00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 # include "incls/_precompiled.incl"
00025
00026 # ifdef DELTA_COMPILER
00027 # include "incls/_nodeBuilder.cpp.incl"
00028
00029
00030
00031 Node* NodeBuilder::EndOfCode = (Node*)-1;
00032
00033
00034
00035
00036 NodeBuilder::NodeBuilder() {
00037 _exprStack = NULL;
00038 _inliner = NULL;
00039 _scope = NULL;
00040 _current = NULL;
00041 }
00042
00043
00044 void NodeBuilder::initialize(InlinedScope* scope) {
00045 _exprStack = new ExprStack(scope, 8);
00046 _inliner = new Inliner(scope);
00047 _scope = scope;
00048 _current = NULL;
00049 }
00050
00051
00052
00053
00054 void NodeBuilder::append(Node* node) {
00055 if (node->isExitNode()) warning("should use append_exit for consistency");
00056 if (aborting() || _current == EndOfCode) {
00057 if (node->nPredecessors() == 0) {
00058
00059
00060 } else {
00061
00062 _current = node;
00063 }
00064 } else {
00065 _current = _current->append(node);
00066 }
00067 }
00068
00069
00070 void NodeBuilder::append_exit(Node* node) {
00071 assert(node->isExitNode(), "not an exit node");
00072 if (_current != EndOfCode) _current->append(node);
00073 _current = NULL;
00074 }
00075
00076
00077 void NodeBuilder::branch(MergeNode* target) {
00078
00079 if (_current != NULL && _current != EndOfCode && _current != target) {
00080 _current->append(target);
00081 }
00082 _current = target;
00083 }
00084
00085
00086 void NodeBuilder::comment(char* s) {
00087 if (CompilerDebug) append(NodeFactory::new_CommentNode(s));
00088 }
00089
00090
00091 GrowableArray<PReg*>* NodeBuilder::copyCurrentExprStack() {
00092 int l = exprStack()->length();
00093 GrowableArray<PReg*>* es = new GrowableArray<PReg*>(l);
00094 for (int i = 0; i < l; i++) {
00095 es->push(exprStack()->at(i)->preg());
00096 }
00097 return es;
00098 }
00099
00100
00101
00102
00103 void NodeBuilder::abort() {
00104 MethodClosure::abort();
00105 _current = EndOfCode;
00106 }
00107
00108 bool NodeBuilder::abortIfDead(Expr* e) {
00109 if (e->isNoResultExpr()) {
00110
00111 abort();
00112 return true;
00113 } else {
00114 return false;
00115 }
00116 }
00117
00118
00119
00120
00121
00122 void NodeBuilder::generate_subinterval(MethodInterval* m, bool produces_result) {
00123 assert(!aborting(), "shouldn't generate when already aborting");
00124 int savedLen = exprStack()->length();
00125 MethodIterator mi(m, this);
00126 if (aborting()) {
00127
00128 Expr* res = exprStack()->isEmpty() ? NULL : exprStack()->top();
00129 assert(res == NULL || res->isNoResultExpr(), "expected no result");
00130 un_abort();
00131 int diff = exprStack()->length() - savedLen;
00132 if (produces_result) diff--;
00133 if (diff > 0) {
00134
00135 exprStack()->pop(diff);
00136 }
00137 if (produces_result) {
00138 if (res == NULL) {
00139
00140
00141
00142
00143 res = new NoResultExpr();
00144 exprStack()->push(res, scope(), m->end_bci());
00145 } else {
00146 exprStack()->assign_top(res);
00147 }
00148 }
00149 }
00150 }
00151
00152
00153 void NodeBuilder::constant_if_node(IfNode* node, ConstantExpr* cond) {
00154
00155 oop c = cond->constant();
00156 int resultBCI = node->begin_bci();
00157 if (c == trueObj || c == falseObj) {
00158 if (node->is_ifTrue() == (c == trueObj)) {
00159
00160 generate_subinterval(node->then_code(), node->produces_result());
00161 } else if (node->else_code() != NULL) {
00162
00163 generate_subinterval(node->else_code(), node->produces_result());
00164 } else {
00165
00166 }
00167 if (node->produces_result()) {
00168 Expr* res = exprStack()->top();
00169
00170
00171
00172 scope()->setExprForBCI(resultBCI, res);
00173 assert(!res->isNoResultExpr() || is_in_dead_code(), "no result should imply in_dead_code");
00174 abortIfDead(res);
00175 } else {
00176 if (is_in_dead_code()) abort();
00177 }
00178 } else {
00179
00180 append(NodeFactory::new_UncommonNode(copyCurrentExprStack(), resultBCI));
00181 }
00182 }
00183
00184
00185 TypeTestNode* NodeBuilder::makeTestNode(bool cond, PReg* r) {
00186 GrowableArray<klassOop>* list = new GrowableArray<klassOop>(2);
00187 if (cond) {
00188 list->append(trueObj->klass());
00189 list->append(falseObj->klass());
00190 } else {
00191 list->append(falseObj->klass());
00192 list->append(trueObj->klass());
00193 }
00194 TypeTestNode* test = NodeFactory::new_TypeTestNode(r, list, true);
00195 test->append(0, NodeFactory::new_UncommonNode(copyCurrentExprStack(), bci()));
00196 return test;
00197 }
00198
00199
00200 void NodeBuilder::if_node(IfNode* node) {
00201 Expr* cond = exprStack()->pop();
00202 int resultBCI = node->begin_bci();
00203 if (abortIfDead(cond)) {
00204 if (node->produces_result()) exprStack()->push(cond, scope(), resultBCI);
00205 return;
00206 }
00207 if (cond->isConstantExpr()) {
00208 constant_if_node(node, (ConstantExpr*)cond);
00209 } else {
00210
00211 TypeTestNode* test = makeTestNode(node->is_ifTrue(), cond->preg());
00212 append(test);
00213 if (node->else_code() != NULL) {
00214
00215 Expr* ifResult = NULL;
00216 Expr* elseResult = NULL;
00217 SAPReg* resultReg = new SAPReg(scope());
00218 MergeNode* ifBranch = NodeFactory::new_MergeNode(node->then_code()->begin_bci());
00219 MergeNode* elseBranch = NodeFactory::new_MergeNode(node->else_code()->begin_bci());
00220 MergeNode* endOfIf = NodeFactory::new_MergeNode(node->end_bci());
00221 test->append(1, ifBranch);
00222 test->append(2, elseBranch);
00223 splitMergeExpr(cond, test);
00224
00225 setCurrent(ifBranch);
00226 generate_subinterval(node->then_code(), node->produces_result());
00227 bool ifEndsDead = is_in_dead_code();
00228 if (node->produces_result()) {
00229 ifResult = exprStack()->pop();
00230 if (!ifResult->isNoResultExpr()) {
00231
00232
00233 materialize(ifResult->preg(), NULL);
00234 append(NodeFactory::new_AssignNode(ifResult->preg(), resultReg));
00235 } else {
00236 assert(ifEndsDead, "oops");
00237 }
00238 }
00239 append(endOfIf);
00240
00241 setCurrent(elseBranch);
00242 generate_subinterval(node->else_code(), node->produces_result());
00243 bool elseEndsDead = is_in_dead_code();
00244 if (node->produces_result()) {
00245 elseResult = exprStack()->pop();
00246 if (!elseResult->isNoResultExpr()) {
00247 materialize(elseResult->preg(), NULL);
00248 append(NodeFactory::new_AssignNode(elseResult->preg(), resultReg));
00249 } else {
00250 assert(elseEndsDead, "oops");
00251 }
00252 }
00253 append(endOfIf);
00254 setCurrent(endOfIf);
00255
00256 if (ifEndsDead && elseEndsDead) {
00257 abort();
00258 } else {
00259 if (node->produces_result()) {
00260 exprStack()->push2nd(new MergeExpr(ifResult, elseResult, resultReg, current()), scope(), resultBCI);
00261 }
00262 }
00263 } else {
00264
00265 assert(!node->produces_result(), "inconsistency - else branch required");
00266 MergeNode* ifBranch = NodeFactory::new_MergeNode(node->then_code()->begin_bci());
00267 MergeNode* endOfIf = NodeFactory::new_MergeNode(node->end_bci());
00268 test->append(1, ifBranch);
00269 test->append(2, endOfIf);
00270 splitMergeExpr(cond, test);
00271
00272 setCurrent(ifBranch);
00273 generate_subinterval(node->then_code(), false);
00274 append(endOfIf);
00275 setCurrent(endOfIf);
00276 if (node->produces_result()) {
00277
00278
00279 scope()->setExprForBCI(resultBCI, exprStack()->top());
00280 }
00281 }
00282 comment("end of if");
00283 }
00284 }
00285
00286
00287 void NodeBuilder::cond_node(CondNode* node) {
00288 Expr* cond = exprStack()->pop();
00289 int resultBCI = node->begin_bci();
00290 if (abortIfDead(cond)) {
00291 exprStack()->push(cond, scope(), resultBCI);
00292 return;
00293 }
00294 if (cond->isConstantExpr()) {
00295
00296 oop c = cond->asConstantExpr()->constant();
00297 if (c == trueObj || c == falseObj) {
00298 if (node->is_and() && c == trueObj ||
00299 node->is_or() && c == falseObj) {
00300 generate_subinterval(node->expr_code(), true);
00301
00302 Expr* res = exprStack()->top();
00303 scope()->setExprForBCI(resultBCI, res);
00304 if (abortIfDead(res)) return;
00305 } else {
00306
00307 exprStack()->push(cond, scope(), resultBCI);
00308 }
00309 } else {
00310
00311 append(NodeFactory::new_UncommonNode(copyCurrentExprStack(), resultBCI));
00312 }
00313 } else {
00314
00315 SAPReg* resultReg = new SAPReg(scope());
00316 TypeTestNode* test = makeTestNode(node->is_and(), cond->preg());
00317 append(test);
00318 MergeNode* condExpr = NodeFactory::new_MergeNode(node->expr_code()->begin_bci());
00319 MergeNode* otherwise = NodeFactory::new_MergeNode(node->expr_code()->begin_bci());
00320 MergeNode* endOfCond = NodeFactory::new_MergeNode(node->end_bci());
00321 test->append(1, condExpr);
00322 test->append(2, otherwise);
00323 setCurrent(otherwise);
00324 append(NodeFactory::new_AssignNode(cond->preg(), resultReg));
00325 append(endOfCond);
00326 splitMergeExpr(cond, test);
00327
00328 setCurrent(condExpr);
00329 generate_subinterval(node->expr_code(), true);
00330 Expr* condResult = exprStack()->pop();
00331 if (condResult->isNoResultExpr()) {
00332 exprStack()->push2nd(new NoResultExpr, scope(), resultBCI);
00333 setCurrent(endOfCond);
00334 } else {
00335 append(NodeFactory::new_AssignNode(condResult->preg(), resultReg));
00336 append(endOfCond);
00337 setCurrent(endOfCond);
00338
00339
00340
00341 Expr* exclude = cond->findKlass(node->is_or() ? falseObj->klass() : trueObj->klass());
00342 Expr* first;
00343 if (exclude) {
00344 first = cond->copyWithout(exclude);
00345 } else {
00346 first = cond;
00347 }
00348 exprStack()->push2nd(new MergeExpr(first, condResult, resultReg, current()), scope(), resultBCI);
00349 comment("end of cond");
00350 }
00351 }
00352 }
00353
00354
00355 void NodeBuilder::while_node(WhileNode* node) {
00356 int loop_bci = node->body_code() != NULL ? node->body_code()->begin_bci() : node->expr_code()->begin_bci();
00357 CompiledLoop* wloop = _scope->addLoop();
00358 LoopHeaderNode* header = NodeFactory::new_LoopHeaderNode();
00359 append(header);
00360 wloop->set_startOfLoop(header);
00361 MergeNode* loop = NodeFactory::new_MergeNode(loop_bci);
00362 MergeNode* exit = NodeFactory::new_MergeNode(node->end_bci());
00363 MergeNode* entry= NULL;
00364 exit->isLoopEnd = true;
00365 if (node->body_code() != NULL) {
00366
00367 entry = NodeFactory::new_MergeNode(node->expr_code()->begin_bci());
00368 append(entry);
00369 entry->isLoopStart = true;
00370 } else {
00371
00372 append(loop);
00373 loop->isLoopStart = true;
00374 }
00375 wloop->set_startOfCond(current());
00376 generate_subinterval(node->expr_code(), true);
00377 Expr* cond = exprStack()->pop();
00378 if (abortIfDead(cond)) {
00379 return;
00380 }
00381 if (false && cond->isConstantExpr()) {
00382 wloop->set_endOfCond(current());
00383
00384
00385 oop c = cond->asConstantExpr()->constant();
00386 if (c == trueObj || c == falseObj) {
00387 if (node->is_whileTrue() == (c == trueObj)) {
00388 append(loop);
00389 setCurrent(exit);
00390 }
00391 } else {
00392
00393 append(NodeFactory::new_UncommonNode(copyCurrentExprStack(), bci()));
00394 }
00395 } else {
00396
00397 TypeTestNode* test = makeTestNode(node->is_whileTrue(), cond->preg());
00398 append(test);
00399 wloop->set_endOfCond(test);
00400 test->append(1, loop);
00401 test->append(2, exit);
00402 setCurrent(exit);
00403 splitMergeExpr(cond, test);
00404 comment("end of while");
00405 }
00406
00407 if (node->body_code() != NULL) {
00408
00409
00410
00411 Node* curr = current();
00412 setCurrent(loop);
00413 generate_subinterval(node->body_code(), false);
00414 wloop->set_startOfBody(loop->next());
00415
00416 if (theCompiler->is_uncommon_compile()) {
00417
00418
00419 append(NodeFactory::new_FixedCodeNode(FixedCodeNode::inc_counter));
00420 }
00421 wloop->set_endOfBody(current());
00422 append(entry);
00423 setCurrent(curr);
00424 }
00425 wloop->set_endOfLoop(exit);
00426 }
00427
00428
00429 void NodeBuilder::primitive_call_node(PrimitiveCallNode* node) {
00430 if (node->pdesc() == NULL) {
00431 error("calling unknown primitive");
00432 exprStack()->pop();
00433 return;
00434 }
00435 PrimInliner* p = new PrimInliner(this, node->pdesc(), node->failure_code());
00436 p->generate();
00437 }
00438
00439
00440 void NodeBuilder::dll_call_node(DLLCallNode* node) {
00441 GrowableArray<PReg*>* args = pass_arguments(NULL, node->nofArgs());
00442 assert(node->failure_code() == NULL, "compiler cannot handle DLL calls with failure blocks yet");
00443 DLLNode* dcall = NodeFactory::new_DLLNode(node->dll_name(), node->function_name(), node->function(), node->async(), scope()->nlrTestPoint(), args, copyCurrentExprStack());
00444 append(dcall);
00445 exprStack()->pop(node->nofArgs());
00446
00447
00448
00449 append(NodeFactory::new_StoreOffsetNode(dcall->dest(), exprStack()->top()->preg(), pointer_no, false));
00450 }
00451
00452
00453 void NodeBuilder::allocate_temporaries(int nofTemps) {
00454 methodOop m = _scope->method();
00455 assert(1 + nofTemps == m->number_of_stack_temporaries(), "no. of stack variables inconsistent");
00456
00457 }
00458
00459
00460 void NodeBuilder::push_self() {
00461 exprStack()->push(scope()->self(), scope(), scope()->bci());
00462 }
00463
00464
00465 void NodeBuilder::push_tos() {
00466 exprStack()->push(exprStack()->top(), scope(), scope()->bci());
00467 }
00468
00469
00470 void NodeBuilder::push_literal(oop obj) {
00471 exprStack()->push(new ConstantExpr(obj, new_ConstPReg(_scope, obj), NULL), scope(), scope()->bci());
00472 }
00473
00474
00475 void NodeBuilder::push_argument(int no) {
00476
00477 assert((0 <= no) && (no < _scope->nofArguments()), "illegal argument no");
00478 exprStack()->push(scope()->argument(no), scope(), scope()->bci());
00479 }
00480
00481
00482 void NodeBuilder::push_temporary(int no) {
00483
00484
00485
00486 assert((0 <= no) && (no < _scope->nofTemporaries()), "illegal temporary no");
00487 Expr* temp = _scope->temporary(no);
00488 PReg* src = temp->preg();
00489 SAPReg* dst = new SAPReg(_scope);
00490 append(NodeFactory::new_AssignNode(src, dst));
00491 exprStack()->push(temp, scope(), scope()->bci());
00492 }
00493
00494
00495 void NodeBuilder::access_temporary(int no, int context, bool push) {
00496
00497
00498
00499 assert(context >= 0, "context must be >= 0");
00500 int nofIndirections;
00501 OutlinedScope* out = NULL;
00502 InlinedScope* s = _scope->find_scope(context, nofIndirections, out);
00503 if (nofIndirections < 0) {
00504
00505 if (push) {
00506 Expr* contextTemp = s->contextTemporary(no);
00507 PReg* src = contextTemp->preg();
00508 Expr* res;
00509 if (src->isBlockPReg()) {
00510
00511 res = contextTemp;
00512 } else {
00513 SAPReg* dst = new SAPReg(_scope);
00514 append(NodeFactory::new_AssignNode(src, dst));
00515 res = s->contextTemporary(no)->shallowCopy(dst, _current);
00516 }
00517 exprStack()->push(res, scope(), scope()->bci());
00518 } else {
00519
00520 PReg* src = exprStack()->top()->preg();
00521 materialize(src, NULL);
00522 PReg* dst = s->contextTemporary(no)->preg();
00523 append(NodeFactory::new_AssignNode(src, dst));
00524 }
00525 } else {
00526
00527 assert(out, "must be set");
00528 assert(out->scope()->allocates_compiled_context(), "must allocate context");
00529 NameDesc* nd = out->scope()->contextTemporary(no);
00530 Location loc = nd->location();
00531 assert(loc.isContextLocation(), "must be in context");
00532 int tempNo = loc.tempNo();
00533 if (tempNo != no) {
00534 compiler_warning("first time this happens: compiled context offset != interpreted context offset");
00535 }
00536 if (push) {
00537 SAPReg* dst = new SAPReg(_scope);
00538 append(NodeFactory::new_LoadUplevelNode(dst, s->context(), nofIndirections, contextOopDesc::temp0_word_offset() + tempNo, NULL));
00539 exprStack()->push(new UnknownExpr(dst, _current), scope(), scope()->bci());
00540 } else {
00541
00542 Expr* srcExpr = exprStack()->top();
00543 PReg* src = srcExpr->preg();
00544 materialize(src, NULL);
00545 append(NodeFactory::new_StoreUplevelNode(src, s->context(), nofIndirections, contextOopDesc::temp0_word_offset() + tempNo, NULL, srcExpr->needsStoreCheck()));
00546 }
00547 }
00548 }
00549
00550
00551 void NodeBuilder::push_temporary(int no, int context) {
00552 access_temporary(no, context, true);
00553 }
00554
00555
00556 void NodeBuilder::push_instVar(int offset) {
00557 assert(offset >= 0, "offset must be positive");
00558 SAPReg* dst = new SAPReg(_scope);
00559 PReg* base = _scope->self()->preg();
00560 append(NodeFactory::new_LoadOffsetNode(dst, base, offset, false));
00561 exprStack()->push(new UnknownExpr(dst, _current), scope(), scope()->bci());
00562 }
00563
00564
00565 void NodeBuilder::push_global(associationOop associationObj) {
00566 SAPReg* dst = new SAPReg(_scope);
00567 if (associationObj->is_constant()) {
00568
00569 oop c = associationObj->value();
00570 ConstPReg* r = new_ConstPReg(_scope, c);
00571 exprStack()->push(new ConstantExpr(c, r, NULL), _scope, scope()->bci());
00572 } else {
00573
00574
00575
00576 ConstPReg* base = new_ConstPReg(_scope, associationObj);
00577 append(NodeFactory::new_LoadOffsetNode(dst, base, associationOopDesc::value_offset(), false));
00578 exprStack()->push(new UnknownExpr(dst, _current), _scope, scope()->bci());
00579 }
00580 }
00581
00582
00583 void NodeBuilder::store_temporary(int no) {
00584 PReg* src = exprStack()->top()->preg();
00585
00586
00587 materialize(src, NULL);
00588 PReg* dst = _scope->temporary(no)->preg();
00589 if (src != dst) append(NodeFactory::new_AssignNode(src, dst));
00590 }
00591
00592
00593 void NodeBuilder::store_temporary(int no, int context) {
00594 access_temporary(no, context, false);
00595 }
00596
00597
00598 void NodeBuilder::store_instVar(int offset) {
00599 assert(offset >= 0, "offset must be positive");
00600 Expr* srcExpr = exprStack()->top();
00601 PReg* src = srcExpr->preg();
00602 materialize(src, NULL);
00603 PReg* base = _scope->self()->preg();
00604 append(NodeFactory::new_StoreOffsetNode(src, base, offset, srcExpr->needsStoreCheck()));
00605 }
00606
00607
00608 void NodeBuilder::store_global(associationOop associationObj) {
00609 Expr* srcExpr = exprStack()->top();
00610 PReg* src = srcExpr->preg();
00611 materialize(src, NULL);
00612 ConstPReg* base = new_ConstPReg(_scope, associationObj);
00613 append(NodeFactory::new_StoreOffsetNode(src, base, associationOopDesc::value_offset(), srcExpr->needsStoreCheck()));
00614 }
00615
00616
00617 void NodeBuilder::pop() {
00618 exprStack()->pop();
00619 }
00620
00621
00622
00623 void NodeBuilder::materialize(PReg* r, GrowableArray<BlockPReg*>* materialized) {
00624
00625
00626 if (r->isBlockPReg() && (materialized == NULL || !materialized->contains((BlockPReg*)r))) {
00627 BlockPReg* blk = (BlockPReg*)r;
00628 append(NodeFactory::new_BlockMaterializeNode(blk, copyCurrentExprStack()));
00629 if (materialized == NULL) materialized = new GrowableArray<BlockPReg*>(5);
00630 materialized->append(blk);
00631 GrowableArray<PReg*>* reads = blk->uplevelRead();
00632 if (reads) {
00633 for (int i = reads->length() - 1; i >= 0; i--) materialize(reads->at(i), materialized);
00634 }
00635 }
00636 }
00637
00638
00639 GrowableArray<PReg*>* NodeBuilder::pass_arguments(PReg* receiver, int nofArgs) {
00640
00641
00642
00643
00644
00645 int nofFormals = (receiver == NULL) ? nofArgs : nofArgs + 1;
00646 GrowableArray<PReg*>* formals = new GrowableArray<PReg*>(nofFormals);
00647
00648 SAPReg* formalReceiver;
00649 GrowableArray<BlockPReg*> blocks(5);
00650 if (receiver != NULL) {
00651 materialize(receiver, &blocks);
00652 formalReceiver = new SAPReg(_scope, receiverLoc, false, false, bci(), bci());
00653 formals->append(formalReceiver);
00654 if (receiverLoc.isStackLocation()) {
00655
00656 append(NodeFactory::new_AssignNode(receiver, formalReceiver));
00657 }
00658 }
00659
00660 const int first_arg = exprStack()->length() - nofArgs;
00661 const int limit_arg = exprStack()->length();
00662 int sp;
00663
00664 for (sp = first_arg; sp < limit_arg; sp++) {
00665 PReg* actual = exprStack()->at(sp)->preg();
00666 materialize(actual, &blocks);
00667 }
00668
00669 for (sp = first_arg; sp < limit_arg; sp++) {
00670 PReg* actual = exprStack()->at(sp)->preg();
00671 SAPReg* formal = new SAPReg(_scope, Mapping::outgoingArg(sp - first_arg, nofArgs), false, false, bci(), bci());
00672 formals->append(formal);
00673 append(NodeFactory::new_AssignNode(actual, formal));
00674 }
00675
00676 if ((receiver != NULL) && !receiverLoc.isStackLocation()) {
00677 append(NodeFactory::new_AssignNode(receiver, formalReceiver));
00678 }
00679 return formals;
00680 }
00681
00682
00683 void NodeBuilder::gen_normal_send(SendInfo* info, int nofArgs, SAPReg* result) {
00684 GrowableArray<PReg*>* args = pass_arguments(exprStack()->at(exprStack()->length() - nofArgs - 1)->preg(), nofArgs);
00685 SendNode* send = NodeFactory::new_SendNode(info->key, scope()->nlrTestPoint(), args,
00686 copyCurrentExprStack(), false, info);
00687 append(send);
00688 append(NodeFactory::new_AssignNode(send->dest(), result));
00689 }
00690
00691
00692 void NodeBuilder::gen_self_send(SendInfo* info, int nofArgs, SAPReg* result) {
00693 GrowableArray<PReg*>* args = pass_arguments(_scope->self()->preg(), nofArgs);
00694 SendNode* send = NodeFactory::new_SendNode(info->key, scope()->nlrTestPoint(), args,
00695 copyCurrentExprStack(), false, info);
00696 append(send);
00697 append(NodeFactory::new_AssignNode(send->dest(), result));
00698 }
00699
00700
00701 void NodeBuilder::gen_super_send(SendInfo* info, int nofArgs, SAPReg* result) {
00702 GrowableArray<PReg*>* args = pass_arguments(_scope->self()->preg(), nofArgs);
00703 SendNode* send = NodeFactory::new_SendNode(info->key, scope()->nlrTestPoint(), args,
00704 copyCurrentExprStack(), true, info);
00705 append(send);
00706 append(NodeFactory::new_AssignNode(send->dest(), result));
00707 }
00708
00709
00710 void NodeBuilder::normal_send(InterpretedIC* ic) {
00711 int nofArgs = ic->selector()->number_of_arguments();
00712 LookupKey* key = LookupKey::allocate(NULL, ic->selector());
00713 Expr* rcvr = exprStack()->at(exprStack()->length() - nofArgs - 1);
00714 SendInfo* info = new SendInfo(_scope, key, rcvr);
00715 Expr* result = _inliner->inlineNormalSend(info);
00716 exprStack()->pop(nofArgs + 1);
00717 exprStack()->push(result, _scope, scope()->bci());
00718 abortIfDead(result);
00719 }
00720
00721
00722 void NodeBuilder::self_send(InterpretedIC* ic) {
00723 int nofArgs = ic->selector()->number_of_arguments();
00724 LookupKey* key = LookupKey::allocate(_scope->selfKlass(), ic->selector());
00725 SendInfo* info = new SendInfo(_scope, key, _scope->self());
00726 Expr* result = _inliner->inlineSelfSend(info);
00727 exprStack()->pop(nofArgs);
00728 exprStack()->push(result, _scope, scope()->bci());
00729 abortIfDead(result);
00730 }
00731
00732
00733 void NodeBuilder::super_send(InterpretedIC* ic) {
00734 int nofArgs = ic->selector()->number_of_arguments();
00735
00736 klassOop klass = _scope->selfKlass()->klass_part()->superKlass();
00737 LookupKey* key = LookupKey::allocate(klass, lookupCache::method_lookup(klass, ic->selector()));
00738 SendInfo* info = new SendInfo(_scope, key, _scope->self());
00739 Expr* result = _inliner->inlineSuperSend(info);
00740 exprStack()->pop(nofArgs);
00741 exprStack()->push(result, _scope, scope()->bci());
00742 abortIfDead(result);
00743 }
00744
00745
00746 void NodeBuilder::double_equal() {
00747 PrimInliner* p = new PrimInliner(this, primitives::equal(), NULL);
00748 p->generate();
00749 }
00750
00751
00752 void NodeBuilder::double_not_equal() {
00753 PrimInliner* p = new PrimInliner(this, primitives::not_equal(), NULL);
00754 p->generate();
00755 }
00756
00757
00758 void NodeBuilder::method_return(int nofArgs) {
00759
00760 Expr* result = exprStack()->pop();
00761 if (_current == EndOfCode) {
00762
00763
00764 _scope->addResult(new NoResultExpr);
00765 return;
00766 }
00767
00768 if (result->isNoResultExpr()) {
00769
00770 _scope->addResult(result);
00771 } else {
00772
00773 PReg* src = result->preg();
00774 materialize(src, NULL);
00775 if (_scope->isTop()) {
00776
00777 append(NodeFactory::new_AssignNode(src, _scope->resultPR));
00778 _scope->addResult(result->shallowCopy(_scope->resultPR, _current));
00779 } else {
00780
00781 if (UseNewBackend) {
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793 append(NodeFactory::new_AssignNode(src, _scope->resultPR));
00794 } else {
00795 if (_scope->needsContextZapping()) {
00796
00797 append(NodeFactory::new_InlinedReturnNode(bci(), src, _scope->resultPR));
00798 } else {
00799
00800 append(NodeFactory::new_AssignNode(src, _scope->resultPR));
00801 }
00802 }
00803 _scope->addResult(result->shallowCopy(_scope->resultPR, _current));
00804 }
00805 }
00806
00807 append(scope()->returnPoint());
00808
00809
00810 _current = EndOfCode;
00811 }
00812
00813
00814 void NodeBuilder::nonlocal_return(int nofArgs) {
00815
00816 Expr* resultExpr = exprStack()->pop();
00817 PReg* src = resultExpr->preg();
00818 materialize(src, NULL);
00819 if (scope()->isTop()) {
00820
00821 append(NodeFactory::new_AssignNode(src, scope()->resultPR));
00822 append(scope()->nlrPoint());
00823 } else {
00824
00825 Scope* home = scope()->home();
00826 if (home->isInlinedScope()) {
00827
00828 InlinedScope* h = (InlinedScope*)home;
00829 append(NodeFactory::new_AssignNode(src, h->resultPR));
00830 h->addResult(resultExpr->shallowCopy(h->resultPR, _current));
00831
00832
00833 append(h->returnPoint());
00834 } else {
00835
00836
00837
00838
00839
00840
00841 int endBCI = scope()->nlrPoint()->bci();
00842 bool haveSetupNode = scope()->nlrPoint()->next() != NULL;
00843 assert(!haveSetupNode || scope()->nlrPoint()->next()->isNLRSetupNode(), "expected setup node");
00844 PReg* res = haveSetupNode ? ((NonTrivialNode*)scope()->nlrPoint()->next())->src() :
00845 new SAPReg(scope(), NLRResultLoc, true, true, bci(), endBCI);
00846 append(NodeFactory::new_AssignNode(src, res));
00847 append(scope()->nlrPoint());
00848 if (!haveSetupNode) {
00849
00850 append_exit(NodeFactory::new_NLRSetupNode(res, endBCI));
00851 }
00852 }
00853 }
00854
00855 _current = EndOfCode;
00856 }
00857
00858 GrowableArray<NonTrivialNode*>* NodeBuilder::nodesBetween(Node* from, Node* to) {
00859
00860 GrowableArray<NonTrivialNode*>* nodes = new GrowableArray<NonTrivialNode*>(5);
00861 Node* n = from;
00862 while (n != to) {
00863 if (!n->hasSingleSuccessor()) return NULL;
00864 bool shouldCopy = n->shouldCopyWhenSplitting();
00865 bool ok = (n == from) ||
00866 shouldCopy ||
00867 n->isTrivial() ||
00868 n->isMergeNode();
00869 if (!ok) return NULL;
00870 if (shouldCopy && n != from) nodes->append((NonTrivialNode*)n);
00871 n = n->next();
00872 }
00873 return nodes;
00874 }
00875
00876 MergeNode* NodeBuilder::insertMergeBefore(Node* n) {
00877
00878 assert(n->hasSinglePredecessor(), "should have only one predecessor");
00879 MergeNode* merge = NodeFactory::new_MergeNode(n->bci());
00880 Node* prev = n->firstPrev();
00881 prev->moveNext(n, merge);
00882 merge->setPrev(prev);
00883 n->removePrev(prev);
00884 merge->append(n);
00885 return merge;
00886 }
00887
00888
00889 static int split_count = 0;
00890
00891 void NodeBuilder::splitMergeExpr(Expr* expr, TypeTestNode* test) {
00892
00893
00894
00895
00896 split_count++;
00897 GrowableArray<Expr*>* exprsToSplit = splittablePaths(expr, test);
00898 if (!exprsToSplit) return;
00899
00900 for (int i = exprsToSplit->length() - 1; i >= 0; i--) {
00901 Expr* e = exprsToSplit->at(i);
00902 Node* start = e->node();
00903 GrowableArray<NonTrivialNode*>* nodesToCopy = nodesBetween(start, test);
00904 assert(nodesToCopy != NULL, "should have worked");
00905
00906
00907 klassOop c = e->asConstantExpr()->klass();
00908 int j = test->classes()->length();
00909 while (j-- > 0 && test->classes()->at(j) != c) ;
00910 assert(j >= 0, "didn't find klass in type test");
00911 Node* to = test->next(j+1);
00912 if (CompilerDebug) cout(PrintSplitting)->print("%*s*splitting merge expr: from N%d to N%d (%dth split)\n", _scope->depth*2, "", start->id(), to->id(), split_count);
00913 if (!to->isMergeNode()) {
00914 to = insertMergeBefore(to);
00915 }
00916
00917
00918 start->removeNext(start->next());
00919
00920 Node* current = start;
00921 #ifdef ASSERT
00922 bool found = nodesToCopy->length() == 0;
00923 #endif
00924 for (int i = 0; i < nodesToCopy->length(); i++) {
00925 NonTrivialNode* orig = nodesToCopy->at(i);
00926 Node* copy = orig->copy(NULL, NULL);
00927 if (CompilerDebug) cout(PrintSplitting)->print("%*s* (copying node N%d along the path -> N%d)\n", _scope->depth*2, "", orig->id(), copy->id());
00928 current = current->append(copy);
00929 #ifdef ASSERT
00930 if (orig->dest() == test->src()) found = true;
00931 #endif
00932 }
00933 #ifdef ASSERT
00934 if (!found) {
00935
00936
00937 for (Node* n = start; n && !found; n = n->firstPrev()) {
00938 if (n->hasDest() && ((NonTrivialNode*)n)->dest() == test->src()) {
00939 found = true;
00940 }
00941 }
00942 assert(found, "assignment to tested PReg not found");
00943 }
00944 #endif
00945
00946 current->append(to);
00947 }
00948 }
00949
00950 GrowableArray<Expr*>* NodeBuilder::splittablePaths(const Expr* expr, const TypeTestNode* test) const {
00951
00952 if (!Splitting) return NULL;
00953 if (!expr->isMergeExpr()) return NULL;
00954 MergeExpr* m = expr->asMergeExpr();
00955 if (!m->isSplittable()) return NULL;
00956
00957 GrowableArray<Node*>* exprNodes = new GrowableArray<Node*>(10);
00958 GrowableArray<Expr*>* okExprs = new GrowableArray<Expr*>(10);
00959
00960
00961 for (int i = m->exprs->length() - 1; i >= 0; i--) {
00962 for (Expr* x = m->exprs->at(i); x; x = x->next) {
00963 Node* start = x->node();
00964 exprNodes->append(start);
00965 if (!x->isConstantExpr()) continue;
00966
00967 const Node* n = start;
00968 while (n != test) {
00969 if (!n->hasSingleSuccessor()) goto nextExpr;
00970 bool ok = (n == start) ||
00971 n->isTrivial() ||
00972 n->isAssignNode() ||
00973 n->isMergeNode();
00974 if (!ok) goto nextExpr;
00975 n = n->next();
00976 }
00977
00978 okExprs->append(x);
00979 }
00980 nextExpr: ;
00981 }
00982
00983
00984
00985 for (i = okExprs->length() - 1; i >= 0; i--) {
00986 Node* start = okExprs->at(i)->node()->next();
00987 for (Node* n = start; n != (Node*)test; n = n->next()) {
00988 if (exprNodes->contains(n)) {
00989 lprintf("error in splittable boolean expression:\n");
00990 m->print();
00991 okExprs->at(i)->print();
00992 #ifdef DEBUG
00993 printNodes(okExprs->at(i)->node());
00994 #endif
00995 for (int j = 0; j < exprNodes->length(); j++) {
00996 exprNodes->at(j)->print();
00997 lprintf("\n");
00998 }
00999 fatal("compiler error");
01000 }
01001 }
01002 }
01003
01004 return okExprs;
01005 }
01006
01007 void NodeBuilder::allocate_closure(AllocationType type, int nofArgs, methodOop method) {
01008 PReg* context;
01009 if (type == tos_as_scope) {
01010 context = exprStack()->pop()->preg();
01011 } else {
01012 context = _scope->context();
01013 }
01014 CompileTimeClosure* closure = new CompileTimeClosure(_scope, method, context, nofArgs);
01015 BlockPReg* block = new BlockPReg(_scope, closure, bci(), EpilogueBCI);
01016 append(NodeFactory::new_BlockCreateNode(block, copyCurrentExprStack()));
01017 exprStack()->push(new BlockExpr(block, _current), _scope, scope()->bci());
01018 }
01019
01020
01021 static methodOopDesc::Block_Info incoming_info(methodOop m) {
01022
01023
01024
01025 if (m->is_blockMethod()) {
01026 return m->block_info();
01027 } else {
01028 return methodOopDesc::expects_self;
01029 }
01030 }
01031
01032
01033 void NodeBuilder::allocate_context(int nofTemps, bool forMethod) {
01034 _scope->createContextTemporaries(nofTemps);
01035 assert(!scope()->contextInitializer(), "should not already have a contextInitializer");
01036 PReg* parent;
01037 if (forMethod) {
01038
01039 parent = new SAPReg(_scope, frameLoc, true, true, PrologueBCI, EpilogueBCI);
01040 } else {
01041
01042 assert(incoming_info(_scope->method()) != methodOopDesc::expects_self, "fix this");
01043 assert(incoming_info(_scope->method()) != methodOopDesc::expects_parameter, "fix this");
01044 if (_scope->isTop()) {
01045 parent =
01046 (incoming_info(_scope->method()) == methodOopDesc::expects_context)
01047 ? _scope->self()->preg()
01048 : NULL;
01049
01050 } else {
01051
01052 parent = _scope->context();
01053 _scope->setContext(new SAPReg(_scope, PrologueBCI, EpilogueBCI));
01054 }
01055 }
01056 ContextCreateNode* creator = NodeFactory::new_ContextCreateNode(parent, _scope->context(), nofTemps, copyCurrentExprStack());
01057 append(creator);
01058
01059 scope()->set_contextInitializer(NodeFactory::new_ContextInitNode(creator));
01060 append(scope()->contextInitializer());
01061 ConstantExpr* nil = new ConstantExpr(nilObj, new_ConstPReg(_scope, nilObj), NULL);
01062 for (int i = 0; i < nofTemps; i++) scope()->contextInitializer()->initialize(i, nil);
01063 }
01064
01065
01066 void NodeBuilder::removeContextCreation() {
01067 assert(scope()->contextInitializer() != NULL, "must have context");
01068 ContextCreateNode* creator = scope()->contextInitializer()->creator();
01069 creator->eliminate(creator->bb(), NULL, true, false);
01070 scope()->contextInitializer()->notifyNoContext();
01071 }
01072
01073
01074 void NodeBuilder::set_self_via_context() {
01075 if (Inline) {
01076 Scope* s = _scope->parent();
01077 if (s->isInlinedScope()) {
01078
01079 assert(_scope->self() == ((InlinedScope*)s)->self(), "should have identical selves");
01080 return;
01081 }
01082 }
01083
01084
01085 if (_scope->is_self_initialized()) return;
01086 _scope->set_self_initialized();
01087
01088
01089 int contextNo = _scope->homeContext();
01090 if (_scope->allocatesInterpretedContext()) {
01091
01092
01093
01094 assert(_scope->contextInitializer() != NULL, "should have a _contextInitializer already");
01095 contextNo--;
01096 }
01097
01098
01099
01100
01101
01102
01103 const int self_no = 0;
01104 PReg* reg = _scope->self()->preg();
01105 append(NodeFactory::new_LoadUplevelNode(reg, reg, contextNo, contextOopDesc::temp0_word_offset() + self_no, NULL));
01106 }
01107
01108
01109 Expr* NodeBuilder::copy_into_context(Expr* e, int no) {
01110 if (e->isBlockExpr()) {
01111
01112
01113
01114
01115 BlockPReg* block = (BlockPReg*)e->preg();
01116 BlockMaterializeNode* n = NodeFactory::new_BlockMaterializeNode(block, copyCurrentExprStack());
01117 scope()->contextInitializer()->addBlockMaterializer(n);
01118 append(n);
01119
01120
01121
01122
01123 Location* loc = Mapping::new_contextTemporary(no, no, scope()->scopeID());
01124 block->addContextCopy(loc);
01125
01126
01127 return e;
01128 } else {
01129 return e->shallowCopy(new SAPReg(scope(), PrologueBCI, EpilogueBCI, true), NULL);
01130 }
01131 }
01132
01133
01134 void NodeBuilder::copy_self_into_context() {
01135 const int self_no = 0;
01136
01137 Expr* self_expr_in_context = copy_into_context(scope()->self(), self_no);
01138 scope()->contextTemporariesAtPut(self_no, self_expr_in_context);
01139 scope()->contextInitializer()->initialize(self_no, scope()->self());
01140 }
01141
01142
01143 void NodeBuilder::copy_argument_into_context(int argNo, int no) {
01144
01145
01146 Expr* arg_expr_in_context = copy_into_context(scope()->argument(argNo), no);
01147 scope()->contextTemporariesAtPut(no, arg_expr_in_context);
01148 scope()->contextInitializer()->initialize(no, scope()->argument(argNo));
01149 }
01150
01151
01152 void NodeBuilder::zap_scope() {
01153 assert(scope()->isMethodScope(), "blocks cannot be target of a NLR, no zap required");
01154 assert(scope()->contextInitializer() != NULL, "should have a context allocated");
01155
01156 }
01157
01158
01159 void NodeBuilder::predict_prim_call(primitive_desc* pdesc, int failure_start) {
01160
01161 }
01162
01163
01164 PReg* NodeBuilder::float_at(int fno) {
01165 if (UseFPUStack) {
01166 if (fno < scope()->nofFloatTemporaries()) {
01167
01168 return scope()->floatTemporary(fno)->preg();
01169 } else {
01170
01171
01172
01173 return new SAPReg(_scope, topOfFloatStack, true, true, bci(), bci());
01174 }
01175 } else {
01176
01177 return scope()->floatTemporary(fno)->preg();
01178 }
01179 }
01180
01181
01182 void NodeBuilder::float_allocate(int nofFloatTemps, int nofFloatExprs) {
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212 int size = nofFloatTemps + nofFloatExprs;
01213 assert(size == method()->total_number_of_floats(), "inconsistency");
01214
01215 }
01216
01217
01218 void NodeBuilder::float_floatify(Floats::Function f, int fno) {
01219
01220 Expr* t = _exprStack->pop();
01221 if (t->hasKlass() && t->klass() == doubleKlassObj) {
01222
01223 } else {
01224
01225 }
01226 append(NodeFactory::new_FloatUnaryArithNode(float_at(fno), t->preg(), f2FloatArithOp));
01227 }
01228
01229
01230 void NodeBuilder::float_move(int to, int from) {
01231
01232 append(NodeFactory::new_AssignNode(float_at(from), float_at(to)));
01233 }
01234
01235
01236 void NodeBuilder::float_set(int to, doubleOop value) {
01237
01238 ConstPReg* val = new_ConstPReg(_scope, value);
01239 append(NodeFactory::new_AssignNode(val, float_at(to)));
01240 }
01241
01242
01243 void NodeBuilder::float_nullary(Floats::Function f, int to) {
01244
01245
01246 switch (f) {
01247 case Floats::zero : float_set(to, oopFactory::new_double(0.0)); break;
01248 case Floats::one : float_set(to, oopFactory::new_double(1.0)); break;
01249 default : fatal1("bad float nullary code %d", f);
01250 }
01251 }
01252
01253
01254 void NodeBuilder::float_unary(Floats::Function f, int fno) {
01255
01256
01257 ArithOpCode op;
01258 switch (f) {
01259 case Floats::abs : op = fAbsArithOp; break;
01260 case Floats::negated: op = fNegArithOp; break;
01261 case Floats::squared: op = fSqrArithOp; break;
01262 case Floats::sqrt : Unimplemented();
01263 case Floats::sin : Unimplemented();
01264 case Floats::cos : Unimplemented();
01265 case Floats::tan : Unimplemented();
01266 case Floats::exp : Unimplemented();
01267 case Floats::ln : Unimplemented();
01268 default : fatal1("bad float unary code %d", f);
01269 }
01270 PReg* preg = float_at(fno);
01271 append(NodeFactory::new_FloatUnaryArithNode(preg, preg, op));
01272 }
01273
01274
01275 void NodeBuilder::float_binary(Floats::Function f, int fno) {
01276
01277
01278 ArithOpCode op;
01279 switch (f) {
01280 case Floats::add : op = fAddArithOp; break;
01281 case Floats::subtract: op = fSubArithOp; break;
01282 case Floats::multiply: op = fMulArithOp; break;
01283 case Floats::divide : op = fDivArithOp; break;
01284 case Floats::modulo : op = fModArithOp; break;
01285 default : fatal1("bad float binary code %d", f);
01286 }
01287 PReg* op1 = float_at(fno);
01288 PReg* op2 = float_at(fno+1);
01289 append(NodeFactory::new_FloatArithRRNode(op1, op1, op, op2));
01290 }
01291
01292
01293 void NodeBuilder::float_unaryToOop(Floats::Function f, int fno) {
01294
01295
01296 PReg* src = float_at(fno);
01297 SAPReg* res = new SAPReg(_scope);
01298 switch (f) {
01299 case Floats::is_zero:
01300 case Floats::is_not_zero:
01301 { ConstPReg* zero = new_ConstPReg(_scope, oopFactory::new_double(0.0));
01302 NodeFactory::new_FloatArithRRNode(new NoPReg(_scope), src, fCmpArithOp, zero);
01303 BranchOpCode cond = f == Floats::is_zero ? EQBranchOp : NEBranchOp;
01304 _exprStack->push(PrimInliner::generate_cond(cond, this, res), scope(), scope()->bci());
01305 }
01306 break;
01307 case Floats::oopify:
01308 { append(NodeFactory::new_FloatUnaryArithNode(res, src, f2OopArithOp));
01309 Expr* result = new KlassExpr(doubleKlassObj, res, current());
01310 _exprStack->push(result, scope(), scope()->bci());
01311 }
01312 break;
01313 default: fatal1("bad float unaryToOop code %d", f);
01314 }
01315 }
01316
01317
01318 void NodeBuilder::float_binaryToOop(Floats::Function f, int fno) {
01319
01320
01321 Assembler::Condition cc1;
01322 switch (f) {
01323 case Floats::is_equal : cc1 = Assembler::equal; break;
01324 case Floats::is_not_equal : cc1 = Assembler::notEqual; break;
01325 case Floats::is_less : cc1 = Assembler::less; break;
01326 case Floats::is_less_equal : cc1 = Assembler::lessEqual; break;
01327 case Floats::is_greater : cc1 = Assembler::greater; break;
01328 case Floats::is_greater_equal: cc1 = Assembler::greaterEqual; break;
01329 default : fatal1("bad float comparison code %d", f);
01330 }
01331 int mask;
01332 Assembler::Condition cond;
01333 MacroAssembler::fpu_mask_and_cond_for(cc1, mask, cond);
01334 PReg* op1 = float_at(fno);
01335 PReg* op2 = float_at(fno+1);
01336 SAPReg* fpu_status = new SAPReg(_scope, Mapping::asLocation(eax), false, false, bci(), bci());
01337 append(NodeFactory::new_FloatArithRRNode(fpu_status, op1, fCmpArithOp, op2));
01338 append(NodeFactory::new_ArithRCNode(new NoPReg(_scope), fpu_status, TestArithOp, mask));
01339 BranchOpCode cc2;
01340 switch (cond) {
01341 case Assembler::zero : cc2 = EQBranchOp; break;
01342 case Assembler::notZero: cc2 = NEBranchOp; break;
01343 default : ShouldNotReachHere();
01344 }
01345 SAPReg* res = new SAPReg(_scope);
01346 _exprStack->push(PrimInliner::generate_cond(cc2, this, res), scope(), scope()->bci());
01347 }
01348
01349
01350 # endif