void LIRGenerator::do_Convert(Convert* x) { // flags that vary for the different operations and different SSE-settings bool fixed_input, fixed_result, round_result, needs_stub; switch (x->op()) { case Bytecodes::_i2l: // fall through case Bytecodes::_l2i: // fall through case Bytecodes::_i2b: // fall through case Bytecodes::_i2c: // fall through case Bytecodes::_i2s: fixed_input = false; fixed_result = false; round_result = false; needs_stub = false; break; case Bytecodes::_f2d: fixed_input = UseSSE == 1; fixed_result = false; round_result = false; needs_stub = false; break; case Bytecodes::_d2f: fixed_input = false; fixed_result = UseSSE == 1; round_result = UseSSE < 1; needs_stub = false; break; case Bytecodes::_i2f: fixed_input = false; fixed_result = false; round_result = UseSSE < 1; needs_stub = false; break; case Bytecodes::_i2d: fixed_input = false; fixed_result = false; round_result = false; needs_stub = false; break; case Bytecodes::_f2i: fixed_input = false; fixed_result = false; round_result = false; needs_stub = true; break; case Bytecodes::_d2i: fixed_input = false; fixed_result = false; round_result = false; needs_stub = true; break; case Bytecodes::_l2f: fixed_input = false; fixed_result = UseSSE >= 1; round_result = UseSSE < 1; needs_stub = false; break; case Bytecodes::_l2d: fixed_input = false; fixed_result = UseSSE >= 2; round_result = UseSSE < 2; needs_stub = false; break; case Bytecodes::_f2l: fixed_input = true; fixed_result = true; round_result = false; needs_stub = false; break; case Bytecodes::_d2l: fixed_input = true; fixed_result = true; round_result = false; needs_stub = false; break; default: ShouldNotReachHere(); } LIRItem value(x->value(), this); value.load_item(); LIR_Opr input = value.result(); LIR_Opr result = rlock(x); // arguments of lir_convert LIR_Opr conv_input = input; LIR_Opr conv_result = result; ConversionStub* stub = NULL; if (fixed_input) { conv_input = fixed_register_for(input->type()); __ move(input, conv_input); } assert(fixed_result == false || round_result == false, "cannot set both"); if (fixed_result) { conv_result = fixed_register_for(result->type()); } else if (round_result) { result = new_register(result->type()); set_vreg_flag(result, must_start_in_memory); } if (needs_stub) { stub = new ConversionStub(x->op(), conv_input, conv_result); } __ convert(x->op(), conv_input, conv_result, stub); if (result != conv_result) { __ move(conv_result, result); } assert(result->is_virtual(), "result must be virtual register"); set_result(x, result); }
void LIRGenerator::do_If(If* x) { assert(x->number_of_sux() == 2, "inconsistency"); ValueTag tag = x->x()->type()->tag(); bool is_safepoint = x->is_safepoint(); If::Condition cond = x->cond(); LIRItem xitem(x->x(), this); LIRItem yitem(x->y(), this); LIRItem* xin = &xitem; LIRItem* yin = &yitem; if (tag == longTag) { // for longs, only conditions "eql", "neq", "lss", "geq" are valid; // mirror for other conditions if (cond == If::gtr || cond == If::leq) { cond = Instruction::mirror(cond); xin = &yitem; yin = &xitem; } xin->set_destroys_register(); } xin->load_item(); if (tag == longTag && yin->is_constant() && yin->get_jlong_constant() == 0 && (cond == If::eql || cond == If::neq)) { // inline long zero yin->dont_load_item(); } else if (tag == longTag || tag == floatTag || tag == doubleTag) { // longs cannot handle constants at right side yin->load_item(); } else { yin->dont_load_item(); } // add safepoint before generating condition code so it can be recomputed if (x->is_safepoint()) { // increment backedge counter if needed increment_backedge_counter(state_for(x, x->state_before()), x->profiled_bci()); __ safepoint(LIR_OprFact::illegalOpr, state_for(x, x->state_before())); } set_no_result(x); LIR_Opr left = xin->result(); LIR_Opr right = yin->result(); __ cmp(lir_cond(cond), left, right); // Generate branch profiling. Profiling code doesn't kill flags. profile_branch(x, cond); move_to_phi(x->state()); if (x->x()->type()->is_float_kind()) { __ branch(lir_cond(cond), right->type(), x->tsux(), x->usux()); } else { __ branch(lir_cond(cond), right->type(), x->tsux()); } assert(x->default_sux() == x->fsux(), "wrong destination above"); __ jump(x->default_sux()); }
void LIR_Assembler::roundfp_op(LIR_Opr src, LIR_Opr tmp, LIR_Opr dest, bool pop_fpu_stack) { assert((src->is_single_fpu() && dest->is_single_stack()) || (src->is_double_fpu() && dest->is_double_stack()), "round_fp: rounds register -> stack location"); reg2stack (src, dest, src->type(), pop_fpu_stack); }
FrameMap::FrameMap(ciMethod* method, int monitors, int reserved_argument_area_size) { assert(_init_done, "should already be completed"); _framesize = -1; _num_spills = -1; assert(monitors >= 0, "not set"); _num_monitors = monitors; assert(reserved_argument_area_size >= 0, "not set"); _reserved_argument_area_size = MAX2(4, reserved_argument_area_size) * BytesPerWord; _argcount = method->arg_size(); _argument_locations = new intArray(_argcount, -1); _incoming_arguments = java_calling_convention(signature_type_array_for(method), false); _oop_map_arg_count = _incoming_arguments->reserved_stack_slots(); int java_index = 0; for (int i = 0; i < _incoming_arguments->length(); i++) { LIR_Opr opr = _incoming_arguments->at(i); if (opr->is_address()) { LIR_Address* address = opr->as_address_ptr(); _argument_locations->at_put(java_index, address->disp() - STACK_BIAS); _incoming_arguments->args()->at_put(i, LIR_OprFact::stack(java_index, as_BasicType(as_ValueType(address->type())))); } java_index += type2size[opr->type()]; } }
// Returns if item is an int constant that can be represented by a simm13 static bool is_simm13(LIR_Opr item) { if (item->is_constant() && item->type() == T_INT) { return Assembler::is_simm13(item->as_constant_ptr()->as_jint()); } else { return false; } }
void LIRGenerator::store_stack_parameter (LIR_Opr item, ByteSize offset_from_sp) { BasicType t = item->type(); LIR_Opr sp_opr = FrameMap::SP_opr; if ((t == T_LONG || t == T_DOUBLE) && ((in_bytes(offset_from_sp) - STACK_BIAS) % 8 != 0)) { __ unaligned_move(item, new LIR_Address(sp_opr, in_bytes(offset_from_sp), t)); } else { __ move(item, new LIR_Address(sp_opr, in_bytes(offset_from_sp), t)); } }
LIR_Opr LocalMapping::get_cache_reg(LIR_Opr opr) const { RInfo reg; if (opr->is_single_stack()) { reg = get_cache_reg(opr->single_stack_ix()); } else if (opr->is_double_stack() && CacheDoubleWord) { reg = get_cache_reg(opr->double_stack_ix()); } if (reg.is_illegal()) { return LIR_OprFact::illegalOpr; } switch (opr->type()) { case T_INT: case T_OBJECT: if (!reg.is_word()) { return LIR_OprFact::illegalOpr; } break; case T_FLOAT: if (!reg.is_float()) { return LIR_OprFact::illegalOpr; } break; case T_DOUBLE: if (!reg.is_double()) { return LIR_OprFact::illegalOpr; } break; case T_LONG: if (!reg.is_long()) { return LIR_OprFact::illegalOpr; } break; } return LIR_OprFact::rinfo(reg, opr->type()); }
CallingConvention* FrameMap::c_calling_convention(const BasicTypeArray* signature) { // compute the size of the arguments first. The signature array // that java_calling_convention takes includes a T_VOID after double // work items but our signatures do not. int i; int sizeargs = 0; for (i = 0; i < signature->length(); i++) { sizeargs += type2size[signature->at(i)]; } BasicType* sig_bt = NEW_RESOURCE_ARRAY(BasicType, sizeargs); VMRegPair* regs = NEW_RESOURCE_ARRAY(VMRegPair, sizeargs); int sig_index = 0; for (i = 0; i < sizeargs; i++, sig_index++) { sig_bt[i] = signature->at(sig_index); if (sig_bt[i] == T_LONG || sig_bt[i] == T_DOUBLE) { sig_bt[i + 1] = T_VOID; i++; } } intptr_t out_preserve = SharedRuntime::c_calling_convention(sig_bt, regs, NULL, sizeargs); LIR_OprList* args = new LIR_OprList(signature->length()); for (i = 0; i < sizeargs;) { BasicType t = sig_bt[i]; assert(t != T_VOID, "should be skipping these"); // C calls are always outgoing bool outgoing = true; LIR_Opr opr = map_to_opr(t, regs + i, outgoing); // they might be of different types if for instance floating point // values are passed in cpu registers, but the sizes must match. assert(type2size[opr->type()] == type2size[t], "type mismatch"); args->append(opr); if (opr->is_address()) { LIR_Address* addr = opr->as_address_ptr(); out_preserve = MAX2(out_preserve, (intptr_t)(addr->disp() - STACK_BIAS) / 4); } i += type2size[t]; } assert(args->length() == signature->length(), "size mismatch"); out_preserve += SharedRuntime::out_preserve_stack_slots(); update_reserved_argument_area_size(out_preserve * BytesPerWord); return new CallingConvention(args, out_preserve); }
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 LIRGenerator::store_stack_parameter (LIR_Opr item, ByteSize offset_from_sp) { BasicType type = item->type(); __ store(item, new LIR_Address(FrameMap::rsp_opr, in_bytes(offset_from_sp), type)); }
void LIRGenerator::do_If(If* x) { assert(x->number_of_sux() == 2, "inconsistency"); ValueTag tag = x->x()->type()->tag(); LIRItem xitem(x->x(), this); LIRItem yitem(x->y(), this); LIRItem* xin = &xitem; LIRItem* yin = &yitem; If::Condition cond = x->cond(); if (tag == longTag) { // for longs, only conditions "eql", "neq", "lss", "geq" are valid; // mirror for other conditions if (cond == If::gtr || cond == If::leq) { // swap inputs cond = Instruction::mirror(cond); xin = &yitem; yin = &xitem; } xin->set_destroys_register(); } LIR_Opr left = LIR_OprFact::illegalOpr; LIR_Opr right = LIR_OprFact::illegalOpr; xin->load_item(); left = xin->result(); if (is_simm13(yin->result())) { // inline int constants which are small enough to be immediate operands right = LIR_OprFact::value_type(yin->value()->type()); } else if (tag == longTag && yin->is_constant() && yin->get_jlong_constant() == 0 && (cond == If::eql || cond == If::neq)) { // inline long zero right = LIR_OprFact::value_type(yin->value()->type()); } else if (tag == objectTag && yin->is_constant() && (yin->get_jobject_constant()->is_null_object())) { right = LIR_OprFact::value_type(yin->value()->type()); } else { yin->load_item(); right = yin->result(); } set_no_result(x); // add safepoint before generating condition code so it can be recomputed if (x->is_safepoint()) { // increment backedge counter if needed increment_backedge_counter(state_for(x, x->state_before())); __ safepoint(new_register(T_INT), state_for(x, x->state_before())); } __ cmp(lir_cond(cond), left, right); profile_branch(x, cond); move_to_phi(x->state()); if (x->x()->type()->is_float_kind()) { __ branch(lir_cond(cond), right->type(), x->tsux(), x->usux()); } else { __ branch(lir_cond(cond), right->type(), x->tsux()); } assert(x->default_sux() == x->fsux(), "wrong destination above"); __ jump(x->default_sux()); }