void LIRGenerator::do_NewObjectArray(NewObjectArray* x) { LIRItem length(x->length(), this); // in case of patching (i.e., object class is not yet loaded), we need to reexecute the instruction // and therefore provide the state before the parameters have been consumed CodeEmitInfo* patching_info = NULL; if (!x->klass()->is_loaded() || PatchALot) { patching_info = state_for(x, x->state_before()); } CodeEmitInfo* info = state_for(x, x->state()); const LIR_Opr reg = result_register_for(x->type()); LIR_Opr tmp1 = FrameMap::rcx_oop_opr; LIR_Opr tmp2 = FrameMap::rsi_oop_opr; LIR_Opr tmp3 = FrameMap::rdi_oop_opr; LIR_Opr tmp4 = reg; LIR_Opr klass_reg = FrameMap::rdx_oop_opr; length.load_item_force(FrameMap::rbx_opr); LIR_Opr len = length.result(); CodeStub* slow_path = new NewObjectArrayStub(klass_reg, len, reg, info); ciObject* obj = (ciObject*) ciObjArrayKlass::make(x->klass()); if (obj == ciEnv::unloaded_ciobjarrayklass()) { BAILOUT("encountered unloaded_ciobjarrayklass due to out of memory error"); } jobject2reg_with_patching(klass_reg, obj, patching_info); __ allocate_array(reg, len, tmp1, tmp2, tmp3, tmp4, T_OBJECT, klass_reg, slow_path); LIR_Opr result = rlock_result(x); __ move(reg, result); }
void LIRGenerator::do_NewMultiArray(NewMultiArray* x) { Values* dims = x->dims(); int i = dims->length(); LIRItemList* items = new LIRItemList(dims->length(), NULL); while (i-- > 0) { LIRItem* size = new LIRItem(dims->at(i), this); items->at_put(i, size); } // need to get the info before, as the items may become invalid through item_free CodeEmitInfo* patching_info = NULL; if (!x->klass()->is_loaded() || PatchALot) { patching_info = state_for(x, x->state_before()); // cannot re-use same xhandlers for multiple CodeEmitInfos, so // clone all handlers x->set_exception_handlers(new XHandlers(x->exception_handlers())); } i = dims->length(); while (i-- > 0) { LIRItem* size = items->at(i); // if a patching_info was generated above then debug information for the state before // the call is going to be emitted. The LIRGenerator calls above may have left some values // in registers and that's been recorded in the CodeEmitInfo. In that case the items // for those values can't simply be freed if they are registers because the values // might be destroyed by store_stack_parameter. So in the case of patching, delay the // freeing of the items that already were in registers size->load_item(); store_stack_parameter (size->result(), in_ByteSize(STACK_BIAS + frame::memory_parameter_word_sp_offset * wordSize + i * sizeof(jint))); } // This instruction can be deoptimized in the slow path : use // O0 as result register. const LIR_Opr reg = result_register_for(x->type()); CodeEmitInfo* info = state_for(x, x->state()); jobject2reg_with_patching(reg, x->klass(), patching_info); LIR_Opr rank = FrameMap::O1_opr; __ move(LIR_OprFact::intConst(x->rank()), rank); LIR_Opr varargs = FrameMap::as_pointer_opr(O2); int offset_from_sp = (frame::memory_parameter_word_sp_offset * wordSize) + STACK_BIAS; __ add(FrameMap::SP_opr, LIR_OprFact::intptrConst(offset_from_sp), varargs); LIR_OprList* args = new LIR_OprList(3); args->append(reg); args->append(rank); args->append(varargs); __ call_runtime(Runtime1::entry_for(Runtime1::new_multi_array_id), LIR_OprFact::illegalOpr, reg, args, info); LIR_Opr result = rlock_result(x); __ move(reg, result); }
void LIRGenerator::do_NewMultiArray(NewMultiArray* x) { Values* dims = x->dims(); int i = dims->length(); LIRItemList* items = new LIRItemList(dims->length(), NULL); while (i-- > 0) { LIRItem* size = new LIRItem(dims->at(i), this); items->at_put(i, size); } // Evaluate state_for early since it may emit code. CodeEmitInfo* patching_info = NULL; if (!x->klass()->is_loaded() || PatchALot) { patching_info = state_for(x, x->state_before()); // cannot re-use same xhandlers for multiple CodeEmitInfos, so // clone all handlers. This is handled transparently in other // places by the CodeEmitInfo cloning logic but is handled // specially here because a stub isn't being used. x->set_exception_handlers(new XHandlers(x->exception_handlers())); } CodeEmitInfo* info = state_for(x, x->state()); i = dims->length(); while (i-- > 0) { LIRItem* size = items->at(i); size->load_nonconstant(); store_stack_parameter(size->result(), in_ByteSize(i*4)); } LIR_Opr reg = result_register_for(x->type()); jobject2reg_with_patching(reg, x->klass(), patching_info); LIR_Opr rank = FrameMap::rbx_opr; __ move(LIR_OprFact::intConst(x->rank()), rank); LIR_Opr varargs = FrameMap::rcx_opr; __ move(FrameMap::rsp_opr, varargs); LIR_OprList* args = new LIR_OprList(3); args->append(reg); args->append(rank); args->append(varargs); __ call_runtime(Runtime1::entry_for(Runtime1::new_multi_array_id), LIR_OprFact::illegalOpr, reg, args, info); LIR_Opr result = rlock_result(x); __ move(reg, result); }
void LIRGenerator::do_NewInstance(NewInstance* x) { #ifndef PRODUCT if (PrintNotLoaded && !x->klass()->is_loaded()) { tty->print_cr(" ###class not loaded at new bci %d", x->printable_bci()); } #endif CodeEmitInfo* info = state_for(x, x->state()); LIR_Opr reg = result_register_for(x->type()); LIR_Opr klass_reg = new_register(objectType); new_instance(reg, x->klass(), FrameMap::rcx_oop_opr, FrameMap::rdi_oop_opr, FrameMap::rsi_oop_opr, LIR_OprFact::illegalOpr, FrameMap::rdx_oop_opr, info); LIR_Opr result = rlock_result(x); __ move(reg, result); }
void LIRGenerator::do_NewInstance(NewInstance* x) { // This instruction can be deoptimized in the slow path : use // O0 as result register. const LIR_Opr reg = result_register_for(x->type()); if (PrintNotLoaded && !x->klass()->is_loaded()) { tty->print_cr(" ###class not loaded at new bci %d", x->bci()); } CodeEmitInfo* info = state_for(x, x->state()); LIR_Opr tmp1 = FrameMap::G1_oop_opr; LIR_Opr tmp2 = FrameMap::G3_oop_opr; LIR_Opr tmp3 = FrameMap::G4_oop_opr; LIR_Opr tmp4 = FrameMap::O1_oop_opr; LIR_Opr klass_reg = FrameMap::G5_oop_opr; new_instance(reg, x->klass(), tmp1, tmp2, tmp3, tmp4, klass_reg, info); LIR_Opr result = rlock_result(x); __ move(reg, result); }
void LIRGenerator::do_Return(Return* x) { if (x->type()->is_void()) { if (x->is_synchronized()) { emit()->return_op_prolog(x->monitor_no()); } emit()->return_op(LIR_OprFact::illegalOpr); } else { RInfo reg = result_register_for(x->type())->rinfo(); LIRItem result(x->result(), this); result.handle_float_kind(); if (x->is_synchronized()) { emit()->return_op_prolog(x->monitor_no()); } result.load_item_force(reg); emit()->return_op(result.result()); } set_no_result(x); }
void LIRGenerator::do_NewTypeArray(NewTypeArray* x) { LIRItem length(x->length(), this); length.load_item(); LIR_Opr reg = result_register_for(x->type()); LIR_Opr tmp1 = FrameMap::G1_oop_opr; LIR_Opr tmp2 = FrameMap::G3_oop_opr; LIR_Opr tmp3 = FrameMap::G4_oop_opr; LIR_Opr tmp4 = FrameMap::O1_oop_opr; LIR_Opr klass_reg = FrameMap::G5_oop_opr; LIR_Opr len = length.result(); BasicType elem_type = x->elt_type(); __ oop2reg(ciTypeArrayKlass::make(elem_type)->encoding(), klass_reg); CodeEmitInfo* info = state_for(x, x->state()); CodeStub* slow_path = new NewTypeArrayStub(klass_reg, len, reg, info); __ allocate_array(reg, len, tmp1, tmp2, tmp3, tmp4, elem_type, klass_reg, slow_path); LIR_Opr result = rlock_result(x); __ move(reg, result); }
// for _ladd, _lmul, _lsub, _ldiv, _lrem void LIRGenerator::do_ArithmeticOp_Long(ArithmeticOp* x) { if (x->op() == Bytecodes::_ldiv || x->op() == Bytecodes::_lrem ) { // long division is implemented as a direct call into the runtime LIRItem left(x->x(), this); LIRItem right(x->y(), this); // the check for division by zero destroys the right operand right.set_destroys_register(); BasicTypeList signature(2); signature.append(T_LONG); signature.append(T_LONG); CallingConvention* cc = frame_map()->c_calling_convention(&signature); // check for division by zero (destroys registers of right operand!) CodeEmitInfo* info = state_for(x); const LIR_Opr result_reg = result_register_for(x->type()); left.load_item_force(cc->at(1)); right.load_item(); __ move(right.result(), cc->at(0)); __ cmp(lir_cond_equal, right.result(), LIR_OprFact::longConst(0)); __ branch(lir_cond_equal, T_LONG, new DivByZeroStub(info)); address entry; switch (x->op()) { case Bytecodes::_lrem: entry = CAST_FROM_FN_PTR(address, SharedRuntime::lrem); break; // check if dividend is 0 is done elsewhere case Bytecodes::_ldiv: entry = CAST_FROM_FN_PTR(address, SharedRuntime::ldiv); break; // check if dividend is 0 is done elsewhere case Bytecodes::_lmul: entry = CAST_FROM_FN_PTR(address, SharedRuntime::lmul); break; default: ShouldNotReachHere(); } LIR_Opr result = rlock_result(x); __ call_runtime_leaf(entry, getThreadTemp(), result_reg, cc->args()); __ move(result_reg, result); } else if (x->op() == Bytecodes::_lmul) { // missing test if instr is commutative and if we should swap LIRItem left(x->x(), this); LIRItem right(x->y(), this); // right register is destroyed by the long mul, so it must be // copied to a new register. right.set_destroys_register(); left.load_item(); right.load_item(); LIR_Opr reg = FrameMap::long0_opr; arithmetic_op_long(x->op(), reg, left.result(), right.result(), NULL); LIR_Opr result = rlock_result(x); __ move(reg, result); } else { // missing test if instr is commutative and if we should swap LIRItem left(x->x(), this); LIRItem right(x->y(), this); left.load_item(); // don't load constants to save register right.load_nonconstant(); rlock_result(x); arithmetic_op_long(x->op(), x->operand(), left.result(), right.result(), NULL); } }