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"); } } } }
int Compilation::emit_code_body() { // emit code Runtime1::setup_code_buffer(code(), allocator()->num_calls()); code()->initialize_oop_recorder(env()->oop_recorder()); _masm = new C1_MacroAssembler(code()); _masm->set_oop_recorder(env()->oop_recorder()); LIR_Assembler lir_asm(this); lir_asm.emit_code(hir()->code()); CHECK_BAILOUT_(0); emit_code_epilog(&lir_asm); CHECK_BAILOUT_(0); generate_exception_handler_table(); #ifndef PRODUCT if (PrintExceptionHandlers && Verbose) { exception_handler_table()->print(); } #endif /* PRODUCT */ return frame_map()->framesize(); }
void Compilation::emit_lir() { CHECK_BAILOUT(); LIRGenerator gen(this, method()); { PhaseTraceTime timeit(_t_lirGeneration); hir()->iterate_linear_scan_order(&gen); } CHECK_BAILOUT(); { PhaseTraceTime timeit(_t_linearScan); LinearScan* allocator = new LinearScan(hir(), &gen, frame_map()); set_allocator(allocator); // Assign physical registers to LIR operands using a linear scan algorithm. allocator->do_linear_scan(); CHECK_BAILOUT(); _max_spills = allocator->max_spills(); } if (BailoutAfterLIR) { if (PrintLIR && !bailed_out()) { print_LIR(hir()->code()); } bailout("Bailing out because of -XX:+BailoutAfterLIR"); } }
void Compilation::install_code(int frame_size) { // frame_size is in 32-bit words so adjust it intptr_t words assert(frame_size == frame_map()->framesize(), "must match"); assert(in_bytes(frame_map()->framesize_in_bytes()) % sizeof(intptr_t) == 0, "must be at least pointer aligned"); _env->register_method( method(), osr_bci(), &_offsets, in_bytes(_frame_map->sp_offset_for_orig_pc()), code(), in_bytes(frame_map()->framesize_in_bytes()) / sizeof(intptr_t), debug_info_recorder()->_oopmaps, exception_handler_table(), implicit_exception_table(), compiler(), _env->comp_level(), needs_debug_information(), has_unsafe_access() ); }
void LIR_OopMapGenerator::generate() { // Initialize by iterating down the method's signature and marking // oop locals in the state assert((int) oop_map()->size() == frame_map()->num_local_names(), "just checking"); oop_map()->clear(); ciSignature* sig = ir()->method()->signature(); int idx = 0; // Handle receiver for non-static methods if (!ir()->method()->is_static()) { mark(frame_map()->name_for_argument(idx)); ++idx; } for (int i = 0; i < sig->count(); i++) { ciType* type = sig->type_at(i); if (!type->is_primitive_type()) { mark(frame_map()->name_for_argument(idx)); } idx += type->size(); } // The start block contains a Base instruction, which causes the LIR // for ref-uninit conflicts to be generated. We need to handle this // block specially so we don't traverse its "osr_entry" successor, // because we don't know how to set up the state appropriately for // that entry point. _base = ir()->start()->end()->as_Base(); // Always start iterating at the start (even for OSR compiles) merge_state(ir()->start()); BlockBegin* block = work_list_dequeue(); while (block != NULL) { oop_map()->set_from(*block->lir_oop_map()); iterate_one(block); block = work_list_dequeue(); } }
// 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); } }
void LIR_Assembler::build_frame() { _masm->build_frame(frame_map()); }