Expr* PrimInliner::obj_new() { // replace generic allocation primitive by size-specific primitive, if possible Expr* rcvr = parameter(0); if (!rcvr->isConstantExpr() || !rcvr->constant()->is_klass()) return NULL; Klass* klass = klassOop(rcvr->constant())->klass_part(); // class being instantiated if (klass->oop_is_indexable()) return NULL; // would fail (extremely unlikely) int size = klass->non_indexable_size(); // size in words if (klass->can_inline_allocation()) { // These special compiler primitives only work for memOop klasses int number_of_instance_variables = size - memOopDesc::header_size(); switch (number_of_instance_variables) { case 0: _pdesc = primitives::new0(); break; case 1: _pdesc = primitives::new1(); break; case 2: _pdesc = primitives::new2(); break; case 3: _pdesc = primitives::new3(); break; case 4: _pdesc = primitives::new4(); break; case 5: _pdesc = primitives::new5(); break; case 6: _pdesc = primitives::new6(); break; case 7: _pdesc = primitives::new7(); break; case 8: _pdesc = primitives::new8(); break; case 9: _pdesc = primitives::new9(); break; default: ; // use generic primitives } } Expr* u = genCall(true); return new KlassExpr(klass->as_klassOop(), u->preg(), u->node()); }
Expr* PrimInliner::array_size() { assert(_failure_block == NULL, "primitive must have no failure block"); assert_receiver(); // parameters & result registers Expr* array = parameter(0); Klass* klass = array->klass()->klass_part(); int lenOffs = klass->non_indexable_size(); // get size SAPReg* res = new SAPReg(_scope); _gen->append(NodeFactory::new_LoadOffsetNode(res, array->preg(), lenOffs, true)); return new KlassExpr(smiKlassObj, res, _gen->_current); }
Expr* PrimInliner::array_at_put_ifFail(ArrayAtPutNode::AccessType access_type) { assert_failure_block(); assert_receiver(); // parameters & result registers Expr* array = parameter(0); Expr* index = parameter(1); Expr* element = parameter(2); SAPReg* resPReg = new SAPReg(_scope); // holds the result if primitive didn't fail SAPReg* errPReg = new SAPReg(_scope); // holds the error message if primitive failed Klass* klass = array->klass()->klass_part(); int lenOffs = klass->non_indexable_size(); int arrOffs = lenOffs + 1; bool storeCheck = (access_type == ArrayAtPutNode::object_at_put) && element->needsStoreCheck(); if (access_type == ArrayAtPutNode::object_at_put) { // make sure blocks stored into array are created _gen->materialize(element->preg(), NULL); } // atPut node ArrayAtPutNode* atPut = NodeFactory::new_ArrayAtPutNode( access_type, array->preg(), index->preg(), index->is_smi(), element->preg(), element->is_smi(), NULL, errPReg, arrOffs, lenOffs, storeCheck ); _gen->append(atPut); // continuation Expr* resExpr = array; if (atPut->canFail()) { if (shouldUseUncommonTrap()) { // uncommon branch instead of failure code atPut->append(1, NodeFactory::new_UncommonNode(_gen->copyCurrentExprStack(), _bci /*_failure_block->begin_bci()*/)); } else { // append failure code NopNode* err = NodeFactory::new_NopNode(); atPut->append(1, err); Expr* errExpr = new KlassExpr(Universe::symbolKlassObj(), errPReg, atPut); resExpr = merge_failure_block(atPut, resExpr, err, errExpr, true); } } return resExpr; }
Expr* PrimInliner::array_at_ifFail(ArrayAtNode::AccessType access_type) { assert_failure_block(); assert_receiver(); // parameters & result registers Expr* array = parameter(0); Expr* index = parameter(1); SAPReg* resPReg = new SAPReg(_scope); // holds the result if primitive didn't fail SAPReg* errPReg = new SAPReg(_scope); // holds the error message if primitive failed Klass* klass = array->klass()->klass_part(); int lenOffs = klass->non_indexable_size(); int arrOffs = lenOffs + 1; // at node ArrayAtNode* at = NodeFactory::new_ArrayAtNode( access_type, array->preg(), index->preg(), index->is_smi(), resPReg, errPReg, arrOffs, lenOffs ); _gen->append(at); // continuation Expr* resExpr; switch (access_type) { case ArrayAtNode::byte_at : // fall through case ArrayAtNode::double_byte_at: resExpr = new KlassExpr(Universe::smiKlassObj(), resPReg, at); break; case ArrayAtNode::character_at : resExpr = new KlassExpr(Universe::characterKlassObj(), resPReg, at); break; case ArrayAtNode::object_at : resExpr = new UnknownExpr(resPReg, at); break; default : ShouldNotReachHere(); } if (at->canFail()) { if (shouldUseUncommonTrap()) { // uncommon branch instead of failure code at->append(1, NodeFactory::new_UncommonNode(_gen->copyCurrentExprStack(), _bci /*_failure_block->begin_bci()*/)); } else { // append failure code NopNode* err = NodeFactory::new_NopNode(); at->append(1, err); Expr* errExpr = new KlassExpr(Universe::symbolKlassObj(), errPReg, at); resExpr = merge_failure_block(at, resExpr, err, errExpr, false); } } return resExpr; }