in src/hotspot/share/c1/c1_LIR.cpp [399:899]
void LIR_OpVisitState::visit(LIR_Op* op) {
// copy information from the LIR_Op
reset();
set_op(op);
switch (op->code()) {
// LIR_Op0
case lir_breakpoint: // result and info always invalid
case lir_membar: // result and info always invalid
case lir_membar_acquire: // result and info always invalid
case lir_membar_release: // result and info always invalid
case lir_membar_loadload: // result and info always invalid
case lir_membar_storestore: // result and info always invalid
case lir_membar_loadstore: // result and info always invalid
case lir_membar_storeload: // result and info always invalid
case lir_on_spin_wait:
{
assert(op->as_Op0() != nullptr, "must be");
assert(op->_info == nullptr, "info not used by this instruction");
assert(op->_result->is_illegal(), "not used");
break;
}
case lir_nop: // may have info, result always invalid
case lir_std_entry: // may have result, info always invalid
case lir_osr_entry: // may have result, info always invalid
case lir_get_thread: // may have result, info always invalid
{
assert(op->as_Op0() != nullptr, "must be");
if (op->_info != nullptr) do_info(op->_info);
if (op->_result->is_valid()) do_output(op->_result);
break;
}
// LIR_OpLabel
case lir_label: // result and info always invalid
{
assert(op->as_OpLabel() != nullptr, "must be");
assert(op->_info == nullptr, "info not used by this instruction");
assert(op->_result->is_illegal(), "not used");
break;
}
// LIR_Op1
case lir_push: // input always valid, result and info always invalid
case lir_pop: // input always valid, result and info always invalid
case lir_leal: // input and result always valid, info always invalid
case lir_monaddr: // input and result always valid, info always invalid
case lir_null_check: // input and info always valid, result always invalid
case lir_move: // input and result always valid, may have info
case lir_sqrt: // FP Ops have no info, but input and result
case lir_abs:
case lir_neg:
case lir_f2hf:
case lir_hf2f:
{
assert(op->as_Op1() != nullptr, "must be");
LIR_Op1* op1 = (LIR_Op1*)op;
if (op1->_info) do_info(op1->_info);
if (op1->_opr->is_valid()) do_input(op1->_opr);
if (op1->_tmp->is_valid()) do_temp(op1->_tmp);
if (op1->_result->is_valid()) do_output(op1->_result);
break;
}
case lir_return:
{
assert(op->as_OpReturn() != nullptr, "must be");
LIR_OpReturn* op_ret = (LIR_OpReturn*)op;
if (op_ret->_info) do_info(op_ret->_info);
if (op_ret->_opr->is_valid()) do_input(op_ret->_opr);
if (op_ret->_result->is_valid()) do_output(op_ret->_result);
if (op_ret->stub() != nullptr) do_stub(op_ret->stub());
break;
}
case lir_safepoint:
{
assert(op->as_Op1() != nullptr, "must be");
LIR_Op1* op1 = (LIR_Op1*)op;
assert(op1->_info != nullptr, ""); do_info(op1->_info);
if (op1->_opr->is_valid()) do_temp(op1->_opr); // safepoints on SPARC need temporary register
assert(op1->_tmp->is_illegal(), "not used");
assert(op1->_result->is_illegal(), "safepoint does not produce value");
break;
}
// LIR_OpConvert;
case lir_convert: // input and result always valid, info always invalid
{
assert(op->as_OpConvert() != nullptr, "must be");
LIR_OpConvert* opConvert = (LIR_OpConvert*)op;
assert(opConvert->_info == nullptr, "must be");
if (opConvert->_opr->is_valid()) do_input(opConvert->_opr);
if (opConvert->_result->is_valid()) do_output(opConvert->_result);
break;
}
// LIR_OpBranch;
case lir_branch: // may have info, input and result register always invalid
case lir_cond_float_branch: // may have info, input and result register always invalid
{
assert(op->as_OpBranch() != nullptr, "must be");
LIR_OpBranch* opBranch = (LIR_OpBranch*)op;
assert(opBranch->_tmp1->is_illegal() && opBranch->_tmp2->is_illegal() &&
opBranch->_tmp3->is_illegal() && opBranch->_tmp4->is_illegal() &&
opBranch->_tmp5->is_illegal(), "not used");
if (opBranch->_opr1->is_valid()) do_input(opBranch->_opr1);
if (opBranch->_opr2->is_valid()) do_input(opBranch->_opr2);
if (opBranch->_info != nullptr) do_info(opBranch->_info);
assert(opBranch->_result->is_illegal(), "not used");
if (opBranch->_stub != nullptr) opBranch->stub()->visit(this);
break;
}
// LIR_OpAllocObj
case lir_alloc_object:
{
assert(op->as_OpAllocObj() != nullptr, "must be");
LIR_OpAllocObj* opAllocObj = (LIR_OpAllocObj*)op;
if (opAllocObj->_info) do_info(opAllocObj->_info);
if (opAllocObj->_opr->is_valid()) { do_input(opAllocObj->_opr);
do_temp(opAllocObj->_opr);
}
if (opAllocObj->_tmp1->is_valid()) do_temp(opAllocObj->_tmp1);
if (opAllocObj->_tmp2->is_valid()) do_temp(opAllocObj->_tmp2);
if (opAllocObj->_tmp3->is_valid()) do_temp(opAllocObj->_tmp3);
if (opAllocObj->_tmp4->is_valid()) do_temp(opAllocObj->_tmp4);
if (opAllocObj->_result->is_valid()) do_output(opAllocObj->_result);
if (opAllocObj->_stub != nullptr) do_stub(opAllocObj->_stub);
break;
}
// LIR_Op2
case lir_cmp:
case lir_cmp_l2i:
case lir_ucmp_fd2i:
case lir_cmp_fd2i:
case lir_add:
case lir_sub:
case lir_rem:
case lir_logic_and:
case lir_logic_or:
case lir_logic_xor:
case lir_shl:
case lir_shr:
case lir_ushr:
case lir_xadd:
case lir_xchg:
case lir_assert:
{
assert(op->as_Op2() != nullptr, "must be");
LIR_Op2* op2 = (LIR_Op2*)op;
assert(op2->_tmp2->is_illegal() && op2->_tmp3->is_illegal() &&
op2->_tmp4->is_illegal() && op2->_tmp5->is_illegal(), "not used");
if (op2->_info) do_info(op2->_info);
if (op2->_opr1->is_valid()) do_input(op2->_opr1);
if (op2->_opr2->is_valid()) do_input(op2->_opr2);
if (op2->_tmp1->is_valid()) do_temp(op2->_tmp1);
if (op2->_result->is_valid()) do_output(op2->_result);
if (op->code() == lir_xchg || op->code() == lir_xadd) {
// on ARM and PPC, return value is loaded first so could
// destroy inputs. On other platforms that implement those
// (x86, sparc), the extra constrainsts are harmless.
if (op2->_opr1->is_valid()) do_temp(op2->_opr1);
if (op2->_opr2->is_valid()) do_temp(op2->_opr2);
}
break;
}
// special handling for cmove: right input operand must not be equal
// to the result operand, otherwise the backend fails
case lir_cmove:
{
assert(op->as_Op4() != nullptr, "must be");
LIR_Op4* op4 = (LIR_Op4*)op;
assert(op4->_info == nullptr && op4->_tmp1->is_illegal() && op4->_tmp2->is_illegal() &&
op4->_tmp3->is_illegal() && op4->_tmp4->is_illegal() && op4->_tmp5->is_illegal(), "not used");
assert(op4->_opr1->is_valid() && op4->_opr2->is_valid() && op4->_result->is_valid(), "used");
do_input(op4->_opr1);
do_input(op4->_opr2);
if (op4->_opr3->is_valid()) do_input(op4->_opr3);
if (op4->_opr4->is_valid()) do_input(op4->_opr4);
do_temp(op4->_opr2);
do_output(op4->_result);
break;
}
// vspecial handling for strict operations: register input operands
// as temp to guarantee that they do not overlap with other
// registers
case lir_mul:
case lir_div:
{
assert(op->as_Op2() != nullptr, "must be");
LIR_Op2* op2 = (LIR_Op2*)op;
assert(op2->_info == nullptr, "not used");
assert(op2->_opr1->is_valid(), "used");
assert(op2->_opr2->is_valid(), "used");
assert(op2->_result->is_valid(), "used");
assert(op2->_tmp2->is_illegal() && op2->_tmp3->is_illegal() &&
op2->_tmp4->is_illegal() && op2->_tmp5->is_illegal(), "not used");
do_input(op2->_opr1); do_temp(op2->_opr1);
do_input(op2->_opr2); do_temp(op2->_opr2);
if (op2->_tmp1->is_valid()) do_temp(op2->_tmp1);
do_output(op2->_result);
break;
}
case lir_throw: {
assert(op->as_Op2() != nullptr, "must be");
LIR_Op2* op2 = (LIR_Op2*)op;
if (op2->_info) do_info(op2->_info);
if (op2->_opr1->is_valid()) do_temp(op2->_opr1);
if (op2->_opr2->is_valid()) do_input(op2->_opr2); // exception object is input parameter
assert(op2->_result->is_illegal(), "no result");
assert(op2->_tmp2->is_illegal() && op2->_tmp3->is_illegal() &&
op2->_tmp4->is_illegal() && op2->_tmp5->is_illegal(), "not used");
break;
}
case lir_unwind: {
assert(op->as_Op1() != nullptr, "must be");
LIR_Op1* op1 = (LIR_Op1*)op;
assert(op1->_info == nullptr, "no info");
assert(op1->_opr->is_valid(), "exception oop"); do_input(op1->_opr);
assert(op1->_tmp->is_illegal(), "not used");
assert(op1->_result->is_illegal(), "no result");
break;
}
// LIR_Op3
case lir_idiv:
case lir_irem: {
assert(op->as_Op3() != nullptr, "must be");
LIR_Op3* op3= (LIR_Op3*)op;
if (op3->_info) do_info(op3->_info);
if (op3->_opr1->is_valid()) do_input(op3->_opr1);
// second operand is input and temp, so ensure that second operand
// and third operand get not the same register
if (op3->_opr2->is_valid()) do_input(op3->_opr2);
if (op3->_opr2->is_valid()) do_temp(op3->_opr2);
if (op3->_opr3->is_valid()) do_temp(op3->_opr3);
if (op3->_result->is_valid()) do_output(op3->_result);
break;
}
case lir_fmad:
case lir_fmaf: {
assert(op->as_Op3() != nullptr, "must be");
LIR_Op3* op3= (LIR_Op3*)op;
assert(op3->_info == nullptr, "no info");
do_input(op3->_opr1);
do_input(op3->_opr2);
do_input(op3->_opr3);
do_output(op3->_result);
break;
}
// LIR_OpJavaCall
case lir_static_call:
case lir_optvirtual_call:
case lir_icvirtual_call:
case lir_dynamic_call: {
LIR_OpJavaCall* opJavaCall = op->as_OpJavaCall();
assert(opJavaCall != nullptr, "must be");
if (opJavaCall->_receiver->is_valid()) do_input(opJavaCall->_receiver);
// only visit register parameters
int n = opJavaCall->_arguments->length();
for (int i = opJavaCall->_receiver->is_valid() ? 1 : 0; i < n; i++) {
if (!opJavaCall->_arguments->at(i)->is_pointer()) {
do_input(*opJavaCall->_arguments->adr_at(i));
}
}
if (opJavaCall->_info) do_info(opJavaCall->_info);
do_call();
if (opJavaCall->_result->is_valid()) do_output(opJavaCall->_result);
break;
}
// LIR_OpRTCall
case lir_rtcall: {
assert(op->as_OpRTCall() != nullptr, "must be");
LIR_OpRTCall* opRTCall = (LIR_OpRTCall*)op;
// only visit register parameters
int n = opRTCall->_arguments->length();
for (int i = 0; i < n; i++) {
if (!opRTCall->_arguments->at(i)->is_pointer()) {
do_input(*opRTCall->_arguments->adr_at(i));
}
}
if (opRTCall->_info) do_info(opRTCall->_info);
if (opRTCall->_tmp->is_valid()) do_temp(opRTCall->_tmp);
do_call();
if (opRTCall->_result->is_valid()) do_output(opRTCall->_result);
break;
}
// LIR_OpArrayCopy
case lir_arraycopy: {
assert(op->as_OpArrayCopy() != nullptr, "must be");
LIR_OpArrayCopy* opArrayCopy = (LIR_OpArrayCopy*)op;
assert(opArrayCopy->_result->is_illegal(), "unused");
assert(opArrayCopy->_src->is_valid(), "used"); do_input(opArrayCopy->_src); do_temp(opArrayCopy->_src);
assert(opArrayCopy->_src_pos->is_valid(), "used"); do_input(opArrayCopy->_src_pos); do_temp(opArrayCopy->_src_pos);
assert(opArrayCopy->_dst->is_valid(), "used"); do_input(opArrayCopy->_dst); do_temp(opArrayCopy->_dst);
assert(opArrayCopy->_dst_pos->is_valid(), "used"); do_input(opArrayCopy->_dst_pos); do_temp(opArrayCopy->_dst_pos);
assert(opArrayCopy->_length->is_valid(), "used"); do_input(opArrayCopy->_length); do_temp(opArrayCopy->_length);
assert(opArrayCopy->_tmp->is_valid(), "used"); do_temp(opArrayCopy->_tmp);
if (opArrayCopy->_info) do_info(opArrayCopy->_info);
// the implementation of arraycopy always has a call into the runtime
do_call();
break;
}
// LIR_OpUpdateCRC32
case lir_updatecrc32: {
assert(op->as_OpUpdateCRC32() != nullptr, "must be");
LIR_OpUpdateCRC32* opUp = (LIR_OpUpdateCRC32*)op;
assert(opUp->_crc->is_valid(), "used"); do_input(opUp->_crc); do_temp(opUp->_crc);
assert(opUp->_val->is_valid(), "used"); do_input(opUp->_val); do_temp(opUp->_val);
assert(opUp->_result->is_valid(), "used"); do_output(opUp->_result);
assert(opUp->_info == nullptr, "no info for LIR_OpUpdateCRC32");
break;
}
// LIR_OpLock
case lir_lock:
case lir_unlock: {
assert(op->as_OpLock() != nullptr, "must be");
LIR_OpLock* opLock = (LIR_OpLock*)op;
if (opLock->_info) do_info(opLock->_info);
// TODO: check if these operands really have to be temp
// (or if input is sufficient). This may have influence on the oop map!
assert(opLock->_lock->is_valid(), "used"); do_temp(opLock->_lock);
assert(opLock->_hdr->is_valid(), "used"); do_temp(opLock->_hdr);
assert(opLock->_obj->is_valid(), "used"); do_temp(opLock->_obj);
if (opLock->_scratch->is_valid()) do_temp(opLock->_scratch);
assert(opLock->_result->is_illegal(), "unused");
do_stub(opLock->_stub);
break;
}
// LIR_OpTypeCheck
case lir_instanceof:
case lir_checkcast:
case lir_store_check: {
assert(op->as_OpTypeCheck() != nullptr, "must be");
LIR_OpTypeCheck* opTypeCheck = (LIR_OpTypeCheck*)op;
if (opTypeCheck->_info_for_exception) do_info(opTypeCheck->_info_for_exception);
if (opTypeCheck->_info_for_patch) do_info(opTypeCheck->_info_for_patch);
if (opTypeCheck->_object->is_valid()) do_input(opTypeCheck->_object);
if (op->code() == lir_store_check && opTypeCheck->_object->is_valid()) {
do_temp(opTypeCheck->_object);
}
if (opTypeCheck->_array->is_valid()) do_input(opTypeCheck->_array);
if (opTypeCheck->_tmp1->is_valid()) do_temp(opTypeCheck->_tmp1);
if (opTypeCheck->_tmp2->is_valid()) do_temp(opTypeCheck->_tmp2);
if (opTypeCheck->_tmp3->is_valid()) do_temp(opTypeCheck->_tmp3);
if (opTypeCheck->_result->is_valid()) do_output(opTypeCheck->_result);
if (opTypeCheck->_stub != nullptr) do_stub(opTypeCheck->_stub);
break;
}
// LIR_OpCompareAndSwap
case lir_cas_long:
case lir_cas_obj:
case lir_cas_int: {
assert(op->as_OpCompareAndSwap() != nullptr, "must be");
LIR_OpCompareAndSwap* opCmpAndSwap = (LIR_OpCompareAndSwap*)op;
if (opCmpAndSwap->_info) do_info(opCmpAndSwap->_info);
assert(opCmpAndSwap->_addr->is_valid(), "used"); do_input(opCmpAndSwap->_addr);
do_temp(opCmpAndSwap->_addr);
assert(opCmpAndSwap->_cmp_value->is_valid(), "used"); do_input(opCmpAndSwap->_cmp_value);
do_temp(opCmpAndSwap->_cmp_value);
assert(opCmpAndSwap->_new_value->is_valid(), "used"); do_input(opCmpAndSwap->_new_value);
do_temp(opCmpAndSwap->_new_value);
if (opCmpAndSwap->_tmp1->is_valid()) do_temp(opCmpAndSwap->_tmp1);
if (opCmpAndSwap->_tmp2->is_valid()) do_temp(opCmpAndSwap->_tmp2);
if (opCmpAndSwap->_result->is_valid()) do_output(opCmpAndSwap->_result);
break;
}
// LIR_OpAllocArray;
case lir_alloc_array: {
assert(op->as_OpAllocArray() != nullptr, "must be");
LIR_OpAllocArray* opAllocArray = (LIR_OpAllocArray*)op;
if (opAllocArray->_info) do_info(opAllocArray->_info);
if (opAllocArray->_klass->is_valid()) { do_input(opAllocArray->_klass);
do_temp(opAllocArray->_klass);
}
if (opAllocArray->_len->is_valid()) { do_input(opAllocArray->_len);
do_temp(opAllocArray->_len);
}
if (opAllocArray->_tmp1->is_valid()) do_temp(opAllocArray->_tmp1);
if (opAllocArray->_tmp2->is_valid()) do_temp(opAllocArray->_tmp2);
if (opAllocArray->_tmp3->is_valid()) do_temp(opAllocArray->_tmp3);
if (opAllocArray->_tmp4->is_valid()) do_temp(opAllocArray->_tmp4);
if (opAllocArray->_result->is_valid()) do_output(opAllocArray->_result);
if (opAllocArray->_stub != nullptr) do_stub(opAllocArray->_stub);
break;
}
// LIR_OpLoadKlass
case lir_load_klass:
{
LIR_OpLoadKlass* opLoadKlass = op->as_OpLoadKlass();
assert(opLoadKlass != nullptr, "must be");
do_input(opLoadKlass->_obj);
do_output(opLoadKlass->_result);
if (opLoadKlass->_info) do_info(opLoadKlass->_info);
break;
}
// LIR_OpProfileCall:
case lir_profile_call: {
assert(op->as_OpProfileCall() != nullptr, "must be");
LIR_OpProfileCall* opProfileCall = (LIR_OpProfileCall*)op;
if (opProfileCall->_recv->is_valid()) do_temp(opProfileCall->_recv);
assert(opProfileCall->_mdo->is_valid(), "used"); do_temp(opProfileCall->_mdo);
assert(opProfileCall->_tmp1->is_valid(), "used"); do_temp(opProfileCall->_tmp1);
break;
}
// LIR_OpProfileType:
case lir_profile_type: {
assert(op->as_OpProfileType() != nullptr, "must be");
LIR_OpProfileType* opProfileType = (LIR_OpProfileType*)op;
do_input(opProfileType->_mdp); do_temp(opProfileType->_mdp);
do_input(opProfileType->_obj);
do_temp(opProfileType->_tmp);
break;
}
default:
op->visit(this);
}
}