/* * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 2017 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. *
*/
// "lock" stores the address of the monitor stack slot, so this is not an oop.
LIR_Opr lock = new_register(T_INT);
CodeEmitInfo* info_for_exception = NULL; if (x->needs_null_check()) {
info_for_exception = state_for (x);
} // This CodeEmitInfo must not have the xhandlers because here the // object is already locked (xhandlers expect object to be unlocked).
CodeEmitInfo* info = state_for (x, x->state(), true);
monitor_enter(obj.result(), lock, syncTempOpr(), LIR_OprFact::illegalOpr,
x->monitor_no(), info_for_exception, info);
}
// for _ladd, _lmul, _lsub, _ldiv, _lrem void LIRGenerator::do_ArithmeticOp_Long(ArithmeticOp* x) { if (x->op() == Bytecodes::_ldiv || x->op() == Bytecodes::_lrem) { // Use shifts if divisor is a power of 2 otherwise use DSGR instruction. // Instruction: DSGR R1, R2 // input : R1+1: dividend (R1, R1+1 designate a register pair, R1 must be even) // R2: divisor // // output: R1+1: quotient // R1: remainder // // Register selection: R1: Z_R10 // R1+1: Z_R11 // R2: to be chosen by register allocator (linear scan)
// R1, and R1+1 will be destroyed.
LIRItem right(x->y(), this);
LIRItem left(x->x() , this); // Visit left second, so that the is_register test is valid.
// Call state_for before load_item_force because state_for may // force the evaluation of other instructions that are needed for // correct debug info. Otherwise the live range of the fix // register might be too long.
CodeEmitInfo* info = state_for (x);
if (!ImplicitDiv0Checks) {
__ cmp(lir_cond_equal, right.result(), LIR_OprFact::longConst(0));
__ branch(lir_cond_equal, new DivByZeroStub(info)); // Idiv/irem cannot trap (passing info would generate an assertion).
info = NULL;
}
// for: _iadd, _imul, _isub, _idiv, _irem void LIRGenerator::do_ArithmeticOp_Int(ArithmeticOp* x) { if (x->op() == Bytecodes::_idiv || x->op() == Bytecodes::_irem) { // Use shifts if divisor is a power of 2 otherwise use DSGFR instruction. // Instruction: DSGFR R1, R2 // input : R1+1: dividend (R1, R1+1 designate a register pair, R1 must be even) // R2: divisor // // output: R1+1: quotient // R1: remainder // // Register selection: R1: Z_R10 // R1+1: Z_R11 // R2: To be chosen by register allocator (linear scan).
// R1, and R1+1 will be destroyed.
LIRItem right(x->y(), this);
LIRItem left(x->x() , this); // Visit left second, so that the is_register test is valid.
// Call state_for before load_item_force because state_for may // force the evaluation of other instructions that are needed for // correct debug info. Otherwise the live range of the fix // register might be too long.
CodeEmitInfo* info = state_for (x);
if (!ImplicitDiv0Checks) {
__ cmp(lir_cond_equal, right.result(), LIR_OprFact::intConst(0));
__ branch(lir_cond_equal, new DivByZeroStub(info)); // Idiv/irem cannot trap (passing info would generate an assertion).
info = NULL;
}
if (result_reg != result) {
__ move(result_reg, result);
}
} else {
LIRItem left(x->x(), this);
LIRItem right(x->y(), this);
LIRItem* left_arg = &left;
LIRItem* right_arg = &right; if (x->is_commutative() && left.is_stack() && right.is_register()) { // swap them if left is real stack (or cached) and right is real register(not cached)
left_arg = &right;
right_arg = &left;
}
left_arg->load_item();
// Do not need to load right, as we can handle stack and constants. if (x->op() == Bytecodes::_imul) { bool use_tmp = false; if (right_arg->is_constant()) { int iconst = right_arg->get_jint_constant(); if (is_power_of_2(iconst - 1) || is_power_of_2(iconst + 1)) {
use_tmp = true;
}
}
right_arg->dont_load_item();
LIR_Opr tmp = LIR_OprFact::illegalOpr; if (use_tmp) {
tmp = new_register(T_INT);
}
rlock_result(x);
void LIRGenerator::do_ArithmeticOp(ArithmeticOp* x) { // If an operand with use count 1 is the left operand, then it is // likely that no move for 2-operand-LIR-form is necessary. if (x->is_commutative() && x->y()->as_Constant() == NULL && x->x()->use_count() > x->y()->use_count()) {
x->swap_operands();
}
ValueTag tag = x->type()->tag();
assert(x->x()->type()->tag() == tag && x->y()->type()->tag() == tag, "wrong parameters"); switch (tag) { case floatTag: case doubleTag: do_ArithmeticOp_FPU(x); return; case longTag: do_ArithmeticOp_Long(x); return; case intTag: do_ArithmeticOp_Int(x); return; default:
ShouldNotReachHere();
}
}
// _ishl, _lshl, _ishr, _lshr, _iushr, _lushr void LIRGenerator::do_ShiftOp(ShiftOp* x) { // count must always be in rcx
LIRItem value(x->x(), this);
LIRItem count(x->y(), this);
// _iand, _land, _ior, _lor, _ixor, _lxor void LIRGenerator::do_LogicOp(LogicOp* x) { // IF an operand with use count 1 is the left operand, then it is // likely that no move for 2-operand-LIR-form is necessary. if (x->is_commutative() && x->y()->as_Constant() == NULL && x->x()->use_count() > x->y()->use_count()) {
x->swap_operands();
}
LIR_Opr LIRGenerator::atomic_xchg(BasicType type, LIR_Opr addr, LIRItem& value) {
Unimplemented(); // Currently not supported on this platform. return LIR_OprFact::illegalOpr;
}
void LIRGenerator::do_MathIntrinsic(Intrinsic* x) { switch (x->id()) { case vmIntrinsics::_dabs: case vmIntrinsics::_dsqrt: case vmIntrinsics::_dsqrt_strict: {
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: case vmIntrinsics::_dsqrt_strict: {
__ sqrt(value.result(), dst, LIR_OprFact::illegalOpr); break;
} case vmIntrinsics::_dabs: {
__ abs(value.result(), dst, LIR_OprFact::illegalOpr); break;
} default:
ShouldNotReachHere();
} break;
} case vmIntrinsics::_dsin: // fall through case vmIntrinsics::_dcos: // fall through case vmIntrinsics::_dtan: // fall through case vmIntrinsics::_dlog: // fall through case vmIntrinsics::_dlog10: // fall through case vmIntrinsics::_dexp: {
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; case vmIntrinsics::_dexp:
runtime_entry = CAST_FROM_FN_PTR(address, SharedRuntime::dexp); break; default:
ShouldNotReachHere();
}
// Copy stubs possibly call C code, e.g. G1 barriers, so we need to reserve room // for the C ABI (see frame::z_abi_160).
BasicTypeArray sig; // Empty signature is precise enough.
frame_map()->c_calling_convention(&sig);
// Make all state_for calls early since they can emit code.
CodeEmitInfo* info = state_for (x, x->state());
LIR_Opr result = rlock_result(x);
__ move(reg, result);
}
void LIRGenerator::do_NewObjectArray(NewObjectArray* x) { // Evaluate state_for early since it may emit code.
CodeEmitInfo* info = state_for (x, x->state()); // In case of patching (i.e., object class is not yet loaded), we need to reexecute the instruction // and therefore provide the state before the parameters have been consumed.
CodeEmitInfo* patching_info = NULL; if (!x->klass()->is_loaded() || PatchALot) {
patching_info = state_for (x, x->state_before());
}
CodeStub* slow_path = new NewObjectArrayStub(klass_reg, len, reg, info);
ciKlass* obj = ciObjArrayKlass::make(x->klass()); if (obj == ciEnv::unloaded_ciobjarrayklass()) {
BAILOUT("encountered unloaded_ciobjarrayklass due to out of memory error");
}
klass2reg_with_patching(klass_reg, obj, patching_info);
__ allocate_array(reg, len, tmp1, tmp2, tmp3, tmp4, T_OBJECT, klass_reg, slow_path);
LIR_Opr result = rlock_result(x);
__ move(reg, result);
}
void LIRGenerator::do_NewMultiArray(NewMultiArray* x) {
Values* dims = x->dims(); int i = dims->length();
LIRItemList* items = new LIRItemList(i, i, 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 (NOTE: Usually this is handled transparently // by the CodeEmitInfo cloning logic in CodeStub constructors but // is done explicitly 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(32); // FrameMap::_reserved_argument_area_size includes the dimensions varargs, because // it's initialized to hir()->max_stack() when the FrameMap is created.
store_stack_parameter(size->result(), in_ByteSize(i*sizeof(jint) + FrameMap::first_available_sp_in_frame));
}
CodeEmitInfo* patching_info = NULL; if (!x->klass()->is_loaded() || (PatchALot && !x->is_incompatible_class_change_check() && !x->is_invokespecial_receiver_check())) { // Must do this before locking the destination register as an oop register, // and before the obj is loaded (the latter is for deoptimization).
patching_info = state_for (x, x->state_before());
}
obj.load_item();
// info for exceptions
CodeEmitInfo* info_for_exception =
(x->needs_exception_state() ? state_for(x) :
state_for(x, x->state_before(), true/*ignore_xhandler*/));
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(); // TODO: don't load long constants != 0L if (tag == longTag && yin->is_constant() && yin->get_jlong_constant() == 0 && (cond == If::eql || cond == If::neq)) { // inline long zero
yin->dont_load_item();
} elseif (tag == longTag || tag == floatTag || tag == doubleTag) { // Longs cannot handle constants at right side.
yin->load_item();
} else {
yin->dont_load_item();
}
LIR_Opr left = xin->result();
LIR_Opr 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_conditionally(lir_cond(cond), left, right, state_for(x, x->state_before()),
x->tsux()->bci(), x->fsux()->bci(), x->profiled_bci()); // Use safepoint_poll_register() instead of LIR_OprFact::illegalOpr.
__ safepoint(safepoint_poll_register(), state_for (x, x->state_before()));
}
crc.load_item_force(arg1); // We skip int->long conversion here, because CRC32 stub doesn't care about high bits.
__ leal(LIR_OprFact::address(a), arg2);
len.load_item_force(arg3); // We skip int->long conversion here, because CRC32 stub expects int.
crc.load_item_force(arg1); // We skip int->long conversion here, because CRC32C stub doesn't care about high bits.
__ leal(LIR_OprFact::address(a), arg2);
__ move(len, cc->at(2)); // We skip int->long conversion here, because CRC32C stub expects int.
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.