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"); } } } }
LIR_Opr result() { assert(_destroys_register==not_destroyed||(!_result->is_register()||_result->is_virtual()), "shouldn't use set_destroys_register with physical regsiters"); if(_destroys_register==awaiting_copy&&_result->is_register()){ LIR_Opr new_result=_gen->new_register(type())->set_destroyed(); gen()->lir()->move(_result, new_result); _destroys_register = destroyed; _result=new_result; } return _result; }
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(); } }
LIR_Opr result() { assert(!_destroys_register || (!_result->is_register() || _result->is_virtual()), "shouldn't use set_destroys_register with physical regsiters"); if (_destroys_register && _result->is_register()) { if (_new_result->is_illegal()) { _new_result = _gen->new_register(type()); gen()->lir()->move(_result, _new_result); } return _new_result; } else { return _result; } return _result; }
void LIRGenerator::put_Object_unsafe(LIR_Opr src, LIR_Opr offset, LIR_Opr data, BasicType type, bool is_volatile) { if (is_volatile && type == T_LONG) { LIR_Address* addr = new LIR_Address(src, offset, T_DOUBLE); LIR_Opr tmp = new_register(T_DOUBLE); LIR_Opr spill = new_register(T_DOUBLE); set_vreg_flag(spill, must_start_in_memory); __ move(data, spill); __ move(spill, tmp); __ move(tmp, addr); } else { LIR_Address* addr = new LIR_Address(src, offset, type); bool is_obj = (type == T_ARRAY || type == T_OBJECT); if (is_obj) { // Do the pre-write barrier, if any. pre_barrier(LIR_OprFact::address(addr), false, NULL); __ move(data, addr); assert(src->is_register(), "must be register"); // Seems to be a precise address post_barrier(LIR_OprFact::address(addr), data); } else { __ move(data, addr); } } }
// Version that _does_ generate a load of the previous value from addr. // addr (the address of the field to be read) must be a LIR_Address // pre_val (a temporary register) must be a register; G1PreBarrierStub(LIR_Opr addr, LIR_Opr pre_val, LIR_PatchCode patch_code, CodeEmitInfo* info) : _addr(addr), _pre_val(pre_val), _do_load(true), _patch_code(patch_code), _info(info) { assert(_pre_val->is_register(), "should be temporary register"); assert(_addr->is_address(), "should be the address of the field"); }
bool LocalMapping::is_cache_reg(LIR_Opr opr) const { if (opr->is_register()) { return is_cache_reg(opr->rinfo()); } else { return false; } }
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 set_result(Value x, LIR_Opr opr) { assert(opr->is_valid(), "must set to valid value"); assert(x->operand()->is_illegal(), "operand should never change"); assert(!opr->is_register() || opr->is_virtual(), "should never set result to a physical register"); x->set_operand(opr); assert(opr == x->operand(), "must be"); if (opr->is_virtual()) { _instruction_for_operand.at_put_grow(opr->vreg_number(), x, NULL); } }
// 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 traverse(BlockBegin* bb, LIR_OpList* inst) { int length = inst->length(); for (int i = 0; i < length; i++) { LIR_Op* op = inst->at(i); _state.visit(op); for (LIR_OpVisitState::OprMode mode = LIR_OpVisitState::firstMode; mode < LIR_OpVisitState::numModes; mode = (LIR_OpVisitState::OprMode)(mode + 1)) { for (int i = 0; i < _state.opr_count(mode); i++) { LIR_Opr opr = _state.opr_at(mode, i); if (opr->is_register()) { _info->lock(opr->as_rinfo()); } } } if (_state.has_call()) { _had_call = true; } } }
// Version that _does not_ generate load of the previous value; the // previous value is assumed to have already been loaded into pre_val. G1PreBarrierStub(LIR_Opr pre_val) : _addr(LIR_OprFact::illegalOpr), _pre_val(pre_val), _do_load(false), _patch_code(lir_patch_none), _info(NULL) { assert(_pre_val->is_register(), "should be a register"); }