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/_codeGenerator.cpp.incl"
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 class Stub: public ResourceObj {
00041 private:
00042 PRegMapping* _mapping;
00043 Node* _dst;
00044 Label _stub_code;
00045
00046 Stub(PRegMapping* mapping, Node* dst) {
00047 assert(dst->hasMapping() && !mapping->isConformant(dst->mapping()), "no stub required");
00048 _mapping = mapping;
00049 _dst = dst;
00050 }
00051
00052 public:
00053 static Stub* new_jcc_stub(PRegMapping* mapping, Node* dst, Assembler::Condition cc) {
00054 Stub* s = new Stub(mapping, dst);
00055
00056 mapping->assembler()->jcc(cc, s->_stub_code);
00057 return s;
00058 }
00059
00060 static Stub* new_NLR_stub(PRegMapping* mapping, Node* dst, int flags) {
00061 Stub* s = new Stub(mapping, dst);
00062
00063 mapping->assembler()->ic_info(s->_stub_code, flags);
00064 return s;
00065 }
00066
00067 void generateMergeStub() {
00068 _mapping->assembler()->bind(_stub_code);
00069 _mapping->makeConformant(_dst->mapping());
00070 _mapping->assembler()->jmp(_dst->label);
00071 }
00072 };
00073
00074
00075 class DebugInfoWriter: public PRegClosure {
00076 private:
00077 GrowableArray<PReg*>* _pregs;
00078 GrowableArray<int>* _locations;
00079 GrowableArray<bool>* _present;
00080
00081 Location location_at(int i) { return Location(_locations->at(i)); }
00082 void location_at_put(int i, Location loc) { _locations->at_put(i, loc._loc); }
00083
00084 public:
00085 DebugInfoWriter(int number_of_pregs) {
00086 _pregs = new GrowableArray<PReg*>(number_of_pregs, number_of_pregs, NULL );
00087 _locations = new GrowableArray<int >(number_of_pregs, number_of_pregs, illegalLocation._loc);
00088 _present = new GrowableArray<bool >(number_of_pregs, number_of_pregs, false );
00089 }
00090
00091
00092 void preg_do(PReg* preg) {
00093 if (preg->logicalAddress() != NULL && !preg->loc.isContextLocation()) {
00094
00095
00096
00097 int i = preg->id();
00098 _pregs ->at_put(i, preg);
00099 _present->at_put(i, true);
00100 }
00101 }
00102
00103
00104 void write_debug_info(PRegMapping* mapping, int pc_offset) {
00105
00106 mapping->iterate(this);
00107
00108 ScopeDescRecorder* rec = theCompiler->scopeDescRecorder();
00109 for (int i = _locations->length(); i-- > 0; ) {
00110 PReg* preg = _pregs->at(i);
00111 bool present = _present->at(i);
00112 Location old_loc = location_at(i);
00113 Location new_loc = present ? mapping->locationFor(preg) : illegalLocation;
00114 if ((!present && old_loc != illegalLocation) ||
00115 ( present && old_loc == illegalLocation) ||
00116 ( present && old_loc != new_loc)) {
00117
00118 NameNode* nameNode;
00119 if (new_loc == illegalLocation) {
00120 nameNode = new IllegalName();
00121 } else {
00122 nameNode = new LocationName(new_loc);
00123 }
00124
00125 if (PrintDebugInfoGeneration) {
00126 std->print_cr("%5d: %-20s @ %s", pc_offset, preg->name(), new_loc.name());
00127 }
00128 rec->changeLogicalAddress(preg->logicalAddress(), nameNode, pc_offset);
00129 }
00130 location_at_put(i, new_loc);
00131 _present->at_put(i, false);
00132 }
00133 }
00134
00135
00136 void print() {
00137 std->print_cr("a DebugInfoWriter");
00138 }
00139 };
00140
00141
00142
00143
00144 CodeGenerator::CodeGenerator(MacroAssembler* masm, PRegMapping* mapping) : _mergeStubs(16) {
00145 assert(masm == mapping->assembler(), "should be the same");
00146 PRegLocker::initialize();
00147 _masm = masm;
00148 _currentMapping = mapping;
00149 _debugInfoWriter = new DebugInfoWriter(bbIterator->pregTable->length());
00150 _maxNofStackTmps = 0;
00151 _previousNode = NULL;
00152 _nilReg = noreg;
00153 _pushCode = NULL;
00154 }
00155
00156
00157 void CodeGenerator::setMapping(PRegMapping* mapping) {
00158 maxNofStackTmps();
00159 _currentMapping = mapping;
00160 }
00161
00162
00163 int CodeGenerator::maxNofStackTmps() {
00164 if (_currentMapping != NULL) {
00165 _maxNofStackTmps = max(_maxNofStackTmps, _currentMapping->maxNofStackTmps());
00166 }
00167 return _maxNofStackTmps;
00168 }
00169
00170
00171 Register CodeGenerator::def(PReg* preg) const {
00172 assert(!preg->isConstPReg(), "cannot assign to ConstPReg");
00173 assert(!preg->loc.isContextLocation(), "cannot assign into context yet");
00174 return _currentMapping->def(preg);
00175 }
00176
00177
00178 bool CodeGenerator::isLiveRangeBoundary(Node* a, Node* b) const {
00179 return a->scope() != b->scope() || a->bci() != b->bci();
00180 }
00181
00182
00183 void CodeGenerator::jmp(Node* from, Node* to, bool to_maybe_nontrivial) {
00184
00185 if (from != NULL && isLiveRangeBoundary(from, to)) _currentMapping->killDeadsAt(to);
00186
00187 if (to_maybe_nontrivial || (to->isMergeNode() && !to->isTrivial())) {
00188
00189 if (!to->hasMapping()) {
00190
00191 _currentMapping->makeInjective();
00192 to->setMapping(_currentMapping);
00193 } else {
00194
00195 _currentMapping->makeConformant(to->mapping());
00196 }
00197 } else {
00198
00199 assert(!to->hasMapping(), "more than one predecessor?");
00200 to->setMapping(_currentMapping);
00201 }
00202 _masm->jmp(to->label);
00203 setMapping(NULL);
00204 }
00205
00206
00207 void CodeGenerator::jcc(Assembler::Condition cc, Node* from, Node* to, bool to_maybe_nontrivial) {
00208
00209 if (to_maybe_nontrivial || (to->isMergeNode() && !to->isTrivial())) {
00210
00211 if (!to->hasMapping()) {
00212
00213 _currentMapping->makeInjective();
00214 PRegMapping* copy = new PRegMapping(_currentMapping);
00215
00216 if (isLiveRangeBoundary(from, to)) copy->killDeadsAt(to);
00217 to->setMapping(copy);
00218 _masm->jcc(cc, to->label);
00219 } else {
00220
00221 PRegMapping* copy = new PRegMapping(_currentMapping);
00222 if (isLiveRangeBoundary(from, to)) copy->killDeadsAt(to);
00223 if (copy->isConformant(to->mapping())) {
00224
00225 _masm->jcc(cc, to->label);
00226 } else {
00227
00228 _mergeStubs.push(Stub::new_jcc_stub(copy, to, cc));
00229 }
00230 }
00231 } else {
00232
00233 assert(!to->hasMapping(), "more than one predecessor?");
00234 PRegMapping* copy = new PRegMapping(_currentMapping);
00235 if (isLiveRangeBoundary(from, to)) copy->killDeadsAt(to);
00236 to->setMapping(copy);
00237 _masm->jcc(cc, to->label);
00238 }
00239 }
00240
00241
00242 void CodeGenerator::bindLabel(Node* node) {
00243 if (_currentMapping == NULL) {
00244
00245 assert(node->hasMapping(), "must have a mapping");
00246 setMapping(node->mapping());
00247 } else {
00248
00249 if (!node->hasMapping()) {
00250
00251 if (node->isMergeNode() && !node->isTrivial()) {
00252
00253
00254 if (_previousNode != NULL && isLiveRangeBoundary(_previousNode, node)) _currentMapping->killDeadsAt(node);
00255 _currentMapping->makeInjective();
00256 node->setMapping(_currentMapping);
00257 }
00258 } else {
00259
00260 if (_previousNode != NULL && isLiveRangeBoundary(_previousNode, node)) _currentMapping->killDeadsAt(node);
00261 _currentMapping->makeConformant(node->mapping());
00262 setMapping(node->mapping());
00263 }
00264 }
00265 assert(_currentMapping != NULL, "must have a mapping");
00266 _masm->bind(node->label);
00267 }
00268
00269
00270 void CodeGenerator::inlineCache(Node* call, MergeNode* nlrTestPoint, int flags) {
00271 assert(_currentMapping != NULL, "mapping must exist");
00272 assert(call->scope() == nlrTestPoint->scope(), "should be in the same scope");
00273
00274 if (nlrTestPoint->isMergeNode() && !nlrTestPoint->isTrivial()) {
00275
00276 if (!nlrTestPoint->hasMapping()) {
00277
00278 PRegMapping* copy = new PRegMapping(_currentMapping);
00279 if (isLiveRangeBoundary(call, nlrTestPoint)) copy->killDeadsAt(nlrTestPoint);
00280 assert(_currentMapping->isInjective(), "must be injective");
00281 copy->acquireNLRRegisters();
00282 nlrTestPoint->setMapping(copy);
00283 _masm->ic_info(nlrTestPoint->label, flags);
00284 } else {
00285
00286 PRegMapping* copy = new PRegMapping(_currentMapping);
00287 if (isLiveRangeBoundary(call, nlrTestPoint)) copy->killDeadsAt(nlrTestPoint);
00288 copy->acquireNLRRegisters();
00289 if (copy->isConformant(nlrTestPoint->mapping())) {
00290
00291 _masm->ic_info(nlrTestPoint->label, flags);
00292 } else {
00293
00294 _mergeStubs.push(Stub::new_NLR_stub(copy, nlrTestPoint, flags));
00295 }
00296 }
00297 } else {
00298
00299 assert(!nlrTestPoint->hasMapping(), "more than one predecessor?");
00300 PRegMapping* copy = new PRegMapping(_currentMapping);
00301 if (isLiveRangeBoundary(call, nlrTestPoint)) copy->killDeadsAt(nlrTestPoint);
00302 copy->acquireNLRRegisters();
00303 nlrTestPoint->setMapping(copy);
00304 _masm->ic_info(nlrTestPoint->label, flags);
00305 }
00306 }
00307
00308
00309 void CodeGenerator::generateMergeStubs() {
00310 char* start_pc = _masm->pc();
00311 while (_mergeStubs.nonEmpty()) _mergeStubs.pop()->generateMergeStub();
00312 if (PrintCodeGeneration && _masm->pc() > start_pc) {
00313 std->print("---\n");
00314 std->print("fixup merge stubs\n");
00315 _masm->code()->decode();
00316 }
00317 }
00318
00319
00320
00321
00322 char* CodeGenerator::nmethodAddress() const {
00323
00324
00325 return (char*)(((nmethod*) (_masm->code()->code_begin())) - 1);
00326 }
00327
00328
00329 void CodeGenerator::incrementInvocationCounter() {
00330
00331 char* addr = nmethodAddress() + nmethod::invocationCountOffset();
00332 _masm->incl(Address(int(addr), relocInfo::internal_word_type));
00333 }
00334
00335
00336
00337
00338 void CodeGenerator::initialize(InlinedScope* scope) {
00339
00340
00341
00342
00343
00344
00345
00346 int i;
00347 for (i = 0; i < scope->nofArguments(); i++) {
00348 _currentMapping->mapToArgument(scope->argument(i)->preg(), i);
00349 }
00350
00351 for (i = 0; i < scope->nofTemporaries(); i++) {
00352 _currentMapping->mapToTemporary(scope->temporary(i)->preg(), i);
00353 }
00354
00355 _currentMapping->mapToRegister(scope->self()->preg(), self_reg);
00356 }
00357
00358
00359 void CodeGenerator::finalize(InlinedScope* scope) {
00360
00361 generateMergeStubs();
00362
00363
00364 int n = maxNofStackTmps();
00365 int frame_size = 2 + n;
00366
00367 if (frame_size < minimum_size_for_deoptimized_frame) {
00368
00369 n += minimum_size_for_deoptimized_frame - frame_size;
00370 }
00371
00372 Assembler masm(_pushCode);
00373 if (_pushCode->code_begin() + n <= _pushCode->code_limit()) {
00374 while (n-- > 0) masm.pushl(_nilReg);
00375 } else {
00376 masm.jmp(_masm->pc(), relocInfo::none);
00377 while (n-- > 0) _masm->pushl(_nilReg);
00378 _masm->jmp(_pushCode->code_limit(), relocInfo::none);
00379 }
00380
00381
00382 if (CompilerDebug) _masm->movl(eax, nofCompilations);
00383
00384 if (PrintCodeGeneration) {
00385 std->print("---\n");
00386 std->print("merge stubs\n");
00387 _masm->code()->decode();
00388 std->print("---\n");
00389 }
00390 }
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497 void CodeGenerator::zapContext(PReg* context) {
00498 _masm->movl(Address(use(context), contextOopDesc::parent_byte_offset()), 0);
00499 }
00500
00501
00502 void CodeGenerator::storeCheck(Register obj) {
00503
00504
00505
00506
00507
00508 Temporary base(_currentMapping);
00509 Temporary indx(_currentMapping);
00510 _masm->movl(base.reg(), Address(int(&byte_map_base), relocInfo::external_word_type));
00511 _masm->movl(indx.reg(), obj);
00512 _masm->shrl(indx.reg(), card_shift);
00513 _masm->movb(Address(base.reg(), indx.reg(), Address::times_1), 0);
00514 }
00515
00516
00517 void CodeGenerator::assign(PReg* dst, PReg* src, bool needsStoreCheck) {
00518 PRegLocker lock(src);
00519 enum { is_const, is_loaded, is_mapped, is_undefined } state = is_undefined;
00520 oop value;
00521 Register reg;
00522 PReg* preg;
00523
00524 { Temporary t1(_currentMapping, NLR_result_reg);
00525 if (t1.reg() != NLR_result_reg) {
00526 reg = t1.reg();
00527 } else {
00528 Temporary t2(_currentMapping);
00529 reg = t2.reg();
00530 }
00531 }
00532 Temporary t(_currentMapping, reg);
00533 assert(reg != NLR_result_reg, "fix this");
00534 assert(t.reg() == reg, "should be the same");
00535
00536
00537 if (src->isConstPReg()) {
00538 value = ((ConstPReg*)src)->constant;
00539 state = is_const;
00540 } else if (src->loc == resultOfNLR) {
00541 _currentMapping->mapToRegister(src, NLR_result_reg);
00542 preg = src;
00543 state = is_mapped;
00544 } else if (src->loc.isContextLocation()) {
00545 PReg* context = theCompiler->contextList->at(src->loc.contextNo())->context();
00546 Address addr = Address(use(context), Mapping::contextOffset(src->loc.tempNo()));
00547 _masm->movl(reg, addr);
00548 state = is_loaded;
00549 } else {
00550 assert(!src->loc.isSpecialLocation(), "what's this?");
00551 preg = src;
00552 state = is_mapped;
00553 }
00554
00555
00556 if (dst->loc == topOfStack) {
00557 switch (state) {
00558 case is_const : _masm->pushl(value); break;
00559 case is_loaded: _masm->pushl(reg); break;
00560 case is_mapped: _masm->pushl(use(preg)); break;
00561 default : ShouldNotReachHere();
00562 }
00563 } else if (dst->loc.isContextLocation()) {
00564 PReg* context = theCompiler->contextList->at(dst->loc.contextNo())->context();
00565 PRegLocker lock(context);
00566 Address addr = Address(use(context), Mapping::contextOffset(dst->loc.tempNo()));
00567 switch (state) {
00568 case is_const : _masm->movl(addr, value); break;
00569 case is_loaded: _masm->movl(addr, reg); break;
00570 case is_mapped: _masm->movl(addr, use(preg)); break;
00571 default : ShouldNotReachHere();
00572 }
00573 if (needsStoreCheck) storeCheck(use(context));
00574 } else {
00575 assert(!dst->loc.isSpecialLocation(), "what's this?");
00576 switch (state) {
00577 case is_const : _masm->movl(def(dst), value); break;
00578 case is_loaded: _masm->movl(def(dst), reg); break;
00579 case is_mapped: _currentMapping->move(dst, preg); break;
00580 default : ShouldNotReachHere();
00581 }
00582 }
00583 }
00584
00585
00586
00587
00588 static int _callDepth = 0;
00589 static int _numberOfCalls = 0;
00590 static int _numberOfReturns = 0;
00591 static int _numberOfNLRs = 0;
00592
00593
00594 void CodeGenerator::indent() {
00595 const int maxIndent = 40;
00596 if (_callDepth <= maxIndent) {
00597 std->print("%*s", _callDepth, "");
00598 } else {
00599 std->print("%*d: ", maxIndent-2, _callDepth);
00600 }
00601 }
00602
00603
00604 char* CodeGenerator::nmethodName() {
00605 deltaVFrame* f = DeltaProcess::active()->last_delta_vframe();
00606 return f->method()->selector()->as_string();
00607 }
00608
00609
00610 void CodeGenerator::verifyObj(oop obj) {
00611 if (!obj->is_smi() && !obj->is_mem()) fatal("should be an ordinary oop");
00612 klassOop klass = obj->klass();
00613 if (klass == NULL || !klass->is_mem()) fatal("should be an ordinary memOop");
00614 if (obj->is_block()) blockClosureOop(obj)->verify();
00615 }
00616
00617
00618 void CodeGenerator::verifyContext(oop obj) {
00619 if (obj->is_mark()) error("context should never be mark");
00620 if (!Universe::is_heap((oop*)obj)) error("context outside of heap");
00621 if (!obj->is_context()) error("should be a context");
00622 oop c = (oop)(contextOop(obj)->parent());
00623 if (c->is_mem()) verifyContext(c);
00624 }
00625
00626
00627 void CodeGenerator::verifyArguments(oop recv, oop* ebp, int nofArgs) {
00628 bool print_args_long = true;
00629 ResourceMark rm;
00630 _numberOfCalls++;
00631 _callDepth++;
00632 if (TraceCalls) {
00633 ResourceMark rm;
00634 indent(); std->print("( %s %s ", recv->print_value_string(), nmethodName());
00635 }
00636 verifyObj(recv);
00637 int i = nofArgs;
00638 oop* arg = ebp + (nofArgs + 2);
00639 while (i-- > 0) {
00640 arg--;
00641 verifyObj(*arg);
00642 if (TraceCalls) {
00643 ResourceMark rm;
00644 if (print_args_long || (*arg)->is_smi()) {
00645 std->print("%s ", (*arg)->print_value_string());
00646 } else {
00647 std->print("0x%x ", *arg);
00648 }
00649 }
00650 }
00651 if (TraceCalls) std->cr();
00652 if (VerifyDebugInfo) {
00653 deltaVFrame* f = DeltaProcess::active()->last_delta_vframe();
00654 while (f != NULL) {
00655 f->verify_debug_info();
00656 f = f->sender_delta_frame();
00657 }
00658 }
00659 }
00660
00661
00662 void CodeGenerator::verifyReturn(oop result) {
00663 _numberOfReturns++;
00664 result->verify();
00665 if (TraceCalls) {
00666 ResourceMark rm;
00667 indent(); std->print(") %s -> %s\n", nmethodName(), result->print_value_string());
00668 }
00669 _callDepth--;
00670 }
00671
00672
00673 void CodeGenerator::verifyNLR(char* fp, char* nlrFrame, int nlrScopeID, oop result) {
00674 _numberOfNLRs++;
00675 LOG_EVENT3("verifyNLR(%#x, %#x, %d, %#x)", fp, nlrFrame, result);
00676 if (nlrFrame <= fp) error("NLR went too far: %#x <= %#x", nlrFrame, fp);
00677
00678 if (nlrScopeID < 0 || nlrScopeID > 99) error("illegal NLR scope ID %#x", nlrScopeID);
00679 if (result->is_mark()) error("NLR result is a markOop");
00680 result->verify();
00681 if (TraceCalls) {
00682 ResourceMark rm;
00683 indent(); std->print(") %s ^ %s\n", nmethodName(), result->print_value_string());
00684 }
00685 _callDepth--;
00686 }
00687
00688
00689 void CodeGenerator::callVerifyObj(Register obj) {
00690
00691
00692 if (!VerifyCode) warning(": verifyObj should not be called");
00693 _masm->pushad();
00694 _masm->call_C((char*)CodeGenerator::verifyObj, obj);
00695 _masm->popad();
00696 }
00697
00698
00699 void CodeGenerator::callVerifyContext(Register context) {
00700
00701
00702 if (!VerifyCode) warning(": verifyContext should not be called");
00703 _masm->pushad();
00704 _masm->call_C((char*)CodeGenerator::verifyContext, context);
00705 _masm->popad();
00706 }
00707
00708
00709 void CodeGenerator::callVerifyArguments(Register recv, int nofArgs) {
00710
00711
00712 if (!VerifyCode && !TraceCalls && !TraceResults) warning(": performance bug: verifyArguments should not be called");
00713 assert(recv != temp1, "use another temporary register");
00714 _masm->pushad();
00715 _masm->movl(temp1, nofArgs);
00716 _masm->call_C((char*)CodeGenerator::verifyArguments, recv, ebp, temp1);
00717 _masm->popad();
00718 }
00719
00720
00721 void CodeGenerator::callVerifyReturn() {
00722
00723
00724 if (!VerifyCode && !TraceCalls && !TraceResults) warning(": verifyReturn should not be called");
00725 _masm->pushad();
00726 _masm->call_C((char*)CodeGenerator::verifyReturn, result_reg);
00727 _masm->popad();
00728 }
00729
00730
00731 void CodeGenerator::callVerifyNLR() {
00732
00733 if (!VerifyCode && !TraceCalls && !TraceResults) warning(": verifyNLR should not be called");
00734 _masm->pushad();
00735 _masm->call_C((char*)CodeGenerator::verifyNLR, ebp, NLR_home_reg, NLR_homeId_reg, NLR_result_reg);
00736 _masm->popad();
00737 }
00738
00739
00740
00741
00742 static bool bb_needs_jump;
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755 void CodeGenerator::beginOfBasicBlock(Node* node) {
00756 if (PrintCodeGeneration && WizardMode) std->print("--- begin of basic block (N%d) ---\n", node->id());
00757 bindLabel(node);
00758 }
00759
00760
00761 void CodeGenerator::endOfBasicBlock(Node* node) {
00762 if (bb_needs_jump && node->next() != NULL) {
00763 Node* from = node;
00764 Node* to = node->next();
00765 if (PrintCodeGeneration) {
00766 std->print("branch from N%d to N%d\n", from->id(), to->id());
00767 if (PrintPRegMapping) _currentMapping->print();
00768 }
00769 jmp(from, to);
00770 _previousNode = NULL;
00771 if (PrintCodeGeneration) _masm->code()->decode();
00772 }
00773
00774 if (PrintCodeGeneration && WizardMode) std->print("--- end of basic block (N%d) ---\n", node->id());
00775 }
00776
00777
00778 void CodeGenerator::updateDebuggingInfo(Node* node) {
00779 ScopeDescRecorder* rec = theCompiler->scopeDescRecorder();
00780 int pc_offset = assembler()->offset();
00781 rec->addPcDesc(pc_offset, node->scope()->scopeInfo(), node->bci());
00782 _debugInfoWriter->write_debug_info(_currentMapping, pc_offset);
00783 }
00784
00785
00786
00787 void CodeGenerator::beginOfNode(Node* node) {
00788 assert(_currentMapping != NULL, "must have a valid mapping");
00789
00790 if (_previousNode != NULL && isLiveRangeBoundary(_previousNode, node)) _currentMapping->killDeadsAt(node);
00791 _currentMapping->cleanupContextReferences();
00792
00793 if (GenerateFullDebugInfo) updateDebuggingInfo(node);
00794
00795 if (PrintCodeGeneration) {
00796 std->print("---\n");
00797 std->print("N%d: ", node->id());
00798 node->print();
00799 std->print(" (bci = %d)\n", node->bci());
00800 if (PrintPRegMapping) _currentMapping->print();
00801 }
00802 bb_needs_jump = true;
00803 };
00804
00805
00806 void CodeGenerator::endOfNode(Node* node) {
00807 if (PrintCodeGeneration) _masm->code()->decode();
00808
00809
00810
00811 _previousNode = _currentMapping == NULL ? NULL : node;
00812 };
00813
00814
00815
00816
00817 void CodeGenerator::aPrologueNode(PrologueNode* node) {
00818
00819 _masm->align(oopSize);
00820 theCompiler->set_entry_point_offset(_masm->offset());
00821
00822
00823 InlinedScope* scope = node->scope();
00824 PReg* recv = scope->self()->preg();
00825 PRegLocker lock(recv);
00826 if (scope->isMethodScope()) {
00827
00828 klassOop klass = scope->selfKlass();
00829 if (klass == smiKlassObj) {
00830
00831 _masm->test(use(recv), Mem_Tag);
00832 _masm->jcc(Assembler::notZero, CompiledIC::normalLookupRoutine());
00833 } else {
00834 _masm->test(use(recv), Mem_Tag);
00835 _masm->jcc(Assembler::zero, CompiledIC::normalLookupRoutine());
00836 _masm->cmpl(Address(use(recv), memOopDesc::klass_byte_offset()), klass);
00837 _masm->jcc(Assembler::notEqual, CompiledIC::normalLookupRoutine());
00838 }
00839 } else {
00840
00841
00842
00843
00844 if (scope->method()->block_info() == methodOopDesc::expects_context) {
00845 const bool use_fast_check = false;
00846 if (use_fast_check) {
00847
00848 Unimplemented();
00849 } else {
00850 _masm->call(StubRoutines::verify_context_chain(), relocInfo::runtime_call_type);
00851 }
00852 }
00853 }
00854
00855
00856 _masm->align(oopSize);
00857 theCompiler->set_verified_entry_point_offset(_masm->offset());
00858
00859
00860 _masm->enter();
00861 { Temporary t(_currentMapping);
00862 _masm->movl(t.reg(), Universe::nilObj());
00863 _nilReg = t.reg();
00864 char* beg = _masm->pc();
00865 int i = 10;
00866 while (i-- > 0) _masm->nop();
00867 char* end = _masm->pc();
00868 _pushCode = new CodeBuffer(beg, end - beg);
00869 }
00870
00871 if (scope->isBlockScope()) {
00872
00873
00874
00875 assert(scope->context() == scope->temporary(0)->preg(), "should be the same");
00876 Register reg = use(recv);
00877 _masm->movl(def(recv), Address(reg, blockClosureOopDesc::context_byte_offset()));
00878 assign(scope->context(), recv);
00879 }
00880
00881 if (VerifyCode || VerifyDebugInfo || TraceCalls) callVerifyArguments(use(recv), scope->method()->number_of_arguments());
00882
00883
00884 Label recompile_stub_call;
00885 if (RecompilationPolicy::needRecompileCounter(theCompiler)) {
00886 char* addr = nmethodAddress() + nmethod::invocationCountOffset();
00887 _masm->movl(temp1, Address(int(addr), relocInfo::internal_word_type));
00888 _masm->incl(temp1);
00889 _masm->cmpl(temp1, theCompiler->get_invocation_counter_limit());
00890 _masm->movl(Address(int(addr), relocInfo::internal_word_type), temp1);
00891 _masm->jcc(Assembler::greaterEqual, recompile_stub_call);
00892
00893
00894
00895
00896
00897 }
00898 Label start;
00899 _masm->jmp(start);
00900
00901
00902
00903 _masm->bind(recompile_stub_call);
00904 updateDebuggingInfo(node);
00905 theCompiler->set_special_handler_call_offset(theMacroAssm->offset());
00906 _masm->call(StubRoutines::recompile_stub_entry(), relocInfo::runtime_call_type);
00907
00908 _masm->bind(start);
00909 }
00910
00911
00912 void CodeGenerator::aLoadIntNode(LoadIntNode* node) {
00913 _masm->movl(def(node->dst()), node->value());
00914 }
00915
00916
00917 void CodeGenerator::aLoadOffsetNode(LoadOffsetNode* node) {
00918 PRegLocker lock(node->base(), node->dst());
00919 _masm->movl(def(node->dst()), Address(use(node->base()), byteOffset(node->offset)));
00920 }
00921
00922
00923 int CodeGenerator::byteOffset(int offset) {
00924
00925 assert(offset >= 0, "wrong offset");
00926 return offset*oopSize - Mem_Tag;
00927 }
00928
00929
00930 void CodeGenerator::uplevelBase(PReg* startContext, int nofLevels, Register base) {
00931
00932 _masm->movl(base, use(startContext));
00933 if (VerifyCode) callVerifyContext(base);
00934 while (nofLevels-- > 0) _masm->movl(base, Address(base, contextOopDesc::parent_byte_offset()));
00935 }
00936
00937
00938 void CodeGenerator::aLoadUplevelNode(LoadUplevelNode* node) {
00939 PRegLocker lock(node->context0());
00940 Temporary base(_currentMapping);
00941 uplevelBase(node->context0(), node->nofLevels(), base.reg());
00942 Register dst = def(node->dst());
00943 _masm->movl(dst, Address(base.reg(), byteOffset(node->offset())));
00944 if (VerifyCode) callVerifyObj(dst);
00945 }
00946
00947
00948 void CodeGenerator::anAssignNode(AssignNode* node) {
00949 assign(node->dst(), node->src());
00950 }
00951
00952
00953 void CodeGenerator::aStoreOffsetNode(StoreOffsetNode* node) {
00954 PRegLocker lock(node->base(), node->src());
00955 Register base = use(node->base());
00956 _masm->movl(Address(base, byteOffset(node->offset())), use(node->src()));
00957 if (node->needsStoreCheck()) storeCheck(base);
00958 }
00959
00960
00961 void CodeGenerator::aStoreUplevelNode(StoreUplevelNode* node) {
00962 PRegLocker lock(node->context0(), node->src());
00963 Temporary base(_currentMapping);
00964 uplevelBase(node->context0(), node->nofLevels(), base.reg());
00965 _masm->movl(Address(base.reg(), byteOffset(node->offset())), use(node->src()));
00966 if (node->needsStoreCheck()) storeCheck(base.reg());
00967 }
00968
00969
00970 void CodeGenerator::moveConstant(ArithOpCode op, PReg*& x, PReg*& y, bool& x_attr, bool& y_attr) {
00971 if (x->isConstPReg() && ArithOpIsCommutative[op]) {
00972 PReg* t1 = x ; x = y ; y = t1;
00973 bool t2 = x_attr; x_attr = y_attr; y_attr = t2;
00974 }
00975 }
00976
00977
00978 void CodeGenerator::arithRROp(ArithOpCode op, Register x, Register y) {
00979 assert(Int_Tag == 0, "check this code");
00980 switch (op) {
00981 case TestArithOp : _masm->testl(x, y); break;
00982 case tAddArithOp :
00983 case AddArithOp : _masm->addl(x, y); break;
00984 case tSubArithOp :
00985 case SubArithOp : _masm->subl(x, y); break;
00986 case tMulArithOp : _masm->sarl(x, Tag_Size);
00987 case MulArithOp : _masm->imull(x, y); break;
00988 case tDivArithOp :
00989 case DivArithOp : Unimplemented(); break;
00990 case tModArithOp :
00991 case ModArithOp : Unimplemented(); break;
00992 case tAndArithOp :
00993 case AndArithOp : _masm->andl(x, y); break;
00994 case tOrArithOp :
00995 case OrArithOp : _masm->orl(x, y); break;
00996 case tXOrArithOp :
00997 case XOrArithOp : _masm->xorl(x, y); break;
00998 case tShiftArithOp: Unimplemented();
00999 case ShiftArithOp: Unimplemented();
01000 case tCmpArithOp :
01001 case CmpArithOp : _masm->cmpl(x, y); break;
01002 default: ShouldNotReachHere();
01003 }
01004 }
01005
01006
01007 void CodeGenerator::arithRCOp(ArithOpCode op, Register x, int y) {
01008 assert(Int_Tag == 0, "check this code");
01009 switch (op) {
01010 case TestArithOp : _masm->testl(x, y); break;
01011 case tAddArithOp :
01012 case AddArithOp :
01013 if (y == 0) {
01014 warning("code generated to add 0 (no load required)");
01015 } else {
01016 _masm->addl(x, y);
01017 }
01018 break;
01019 case tSubArithOp :
01020 case SubArithOp :
01021 if (y == 0) {
01022 warning("code generated to subtract 0 (no load required)");
01023 } else {
01024 _masm->subl(x, y);
01025 }
01026 break;
01027 case tMulArithOp : y = arithmetic_shift_right(y, Tag_Size);
01028 case MulArithOp :
01029
01030
01031
01032
01033
01034 switch (y) {
01035 case -1:
01036 _masm->negl(x);
01037 break;
01038 case 0:
01039 warning("code generated to multiply with 0 (no load required)");
01040 _masm->xorl(x, x);
01041 break;
01042 case 1:
01043 warning("code generated to multiply with 1 (no load required)");
01044
01045 break;
01046 case 2:
01047 _masm->addl(x, x);
01048 break;
01049 default:
01050 _masm->imull(x, x, y);
01051 break;
01052 }
01053 break;
01054 case tDivArithOp :
01055 case DivArithOp : Unimplemented(); break;
01056 case tModArithOp :
01057 case ModArithOp : Unimplemented(); break;
01058 case tAndArithOp :
01059 case AndArithOp : _masm->andl(x, y); break;
01060 case tOrArithOp :
01061 case OrArithOp : _masm->orl(x, y); break;
01062 case tXOrArithOp :
01063 case XOrArithOp : _masm->xorl(x, y); break;
01064 case tShiftArithOp:
01065 if (y < 0) {
01066
01067 int shift_count = ((-y) >> Tag_Size) % 32;
01068 _masm->sarl(x, shift_count);
01069 _masm->andl(x, -1 << Tag_Size);
01070 } else if (y > 0) {
01071
01072 int shift_count = ((+y) >> Tag_Size) % 32;
01073 _masm->shll(x, shift_count);
01074 }
01075 break;
01076 case ShiftArithOp: Unimplemented();
01077 case tCmpArithOp :
01078 case CmpArithOp : _masm->cmpl(x, y); break;
01079 default: ShouldNotReachHere();
01080 }
01081 }
01082
01083
01084 void CodeGenerator::arithROOp(ArithOpCode op, Register x, oop y) {
01085 assert(!y->is_smi(), "check this code");
01086 switch (op) {
01087 case CmpArithOp : _masm->cmpl(x, y); break;
01088 default : ShouldNotReachHere();
01089 }
01090 }
01091
01092
01093 void CodeGenerator::arithRXOp(ArithOpCode op, Register x, oop y) {
01094 if (y->is_smi()) {
01095 arithRCOp(op, x, int(y));
01096 } else {
01097 arithROOp(op, x, y);
01098 }
01099 }
01100
01101
01102 bool CodeGenerator::producesResult(ArithOpCode op) {
01103 return (op != TestArithOp) && (op != CmpArithOp) && (op != tCmpArithOp);
01104 }
01105
01106
01107 Register CodeGenerator::targetRegister(ArithOpCode op, PReg* z, PReg* x) {
01108 assert(PRegLocker::locks(z) && PRegLocker::locks(x), "should be locked");
01109 Register reg = noreg;
01110 if (producesResult(op)) {
01111
01112 Register x_reg = use(x);
01113
01114 if (_currentMapping->onStack(x)) {
01115
01116 _currentMapping->killRegister(x);
01117 reg = _currentMapping->def(z, x_reg);
01118 } else {
01119
01120 reg = def(z);
01121 _masm->movl(reg, x_reg);
01122 }
01123 } else {
01124
01125 reg = use(x);
01126 }
01127 return reg;
01128 }
01129
01130
01131 void CodeGenerator::anArithRRNode(ArithRRNode* node) {
01132 ArithOpCode op = node->op();
01133 PReg* z = node->dst();
01134 PReg* x = node->src();
01135 PReg* y = node->operand();
01136 bool dummy;
01137 moveConstant(op, x, y, dummy, dummy);
01138 PRegLocker lock(z, x, y);
01139 Register reg = targetRegister(op, z, x);
01140 if (y->isConstPReg()) {
01141 arithRXOp(op, reg, ((ConstPReg*)y)->constant);
01142 } else {
01143 arithRROp(op, reg, use(y));
01144 }
01145 }
01146
01147
01148 void CodeGenerator::anArithRCNode(ArithRCNode* node) {
01149 ArithOpCode op = node->op();
01150 PReg* z = node->dst();
01151 PReg* x = node->src();
01152 int y = node->operand();
01153 PRegLocker lock(z, x);
01154 Register reg = targetRegister(op, z, x);
01155 arithRCOp(op, reg, y);
01156 }
01157
01158
01159 void CodeGenerator::aTArithRRNode(TArithRRNode* node) {
01160 ArithOpCode op = node->op();
01161 PReg* z = node->dst();
01162 PReg* x = node->src();
01163 PReg* y = node->operand();
01164 bool x_is_int = node->arg1IsInt();
01165 bool y_is_int = node->arg2IsInt();
01166 moveConstant(op, x, y, x_is_int, y_is_int);
01167 PRegLocker lock(z, x, y);
01168 Register tags = noreg;
01169 if (x_is_int) {
01170 if (y_is_int) {
01171
01172 } else {
01173
01174 tags = use(y);
01175 }
01176 } else {
01177 if (y_is_int) {
01178
01179 tags = use(x);
01180 } else {
01181
01182 Temporary t(_currentMapping);
01183 tags = t.reg();
01184 _masm->movl(tags, use(x));
01185 _masm->orl (tags, use(y));
01186 }
01187 }
01188 if (tags != noreg) {
01189
01190 _masm->test(tags, Mem_Tag);
01191 jcc(Assembler::notZero, node, node->next(1));
01192 }
01193 Register reg = targetRegister(op, z, x);
01194 if (y->isConstPReg()) {
01195 arithRXOp(op, reg, ((ConstPReg*)y)->constant);
01196 } else {
01197 arithRROp(op, reg, use(y));
01198 }
01199 }
01200
01201
01202 void CodeGenerator::aFloatArithRRNode(FloatArithRRNode* node) {
01203 Unimplemented();
01204 }
01205
01206
01207 void CodeGenerator::aFloatUnaryArithNode(FloatUnaryArithNode* node) {
01208 Unimplemented();
01209 }
01210
01211
01212 void CodeGenerator::aContextCreateNode(ContextCreateNode* node) {
01213
01214
01215
01216 assert(node->src() != node->dst(), "should not be the same");
01217 assert(node->dst() == node->scope()->context(), "should assign to scope context");
01218 _currentMapping->kill(node->dst());
01219 switch (node->sizeOfContext()) {
01220 case 0 :
01221 case 1 :
01222 case 2 :
01223 default:
01224 _masm->pushl(int(as_smiOop(node->nofTemps())));
01225 aPrimNode(node);
01226 _masm->addl(esp, oopSize);
01227 break;
01228 }
01229 PRegLocker lock(node->dst());
01230 Register context_reg = use(node->dst());
01231 if (node->src() == NULL) {
01232 assert(node->scope()->isMethodScope() || node->scope()->method()->block_info() == methodOopDesc::expects_nil, "inconsistency");
01233 _masm->movl(Address(context_reg, contextOopDesc::parent_byte_offset()), NULL);
01234
01235
01236
01237
01238 } else if (_currentMapping->isDefined(node->src())) {
01239
01240 _masm->movl(Address(context_reg, contextOopDesc::parent_byte_offset()), use(node->src()));
01241 } else {
01242
01243 assert(node->src()->loc == frameLoc, "parent should point to current stack frame");
01244 _masm->movl(Address(context_reg, contextOopDesc::parent_byte_offset()), frame_reg);
01245 }
01246 storeCheck(context_reg);
01247 }
01248
01249
01250 void CodeGenerator::aContextInitNode(ContextInitNode* node) {
01251
01252 for (int i = node->nofTemps(); i-- > 0; ) {
01253 PReg* src = node->initialValue(i)->preg();
01254 PReg* dst;
01255 if (src->isBlockPReg()) {
01256
01257 if (node->wasEliminated()) {
01258 continue;
01259 } else {
01260 dst = node->contextTemp(i)->preg();
01261 }
01262 } else {
01263 dst = node->contextTemp(i)->preg();
01264 }
01265 assign(dst, src, false);
01266 }
01267
01268
01269 assert(node->firstPrev()->isContextCreateNode(), "should be immediatly after a ContextCreateNode");
01270 }
01271
01272
01273 void CodeGenerator::aContextZapNode(ContextZapNode* node) {
01274 if (!node->isActive()) return;
01275 assert(node->scope()->needsContextZapping() && node->src() == node->scope()->context(), "no zapping needed or wrong context");
01276
01277
01278
01279 Temporary t1(_currentMapping, NLR_result_reg);
01280 Temporary t2(_currentMapping, NLR_home_reg);
01281 Temporary t3(_currentMapping, NLR_homeId_reg);
01282
01283 _masm->movl(Address(use(node->src()), contextOopDesc::parent_byte_offset()), 0);
01284
01285
01286 }
01287
01288
01289 void CodeGenerator::copyIntoContexts(BlockCreateNode* node) {
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302 BlockPReg* blk = node->block();
01303 GrowableArray<Location*>* copies = blk->contextCopies();
01304 if (copies != NULL) {
01305 for (int i = copies->length(); i-- > 0; ) {
01306 Location* l = copies->at(i);
01307 InlinedScope* scopeWithContext = theCompiler->scopes->at(l->scopeID());
01308 PReg* r = scopeWithContext->contextTemporaries()->at(l->tempNo())->preg();
01309 if (r->loc == unAllocated) continue;
01310 if (r->isBlockPReg()) continue;
01311 if (!r->loc.isContextLocation()) fatal("expected context location");
01312 if (scopeWithContext->isSenderOrSame(node->scope())) {
01313 assign(r, node->block());
01314 }
01315 }
01316 }
01317 }
01318
01319
01320 void CodeGenerator::materializeBlock(BlockCreateNode* node) {
01321 CompileTimeClosure* closure = node->block()->closure();
01322
01323 _currentMapping->kill(node->dst());
01324 int nofArgs = closure->nofArgs();
01325 switch (nofArgs) {
01326 case 0 :
01327 case 1 :
01328 case 2 :
01329 default:
01330 _masm->pushl(int(as_smiOop(nofArgs)));
01331 aPrimNode(node);
01332 _masm->addl(esp, oopSize);
01333 break;
01334 }
01335
01336 if (node->block()->isMemoized()) copyIntoContexts(node);
01337
01338 PRegLocker lock(node->block());
01339 Register closure_reg = use(node->block());
01340
01341
01342 _masm->movl(Address(closure_reg, blockClosureOopDesc::context_byte_offset() ), use(closure->context()));
01343 _masm->movl(Address(closure_reg, blockClosureOopDesc::method_or_entry_byte_offset()), (int)closure->jump_table_entry());
01344 storeCheck(closure_reg);
01345 }
01346
01347
01348 void CodeGenerator::aBlockCreateNode(BlockCreateNode* node) {
01349 if (node->block()->closure()->method()->is_clean_block()) {
01350
01351 CompileTimeClosure* closure = node->block()->closure();
01352 blockClosureOop blk = blockClosureOopDesc::create_clean_block(closure->nofArgs(), closure->jump_table_entry());
01353 _masm->movl(def(node->dst()), blk);
01354 } else if (node->block()->isMemoized()) {
01355
01356 _masm->movl(def(node->dst()), MemoizedBlockNameDesc::uncreatedBlockValue());
01357 } else {
01358
01359 materializeBlock(node);
01360 }
01361 }
01362
01363
01364 void CodeGenerator::aBlockMaterializeNode(BlockMaterializeNode* node) {
01365 assert(node->next() == node->likelySuccessor(), "code pattern is not optimal");
01366 if (node->block()->closure()->method()->is_clean_block()) {
01367
01368 } else if (node->block()->isMemoized()) {
01369
01370
01371 Register closure_reg = use(node->block());
01372 assert(MemoizedBlockNameDesc::uncreatedBlockValue() == oop(0), "change the code generation here");
01373 _masm->testl(closure_reg, closure_reg);
01374 jcc(Assembler::notZero, node, node->next(), true);
01375 materializeBlock(node);
01376 jmp(node, node->next(), true);
01377 bb_needs_jump = false;
01378 }
01379 }
01380
01381
01382 void CodeGenerator::aSendNode(SendNode* node) {
01383
01384
01385
01386
01387
01388
01389
01390 if (node->isCounting()) incrementInvocationCounter();
01391 char* entry = node->isSuperSend() ? CompiledIC::superLookupRoutine() : CompiledIC::normalLookupRoutine();
01392 PReg* recv = node->recv();
01393 _currentMapping->killDeadsAt(node->next(), recv);
01394 _currentMapping->makeInjective();
01395 _currentMapping->saveRegisters();
01396 _currentMapping->killRegisters(recv);
01397 _currentMapping->use(recv, receiver_reg);
01398 updateDebuggingInfo(node);
01399 _masm->call(entry, relocInfo::ic_type);
01400 _currentMapping->killRegisters();
01401
01402 int flags = 0;
01403 if (node->isSuperSend()) setNth(flags, super_send_bit_no);
01404 if (node->isUninlinable()) setNth(flags, uninlinable_bit_no);
01405 if (node->staticReceiver()) setNth(flags, receiver_static_bit_no);
01406
01407 inlineCache(node, node->scope()->nlrTestPoint(), flags);
01408 _currentMapping->mapToRegister(node->dst(), result_reg);
01409 }
01410
01411
01412 void CodeGenerator::aPrimNode(PrimNode* node) {
01413 MergeNode* nlr = node->pdesc()->can_perform_NLR() ? node->scope()->nlrTestPoint() : NULL;
01414 _currentMapping->killDeadsAt(node->next());
01415 _currentMapping->makeInjective();
01416 _currentMapping->saveRegisters();
01417 _currentMapping->killRegisters();
01418 updateDebuggingInfo(node);
01419
01420 _masm->set_last_Delta_frame_before_call();
01421 _masm->call((char*)(node->pdesc()->fn()), relocInfo::prim_type);
01422 _currentMapping->killRegisters();
01423 if (nlr != NULL) inlineCache(node, nlr);
01424 _masm->reset_last_Delta_frame();
01425 _currentMapping->mapToRegister(node->dst(), result_reg);
01426 }
01427
01428
01429 void CodeGenerator::aDLLNode(DLLNode* node) {
01430
01431
01432 char* entry = (node->function() == NULL)
01433 ? StubRoutines::lookup_DLL_entry(node->async())
01434 : StubRoutines::call_DLL_entry(node->async());
01435
01436
01437
01438
01439
01440 _currentMapping->saveRegisters();
01441 _currentMapping->killRegisters();
01442 updateDebuggingInfo(node);
01443 _masm->movl(ebx, node->nofArguments());
01444 _masm->movl(ecx, esp);
01445
01446
01447
01448 _masm->movl(edx, int(node->function()));
01449 _masm->inline_oop(node->dll_name());
01450 _masm->inline_oop(node->function_name());
01451 _masm->call(entry, relocInfo::runtime_call_type);
01452 _currentMapping->killRegisters();
01453
01454
01455 inlineCache(node, node->scope()->nlrTestPoint());
01456 _currentMapping->mapToRegister(node->dst(), result_reg);
01457 _masm->addl(esp, node->nofArguments()*oopSize);
01458 }
01459
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486 void CodeGenerator::testForSingleKlass(Register obj, klassOop klass, Register klassReg, Label& success, Label& failure) {
01487 if (klass == Universe::smiKlassObj()) {
01488
01489 _masm->test(obj, Mem_Tag);
01490 } else if (klass == Universe::trueObj()->klass()) {
01491
01492 _masm->cmpl(obj, Universe::trueObj());
01493 } else if (klass == Universe::falseObj()->klass()) {
01494
01495 _masm->cmpl(obj, Universe::falseObj());
01496 } else if (klass == Universe::nilObj()->klass()) {
01497
01498 _masm->cmpl(obj, Universe::nilObj());
01499 } else {
01500
01501 _masm->test(obj, Mem_Tag);
01502 _masm->jcc(Assembler::zero, failure);
01503 _masm->movl(klassReg, Address(obj, memOopDesc::klass_byte_offset()));
01504 _masm->cmpl(klassReg, klass);
01505 }
01506 _masm->jcc(Assembler::notEqual, failure);
01507 _masm->jmp(success);
01508 }
01509
01510
01511 void CodeGenerator::generateTypeTests(LoopHeaderNode* node, Label& failure) {
01512 Unimplemented();
01513
01514 int last = 0;
01515 for (int i = 0; i <= last; i++) {
01516 HoistedTypeTest* t = node->tests()->at(i);
01517 if (t->testedPR->loc == unAllocated) continue;
01518 if (t->testedPR->isConstPReg()) {
01519 guarantee(t->testedPR->loc == unAllocated, "code assumes ConstPRegs are unallocated");
01520
01521 } else {
01522
01523
01524 }
01525 }
01526 }
01527
01528
01529
01530
01531
01532
01533
01534
01535
01536
01537
01538
01539
01540
01541
01542
01543
01544
01545
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 void CodeGenerator::generateIntegerLoopTest(PReg* preg, LoopHeaderNode* node, Label& failure) {
01583 if (preg != NULL) {
01584 if (preg->isConstPReg()) {
01585
01586
01587 } else if (preg->loc == unAllocated) {
01588
01589 guarantee(preg->cpReg() == preg, "should use cpReg()");
01590 } else {
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 void CodeGenerator::generateIntegerLoopTests(LoopHeaderNode* node, Label& failure) {
01628 assert(node->isIntegerLoop(), "must be integer loop");
01629 generateIntegerLoopTest(node->lowerBound(), node, failure);
01630 generateIntegerLoopTest(node->upperBound(), node, failure);
01631 generateIntegerLoopTest(node->loopVar (), node, failure);
01632 }
01633
01634
01635
01636
01637
01638
01639
01640
01641
01642
01643
01644
01645 void CodeGenerator::generateArrayLoopTests(LoopHeaderNode* node, Label& failure) {
01646 assert(node->isIntegerLoop(), "must be integer loop");
01647 if (node->upperLoad() != NULL) {
01648
01649
01650 PReg* loopArray = node->upperLoad()->src();
01651 AbstractArrayAtNode* atNode;
01652 int i = node->arrayAccesses()->length();
01653 while (i-- > 0) {
01654 atNode = node->arrayAccesses()->at(i);
01655 if (atNode->src() == loopArray && !atNode->needsBoundsCheck()) break;
01656 }
01657 if (i >= 0) {
01658
01659 PReg* lo = node->lowerBound();
01660 PReg* hi = node->upperBound();
01661 if (lo != NULL && lo->isConstPReg() && ((ConstPReg*)lo)->constant->is_smi() && ((ConstPReg*)lo)->constant >= as_smiOop(1)) {
01662
01663 } else {
01664
01665
01666 if (lo->loc == unAllocated) {
01667
01668 } else {
01669
01670 }
01671 }
01672
01673
01674 }
01675 }
01676 }
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686
01687
01688
01689
01690
01691
01692
01693
01694
01695
01696
01697
01698
01699
01700
01701
01702
01703
01704
01705
01706
01707
01708
01709
01710
01711
01712
01713
01714
01715
01716
01717
01718
01719
01720
01721 void CodeGenerator::aLoopHeaderNode(LoopHeaderNode* node) {
01722 if (node->isActivated()) {
01723 warning("loop header node not yet implemented");
01724 return;
01725
01726
01727
01728
01729
01730
01731
01732
01733
01734 Label failure;
01735 generateTypeTests(node, failure);
01736 if (node->isIntegerLoop()) {
01737 generateIntegerLoopTests(node, failure);
01738 generateArrayLoopTests(node, failure);
01739 }
01740 _masm->bind(failure);
01741 updateDebuggingInfo(node);
01742 _masm->call(StubRoutines::unused_uncommon_trap_entry(), relocInfo::uncommon_type);
01743 bb_needs_jump = false;
01744 setMapping(NULL);
01745 }
01746 }
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757
01758
01759
01760
01761
01762
01763
01764
01765
01766
01767
01768
01769
01770
01771
01772
01773
01774
01775
01776 void CodeGenerator::aReturnNode(ReturnNode* node) {
01777 InlinedScope* scope = node->scope();
01778 if (scope->needsContextZapping()) zapContext(scope->context());
01779
01780 PReg* result = scope->resultPR;
01781 _currentMapping->killRegisters(result);
01782 _currentMapping->use(result, result_reg);
01783
01784 if (VerifyCode || TraceCalls || TraceResults) callVerifyReturn();
01785 int no_of_args_to_pop = scope->nofArguments();
01786 if (scope->method()->is_blockMethod()) {
01787
01788
01789
01790 no_of_args_to_pop++;
01791 }
01792 _masm->leave();
01793 _masm->ret(no_of_args_to_pop * oopSize);
01794
01795 setMapping(NULL);
01796 }
01797
01798
01799 void CodeGenerator::aNLRSetupNode(NLRSetupNode* node) {
01800 InlinedScope* scope = node->scope();
01801
01802
01803
01804
01805
01806 Label NLR_error;
01807 Temporary home(_currentMapping, NLR_home_reg);
01808 uplevelBase(scope->context(), scope->homeContext() + 1, home.reg());
01809 _masm->testl(home.reg(), home.reg());
01810 _masm->jcc(Assembler::zero, NLR_error);
01811
01812 PReg* resultPReg = scope->resultPR;
01813 _currentMapping->killRegisters(resultPReg);
01814 Register result;
01815 { Temporary t(_currentMapping, NLR_result_reg); result = t.reg(); }
01816 _currentMapping->use(resultPReg, result);
01817
01818
01819
01820 if (result != NLR_result_reg || home.reg() != NLR_home_reg) {
01821 _masm->pushl(result);
01822 _masm->pushl(home.reg());
01823 _masm->popl(NLR_home_reg);
01824 _masm->popl(NLR_result_reg);
01825 }
01826
01827 _masm->movl(NLR_homeId_reg, scope->home()->scopeID());
01828
01829 if (VerifyCode || TraceCalls || TraceResults) callVerifyNLR();
01830 _masm->jmp(StubRoutines::continue_NLR_entry(), relocInfo::runtime_call_type);
01831
01832
01833 _masm->bind(NLR_error);
01834 _masm->call_C((char*)suspend_on_NLR_error, relocInfo::runtime_call_type);
01835
01836 setMapping(NULL);
01837 }
01838
01839
01840 void CodeGenerator::anInlinedReturnNode(InlinedReturnNode* node) {
01841
01842 ShouldNotReachHere();
01843 }
01844
01845
01846 void CodeGenerator::aNLRContinuationNode(NLRContinuationNode* node) {
01847 guarantee(_currentMapping->NLRinProgress(), "NLR must be in progress");
01848 InlinedScope* scope = node->scope();
01849 if (scope->needsContextZapping()) zapContext(scope->context());
01850
01851 if (VerifyCode || TraceCalls || TraceResults) callVerifyNLR();
01852 _masm->jmp(StubRoutines::continue_NLR_entry(), relocInfo::runtime_call_type);
01853
01854 setMapping(NULL);
01855 }
01856
01857
01858 Assembler::Condition CodeGenerator::mapToCC(BranchOpCode op) {
01859 switch (op) {
01860 case EQBranchOp : return Assembler::equal;
01861 case NEBranchOp : return Assembler::notEqual;
01862 case LTBranchOp : return Assembler::less;
01863 case LEBranchOp : return Assembler::lessEqual;
01864 case GTBranchOp : return Assembler::greater;
01865 case GEBranchOp : return Assembler::greaterEqual;
01866 case LTUBranchOp: return Assembler::below;
01867 case LEUBranchOp: return Assembler::belowEqual;
01868 case GTUBranchOp: return Assembler::above;
01869 case GEUBranchOp: return Assembler::aboveEqual;
01870 case VSBranchOp : return Assembler::overflow;
01871 case VCBranchOp : return Assembler::noOverflow;
01872 }
01873 ShouldNotReachHere();
01874 return Assembler::zero;
01875 }
01876
01877
01878 void CodeGenerator::aBranchNode(BranchNode* node) {
01879 jcc(mapToCC(node->op()), node, node->next(1));
01880 }
01881
01882
01883 void CodeGenerator::aTypeTestNode(TypeTestNode* node) {
01884
01885
01886
01887
01888
01889
01890
01891 const int len = node->classes()->length();
01892
01893 if (ReorderBBs) {
01894 PRegLocker lock(node->src());
01895 Register obj = use(node->src());
01896
01897 if (len == 1) {
01898
01899 assert(node->hasUnknown(), "should be eliminated if there's no unknown case");
01900 assert(node->likelySuccessor() == node->next(1), "code pattern is not optimal");
01901 klassOop klass = node->classes()->at(0);
01902 if (klass == Universe::smiKlassObj()) {
01903
01904 _masm->test(obj, Mem_Tag);
01905 } else if (klass == Universe::trueObj()->klass()) {
01906
01907 _masm->cmpl(obj, Universe::trueObj());
01908 } else if (klass == Universe::falseObj()->klass()) {
01909
01910 _masm->cmpl(obj, Universe::falseObj());
01911 } else if (klass == Universe::nilObj()->klass()) {
01912
01913 _masm->cmpl(obj, Universe::nilObj());
01914 } else {
01915
01916 Temporary objKlass(_currentMapping);
01917 _masm->test(obj, Mem_Tag);
01918 _masm->jcc(Assembler::zero, node->next()->label);
01919 _masm->movl(objKlass.reg(), Address(obj, memOopDesc::klass_byte_offset()));
01920 _masm->cmpl(objKlass.reg(), klass);
01921 }
01922 jcc(Assembler::notEqual, node, node->next());
01923 jmp(node, node->next(1));
01924 bb_needs_jump = false;
01925 return;
01926 }
01927
01928 if (len == 2) {
01929
01930 klassOop klass1 = node->classes()->at(0);
01931 klassOop klass2 = node->classes()->at(1);
01932 oop bool1 = Universe::trueObj();
01933 oop bool2 = Universe::falseObj();
01934 if (klass1 == bool2->klass() && klass2 == bool1->klass()) {
01935 oop t = bool1; bool1 = bool2; bool2 = t;
01936 }
01937 if (klass1 == bool1->klass() && klass2 == bool2->klass()) {
01938 const bool ignoreNoUnknownForNow = true;
01939
01940
01941
01942
01943
01944
01945
01946 if (ignoreNoUnknownForNow || node->hasUnknown()) {
01947 assert(ignoreNoUnknownForNow || node->likelySuccessor() == node->next(2), "code pattern is not optimal");
01948 _masm->cmpl(obj, bool1);
01949 jcc(Assembler::equal, node, node->next(1));
01950 _masm->cmpl(obj, bool2);
01951 jcc(Assembler::notEqual, node, node->next());
01952 jmp(node, node->next(2));
01953 } else {
01954 assert(node->likelySuccessor() == node->next(1), "code pattern is not optimal");
01955 _masm->cmpl(obj, bool2);
01956 jcc(Assembler::equal, node, node->next(2));
01957 jmp(node, node->next(1));
01958 }
01959 bb_needs_jump = false;
01960 return;
01961 }
01962 }
01963 }
01964
01965
01966 Label unknownCase;
01967 Temporary objKlass(_currentMapping);
01968 bool klassHasBeenLoaded = false;
01969 bool smiHasBeenChecked = false;
01970 PRegLocker lock(node->src());
01971 Register obj = use(node->src());
01972 for (int i = 0; i < len; i++) {
01973 klassOop klass = node->classes()->at(i);
01974 if (klass == trueObj->klass()) {
01975
01976 _masm->cmpl(obj, trueObj);
01977 jcc(Assembler::equal, node, node->next(i+1));
01978 } else if (klass == falseObj->klass()) {
01979
01980 _masm->cmpl(obj, falseObj);
01981 jcc(Assembler::equal, node, node->next(i+1));
01982 } else if (klass == nilObj->klass()) {
01983
01984 _masm->cmpl(obj, nilObj);
01985 jcc(Assembler::equal, node, node->next(i+1));
01986 } else if (klass == smiKlassObj) {
01987
01988 if (!smiHasBeenChecked) {
01989 _masm->test(obj, Mem_Tag);
01990 jcc(Assembler::zero, node, node->next(i+1));
01991 smiHasBeenChecked = true;
01992 }
01993 } else {
01994
01995 if (!klassHasBeenLoaded) {
01996 if (!smiHasBeenChecked) {
01997 Node* smiCase = node->smiCase();
01998 if (smiCase != NULL || node->hasUnknown()) {
01999
02000 _masm->test(obj, Mem_Tag);
02001 if (smiCase != NULL) {
02002
02003 jcc(Assembler::zero, node, smiCase);
02004 } else {
02005
02006 _masm->jcc(Assembler::zero, unknownCase);
02007 }
02008 }
02009 smiHasBeenChecked = true;
02010 }
02011 _masm->movl(objKlass.reg(), Address(obj, memOopDesc::klass_byte_offset()));
02012 klassHasBeenLoaded = true;
02013 }
02014 _masm->cmpl(objKlass.reg(), klass);
02015 jcc(Assembler::equal, node, node->next(i+1));
02016 }
02017 }
02018
02019 _masm->bind(unknownCase);
02020
02021
02022
02023
02024
02025
02026
02027
02028
02029 }
02030
02031
02032
02033
02034
02035
02036
02037 void CodeGenerator::aNLRTestNode(NLRTestNode* node) {
02038 assert(_currentMapping->NLRinProgress(), "NLR must be in progress");
02039 InlinedScope* scope = node->scope();
02040
02041 Label L;
02042 _masm->cmpl(NLR_home_reg, frame_reg);
02043 _masm->jcc(Assembler::notEqual, L);
02044
02045 int id = scope->scopeID();
02046 if (id == 0) {
02047
02048 _masm->testl(NLR_homeId_reg, NLR_homeId_reg);
02049 } else {
02050 _masm->cmpl(NLR_homeId_reg, id);
02051 }
02052 _currentMapping->releaseNLRRegisters();
02053 jcc(Assembler::equal, node, node->next(1));
02054 _currentMapping->acquireNLRRegisters();
02055
02056 _masm->bind(L);
02057 }
02058
02059
02060 void CodeGenerator::aMergeNode(MergeNode* node) {
02061 assert(node->isTrivial() || _currentMapping->isInjective(), "must be injective if more than one predecessor");
02062 }
02063
02064
02065 void CodeGenerator::jcc_error(Assembler::Condition cc, AbstractBranchNode* node, Label& label) {
02066 assert(node->canFail(), "should not be called if node cannot fail");
02067 Node* failure_start = node->next(1);
02068 if (failure_start->isUncommonNode()) {
02069 jcc(cc, node, failure_start, true);
02070 } else {
02071 _masm->jcc(cc, label);
02072 }
02073 }
02074
02075
02076 void CodeGenerator::anArrayAtNode(ArrayAtNode* node) {
02077 PReg* array = node->array();
02078 PReg* index = node->index();
02079 PReg* result = node->dst();
02080 PReg* error = node->error();
02081 PRegLocker lock(array, index);
02082 Register array_reg = use(array);
02083
02084 Temporary offset(_currentMapping, index);
02085
02086 theMacroAssm->subl(offset.reg(), int(smiOop_one));
02087
02088 Label indexNotSmi;
02089 if (!node->index_is_smi()) {
02090 _masm->test(offset.reg(), Mem_Tag);
02091 jcc_error(Assembler::notZero, node, indexNotSmi);
02092 }
02093
02094 Label indexOutOfBounds;
02095 if (node->index_needs_bounds_check()) {
02096 const int size_offset = byteOffset(node->size_word_offset());
02097 _masm->cmpl(offset.reg(), Address(array_reg, size_offset));
02098 jcc_error(Assembler::aboveEqual, node, indexOutOfBounds);
02099 }
02100
02101 assert(Tag_Size == 2, "check this code");
02102 const int data_offset = byteOffset(node->data_word_offset());
02103 switch (node->access_type()) {
02104 case ArrayAtNode::byte_at:
02105 { Register result_reg = def(result);
02106 _masm->sarl(offset.reg(), Tag_Size);
02107 if (result_reg.hasByteRegister()) {
02108
02109 _masm->xorl(result_reg, result_reg);
02110 _masm->movb(result_reg, Address(array_reg, offset.reg(), Address::times_1, data_offset));
02111 } else {
02112
02113
02114 _masm->movl(result_reg, Address(array_reg, offset.reg(), Address::times_1, data_offset));
02115 _masm->andl(result_reg, 0x000000FF);
02116 }
02117 _masm->shll(result_reg, Tag_Size);
02118 }
02119 break;
02120 case ArrayAtNode::double_byte_at:
02121 { Register result_reg = def(result);
02122 _masm->sarl(offset.reg(), Tag_Size - 1);
02123 _masm->movl(result_reg, Address(array_reg, offset.reg(), Address::times_1, data_offset));
02124 _masm->andl(result_reg, 0x0000FFFF);
02125 _masm->shll(result_reg, Tag_Size);
02126 }
02127 break;
02128 case ArrayAtNode::character_at:
02129 { Register result_reg = def(result);
02130 _masm->sarl(offset.reg(), Tag_Size - 1);
02131 _masm->movl(result_reg, Address(array_reg, offset.reg(), Address::times_1, data_offset));
02132 _masm->andl(result_reg, 0x0000FFFF);
02133
02134
02135 objArrayOop chars = Universe::asciiCharacters();
02136 _masm->cmpl(result_reg, chars->length());
02137 jcc_error(Assembler::aboveEqual, node, indexOutOfBounds);
02138
02139 _masm->movl(offset.reg(), chars);
02140 _masm->movl(result_reg, Address(offset.reg(), result_reg, Address::times_4, byteOffset(chars->klass()->klass_part()->non_indexable_size() + 1)));
02141 }
02142 break;
02143 case ArrayAtNode::object_at:
02144
02145 _masm->movl(def(result), Address(array_reg, offset.reg(), Address::times_1, data_offset));
02146 break;
02147 default:
02148 ShouldNotReachHere();
02149 break;
02150 }
02151
02152 if (node->canFail() && !node->next(1)->isUncommonNode()) {
02153 Label exit;
02154 _masm->jmp(exit);
02155
02156 if (!node->index_is_smi()) {
02157 _masm->bind(indexNotSmi);
02158 _masm->hlt();
02159 }
02160 if (node->index_needs_bounds_check()) {
02161 _masm->bind(indexOutOfBounds);
02162 _masm->hlt();
02163 }
02164
02165
02166
02167 _masm->bind(exit);
02168 Register r = def(error);
02169 _masm->test(r, 0);
02170 jcc(Assembler::notZero, node, node->next(1));
02171 }
02172 }
02173
02174
02175 void CodeGenerator::anArrayAtPutNode(ArrayAtPutNode* node) {
02176 PReg* array = node->array();
02177 PReg* index = node->index();
02178 PReg* element = node->element();
02179 PReg* error = node->error();
02180 PRegLocker lock(array, index, element);
02181 Register array_reg = use(array);
02182
02183 Temporary offset(_currentMapping, index);
02184
02185 theMacroAssm->subl(offset.reg(), int(smiOop_one));
02186
02187 Label indexNotSmi;
02188 if (!node->index_is_smi()) {
02189 _masm->test(offset.reg(), Mem_Tag);
02190 jcc_error(Assembler::notZero, node, indexNotSmi);
02191 }
02192
02193 Label indexOutOfBounds;
02194 if (node->index_needs_bounds_check()) {
02195 const int size_offset = byteOffset(node->size_word_offset());
02196 _masm->cmpl(offset.reg(), Address(array_reg, size_offset));
02197 jcc_error(Assembler::aboveEqual, node, indexOutOfBounds);
02198 }
02199
02200 assert(Tag_Size == 2, "check this code");
02201 const int data_offset = byteOffset(node->data_word_offset());
02202 Label elementNotSmi, elementOutOfRange;
02203 switch (node->access_type()) {
02204 case ArrayAtPutNode::byte_at_put:
02205 {
02206 Temporary elt(_currentMapping, element);
02207 _masm->sarl(offset.reg(), Tag_Size);
02208
02209 if (!node->element_is_smi()) {
02210 _masm->test(elt.reg(), Mem_Tag);
02211 jcc_error(Assembler::notZero, node, elementNotSmi);
02212 }
02213 _masm->sarl(elt.reg(), Tag_Size);
02214
02215 if (node->element_needs_range_check()) {
02216 _masm->cmpl(elt.reg(), 0x100);
02217 jcc_error(Assembler::aboveEqual, node, elementOutOfRange);
02218 }
02219
02220 if (elt.reg().hasByteRegister()) {
02221
02222 _masm->movb(Address(array_reg, offset.reg(), Address::times_1, data_offset), elt.reg());
02223 } else {
02224
02225
02226 Temporary field(_currentMapping);
02227 _masm->movl(field.reg(), Address(array_reg, offset.reg(), Address::times_1, data_offset));
02228 _masm->andl(field.reg(), 0xFFFFFF00);
02229 _masm->orl(field.reg(), elt.reg());
02230 _masm->movl(Address(array_reg, offset.reg(), Address::times_1, data_offset), field.reg());
02231 }
02232 assert(!node->needs_store_check(), "just checking");
02233 }
02234 break;
02235 case ArrayAtPutNode::double_byte_at_put:
02236 {
02237 Temporary elt(_currentMapping, element);
02238 _masm->sarl(offset.reg(), Tag_Size - 1);
02239
02240 if (!node->element_is_smi()) {
02241 _masm->test(elt.reg(), Mem_Tag);
02242 jcc_error(Assembler::notZero, node, elementNotSmi);
02243 }
02244 _masm->sarl(elt.reg(), Tag_Size);
02245
02246 if (node->element_needs_range_check()) {
02247 _masm->cmpl(elt.reg(), 0x10000);
02248 jcc_error(Assembler::aboveEqual, node, elementOutOfRange);
02249 }
02250
02251 if (elt.reg().hasByteRegister()) {
02252
02253 _masm->movb(Address(array_reg, offset.reg(), Address::times_1, data_offset + 0), elt.reg());
02254 _masm->shrl(elt.reg(), 8);
02255 _masm->movb(Address(array_reg, offset.reg(), Address::times_1, data_offset + 1), elt.reg());
02256 } else {
02257
02258
02259 Temporary field(_currentMapping);
02260 _masm->movl(field.reg(), Address(array_reg, offset.reg(), Address::times_1, data_offset));
02261 _masm->andl(field.reg(), 0xFFFF0000);
02262 _masm->orl(field.reg(), elt.reg());
02263 _masm->movl(Address(array_reg, offset.reg(), Address::times_1, data_offset), field.reg());
02264 }
02265 assert(!node->needs_store_check(), "just checking");
02266 }
02267 break;
02268 case ArrayAtPutNode::object_at_put:
02269
02270 if (node->needs_store_check()) {
02271 _masm->leal(offset.reg(), Address(array_reg, offset.reg(), Address::times_1, data_offset));
02272 _masm->movl(Address(offset.reg()), use(element));
02273 storeCheck(offset.reg());
02274 } else {
02275 _masm->movl(Address(array_reg, offset.reg(), Address::times_1, data_offset), use(element));
02276 }
02277 break;
02278 default:
02279 ShouldNotReachHere();
02280 break;
02281 }
02282
02283 if (node->canFail() && !node->next(1)->isUncommonNode()) {
02284 Label exit;
02285 _masm->jmp(exit);
02286
02287 if (!node->index_is_smi()) {
02288 _masm->bind(indexNotSmi);
02289 _masm->hlt();
02290 }
02291 if (node->index_needs_bounds_check()) {
02292 _masm->bind(indexOutOfBounds);
02293 _masm->hlt();
02294 }
02295 if (!node->element_is_smi()) {
02296 _masm->bind(elementNotSmi);
02297 _masm->hlt();
02298 }
02299 if (node->element_needs_range_check()) {
02300 _masm->bind(elementOutOfRange);
02301 _masm->hlt();
02302 }
02303
02304
02305
02306 _masm->bind(exit);
02307 Register r = def(error);
02308 _masm->test(r, 0);
02309 jcc(Assembler::notZero, node, node->next(1));
02310 }
02311 }
02312
02313
02314 void CodeGenerator::anInlinedPrimitiveNode(InlinedPrimitiveNode* node) {
02315 switch (node->op()) {
02316 case InlinedPrimitiveNode::obj_klass:
02317 { Label is_smi;
02318 PRegLocker lock(node->src());
02319 Register obj_reg = use(node->src());
02320 Register klass_reg = def(node->dst());
02321 _masm->movl(klass_reg, Universe::smiKlassObj());
02322 _masm->test(obj_reg, Mem_Tag);
02323 _masm->jcc(Assembler::zero, is_smi);
02324 _masm->movl(klass_reg, Address(obj_reg, memOopDesc::klass_byte_offset()));
02325 _masm->bind(is_smi);
02326 };
02327 break;
02328 case InlinedPrimitiveNode::obj_hash:
02329 { Unimplemented();
02330
02331
02332 };
02333 break;
02334 case InlinedPrimitiveNode::proxy_byte_at:
02335 { PReg* proxy = node->src();
02336 PReg* index = node->arg1();
02337 PReg* result = node->dst();
02338 PReg* error = node->error();
02339 PRegLocker lock(proxy, index);
02340
02341 Temporary base (_currentMapping, proxy);
02342 Temporary offset(_currentMapping, index);
02343
02344 Label indexNotSmi;
02345 if (!node->arg1_is_smi()) {
02346 _masm->test(offset.reg(), Mem_Tag);
02347 jcc_error(Assembler::notZero, node, indexNotSmi);
02348 }
02349
02350 assert(Tag_Size == 2, "check this code");
02351 Register result_reg = def(result);
02352 _masm->movl(base.reg(), Address(base.reg(), pointer_offset));
02353 _masm->sarl(offset.reg(), Tag_Size);
02354 if (result_reg.hasByteRegister()) {
02355
02356 _masm->xorl(result_reg, result_reg);
02357 _masm->movb(result_reg, Address(base.reg(), offset.reg(), Address::times_1, 0));
02358 } else {
02359
02360
02361 _masm->movl(result_reg, Address(base.reg(), offset.reg(), Address::times_1, 0));
02362 _masm->andl(result_reg, 0x000000FF);
02363 }
02364 _masm->shll(result_reg, Tag_Size);
02365
02366 if (node->canFail() && !node->next(1)->isUncommonNode()) {
02367 Label exit;
02368 _masm->jmp(exit);
02369
02370 if (!node->arg1_is_smi()) {
02371 _masm->bind(indexNotSmi);
02372 _masm->hlt();
02373 }
02374
02375
02376
02377 _masm->bind(exit);
02378 Register r = def(error);
02379 _masm->test(r, 0);
02380 jcc(Assembler::notZero, node, node->next(1));
02381 }
02382 }
02383 break;
02384 case InlinedPrimitiveNode::proxy_byte_at_put:
02385 { bool const_val = node->arg2()->isConstPReg();
02386 PReg* proxy = node->src();
02387 PReg* index = node->arg1();
02388 PReg* value = node->arg2();
02389 PReg* error = node->error();
02390
02391
02392
02393
02394
02395
02396 Temporary base (_currentMapping, proxy);
02397 Temporary offset(_currentMapping, index);
02398
02399
02400
02401
02402 Temporary val(_currentMapping);
02403 if (const_val) {
02404
02405 if (!node->arg2_is_smi()) fatal("proxy_byte_at_put: should not happen - internal error");
02406
02407 } else {
02408 _masm->movl(val.reg(), use(value));
02409 }
02410
02411 Label indexNotSmi;
02412 if (!node->arg1_is_smi()) {
02413 _masm->test(offset.reg(), Mem_Tag);
02414 jcc_error(Assembler::notZero, node, indexNotSmi);
02415 }
02416
02417 Label valueNotSmi;
02418 if (!node->arg2_is_smi()) {
02419 assert(!const_val, "constant shouldn't need a smi check");
02420 _masm->test(val.reg(), Mem_Tag);
02421 jcc_error(Assembler::notZero, node, valueNotSmi);
02422 }
02423
02424 assert(Tag_Size == 2, "check this code");
02425 _masm->movl(base.reg(), Address(base.reg(), pointer_offset));
02426 _masm->sarl(offset.reg(), Tag_Size);
02427 if (const_val) {
02428 smiOop constant = smiOop(((ConstPReg*)value)->constant);
02429 assert(constant->is_smi(), "should be a smi");
02430 _masm->movb(Address(base.reg(), offset.reg(), Address::times_1, 0), constant->value() & 0xFF);
02431 } else {
02432 _masm->sarl(val.reg(), Tag_Size);
02433 if (val.reg().hasByteRegister()) {
02434
02435 _masm->movb(Address(base.reg(), offset.reg(), Address::times_1, 0), val.reg());
02436 } else {
02437
02438
02439 Temporary field(_currentMapping);
02440 _masm->movl(field.reg(), Address(base.reg(), offset.reg(), Address::times_1, 0));
02441 _masm->andl(val .reg(), 0x000000FF);
02442 _masm->andl(field.reg(), 0xFFFFFF00);
02443 _masm->orl (field.reg(), val.reg());
02444 _masm->movl(Address(base.reg(), offset.reg(), Address::times_1, 0), field.reg());
02445 }
02446 }
02447
02448 if (node->canFail() && !node->next(1)->isUncommonNode()) {
02449 Label exit;
02450 _masm->jmp(exit);
02451
02452 if (!node->arg1_is_smi()) {
02453 _masm->bind(indexNotSmi);
02454 _masm->hlt();
02455 }
02456 if (!node->arg2_is_smi()) {
02457 _masm->bind(valueNotSmi);
02458 _masm->hlt();
02459 }
02460
02461
02462
02463 _masm->bind(exit);
02464 Register r = def(error);
02465 _masm->test(r, 0);
02466 jcc(Assembler::notZero, node, node->next(1));
02467 }
02468 }
02469 break;
02470 default: ShouldNotReachHere();
02471 }
02472 }
02473
02474
02475 void CodeGenerator::anUncommonNode(UncommonNode* node) {
02476
02477
02478 updateDebuggingInfo(node);
02479 _masm->call(StubRoutines::unused_uncommon_trap_entry(), relocInfo::uncommon_type);
02480 setMapping(NULL);
02481 }
02482
02483
02484 void CodeGenerator::aFixedCodeNode(FixedCodeNode* node) {
02485 switch(node->kind()) {
02486 case FixedCodeNode::dead_end: _masm->hlt(); setMapping(NULL); break;
02487 case FixedCodeNode::inc_counter: incrementInvocationCounter(); break;
02488 default: fatal1("unexpected FixedCodeNode kind %d", node->kind());
02489 }
02490 }
02491
02492
02493 # endif
02494
02495