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_MathIntrinsic(Intrinsic* x) { switch (x->id()) { case vmIntrinsics::_dabs: case vmIntrinsics::_dsqrt: { assert(x->number_of_arguments() == 1, "wrong type"); LIRItem value(x->argument_at(0), this); value.load_item(); LIR_Opr dst = rlock_result(x); switch (x->id()) { case vmIntrinsics::_dsqrt: { __ sqrt(value.result(), dst, LIR_OprFact::illegalOpr); break; } case vmIntrinsics::_dabs: { __ abs(value.result(), dst, LIR_OprFact::illegalOpr); break; } } break; } case vmIntrinsics::_dlog10: // fall through case vmIntrinsics::_dlog: // fall through case vmIntrinsics::_dsin: // fall through case vmIntrinsics::_dtan: // fall through case vmIntrinsics::_dcos: { assert(x->number_of_arguments() == 1, "wrong type"); address runtime_entry = NULL; switch (x->id()) { case vmIntrinsics::_dsin: runtime_entry = CAST_FROM_FN_PTR(address, SharedRuntime::dsin); break; case vmIntrinsics::_dcos: runtime_entry = CAST_FROM_FN_PTR(address, SharedRuntime::dcos); break; case vmIntrinsics::_dtan: runtime_entry = CAST_FROM_FN_PTR(address, SharedRuntime::dtan); break; case vmIntrinsics::_dlog: runtime_entry = CAST_FROM_FN_PTR(address, SharedRuntime::dlog); break; case vmIntrinsics::_dlog10: runtime_entry = CAST_FROM_FN_PTR(address, SharedRuntime::dlog10); break; default: ShouldNotReachHere(); } LIR_Opr result = call_runtime(x->argument_at(0), runtime_entry, x->type(), NULL); set_result(x, result); } } }
// for _ladd, _lmul, _lsub, _ldiv, _lrem void LIRGenerator::do_ArithmeticOp_Long(ArithmeticOp* x) { switch (x->op()) { case Bytecodes::_lrem: case Bytecodes::_lmul: case Bytecodes::_ldiv: { if (x->op() == Bytecodes::_ldiv || x->op() == Bytecodes::_lrem) { LIRItem right(x->y(), this); right.load_item(); CodeEmitInfo* info = state_for(x); LIR_Opr item = right.result(); assert(item->is_register(), "must be"); __ cmp(lir_cond_equal, item, 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(); } // order of arguments to runtime call is reversed. LIR_Opr result = call_runtime(x->y(), x->x(), entry, x->type(), NULL); set_result(x, result); break; } case Bytecodes::_ladd: case Bytecodes::_lsub: { LIRItem left(x->x(), this); LIRItem right(x->y(), this); left.load_item(); right.load_item(); rlock_result(x); arithmetic_op_long(x->op(), x->operand(), left.result(), right.result(), NULL); break; } default: ShouldNotReachHere(); } }
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); }
// for _fadd, _fmul, _fsub, _fdiv, _frem // _dadd, _dmul, _dsub, _ddiv, _drem void LIRGenerator::do_ArithmeticOp_FPU(ArithmeticOp* x) { switch (x->op()) { case Bytecodes::_fadd: case Bytecodes::_fmul: case Bytecodes::_fsub: case Bytecodes::_fdiv: case Bytecodes::_dadd: case Bytecodes::_dmul: case Bytecodes::_dsub: case Bytecodes::_ddiv: { LIRItem left(x->x(), this); LIRItem right(x->y(), this); left.load_item(); right.load_item(); rlock_result(x); arithmetic_op_fpu(x->op(), x->operand(), left.result(), right.result(), x->is_strictfp()); } break; case Bytecodes::_frem: case Bytecodes::_drem: { address entry; switch (x->op()) { case Bytecodes::_frem: entry = CAST_FROM_FN_PTR(address, SharedRuntime::frem); break; case Bytecodes::_drem: entry = CAST_FROM_FN_PTR(address, SharedRuntime::drem); break; default: ShouldNotReachHere(); } LIR_Opr result = call_runtime(x->x(), x->y(), entry, x->type(), NULL); set_result(x, result); } break; default: ShouldNotReachHere(); } }
// _i2l, _i2f, _i2d, _l2i, _l2f, _l2d, _f2i, _f2l, _f2d, _d2i, _d2l, _d2f // _i2b, _i2c, _i2s void LIRGenerator::do_Convert(Convert* x) { switch (x->op()) { case Bytecodes::_f2l: case Bytecodes::_d2l: case Bytecodes::_d2i: case Bytecodes::_l2f: case Bytecodes::_l2d: { address entry; switch (x->op()) { case Bytecodes::_l2f: entry = CAST_FROM_FN_PTR(address, SharedRuntime::l2f); break; case Bytecodes::_l2d: entry = CAST_FROM_FN_PTR(address, SharedRuntime::l2d); break; case Bytecodes::_f2l: entry = CAST_FROM_FN_PTR(address, SharedRuntime::f2l); break; case Bytecodes::_d2l: entry = CAST_FROM_FN_PTR(address, SharedRuntime::d2l); break; case Bytecodes::_d2i: entry = CAST_FROM_FN_PTR(address, SharedRuntime::d2i); break; default: ShouldNotReachHere(); } LIR_Opr result = call_runtime(x->value(), entry, x->type(), NULL); set_result(x, result); break; } case Bytecodes::_i2f: case Bytecodes::_i2d: { LIRItem value(x->value(), this); LIR_Opr reg = rlock_result(x); // To convert an int to double, we need to load the 32-bit int // from memory into a single precision floating point register // (even numbered). Then the sparc fitod instruction takes care // of the conversion. This is a bit ugly, but is the best way to // get the int value in a single precision floating point register value.load_item(); LIR_Opr tmp = force_to_spill(value.result(), T_FLOAT); __ convert(x->op(), tmp, reg); break; } break; case Bytecodes::_i2l: case Bytecodes::_i2b: case Bytecodes::_i2c: case Bytecodes::_i2s: case Bytecodes::_l2i: case Bytecodes::_f2d: case Bytecodes::_d2f: { // inline code LIRItem value(x->value(), this); value.load_item(); LIR_Opr reg = rlock_result(x); __ convert(x->op(), value.result(), reg, false); } break; case Bytecodes::_f2i: { LIRItem value (x->value(), this); value.set_destroys_register(); value.load_item(); LIR_Opr reg = rlock_result(x); set_vreg_flag(reg, must_start_in_memory); __ convert(x->op(), value.result(), reg, false); } break; default: ShouldNotReachHere(); } }