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/_primInliner.cpp.incl"
00028
00029 inline bool equal(char* s, char* t) { return strcmp(s, t) == 0; }
00030
00031
00032 void PrimInliner::assert_failure_block() {
00033 assert(_failure_block != NULL, "primitive must have a failure block");
00034 }
00035
00036
00037 void PrimInliner::assert_no_failure_block() {
00038 assert(_failure_block == NULL, "primitive doesn't have a failure block");
00039 }
00040
00041
00042 void PrimInliner::assert_receiver() {
00043 assert(parameter(0) == _scope->self(), "first parameter must be self");
00044 }
00045
00046
00047 int PrimInliner::log2(int x) const {
00048 int i = -1;
00049 int p = 1;
00050 while (p != 0 && p <= x) {
00051
00052 i++; p *= 2;
00053 }
00054
00055
00056 return i;
00057 }
00058
00059
00060 Expr* PrimInliner::tryConstantFold() {
00061
00062
00063
00064
00065
00066 if (!_pdesc->can_be_constant_folded()) {
00067
00068 if ((equal(_pdesc->name(), "primitiveIndexedByteAt:ifFail:") ||
00069 equal(_pdesc->name(), "primitiveIndexedByteCharacterAt:ifFail:")) &&
00070 parameter(0)->hasKlass() && parameter(0)->klass() == Universe::symbolKlassObj()) {
00071
00072
00073
00074 } else {
00075 return NULL;
00076 }
00077 }
00078
00079 int i = number_of_parameters();
00080 oop* args = NEW_RESOURCE_ARRAY(oop, i);
00081 while (i > 0) {
00082 i--;
00083 Expr* arg = parameter(i);
00084 if (!arg->isConstantExpr()) return NULL;
00085 args[i] = arg->constant();
00086 }
00087
00088 oop res = _pdesc->eval(args);
00089 if (res->is_mark()) {
00090
00091 return primitiveFailure(unmarkSymbol(res));
00092 } else if (res->is_mem() && !res->is_old()) {
00093
00094 if (res->is_double()) {
00095 res = oopFactory::clone_double_to_oldspace(doubleOop(res));
00096 } else {
00097
00098 warning("const folding: primitive %s is returning non-tenured object", _pdesc->name());
00099 return NULL;
00100 }
00101 }
00102 ConstPReg* constResult = new_ConstPReg(_scope, res);
00103 SAPReg* result = new SAPReg(_scope);
00104 _gen->append(NodeFactory::new_AssignNode(constResult, result));
00105 if (CompilerDebug) cout(PrintInlining)->print("%*sconstant-folding %s --> %#x\n", _scope->depth + 2, "", _pdesc->name(), res);
00106 assert(!constResult->constant->is_mark(), "result must not be marked");
00107 return new ConstantExpr(res, constResult, _gen->current());
00108 }
00109
00110
00111 Expr* PrimInliner::tryTypeCheck() {
00112
00113
00114
00115
00116
00117
00118 int num = number_of_parameters();
00119 for (int i = 0; i < num; i++) {
00120 Expr* a = parameter(i);
00121 if (a->hasKlass()) {
00122 Expr* primArgType = _pdesc->parameter_klass(i, a->preg(), NULL);
00123 if (primArgType && primArgType->hasKlass() && (a->klass() != primArgType->klass())) {
00124
00125 return primitiveFailure(failureSymbolForArg(i));
00126 }
00127 }
00128 }
00129 return NULL;
00130 }
00131
00132
00133 symbolOop PrimInliner::failureSymbolForArg(int i) {
00134 assert(i >= 0 && i < number_of_parameters(), "bad index");
00135 switch (i) {
00136 case 0: return vmSymbols::receiver_has_wrong_type();
00137 case 1: return vmSymbols::first_argument_has_wrong_type();
00138 case 2: return vmSymbols::second_argument_has_wrong_type();
00139 case 3: return vmSymbols::third_argument_has_wrong_type();
00140 case 4: return vmSymbols::fourth_argument_has_wrong_type();
00141 case 5: return vmSymbols::fifth_argument_has_wrong_type();
00142 case 6: return vmSymbols::sixth_argument_has_wrong_type();
00143 case 7: return vmSymbols::seventh_argument_has_wrong_type();
00144 case 8: return vmSymbols::eighth_argument_has_wrong_type();
00145 case 9: return vmSymbols::ninth_argument_has_wrong_type();
00146 case 10: return vmSymbols::tenth_argument_has_wrong_type();
00147 default: return vmSymbols::argument_has_wrong_type();
00148 }
00149 }
00150
00151
00152
00153
00154 class AssignmentFinder: public SpecializedMethodClosure {
00155 public:
00156 int tempNo;
00157 MethodInterval* block;
00158 MethodInterval* interval;
00159
00160 AssignmentFinder(MethodInterval* b) : SpecializedMethodClosure() {
00161 block = b;
00162 interval = NULL;
00163 MethodIterator iter(block, this);
00164 }
00165 void instruction() { abort(); }
00166 void store_temporary(int no) {
00167 tempNo = no;
00168 interval = MethodIterator::factory->new_MethodInterval(method(), NULL, next_bci(), block->end_bci());
00169 }
00170 };
00171
00172
00173 Expr* PrimInliner::primitiveFailure(symbolOop failureCode) {
00174
00175 if (CompilerDebug) cout(PrintInlining)->print("%*sprimitive %s will fail: %s\n", _scope->depth + 2, "", _pdesc->name(), failureCode->as_string());
00176 if (_failure_block == NULL) {
00177 error("\nPotential compiler bug: compiler believes primitive %s will fail\nwith error %s, but primitive has no failure block.\n",
00178 _pdesc->name(), failureCode->as_string());
00179 return NULL;
00180 }
00181
00182
00183
00184
00185
00186 AssignmentFinder closure(_failure_block);
00187 assert(closure.interval != NULL, "no assignment found");
00188 Expr* old_temp = _scope->temporary(closure.tempNo);
00189 Expr* res = new ConstantExpr(failureCode, new_ConstPReg(_scope, failureCode), _gen->current());
00190 _scope->set_temporary(closure.tempNo, res);
00191 closure.set_prim_failure(false);
00192 _gen->generate_subinterval(closure.interval, true);
00193 _scope->set_temporary(closure.tempNo, old_temp);
00194 return _gen->exprStack()->pop();
00195 }
00196
00197 Expr* PrimInliner::merge_failure_block(Node* ok_exit, Expr* ok_result, Node* failure_exit, Expr* failure_code, bool ok_result_is_read_only) {
00198 assert(failure_code->hasKlass() && failure_code->klass() == Universe::symbolKlassObj(), "failure code must be a symbol");
00199 _cannotFail = false;
00200
00201 _gen->setCurrent(failure_exit);
00202 _gen->exprStack()->push(failure_code, _scope, failure_exit->bci());
00203
00204 _gen->generate_subinterval(_failure_block, true);
00205 Expr* failure_block_result = _gen->exprStack()->pop();
00206 if (failure_block_result->isNoResultExpr()) {
00207
00208 assert(!_gen->current() || _gen->current() == NodeBuilder::EndOfCode, "shouldn't reach here");
00209 _gen->setCurrent(ok_exit);
00210 return ok_result;
00211 } else {
00212 if (ok_result_is_read_only) {
00213
00214
00215
00216 PReg* resPReg = new SAPReg(_scope);
00217 Node* node = NodeFactory::new_AssignNode(ok_result->preg(), resPReg);
00218 Expr* resExpr = ok_result->shallowCopy(resPReg, node);
00219 ok_exit->append(node);
00220 ok_exit = node;
00221 ok_result = resExpr;
00222 }
00223 _gen->append(NodeFactory::new_AssignNode(failure_block_result->preg(), ok_result->preg()));
00224
00225 MergeNode* prim_exit = NodeFactory::new_MergeNode(_failure_block->end_bci());
00226 _gen->append(prim_exit);
00227 ok_exit->append(prim_exit);
00228 _gen->setCurrent(prim_exit);
00229 return new MergeExpr(ok_result, failure_block_result, ok_result->preg(), prim_exit);
00230 }
00231 }
00232
00233 class PrimSendFinder : public SpecializedMethodClosure {
00234 public:
00235 RScope* rs;
00236 bool was_executed;
00237
00238 PrimSendFinder(RScope* rs) { this->rs = rs; was_executed = false; rs->extend(); }
00239 virtual void normal_send(InterpretedIC* ic) { check_send(ic); }
00240 virtual void self_send (InterpretedIC* ic) { check_send(ic); }
00241 virtual void super_send (InterpretedIC* ic) { check_send(ic); }
00242 void check_send(InterpretedIC* ic) {
00243 GrowableArray<RScope*>* sub = rs->subScopes(bci());
00244 if (sub->length() == 1 && sub->first()->isUntakenScope()) {
00245
00246 } else {
00247 was_executed = true;
00248 }
00249 }
00250 };
00251
00252
00253 inline bool PrimInliner::basic_shouldUseUncommonTrap() const {
00254 ResourceMark rm;
00255 if (!theCompiler->useUncommonTraps) return false;
00256
00257
00258
00259
00260 if (_scope->rscope->isNotUncommonAt(_bci)) return false;
00261
00262 if (_scope->rscope->isUncommonAt(_bci)) return true;
00263
00264
00265 if (!_scope->rscope->get_nmethod()) {
00266 return true;
00267 }
00268 #ifdef broken
00269
00270
00271
00272
00273
00274 PrimSendFinder p(_scope->rscope);
00275 MethodIterator it(_failure_block, &p);
00276 return !p.was_executed;
00277 #endif
00278
00279 return true;
00280 }
00281
00282 bool PrimInliner::shouldUseUncommonTrap() {
00283
00284 _usingUncommonTrap = basic_shouldUseUncommonTrap();
00285 return _usingUncommonTrap;
00286 }
00287
00288 Expr* PrimInliner::smi_ArithmeticOp(ArithOpCode op, Expr* arg1, Expr* arg2) {
00289 assert_failure_block();
00290 assert_receiver();
00291
00292
00293 bool intArg1 = arg1->is_smi();
00294 bool intArg2 = arg2->is_smi();
00295 bool intBoth = intArg1 && intArg2;
00296 SAPReg* resPReg = new SAPReg(_scope);
00297 SAPReg* errPReg = new SAPReg(_scope);
00298 MergeNode* failureStart = NodeFactory::new_MergeNode(_failure_block->begin_bci());
00299
00300
00301 Node* n1;
00302 AssignNode* n1Err;
00303 ConstantExpr* n1Expr = NULL;
00304 if (intBoth) {
00305
00306 n1 = NodeFactory::new_ArithRRNode(resPReg, arg1->preg(), op, arg2->preg());
00307 } else {
00308
00309 n1 = NodeFactory::new_TArithRRNode(resPReg, arg1->preg(), op, arg2->preg(), intArg1, intArg2);
00310 if (shouldUseUncommonTrap()) {
00311
00312 n1->append(1, failureStart);
00313 } else {
00314 ConstPReg* n1PReg = new_ConstPReg(_scope, vmSymbols::first_argument_has_wrong_type());
00315 n1Err = NodeFactory::new_AssignNode(n1PReg, errPReg);
00316 n1Expr = new ConstantExpr(n1PReg->constant, errPReg, n1Err);
00317 n1->append(1, n1Err);
00318 n1Err->append(failureStart);
00319 }
00320 }
00321 _gen->append(n1);
00322 Expr* result = new KlassExpr(smiKlassObj, resPReg, n1);
00323
00324
00325 const bool taken_is_uncommon = true;
00326 BranchNode* n2 = NodeFactory::new_BranchNode(VSBranchOp, taken_is_uncommon);
00327 AssignNode* n2Err;
00328 ConstantExpr* n2Expr = NULL;
00329 if (shouldUseUncommonTrap()) {
00330
00331 n2->append(1, failureStart);
00332 } else {
00333 ConstPReg* n2PReg = new_ConstPReg(_scope, vmSymbols::smi_overflow());
00334 n2Err = NodeFactory::new_AssignNode(n2PReg, errPReg);
00335 n2Expr = new ConstantExpr(n2PReg->constant, errPReg, n2Err);
00336 n2->append(1, n2Err);
00337 n2Err->append(failureStart);
00338 }
00339 _gen->append(n2);
00340
00341
00342 if (shouldUseUncommonTrap()) {
00343
00344 failureStart->append(NodeFactory::new_UncommonNode(_gen->copyCurrentExprStack(), _bci ));
00345 } else {
00346 assert(n2Expr != NULL, "no error message defined");
00347 Expr* error;
00348 if (n1Expr != NULL) {
00349 error = new MergeExpr(n1Expr, n2Expr, errPReg, failureStart);
00350 } else {
00351 error = n2Expr;
00352 }
00353 result = merge_failure_block(n2, result, failureStart, error, false);
00354 }
00355 return result;
00356 }
00357
00358
00359 Expr* PrimInliner::smi_BitOp(ArithOpCode op, Expr* arg1, Expr* arg2) {
00360 assert_failure_block();
00361 assert_receiver();
00362
00363
00364 bool intArg1 = arg1->is_smi();
00365 bool intArg2 = arg2->is_smi();
00366 bool intBoth = intArg1 && intArg2;
00367 SAPReg* resPReg = new SAPReg(_scope);
00368 SAPReg* errPReg = new SAPReg(_scope);
00369
00370
00371 Node* n1;
00372 AssignNode* n1Err;
00373 ConstantExpr* n1Expr;
00374 if (intBoth) {
00375
00376 n1 = NodeFactory::new_ArithRRNode(resPReg, arg1->preg(), op, arg2->preg());
00377 } else {
00378
00379 n1 = NodeFactory::new_TArithRRNode(resPReg, arg1->preg(), op, arg2->preg(), intArg1, intArg2);
00380 ConstPReg* n1PReg = new_ConstPReg(_scope, vmSymbols::first_argument_has_wrong_type());
00381 n1Err = NodeFactory::new_AssignNode(n1PReg, errPReg);
00382 n1Expr = new ConstantExpr(n1PReg->constant, errPReg, n1Err);
00383 n1->append(1, n1Err);
00384 }
00385 _gen->append(n1);
00386
00387
00388 Expr* result = new KlassExpr(smiKlassObj, resPReg, n1);
00389 if (!intBoth) {
00390
00391 if (shouldUseUncommonTrap()) {
00392
00393 n1Err->append(NodeFactory::new_UncommonNode(_gen->copyCurrentExprStack(), _bci ));
00394 } else {
00395
00396 result = merge_failure_block(n1, result, n1Err, n1Expr, false);
00397 }
00398 }
00399 return result;
00400 }
00401
00402
00403 Expr* PrimInliner::smi_Div(Expr* x, Expr* y) {
00404 if (y->preg()->isConstPReg()) {
00405 assert(y->is_smi(), "type check should have failed");
00406 int d = smiOop(((ConstPReg*)y->preg())->constant)->value();
00407 if (is_power_of_2(d)) {
00408
00409 ConstPReg* preg = new_ConstPReg(_scope, as_smiOop(-log2(d)));
00410 return smi_BitOp(tShiftArithOp, x, new ConstantExpr(preg->constant, preg, _gen->_current));
00411 }
00412 }
00413
00414 return NULL;
00415 }
00416
00417
00418 Expr* PrimInliner::smi_Mod(Expr* x, Expr* y) {
00419 if (y->preg()->isConstPReg()) {
00420 assert(y->is_smi(), "type check should have failed");
00421 int d = smiOop(((ConstPReg*)y->preg())->constant)->value();
00422 if (is_power_of_2(d)) {
00423
00424 ConstPReg* preg = new_ConstPReg(_scope, as_smiOop(d-1));
00425 return smi_BitOp(tAndArithOp, x, new ConstantExpr(preg->constant, preg, _gen->_current));
00426 }
00427 }
00428
00429 return NULL;
00430 }
00431
00432
00433 Expr* PrimInliner::smi_Shift(Expr* arg1, Expr* arg2) {
00434 if (parameter(1)->preg()->isConstPReg()) {
00435
00436 assert(arg2->is_smi(), "type check should have failed");
00437 return smi_BitOp(tShiftArithOp, arg1, arg2);
00438 }
00439
00440 return NULL;
00441 }
00442
00443
00444 static BranchOpCode not(BranchOpCode cond) {
00445 switch (cond) {
00446 case EQBranchOp : return NEBranchOp;
00447 case NEBranchOp : return EQBranchOp;
00448 case LTBranchOp : return GEBranchOp;
00449 case LEBranchOp : return GTBranchOp;
00450 case GTBranchOp : return LEBranchOp;
00451 case GEBranchOp : return LTBranchOp;
00452 case LTUBranchOp: return GEUBranchOp;
00453 case LEUBranchOp: return GTUBranchOp;
00454 case GTUBranchOp: return LEUBranchOp;
00455 case GEUBranchOp: return LTUBranchOp;
00456 case VSBranchOp : return VCBranchOp;
00457 case VCBranchOp : return VSBranchOp;
00458 }
00459 ShouldNotReachHere();
00460 return EQBranchOp;
00461 }
00462
00463
00464 Expr* PrimInliner::generate_cond(BranchOpCode cond, NodeBuilder* gen, PReg* resPReg) {
00465
00466
00467
00468
00469
00470 BranchNode* n2 = NodeFactory::new_BranchNode(not(cond));
00471 gen->append(n2);
00472
00473
00474 ConstPReg* tPReg = new_ConstPReg(gen->scope(), trueObj);
00475 AssignNode* tAsgn = NodeFactory::new_AssignNode(tPReg, resPReg);
00476 ConstantExpr* tExpr = new ConstantExpr(trueObj, resPReg, tAsgn);
00477 n2->append(0, tAsgn);
00478
00479
00480 ConstPReg* fPReg = new_ConstPReg(gen->scope(), falseObj);
00481 AssignNode* fAsgn = NodeFactory::new_AssignNode(fPReg, resPReg);
00482 ConstantExpr* fExpr = new ConstantExpr(falseObj, resPReg, fAsgn);
00483 n2->append(1, fAsgn);
00484
00485
00486 MergeNode* ftm = NodeFactory::new_MergeNode(fAsgn, tAsgn);
00487 Expr* result = new MergeExpr(fExpr, tExpr, resPReg, ftm);
00488 gen->setCurrent(ftm);
00489 return result;
00490 }
00491
00492
00493 Expr* PrimInliner::smi_Comparison(BranchOpCode cond, Expr* arg1, Expr* arg2) {
00494 assert_failure_block();
00495 assert_receiver();
00496
00497
00498 bool intArg1 = arg1->is_smi();
00499 bool intArg2 = arg2->is_smi();
00500 bool intBoth = intArg1 && intArg2;
00501 SAPReg* resPReg = new SAPReg(_scope);
00502 SAPReg* errPReg = new SAPReg(_scope);
00503
00504
00505 Node* n1;
00506 ConstPReg* n1PReg;
00507 AssignNode* n1Err;
00508 ConstantExpr* n1Expr;
00509 if (intBoth) {
00510
00511 n1 = NodeFactory::new_ArithRRNode(new NoPReg(_scope), arg1->preg(), tCmpArithOp, arg2->preg());
00512 } else {
00513
00514 n1 = NodeFactory::new_TArithRRNode(new NoPReg(_scope), arg1->preg(), tCmpArithOp, arg2->preg(), intArg1, intArg2);
00515 n1PReg = new_ConstPReg(_scope, vmSymbols::first_argument_has_wrong_type());
00516 n1Err = NodeFactory::new_AssignNode(n1PReg, errPReg);
00517 n1Expr = new ConstantExpr(n1PReg->constant, errPReg, n1Err);
00518 n1->append(1, n1Err);
00519 }
00520 _gen->append(n1);
00521
00522 Expr* result = generate_cond(cond, _gen, resPReg);
00523
00524
00525 if (!intBoth) {
00526
00527 if (shouldUseUncommonTrap()) {
00528
00529 n1Err->append(NodeFactory::new_UncommonNode(_gen->copyCurrentExprStack(), _bci ));
00530 } else {
00531
00532 result = merge_failure_block(result->node(), result, n1Err, n1Expr, false);
00533 }
00534 }
00535 return result;
00536 }
00537
00538
00539 Expr* PrimInliner::array_size() {
00540 assert(_failure_block == NULL, "primitive must have no failure block");
00541 assert_receiver();
00542
00543
00544 Expr* array = parameter(0);
00545 Klass* klass = array->klass()->klass_part();
00546 int lenOffs = klass->non_indexable_size();
00547
00548
00549 SAPReg* res = new SAPReg(_scope);
00550 _gen->append(NodeFactory::new_LoadOffsetNode(res, array->preg(), lenOffs, true));
00551 return new KlassExpr(smiKlassObj, res, _gen->_current);
00552 }
00553
00554
00555 Expr* PrimInliner::array_at_ifFail(ArrayAtNode::AccessType access_type) {
00556 assert_failure_block();
00557 assert_receiver();
00558
00559
00560 Expr* array = parameter(0);
00561 Expr* index = parameter(1);
00562 SAPReg* resPReg = new SAPReg(_scope);
00563 SAPReg* errPReg = new SAPReg(_scope);
00564 Klass* klass = array->klass()->klass_part();
00565 int lenOffs = klass->non_indexable_size();
00566 int arrOffs = lenOffs + 1;
00567
00568
00569 ArrayAtNode* at = NodeFactory::new_ArrayAtNode(
00570 access_type, array->preg(), index->preg(), index->is_smi(), resPReg, errPReg, arrOffs, lenOffs
00571 );
00572 _gen->append(at);
00573
00574
00575 Expr* resExpr;
00576 switch (access_type) {
00577 case ArrayAtNode::byte_at :
00578 case ArrayAtNode::double_byte_at: resExpr = new KlassExpr(Universe::smiKlassObj(), resPReg, at); break;
00579 case ArrayAtNode::character_at : resExpr = new KlassExpr(Universe::characterKlassObj(), resPReg, at); break;
00580 case ArrayAtNode::object_at : resExpr = new UnknownExpr(resPReg, at); break;
00581 default : ShouldNotReachHere();
00582 }
00583 if (at->canFail()) {
00584 if (shouldUseUncommonTrap()) {
00585
00586 at->append(1, NodeFactory::new_UncommonNode(_gen->copyCurrentExprStack(), _bci ));
00587 } else {
00588
00589 NopNode* err = NodeFactory::new_NopNode();
00590 at->append(1, err);
00591 Expr* errExpr = new KlassExpr(Universe::symbolKlassObj(), errPReg, at);
00592 resExpr = merge_failure_block(at, resExpr, err, errExpr, false);
00593 }
00594 }
00595 return resExpr;
00596 }
00597
00598
00599 Expr* PrimInliner::array_at_put_ifFail(ArrayAtPutNode::AccessType access_type) {
00600 assert_failure_block();
00601 assert_receiver();
00602
00603
00604 Expr* array = parameter(0);
00605 Expr* index = parameter(1);
00606 Expr* element = parameter(2);
00607 SAPReg* resPReg = new SAPReg(_scope);
00608 SAPReg* errPReg = new SAPReg(_scope);
00609 Klass* klass = array->klass()->klass_part();
00610 int lenOffs = klass->non_indexable_size();
00611 int arrOffs = lenOffs + 1;
00612 bool storeCheck = (access_type == ArrayAtPutNode::object_at_put) && element->needsStoreCheck();
00613
00614 if (access_type == ArrayAtPutNode::object_at_put) {
00615
00616 _gen->materialize(element->preg(), NULL);
00617 }
00618
00619
00620 ArrayAtPutNode* atPut = NodeFactory::new_ArrayAtPutNode(
00621 access_type, array->preg(), index->preg(), index->is_smi(), element->preg(), element->is_smi(), NULL, errPReg, arrOffs, lenOffs, storeCheck
00622 );
00623 _gen->append(atPut);
00624
00625
00626 Expr* resExpr = array;
00627 if (atPut->canFail()) {
00628 if (shouldUseUncommonTrap()) {
00629
00630 atPut->append(1, NodeFactory::new_UncommonNode(_gen->copyCurrentExprStack(), _bci ));
00631 } else {
00632
00633 NopNode* err = NodeFactory::new_NopNode();
00634 atPut->append(1, err);
00635 Expr* errExpr = new KlassExpr(Universe::symbolKlassObj(), errPReg, atPut);
00636 resExpr = merge_failure_block(atPut, resExpr, err, errExpr, true);
00637 }
00638 }
00639 return resExpr;
00640 }
00641
00642
00643 Expr* PrimInliner::obj_new() {
00644
00645 Expr* rcvr = parameter(0);
00646 if (!rcvr->isConstantExpr() || !rcvr->constant()->is_klass()) return NULL;
00647 Klass* klass = klassOop(rcvr->constant())->klass_part();
00648 if (klass->oop_is_indexable()) return NULL;
00649 int size = klass->non_indexable_size();
00650
00651 if (klass->can_inline_allocation()) {
00652
00653 int number_of_instance_variables = size - memOopDesc::header_size();
00654 switch (number_of_instance_variables) {
00655 case 0: _pdesc = primitives::new0(); break;
00656 case 1: _pdesc = primitives::new1(); break;
00657 case 2: _pdesc = primitives::new2(); break;
00658 case 3: _pdesc = primitives::new3(); break;
00659 case 4: _pdesc = primitives::new4(); break;
00660 case 5: _pdesc = primitives::new5(); break;
00661 case 6: _pdesc = primitives::new6(); break;
00662 case 7: _pdesc = primitives::new7(); break;
00663 case 8: _pdesc = primitives::new8(); break;
00664 case 9: _pdesc = primitives::new9(); break;
00665 default: ;
00666 }
00667 }
00668 Expr* u = genCall(false);
00669 return new KlassExpr(klass->as_klassOop(), u->preg(), u->node());
00670 }
00671
00672
00673 Expr* PrimInliner::obj_shallowCopy() {
00674
00675
00676 Expr* u = genCall(false);
00677 assert(u->isUnknownExpr(), "oops");
00678 return new KlassExpr(parameter(0)->klass(), u->preg(), u->node());
00679 }
00680
00681
00682 Expr* PrimInliner::obj_equal() {
00683 assert_no_failure_block();
00684
00685
00686 PReg* arg1 = parameter(0)->preg();
00687 PReg* arg2 = parameter(1)->preg();
00688
00689 _gen->append(NodeFactory::new_ArithRRNode(new NoPReg(_scope), arg1, CmpArithOp, arg2));
00690 SAPReg* resPReg = new SAPReg(_scope);
00691 return generate_cond(EQBranchOp, _gen, resPReg);
00692 }
00693
00694
00695 Expr* PrimInliner::obj_class(bool has_receiver) {
00696 assert_no_failure_block();
00697 if (has_receiver) assert_receiver();
00698
00699 Expr* obj = parameter(0);
00700 if (obj->hasKlass()) {
00701
00702 klassOop k = obj->klass();
00703 return new ConstantExpr(k, new_ConstPReg(_scope, k), NULL);
00704 } else {
00705 SAPReg* resPReg = new SAPReg(_scope);
00706 InlinedPrimitiveNode* n = NodeFactory::new_InlinedPrimitiveNode(
00707 InlinedPrimitiveNode::obj_klass, resPReg, NULL, obj->preg()
00708 );
00709 _gen->append(n);
00710
00711 return new UnknownExpr(resPReg, n);
00712 }
00713 }
00714
00715
00716 Expr* PrimInliner::obj_hash(bool has_receiver) {
00717 assert_no_failure_block();
00718 if (has_receiver) assert_receiver();
00719
00720 Expr* obj = parameter(0);
00721 if (obj->is_smi()) {
00722
00723 return obj;
00724 } else {
00725 return NULL;
00726
00727
00728
00729
00730 SAPReg* resPReg = new SAPReg(_scope);
00731 InlinedPrimitiveNode* n = NodeFactory::new_InlinedPrimitiveNode(
00732 InlinedPrimitiveNode::obj_hash, resPReg, NULL, obj->preg()
00733 );
00734 _gen->append(n);
00735 return new KlassExpr(Universe::smiKlassObj(), resPReg, n);
00736 }
00737 }
00738
00739
00740 Expr* PrimInliner::proxy_byte_at() {
00741 assert_failure_block();
00742 assert_receiver();
00743
00744
00745 Expr* proxy = parameter(0);
00746 Expr* index = parameter(1);
00747 SAPReg* resPReg = new SAPReg(_scope);
00748 SAPReg* errPReg = new SAPReg(_scope);
00749
00750
00751 InlinedPrimitiveNode* at = NodeFactory::new_InlinedPrimitiveNode(
00752 InlinedPrimitiveNode::proxy_byte_at, resPReg, errPReg, proxy->preg(), index->preg(), index->is_smi()
00753 );
00754 _gen->append(at);
00755
00756
00757 Expr* resExpr = new KlassExpr(Universe::smiKlassObj(), resPReg, at);
00758 if (at->canFail()) {
00759 if (shouldUseUncommonTrap()) {
00760
00761 at->append(1, NodeFactory::new_UncommonNode(_gen->copyCurrentExprStack(), _bci ));
00762 } else {
00763
00764 NopNode* err = NodeFactory::new_NopNode();
00765 at->append(1, err);
00766 Expr* errExpr = new KlassExpr(Universe::symbolKlassObj(), errPReg, at);
00767 resExpr = merge_failure_block(at, resExpr, err, errExpr, false);
00768 }
00769 }
00770 return resExpr;
00771 }
00772
00773
00774 Expr* PrimInliner::proxy_byte_at_put() {
00775 assert_failure_block();
00776 assert_receiver();
00777
00778
00779 Expr* proxy = parameter(0);
00780 Expr* index = parameter(1);
00781 Expr* value = parameter(2);
00782 SAPReg* errPReg = new SAPReg(_scope);
00783
00784
00785 InlinedPrimitiveNode* atPut = NodeFactory::new_InlinedPrimitiveNode(
00786 InlinedPrimitiveNode::proxy_byte_at_put, NULL, errPReg, proxy->preg(), index->preg(), index->is_smi(), value->preg(), value->is_smi()
00787 );
00788 _gen->append(atPut);
00789
00790
00791 Expr* resExpr = proxy;
00792 if (atPut->canFail()) {
00793 if (shouldUseUncommonTrap()) {
00794
00795 atPut->append(1, NodeFactory::new_UncommonNode(_gen->copyCurrentExprStack(), _bci ));
00796 } else {
00797
00798 NopNode* err = NodeFactory::new_NopNode();
00799 atPut->append(1, err);
00800 Expr* errExpr = new KlassExpr(Universe::symbolKlassObj(), errPReg, atPut);
00801 resExpr = merge_failure_block(atPut, resExpr, err, errExpr, true);
00802 }
00803 }
00804 return resExpr;
00805 }
00806
00807
00808 Expr* PrimInliner::block_primitiveValue() {
00809 PReg* r = parameter(0)->preg();
00810 if (r->isBlockPReg()) {
00811
00812 Inliner* inliner = _gen->inliner();
00813 SendInfo* info = new SendInfo(_scope, parameter(0), _pdesc->selector());
00814 Expr* res = inliner->inlineBlockInvocation(info);
00815 if (res) return res;
00816 }
00817
00818 return NULL;
00819 }
00820
00821
00822 Expr* PrimInliner::tryInline() {
00823
00824
00825
00826
00827
00828
00829
00830 char* name = _pdesc->name();
00831 Expr* res = NULL;
00832 switch (_pdesc->group()) {
00833 case IntArithmeticPrimitive:
00834 if (number_of_parameters() == 2) {
00835 Expr* x = parameter(0);
00836 Expr* y = parameter(1);
00837 if (equal(name, "primitiveAdd:ifFail:")) { res = smi_ArithmeticOp(tAddArithOp, x, y); break; }
00838 if (equal(name, "primitiveSubtract:ifFail:")) { res = smi_ArithmeticOp(tSubArithOp, x, y); break; }
00839 if (equal(name, "primitiveMultiply:ifFail:")) { res = smi_ArithmeticOp(tMulArithOp, x, y); break; }
00840 if (equal(name, "primitiveDiv:ifFail:")) { res = smi_Div(x, y); break; }
00841 if (equal(name, "primitiveMod:ifFail:")) { res = smi_Mod(x, y); break; }
00842 if (equal(name, "primitiveBitAnd:ifFail:")) { res = smi_BitOp(tAndArithOp, x, y); break; }
00843 if (equal(name, "primitiveBitOr:ifFail:")) { res = smi_BitOp(tOrArithOp , x, y); break; }
00844 if (equal(name, "primitiveBitXor:ifFail:")) { res = smi_BitOp(tXOrArithOp, x, y); break; }
00845 if (equal(name, "primitiveRawBitShift:ifFail:")) { res = smi_Shift(x, y); break; }
00846 }
00847 break;
00848 case IntComparisonPrimitive:
00849 if (number_of_parameters() == 2) {
00850 Expr* x = parameter(0);
00851 Expr* y = parameter(1);
00852 if (equal(name, "primitiveSmallIntegerEqual:ifFail:")) { res = smi_Comparison(EQBranchOp, x, y); break; }
00853 if (equal(name, "primitiveSmallIntegerNotEqual:ifFail:")) { res = smi_Comparison(NEBranchOp, x, y); break; }
00854 if (equal(name, "primitiveLessThan:ifFail:")) { res = smi_Comparison(LTBranchOp, x, y); break; }
00855 if (equal(name, "primitiveLessThanOrEqual:ifFail:")) { res = smi_Comparison(LEBranchOp, x, y); break; }
00856 if (equal(name, "primitiveGreaterThan:ifFail:")) { res = smi_Comparison(GTBranchOp, x, y); break; }
00857 if (equal(name, "primitiveGreaterThanOrEqual:ifFail:")) { res = smi_Comparison(GEBranchOp, x, y); break; }
00858 }
00859 break;
00860 case FloatArithmeticPrimitive:
00861 break;
00862 case FloatComparisonPrimitive:
00863 break;
00864 case ObjArrayPrimitive:
00865 if (equal(name, "primitiveIndexedObjectSize")) { res = array_size(); break; }
00866 if (equal(name, "primitiveIndexedObjectAt:ifFail:")) { res = array_at_ifFail(ArrayAtNode::object_at); break; }
00867 if (equal(name, "primitiveIndexedObjectAt:put:ifFail:")) { res = array_at_put_ifFail(ArrayAtPutNode::object_at_put); break; }
00868 break;
00869 case ByteArrayPrimitive:
00870 if (equal(name, "primitiveIndexedByteSize")) { res = array_size(); break; }
00871 if (equal(name, "primitiveIndexedByteAt:ifFail:")) { res = array_at_ifFail(ArrayAtNode::byte_at); break; }
00872 if (equal(name, "primitiveIndexedByteAt:put:ifFail:")) { res = array_at_put_ifFail(ArrayAtPutNode::byte_at_put); break; }
00873 break;
00874 case DoubleByteArrayPrimitive:
00875 if (equal(name, "primitiveIndexedDoubleByteSize")) { res = array_size(); break; }
00876 if (equal(name, "primitiveIndexedDoubleByteAt:ifFail:")) { res = array_at_ifFail(ArrayAtNode::double_byte_at); break; }
00877 if (equal(name, "primitiveIndexedDoubleByteCharacterAt:ifFail:")) { res = array_at_ifFail(ArrayAtNode::character_at); break; }
00878 if (equal(name, "primitiveIndexedDoubleByteAt:put:ifFail:")) { res = array_at_put_ifFail(ArrayAtPutNode::double_byte_at_put);break; }
00879 break;
00880 case BlockPrimitive:
00881 if (strncmp(name, "primitiveValue", 14) == 0) { res = block_primitiveValue(); break; }
00882 break;
00883 case NormalPrimitive:
00884 if (strncmp(name, "primitiveNew", 12) == 0) { res = obj_new(); break; }
00885 if (equal(name, "primitiveShallowCopyIfFail:ifFail:")) { res = obj_shallowCopy(); break; }
00886 if (equal(name, "primitiveEqual:")) { res = obj_equal(); break; }
00887 if (equal(name, "primitiveClass")) { res = obj_class(true); break; }
00888 if (equal(name, "primitiveClassOf:")) { res = obj_class(false); break; }
00889 if (equal(name, "primitiveHash")) { res = obj_hash(true); break; }
00890 if (equal(name, "primitiveHashOf:")) { res = obj_hash(false); break; }
00891 if (equal(name, "primitiveProxyByteAt:ifFail:")) { res = proxy_byte_at(); break; }
00892 if (equal(name, "primitiveProxyByteAt:put:ifFail:")) { res = proxy_byte_at_put(); break; }
00893 break;
00894 default:
00895 fatal1("bad primitive group %d", _pdesc->group());
00896 break;
00897 }
00898
00899 if (CompilerDebug) {
00900 cout(PrintInlining && (res != NULL))->print("%*sinlining %s %s\n", _scope->depth + 2, "", _pdesc->name(),
00901 _usingUncommonTrap ? "(unc. failure)" : (_cannotFail ? "(cannot fail)" : ""));
00902 }
00903 if (!_usingUncommonTrap && !_cannotFail) theCompiler->reporter->report_prim_failure(_pdesc);
00904 return res;
00905 }
00906
00907
00908 PrimInliner::PrimInliner(NodeBuilder* gen, primitive_desc* pdesc, MethodInterval* failure_block) {
00909 assert(pdesc, "must have a primitive desc to inline");
00910 _gen = gen;
00911 _pdesc = pdesc;
00912 _failure_block= failure_block;
00913
00914 _scope = gen->_scope;
00915 _bci = gen->bci();
00916 _exprStack = gen->_exprStack;
00917 _cannotFail = true;
00918 _params = new GrowableArray<Expr*>(number_of_parameters(), number_of_parameters(), NULL);
00919 _usingUncommonTrap = false;
00920
00921
00922 int i = number_of_parameters();
00923 int first = _exprStack->length() - i;
00924 while (i-- > 0) {
00925 _params->at_put(i, _exprStack->at(first + i));
00926 }
00927
00928 assert(_pdesc->can_fail() == (failure_block != NULL), "primitive desc & primitive usage inconsistent");
00929 }
00930
00931
00932 void PrimInliner::generate() {
00933 Expr* res = NULL;
00934 if (InlinePrims) {
00935 if (ConstantFoldPrims) { res = tryConstantFold(); }
00936 if (res == NULL) { res = tryTypeCheck(); }
00937 if (res == NULL) { res = tryInline(); }
00938 }
00939 if (res == NULL) {
00940
00941
00942 res = genCall(_pdesc->can_fail());
00943 }
00944 assert(res, "must have result expr");
00945 _exprStack->pop(_pdesc->number_of_parameters());
00946 _exprStack->push2nd(res, _scope, _bci);
00947 }
00948
00949
00950 Expr* PrimInliner::genCall(bool canFail) {
00951
00952
00953
00954
00955
00956
00957
00958 MergeNode* nlrTestPoint = _pdesc->can_perform_NLR() ? _scope->nlrTestPoint() : NULL;
00959 GrowableArray<PReg*>* args = _gen->pass_arguments(NULL, _pdesc->number_of_parameters());
00960 GrowableArray<PReg*>* exprStack = _pdesc->can_walk_stack() ? _gen->copyCurrentExprStack() : NULL;
00961 PrimNode* pcall = NodeFactory::new_PrimNode(_pdesc, nlrTestPoint, args, exprStack);
00962
00963 _gen->append(pcall);
00964
00965 BranchNode* branch = NULL;
00966 if (_failure_block != NULL && canFail) {
00967
00968 _gen->append(NodeFactory::new_ArithRCNode(new NoPReg(_scope), pcall->dest(), TestArithOp, Mark_Tag_Bit));
00969 branch = NodeFactory::new_BranchNode(NEBranchOp);
00970 _gen->append(branch);
00971 }
00972
00973
00974 SAPReg* resPReg = new SAPReg(_scope);
00975 _gen->append(NodeFactory::new_AssignNode(pcall->dst(), resPReg));
00976 Node* ok_exit = _gen->_current;
00977 Expr* resExpr = _pdesc->return_klass(resPReg, ok_exit);
00978 if (resExpr == NULL) resExpr = new UnknownExpr(resPReg, ok_exit);
00979
00980 if (branch != NULL) {
00981
00982 SAPReg* errPReg = new SAPReg(_scope);
00983 ArithRCNode* failure_exit = NodeFactory::new_ArithRCNode(errPReg, pcall->dst(), AndArithOp, ~Mark_Tag_Bit);
00984 branch->append(1, failure_exit);
00985 resExpr = merge_failure_block(ok_exit, resExpr, failure_exit, new KlassExpr(Universe::symbolKlassObj(), errPReg, failure_exit), false);
00986 }
00987
00988 return resExpr;
00989 }
00990
00991
00992 void PrimInliner::print() {
00993 std->print("a PrimInliner\n");
00994 }
00995
00996
00997 # endif