void LIR_Assembler::move_op(LIR_Opr src, LIR_Opr dest, LIR_Opr tmp1, LIR_Opr tmp2, LIR_Opr tmp3, BasicType type, LIR_PatchCode patch_code, CodeEmitInfo* info, bool unaligned) { if (src->is_register()) { if (dest->is_register()) { assert(patch_code == lir_patch_none && info == NULL, "no patching and info allowed here"); assert(!tmp1->is_valid() && !tmp2->is_valid(), "unnecessary definition of temp operands"); reg2reg(src, dest); } else if (dest->is_stack()) { assert(patch_code == lir_patch_none && info == NULL, "no patching and info allowed here"); assert(!tmp1->is_valid() && !tmp2->is_valid(), "unnecessary definition of temp operands"); reg2stack(src,dest,type); } else if (dest->is_address()) { reg2mem(src,dest,tmp1,tmp2,tmp3,type,patch_code,info,unaligned); } else { ShouldNotReachHere(); } } else if (src->is_stack()) { assert(patch_code == lir_patch_none && info == NULL, "no patching and info allowed here"); if (dest->is_register()) { assert(!tmp1->is_valid() && !tmp2->is_valid(), "unnecessary definition of temp operands"); stack2reg(src, dest, type); } else if (dest->is_stack()) { assert(!tmp2->is_valid(),"unnecessary definition of temp operands"); stack2stack(src, dest, tmp1, type); } else { ShouldNotReachHere(); } } else if (src->is_constant()) { if (dest->is_register()) { assert(!tmp3->is_valid(),"unnecessary definition of temp operands"); const2reg(src, dest, patch_code, info, tmp1, tmp2); // patching is possible } else if (dest->is_stack()) { assert(patch_code == lir_patch_none && info == NULL, "no patching and info allowed here"); assert(!tmp3->is_valid(),"unnecessary definition of temp operands"); const2stack(src, dest, tmp1, tmp2); } else if (dest->is_address()) { assert(patch_code == lir_patch_none, "no patching allowed here"); const2mem(src, dest, tmp1, tmp2, tmp3, type, info); } else { ShouldNotReachHere(); } } else if (src->is_address()) { assert(!tmp2->is_valid(),"unnecessary definition of temp operand"); mem2reg(src, dest, tmp1, type, patch_code, info, unaligned); } else { ShouldNotReachHere(); } }
void LIR_Assembler::move_op(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_PatchCode patch_code, CodeEmitInfo* info, bool pop_fpu_stack, bool unaligned, bool wide) { if (src->is_register()) { if (dest->is_register()) { assert(patch_code == lir_patch_none && info == NULL, "no patching and info allowed here"); reg2reg(src, dest); } else if (dest->is_stack()) { assert(patch_code == lir_patch_none && info == NULL, "no patching and info allowed here"); reg2stack(src, dest, type, pop_fpu_stack); } else if (dest->is_address()) { reg2mem(src, dest, type, patch_code, info, pop_fpu_stack, wide, unaligned); } else { ShouldNotReachHere(); } } else if (src->is_stack()) { assert(patch_code == lir_patch_none && info == NULL, "no patching and info allowed here"); if (dest->is_register()) { stack2reg(src, dest, type); } else if (dest->is_stack()) { stack2stack(src, dest, type); } else { ShouldNotReachHere(); } } else if (src->is_constant()) { if (dest->is_register()) { const2reg(src, dest, patch_code, info); // patching is possible } else if (dest->is_stack()) { assert(patch_code == lir_patch_none && info == NULL, "no patching and info allowed here"); const2stack(src, dest); } else if (dest->is_address()) { assert(patch_code == lir_patch_none, "no patching allowed here"); const2mem(src, dest, type, info, wide); } else { ShouldNotReachHere(); } } else if (src->is_address()) { mem2reg(src, dest, type, patch_code, info, wide, unaligned); } else { ShouldNotReachHere(); } }
void LIR_OopMapGenerator::process_move(LIR_Op* op) { LIR_Op1* op1 = op->as_Op1(); LIR_Opr src = op1->in_opr(); LIR_Opr dst = op1->result_opr(); assert(!src->is_stack() || !dst->is_stack(), "No memory-memory moves allowed"); if ((src->is_stack() && frame_map()->is_spill_pos(src)) || (dst->is_stack() && frame_map()->is_spill_pos(dst))) { // Oops in the spill area are handled by another mechanism (see // CodeEmitInfo::record_spilled_oops) return; } if (dst->is_oop()) { assert((src->is_oop() && (src->is_stack() || src->is_register() || src->is_constant()) ) || src->is_address(), "Wrong tracking of oops/non-oops in LIR"); assert(!src->is_stack() || is_marked(src->single_stack_ix()), "Error in tracking of oop stores to stack"); if (dst->is_stack()) { mark(dst->single_stack_ix()); } else if (dst->is_register()) { if (LIRCacheLocals) { if (local_mapping()->is_cache_reg(dst)) { mark(dst); } } else { assert(local_mapping() == NULL, "expected no local mapping"); } } } else { // !dst->is_oop() // Note that dst may be an address assert(!src->is_single_stack() || !is_marked(src->single_stack_ix()), "Error in tracking of oop stores to stack"); assert(!src->is_double_stack() || !is_marked(src->double_stack_ix()), "Error in tracking of oop stores to stack"); assert(!src->is_double_stack() || !is_marked(1 + src->double_stack_ix()), "Error in tracking of oop stores to stack"); if (dst->is_stack()) { if (dst->is_single_stack()) { clear_all(dst->single_stack_ix()); } else { clear_all(dst->double_stack_ix()); clear_all(1 + dst->double_stack_ix()); } } else if (dst->is_register()) { if (LIRCacheLocals) { if (local_mapping()->is_cache_reg(dst)) { clear_all(dst); } } else { assert(local_mapping() == NULL, "expected no local mapping"); } } } }
bool FrameMap::finalize_frame(int nof_slots) { assert(nof_slots >= 0, "must be positive"); assert(_num_spills == -1, "can only be set once"); _num_spills = nof_slots; assert(_framesize == -1, "should only be calculated once"); _framesize = round_to(in_bytes(sp_offset_for_monitor_base(0)) + _num_monitors * sizeof(BasicObjectLock) + sizeof(intptr_t) + // offset of deopt orig pc frame_pad_in_bytes, StackAlignmentInBytes) / 4; int java_index = 0; for (int i = 0; i < _incoming_arguments->length(); i++) { LIR_Opr opr = _incoming_arguments->at(i); if (opr->is_stack()) { _argument_locations->at_put(java_index, in_bytes(framesize_in_bytes()) + _argument_locations->at(java_index)); } java_index += type2size[opr->type()]; } // make sure it's expressible on the platform return validate_frame(); }
void FpuStackAllocator::handle_op1(LIR_Op1* op1) { LIR_Opr in = op1->in_opr(); LIR_Opr res = op1->result_opr(); LIR_Opr new_in = in; // new operands relative to the actual fpu stack top LIR_Opr new_res = res; // Note: this switch is processed for all LIR_Op1, regardless if they have FPU-arguments, // so checks for is_float_kind() are necessary inside the cases switch (op1->code()) { case lir_return: { // FPU-Stack must only contain the (optional) fpu return value. // All remaining dead values are popped from the stack // If the input operand is a fpu-register, it is exchanged to the bottom of the stack clear_fpu_stack(in); if (in->is_fpu_register() && !in->is_xmm_register()) { new_in = to_fpu_stack_top(in); } break; } case lir_move: { if (in->is_fpu_register() && !in->is_xmm_register()) { if (res->is_xmm_register()) { // move from fpu register to xmm register (necessary for operations that // are not available in the SSE instruction set) insert_exchange(in); new_in = to_fpu_stack_top(in); pop_always(op1, in); } else if (res->is_fpu_register() && !res->is_xmm_register()) { // move from fpu-register to fpu-register: // * input and result register equal: // nothing to do // * input register is last use: // rename the input register to result register -> input register // not present on fpu-stack afterwards // * input register not last use: // duplicate input register to result register to preserve input // // Note: The LIR-Assembler does not produce any code for fpu register moves, // so input and result stack index must be equal if (fpu_num(in) == fpu_num(res)) { // nothing to do } else if (in->is_last_use()) { insert_free_if_dead(res);//, in); do_rename(in, res); } else { insert_free_if_dead(res); insert_copy(in, res); } new_in = to_fpu_stack(res); new_res = new_in; } else { // move from fpu-register to memory // input operand must be on top of stack insert_exchange(in); // create debug information here because afterwards the register may have been popped compute_debug_information(op1); new_in = to_fpu_stack_top(in); pop_if_last_use(op1, in); } } else if (res->is_fpu_register() && !res->is_xmm_register()) { // move from memory/constant to fpu register // result is pushed on the stack insert_free_if_dead(res); // create debug information before register is pushed compute_debug_information(op1); do_push(res); new_res = to_fpu_stack_top(res); } break; } case lir_neg: { if (in->is_fpu_register() && !in->is_xmm_register()) { assert(res->is_fpu_register() && !res->is_xmm_register(), "must be"); assert(in->is_last_use(), "old value gets destroyed"); insert_free_if_dead(res, in); insert_exchange(in); new_in = to_fpu_stack_top(in); do_rename(in, res); new_res = to_fpu_stack_top(res); } break; } case lir_convert: { Bytecodes::Code bc = op1->as_OpConvert()->bytecode(); switch (bc) { case Bytecodes::_d2f: case Bytecodes::_f2d: assert(res->is_fpu_register(), "must be"); assert(in->is_fpu_register(), "must be"); if (!in->is_xmm_register() && !res->is_xmm_register()) { // this is quite the same as a move from fpu-register to fpu-register // Note: input and result operands must have different types if (fpu_num(in) == fpu_num(res)) { // nothing to do new_in = to_fpu_stack(in); } else if (in->is_last_use()) { insert_free_if_dead(res);//, in); new_in = to_fpu_stack(in); do_rename(in, res); } else { insert_free_if_dead(res); insert_copy(in, res); new_in = to_fpu_stack_top(in, true); } new_res = to_fpu_stack(res); } break; case Bytecodes::_i2f: case Bytecodes::_l2f: case Bytecodes::_i2d: case Bytecodes::_l2d: assert(res->is_fpu_register(), "must be"); if (!res->is_xmm_register()) { insert_free_if_dead(res); do_push(res); new_res = to_fpu_stack_top(res); } break; case Bytecodes::_f2i: case Bytecodes::_d2i: assert(in->is_fpu_register(), "must be"); if (!in->is_xmm_register()) { insert_exchange(in); new_in = to_fpu_stack_top(in); // TODO: update registes of stub } break; case Bytecodes::_f2l: case Bytecodes::_d2l: assert(in->is_fpu_register(), "must be"); if (!in->is_xmm_register()) { insert_exchange(in); new_in = to_fpu_stack_top(in); pop_always(op1, in); } break; case Bytecodes::_i2l: case Bytecodes::_l2i: case Bytecodes::_i2b: case Bytecodes::_i2c: case Bytecodes::_i2s: // no fpu operands break; default: ShouldNotReachHere(); } break; } case lir_roundfp: { assert(in->is_fpu_register() && !in->is_xmm_register(), "input must be in register"); assert(res->is_stack(), "result must be on stack"); insert_exchange(in); new_in = to_fpu_stack_top(in); pop_if_last_use(op1, in); break; } default: { assert(!in->is_float_kind() && !res->is_float_kind(), "missed a fpu-operation"); } } op1->set_in_opr(new_in); op1->set_result_opr(new_res); }