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 # ifdef DELTA_COMPILER
00026 # include "incls/_oldCodeGenerator.cpp.incl"
00027 
00028 
00029 static bool bb_needs_jump;
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 void OldCodeGenerator::beginOfBasicBlock(Node* node) {
00042   theMacroAssm->bind(node->label);
00043 }
00044 
00045 
00046 void OldCodeGenerator::endOfBasicBlock(Node* node) {
00047   if (bb_needs_jump && node->next() != NULL) theMacroAssm->jmp(node->next()->label);
00048 }
00049 
00050 
00051 void OldCodeGenerator::beginOfNode(Node* node) {
00052   
00053   
00054   
00055   bb_needs_jump = true;
00056 }
00057 
00058 
00059 void OldCodeGenerator::endOfNode(Node* node) {
00060   
00061 }
00062 
00063 
00064 void OldCodeGenerator::aPrologueNode(PrologueNode* node)                { node->gen(); }
00065 void OldCodeGenerator::aLoadIntNode(LoadIntNode* node)                  { node->gen(); }
00066 void OldCodeGenerator::aLoadOffsetNode(LoadOffsetNode* node)            { node->gen(); }
00067 void OldCodeGenerator::aLoadUplevelNode(LoadUplevelNode* node)          { node->gen(); }
00068 void OldCodeGenerator::anAssignNode(AssignNode* node)                   { node->gen(); }
00069 void OldCodeGenerator::aStoreOffsetNode(StoreOffsetNode* node)          { node->gen(); }
00070 void OldCodeGenerator::aStoreUplevelNode(StoreUplevelNode* node)        { node->gen(); }
00071 void OldCodeGenerator::anArithRRNode(ArithRRNode* node)                 { node->gen(); }
00072 void OldCodeGenerator::aFloatArithRRNode(FloatArithRRNode* node)        { node->gen(); }
00073 void OldCodeGenerator::aFloatUnaryArithNode(FloatUnaryArithNode* node)  { node->gen(); }
00074 void OldCodeGenerator::anArithRCNode(ArithRCNode* node)                 { node->gen(); }
00075 void OldCodeGenerator::aTArithRRNode(TArithRRNode* node)                { node->gen(); }
00076 void OldCodeGenerator::aContextCreateNode(ContextCreateNode* node)      { node->gen(); }
00077 void OldCodeGenerator::aContextInitNode(ContextInitNode* node)          { node->gen(); }
00078 void OldCodeGenerator::aContextZapNode(ContextZapNode* node)            { node->gen(); }
00079 void OldCodeGenerator::aBlockCreateNode(BlockCreateNode* node)          { node->gen(); }
00080 void OldCodeGenerator::aBlockMaterializeNode(BlockMaterializeNode* node){ node->gen(); }
00081 void OldCodeGenerator::aSendNode(SendNode* node)                        { node->gen(); }
00082 void OldCodeGenerator::aPrimNode(PrimNode* node)                        { node->gen(); }
00083 void OldCodeGenerator::aDLLNode(DLLNode* node)                          { node->gen(); }
00084 void OldCodeGenerator::aLoopHeaderNode(LoopHeaderNode* node)            { node->gen(); }
00085 void OldCodeGenerator::aReturnNode(ReturnNode* node)                    { node->gen(); }
00086 void OldCodeGenerator::aNLRSetupNode(NLRSetupNode* node)                { node->gen(); }
00087 void OldCodeGenerator::anInlinedReturnNode(InlinedReturnNode* node)     { node->gen(); }
00088 void OldCodeGenerator::aNLRContinuationNode(NLRContinuationNode* node)  { node->gen(); }
00089 void OldCodeGenerator::aBranchNode(BranchNode* node)                    { node->gen(); }
00090 void OldCodeGenerator::aTypeTestNode(TypeTestNode* node)                { node->gen(); }
00091 void OldCodeGenerator::aNLRTestNode(NLRTestNode* node)                  { node->gen(); }
00092 void OldCodeGenerator::aMergeNode(MergeNode* node)                      { node->gen(); }
00093 void OldCodeGenerator::anArrayAtNode(ArrayAtNode* node)                 { node->gen(); }
00094 void OldCodeGenerator::anArrayAtPutNode(ArrayAtPutNode* node)           { node->gen(); }
00095 void OldCodeGenerator::anInlinedPrimitiveNode(InlinedPrimitiveNode* node){ node->gen(); }
00096 void OldCodeGenerator::anUncommonNode(UncommonNode* node)               { node->gen(); }
00097 void OldCodeGenerator::aFixedCodeNode(FixedCodeNode* node)              { node->gen(); }
00098 void OldCodeGenerator::aNopNode(NopNode* node)                          { node->gen(); }
00099 void OldCodeGenerator::aCommentNode(CommentNode* node)                  { node->gen(); }
00100 
00101 
00102 
00103 
00104 
00105 
00106 
00107 
00108 
00109 
00110 
00111 
00112 
00113 
00114 
00115 static void inlineCache(Label& nlrTestPoint, SendInfo* info, bool super) {
00116   
00117   char flags = 0;
00118   if (super)                            setNth(flags, super_send_bit_no);
00119   if (info && info->uninlinable)        setNth(flags, uninlinable_bit_no);
00120   if (info && info->receiverStatic)     setNth(flags, receiver_static_bit_no);
00121   theMacroAssm->ic_info(nlrTestPoint, flags);
00122 }
00123 
00124 
00125 
00126 
00127 
00128 
00129 
00130 
00131 static void call_C(char* dest, relocInfo::relocType relocType, bool needsDeltaFPCode) {
00132   if (needsDeltaFPCode) theMacroAssm->set_last_Delta_frame_before_call();
00133   theMacroAssm->call(dest, relocType);
00134   if (needsDeltaFPCode) theMacroAssm->reset_last_Delta_frame();
00135 }
00136 
00137 
00138 static void call_C(char* dest, relocInfo::relocType relocType, bool needsDeltaFPCode, Label& nlrTestPoint) {
00139   if (needsDeltaFPCode) theMacroAssm->set_last_Delta_frame_before_call();
00140   theMacroAssm->call(dest, relocType);
00141   inlineCache(nlrTestPoint, NULL, false);
00142   if (needsDeltaFPCode) theMacroAssm->reset_last_Delta_frame();
00143 }
00144 
00145 
00146 
00147 
00148 
00149 
00150 
00151 
00152 
00153 static int callDepth = 0;       
00154 static int numberOfCalls = 0;   
00155 
00156 static void indent() { 
00157   const int maxIndent = 30;
00158   if (callDepth < maxIndent) {
00159     lprintf("%*s", callDepth, " ");
00160   } else {
00161     lprintf("%*s <%5d>", maxIndent - 9, " ", callDepth);
00162   }
00163 }
00164 
00165 
00166 static char* nmethodName() {
00167   deltaVFrame* f = DeltaProcess::active()->last_delta_vframe();
00168    return f->method()->selector()->as_string();
00169 }
00170 
00171 
00172 static void breakpointCode() {
00173   
00174   
00175   if (!VerifyCode) warning(": breakpoint should not be called");
00176   theMacroAssm->pushad();
00177   call_C((char*)breakpoint, relocInfo::runtime_call_type, true);
00178   theMacroAssm->popad();
00179 }
00180 
00181 
00182 static void verifyOopCode(Register reg) {
00183   
00184   
00185   if (!VerifyCode) warning(": verifyOop should not be called");
00186   Label L;
00187   theMacroAssm->test(reg, Mark_Tag_Bit);
00188   theMacroAssm->jcc(Assembler::zero, L);
00189   theMacroAssm->hlt();
00190   theMacroAssm->bind(L);
00191 }
00192 
00193 
00194 extern "C" void verifyContext(oop obj) {
00195   
00196   contextOop ctx = contextOop(obj); 
00197   while (1) {
00198     if (ctx->is_mark()) error("context should never be mark");
00199     if (!Universe::is_heap((oop*)ctx)) error("context outside of heap");
00200     if (!ctx->is_context()) error("should be a context");
00201     if (ctx->unoptimized_context() != NULL) {
00202       error("context has been deoptimized -- shouldn't use in compiled code");
00203     }
00204     if (!ctx->has_outer_context()) break; 
00205     ctx = ctx->outer_context();
00206   }
00207 }
00208 
00209 
00210 static void verifyContextCode(Register reg) {
00211   
00212   
00213   if (!VerifyCode) warning(": verifyContext should not be called");
00214   theMacroAssm->pushad();
00215   theMacroAssm->pushl(reg);     
00216   call_C((char*)verifyContext, relocInfo::runtime_call_type, true);
00217   theMacroAssm->addl(esp, oopSize);   
00218   theMacroAssm->popad();
00219 }
00220 
00221 
00222 extern "C" void verifyNilOrContext(oop obj) {
00223   if (obj != nilObj) verifyContext(obj);
00224 }
00225 
00226 
00227 static void verifyNilOrContextCode(Register reg) {
00228   
00229   
00230   if (!VerifyCode) warning(": verifyNilOrContext should not be called");
00231   theMacroAssm->pushad();
00232   theMacroAssm->pushl(reg);     
00233   call_C((char*)verifyNilOrContext, relocInfo::runtime_call_type, true);
00234   theMacroAssm->addl(esp, oopSize);   
00235   theMacroAssm->popad();
00236 }
00237 
00238 
00239 extern "C" void verifyBlock(blockClosureOop blk) {
00240   blk->verify();
00241 }
00242 
00243 
00244 static void verifyBlockCode(Register reg) {
00245   
00246   
00247   if (!VerifyCode) warning(": verifyBlockCode should not be called");
00248   theMacroAssm->pushad();
00249   theMacroAssm->pushl(reg);     
00250   call_C((char*)verifyBlock, relocInfo::runtime_call_type, true);
00251   theMacroAssm->addl(esp, oopSize);   
00252   theMacroAssm->popad();
00253 }
00254 
00255 
00256 static int NumberOfReturns = 0;   
00257 
00258 extern "C" void verifyReturn(oop obj) {
00259   NumberOfReturns++;
00260   obj->verify();
00261   if (TraceCalls) {
00262     ResourceMark rm;
00263     callDepth--;
00264     indent(); lprintf("return %s from %s\n", obj->print_value_string(), nmethodName()); 
00265   }
00266 }
00267 
00268 
00269 static void verifyReturnCode(Register reg) {
00270   
00271   
00272   if (!VerifyCode && !GenTraceCalls) warning(": verifyReturn should not be called");
00273   theMacroAssm->pushad();
00274   theMacroAssm->pushl(reg);     
00275   call_C((char*)verifyReturn, relocInfo::runtime_call_type, true);
00276   theMacroAssm->addl(esp, oopSize);   
00277   theMacroAssm->popad();
00278 }
00279 
00280 
00281 extern "C" void verifyNLR(char* fp, char* nlrFrame, int nlrScopeID, oop nlrResult) {
00282   LOG_EVENT3("verifyNLR(%#x, %#x, %d, %#x)", fp, nlrFrame, nlrResult);
00283   if (nlrFrame <= fp) error("NLR went too far: %#x <= %#x", nlrFrame, fp);
00284   
00285   if (nlrScopeID < 0 || nlrScopeID > 99) error("illegal NLR scope ID %#x", nlrScopeID);
00286   if (nlrResult->is_mark()) error("NLR result is a markOop");
00287   if (TraceCalls) {
00288     ResourceMark rm;
00289     callDepth--;
00290     indent(); lprintf("NLR %s from/thru %s\n", nlrResult->print_value_string(), nmethodName()); 
00291   }
00292 }
00293 
00294 
00295 static void verifyNLRCode() {
00296   
00297   if (!VerifyCode) warning(": verifyNLRCode should not be called");
00298   theMacroAssm->pushad();
00299   theMacroAssm->pushl(Mapping::asRegister(NLRResultLoc));       
00300   theMacroAssm->pushl(Mapping::asRegister(NLRHomeIdLoc));
00301   theMacroAssm->pushl(Mapping::asRegister(NLRHomeLoc));
00302   theMacroAssm->pushl(ebp);
00303   call_C((char*)verifyNLR, relocInfo::runtime_call_type, true);
00304   theMacroAssm->addl(esp, 4*oopSize);   
00305   theMacroAssm->popad();
00306 }
00307 
00308 
00309 extern "C" void verifySmi(oop obj) {
00310   if (!obj->is_smi()) fatal("should be a smi");
00311 }
00312 
00313 
00314 static void verifySmiCode(Register reg) {
00315   
00316   
00317   if (!VerifyCode) warning(": verifySmi should not be called");
00318   theMacroAssm->pushad();
00319   theMacroAssm->pushl(reg);     
00320   call_C((char*)verifySmi, relocInfo::runtime_call_type, true);
00321   theMacroAssm->addl(esp, oopSize);   
00322   theMacroAssm->popad();
00323 }
00324 
00325 
00326 extern "C" void verifyObj(oop obj) {
00327   if (!obj->is_smi() && !obj->is_mem()) fatal("should be an ordinary oop");
00328   klassOop klass = obj->klass();
00329   if (klass == NULL || !klass->is_mem()) fatal("should be an ordinary memOop");
00330   if (obj->is_block()) blockClosureOop(obj)->verify();
00331 }
00332 
00333 
00334 static void verifyObjCode(Register reg) {
00335   
00336   
00337   if (!VerifyCode) warning(": verifyObj should not be called");
00338   theMacroAssm->pushad();
00339   theMacroAssm->pushl(reg);     
00340   call_C((char*)verifyObj, relocInfo::runtime_call_type, true);
00341   theMacroAssm->addl(esp, oopSize);   
00342   theMacroAssm->popad();
00343 }
00344 
00345 
00346 extern "C" void verifyArguments(oop recv, int ebp, int nofArgs) {
00347   ResourceMark rm;
00348   numberOfCalls++;
00349   if (TraceCalls) { 
00350     callDepth++;
00351     indent(); 
00352     lprintf("calling %s %s ", nmethodName(), recv->print_value_string());
00353   }
00354   verifyObj(recv);
00355   int i = nofArgs;
00356   oop* arg = (oop*)(ebp + (nofArgs + 2)*oopSize);
00357   while (i-- > 0) {
00358     arg--;
00359     verifyObj(*arg);
00360     if (TraceCalls) {
00361       ResourceMark rm;
00362       lprintf("%s, ", (*arg)->print_value_string());
00363     }
00364   }
00365   if (VerifyDebugInfo) { 
00366     deltaVFrame* f = DeltaProcess::active()->last_delta_vframe();
00367     while (f != NULL) {
00368       f->verify_debug_info();
00369       f = f->sender_delta_frame();
00370     }
00371   }
00372 }
00373 
00374 
00375 static void verifyArgumentsCode(Register recv, int nofArgs) {
00376   
00377   
00378   assert(VerifyCode || GenTraceCalls || VerifyDebugInfo, "performance bug: verifyArguments should not be called");
00379   theMacroAssm->pushad();
00380   theMacroAssm->pushl(nofArgs); 
00381   theMacroAssm->pushl(ebp);
00382   theMacroAssm->pushl(recv);
00383   call_C((char*)verifyArguments, relocInfo::runtime_call_type, true);
00384   theMacroAssm->addl(esp, 3*oopSize);   
00385   theMacroAssm->popad();
00386 }
00387 
00388 
00389 static int result_counter = 0;
00390 
00391 static void trace_result(int compilation, methodOop method, oop result) {
00392   ResourceMark rm;
00393   std->print("%6d: 0x%08x (compilation %4d, ", result_counter++, int(result), compilation);
00394   method->selector()->print_value();
00395   std->print(")\n", compilation);
00396 }
00397 
00398 
00399 static void call_trace_result(Register result) {
00400   theMacroAssm->pushad();
00401   theMacroAssm->pushl(result);
00402   theMacroAssm->pushl(theCompiler->method);
00403   theMacroAssm->pushl(nofCompilations);
00404   call_C((char*)trace_result, relocInfo::runtime_call_type, true);
00405   theMacroAssm->addl(esp, 3*oopSize);   
00406   theMacroAssm->popad();
00407 }
00408 
00409 
00410 
00411 
00412 static Register moveLocToReg(Location src, Register temp) {
00413   
00414   
00415   if (src.isRegisterLocation()) {
00416     return Mapping::asRegister(src);
00417   } else {
00418     Mapping::load(src, temp);
00419     return temp;
00420   }
00421 }
00422 
00423 
00424 static Register movePRegToReg(PReg* src, Register temp) {
00425   
00426   
00427   if (src->isConstPReg()) {
00428     theMacroAssm->movl(temp, ((ConstPReg*)src)->constant);
00429     return temp;
00430   } else {
00431     return moveLocToReg(src->loc, temp);
00432   }
00433 }
00434 
00435 
00436 static inline Register answerLocReg(Location src, Register temp) {
00437   
00438   
00439   return src.isRegisterLocation() ? Mapping::asRegister(src) : temp;
00440 }
00441 
00442 
00443 static inline Register answerPRegReg(PReg* src, Register temp) {
00444   
00445   
00446   return answerLocReg(src->loc, temp);
00447 }
00448 
00449 
00450 static void load(PReg* src, Register dst) {
00451   
00452   if (src->isConstPReg()) {
00453     theMacroAssm->movl(dst, ((ConstPReg*)src)->constant);
00454   } else {
00455     Mapping::load(src->loc, dst);
00456   }
00457 }
00458 
00459 
00460 static void fload(PReg* src, Register base, Register temp) {
00461   assert(base != temp, "registers must be different");
00462   
00463   if (src->isConstPReg()) {
00464     theMacroAssm->movl(temp, ((ConstPReg*)src)->constant);
00465     theMacroAssm->fld_d(Address(temp, byteOffset(doubleOopDesc::value_offset()))); 
00466   } else {
00467     Mapping::fload(src->loc, base);
00468   }
00469 }
00470 
00471 
00472 static void store(Register src, PReg* dst, Register temp1, Register temp2, bool needsStoreCheck = true) {
00473   
00474   assert(!dst->isConstPReg(), "destination cannot be a constant");
00475   Mapping::store(src, dst->loc, temp1, temp2, needsStoreCheck);
00476 }
00477 
00478 
00479 static void fstore(PReg* dst, Register base) {
00480   
00481   assert(!dst->isConstPReg(), "destination cannot be a constant");
00482   Mapping::fstore(dst->loc, base);
00483 }
00484 
00485 
00486 static void storeO(ConstPReg* src, PReg* dst, Register temp1, Register temp2, bool needsStoreCheck = true) {
00487   
00488   assert(!dst->isConstPReg(), "destination cannot be a constant");
00489   Mapping::storeO(src->constant, dst->loc, temp1, temp2, needsStoreCheck);
00490 }
00491 
00492 
00493 
00494 
00495 
00496 
00497 
00498 static void set_floats_base(Node* node, Register base, bool enforce = false) {
00499   
00500   assert(floatSize == 8, "check this code");
00501   assert(node->isAccessingFloats(), "must be a node accessing floats");
00502   assert(base == temp3, "check this code");
00503   if (node->hasSinglePredecessor() && node->firstPrev()->isAccessingFloats() && !enforce) {
00504     
00505     
00506   } else {
00507     theMacroAssm->movl(base, ebp);
00508     theMacroAssm->andl(base, -floatSize); 
00509   }
00510 }
00511 
00512 
00513 static void assign(Node* node, PReg* src, PReg* dst, Register temp1, Register temp2, Register temp3, bool needsStoreCheck = true) {
00514   
00515   assert(temp1 != temp2 && temp1 != temp3 && temp2 != temp3, "registers must be different");
00516   if (src->loc != dst->loc) {
00517     if (node->isAccessingFloats()) {
00518       Register base = temp3;
00519       set_floats_base(node, base);
00520       fload(src, base, temp1);
00521       fstore(dst, base);
00522     } else if (src->isConstPReg()) {
00523       
00524       storeO((ConstPReg*)src, dst, temp1, temp2, needsStoreCheck);
00525     } else {
00526       Register t = movePRegToReg(src, answerPRegReg(dst, temp1));
00527       store(t, dst, temp2, temp3, needsStoreCheck);
00528     }
00529   }
00530 }
00531 
00532 
00533 static Register uplevelBase(PReg* startContext, int nofLevels, Register temp) {
00534   
00535   Register b = nofLevels > 0 ? temp : answerPRegReg(startContext, temp);
00536   load(startContext, b);
00537   while (nofLevels-- > 0) { 
00538    if (VerifyCode) verifyContextCode(b);
00539    theMacroAssm->Load(b, contextOopDesc::parent_byte_offset(), b); 
00540   }
00541   return b;
00542 }
00543 
00544 
00545 
00546 
00547 static char* nmethodAddr() {
00548   
00549   
00550   return (char*)(((nmethod*) (theMacroAssm->code()->code_begin())) - 1);
00551 }
00552 
00553 
00554 static void incCounter() {
00555   
00556   char* addr = nmethodAddr() + nmethod::invocationCountOffset();
00557   theMacroAssm->incl(Address(int(addr), relocInfo::internal_word_type));
00558 }
00559 
00560 
00561 
00562 
00563 static Assembler::Condition mapToCC(BranchOpCode op) {
00564   switch (op) {
00565     case EQBranchOp : return Assembler::equal;
00566     case NEBranchOp : return Assembler::notEqual;
00567     case LTBranchOp : return Assembler::less;
00568     case LEBranchOp : return Assembler::lessEqual;
00569     case GTBranchOp : return Assembler::greater;
00570     case GEBranchOp : return Assembler::greaterEqual;
00571     case LTUBranchOp: return Assembler::below;
00572     case LEUBranchOp: return Assembler::belowEqual;
00573     case GTUBranchOp: return Assembler::above;
00574     case GEUBranchOp: return Assembler::aboveEqual;
00575     case VSBranchOp : return Assembler::overflow;
00576     case VCBranchOp : return Assembler::noOverflow;
00577     default: ShouldNotReachHere(); return Assembler::zero;
00578   }
00579 }
00580 
00581 
00582 static void primitiveCall(InlinedScope* scope, primitive_desc* pdesc) {
00583   if (pdesc->can_perform_NLR()) {
00584     call_C((char*)(&pdesc->fn()), relocInfo::prim_type, pdesc->needs_delta_fp_code(), scope->nlrTestPoint()->label);
00585   } else {
00586     call_C((char*)(&pdesc->fn()), relocInfo::prim_type, pdesc->needs_delta_fp_code());
00587   }
00588 }
00589 
00590 
00591 static void zapContext(PReg* context, Register temp) {
00592   Register c = movePRegToReg(context, temp);
00593   theMacroAssm->movl(Address(c, contextOopDesc::parent_byte_offset()), 0);
00594 }
00595 
00596 
00597 static void continueNLR(Register temp1, Register temp2) {
00598   assert(temp1 == ::temp1 && temp2 == ::temp2, "different register usage than stub routine - check this");
00599   if (VerifyCode) verifyNLRCode();
00600   theMacroAssm->jmp(StubRoutines::continue_NLR_entry(), relocInfo::runtime_call_type);
00601 }
00602 
00603 
00604 
00605 
00606 void BasicNode::gen() {
00607   ScopeDescRecorder* rec = theCompiler->scopeDescRecorder();
00608   rec->addPcDesc(theMacroAssm->offset(), _scope->scopeInfo(), _bci);
00609 }
00610 
00611 
00612 static void checkRecompilation(Label& recompile_stub_call, Register t) {
00613   if (RecompilationPolicy::needRecompileCounter(theCompiler)) {
00614     
00615     char* addr = nmethodAddr() + nmethod::invocationCountOffset();
00616     theMacroAssm->movl(t, Address(int(addr), relocInfo::internal_word_type));
00617     theMacroAssm->incl(t);
00618     theMacroAssm->cmpl(t, theCompiler->get_invocation_counter_limit());
00619     theMacroAssm->movl(Address(int(addr), relocInfo::internal_word_type), t);
00620     theMacroAssm->jcc(Assembler::greaterEqual, recompile_stub_call);
00621   }
00622 }
00623 
00624 
00625 static void verify_context_chain(Register closure, int chain_length, Register temp1, Register temp2) {
00626   
00627   
00628   
00629   
00630   
00631   assert(closure != temp1 && closure != temp2 && temp1 != temp2, "registers must be different");
00632   assert(chain_length >= 1, "must have at least one context in the chain");
00633   const Register context = temp1;
00634   const Register sum     = temp2;
00635   
00636   theMacroAssm->movl(context, Address(closure, blockClosureOopDesc::context_byte_offset()));
00637   theMacroAssm->movl(sum, Address(context, memOopDesc::mark_byte_offset()));
00638   
00639   for (int i = chain_length - 1; i-- > 0; ) {
00640     theMacroAssm->movl(context, Address(context, contextOopDesc::parent_byte_offset()));
00641     theMacroAssm->orl(sum, Address(context, memOopDesc::mark_byte_offset()));
00642   }
00643   
00644   theMacroAssm->testl(sum, markOopDesc::context_forward_bit_mask());
00645   theMacroAssm->jcc(Assembler::notZero, StubRoutines::deoptimize_block_entry(), relocInfo::runtime_call_type);
00646   
00647 }
00648 
00649 
00650 void PrologueNode::gen() {
00651   BasicNode::gen();
00652 
00653   
00654   
00655   Label recompile_stub_call;
00656   theMacroAssm->bind(recompile_stub_call);
00657   theCompiler->set_special_handler_call_offset(theMacroAssm->offset());
00658   theMacroAssm->call(StubRoutines::recompile_stub_entry(), relocInfo::runtime_call_type);
00659 
00660   
00661   theMacroAssm->align(oopSize);
00662   theCompiler->set_entry_point_offset(theMacroAssm->offset());
00663   Register recv = moveLocToReg(selfLoc, temp1);
00664   if (scope()->isMethodScope()) {
00665     
00666     klassOop klass = _scope->selfKlass();
00667     if (klass == smiKlassObj) {
00668       
00669       theMacroAssm->test(recv, Mem_Tag);
00670       theMacroAssm->jcc(Assembler::notZero, CompiledIC::normalLookupRoutine());
00671     } else {
00672       
00673       theMacroAssm->test(recv, Mem_Tag);
00674       theMacroAssm->jcc(Assembler::zero, CompiledIC::normalLookupRoutine());
00675       theMacroAssm->cmpl(Address(recv, memOopDesc::klass_byte_offset()), klass);
00676       theMacroAssm->jcc(Assembler::notEqual, CompiledIC::normalLookupRoutine());
00677     }
00678   } else {
00679     
00680     
00681     
00682     
00683     if (scope()->method()->block_info() == methodOopDesc::expects_context) {
00684       const bool use_fast_check = false;                        
00685       if (use_fast_check) {
00686         
00687         
00688         
00689         int length = _scope->homeContext() + 1;                 
00690         if (scope()->allocatesCompiledContext()) length--;      
00691         verify_context_chain(recv, length, temp2, temp3);
00692       } else {
00693         theMacroAssm->call(StubRoutines::verify_context_chain(), relocInfo::runtime_call_type);
00694       }
00695     }
00696   }
00697 
00698   
00699   theMacroAssm->align(oopSize);
00700   theCompiler->set_verified_entry_point_offset(theMacroAssm->offset());
00701   
00702   int frame_size = 2;   
00703   theMacroAssm->enter();
00704   
00705   int nofFloats = theCompiler->totalNofFloatTemporaries();
00706   if (nofFloats > 0) {
00707     assert(floatSize == oopSize*2, "check this code");
00708     assert(first_float_offset == -4, "check this code");
00709     int float_section_size = nofFloats*(floatSize/oopSize) + 2; 
00710     frame_size += 1 + float_section_size;                       
00711     theMacroAssm->pushl(Floats::magic);                         
00712     theMacroAssm->subl(esp, float_section_size * oopSize);      
00713     theCompiler->set_float_section_size(float_section_size);
00714     theCompiler->set_float_section_start_offset(-2);            
00715   }
00716   
00717   int nofTemps = theAllocator->nofStackTemps();
00718   if (nofTemps > 0) {
00719     assert(first_temp_offset == -1, "check this code");
00720     frame_size += nofTemps;
00721     theMacroAssm->movl(temp2, nilObj);
00722     for (int i = 0; i < nofTemps; i++) theMacroAssm->pushl(temp2);
00723   }
00724   
00725   if (frame_size < minimum_size_for_deoptimized_frame) {
00726     if (nofTemps == 0) theMacroAssm->movl(temp2, nilObj);       
00727     while (frame_size < minimum_size_for_deoptimized_frame) {
00728       frame_size++;
00729       theMacroAssm->pushl(temp2);
00730     }
00731   }
00732 
00733   if (VerifyCode || VerifyDebugInfo || GenTraceCalls) verifyArgumentsCode(recv, scope()->method()->number_of_arguments());
00734 
00735   
00736   
00737   if (scope()->isMethodScope()) {
00738     store(recv, scope()->self()->preg(), temp2, temp3);
00739   } else {
00740     
00741     Register c = answerPRegReg(scope()->self()->preg(), temp2);
00742     theMacroAssm->Load(recv, blockClosureOopDesc::context_byte_offset(), c);
00743     store(c, scope()->self()->preg(), temp1, temp3);
00744     store(c, scope()->context(), temp1, temp3);
00745 
00746     if (VerifyCode) {
00747       switch (scope()->method()->block_info()) {
00748         case methodOopDesc::expects_nil      : verifyNilOrContextCode(c); break;
00749         case methodOopDesc::expects_self     : 
00750         case methodOopDesc::expects_parameter: verifyOopCode(c);          break;
00751         case methodOopDesc::expects_context  : verifyContextCode(c);      break;
00752         default: ShouldNotReachHere();
00753       }
00754     }
00755   }
00756   
00757   checkRecompilation(recompile_stub_call, temp2);
00758 }
00759 
00760 
00761 void LoadIntNode::gen() {
00762   BasicNode::gen();
00763   Register t = answerPRegReg(_dest, temp1);
00764   theMacroAssm->movl(t, _value);
00765   store(t, _dest, temp2, temp3);
00766 }
00767 
00768 
00769 void LoadOffsetNode::gen() {
00770   BasicNode::gen();
00771   Register b = movePRegToReg(_src, temp1);
00772   Register t = answerPRegReg(_dest, temp2);
00773   theMacroAssm->Load(b, byteOffset(offset), t);
00774   store(t, _dest, temp1, temp3);
00775 }
00776 
00777 
00778 void LoadUplevelNode::gen() {
00779   BasicNode::gen();
00780   Register b = uplevelBase(_context0, _nofLevels, temp1);
00781   Register t = answerPRegReg(_dest, temp2);
00782   theMacroAssm->Load(b, byteOffset(_offset), t);
00783   if (VerifyCode) verifyObjCode(t);
00784   store(t, _dest, temp1, temp3);
00785 }
00786 
00787 
00788 void StoreOffsetNode::gen() {
00789   BasicNode::gen();
00790   Register b = movePRegToReg(_base, temp1);
00791   Register t = movePRegToReg(_src, temp2);
00792   theMacroAssm->Store(t, b, byteOffset(_offset));
00793   if (_needsStoreCheck) {
00794     
00795     if (b != temp1) load(_base, temp1);
00796     theMacroAssm->store_check(temp1, temp2);
00797   }
00798 }
00799 
00800 
00801 void StoreUplevelNode::gen() {
00802   StoreNode::gen();
00803   Register b = uplevelBase(_context0, _nofLevels, temp1);
00804   Register t = movePRegToReg(_src, temp2);
00805   theMacroAssm->Store(t, b, byteOffset(_offset));
00806   if (_needsStoreCheck) {
00807     
00808     if (b != temp1) load(_context0, temp1);
00809     theMacroAssm->store_check(temp1, temp2);
00810   }
00811 }
00812 
00813 
00814 void MergeNode::gen() {
00815   BasicNode::gen();
00816   
00817 }
00818 
00819 
00820 void SendNode::gen() {
00821   BasicNode::gen();
00822   if (isCounting()) incCounter();
00823   char* entry = _superSend ? CompiledIC::superLookupRoutine() : CompiledIC::normalLookupRoutine();
00824   theMacroAssm->call(entry, relocInfo::ic_type);
00825   inlineCache(scope()->nlrTestPoint()->label, _info, _superSend);
00826   assert(_dest->loc == resultLoc, "assignment missing");
00827 }
00828 
00829 
00830 void PrimNode::gen() {
00831   BasicNode::gen();
00832   primitiveCall(scope(), _pdesc);
00833   
00834   Register t = moveLocToReg(resultLoc, answerPRegReg(_dest, temp1));
00835   store(t, _dest, temp2, temp3);
00836 }
00837 
00838 
00839 void DLLNode::gen() {
00840   BasicNode::gen();
00841   assert(temp1 == ebx && temp2 == ecx && temp3 == edx, "registers are no temps anymore -> fix parameter passing");
00842   
00843   
00844   char* entry = (function() == NULL) ? StubRoutines::lookup_DLL_entry(async()) : StubRoutines::call_DLL_entry(async());
00845   
00846   
00847   
00848   
00849   
00850   theMacroAssm->movl(ebx, nofArguments());      
00851   theMacroAssm->movl(ecx, esp);                 
00852   
00853   
00854   
00855   theMacroAssm->movl(edx, int(function()));     
00856   theMacroAssm->inline_oop(dll_name());         
00857   theMacroAssm->inline_oop(function_name());    
00858   theMacroAssm->call(entry, relocInfo::runtime_call_type);
00859   
00860   
00861   inlineCache(scope()->nlrTestPoint()->label, NULL, false);
00862   
00863   theMacroAssm->addl(esp, nofArguments()*oopSize);      
00864   Register t = moveLocToReg(resultLoc, answerPRegReg(_dest, temp1));
00865   store(t, _dest, temp2, temp3);
00866 }
00867 
00868 
00869 static bool producesResult(ArithOpCode op) {
00870   return (op != TestArithOp) && (op != CmpArithOp) && (op != tCmpArithOp);
00871 }
00872 
00873 
00874 static bool setupRegister(PReg* dst, PReg* arg, ArithOpCode op, Register& x, Register t) {
00875   
00876   
00877   
00878   bool result = producesResult(op);
00879   if (result) {
00880     
00881     if ((dst->loc == arg->loc) ) {
00882       
00883       x = movePRegToReg(arg, t);
00884     } else {
00885       
00886       x = t; load(arg, t);
00887     }
00888   } else {
00889     
00890     assert(dst->isNoPReg(), "dst should be a noPReg");
00891     x = movePRegToReg(arg, t);
00892   }
00893   return result;
00894 }
00895 
00896 
00897 static bool setupRegisters(PReg* dst, PReg* arg1, ArithOpCode op, PReg* arg2, Register& x, Register& y, Register t1, Register t2) {
00898   
00899   
00900   
00901   assert(t1 != t2, "registers should be different");
00902   bool result = producesResult(op);
00903   if (result) {
00904     
00905     if ((dst->loc == arg1->loc) ) {
00906       
00907       x = movePRegToReg(arg1, t1);
00908       y = movePRegToReg(arg2, t2);
00909     } else {
00910       
00911       x = t1; load(arg1, t1);
00912       y = movePRegToReg(arg2, t2);
00913     }
00914   } else {
00915     
00916     assert(dst->isNoPReg(), "dst should be a noPReg");
00917     x = movePRegToReg(arg1, t1);
00918     y = movePRegToReg(arg2, t2);
00919   }
00920   return result;
00921 }
00922 
00923 
00924 static void arithRROp(ArithOpCode op, Register x, Register y) {
00925   assert(Int_Tag == 0, "check this code");
00926   switch (op) {
00927     case TestArithOp  : theMacroAssm->testl(x, y);      break;
00928     case tAddArithOp  : 
00929     case  AddArithOp  : theMacroAssm->addl(x, y);       break;
00930     case tSubArithOp  : 
00931     case  SubArithOp  : theMacroAssm->subl(x, y);       break;
00932     case tMulArithOp  : theMacroAssm->sarl(x, Tag_Size);
00933     case  MulArithOp  : theMacroAssm->imull(x, y);      break;
00934     case tDivArithOp  : 
00935     case  DivArithOp  : Unimplemented();                break;
00936     case tModArithOp  : 
00937     case  ModArithOp  : Unimplemented();                break;
00938     case tAndArithOp  : 
00939     case  AndArithOp  : theMacroAssm->andl(x, y);       break;
00940     case tOrArithOp   : 
00941     case  OrArithOp   : theMacroAssm->orl(x, y);        break;
00942     case tXOrArithOp  : 
00943     case  XOrArithOp  : theMacroAssm->xorl(x, y);       break;
00944     case tShiftArithOp: Unimplemented();
00945     case  ShiftArithOp: Unimplemented();
00946     case tCmpArithOp  : 
00947     case  CmpArithOp  : theMacroAssm->cmpl(x, y);       break;
00948     default           : ShouldNotReachHere();
00949   }
00950 }
00951 
00952 
00953 static void arithRCOp(ArithOpCode op, Register x, int y) {
00954   assert(Int_Tag == 0, "check this code");
00955   switch (op) {
00956     case TestArithOp  : theMacroAssm->testl(x, y);      break;
00957     case tAddArithOp  : 
00958     case  AddArithOp  : theMacroAssm->addl(x, y);       break;
00959     case tSubArithOp  : 
00960     case  SubArithOp  : theMacroAssm->subl(x, y);       break;
00961     case tMulArithOp  : y = arithmetic_shift_right(y, Tag_Size);
00962     case  MulArithOp  : theMacroAssm->imull(x, x, y);   break;
00963     case tDivArithOp  : 
00964     case  DivArithOp  : Unimplemented();                break;
00965     case tModArithOp  : 
00966     case  ModArithOp  : Unimplemented();                break;
00967     case tAndArithOp  : 
00968     case  AndArithOp  : theMacroAssm->andl(x, y);       break;
00969     case tOrArithOp   : 
00970     case  OrArithOp   : theMacroAssm->orl(x, y);        break;
00971     case tXOrArithOp  : 
00972     case  XOrArithOp  : theMacroAssm->xorl(x, y);       break;
00973     case tShiftArithOp:
00974       if (y < 0) {
00975         
00976         int shift_count = ((-y) >> Tag_Size) % 32;
00977         theMacroAssm->sarl(x, shift_count);
00978         theMacroAssm->andl(x, -1 << Tag_Size);          
00979       } else if (y > 0) {
00980         
00981         int shift_count = ((+y) >> Tag_Size) % 32;
00982         theMacroAssm->shll(x, shift_count);
00983       }
00984       break;
00985     case  ShiftArithOp: Unimplemented();
00986     case tCmpArithOp  : 
00987     case  CmpArithOp  : theMacroAssm->cmpl(x, y);       break;
00988     default           : ShouldNotReachHere();
00989   }
00990 }
00991 
00992 
00993 static void arithROOp(ArithOpCode op, Register x, oop y) {
00994   assert(!y->is_smi(), "check this code");
00995   switch (op) {
00996     case  CmpArithOp  : theMacroAssm->cmpl(x, y);       break;
00997     default           : ShouldNotReachHere();
00998   }
00999 }
01000 
01001 
01002 void TArithRRNode::gen() {
01003   BasicNode::gen();
01004   PReg* arg1 = _src;
01005   PReg* arg2 = _oper;
01006   if (arg2->isConstPReg()) {
01007     oop y = ((ConstPReg*)arg2)->constant;
01008     assert(y->is_smi() == _arg2IsInt, "flag value inconsistent");
01009     if (_arg2IsInt) {
01010       
01011       Register x;
01012       bool result = setupRegister(_dest, arg1, _op, x, temp1);
01013       if (!_arg1IsInt) {
01014         
01015         theMacroAssm->test(x, Mem_Tag);
01016         theMacroAssm->jcc(Assembler::notZero, next(1)->label);
01017       }
01018       arithRCOp(_op, x, int(y));                        
01019       if (result) store(x, _dest, temp2, temp3);
01020     } else {
01021       
01022       theMacroAssm->jmp(next(1)->label);
01023     }
01024   } else {
01025     Register x, y;
01026     bool result = setupRegisters(_dest, arg1, _op, arg2, x, y, temp1, temp2);
01027     
01028     Register tags = noreg;
01029     if (_arg1IsInt) {
01030       if (_arg2IsInt) {
01031         
01032       } else {
01033         
01034         tags = y;
01035       }
01036     } else {
01037       if (_arg2IsInt) {
01038         
01039         tags = x;
01040       } else {
01041         
01042         tags = temp3;
01043         theMacroAssm->movl(tags, x);
01044         theMacroAssm->orl (tags, y);
01045       }
01046     }
01047     if (tags != noreg) {
01048       
01049       theMacroAssm->test(tags, Mem_Tag);
01050       theMacroAssm->jcc(Assembler::notZero, next(1)->label);
01051     }
01052     
01053     arithRROp(_op, x, y);
01054     if (result) {
01055       Register t = (x == temp1) ? temp2 : temp1;
01056       store(x, _dest, t, temp3);
01057     }
01058   }
01059 }
01060 
01061 
01062 void ArithRRNode::gen() {
01063   BasicNode::gen();
01064   PReg* arg1 = _src;
01065   PReg* arg2 = _oper;
01066   if (arg2->isConstPReg()) {
01067     oop y = ((ConstPReg*)arg2)->constant;
01068     Register x;
01069     bool result = setupRegister(_dest, arg1, _op, x, temp1);
01070     if (y->is_smi()) {
01071       arithRCOp(_op, x, int(y));                
01072     } else {
01073       arithROOp(_op, x, y);
01074     }
01075     if (result) store(x, _dest, temp2, temp3);
01076   } else {
01077     Register x, y;
01078     bool result = setupRegisters(_dest, arg1, _op, arg2, x, y, temp1, temp2);
01079     arithRROp(_op, x, y);
01080     if (result) {
01081       Register t = (x == temp1) ? temp2 : temp1;
01082       store(x, _dest, t, temp3);
01083     }
01084   }
01085 }
01086 
01087 
01088 void ArithRCNode::gen() {
01089   BasicNode::gen();
01090   PReg* arg1 = _src;
01091   int y = _oper;
01092   Register x;
01093   bool result = setupRegister(_dest, arg1, _op, x, temp1);
01094   arithRCOp(_op, x, y);
01095   if (result) store(x, _dest, temp2, temp3);
01096 }
01097 
01098 
01099 static void floatArithRROp(ArithOpCode op) {
01100   switch (op) {
01101     case fAddArithOp: theMacroAssm->faddp();    break;
01102     case fSubArithOp: theMacroAssm->fsubp();    break;
01103     case fMulArithOp: theMacroAssm->fmulp();    break;
01104     case fDivArithOp: theMacroAssm->fdivp();    break;
01105     case fModArithOp: theMacroAssm->fprem();    break;
01106     case fCmpArithOp: theMacroAssm->fcompp();   break;
01107     default         : ShouldNotReachHere();
01108   }
01109 }
01110 
01111 
01112 void FloatArithRRNode::gen() {
01113   BasicNode::gen();
01114   bool noResult = (_op == fCmpArithOp);
01115   bool exchange = (_op == fModArithOp || _op == fCmpArithOp);
01116   Register base = temp3;
01117   set_floats_base(this, base);
01118   fload(_src, base, temp1);
01119   fload(_oper, base, temp2);
01120   if (exchange) theMacroAssm->fxch();   
01121   floatArithRROp(_op);
01122   if (_op == fCmpArithOp) {
01123     
01124     assert(!Mapping::isFloatTemporary(_dest->loc), "fCmpArithOp doesn't produce a float");
01125     if (_dest->loc.isRegisterLocation() && _dest->loc.number() == eax.number()) {
01126       
01127       theMacroAssm->fwait();
01128       theMacroAssm->fnstsw_ax();
01129     } else {
01130       
01131       Unimplemented();
01132     }
01133   } else {
01134     
01135     fstore(_dest, base);
01136   }
01137 }
01138 
01139 
01140 static Address doubleKlass_addr() {
01141   return Address((int)&doubleKlassObj, relocInfo::external_word_type);
01142 }
01143 
01144 
01145 static oop oopify_float() {
01146   double x;
01147   __asm fstp x                                                  
01148   BlockScavenge bs;                                             
01149   return oopFactory::new_double(x);                             
01150 }
01151 
01152 
01153 static void floatArithROp(ArithOpCode op, Register reg, Register temp) {
01154   assert(reg != temp, "registers must be different");
01155   switch (op) {
01156     case fNegArithOp   : theMacroAssm->fchs();  break;
01157     case fAbsArithOp   : theMacroAssm->fabs();  break;
01158     case fSqrArithOp   : theMacroAssm->fmul(0); break;
01159     case f2OopArithOp  :
01160       { theMacroAssm->pushl(reg);                               
01161         theMacroAssm->pushad();                                 
01162         theMacroAssm->call((char*)oopify_float, relocInfo::runtime_call_type);
01163         theMacroAssm->movl(Address(esp, nofRegisters * oopSize), eax);  
01164         theMacroAssm->popad();                                  
01165         theMacroAssm->popl(reg);                                
01166       }
01167       break;
01168     case f2FloatArithOp:
01169       { Label is_smi, is_float, done;
01170         theMacroAssm->test(reg, Mem_Tag);                       
01171         theMacroAssm->jcc(Assembler::zero, is_smi);
01172         theMacroAssm->movl(temp, Address(reg, memOopDesc::klass_byte_offset()));        
01173         theMacroAssm->cmpl(temp, doubleKlass_addr());           
01174         theMacroAssm->jcc(Assembler::equal, is_float);
01175         theMacroAssm->hlt(); 
01176 
01177         
01178         theMacroAssm->bind(is_smi);
01179         theMacroAssm->sarl(reg, Tag_Size);                      
01180         theMacroAssm->movl(Address(esp, -oopSize), reg);        
01181         theMacroAssm->fild_s(Address(esp, -oopSize));           
01182         theMacroAssm->jmp(done);
01183 
01184         
01185         theMacroAssm->bind(is_float);
01186         theMacroAssm->fld_d(Address(reg, byteOffset(doubleOopDesc::value_offset()))); 
01187 
01188         theMacroAssm->bind(done);
01189       }
01190       break;
01191     default            : ShouldNotReachHere();
01192   }
01193 }
01194 
01195 
01196 void FloatUnaryArithNode::gen() {
01197   BasicNode::gen();
01198   Register reg;
01199   Register base = temp3;
01200   set_floats_base(this, base);
01201   if (Mapping::isFloatTemporary(_src->loc) || _src->loc == topOfFloatStack) {
01202     
01203     fload(_src, base, temp1);
01204     reg = temp1;
01205   } else {
01206     
01207     reg = movePRegToReg(_src, temp1);
01208   }
01209   floatArithROp(_op, reg, temp2);
01210   if (Mapping::isFloatTemporary(_dest->loc) || _dest->loc == topOfFloatStack) {
01211     
01212     fstore(_dest, base);
01213   } else {
01214     
01215     store(reg, _dest, temp2, temp3);
01216     set_floats_base(this, base, true);  
01217   }
01218 }
01219 
01220 
01221 void AssignNode::gen() {
01222   StoreNode::gen();
01223   assign(this, _src, _dest, temp1, temp2, temp3);
01224 }
01225 
01226 
01227 void BranchNode::gen() {
01228   BasicNode::gen();
01229   theMacroAssm->jcc(mapToCC(_op), next(1)->label);
01230 }
01231 
01232 
01233 
01234 
01235 
01236 
01237 
01238 
01239 
01240 
01241 
01242 
01243 void ContextCreateNode::gen() {
01244   BasicNode::gen();
01245 
01246   switch (_contextSize) {
01247     case 0:  primitiveCall(scope(), primitives::context_allocate0()); break;
01248     case 1:  primitiveCall(scope(), primitives::context_allocate1()); break;
01249     case 2:  primitiveCall(scope(), primitives::context_allocate2()); break;
01250     default: assert(_pdesc == primitives::context_allocate(), "bad context create prim");
01251              theMacroAssm->pushl((int)as_smiOop(_contextSize));
01252              primitiveCall(scope(), _pdesc);
01253              theMacroAssm->addl(esp, oopSize);  
01254   }
01255   Register context = Mapping::asRegister(resultLoc);
01256   if (_src == NULL) {
01257     assert(scope()->isMethodScope() || scope()->method()->block_info() == methodOopDesc::expects_nil, "inconsistency");
01258     theMacroAssm->movl(Address(context, contextOopDesc::parent_byte_offset()), NULL);
01259     
01260     
01261     
01262     
01263   } else {
01264     
01265     Register parent = movePRegToReg(_src, temp1);
01266     theMacroAssm->movl(Address(context, contextOopDesc::parent_byte_offset()), parent);
01267   }
01268   store(context, _dest, temp2, temp3);
01269   theMacroAssm->store_check(context, temp2);
01270 }
01271 
01272 
01273 void ContextInitNode::gen() {
01274   BasicNode::gen();
01275   
01276   for (int i = nofTemps() - 1; i >= 0; i--) {
01277     PReg* src = _initializers->at(i)->preg();
01278     PReg* dest;
01279     if (src->isBlockPReg()) {
01280       
01281       if (wasEliminated()) {
01282         continue;                               
01283       } else {
01284         dest = contents()->at(i)->preg();       
01285       }
01286     } else {
01287       dest = contents()->at(i)->preg();
01288     }
01289     assign(this, src, dest, temp1, temp2, temp3, false);
01290   }
01291   
01292   
01293 }
01294 
01295 
01296 void ContextZapNode::gen() {
01297   
01298   ShouldNotReachHere();
01299 }
01300 
01301 
01302 void FixedCodeNode::gen() {
01303   BasicNode::gen();
01304   switch(_kind) {
01305     case dead_end:    theMacroAssm->hlt(); break;
01306     case inc_counter: incCounter(); break;
01307     default:          fatal1("unexpected FixedCodeNode kind %d", _kind);
01308   }
01309 }
01310 
01311 
01312 void InlinedReturnNode::gen() {
01313   BasicNode::gen();
01314   assign(this, _src, _dest, temp1, temp2, temp3);
01315   if (scope()->needsContextZapping()) {
01316     zapContext(scope()->context(), temp1);
01317   }
01318 }
01319 
01320 
01321 void ReturnNode::gen() {
01322   BasicNode::gen();
01323   assert(_src->loc == resultLoc, "result in wrong location");
01324   if (scope()->needsContextZapping()) {
01325     zapContext(scope()->context(), temp1);
01326   }
01327   
01328   if (VerifyCode || GenTraceCalls) verifyReturnCode(Mapping::asRegister(resultLoc));
01329   if (TraceResults) call_trace_result(result_reg);
01330   int no_of_args_to_pop = scope()->nofArguments();
01331   if (scope()->method()->is_blockMethod()) {
01332     
01333     
01334     
01335     no_of_args_to_pop++;
01336   }
01337   theMacroAssm->leave();
01338   theMacroAssm->ret(no_of_args_to_pop * oopSize);
01339 }
01340 
01341 
01342 void NLRSetupNode::gen() {
01343   BasicNode::gen();
01344   assert(_src->loc == NLRResultLoc, "result in wrong location");
01345   
01346   Label NLR_error;
01347   Register home = uplevelBase(scope()->context(), scope()->homeContext() + 1, temp1);
01348   theMacroAssm->testl(home, home);
01349   theMacroAssm->jcc(Assembler::zero, NLR_error); 
01350   if (home != Mapping::asRegister(NLRHomeLoc)) {
01351     theMacroAssm->movl(Mapping::asRegister(NLRHomeLoc), home);
01352   }
01353   
01354   theMacroAssm->movl(NLR_homeId_reg, scope()->home()->scopeID());
01355   if (TraceResults) call_trace_result(NLR_result_reg);
01356   continueNLR(temp1, temp2);
01357   
01358   theMacroAssm->bind(NLR_error);
01359   call_C((char*)suspend_on_NLR_error, relocInfo::runtime_call_type, true);
01360   theMacroAssm->hlt();
01361 }
01362 
01363 
01364 void NLRContinuationNode::gen() {
01365   BasicNode::gen();
01366   if (scope()->needsContextZapping()) {
01367     zapContext(scope()->context(), temp1);
01368   }
01369   continueNLR(temp1, temp2);
01370 }
01371 
01372 
01373 void NLRTestNode::gen() {
01374   BasicNode::gen();
01375   
01376   
01377   Label L;
01378   theMacroAssm->cmpl(Mapping::asRegister(NLRHomeLoc), ebp);
01379   theMacroAssm->jcc(Assembler::notEqual, L);
01380   
01381   int id = scope()->scopeID();
01382   if (id == 0) {
01383     
01384     theMacroAssm->testl(Mapping::asRegister(NLRHomeIdLoc), Mapping::asRegister(NLRHomeIdLoc));
01385   } else {
01386     theMacroAssm->cmpl(Mapping::asRegister(NLRHomeIdLoc), id);
01387   }
01388   theMacroAssm->jcc(Assembler::equal, next1()->label);
01389   
01390   theMacroAssm->bind(L);
01391 }
01392 
01393 
01394 void InterruptCheckNode::gen() {
01395   BasicNode::gen();
01396   Unimplemented();
01397 }
01398 
01399 
01400 static void testForSingleKlass(Register obj, klassOop klass, Register klassReg, Label& success, Label& failure) {
01401   if (klass == Universe::smiKlassObj()) {
01402     
01403     theMacroAssm->test(obj, Mem_Tag);
01404   } else if (klass == Universe::trueObj()->klass()) {
01405     
01406     theMacroAssm->cmpl(obj, Universe::trueObj());
01407   } else if (klass == Universe::falseObj()->klass()) {
01408     
01409     theMacroAssm->cmpl(obj, Universe::falseObj());
01410   } else if (klass == Universe::nilObj()->klass()) {
01411     
01412     theMacroAssm->cmpl(obj, Universe::nilObj());
01413   } else {
01414     
01415     theMacroAssm->test(obj, Mem_Tag);
01416     theMacroAssm->jcc(Assembler::zero, failure);
01417     theMacroAssm->movl(klassReg, Address(obj, memOopDesc::klass_byte_offset()));
01418     theMacroAssm->cmpl(klassReg, klass);
01419   }
01420   theMacroAssm->jcc(Assembler::notEqual, failure);
01421   theMacroAssm->jmp(success);   
01422 }
01423 
01424 
01425 static bool testForBoolKlasses(Register obj, klassOop klass1, klassOop klass2, Register klassReg, 
01426                                bool hasUnknown, Label& success1, Label& success2, Label& failure) {
01427   oop bool1  = Universe::trueObj();
01428   oop bool2  = Universe::falseObj();
01429   if (klass1 == bool2->klass() && klass2 == bool1->klass()) {
01430     oop t = bool1; bool1 = bool2; bool2 = t;
01431   }
01432   if (klass1 == bool1->klass() && klass2 == bool2->klass()) {
01433     if (hasUnknown) {
01434       theMacroAssm->cmpl(obj, bool1);
01435       theMacroAssm->jcc(Assembler::equal, success1);
01436       theMacroAssm->cmpl(obj, bool2);
01437       theMacroAssm->jcc(Assembler::notEqual, failure);
01438       theMacroAssm->jmp(success2);      
01439     } else {
01440       theMacroAssm->cmpl(obj, bool2);
01441       theMacroAssm->jcc(Assembler::equal, success2);
01442       theMacroAssm->jmp(success1);      
01443     }
01444     return true;
01445   }
01446   return false;
01447 }
01448 
01449 
01450 static void generalTypeTest(Register obj, Register klassReg, bool hasUnknown,
01451                             GrowableArray<klassOop>* classes, GrowableArray<Label*>* next) {
01452   
01453   int smi_case = -1;                    
01454   const int len = classes->length();
01455   GrowableArray<klassOop> klasses(len); 
01456   GrowableArray<Label*>    labels(len); 
01457 
01458   
01459   for (int i = 0; i < len; i++) {
01460     const klassOop klass = classes->at(i);
01461     if (klass == Universe::smiKlassObj()) {
01462       smi_case = i + 1;
01463     } else {
01464       klasses.append(klass);
01465       labels.append(next->at(i+1));
01466     }
01467   }
01468 
01469   if (smi_case == -1 && hasUnknown) {
01470     
01471     smi_case = 0;
01472   }
01473 
01474   
01475   if (smi_case >= 0) {
01476     theMacroAssm->test(obj, Mem_Tag);
01477     theMacroAssm->jcc(Assembler::zero, *next->at(smi_case));
01478   }
01479 
01480   bool klassHasBeenLoaded = false;
01481   const int nof_cmps = hasUnknown ? klasses.length() : klasses.length() - 1;
01482   for (i = 0; i < nof_cmps; i++) {
01483     const klassOop klass = klasses.at(i);
01484     if (klass == Universe::trueObj()->klass()) {
01485       
01486       theMacroAssm->cmpl(obj, Universe::trueObj());
01487     } else if (klass == Universe::falseObj()->klass()) {
01488       
01489       theMacroAssm->cmpl(obj, Universe::falseObj());
01490     } else if (klass == Universe::nilObj()->klass()) {
01491       
01492       theMacroAssm->cmpl(obj, Universe::nilObj());
01493     } else {
01494       
01495       assert(klass != Universe::smiKlassObj(), "should have been excluded");
01496       if (!klassHasBeenLoaded) {
01497         theMacroAssm->movl(klassReg, Address(obj, memOopDesc::klass_byte_offset()));
01498         klassHasBeenLoaded = true;
01499       }
01500       theMacroAssm->cmpl(klassReg, klass);
01501     }
01502     theMacroAssm->jcc(Assembler::equal, *labels.at(i));
01503   }
01504   if (hasUnknown) {
01505     theMacroAssm->jmp(*(next->first()));
01506   } else {
01507     
01508     theMacroAssm->jmp(*labels.at(i));
01509   }
01510 }
01511 
01512 
01513 void TypeTestNode::gen() {
01514   BasicNode::gen();
01515   const int len = classes()->length();
01516   const Register obj = movePRegToReg(_src, temp1);
01517   const Register klassReg = temp2;
01518   bb_needs_jump = false;  
01519 
01520   if (ReorderBBs) {
01521     
01522 
01523     if (len == 1) {
01524       
01525       assert(hasUnknown(), "should be eliminated if there's no unknown case");
01526       assert(likelySuccessor() == next(1), "code pattern is not optimal");
01527       klassOop klass = classes()->at(0);
01528       testForSingleKlass(obj, klass, klassReg, next(1)->label, next()->label);
01529       return;
01530     }
01531 
01532     if (len == 2) {
01533       
01534       klassOop klass1 = classes()->at(0);
01535       klassOop klass2 = classes()->at(1);
01536       if (testForBoolKlasses(obj, klass1, klass2, klassReg, hasUnknown(), next(1)->label, next(2)->label, next()->label)) {
01537         return;
01538       }
01539     }
01540   }
01541 
01542   
01543   GrowableArray<Label*> labels(len + 1);
01544   for (int i = 0; i <= len; i++) labels.append(&next(i)->label);
01545   generalTypeTest(obj, klassReg, hasUnknown(), classes(), &labels);
01546 }
01547 
01548 
01549 
01550 
01551 
01552 
01553 
01554 
01555 
01556 
01557 
01558 
01559 
01560 
01561 
01562 
01563 
01564 
01565 
01566 
01567 
01568 
01569 
01570 
01571 
01572 
01573 
01574 
01575 
01576 
01577 
01578 
01579 
01580 
01581 
01582 
01583 
01584 
01585 
01586 
01587 
01588 
01589 
01590 
01591 
01592 
01593 
01594 
01595 
01596 
01597 
01598 
01599 
01600 
01601 
01602 
01603 
01604 
01605 
01606 
01607 
01608 
01609 
01610 
01611 
01612 
01613 
01614 
01615 
01616 
01617 
01618 
01619 
01620 
01621 
01622 
01623 
01624 
01625 
01626 
01627 
01628 
01629 
01630 
01631 
01632 
01633 
01634 
01635 
01636 
01637 
01638 
01639 
01640 
01641 
01642 
01643 
01644 
01645 
01646 
01647 
01648 
01649 
01650 
01651 
01652 
01653 
01654 
01655 
01656 
01657 
01658 
01659 
01660 
01661 
01662 
01663 
01664 
01665 
01666 
01667 
01668 
01669 
01670 
01671 
01672 
01673 
01674 
01675 
01676 
01677 
01678 void UncommonNode::gen() {
01679   BasicNode::gen();
01680   theMacroAssm->call(StubRoutines::unused_uncommon_trap_entry(), relocInfo::uncommon_type);
01681 }
01682 
01683 
01684 void BlockCreateNode::copyIntoContexts(Register val, Register t1, Register t2) {
01685   
01686   
01687   
01688   
01689   
01690   
01691   
01692   
01693   
01694   
01695   
01696   
01697   
01698   BlockPReg* blk = block();
01699   GrowableArray<Location*>* copies = blk->contextCopies();
01700   if (copies == NULL) return;
01701   for (int i = copies->length() - 1; i >= 0; i--) {
01702     Location* l = copies->at(i);
01703     InlinedScope* scopeWithContext = theCompiler->scopes->at(l->scopeID());
01704     PReg* r = scopeWithContext->contextTemporaries()->at(l->tempNo())->preg();
01705     if (r->loc == unAllocated) continue;          
01706     if (r->isBlockPReg()) continue;               
01707     if (!r->loc.isContextLocation()) fatal("expected context location");
01708     if (scopeWithContext->isSenderOrSame(_scope)) {
01709       store(val, r, t1, t2);
01710     }
01711   }
01712 }
01713 
01714 
01715 void BlockCreateNode::materialize() {
01716   CompileTimeClosure* closure = block()->closure();
01717   if (closure->context()->loc.isRegisterLocation()) {
01718     
01719     
01720     
01721     theMacroAssm->pushl(Mapping::asRegister(closure->context()->loc));
01722   }
01723   int nofArgs = closure->nofArgs();
01724   switch (nofArgs) {
01725     case 0:   primitiveCall(scope(), primitives::block_allocate0()); break;
01726     case 1:   primitiveCall(scope(), primitives::block_allocate1()); break;
01727     case 2:   primitiveCall(scope(), primitives::block_allocate2()); break;
01728     default:  assert(_pdesc == primitives::block_allocate(), "bad block clone prim");
01729               theMacroAssm->pushl((int)as_smiOop(nofArgs));
01730               primitiveCall(scope(), _pdesc);
01731               theMacroAssm->addl(esp, oopSize); 
01732   }
01733   
01734   Register t = moveLocToReg(resultLoc, answerPRegReg(_dest, temp1));
01735   store(t, _dest, temp2, temp3);
01736   
01737   if (block()->isMemoized()) copyIntoContexts(t, temp2, temp3);
01738   
01739   Register closureReg = Mapping::asRegister(resultLoc); 
01740   Register contextReg;
01741   if (closure->context()->loc.isRegisterLocation()) {
01742     
01743     
01744     contextReg = temp1;
01745     theMacroAssm->popl(contextReg);
01746   } else {
01747     contextReg = movePRegToReg(closure->context(), temp1);
01748   }
01749   if (VerifyCode) {
01750     switch (closure->method()->block_info()) {
01751       case methodOopDesc::expects_nil      : verifyNilOrContextCode(contextReg); break;
01752       case methodOopDesc::expects_self     : 
01753       case methodOopDesc::expects_parameter: verifyOopCode(contextReg); break;
01754       case methodOopDesc::expects_context  : verifyContextCode(contextReg); break;
01755       default: ShouldNotReachHere();
01756     }
01757   }
01758   theMacroAssm->Store(contextReg, closureReg, blockClosureOopDesc::context_byte_offset());
01759   
01760   
01761   theMacroAssm->movl(Address(closureReg, blockClosureOopDesc::method_or_entry_byte_offset()), int(closure->jump_table_entry()));
01762   if (VerifyCode) verifyBlockCode(closureReg);
01763   theMacroAssm->store_check(closureReg, temp1);
01764 }
01765 
01766 
01767 void BlockCreateNode::gen() {
01768   BasicNode::gen();
01769   if (block()->closure()->method()->is_clean_block()) {
01770     
01771     CompileTimeClosure* closure = block()->closure();
01772     blockClosureOop blk = blockClosureOopDesc::create_clean_block(closure->nofArgs(), closure->jump_table_entry());
01773     Mapping::storeO(blk, _dest->loc, temp1, temp3, true);
01774   } else if (block()->isMemoized()) {
01775     
01776     Mapping::storeO(MemoizedBlockNameDesc::uncreatedBlockValue(), _dest->loc, temp1, temp3, true);
01777   } else {
01778     
01779     materialize();
01780   }
01781 }
01782 
01783 
01784 void BlockMaterializeNode::gen() {
01785   BasicNode::gen();
01786   if (block()->isMemoized() && !block()->closure()->method()->is_clean_block()) {
01787     
01788     
01789     Label L;
01790     Register t = movePRegToReg(block(), temp1);
01791     assert(MemoizedBlockNameDesc::uncreatedBlockValue() == oop(0), "change the code generation here");
01792     theMacroAssm->testl(t, t);
01793     theMacroAssm->jcc(Assembler::notZero, L);
01794     materialize();
01795     theMacroAssm->bind(L);
01796   }
01797 }
01798 
01799 void LoopHeaderNode::gen() {
01800   if (!_activated) return;    
01801   
01802   
01803   
01804   
01805   
01806   
01807   
01808   
01809   TrivialNode::gen();
01810   Label ok;
01811   Label failure;
01812   generateTypeTests(ok, failure);
01813   generateIntegerLoopTests(ok, failure);
01814   generateArrayLoopTests(ok, failure);
01815   if (ok.is_unbound()) theMacroAssm->bind(ok);
01816   theMacroAssm->jmp(next()->label);
01817   
01818   bb_needs_jump = false;  
01819   theMacroAssm->bind(failure);
01820   theMacroAssm->call(StubRoutines::unused_uncommon_trap_entry(), relocInfo::uncommon_type);
01821 }
01822 
01823 
01824 void LoopHeaderNode::generateTypeTests(Label& cont, Label& failure) {
01825   
01826   Label* ok;
01827   const Register klassReg = temp2;
01828   const int len = _tests->length() - 1;
01829   int last;                                             
01830   for (last = len; last >= 0 && _tests->at(last)->testedPR->loc == unAllocated; last--) ;
01831   if (last < 0) return;                                 
01832   for (int i = 0; i <= last; i++) {
01833     HoistedTypeTest* t = _tests->at(i);
01834     if (t->testedPR->loc == unAllocated) continue;      
01835     if (t->testedPR->isConstPReg()) { 
01836       guarantee(t->testedPR->loc == unAllocated, "code assumes ConstPRegs are unallocated");
01837       handleConstantTypeTest((ConstPReg*)t->testedPR, t->klasses);
01838     } else {
01839       const Register obj = movePRegToReg(t->testedPR, temp1);
01840       Label okLabel;
01841       ok = (i == last) ? &cont : &okLabel;
01842       if (t->klasses->length() == 1) {
01843         testForSingleKlass(obj, t->klasses->at(0), klassReg, *ok, failure);
01844       } else if (t->klasses->length() == 2 &&
01845                  testForBoolKlasses(obj, t->klasses->at(0), t->klasses->at(1), klassReg, true, 
01846                  *ok, *ok, failure)) {
01847         
01848       } else {
01849         const int len = t->klasses->length();
01850         GrowableArray<Label*> labels(len + 1);
01851         labels.append(&failure);
01852         for (int i = 0; i < len; i++) labels.append(ok);
01853         generalTypeTest(obj, klassReg, true, t->klasses, &labels);
01854       }
01855       if (i != last) theMacroAssm->bind(*ok);
01856     }
01857   }
01858 }
01859 
01860 void LoopHeaderNode::generateIntegerLoopTest(PReg* p, Label& prev, Label& failure) {
01861   const Register klassReg = temp2;
01862   if (p != NULL) {
01863     if (p->isConstPReg()) {
01864       
01865       handleConstantTypeTest((ConstPReg*)p, NULL);
01866     } else if (p->loc == unAllocated) {
01867       
01868       guarantee(p->cpReg() == p, "should use cpReg()");
01869     } else {
01870       
01871       if (prev.is_unbound()) theMacroAssm->bind(prev);
01872       Label ok;
01873       const Register obj = movePRegToReg(p, temp1);
01874       testForSingleKlass(obj, Universe::smiKlassObj(), klassReg, ok, failure);
01875       theMacroAssm->bind(ok);
01876     }
01877   }
01878 }
01879 
01880 void LoopHeaderNode::generateIntegerLoopTests(Label& prev, Label& failure) {
01881   if (!_integerLoop) return;
01882   generateIntegerLoopTest(_lowerBound, prev, failure);
01883   generateIntegerLoopTest(_upperBound, prev, failure);
01884   generateIntegerLoopTest(_loopVar   , prev, failure);
01885 }
01886 
01887 void LoopHeaderNode::handleConstantTypeTest(ConstPReg* r, GrowableArray<klassOop>* klasses) {
01888   
01889   if ((klasses == NULL && r->constant->is_smi()) || (klasses && klasses->contains(r->constant->klass()))) {
01890     
01891   } else {
01892     compiler_warning("loop header type test will always fail!");
01893     
01894     theMacroAssm->call(StubRoutines::unused_uncommon_trap_entry(), relocInfo::uncommon_type);
01895   }
01896 }
01897 
01898 void LoopHeaderNode::generateArrayLoopTests(Label& prev, Label& failure) {
01899   if (!_integerLoop) return;
01900   Register boundReg = temp1;
01901   const Register tempReg  = temp2;
01902   if (_upperLoad != NULL) {
01903     
01904     
01905     PReg* loopArray = _upperLoad->src();
01906     AbstractArrayAtNode* atNode;
01907     for (int i = _arrayAccesses->length() - 1; i >= 0; i--) {
01908       atNode = _arrayAccesses->at(i);
01909       if (atNode->src() == loopArray && !atNode->needsBoundsCheck()) break;
01910     }
01911     if (i >= 0) {
01912       
01913       if (_lowerBound != NULL && _lowerBound->isConstPReg() && ((ConstPReg*)_lowerBound)->constant->is_smi() && ((ConstPReg*)_lowerBound)->constant >= as_smiOop(1)) {
01914         
01915       } else {
01916         
01917        if (prev.is_unbound()) theMacroAssm->bind(prev);
01918        if (_lowerBound->loc == unAllocated) {
01919          guarantee(_lowerBound->cpReg() == _lowerBound, "should use cpReg()");
01920        } else {
01921          const Register t = movePRegToReg(_lowerBound ? _lowerBound : _loopVar, tempReg);
01922          theMacroAssm->cmpl(boundReg, as_smiOop(1));
01923          theMacroAssm->jcc(Assembler::less, failure);
01924        }
01925       }
01926 
01927       
01928       boundReg = movePRegToReg(_upperBound, boundReg);
01929       const Register t = movePRegToReg(atNode->src(), tempReg);
01930       theMacroAssm->movl(t, Address(t, byteOffset(atNode->sizeOffset())));
01931       theMacroAssm->cmpl(boundReg, t);
01932       theMacroAssm->jcc(Assembler::above, failure);
01933     }
01934   }
01935 }
01936 
01937 
01938 static void jcc_error(Node* node, Assembler::Condition cond, Label& label) {
01939 
01940 
01941 
01942 
01943   Node* failure_start = node->next(1);
01944   if (failure_start->isUncommonNode()) {
01945     
01946     theMacroAssm->jcc(cond, failure_start->label);
01947   } else {
01948     
01949     theMacroAssm->jcc(cond, label);
01950   }
01951 }
01952 
01953 
01954 void ArrayAtNode::gen() {
01955   BasicNode::gen();
01956   
01957   Register size  = temp3;
01958   Register index = temp2; load(_arg, index);    
01959   Register array = movePRegToReg(_src, temp1);  
01960   
01961   theMacroAssm->subl(index, int(smiOop_one));
01962   
01963   if (_needBoundsCheck) {
01964     theMacroAssm->movl(size, Address(array, byteOffset(_sizeOffset)));
01965   }
01966   
01967   Label indexNotSmi;
01968   if (!_intArg) {
01969     theMacroAssm->test(index, Mem_Tag);
01970     jcc_error(this, Assembler::notZero, indexNotSmi);
01971   }
01972   
01973   Label indexOutOfBounds;
01974   if (_needBoundsCheck) {
01975     theMacroAssm->cmpl(index, size);
01976     jcc_error(this, Assembler::aboveEqual, indexOutOfBounds);
01977   }
01978   
01979   Register t = answerPRegReg(_dest, temp3);
01980   assert(Tag_Size == 2, "check this code");
01981   switch (_access_type) {
01982     case byte_at:
01983       theMacroAssm->sarl(index, Tag_Size);      
01984       theMacroAssm->xorl(t, t);                 
01985       theMacroAssm->movb(t, Address(array, index, Address::times_1, byteOffset(_dataOffset)));
01986       theMacroAssm->shll(t, Tag_Size);          
01987       break;
01988     case double_byte_at:
01989       theMacroAssm->sarl(index, Tag_Size - 1);  
01990       theMacroAssm->movl(t, Address(array, index, Address::times_1, byteOffset(_dataOffset)));
01991       theMacroAssm->andl(t, 0x0000FFFF);        
01992       theMacroAssm->shll(t, Tag_Size);          
01993       break;
01994     case character_at:
01995       { theMacroAssm->sarl(index, Tag_Size - 1);
01996         theMacroAssm->movl(t, Address(array, index, Address::times_1, byteOffset(_dataOffset)));
01997         theMacroAssm->andl(t, 0x0000FFFF);      
01998         
01999         
02000         objArrayOop chars = Universe::asciiCharacters();
02001         theMacroAssm->cmpl(t, chars->length());
02002         jcc_error(this, Assembler::aboveEqual, indexOutOfBounds);
02003         
02004         theMacroAssm->movl(temp1, chars);
02005         theMacroAssm->movl(t, Address(temp1, t, Address::times_4, byteOffset(chars->klass()->klass_part()->non_indexable_size() + 1)));
02006       }
02007       break;
02008     case object_at:
02009       
02010       theMacroAssm->movl(t, Address(array, index, Address::times_1, byteOffset(_dataOffset)));
02011       break;
02012     default:
02013       ShouldNotReachHere();
02014       break;
02015   }
02016   assert(t != temp1 && t != temp2, "just checking");
02017   store(t, _dest, temp1, temp2);
02018   
02019   if (canFail() && !next(1)->isUncommonNode()) {
02020     Label exit;
02021     theMacroAssm->jmp(exit);
02022     
02023     if (!_intArg) {
02024       theMacroAssm->bind(indexNotSmi);
02025       theMacroAssm->movl(temp1, vmSymbols::first_argument_has_wrong_type());
02026       store(temp1, _error, temp2, temp3);
02027       theMacroAssm->jmp(next(1)->label);
02028     }
02029     if (_needBoundsCheck) {
02030       theMacroAssm->bind(indexOutOfBounds);
02031       theMacroAssm->movl(temp1, vmSymbols::out_of_bounds());
02032       store(temp1, _error, temp2, temp3);
02033       theMacroAssm->jmp(next(1)->label);
02034     }
02035     theMacroAssm->bind(exit);
02036   }
02037 }
02038 
02039 
02040 void ArrayAtPutNode::gen() {
02041   BasicNode::gen();
02042   
02043   Register size  = temp3;
02044   Register index = temp2; load(_arg, index);    
02045   Register array = temp1; load(_src, array);    
02046   
02047   theMacroAssm->subl(index, int(smiOop_one));
02048   
02049   if (_needBoundsCheck) {
02050     theMacroAssm->movl(size, Address(array, byteOffset(_sizeOffset)));
02051   }
02052   
02053   Label indexNotSmi;
02054   if (!_intArg) {
02055     theMacroAssm->test(index, Mem_Tag);
02056     jcc_error(this, Assembler::notZero, indexNotSmi);
02057   }
02058   
02059   Label indexOutOfBounds;
02060   if (_needBoundsCheck) {
02061     theMacroAssm->cmpl(index, size);
02062     jcc_error(this, Assembler::aboveEqual, indexOutOfBounds);
02063   }
02064   
02065   Label elementNotSmi, elementOutOfRange;
02066   Register element = temp3; load(elem, element);
02067   assert(Tag_Size == 2, "check this code");
02068   switch (_access_type) {
02069     case byte_at_put:
02070       if (!_smi_element) {
02071         theMacroAssm->test(element, Mem_Tag);
02072         jcc_error(this, Assembler::notZero, elementNotSmi);
02073       }
02074       theMacroAssm->sarl(element, Tag_Size);    
02075       if (_needs_element_range_check) {
02076         theMacroAssm->cmpl(element, 0x100);
02077         jcc_error(this, Assembler::aboveEqual, elementOutOfRange);
02078       }
02079       theMacroAssm->sarl(index, Tag_Size);      
02080       theMacroAssm->movb(Address(array, index, Address::times_1, byteOffset(_dataOffset)), element);
02081       assert(!_needs_store_check, "just checking");
02082       break;
02083     case double_byte_at_put:
02084       if (!_smi_element) {
02085         theMacroAssm->test(element, Mem_Tag);
02086         jcc_error(this, Assembler::notZero, elementNotSmi);
02087       }
02088       theMacroAssm->sarl(element, Tag_Size);    
02089       if (_needs_element_range_check) {
02090         theMacroAssm->cmpl(element, 0x10000);
02091         jcc_error(this, Assembler::aboveEqual, elementOutOfRange);
02092       }
02093       theMacroAssm->sarl(index, Tag_Size - 1);  
02094       theMacroAssm->leal(array, Address(array, index, Address::times_1, byteOffset(_dataOffset)));
02095       assert(temp2 != array && temp2 != element, "check this code");
02096       theMacroAssm->movl(temp2, element);       
02097       theMacroAssm->shrl(temp2, 8);             
02098       theMacroAssm->movb(Address(array, 0), element);
02099       theMacroAssm->movb(Address(array, 1), temp2);
02100       assert(!_needs_store_check, "just checking");
02101       
02102       
02103       
02104       break;
02105     case object_at_put:
02106       
02107       if (_needs_store_check) {
02108         theMacroAssm->leal(array, Address(array, index, Address::times_1, byteOffset(_dataOffset)));
02109         theMacroAssm->movl(Address(array), element);
02110         theMacroAssm->store_check(array, temp3);
02111       } else {
02112         theMacroAssm->movl(Address(array, index, Address::times_1, byteOffset(_dataOffset)), element);
02113       }
02114       break;
02115     default:
02116       ShouldNotReachHere();
02117       break;
02118   }
02119   
02120   if (canFail() && !next(1)->isUncommonNode()) {
02121     Label exit;
02122     theMacroAssm->jmp(exit);
02123     
02124     if (!_intArg) {
02125       theMacroAssm->bind(indexNotSmi);
02126       theMacroAssm->movl(temp1, vmSymbols::first_argument_has_wrong_type());
02127       store(temp1, _error, temp2, temp3);
02128       theMacroAssm->jmp(next(1)->label);
02129     }
02130     if (_needBoundsCheck) {
02131       theMacroAssm->bind(indexOutOfBounds);
02132       theMacroAssm->movl(temp1, vmSymbols::out_of_bounds());
02133       store(temp1, _error, temp2, temp3);
02134       theMacroAssm->jmp(next(1)->label);
02135     }
02136     if (!_smi_element) {
02137       theMacroAssm->bind(elementNotSmi);
02138       theMacroAssm->movl(temp1, vmSymbols::second_argument_has_wrong_type());
02139       store(temp1, _error, temp2, temp3);
02140       theMacroAssm->jmp(next(1)->label);
02141     }
02142     if (_needs_element_range_check) {
02143       theMacroAssm->bind(elementOutOfRange);
02144       theMacroAssm->movl(temp1, vmSymbols::value_out_of_range());
02145       store(temp1, _error, temp2, temp3);
02146       theMacroAssm->jmp(next(1)->label);
02147     }
02148     theMacroAssm->bind(exit);
02149   }
02150 }
02151 
02152 
02153 void InlinedPrimitiveNode::gen() {
02154   BasicNode::gen();
02155   switch (_op) {
02156     case InlinedPrimitiveNode::obj_klass:
02157       { Register obj   = movePRegToReg(_src, temp1);                    
02158         Register klass = temp2;
02159         Label is_smi;
02160         theMacroAssm->movl(klass, Universe::smiKlassObj());
02161         theMacroAssm->test(obj, Mem_Tag);
02162         theMacroAssm->jcc(Assembler::zero, is_smi);
02163         theMacroAssm->movl(klass, Address(obj, memOopDesc::klass_byte_offset()));
02164         theMacroAssm->bind(is_smi);
02165         store(klass, _dest, temp1, temp3);
02166       }
02167       break;
02168     case InlinedPrimitiveNode::obj_hash:
02169       { Unimplemented();
02170         
02171         
02172       };
02173       break;
02174     case InlinedPrimitiveNode::proxy_byte_at:
02175       { Register proxy  = temp1; load(_src,  proxy);                    
02176         Register index  = temp2; load(_arg1, index);                    
02177         Register result = answerPRegReg(_dest, temp3);
02178         Label indexNotSmi;
02179         
02180         if (!_arg1_is_smi) {
02181           theMacroAssm->test(index, Mem_Tag);
02182           jcc_error(this, Assembler::notZero, indexNotSmi);
02183         }
02184         
02185         theMacroAssm->movl(proxy, Address(proxy, pointer_offset));      
02186         theMacroAssm->sarl(index, Tag_Size);                            
02187         theMacroAssm->xorl(result, result);                             
02188         theMacroAssm->movb(result, Address(proxy, index, Address::times_1, 0));
02189         theMacroAssm->shll(result, Tag_Size);                           
02190         
02191         assert(result != temp1 && result != temp2, "just checking");
02192         store(result, _dest, temp1, temp2);
02193         
02194         if (canFail() && !next(1)->isUncommonNode()) {
02195           Label exit;
02196           theMacroAssm->jmp(exit);
02197           
02198           if (!_arg1_is_smi) {
02199             theMacroAssm->bind(indexNotSmi);
02200             theMacroAssm->movl(temp1, vmSymbols::first_argument_has_wrong_type());
02201             store(temp1, _error, temp2, temp3);
02202             theMacroAssm->jmp(next(1)->label);
02203           }
02204           theMacroAssm->bind(exit);
02205         }
02206       }
02207       break;
02208     case InlinedPrimitiveNode::proxy_byte_at_put:
02209       { bool const_val = _arg2->isConstPReg();
02210         Register proxy = temp1; load(_src,  proxy);                     
02211         Register index = temp2; load(_arg1, index);                     
02212         Register value; 
02213         if (const_val) {
02214           
02215           if (!_arg2_is_smi) fatal("proxy_byte_at_put: should not happen - internal error");
02216           
02217         } else {
02218           value = temp3; load(_arg2, value);                            
02219         }
02220         Label indexNotSmi, valueNotSmi;
02221         
02222         if (!_arg1_is_smi) {
02223           theMacroAssm->test(index, Mem_Tag);
02224           jcc_error(this, Assembler::notZero, indexNotSmi);
02225         }
02226         
02227         if (!_arg2_is_smi) {
02228           assert(!const_val, "constant shouldn't need a smi check");
02229           theMacroAssm->test(value, Mem_Tag);
02230           jcc_error(this, Assembler::notZero, valueNotSmi);
02231         }
02232         
02233         theMacroAssm->movl(proxy, Address(proxy, pointer_offset));      
02234         theMacroAssm->sarl(index, Tag_Size);                            
02235         if (const_val) {
02236           smiOop constant = smiOop(((ConstPReg*)_arg2)->constant);
02237           assert(constant->is_smi(), "should be a smi");
02238           theMacroAssm->movb(Address(proxy, index, Address::times_1, 0), constant->value() & 0xFF);
02239         } else {
02240           theMacroAssm->sarl(value, Tag_Size);                          
02241           theMacroAssm->movb(Address(proxy, index, Address::times_1, 0), value);
02242         }
02243         
02244         if (canFail() && !next(1)->isUncommonNode()) {
02245           Label exit;
02246           theMacroAssm->jmp(exit);
02247           
02248           if (!_arg1_is_smi) {
02249             theMacroAssm->bind(indexNotSmi);
02250             theMacroAssm->movl(temp1, vmSymbols::first_argument_has_wrong_type());
02251             store(temp1, _error, temp2, temp3);
02252             theMacroAssm->jmp(next(1)->label);
02253           }
02254           if (!_arg2_is_smi) {
02255             theMacroAssm->bind(valueNotSmi);
02256             theMacroAssm->movl(temp1, vmSymbols::second_argument_has_wrong_type());
02257             store(temp1, _error, temp2, temp3);
02258             theMacroAssm->jmp(next(1)->label);
02259           }
02260           theMacroAssm->bind(exit);
02261         }
02262       };
02263       break;
02264     default: ShouldNotReachHere();
02265   }
02266 }
02267 
02268 
02269 #endif