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::tryConstantFold() { // Returns the result if the primitive call has been constant folded // successfully; returns NULL otherwise. // Note: The result may be a marked oop - which has to be unmarked // before using it - and which indicates that the primitive will fail // always. if (!_pdesc->can_be_constant_folded()) { // check for Symbol>>at: before declaring failure if ((equal(_pdesc->name(), "primitiveIndexedByteAt:ifFail:") || equal(_pdesc->name(), "primitiveIndexedByteCharacterAt:ifFail:")) && parameter(0)->hasKlass() && parameter(0)->klass() == Universe::symbolKlassObj()) { // the at: primitive can be constant-folded for symbols // what if the receiver is a constant string? unfortunately, Smalltalk has // "assignable constants" like Fortran... } else { return NULL; } } // get parameters int i = number_of_parameters(); oop* args = NEW_RESOURCE_ARRAY(oop, i); while (i > 0) { i--; Expr* arg = parameter(i); if (!arg->isConstantExpr()) return NULL; args[i] = arg->constant(); } // all parameters are constants, so call primitive oop res = _pdesc->eval(args); if (res->is_mark()) { // primitive failed return primitiveFailure(unmarkSymbol(res)); } else if (res->is_mem() && !res->is_old()) { // must tenure result because nmethods aren't scavenged if (res->is_double()) { res = oopFactory::clone_double_to_oldspace(doubleOop(res)); } else { // don't know how to tenure non-doubles warning("const folding: primitive %s is returning non-tenured object", _pdesc->name()); return NULL; } } ConstPReg* constResult = new_ConstPReg(_scope, res); SAPReg* result = new SAPReg(_scope); _gen->append(NodeFactory::new_AssignNode(constResult, result)); if (CompilerDebug) cout(PrintInlining)->print("%*sconstant-folding %s --> %#x\n", _scope->depth + 2, "", _pdesc->name(), res); assert(!constResult->constant->is_mark(), "result must not be marked"); return new ConstantExpr(res, constResult, _gen->current()); }