in compiler/optimizing/instruction_builder.cc [1713:2695]
bool HInstructionBuilder::ProcessDexInstruction(const Instruction& instruction, uint32_t dex_pc) {
switch (instruction.Opcode()) {
case Instruction::CONST_4: {
int32_t register_index = instruction.VRegA();
HIntConstant* constant = graph_->GetIntConstant(instruction.VRegB_11n(), dex_pc);
UpdateLocal(register_index, constant);
break;
}
case Instruction::CONST_16: {
int32_t register_index = instruction.VRegA();
HIntConstant* constant = graph_->GetIntConstant(instruction.VRegB_21s(), dex_pc);
UpdateLocal(register_index, constant);
break;
}
case Instruction::CONST: {
int32_t register_index = instruction.VRegA();
HIntConstant* constant = graph_->GetIntConstant(instruction.VRegB_31i(), dex_pc);
UpdateLocal(register_index, constant);
break;
}
case Instruction::CONST_HIGH16: {
int32_t register_index = instruction.VRegA();
HIntConstant* constant = graph_->GetIntConstant(instruction.VRegB_21h() << 16, dex_pc);
UpdateLocal(register_index, constant);
break;
}
case Instruction::CONST_WIDE_16: {
int32_t register_index = instruction.VRegA();
// Get 16 bits of constant value, sign extended to 64 bits.
int64_t value = instruction.VRegB_21s();
value <<= 48;
value >>= 48;
HLongConstant* constant = graph_->GetLongConstant(value, dex_pc);
UpdateLocal(register_index, constant);
break;
}
case Instruction::CONST_WIDE_32: {
int32_t register_index = instruction.VRegA();
// Get 32 bits of constant value, sign extended to 64 bits.
int64_t value = instruction.VRegB_31i();
value <<= 32;
value >>= 32;
HLongConstant* constant = graph_->GetLongConstant(value, dex_pc);
UpdateLocal(register_index, constant);
break;
}
case Instruction::CONST_WIDE: {
int32_t register_index = instruction.VRegA();
HLongConstant* constant = graph_->GetLongConstant(instruction.VRegB_51l(), dex_pc);
UpdateLocal(register_index, constant);
break;
}
case Instruction::CONST_WIDE_HIGH16: {
int32_t register_index = instruction.VRegA();
int64_t value = static_cast<int64_t>(instruction.VRegB_21h()) << 48;
HLongConstant* constant = graph_->GetLongConstant(value, dex_pc);
UpdateLocal(register_index, constant);
break;
}
// Note that the SSA building will refine the types.
case Instruction::MOVE:
case Instruction::MOVE_FROM16:
case Instruction::MOVE_16: {
HInstruction* value = LoadLocal(instruction.VRegB(), Primitive::kPrimInt);
UpdateLocal(instruction.VRegA(), value);
break;
}
// Note that the SSA building will refine the types.
case Instruction::MOVE_WIDE:
case Instruction::MOVE_WIDE_FROM16:
case Instruction::MOVE_WIDE_16: {
HInstruction* value = LoadLocal(instruction.VRegB(), Primitive::kPrimLong);
UpdateLocal(instruction.VRegA(), value);
break;
}
case Instruction::MOVE_OBJECT:
case Instruction::MOVE_OBJECT_16:
case Instruction::MOVE_OBJECT_FROM16: {
HInstruction* value = LoadLocal(instruction.VRegB(), Primitive::kPrimNot);
UpdateLocal(instruction.VRegA(), value);
break;
}
case Instruction::RETURN_VOID_NO_BARRIER:
case Instruction::RETURN_VOID: {
BuildReturn(instruction, Primitive::kPrimVoid, dex_pc);
break;
}
#define IF_XX(comparison, cond) \
case Instruction::IF_##cond: If_22t<comparison>(instruction, dex_pc); break; \
case Instruction::IF_##cond##Z: If_21t<comparison>(instruction, dex_pc); break
IF_XX(HEqual, EQ);
IF_XX(HNotEqual, NE);
IF_XX(HLessThan, LT);
IF_XX(HLessThanOrEqual, LE);
IF_XX(HGreaterThan, GT);
IF_XX(HGreaterThanOrEqual, GE);
case Instruction::GOTO:
case Instruction::GOTO_16:
case Instruction::GOTO_32: {
AppendInstruction(new (arena_) HGoto(dex_pc));
current_block_ = nullptr;
break;
}
case Instruction::RETURN: {
BuildReturn(instruction, return_type_, dex_pc);
break;
}
case Instruction::RETURN_OBJECT: {
BuildReturn(instruction, return_type_, dex_pc);
break;
}
case Instruction::RETURN_WIDE: {
BuildReturn(instruction, return_type_, dex_pc);
break;
}
case Instruction::INVOKE_DIRECT:
case Instruction::INVOKE_INTERFACE:
case Instruction::INVOKE_STATIC:
case Instruction::INVOKE_SUPER:
case Instruction::INVOKE_VIRTUAL:
case Instruction::INVOKE_VIRTUAL_QUICK: {
uint16_t method_idx;
if (instruction.Opcode() == Instruction::INVOKE_VIRTUAL_QUICK) {
if (!CanDecodeQuickenedInfo()) {
return false;
}
method_idx = LookupQuickenedInfo(dex_pc);
} else {
method_idx = instruction.VRegB_35c();
}
uint32_t number_of_vreg_arguments = instruction.VRegA_35c();
uint32_t args[5];
instruction.GetVarArgs(args);
if (!BuildInvoke(instruction, dex_pc, method_idx,
number_of_vreg_arguments, false, args, -1)) {
return false;
}
break;
}
case Instruction::INVOKE_DIRECT_RANGE:
case Instruction::INVOKE_INTERFACE_RANGE:
case Instruction::INVOKE_STATIC_RANGE:
case Instruction::INVOKE_SUPER_RANGE:
case Instruction::INVOKE_VIRTUAL_RANGE:
case Instruction::INVOKE_VIRTUAL_RANGE_QUICK: {
uint16_t method_idx;
if (instruction.Opcode() == Instruction::INVOKE_VIRTUAL_RANGE_QUICK) {
if (!CanDecodeQuickenedInfo()) {
return false;
}
method_idx = LookupQuickenedInfo(dex_pc);
} else {
method_idx = instruction.VRegB_3rc();
}
uint32_t number_of_vreg_arguments = instruction.VRegA_3rc();
uint32_t register_index = instruction.VRegC();
if (!BuildInvoke(instruction, dex_pc, method_idx,
number_of_vreg_arguments, true, nullptr, register_index)) {
return false;
}
break;
}
case Instruction::NEG_INT: {
Unop_12x<HNeg>(instruction, Primitive::kPrimInt, dex_pc);
break;
}
case Instruction::NEG_LONG: {
Unop_12x<HNeg>(instruction, Primitive::kPrimLong, dex_pc);
break;
}
case Instruction::NEG_FLOAT: {
Unop_12x<HNeg>(instruction, Primitive::kPrimFloat, dex_pc);
break;
}
case Instruction::NEG_DOUBLE: {
Unop_12x<HNeg>(instruction, Primitive::kPrimDouble, dex_pc);
break;
}
case Instruction::NOT_INT: {
Unop_12x<HNot>(instruction, Primitive::kPrimInt, dex_pc);
break;
}
case Instruction::NOT_LONG: {
Unop_12x<HNot>(instruction, Primitive::kPrimLong, dex_pc);
break;
}
case Instruction::INT_TO_LONG: {
Conversion_12x(instruction, Primitive::kPrimInt, Primitive::kPrimLong, dex_pc);
break;
}
case Instruction::INT_TO_FLOAT: {
Conversion_12x(instruction, Primitive::kPrimInt, Primitive::kPrimFloat, dex_pc);
break;
}
case Instruction::INT_TO_DOUBLE: {
Conversion_12x(instruction, Primitive::kPrimInt, Primitive::kPrimDouble, dex_pc);
break;
}
case Instruction::LONG_TO_INT: {
Conversion_12x(instruction, Primitive::kPrimLong, Primitive::kPrimInt, dex_pc);
break;
}
case Instruction::LONG_TO_FLOAT: {
Conversion_12x(instruction, Primitive::kPrimLong, Primitive::kPrimFloat, dex_pc);
break;
}
case Instruction::LONG_TO_DOUBLE: {
Conversion_12x(instruction, Primitive::kPrimLong, Primitive::kPrimDouble, dex_pc);
break;
}
case Instruction::FLOAT_TO_INT: {
Conversion_12x(instruction, Primitive::kPrimFloat, Primitive::kPrimInt, dex_pc);
break;
}
case Instruction::FLOAT_TO_LONG: {
Conversion_12x(instruction, Primitive::kPrimFloat, Primitive::kPrimLong, dex_pc);
break;
}
case Instruction::FLOAT_TO_DOUBLE: {
Conversion_12x(instruction, Primitive::kPrimFloat, Primitive::kPrimDouble, dex_pc);
break;
}
case Instruction::DOUBLE_TO_INT: {
Conversion_12x(instruction, Primitive::kPrimDouble, Primitive::kPrimInt, dex_pc);
break;
}
case Instruction::DOUBLE_TO_LONG: {
Conversion_12x(instruction, Primitive::kPrimDouble, Primitive::kPrimLong, dex_pc);
break;
}
case Instruction::DOUBLE_TO_FLOAT: {
Conversion_12x(instruction, Primitive::kPrimDouble, Primitive::kPrimFloat, dex_pc);
break;
}
case Instruction::INT_TO_BYTE: {
Conversion_12x(instruction, Primitive::kPrimInt, Primitive::kPrimByte, dex_pc);
break;
}
case Instruction::INT_TO_SHORT: {
Conversion_12x(instruction, Primitive::kPrimInt, Primitive::kPrimShort, dex_pc);
break;
}
case Instruction::INT_TO_CHAR: {
Conversion_12x(instruction, Primitive::kPrimInt, Primitive::kPrimChar, dex_pc);
break;
}
case Instruction::ADD_INT: {
Binop_23x<HAdd>(instruction, Primitive::kPrimInt, dex_pc);
break;
}
case Instruction::ADD_LONG: {
Binop_23x<HAdd>(instruction, Primitive::kPrimLong, dex_pc);
break;
}
case Instruction::ADD_DOUBLE: {
Binop_23x<HAdd>(instruction, Primitive::kPrimDouble, dex_pc);
break;
}
case Instruction::ADD_FLOAT: {
Binop_23x<HAdd>(instruction, Primitive::kPrimFloat, dex_pc);
break;
}
case Instruction::SUB_INT: {
Binop_23x<HSub>(instruction, Primitive::kPrimInt, dex_pc);
break;
}
case Instruction::SUB_LONG: {
Binop_23x<HSub>(instruction, Primitive::kPrimLong, dex_pc);
break;
}
case Instruction::SUB_FLOAT: {
Binop_23x<HSub>(instruction, Primitive::kPrimFloat, dex_pc);
break;
}
case Instruction::SUB_DOUBLE: {
Binop_23x<HSub>(instruction, Primitive::kPrimDouble, dex_pc);
break;
}
case Instruction::ADD_INT_2ADDR: {
Binop_12x<HAdd>(instruction, Primitive::kPrimInt, dex_pc);
break;
}
case Instruction::MUL_INT: {
Binop_23x<HMul>(instruction, Primitive::kPrimInt, dex_pc);
break;
}
case Instruction::MUL_LONG: {
Binop_23x<HMul>(instruction, Primitive::kPrimLong, dex_pc);
break;
}
case Instruction::MUL_FLOAT: {
Binop_23x<HMul>(instruction, Primitive::kPrimFloat, dex_pc);
break;
}
case Instruction::MUL_DOUBLE: {
Binop_23x<HMul>(instruction, Primitive::kPrimDouble, dex_pc);
break;
}
case Instruction::DIV_INT: {
BuildCheckedDivRem(instruction.VRegA(), instruction.VRegB(), instruction.VRegC(),
dex_pc, Primitive::kPrimInt, false, true);
break;
}
case Instruction::DIV_LONG: {
BuildCheckedDivRem(instruction.VRegA(), instruction.VRegB(), instruction.VRegC(),
dex_pc, Primitive::kPrimLong, false, true);
break;
}
case Instruction::DIV_FLOAT: {
Binop_23x<HDiv>(instruction, Primitive::kPrimFloat, dex_pc);
break;
}
case Instruction::DIV_DOUBLE: {
Binop_23x<HDiv>(instruction, Primitive::kPrimDouble, dex_pc);
break;
}
case Instruction::REM_INT: {
BuildCheckedDivRem(instruction.VRegA(), instruction.VRegB(), instruction.VRegC(),
dex_pc, Primitive::kPrimInt, false, false);
break;
}
case Instruction::REM_LONG: {
BuildCheckedDivRem(instruction.VRegA(), instruction.VRegB(), instruction.VRegC(),
dex_pc, Primitive::kPrimLong, false, false);
break;
}
case Instruction::REM_FLOAT: {
Binop_23x<HRem>(instruction, Primitive::kPrimFloat, dex_pc);
break;
}
case Instruction::REM_DOUBLE: {
Binop_23x<HRem>(instruction, Primitive::kPrimDouble, dex_pc);
break;
}
case Instruction::AND_INT: {
Binop_23x<HAnd>(instruction, Primitive::kPrimInt, dex_pc);
break;
}
case Instruction::AND_LONG: {
Binop_23x<HAnd>(instruction, Primitive::kPrimLong, dex_pc);
break;
}
case Instruction::SHL_INT: {
Binop_23x_shift<HShl>(instruction, Primitive::kPrimInt, dex_pc);
break;
}
case Instruction::SHL_LONG: {
Binop_23x_shift<HShl>(instruction, Primitive::kPrimLong, dex_pc);
break;
}
case Instruction::SHR_INT: {
Binop_23x_shift<HShr>(instruction, Primitive::kPrimInt, dex_pc);
break;
}
case Instruction::SHR_LONG: {
Binop_23x_shift<HShr>(instruction, Primitive::kPrimLong, dex_pc);
break;
}
case Instruction::USHR_INT: {
Binop_23x_shift<HUShr>(instruction, Primitive::kPrimInt, dex_pc);
break;
}
case Instruction::USHR_LONG: {
Binop_23x_shift<HUShr>(instruction, Primitive::kPrimLong, dex_pc);
break;
}
case Instruction::OR_INT: {
Binop_23x<HOr>(instruction, Primitive::kPrimInt, dex_pc);
break;
}
case Instruction::OR_LONG: {
Binop_23x<HOr>(instruction, Primitive::kPrimLong, dex_pc);
break;
}
case Instruction::XOR_INT: {
Binop_23x<HXor>(instruction, Primitive::kPrimInt, dex_pc);
break;
}
case Instruction::XOR_LONG: {
Binop_23x<HXor>(instruction, Primitive::kPrimLong, dex_pc);
break;
}
case Instruction::ADD_LONG_2ADDR: {
Binop_12x<HAdd>(instruction, Primitive::kPrimLong, dex_pc);
break;
}
case Instruction::ADD_DOUBLE_2ADDR: {
Binop_12x<HAdd>(instruction, Primitive::kPrimDouble, dex_pc);
break;
}
case Instruction::ADD_FLOAT_2ADDR: {
Binop_12x<HAdd>(instruction, Primitive::kPrimFloat, dex_pc);
break;
}
case Instruction::SUB_INT_2ADDR: {
Binop_12x<HSub>(instruction, Primitive::kPrimInt, dex_pc);
break;
}
case Instruction::SUB_LONG_2ADDR: {
Binop_12x<HSub>(instruction, Primitive::kPrimLong, dex_pc);
break;
}
case Instruction::SUB_FLOAT_2ADDR: {
Binop_12x<HSub>(instruction, Primitive::kPrimFloat, dex_pc);
break;
}
case Instruction::SUB_DOUBLE_2ADDR: {
Binop_12x<HSub>(instruction, Primitive::kPrimDouble, dex_pc);
break;
}
case Instruction::MUL_INT_2ADDR: {
Binop_12x<HMul>(instruction, Primitive::kPrimInt, dex_pc);
break;
}
case Instruction::MUL_LONG_2ADDR: {
Binop_12x<HMul>(instruction, Primitive::kPrimLong, dex_pc);
break;
}
case Instruction::MUL_FLOAT_2ADDR: {
Binop_12x<HMul>(instruction, Primitive::kPrimFloat, dex_pc);
break;
}
case Instruction::MUL_DOUBLE_2ADDR: {
Binop_12x<HMul>(instruction, Primitive::kPrimDouble, dex_pc);
break;
}
case Instruction::DIV_INT_2ADDR: {
BuildCheckedDivRem(instruction.VRegA(), instruction.VRegA(), instruction.VRegB(),
dex_pc, Primitive::kPrimInt, false, true);
break;
}
case Instruction::DIV_LONG_2ADDR: {
BuildCheckedDivRem(instruction.VRegA(), instruction.VRegA(), instruction.VRegB(),
dex_pc, Primitive::kPrimLong, false, true);
break;
}
case Instruction::REM_INT_2ADDR: {
BuildCheckedDivRem(instruction.VRegA(), instruction.VRegA(), instruction.VRegB(),
dex_pc, Primitive::kPrimInt, false, false);
break;
}
case Instruction::REM_LONG_2ADDR: {
BuildCheckedDivRem(instruction.VRegA(), instruction.VRegA(), instruction.VRegB(),
dex_pc, Primitive::kPrimLong, false, false);
break;
}
case Instruction::REM_FLOAT_2ADDR: {
Binop_12x<HRem>(instruction, Primitive::kPrimFloat, dex_pc);
break;
}
case Instruction::REM_DOUBLE_2ADDR: {
Binop_12x<HRem>(instruction, Primitive::kPrimDouble, dex_pc);
break;
}
case Instruction::SHL_INT_2ADDR: {
Binop_12x_shift<HShl>(instruction, Primitive::kPrimInt, dex_pc);
break;
}
case Instruction::SHL_LONG_2ADDR: {
Binop_12x_shift<HShl>(instruction, Primitive::kPrimLong, dex_pc);
break;
}
case Instruction::SHR_INT_2ADDR: {
Binop_12x_shift<HShr>(instruction, Primitive::kPrimInt, dex_pc);
break;
}
case Instruction::SHR_LONG_2ADDR: {
Binop_12x_shift<HShr>(instruction, Primitive::kPrimLong, dex_pc);
break;
}
case Instruction::USHR_INT_2ADDR: {
Binop_12x_shift<HUShr>(instruction, Primitive::kPrimInt, dex_pc);
break;
}
case Instruction::USHR_LONG_2ADDR: {
Binop_12x_shift<HUShr>(instruction, Primitive::kPrimLong, dex_pc);
break;
}
case Instruction::DIV_FLOAT_2ADDR: {
Binop_12x<HDiv>(instruction, Primitive::kPrimFloat, dex_pc);
break;
}
case Instruction::DIV_DOUBLE_2ADDR: {
Binop_12x<HDiv>(instruction, Primitive::kPrimDouble, dex_pc);
break;
}
case Instruction::AND_INT_2ADDR: {
Binop_12x<HAnd>(instruction, Primitive::kPrimInt, dex_pc);
break;
}
case Instruction::AND_LONG_2ADDR: {
Binop_12x<HAnd>(instruction, Primitive::kPrimLong, dex_pc);
break;
}
case Instruction::OR_INT_2ADDR: {
Binop_12x<HOr>(instruction, Primitive::kPrimInt, dex_pc);
break;
}
case Instruction::OR_LONG_2ADDR: {
Binop_12x<HOr>(instruction, Primitive::kPrimLong, dex_pc);
break;
}
case Instruction::XOR_INT_2ADDR: {
Binop_12x<HXor>(instruction, Primitive::kPrimInt, dex_pc);
break;
}
case Instruction::XOR_LONG_2ADDR: {
Binop_12x<HXor>(instruction, Primitive::kPrimLong, dex_pc);
break;
}
case Instruction::ADD_INT_LIT16: {
Binop_22s<HAdd>(instruction, false, dex_pc);
break;
}
case Instruction::AND_INT_LIT16: {
Binop_22s<HAnd>(instruction, false, dex_pc);
break;
}
case Instruction::OR_INT_LIT16: {
Binop_22s<HOr>(instruction, false, dex_pc);
break;
}
case Instruction::XOR_INT_LIT16: {
Binop_22s<HXor>(instruction, false, dex_pc);
break;
}
case Instruction::RSUB_INT: {
Binop_22s<HSub>(instruction, true, dex_pc);
break;
}
case Instruction::MUL_INT_LIT16: {
Binop_22s<HMul>(instruction, false, dex_pc);
break;
}
case Instruction::ADD_INT_LIT8: {
Binop_22b<HAdd>(instruction, false, dex_pc);
break;
}
case Instruction::AND_INT_LIT8: {
Binop_22b<HAnd>(instruction, false, dex_pc);
break;
}
case Instruction::OR_INT_LIT8: {
Binop_22b<HOr>(instruction, false, dex_pc);
break;
}
case Instruction::XOR_INT_LIT8: {
Binop_22b<HXor>(instruction, false, dex_pc);
break;
}
case Instruction::RSUB_INT_LIT8: {
Binop_22b<HSub>(instruction, true, dex_pc);
break;
}
case Instruction::MUL_INT_LIT8: {
Binop_22b<HMul>(instruction, false, dex_pc);
break;
}
case Instruction::DIV_INT_LIT16:
case Instruction::DIV_INT_LIT8: {
BuildCheckedDivRem(instruction.VRegA(), instruction.VRegB(), instruction.VRegC(),
dex_pc, Primitive::kPrimInt, true, true);
break;
}
case Instruction::REM_INT_LIT16:
case Instruction::REM_INT_LIT8: {
BuildCheckedDivRem(instruction.VRegA(), instruction.VRegB(), instruction.VRegC(),
dex_pc, Primitive::kPrimInt, true, false);
break;
}
case Instruction::SHL_INT_LIT8: {
Binop_22b<HShl>(instruction, false, dex_pc);
break;
}
case Instruction::SHR_INT_LIT8: {
Binop_22b<HShr>(instruction, false, dex_pc);
break;
}
case Instruction::USHR_INT_LIT8: {
Binop_22b<HUShr>(instruction, false, dex_pc);
break;
}
case Instruction::NEW_INSTANCE: {
if (!BuildNewInstance(instruction.VRegB_21c(), dex_pc)) {
return false;
}
UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
break;
}
case Instruction::NEW_ARRAY: {
uint16_t type_index = instruction.VRegC_22c();
HInstruction* length = LoadLocal(instruction.VRegB_22c(), Primitive::kPrimInt);
bool finalizable;
QuickEntrypointEnum entrypoint = NeedsAccessCheck(type_index, &finalizable)
? kQuickAllocArrayWithAccessCheck
: kQuickAllocArray;
AppendInstruction(new (arena_) HNewArray(length,
graph_->GetCurrentMethod(),
dex_pc,
type_index,
*dex_compilation_unit_->GetDexFile(),
entrypoint));
UpdateLocal(instruction.VRegA_22c(), current_block_->GetLastInstruction());
break;
}
case Instruction::FILLED_NEW_ARRAY: {
uint32_t number_of_vreg_arguments = instruction.VRegA_35c();
uint32_t type_index = instruction.VRegB_35c();
uint32_t args[5];
instruction.GetVarArgs(args);
BuildFilledNewArray(dex_pc, type_index, number_of_vreg_arguments, false, args, 0);
break;
}
case Instruction::FILLED_NEW_ARRAY_RANGE: {
uint32_t number_of_vreg_arguments = instruction.VRegA_3rc();
uint32_t type_index = instruction.VRegB_3rc();
uint32_t register_index = instruction.VRegC_3rc();
BuildFilledNewArray(
dex_pc, type_index, number_of_vreg_arguments, true, nullptr, register_index);
break;
}
case Instruction::FILL_ARRAY_DATA: {
BuildFillArrayData(instruction, dex_pc);
break;
}
case Instruction::MOVE_RESULT:
case Instruction::MOVE_RESULT_WIDE:
case Instruction::MOVE_RESULT_OBJECT: {
DCHECK(latest_result_ != nullptr);
UpdateLocal(instruction.VRegA(), latest_result_);
latest_result_ = nullptr;
break;
}
case Instruction::CMP_LONG: {
Binop_23x_cmp(instruction, Primitive::kPrimLong, ComparisonBias::kNoBias, dex_pc);
break;
}
case Instruction::CMPG_FLOAT: {
Binop_23x_cmp(instruction, Primitive::kPrimFloat, ComparisonBias::kGtBias, dex_pc);
break;
}
case Instruction::CMPG_DOUBLE: {
Binop_23x_cmp(instruction, Primitive::kPrimDouble, ComparisonBias::kGtBias, dex_pc);
break;
}
case Instruction::CMPL_FLOAT: {
Binop_23x_cmp(instruction, Primitive::kPrimFloat, ComparisonBias::kLtBias, dex_pc);
break;
}
case Instruction::CMPL_DOUBLE: {
Binop_23x_cmp(instruction, Primitive::kPrimDouble, ComparisonBias::kLtBias, dex_pc);
break;
}
case Instruction::NOP:
break;
case Instruction::IGET:
case Instruction::IGET_QUICK:
case Instruction::IGET_WIDE:
case Instruction::IGET_WIDE_QUICK:
case Instruction::IGET_OBJECT:
case Instruction::IGET_OBJECT_QUICK:
case Instruction::IGET_BOOLEAN:
case Instruction::IGET_BOOLEAN_QUICK:
case Instruction::IGET_BYTE:
case Instruction::IGET_BYTE_QUICK:
case Instruction::IGET_CHAR:
case Instruction::IGET_CHAR_QUICK:
case Instruction::IGET_SHORT:
case Instruction::IGET_SHORT_QUICK: {
if (!BuildInstanceFieldAccess(instruction, dex_pc, false)) {
return false;
}
break;
}
case Instruction::IPUT:
case Instruction::IPUT_QUICK:
case Instruction::IPUT_WIDE:
case Instruction::IPUT_WIDE_QUICK:
case Instruction::IPUT_OBJECT:
case Instruction::IPUT_OBJECT_QUICK:
case Instruction::IPUT_BOOLEAN:
case Instruction::IPUT_BOOLEAN_QUICK:
case Instruction::IPUT_BYTE:
case Instruction::IPUT_BYTE_QUICK:
case Instruction::IPUT_CHAR:
case Instruction::IPUT_CHAR_QUICK:
case Instruction::IPUT_SHORT:
case Instruction::IPUT_SHORT_QUICK: {
if (!BuildInstanceFieldAccess(instruction, dex_pc, true)) {
return false;
}
break;
}
case Instruction::SGET:
case Instruction::SGET_WIDE:
case Instruction::SGET_OBJECT:
case Instruction::SGET_BOOLEAN:
case Instruction::SGET_BYTE:
case Instruction::SGET_CHAR:
case Instruction::SGET_SHORT: {
if (!BuildStaticFieldAccess(instruction, dex_pc, false)) {
return false;
}
break;
}
case Instruction::SPUT:
case Instruction::SPUT_WIDE:
case Instruction::SPUT_OBJECT:
case Instruction::SPUT_BOOLEAN:
case Instruction::SPUT_BYTE:
case Instruction::SPUT_CHAR:
case Instruction::SPUT_SHORT: {
if (!BuildStaticFieldAccess(instruction, dex_pc, true)) {
return false;
}
break;
}
#define ARRAY_XX(kind, anticipated_type) \
case Instruction::AGET##kind: { \
BuildArrayAccess(instruction, dex_pc, false, anticipated_type); \
break; \
} \
case Instruction::APUT##kind: { \
BuildArrayAccess(instruction, dex_pc, true, anticipated_type); \
break; \
}
ARRAY_XX(, Primitive::kPrimInt);
ARRAY_XX(_WIDE, Primitive::kPrimLong);
ARRAY_XX(_OBJECT, Primitive::kPrimNot);
ARRAY_XX(_BOOLEAN, Primitive::kPrimBoolean);
ARRAY_XX(_BYTE, Primitive::kPrimByte);
ARRAY_XX(_CHAR, Primitive::kPrimChar);
ARRAY_XX(_SHORT, Primitive::kPrimShort);
case Instruction::ARRAY_LENGTH: {
HInstruction* object = LoadNullCheckedLocal(instruction.VRegB_12x(), dex_pc);
AppendInstruction(new (arena_) HArrayLength(object, dex_pc));
UpdateLocal(instruction.VRegA_12x(), current_block_->GetLastInstruction());
break;
}
case Instruction::CONST_STRING: {
uint32_t string_index = instruction.VRegB_21c();
AppendInstruction(
new (arena_) HLoadString(graph_->GetCurrentMethod(), string_index, *dex_file_, dex_pc));
UpdateLocal(instruction.VRegA_21c(), current_block_->GetLastInstruction());
break;
}
case Instruction::CONST_STRING_JUMBO: {
uint32_t string_index = instruction.VRegB_31c();
AppendInstruction(
new (arena_) HLoadString(graph_->GetCurrentMethod(), string_index, *dex_file_, dex_pc));
UpdateLocal(instruction.VRegA_31c(), current_block_->GetLastInstruction());
break;
}
case Instruction::CONST_CLASS: {
uint16_t type_index = instruction.VRegB_21c();
// `CanAccessTypeWithoutChecks` will tell whether the method being
// built is trying to access its own class, so that the generated
// code can optimize for this case. However, the optimization does not
// work for inlining, so we use `IsOutermostCompilingClass` instead.
ScopedObjectAccess soa(Thread::Current());
Handle<mirror::DexCache> dex_cache = dex_compilation_unit_->GetDexCache();
bool can_access = compiler_driver_->CanAccessTypeWithoutChecks(
dex_compilation_unit_->GetDexMethodIndex(), dex_cache, type_index);
bool is_in_dex_cache =
compiler_driver_->CanAssumeTypeIsPresentInDexCache(dex_cache, type_index);
AppendInstruction(new (arena_) HLoadClass(
graph_->GetCurrentMethod(),
type_index,
*dex_file_,
IsOutermostCompilingClass(type_index),
dex_pc,
!can_access,
is_in_dex_cache));
UpdateLocal(instruction.VRegA_21c(), current_block_->GetLastInstruction());
break;
}
case Instruction::MOVE_EXCEPTION: {
AppendInstruction(new (arena_) HLoadException(dex_pc));
UpdateLocal(instruction.VRegA_11x(), current_block_->GetLastInstruction());
AppendInstruction(new (arena_) HClearException(dex_pc));
break;
}
case Instruction::THROW: {
HInstruction* exception = LoadLocal(instruction.VRegA_11x(), Primitive::kPrimNot);
AppendInstruction(new (arena_) HThrow(exception, dex_pc));
// We finished building this block. Set the current block to null to avoid
// adding dead instructions to it.
current_block_ = nullptr;
break;
}
case Instruction::INSTANCE_OF: {
uint8_t destination = instruction.VRegA_22c();
uint8_t reference = instruction.VRegB_22c();
uint16_t type_index = instruction.VRegC_22c();
BuildTypeCheck(instruction, destination, reference, type_index, dex_pc);
break;
}
case Instruction::CHECK_CAST: {
uint8_t reference = instruction.VRegA_21c();
uint16_t type_index = instruction.VRegB_21c();
BuildTypeCheck(instruction, -1, reference, type_index, dex_pc);
break;
}
case Instruction::MONITOR_ENTER: {
AppendInstruction(new (arena_) HMonitorOperation(
LoadLocal(instruction.VRegA_11x(), Primitive::kPrimNot),
HMonitorOperation::OperationKind::kEnter,
dex_pc));
break;
}
case Instruction::MONITOR_EXIT: {
AppendInstruction(new (arena_) HMonitorOperation(
LoadLocal(instruction.VRegA_11x(), Primitive::kPrimNot),
HMonitorOperation::OperationKind::kExit,
dex_pc));
break;
}
case Instruction::SPARSE_SWITCH:
case Instruction::PACKED_SWITCH: {
BuildSwitch(instruction, dex_pc);
break;
}
default:
VLOG(compiler) << "Did not compile "
<< PrettyMethod(dex_compilation_unit_->GetDexMethodIndex(), *dex_file_)
<< " because of unhandled instruction "
<< instruction.Name();
MaybeRecordStat(MethodCompilationStat::kNotCompiledUnhandledInstruction);
return false;
}
return true;
} // NOLINT(readability/fn_size)