Merge "ART: Add missing GetInterfaceMethodIfProxy"
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc
index 1650fd1..7a3aa58 100644
--- a/compiler/optimizing/builder.cc
+++ b/compiler/optimizing/builder.cc
@@ -46,7 +46,7 @@
explicit Temporaries(HGraph* graph) : graph_(graph), index_(0) {}
void Add(HInstruction* instruction) {
- HInstruction* temp = new (graph_->GetArena()) HTemporary(index_);
+ HInstruction* temp = new (graph_->GetArena()) HTemporary(index_, instruction->GetDexPc());
instruction->GetBlock()->AddInstruction(temp);
DCHECK(temp->GetPrevious() == instruction);
@@ -161,23 +161,25 @@
if (!dex_compilation_unit_->IsStatic()) {
// Add the implicit 'this' argument, not expressed in the signature.
- HParameterValue* parameter =
- new (arena_) HParameterValue(parameter_index++, Primitive::kPrimNot, true);
+ HParameterValue* parameter = new (arena_) HParameterValue(parameter_index++,
+ Primitive::kPrimNot,
+ true);
entry_block_->AddInstruction(parameter);
HLocal* local = GetLocalAt(locals_index++);
- entry_block_->AddInstruction(new (arena_) HStoreLocal(local, parameter));
+ entry_block_->AddInstruction(new (arena_) HStoreLocal(local, parameter, local->GetDexPc()));
number_of_parameters--;
}
uint32_t pos = 1;
for (int i = 0; i < number_of_parameters; i++) {
- HParameterValue* parameter =
- new (arena_) HParameterValue(parameter_index++, Primitive::GetType(shorty[pos++]));
+ HParameterValue* parameter = new (arena_) HParameterValue(parameter_index++,
+ Primitive::GetType(shorty[pos++]),
+ false);
entry_block_->AddInstruction(parameter);
HLocal* local = GetLocalAt(locals_index++);
// Store the parameter value in the local that the dex code will use
// to reference that parameter.
- entry_block_->AddInstruction(new (arena_) HStoreLocal(local, parameter));
+ entry_block_->AddInstruction(new (arena_) HStoreLocal(local, parameter, local->GetDexPc()));
bool is_wide = (parameter->GetType() == Primitive::kPrimLong)
|| (parameter->GetType() == Primitive::kPrimDouble);
if (is_wide) {
@@ -196,11 +198,11 @@
DCHECK(branch_target != nullptr);
DCHECK(fallthrough_target != nullptr);
PotentiallyAddSuspendCheck(branch_target, dex_pc);
- HInstruction* first = LoadLocal(instruction.VRegA(), Primitive::kPrimInt);
- HInstruction* second = LoadLocal(instruction.VRegB(), Primitive::kPrimInt);
- T* comparison = new (arena_) T(first, second);
+ HInstruction* first = LoadLocal(instruction.VRegA(), Primitive::kPrimInt, dex_pc);
+ HInstruction* second = LoadLocal(instruction.VRegB(), Primitive::kPrimInt, dex_pc);
+ T* comparison = new (arena_) T(first, second, dex_pc);
current_block_->AddInstruction(comparison);
- HInstruction* ifinst = new (arena_) HIf(comparison);
+ HInstruction* ifinst = new (arena_) HIf(comparison, dex_pc);
current_block_->AddInstruction(ifinst);
current_block_->AddSuccessor(branch_target);
current_block_->AddSuccessor(fallthrough_target);
@@ -215,10 +217,10 @@
DCHECK(branch_target != nullptr);
DCHECK(fallthrough_target != nullptr);
PotentiallyAddSuspendCheck(branch_target, dex_pc);
- HInstruction* value = LoadLocal(instruction.VRegA(), Primitive::kPrimInt);
- T* comparison = new (arena_) T(value, graph_->GetIntConstant(0));
+ HInstruction* value = LoadLocal(instruction.VRegA(), Primitive::kPrimInt, dex_pc);
+ T* comparison = new (arena_) T(value, graph_->GetIntConstant(0, dex_pc), dex_pc);
current_block_->AddInstruction(comparison);
- HInstruction* ifinst = new (arena_) HIf(comparison);
+ HInstruction* ifinst = new (arena_) HIf(comparison, dex_pc);
current_block_->AddInstruction(ifinst);
current_block_->AddSuccessor(branch_target);
current_block_->AddSuccessor(fallthrough_target);
@@ -320,7 +322,7 @@
const DexFile::CodeItem& code_item,
const DexFile::TryItem& try_item) {
// Split the edge with a single TryBoundary instruction.
- HTryBoundary* try_boundary = new (arena_) HTryBoundary(kind);
+ HTryBoundary* try_boundary = new (arena_) HTryBoundary(kind, successor->GetDexPc());
HBasicBlock* try_entry_block = graph_->SplitEdge(predecessor, successor);
try_entry_block->AddInstruction(try_boundary);
@@ -538,7 +540,7 @@
// Branching instructions clear current_block, so we know
// the last instruction of the current block is not a branching
// instruction. We add an unconditional goto to the found block.
- current_block_->AddInstruction(new (arena_) HGoto());
+ current_block_->AddInstruction(new (arena_) HGoto(dex_pc));
current_block_->AddSuccessor(block);
}
graph_->AddBlock(block);
@@ -634,104 +636,92 @@
}
template<typename T>
-void HGraphBuilder::Unop_12x(const Instruction& instruction, Primitive::Type type) {
- HInstruction* first = LoadLocal(instruction.VRegB(), type);
- current_block_->AddInstruction(new (arena_) T(type, first));
- UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
+void HGraphBuilder::Unop_12x(const Instruction& instruction,
+ Primitive::Type type,
+ uint32_t dex_pc) {
+ HInstruction* first = LoadLocal(instruction.VRegB(), type, dex_pc);
+ current_block_->AddInstruction(new (arena_) T(type, first, dex_pc));
+ UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction(), dex_pc);
}
void HGraphBuilder::Conversion_12x(const Instruction& instruction,
Primitive::Type input_type,
Primitive::Type result_type,
uint32_t dex_pc) {
- HInstruction* first = LoadLocal(instruction.VRegB(), input_type);
+ HInstruction* first = LoadLocal(instruction.VRegB(), input_type, dex_pc);
current_block_->AddInstruction(new (arena_) HTypeConversion(result_type, first, dex_pc));
- UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
-}
-
-template<typename T>
-void HGraphBuilder::Binop_23x(const Instruction& instruction, Primitive::Type type) {
- HInstruction* first = LoadLocal(instruction.VRegB(), type);
- HInstruction* second = LoadLocal(instruction.VRegC(), type);
- current_block_->AddInstruction(new (arena_) T(type, first, second));
- UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
+ UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction(), dex_pc);
}
template<typename T>
void HGraphBuilder::Binop_23x(const Instruction& instruction,
Primitive::Type type,
uint32_t dex_pc) {
- HInstruction* first = LoadLocal(instruction.VRegB(), type);
- HInstruction* second = LoadLocal(instruction.VRegC(), type);
+ HInstruction* first = LoadLocal(instruction.VRegB(), type, dex_pc);
+ HInstruction* second = LoadLocal(instruction.VRegC(), type, dex_pc);
current_block_->AddInstruction(new (arena_) T(type, first, second, dex_pc));
- UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
+ UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction(), dex_pc);
}
template<typename T>
void HGraphBuilder::Binop_23x_shift(const Instruction& instruction,
- Primitive::Type type) {
- HInstruction* first = LoadLocal(instruction.VRegB(), type);
- HInstruction* second = LoadLocal(instruction.VRegC(), Primitive::kPrimInt);
- current_block_->AddInstruction(new (arena_) T(type, first, second));
- UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
+ Primitive::Type type,
+ uint32_t dex_pc) {
+ HInstruction* first = LoadLocal(instruction.VRegB(), type, dex_pc);
+ HInstruction* second = LoadLocal(instruction.VRegC(), Primitive::kPrimInt, dex_pc);
+ current_block_->AddInstruction(new (arena_) T(type, first, second, dex_pc));
+ UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction(), dex_pc);
}
void HGraphBuilder::Binop_23x_cmp(const Instruction& instruction,
Primitive::Type type,
ComparisonBias bias,
uint32_t dex_pc) {
- HInstruction* first = LoadLocal(instruction.VRegB(), type);
- HInstruction* second = LoadLocal(instruction.VRegC(), type);
+ HInstruction* first = LoadLocal(instruction.VRegB(), type, dex_pc);
+ HInstruction* second = LoadLocal(instruction.VRegC(), type, dex_pc);
current_block_->AddInstruction(new (arena_) HCompare(type, first, second, bias, dex_pc));
- UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
+ UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction(), dex_pc);
}
template<typename T>
-void HGraphBuilder::Binop_12x(const Instruction& instruction, Primitive::Type type) {
- HInstruction* first = LoadLocal(instruction.VRegA(), type);
- HInstruction* second = LoadLocal(instruction.VRegB(), type);
- current_block_->AddInstruction(new (arena_) T(type, first, second));
- UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
-}
-
-template<typename T>
-void HGraphBuilder::Binop_12x_shift(const Instruction& instruction, Primitive::Type type) {
- HInstruction* first = LoadLocal(instruction.VRegA(), type);
- HInstruction* second = LoadLocal(instruction.VRegB(), Primitive::kPrimInt);
- current_block_->AddInstruction(new (arena_) T(type, first, second));
- UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
+void HGraphBuilder::Binop_12x_shift(const Instruction& instruction, Primitive::Type type,
+ uint32_t dex_pc) {
+ HInstruction* first = LoadLocal(instruction.VRegA(), type, dex_pc);
+ HInstruction* second = LoadLocal(instruction.VRegB(), Primitive::kPrimInt, dex_pc);
+ current_block_->AddInstruction(new (arena_) T(type, first, second, dex_pc));
+ UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction(), dex_pc);
}
template<typename T>
void HGraphBuilder::Binop_12x(const Instruction& instruction,
Primitive::Type type,
uint32_t dex_pc) {
- HInstruction* first = LoadLocal(instruction.VRegA(), type);
- HInstruction* second = LoadLocal(instruction.VRegB(), type);
+ HInstruction* first = LoadLocal(instruction.VRegA(), type, dex_pc);
+ HInstruction* second = LoadLocal(instruction.VRegB(), type, dex_pc);
current_block_->AddInstruction(new (arena_) T(type, first, second, dex_pc));
- UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
+ UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction(), dex_pc);
}
template<typename T>
-void HGraphBuilder::Binop_22s(const Instruction& instruction, bool reverse) {
- HInstruction* first = LoadLocal(instruction.VRegB(), Primitive::kPrimInt);
- HInstruction* second = graph_->GetIntConstant(instruction.VRegC_22s());
+void HGraphBuilder::Binop_22s(const Instruction& instruction, bool reverse, uint32_t dex_pc) {
+ HInstruction* first = LoadLocal(instruction.VRegB(), Primitive::kPrimInt, dex_pc);
+ HInstruction* second = graph_->GetIntConstant(instruction.VRegC_22s(), dex_pc);
if (reverse) {
std::swap(first, second);
}
- current_block_->AddInstruction(new (arena_) T(Primitive::kPrimInt, first, second));
- UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
+ current_block_->AddInstruction(new (arena_) T(Primitive::kPrimInt, first, second, dex_pc));
+ UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction(), dex_pc);
}
template<typename T>
-void HGraphBuilder::Binop_22b(const Instruction& instruction, bool reverse) {
- HInstruction* first = LoadLocal(instruction.VRegB(), Primitive::kPrimInt);
- HInstruction* second = graph_->GetIntConstant(instruction.VRegC_22b());
+void HGraphBuilder::Binop_22b(const Instruction& instruction, bool reverse, uint32_t dex_pc) {
+ HInstruction* first = LoadLocal(instruction.VRegB(), Primitive::kPrimInt, dex_pc);
+ HInstruction* second = graph_->GetIntConstant(instruction.VRegC_22b(), dex_pc);
if (reverse) {
std::swap(first, second);
}
- current_block_->AddInstruction(new (arena_) T(Primitive::kPrimInt, first, second));
- UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
+ current_block_->AddInstruction(new (arena_) T(Primitive::kPrimInt, first, second, dex_pc));
+ UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction(), dex_pc);
}
static bool RequiresConstructorBarrier(const DexCompilationUnit* cu, const CompilerDriver& driver) {
@@ -740,7 +730,9 @@
&& driver.RequiresConstructorBarrier(self, cu->GetDexFile(), cu->GetClassDefIndex());
}
-void HGraphBuilder::BuildReturn(const Instruction& instruction, Primitive::Type type) {
+void HGraphBuilder::BuildReturn(const Instruction& instruction,
+ Primitive::Type type,
+ uint32_t dex_pc) {
if (type == Primitive::kPrimVoid) {
if (graph_->ShouldGenerateConstructorBarrier()) {
// The compilation unit is null during testing.
@@ -748,12 +740,12 @@
DCHECK(RequiresConstructorBarrier(dex_compilation_unit_, *compiler_driver_))
<< "Inconsistent use of ShouldGenerateConstructorBarrier. Should not generate a barrier.";
}
- current_block_->AddInstruction(new (arena_) HMemoryBarrier(kStoreStore));
+ current_block_->AddInstruction(new (arena_) HMemoryBarrier(kStoreStore, dex_pc));
}
- current_block_->AddInstruction(new (arena_) HReturnVoid());
+ current_block_->AddInstruction(new (arena_) HReturnVoid(dex_pc));
} else {
- HInstruction* value = LoadLocal(instruction.VRegA(), type);
- current_block_->AddInstruction(new (arena_) HReturn(value));
+ HInstruction* value = LoadLocal(instruction.VRegA(), type, dex_pc);
+ current_block_->AddInstruction(new (arena_) HReturn(value, dex_pc));
}
current_block_->AddSuccessor(exit_block_);
current_block_ = nullptr;
@@ -1050,6 +1042,7 @@
size_t start_index = 0;
size_t argument_index = 0;
uint32_t descriptor_index = 1; // Skip the return type.
+ uint32_t dex_pc = invoke->GetDexPc();
bool is_instance_call = invoke->GetOriginalInvokeType() != InvokeType::kStatic;
bool is_string_init = invoke->IsInvokeStaticOrDirect()
@@ -1060,7 +1053,7 @@
argument_index = 0;
} else if (is_instance_call) {
Temporaries temps(graph_);
- HInstruction* arg = LoadLocal(is_range ? register_index : args[0], Primitive::kPrimNot);
+ HInstruction* arg = LoadLocal(is_range ? register_index : args[0], Primitive::kPrimNot, dex_pc);
HNullCheck* null_check = new (arena_) HNullCheck(arg, invoke->GetDexPc());
current_block_->AddInstruction(null_check);
temps.Add(null_check);
@@ -1089,7 +1082,7 @@
MaybeRecordStat(MethodCompilationStat::kNotCompiledMalformedOpcode);
return false;
}
- HInstruction* arg = LoadLocal(is_range ? register_index + i : args[i], type);
+ HInstruction* arg = LoadLocal(is_range ? register_index + i : args[i], type, dex_pc);
invoke->SetArgumentAt(argument_index, arg);
if (is_wide) {
i++;
@@ -1122,7 +1115,7 @@
// Add move-result for StringFactory method.
if (is_string_init) {
uint32_t orig_this_reg = is_range ? register_index : args[0];
- HInstruction* fake_string = LoadLocal(orig_this_reg, Primitive::kPrimNot);
+ HInstruction* fake_string = LoadLocal(orig_this_reg, Primitive::kPrimNot, dex_pc);
invoke->SetArgumentAt(argument_index, fake_string);
current_block_->AddInstruction(invoke);
PotentiallySimplifyFakeString(orig_this_reg, invoke->GetDexPc(), invoke);
@@ -1148,15 +1141,15 @@
const VerifiedMethod* verified_method =
compiler_driver_->GetVerifiedMethod(dex_file_, dex_compilation_unit_->GetDexMethodIndex());
if (verified_method != nullptr) {
- UpdateLocal(original_dex_register, actual_string);
+ UpdateLocal(original_dex_register, actual_string, dex_pc);
const SafeMap<uint32_t, std::set<uint32_t>>& string_init_map =
verified_method->GetStringInitPcRegMap();
auto map_it = string_init_map.find(dex_pc);
if (map_it != string_init_map.end()) {
std::set<uint32_t> reg_set = map_it->second;
for (auto set_it = reg_set.begin(); set_it != reg_set.end(); ++set_it) {
- HInstruction* load_local = LoadLocal(original_dex_register, Primitive::kPrimNot);
- UpdateLocal(*set_it, load_local);
+ HInstruction* load_local = LoadLocal(original_dex_register, Primitive::kPrimNot, dex_pc);
+ UpdateLocal(*set_it, load_local, dex_pc);
}
}
} else {
@@ -1190,14 +1183,14 @@
Primitive::Type field_type = resolved_field->GetTypeAsPrimitiveType();
- HInstruction* object = LoadLocal(obj_reg, Primitive::kPrimNot);
+ HInstruction* object = LoadLocal(obj_reg, Primitive::kPrimNot, dex_pc);
current_block_->AddInstruction(new (arena_) HNullCheck(object, dex_pc));
if (is_put) {
Temporaries temps(graph_);
HInstruction* null_check = current_block_->GetLastInstruction();
// We need one temporary for the null check.
temps.Add(null_check);
- HInstruction* value = LoadLocal(source_or_dest_reg, field_type);
+ HInstruction* value = LoadLocal(source_or_dest_reg, field_type, dex_pc);
current_block_->AddInstruction(new (arena_) HInstanceFieldSet(
null_check,
value,
@@ -1206,7 +1199,8 @@
resolved_field->IsVolatile(),
field_index,
*dex_file_,
- dex_compilation_unit_->GetDexCache()));
+ dex_compilation_unit_->GetDexCache(),
+ dex_pc));
} else {
current_block_->AddInstruction(new (arena_) HInstanceFieldGet(
current_block_->GetLastInstruction(),
@@ -1215,9 +1209,10 @@
resolved_field->IsVolatile(),
field_index,
*dex_file_,
- dex_compilation_unit_->GetDexCache()));
+ dex_compilation_unit_->GetDexCache(),
+ dex_pc));
- UpdateLocal(source_or_dest_reg, current_block_->GetLastInstruction());
+ UpdateLocal(source_or_dest_reg, current_block_->GetLastInstruction(), dex_pc);
}
return true;
}
@@ -1328,7 +1323,7 @@
// We need to keep the class alive before loading the value.
Temporaries temps(graph_);
temps.Add(cls);
- HInstruction* value = LoadLocal(source_or_dest_reg, field_type);
+ HInstruction* value = LoadLocal(source_or_dest_reg, field_type, dex_pc);
DCHECK_EQ(value->GetType(), field_type);
current_block_->AddInstruction(new (arena_) HStaticFieldSet(cls,
value,
@@ -1337,7 +1332,8 @@
resolved_field->IsVolatile(),
field_index,
*dex_file_,
- dex_cache_));
+ dex_cache_,
+ dex_pc));
} else {
current_block_->AddInstruction(new (arena_) HStaticFieldGet(cls,
field_type,
@@ -1345,8 +1341,9 @@
resolved_field->IsVolatile(),
field_index,
*dex_file_,
- dex_cache_));
- UpdateLocal(source_or_dest_reg, current_block_->GetLastInstruction());
+ dex_cache_,
+ dex_pc));
+ UpdateLocal(source_or_dest_reg, current_block_->GetLastInstruction(), dex_pc);
}
return true;
}
@@ -1360,16 +1357,16 @@
bool isDiv) {
DCHECK(type == Primitive::kPrimInt || type == Primitive::kPrimLong);
- HInstruction* first = LoadLocal(first_vreg, type);
+ HInstruction* first = LoadLocal(first_vreg, type, dex_pc);
HInstruction* second = nullptr;
if (second_is_constant) {
if (type == Primitive::kPrimInt) {
- second = graph_->GetIntConstant(second_vreg_or_constant);
+ second = graph_->GetIntConstant(second_vreg_or_constant, dex_pc);
} else {
- second = graph_->GetLongConstant(second_vreg_or_constant);
+ second = graph_->GetLongConstant(second_vreg_or_constant, dex_pc);
}
} else {
- second = LoadLocal(second_vreg_or_constant, type);
+ second = LoadLocal(second_vreg_or_constant, type, dex_pc);
}
if (!second_is_constant
@@ -1386,7 +1383,7 @@
} else {
current_block_->AddInstruction(new (arena_) HRem(type, first, second, dex_pc));
}
- UpdateLocal(out_vreg, current_block_->GetLastInstruction());
+ UpdateLocal(out_vreg, current_block_->GetLastInstruction(), dex_pc);
}
void HGraphBuilder::BuildArrayAccess(const Instruction& instruction,
@@ -1400,26 +1397,26 @@
// We need one temporary for the null check, one for the index, and one for the length.
Temporaries temps(graph_);
- HInstruction* object = LoadLocal(array_reg, Primitive::kPrimNot);
+ HInstruction* object = LoadLocal(array_reg, Primitive::kPrimNot, dex_pc);
object = new (arena_) HNullCheck(object, dex_pc);
current_block_->AddInstruction(object);
temps.Add(object);
- HInstruction* length = new (arena_) HArrayLength(object);
+ HInstruction* length = new (arena_) HArrayLength(object, dex_pc);
current_block_->AddInstruction(length);
temps.Add(length);
- HInstruction* index = LoadLocal(index_reg, Primitive::kPrimInt);
+ HInstruction* index = LoadLocal(index_reg, Primitive::kPrimInt, dex_pc);
index = new (arena_) HBoundsCheck(index, length, dex_pc);
current_block_->AddInstruction(index);
temps.Add(index);
if (is_put) {
- HInstruction* value = LoadLocal(source_or_dest_reg, anticipated_type);
+ HInstruction* value = LoadLocal(source_or_dest_reg, anticipated_type, dex_pc);
// TODO: Insert a type check node if the type is Object.
current_block_->AddInstruction(new (arena_) HArraySet(
object, index, value, anticipated_type, dex_pc));
} else {
- current_block_->AddInstruction(new (arena_) HArrayGet(object, index, anticipated_type));
- UpdateLocal(source_or_dest_reg, current_block_->GetLastInstruction());
+ current_block_->AddInstruction(new (arena_) HArrayGet(object, index, anticipated_type, dex_pc));
+ UpdateLocal(source_or_dest_reg, current_block_->GetLastInstruction(), dex_pc);
}
graph_->SetHasBoundsChecks(true);
}
@@ -1430,7 +1427,7 @@
bool is_range,
uint32_t* args,
uint32_t register_index) {
- HInstruction* length = graph_->GetIntConstant(number_of_vreg_arguments);
+ HInstruction* length = graph_->GetIntConstant(number_of_vreg_arguments, dex_pc);
QuickEntrypointEnum entrypoint = NeedsAccessCheck(type_index)
? kQuickAllocArrayWithAccessCheck
: kQuickAllocArray;
@@ -1454,8 +1451,8 @@
Temporaries temps(graph_);
temps.Add(object);
for (size_t i = 0; i < number_of_vreg_arguments; ++i) {
- HInstruction* value = LoadLocal(is_range ? register_index + i : args[i], type);
- HInstruction* index = graph_->GetIntConstant(i);
+ HInstruction* value = LoadLocal(is_range ? register_index + i : args[i], type, dex_pc);
+ HInstruction* index = graph_->GetIntConstant(i, dex_pc);
current_block_->AddInstruction(
new (arena_) HArraySet(object, index, value, type, dex_pc));
}
@@ -1469,8 +1466,8 @@
Primitive::Type anticipated_type,
uint32_t dex_pc) {
for (uint32_t i = 0; i < element_count; ++i) {
- HInstruction* index = graph_->GetIntConstant(i);
- HInstruction* value = graph_->GetIntConstant(data[i]);
+ HInstruction* index = graph_->GetIntConstant(i, dex_pc);
+ HInstruction* value = graph_->GetIntConstant(data[i], dex_pc);
current_block_->AddInstruction(new (arena_) HArraySet(
object, index, value, anticipated_type, dex_pc));
}
@@ -1478,12 +1475,12 @@
void HGraphBuilder::BuildFillArrayData(const Instruction& instruction, uint32_t dex_pc) {
Temporaries temps(graph_);
- HInstruction* array = LoadLocal(instruction.VRegA_31t(), Primitive::kPrimNot);
+ HInstruction* array = LoadLocal(instruction.VRegA_31t(), Primitive::kPrimNot, dex_pc);
HNullCheck* null_check = new (arena_) HNullCheck(array, dex_pc);
current_block_->AddInstruction(null_check);
temps.Add(null_check);
- HInstruction* length = new (arena_) HArrayLength(null_check);
+ HInstruction* length = new (arena_) HArrayLength(null_check, dex_pc);
current_block_->AddInstruction(length);
int32_t payload_offset = instruction.VRegB_31t() + dex_pc;
@@ -1494,7 +1491,7 @@
// Implementation of this DEX instruction seems to be that the bounds check is
// done before doing any stores.
- HInstruction* last_index = graph_->GetIntConstant(payload->element_count - 1);
+ HInstruction* last_index = graph_->GetIntConstant(payload->element_count - 1, dex_pc);
current_block_->AddInstruction(new (arena_) HBoundsCheck(last_index, length, dex_pc));
switch (payload->element_width) {
@@ -1536,8 +1533,8 @@
uint32_t element_count,
uint32_t dex_pc) {
for (uint32_t i = 0; i < element_count; ++i) {
- HInstruction* index = graph_->GetIntConstant(i);
- HInstruction* value = graph_->GetLongConstant(data[i]);
+ HInstruction* index = graph_->GetIntConstant(i, dex_pc);
+ HInstruction* value = graph_->GetLongConstant(data[i], dex_pc);
current_block_->AddInstruction(new (arena_) HArraySet(
object, index, value, Primitive::kPrimLong, dex_pc));
}
@@ -1562,7 +1559,7 @@
MaybeRecordStat(MethodCompilationStat::kNotCompiledCantAccesType);
return false;
}
- HInstruction* object = LoadLocal(reference, Primitive::kPrimNot);
+ HInstruction* object = LoadLocal(reference, Primitive::kPrimNot, dex_pc);
HLoadClass* cls = new (arena_) HLoadClass(
graph_->GetCurrentMethod(),
type_index,
@@ -1576,7 +1573,7 @@
if (instruction.Opcode() == Instruction::INSTANCE_OF) {
current_block_->AddInstruction(
new (arena_) HInstanceOf(object, cls, type_known_final, dex_pc));
- UpdateLocal(destination, current_block_->GetLastInstruction());
+ UpdateLocal(destination, current_block_->GetLastInstruction(), dex_pc);
} else {
DCHECK_EQ(instruction.Opcode(), Instruction::CHECK_CAST);
current_block_->AddInstruction(
@@ -1598,7 +1595,7 @@
SwitchTable table(instruction, dex_pc, false);
// Value to test against.
- HInstruction* value = LoadLocal(instruction.VRegA(), Primitive::kPrimInt);
+ HInstruction* value = LoadLocal(instruction.VRegA(), Primitive::kPrimInt, dex_pc);
// Retrieve number of entries.
uint16_t num_entries = table.GetNumEntries();
@@ -1623,7 +1620,7 @@
SwitchTable table(instruction, dex_pc, true);
// Value to test against.
- HInstruction* value = LoadLocal(instruction.VRegA(), Primitive::kPrimInt);
+ HInstruction* value = LoadLocal(instruction.VRegA(), Primitive::kPrimInt, dex_pc);
uint16_t num_entries = table.GetNumEntries();
@@ -1642,12 +1639,12 @@
PotentiallyAddSuspendCheck(case_target, dex_pc);
// The current case's value.
- HInstruction* this_case_value = graph_->GetIntConstant(case_value_int);
+ HInstruction* this_case_value = graph_->GetIntConstant(case_value_int, dex_pc);
// Compare value and this_case_value.
- HEqual* comparison = new (arena_) HEqual(value, this_case_value);
+ HEqual* comparison = new (arena_) HEqual(value, this_case_value, dex_pc);
current_block_->AddInstruction(comparison);
- HInstruction* ifinst = new (arena_) HIf(comparison);
+ HInstruction* ifinst = new (arena_) HIf(comparison, dex_pc);
current_block_->AddInstruction(ifinst);
// Case hit: use the target offset to determine where to go.
@@ -1711,29 +1708,29 @@
switch (instruction.Opcode()) {
case Instruction::CONST_4: {
int32_t register_index = instruction.VRegA();
- HIntConstant* constant = graph_->GetIntConstant(instruction.VRegB_11n());
- UpdateLocal(register_index, constant);
+ HIntConstant* constant = graph_->GetIntConstant(instruction.VRegB_11n(), dex_pc);
+ UpdateLocal(register_index, constant, dex_pc);
break;
}
case Instruction::CONST_16: {
int32_t register_index = instruction.VRegA();
- HIntConstant* constant = graph_->GetIntConstant(instruction.VRegB_21s());
- UpdateLocal(register_index, constant);
+ HIntConstant* constant = graph_->GetIntConstant(instruction.VRegB_21s(), dex_pc);
+ UpdateLocal(register_index, constant, dex_pc);
break;
}
case Instruction::CONST: {
int32_t register_index = instruction.VRegA();
- HIntConstant* constant = graph_->GetIntConstant(instruction.VRegB_31i());
- UpdateLocal(register_index, constant);
+ HIntConstant* constant = graph_->GetIntConstant(instruction.VRegB_31i(), dex_pc);
+ UpdateLocal(register_index, constant, dex_pc);
break;
}
case Instruction::CONST_HIGH16: {
int32_t register_index = instruction.VRegA();
- HIntConstant* constant = graph_->GetIntConstant(instruction.VRegB_21h() << 16);
- UpdateLocal(register_index, constant);
+ HIntConstant* constant = graph_->GetIntConstant(instruction.VRegB_21h() << 16, dex_pc);
+ UpdateLocal(register_index, constant, dex_pc);
break;
}
@@ -1743,8 +1740,8 @@
int64_t value = instruction.VRegB_21s();
value <<= 48;
value >>= 48;
- HLongConstant* constant = graph_->GetLongConstant(value);
- UpdateLocal(register_index, constant);
+ HLongConstant* constant = graph_->GetLongConstant(value, dex_pc);
+ UpdateLocal(register_index, constant, dex_pc);
break;
}
@@ -1754,23 +1751,23 @@
int64_t value = instruction.VRegB_31i();
value <<= 32;
value >>= 32;
- HLongConstant* constant = graph_->GetLongConstant(value);
- UpdateLocal(register_index, constant);
+ HLongConstant* constant = graph_->GetLongConstant(value, dex_pc);
+ UpdateLocal(register_index, constant, dex_pc);
break;
}
case Instruction::CONST_WIDE: {
int32_t register_index = instruction.VRegA();
- HLongConstant* constant = graph_->GetLongConstant(instruction.VRegB_51l());
- UpdateLocal(register_index, constant);
+ HLongConstant* constant = graph_->GetLongConstant(instruction.VRegB_51l(), dex_pc);
+ UpdateLocal(register_index, constant, dex_pc);
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);
- UpdateLocal(register_index, constant);
+ HLongConstant* constant = graph_->GetLongConstant(value, dex_pc);
+ UpdateLocal(register_index, constant, dex_pc);
break;
}
@@ -1778,8 +1775,8 @@
case Instruction::MOVE:
case Instruction::MOVE_FROM16:
case Instruction::MOVE_16: {
- HInstruction* value = LoadLocal(instruction.VRegB(), Primitive::kPrimInt);
- UpdateLocal(instruction.VRegA(), value);
+ HInstruction* value = LoadLocal(instruction.VRegB(), Primitive::kPrimInt, dex_pc);
+ UpdateLocal(instruction.VRegA(), value, dex_pc);
break;
}
@@ -1787,22 +1784,22 @@
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);
+ HInstruction* value = LoadLocal(instruction.VRegB(), Primitive::kPrimLong, dex_pc);
+ UpdateLocal(instruction.VRegA(), value, dex_pc);
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);
+ HInstruction* value = LoadLocal(instruction.VRegB(), Primitive::kPrimNot, dex_pc);
+ UpdateLocal(instruction.VRegA(), value, dex_pc);
break;
}
case Instruction::RETURN_VOID_NO_BARRIER:
case Instruction::RETURN_VOID: {
- BuildReturn(instruction, Primitive::kPrimVoid);
+ BuildReturn(instruction, Primitive::kPrimVoid, dex_pc);
break;
}
@@ -1824,24 +1821,24 @@
HBasicBlock* target = FindBlockStartingAt(offset + dex_pc);
DCHECK(target != nullptr);
PotentiallyAddSuspendCheck(target, dex_pc);
- current_block_->AddInstruction(new (arena_) HGoto());
+ current_block_->AddInstruction(new (arena_) HGoto(dex_pc));
current_block_->AddSuccessor(target);
current_block_ = nullptr;
break;
}
case Instruction::RETURN: {
- BuildReturn(instruction, return_type_);
+ BuildReturn(instruction, return_type_, dex_pc);
break;
}
case Instruction::RETURN_OBJECT: {
- BuildReturn(instruction, return_type_);
+ BuildReturn(instruction, return_type_, dex_pc);
break;
}
case Instruction::RETURN_WIDE: {
- BuildReturn(instruction, return_type_);
+ BuildReturn(instruction, return_type_, dex_pc);
break;
}
@@ -1895,32 +1892,32 @@
}
case Instruction::NEG_INT: {
- Unop_12x<HNeg>(instruction, Primitive::kPrimInt);
+ Unop_12x<HNeg>(instruction, Primitive::kPrimInt, dex_pc);
break;
}
case Instruction::NEG_LONG: {
- Unop_12x<HNeg>(instruction, Primitive::kPrimLong);
+ Unop_12x<HNeg>(instruction, Primitive::kPrimLong, dex_pc);
break;
}
case Instruction::NEG_FLOAT: {
- Unop_12x<HNeg>(instruction, Primitive::kPrimFloat);
+ Unop_12x<HNeg>(instruction, Primitive::kPrimFloat, dex_pc);
break;
}
case Instruction::NEG_DOUBLE: {
- Unop_12x<HNeg>(instruction, Primitive::kPrimDouble);
+ Unop_12x<HNeg>(instruction, Primitive::kPrimDouble, dex_pc);
break;
}
case Instruction::NOT_INT: {
- Unop_12x<HNot>(instruction, Primitive::kPrimInt);
+ Unop_12x<HNot>(instruction, Primitive::kPrimInt, dex_pc);
break;
}
case Instruction::NOT_LONG: {
- Unop_12x<HNot>(instruction, Primitive::kPrimLong);
+ Unop_12x<HNot>(instruction, Primitive::kPrimLong, dex_pc);
break;
}
@@ -2000,67 +1997,67 @@
}
case Instruction::ADD_INT: {
- Binop_23x<HAdd>(instruction, Primitive::kPrimInt);
+ Binop_23x<HAdd>(instruction, Primitive::kPrimInt, dex_pc);
break;
}
case Instruction::ADD_LONG: {
- Binop_23x<HAdd>(instruction, Primitive::kPrimLong);
+ Binop_23x<HAdd>(instruction, Primitive::kPrimLong, dex_pc);
break;
}
case Instruction::ADD_DOUBLE: {
- Binop_23x<HAdd>(instruction, Primitive::kPrimDouble);
+ Binop_23x<HAdd>(instruction, Primitive::kPrimDouble, dex_pc);
break;
}
case Instruction::ADD_FLOAT: {
- Binop_23x<HAdd>(instruction, Primitive::kPrimFloat);
+ Binop_23x<HAdd>(instruction, Primitive::kPrimFloat, dex_pc);
break;
}
case Instruction::SUB_INT: {
- Binop_23x<HSub>(instruction, Primitive::kPrimInt);
+ Binop_23x<HSub>(instruction, Primitive::kPrimInt, dex_pc);
break;
}
case Instruction::SUB_LONG: {
- Binop_23x<HSub>(instruction, Primitive::kPrimLong);
+ Binop_23x<HSub>(instruction, Primitive::kPrimLong, dex_pc);
break;
}
case Instruction::SUB_FLOAT: {
- Binop_23x<HSub>(instruction, Primitive::kPrimFloat);
+ Binop_23x<HSub>(instruction, Primitive::kPrimFloat, dex_pc);
break;
}
case Instruction::SUB_DOUBLE: {
- Binop_23x<HSub>(instruction, Primitive::kPrimDouble);
+ Binop_23x<HSub>(instruction, Primitive::kPrimDouble, dex_pc);
break;
}
case Instruction::ADD_INT_2ADDR: {
- Binop_12x<HAdd>(instruction, Primitive::kPrimInt);
+ Binop_12x<HAdd>(instruction, Primitive::kPrimInt, dex_pc);
break;
}
case Instruction::MUL_INT: {
- Binop_23x<HMul>(instruction, Primitive::kPrimInt);
+ Binop_23x<HMul>(instruction, Primitive::kPrimInt, dex_pc);
break;
}
case Instruction::MUL_LONG: {
- Binop_23x<HMul>(instruction, Primitive::kPrimLong);
+ Binop_23x<HMul>(instruction, Primitive::kPrimLong, dex_pc);
break;
}
case Instruction::MUL_FLOAT: {
- Binop_23x<HMul>(instruction, Primitive::kPrimFloat);
+ Binop_23x<HMul>(instruction, Primitive::kPrimFloat, dex_pc);
break;
}
case Instruction::MUL_DOUBLE: {
- Binop_23x<HMul>(instruction, Primitive::kPrimDouble);
+ Binop_23x<HMul>(instruction, Primitive::kPrimDouble, dex_pc);
break;
}
@@ -2109,117 +2106,117 @@
}
case Instruction::AND_INT: {
- Binop_23x<HAnd>(instruction, Primitive::kPrimInt);
+ Binop_23x<HAnd>(instruction, Primitive::kPrimInt, dex_pc);
break;
}
case Instruction::AND_LONG: {
- Binop_23x<HAnd>(instruction, Primitive::kPrimLong);
+ Binop_23x<HAnd>(instruction, Primitive::kPrimLong, dex_pc);
break;
}
case Instruction::SHL_INT: {
- Binop_23x_shift<HShl>(instruction, Primitive::kPrimInt);
+ Binop_23x_shift<HShl>(instruction, Primitive::kPrimInt, dex_pc);
break;
}
case Instruction::SHL_LONG: {
- Binop_23x_shift<HShl>(instruction, Primitive::kPrimLong);
+ Binop_23x_shift<HShl>(instruction, Primitive::kPrimLong, dex_pc);
break;
}
case Instruction::SHR_INT: {
- Binop_23x_shift<HShr>(instruction, Primitive::kPrimInt);
+ Binop_23x_shift<HShr>(instruction, Primitive::kPrimInt, dex_pc);
break;
}
case Instruction::SHR_LONG: {
- Binop_23x_shift<HShr>(instruction, Primitive::kPrimLong);
+ Binop_23x_shift<HShr>(instruction, Primitive::kPrimLong, dex_pc);
break;
}
case Instruction::USHR_INT: {
- Binop_23x_shift<HUShr>(instruction, Primitive::kPrimInt);
+ Binop_23x_shift<HUShr>(instruction, Primitive::kPrimInt, dex_pc);
break;
}
case Instruction::USHR_LONG: {
- Binop_23x_shift<HUShr>(instruction, Primitive::kPrimLong);
+ Binop_23x_shift<HUShr>(instruction, Primitive::kPrimLong, dex_pc);
break;
}
case Instruction::OR_INT: {
- Binop_23x<HOr>(instruction, Primitive::kPrimInt);
+ Binop_23x<HOr>(instruction, Primitive::kPrimInt, dex_pc);
break;
}
case Instruction::OR_LONG: {
- Binop_23x<HOr>(instruction, Primitive::kPrimLong);
+ Binop_23x<HOr>(instruction, Primitive::kPrimLong, dex_pc);
break;
}
case Instruction::XOR_INT: {
- Binop_23x<HXor>(instruction, Primitive::kPrimInt);
+ Binop_23x<HXor>(instruction, Primitive::kPrimInt, dex_pc);
break;
}
case Instruction::XOR_LONG: {
- Binop_23x<HXor>(instruction, Primitive::kPrimLong);
+ Binop_23x<HXor>(instruction, Primitive::kPrimLong, dex_pc);
break;
}
case Instruction::ADD_LONG_2ADDR: {
- Binop_12x<HAdd>(instruction, Primitive::kPrimLong);
+ Binop_12x<HAdd>(instruction, Primitive::kPrimLong, dex_pc);
break;
}
case Instruction::ADD_DOUBLE_2ADDR: {
- Binop_12x<HAdd>(instruction, Primitive::kPrimDouble);
+ Binop_12x<HAdd>(instruction, Primitive::kPrimDouble, dex_pc);
break;
}
case Instruction::ADD_FLOAT_2ADDR: {
- Binop_12x<HAdd>(instruction, Primitive::kPrimFloat);
+ Binop_12x<HAdd>(instruction, Primitive::kPrimFloat, dex_pc);
break;
}
case Instruction::SUB_INT_2ADDR: {
- Binop_12x<HSub>(instruction, Primitive::kPrimInt);
+ Binop_12x<HSub>(instruction, Primitive::kPrimInt, dex_pc);
break;
}
case Instruction::SUB_LONG_2ADDR: {
- Binop_12x<HSub>(instruction, Primitive::kPrimLong);
+ Binop_12x<HSub>(instruction, Primitive::kPrimLong, dex_pc);
break;
}
case Instruction::SUB_FLOAT_2ADDR: {
- Binop_12x<HSub>(instruction, Primitive::kPrimFloat);
+ Binop_12x<HSub>(instruction, Primitive::kPrimFloat, dex_pc);
break;
}
case Instruction::SUB_DOUBLE_2ADDR: {
- Binop_12x<HSub>(instruction, Primitive::kPrimDouble);
+ Binop_12x<HSub>(instruction, Primitive::kPrimDouble, dex_pc);
break;
}
case Instruction::MUL_INT_2ADDR: {
- Binop_12x<HMul>(instruction, Primitive::kPrimInt);
+ Binop_12x<HMul>(instruction, Primitive::kPrimInt, dex_pc);
break;
}
case Instruction::MUL_LONG_2ADDR: {
- Binop_12x<HMul>(instruction, Primitive::kPrimLong);
+ Binop_12x<HMul>(instruction, Primitive::kPrimLong, dex_pc);
break;
}
case Instruction::MUL_FLOAT_2ADDR: {
- Binop_12x<HMul>(instruction, Primitive::kPrimFloat);
+ Binop_12x<HMul>(instruction, Primitive::kPrimFloat, dex_pc);
break;
}
case Instruction::MUL_DOUBLE_2ADDR: {
- Binop_12x<HMul>(instruction, Primitive::kPrimDouble);
+ Binop_12x<HMul>(instruction, Primitive::kPrimDouble, dex_pc);
break;
}
@@ -2258,32 +2255,32 @@
}
case Instruction::SHL_INT_2ADDR: {
- Binop_12x_shift<HShl>(instruction, Primitive::kPrimInt);
+ Binop_12x_shift<HShl>(instruction, Primitive::kPrimInt, dex_pc);
break;
}
case Instruction::SHL_LONG_2ADDR: {
- Binop_12x_shift<HShl>(instruction, Primitive::kPrimLong);
+ Binop_12x_shift<HShl>(instruction, Primitive::kPrimLong, dex_pc);
break;
}
case Instruction::SHR_INT_2ADDR: {
- Binop_12x_shift<HShr>(instruction, Primitive::kPrimInt);
+ Binop_12x_shift<HShr>(instruction, Primitive::kPrimInt, dex_pc);
break;
}
case Instruction::SHR_LONG_2ADDR: {
- Binop_12x_shift<HShr>(instruction, Primitive::kPrimLong);
+ Binop_12x_shift<HShr>(instruction, Primitive::kPrimLong, dex_pc);
break;
}
case Instruction::USHR_INT_2ADDR: {
- Binop_12x_shift<HUShr>(instruction, Primitive::kPrimInt);
+ Binop_12x_shift<HUShr>(instruction, Primitive::kPrimInt, dex_pc);
break;
}
case Instruction::USHR_LONG_2ADDR: {
- Binop_12x_shift<HUShr>(instruction, Primitive::kPrimLong);
+ Binop_12x_shift<HUShr>(instruction, Primitive::kPrimLong, dex_pc);
break;
}
@@ -2298,92 +2295,92 @@
}
case Instruction::AND_INT_2ADDR: {
- Binop_12x<HAnd>(instruction, Primitive::kPrimInt);
+ Binop_12x<HAnd>(instruction, Primitive::kPrimInt, dex_pc);
break;
}
case Instruction::AND_LONG_2ADDR: {
- Binop_12x<HAnd>(instruction, Primitive::kPrimLong);
+ Binop_12x<HAnd>(instruction, Primitive::kPrimLong, dex_pc);
break;
}
case Instruction::OR_INT_2ADDR: {
- Binop_12x<HOr>(instruction, Primitive::kPrimInt);
+ Binop_12x<HOr>(instruction, Primitive::kPrimInt, dex_pc);
break;
}
case Instruction::OR_LONG_2ADDR: {
- Binop_12x<HOr>(instruction, Primitive::kPrimLong);
+ Binop_12x<HOr>(instruction, Primitive::kPrimLong, dex_pc);
break;
}
case Instruction::XOR_INT_2ADDR: {
- Binop_12x<HXor>(instruction, Primitive::kPrimInt);
+ Binop_12x<HXor>(instruction, Primitive::kPrimInt, dex_pc);
break;
}
case Instruction::XOR_LONG_2ADDR: {
- Binop_12x<HXor>(instruction, Primitive::kPrimLong);
+ Binop_12x<HXor>(instruction, Primitive::kPrimLong, dex_pc);
break;
}
case Instruction::ADD_INT_LIT16: {
- Binop_22s<HAdd>(instruction, false);
+ Binop_22s<HAdd>(instruction, false, dex_pc);
break;
}
case Instruction::AND_INT_LIT16: {
- Binop_22s<HAnd>(instruction, false);
+ Binop_22s<HAnd>(instruction, false, dex_pc);
break;
}
case Instruction::OR_INT_LIT16: {
- Binop_22s<HOr>(instruction, false);
+ Binop_22s<HOr>(instruction, false, dex_pc);
break;
}
case Instruction::XOR_INT_LIT16: {
- Binop_22s<HXor>(instruction, false);
+ Binop_22s<HXor>(instruction, false, dex_pc);
break;
}
case Instruction::RSUB_INT: {
- Binop_22s<HSub>(instruction, true);
+ Binop_22s<HSub>(instruction, true, dex_pc);
break;
}
case Instruction::MUL_INT_LIT16: {
- Binop_22s<HMul>(instruction, false);
+ Binop_22s<HMul>(instruction, false, dex_pc);
break;
}
case Instruction::ADD_INT_LIT8: {
- Binop_22b<HAdd>(instruction, false);
+ Binop_22b<HAdd>(instruction, false, dex_pc);
break;
}
case Instruction::AND_INT_LIT8: {
- Binop_22b<HAnd>(instruction, false);
+ Binop_22b<HAnd>(instruction, false, dex_pc);
break;
}
case Instruction::OR_INT_LIT8: {
- Binop_22b<HOr>(instruction, false);
+ Binop_22b<HOr>(instruction, false, dex_pc);
break;
}
case Instruction::XOR_INT_LIT8: {
- Binop_22b<HXor>(instruction, false);
+ Binop_22b<HXor>(instruction, false, dex_pc);
break;
}
case Instruction::RSUB_INT_LIT8: {
- Binop_22b<HSub>(instruction, true);
+ Binop_22b<HSub>(instruction, true, dex_pc);
break;
}
case Instruction::MUL_INT_LIT8: {
- Binop_22b<HMul>(instruction, false);
+ Binop_22b<HMul>(instruction, false, dex_pc);
break;
}
@@ -2402,17 +2399,17 @@
}
case Instruction::SHL_INT_LIT8: {
- Binop_22b<HShl>(instruction, false);
+ Binop_22b<HShl>(instruction, false, dex_pc);
break;
}
case Instruction::SHR_INT_LIT8: {
- Binop_22b<HShr>(instruction, false);
+ Binop_22b<HShr>(instruction, false, dex_pc);
break;
}
case Instruction::USHR_INT_LIT8: {
- Binop_22b<HUShr>(instruction, false);
+ Binop_22b<HUShr>(instruction, false, dex_pc);
break;
}
@@ -2420,9 +2417,9 @@
uint16_t type_index = instruction.VRegB_21c();
if (compiler_driver_->IsStringTypeIndex(type_index, dex_file_)) {
int32_t register_index = instruction.VRegA();
- HFakeString* fake_string = new (arena_) HFakeString();
+ HFakeString* fake_string = new (arena_) HFakeString(dex_pc);
current_block_->AddInstruction(fake_string);
- UpdateLocal(register_index, fake_string);
+ UpdateLocal(register_index, fake_string, dex_pc);
} else {
QuickEntrypointEnum entrypoint = NeedsAccessCheck(type_index)
? kQuickAllocObjectWithAccessCheck
@@ -2434,14 +2431,14 @@
type_index,
*dex_compilation_unit_->GetDexFile(),
entrypoint));
- UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction());
+ UpdateLocal(instruction.VRegA(), current_block_->GetLastInstruction(), dex_pc);
}
break;
}
case Instruction::NEW_ARRAY: {
uint16_t type_index = instruction.VRegC_22c();
- HInstruction* length = LoadLocal(instruction.VRegB_22c(), Primitive::kPrimInt);
+ HInstruction* length = LoadLocal(instruction.VRegB_22c(), Primitive::kPrimInt, dex_pc);
QuickEntrypointEnum entrypoint = NeedsAccessCheck(type_index)
? kQuickAllocArrayWithAccessCheck
: kQuickAllocArray;
@@ -2451,7 +2448,7 @@
type_index,
*dex_compilation_unit_->GetDexFile(),
entrypoint));
- UpdateLocal(instruction.VRegA_22c(), current_block_->GetLastInstruction());
+ UpdateLocal(instruction.VRegA_22c(), current_block_->GetLastInstruction(), dex_pc);
break;
}
@@ -2491,7 +2488,7 @@
// FilledNewArray, the local needs to be updated after the array was
// filled, otherwise we might overwrite an input vreg.
HStoreLocal* update_local =
- new (arena_) HStoreLocal(GetLocalAt(instruction.VRegA()), latest_result_);
+ new (arena_) HStoreLocal(GetLocalAt(instruction.VRegA()), latest_result_, dex_pc);
HBasicBlock* block = latest_result_->GetBlock();
if (block == current_block_) {
// MoveResult and the previous instruction are in the same block.
@@ -2621,27 +2618,27 @@
ARRAY_XX(_SHORT, Primitive::kPrimShort);
case Instruction::ARRAY_LENGTH: {
- HInstruction* object = LoadLocal(instruction.VRegB_12x(), Primitive::kPrimNot);
+ HInstruction* object = LoadLocal(instruction.VRegB_12x(), Primitive::kPrimNot, dex_pc);
// No need for a temporary for the null check, it is the only input of the following
// instruction.
object = new (arena_) HNullCheck(object, dex_pc);
current_block_->AddInstruction(object);
- current_block_->AddInstruction(new (arena_) HArrayLength(object));
- UpdateLocal(instruction.VRegA_12x(), current_block_->GetLastInstruction());
+ current_block_->AddInstruction(new (arena_) HArrayLength(object, dex_pc));
+ UpdateLocal(instruction.VRegA_12x(), current_block_->GetLastInstruction(), dex_pc);
break;
}
case Instruction::CONST_STRING: {
current_block_->AddInstruction(
new (arena_) HLoadString(graph_->GetCurrentMethod(), instruction.VRegB_21c(), dex_pc));
- UpdateLocal(instruction.VRegA_21c(), current_block_->GetLastInstruction());
+ UpdateLocal(instruction.VRegA_21c(), current_block_->GetLastInstruction(), dex_pc);
break;
}
case Instruction::CONST_STRING_JUMBO: {
current_block_->AddInstruction(
new (arena_) HLoadString(graph_->GetCurrentMethod(), instruction.VRegB_31c(), dex_pc));
- UpdateLocal(instruction.VRegA_31c(), current_block_->GetLastInstruction());
+ UpdateLocal(instruction.VRegA_31c(), current_block_->GetLastInstruction(), dex_pc);
break;
}
@@ -2667,19 +2664,19 @@
*dex_compilation_unit_->GetDexFile(),
IsOutermostCompilingClass(type_index),
dex_pc));
- UpdateLocal(instruction.VRegA_21c(), current_block_->GetLastInstruction());
+ UpdateLocal(instruction.VRegA_21c(), current_block_->GetLastInstruction(), dex_pc);
break;
}
case Instruction::MOVE_EXCEPTION: {
- current_block_->AddInstruction(new (arena_) HLoadException());
- UpdateLocal(instruction.VRegA_11x(), current_block_->GetLastInstruction());
- current_block_->AddInstruction(new (arena_) HClearException());
+ current_block_->AddInstruction(new (arena_) HLoadException(dex_pc));
+ UpdateLocal(instruction.VRegA_11x(), current_block_->GetLastInstruction(), dex_pc);
+ current_block_->AddInstruction(new (arena_) HClearException(dex_pc));
break;
}
case Instruction::THROW: {
- HInstruction* exception = LoadLocal(instruction.VRegA_11x(), Primitive::kPrimNot);
+ HInstruction* exception = LoadLocal(instruction.VRegA_11x(), Primitive::kPrimNot, dex_pc);
current_block_->AddInstruction(new (arena_) HThrow(exception, dex_pc));
// A throw instruction must branch to the exit block.
current_block_->AddSuccessor(exit_block_);
@@ -2710,7 +2707,7 @@
case Instruction::MONITOR_ENTER: {
current_block_->AddInstruction(new (arena_) HMonitorOperation(
- LoadLocal(instruction.VRegA_11x(), Primitive::kPrimNot),
+ LoadLocal(instruction.VRegA_11x(), Primitive::kPrimNot, dex_pc),
HMonitorOperation::kEnter,
dex_pc));
break;
@@ -2718,7 +2715,7 @@
case Instruction::MONITOR_EXIT: {
current_block_->AddInstruction(new (arena_) HMonitorOperation(
- LoadLocal(instruction.VRegA_11x(), Primitive::kPrimNot),
+ LoadLocal(instruction.VRegA_11x(), Primitive::kPrimNot, dex_pc),
HMonitorOperation::kExit,
dex_pc));
break;
@@ -2749,14 +2746,18 @@
return locals_.Get(register_index);
}
-void HGraphBuilder::UpdateLocal(int register_index, HInstruction* instruction) const {
+void HGraphBuilder::UpdateLocal(int register_index,
+ HInstruction* instruction,
+ uint32_t dex_pc) const {
HLocal* local = GetLocalAt(register_index);
- current_block_->AddInstruction(new (arena_) HStoreLocal(local, instruction));
+ current_block_->AddInstruction(new (arena_) HStoreLocal(local, instruction, dex_pc));
}
-HInstruction* HGraphBuilder::LoadLocal(int register_index, Primitive::Type type) const {
+HInstruction* HGraphBuilder::LoadLocal(int register_index,
+ Primitive::Type type,
+ uint32_t dex_pc) const {
HLocal* local = GetLocalAt(register_index);
- current_block_->AddInstruction(new (arena_) HLoadLocal(local, type));
+ current_block_->AddInstruction(new (arena_) HLoadLocal(local, type, dex_pc));
return current_block_->GetLastInstruction();
}
diff --git a/compiler/optimizing/builder.h b/compiler/optimizing/builder.h
index 560ed86..b0238dc 100644
--- a/compiler/optimizing/builder.h
+++ b/compiler/optimizing/builder.h
@@ -131,23 +131,20 @@
void InitializeLocals(uint16_t count);
HLocal* GetLocalAt(int register_index) const;
- void UpdateLocal(int register_index, HInstruction* instruction) const;
- HInstruction* LoadLocal(int register_index, Primitive::Type type) const;
+ void UpdateLocal(int register_index, HInstruction* instruction, uint32_t dex_pc) const;
+ HInstruction* LoadLocal(int register_index, Primitive::Type type, uint32_t dex_pc) const;
void PotentiallyAddSuspendCheck(HBasicBlock* target, uint32_t dex_pc);
void InitializeParameters(uint16_t number_of_parameters);
bool NeedsAccessCheck(uint32_t type_index) const;
template<typename T>
- void Unop_12x(const Instruction& instruction, Primitive::Type type);
-
- template<typename T>
- void Binop_23x(const Instruction& instruction, Primitive::Type type);
+ void Unop_12x(const Instruction& instruction, Primitive::Type type, uint32_t dex_pc);
template<typename T>
void Binop_23x(const Instruction& instruction, Primitive::Type type, uint32_t dex_pc);
template<typename T>
- void Binop_23x_shift(const Instruction& instruction, Primitive::Type type);
+ void Binop_23x_shift(const Instruction& instruction, Primitive::Type type, uint32_t dex_pc);
void Binop_23x_cmp(const Instruction& instruction,
Primitive::Type type,
@@ -155,19 +152,16 @@
uint32_t dex_pc);
template<typename T>
- void Binop_12x(const Instruction& instruction, Primitive::Type type);
-
- template<typename T>
void Binop_12x(const Instruction& instruction, Primitive::Type type, uint32_t dex_pc);
template<typename T>
- void Binop_12x_shift(const Instruction& instruction, Primitive::Type type);
+ void Binop_12x_shift(const Instruction& instruction, Primitive::Type type, uint32_t dex_pc);
template<typename T>
- void Binop_22b(const Instruction& instruction, bool reverse);
+ void Binop_22b(const Instruction& instruction, bool reverse, uint32_t dex_pc);
template<typename T>
- void Binop_22s(const Instruction& instruction, bool reverse);
+ void Binop_22s(const Instruction& instruction, bool reverse, uint32_t dex_pc);
template<typename T> void If_21t(const Instruction& instruction, uint32_t dex_pc);
template<typename T> void If_22t(const Instruction& instruction, uint32_t dex_pc);
@@ -185,7 +179,7 @@
bool second_is_lit,
bool is_div);
- void BuildReturn(const Instruction& instruction, Primitive::Type type);
+ void BuildReturn(const Instruction& instruction, Primitive::Type type, uint32_t dex_pc);
// Builds an instance field access node and returns whether the instruction is supported.
bool BuildInstanceFieldAccess(const Instruction& instruction, uint32_t dex_pc, bool is_put);
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index 679899a..438ef69 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -1560,25 +1560,7 @@
return;
}
- Register temp = invoke->GetLocations()->GetTemp(0).AsRegister<Register>();
- uint32_t method_offset = mirror::Class::EmbeddedVTableEntryOffset(
- invoke->GetVTableIndex(), kArmPointerSize).Uint32Value();
- LocationSummary* locations = invoke->GetLocations();
- Location receiver = locations->InAt(0);
- uint32_t class_offset = mirror::Object::ClassOffset().Int32Value();
- // temp = object->GetClass();
- DCHECK(receiver.IsRegister());
- __ LoadFromOffset(kLoadWord, temp, receiver.AsRegister<Register>(), class_offset);
- codegen_->MaybeRecordImplicitNullCheck(invoke);
- __ MaybeUnpoisonHeapReference(temp);
- // temp = temp->GetMethodAt(method_offset);
- uint32_t entry_point = ArtMethod::EntryPointFromQuickCompiledCodeOffset(
- kArmWordSize).Int32Value();
- __ LoadFromOffset(kLoadWord, temp, temp, method_offset);
- // LR = temp->GetEntryPoint();
- __ LoadFromOffset(kLoadWord, LR, temp, entry_point);
- // LR();
- __ blx(LR);
+ codegen_->GenerateVirtualCall(invoke, invoke->GetLocations()->GetTemp(0));
DCHECK(!codegen_->IsLeafMethod());
codegen_->RecordPcInfo(invoke, invoke->GetDexPc());
}
@@ -4607,6 +4589,28 @@
DCHECK(!IsLeafMethod());
}
+void CodeGeneratorARM::GenerateVirtualCall(HInvokeVirtual* invoke, Location temp_location) {
+ Register temp = temp_location.AsRegister<Register>();
+ uint32_t method_offset = mirror::Class::EmbeddedVTableEntryOffset(
+ invoke->GetVTableIndex(), kArmPointerSize).Uint32Value();
+ LocationSummary* locations = invoke->GetLocations();
+ Location receiver = locations->InAt(0);
+ uint32_t class_offset = mirror::Object::ClassOffset().Int32Value();
+ // temp = object->GetClass();
+ DCHECK(receiver.IsRegister());
+ __ LoadFromOffset(kLoadWord, temp, receiver.AsRegister<Register>(), class_offset);
+ MaybeRecordImplicitNullCheck(invoke);
+ __ MaybeUnpoisonHeapReference(temp);
+ // temp = temp->GetMethodAt(method_offset);
+ uint32_t entry_point = ArtMethod::EntryPointFromQuickCompiledCodeOffset(
+ kArmWordSize).Int32Value();
+ __ LoadFromOffset(kLoadWord, temp, temp, method_offset);
+ // LR = temp->GetEntryPoint();
+ __ LoadFromOffset(kLoadWord, LR, temp, entry_point);
+ // LR();
+ __ blx(LR);
+}
+
void CodeGeneratorARM::EmitLinkerPatches(ArenaVector<LinkerPatch>* linker_patches) {
DCHECK(linker_patches->empty());
size_t size = method_patches_.size() + call_patches_.size() + relative_call_patches_.size();
diff --git a/compiler/optimizing/code_generator_arm.h b/compiler/optimizing/code_generator_arm.h
index 9528cca..4a0df4e 100644
--- a/compiler/optimizing/code_generator_arm.h
+++ b/compiler/optimizing/code_generator_arm.h
@@ -327,6 +327,7 @@
Label* GetFrameEntryLabel() { return &frame_entry_label_; }
void GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Location temp);
+ void GenerateVirtualCall(HInvokeVirtual* invoke, Location temp);
void EmitLinkerPatches(ArenaVector<LinkerPatch>* linker_patches) OVERRIDE;
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc
index 390ea6b..6b1457b 100644
--- a/compiler/optimizing/code_generator_arm64.cc
+++ b/compiler/optimizing/code_generator_arm64.cc
@@ -2474,6 +2474,29 @@
DCHECK(!IsLeafMethod());
}
+void CodeGeneratorARM64::GenerateVirtualCall(HInvokeVirtual* invoke, Location temp_in) {
+ LocationSummary* locations = invoke->GetLocations();
+ Location receiver = locations->InAt(0);
+ Register temp = XRegisterFrom(temp_in);
+ size_t method_offset = mirror::Class::EmbeddedVTableEntryOffset(
+ invoke->GetVTableIndex(), kArm64PointerSize).SizeValue();
+ Offset class_offset = mirror::Object::ClassOffset();
+ Offset entry_point = ArtMethod::EntryPointFromQuickCompiledCodeOffset(kArm64WordSize);
+
+ BlockPoolsScope block_pools(GetVIXLAssembler());
+
+ DCHECK(receiver.IsRegister());
+ __ Ldr(temp.W(), HeapOperandFrom(receiver, class_offset));
+ MaybeRecordImplicitNullCheck(invoke);
+ GetAssembler()->MaybeUnpoisonHeapReference(temp.W());
+ // temp = temp->GetMethodAt(method_offset);
+ __ Ldr(temp, MemOperand(temp, method_offset));
+ // lr = temp->GetEntryPoint();
+ __ Ldr(lr, MemOperand(temp, entry_point.SizeValue()));
+ // lr();
+ __ Blr(lr);
+}
+
void CodeGeneratorARM64::EmitLinkerPatches(ArenaVector<LinkerPatch>* linker_patches) {
DCHECK(linker_patches->empty());
size_t size =
@@ -2567,26 +2590,7 @@
return;
}
- LocationSummary* locations = invoke->GetLocations();
- Location receiver = locations->InAt(0);
- Register temp = XRegisterFrom(invoke->GetLocations()->GetTemp(0));
- size_t method_offset = mirror::Class::EmbeddedVTableEntryOffset(
- invoke->GetVTableIndex(), kArm64PointerSize).SizeValue();
- Offset class_offset = mirror::Object::ClassOffset();
- Offset entry_point = ArtMethod::EntryPointFromQuickCompiledCodeOffset(kArm64WordSize);
-
- BlockPoolsScope block_pools(GetVIXLAssembler());
-
- DCHECK(receiver.IsRegister());
- __ Ldr(temp.W(), HeapOperandFrom(receiver, class_offset));
- codegen_->MaybeRecordImplicitNullCheck(invoke);
- GetAssembler()->MaybeUnpoisonHeapReference(temp.W());
- // temp = temp->GetMethodAt(method_offset);
- __ Ldr(temp, MemOperand(temp, method_offset));
- // lr = temp->GetEntryPoint();
- __ Ldr(lr, MemOperand(temp, entry_point.SizeValue()));
- // lr();
- __ Blr(lr);
+ codegen_->GenerateVirtualCall(invoke, invoke->GetLocations()->GetTemp(0));
DCHECK(!codegen_->IsLeafMethod());
codegen_->RecordPcInfo(invoke, invoke->GetDexPc());
}
diff --git a/compiler/optimizing/code_generator_arm64.h b/compiler/optimizing/code_generator_arm64.h
index 18070fc..12ead7e 100644
--- a/compiler/optimizing/code_generator_arm64.h
+++ b/compiler/optimizing/code_generator_arm64.h
@@ -359,6 +359,7 @@
}
void GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Location temp);
+ void GenerateVirtualCall(HInvokeVirtual* invoke, Location temp);
void EmitLinkerPatches(ArenaVector<LinkerPatch>* linker_patches) OVERRIDE;
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index f48395b..a5ad226 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -19,6 +19,7 @@
#include "art_method.h"
#include "code_generator_utils.h"
#include "compiled_method.h"
+#include "constant_area_fixups_x86.h"
#include "entrypoints/quick/quick_entrypoints.h"
#include "entrypoints/quick/quick_entrypoints_enum.h"
#include "gc/accounting/card_table.h"
@@ -1548,23 +1549,11 @@
}
void InstructionCodeGeneratorX86::VisitInvokeVirtual(HInvokeVirtual* invoke) {
- Register temp = invoke->GetLocations()->GetTemp(0).AsRegister<Register>();
- uint32_t method_offset = mirror::Class::EmbeddedVTableEntryOffset(
- invoke->GetVTableIndex(), kX86PointerSize).Uint32Value();
- LocationSummary* locations = invoke->GetLocations();
- Location receiver = locations->InAt(0);
- uint32_t class_offset = mirror::Object::ClassOffset().Int32Value();
- // temp = object->GetClass();
- DCHECK(receiver.IsRegister());
- __ movl(temp, Address(receiver.AsRegister<Register>(), class_offset));
- codegen_->MaybeRecordImplicitNullCheck(invoke);
- __ MaybeUnpoisonHeapReference(temp);
- // temp = temp->GetMethodAt(method_offset);
- __ movl(temp, Address(temp, method_offset));
- // call temp->GetEntryPoint();
- __ call(Address(
- temp, ArtMethod::EntryPointFromQuickCompiledCodeOffset(kX86WordSize).Int32Value()));
+ if (TryGenerateIntrinsicCode(invoke, codegen_)) {
+ return;
+ }
+ codegen_->GenerateVirtualCall(invoke, invoke->GetLocations()->GetTemp(0));
DCHECK(!codegen_->IsLeafMethod());
codegen_->RecordPcInfo(invoke, invoke->GetDexPc());
}
@@ -2213,7 +2202,7 @@
case Primitive::kPrimFloat:
case Primitive::kPrimDouble: {
locations->SetInAt(0, Location::RequiresFpuRegister());
- locations->SetInAt(1, Location::RequiresFpuRegister());
+ locations->SetInAt(1, Location::Any());
locations->SetOut(Location::SameAsFirstInput());
break;
}
@@ -2275,6 +2264,16 @@
case Primitive::kPrimFloat: {
if (second.IsFpuRegister()) {
__ addss(first.AsFpuRegister<XmmRegister>(), second.AsFpuRegister<XmmRegister>());
+ } else if (add->InputAt(1)->IsX86LoadFromConstantTable()) {
+ HX86LoadFromConstantTable* const_area = add->InputAt(1)->AsX86LoadFromConstantTable();
+ DCHECK(!const_area->NeedsMaterialization());
+ __ addss(first.AsFpuRegister<XmmRegister>(),
+ codegen_->LiteralFloatAddress(
+ const_area->GetConstant()->AsFloatConstant()->GetValue(),
+ const_area->GetLocations()->InAt(0).AsRegister<Register>()));
+ } else {
+ DCHECK(second.IsStackSlot());
+ __ addss(first.AsFpuRegister<XmmRegister>(), Address(ESP, second.GetStackIndex()));
}
break;
}
@@ -2282,6 +2281,16 @@
case Primitive::kPrimDouble: {
if (second.IsFpuRegister()) {
__ addsd(first.AsFpuRegister<XmmRegister>(), second.AsFpuRegister<XmmRegister>());
+ } else if (add->InputAt(1)->IsX86LoadFromConstantTable()) {
+ HX86LoadFromConstantTable* const_area = add->InputAt(1)->AsX86LoadFromConstantTable();
+ DCHECK(!const_area->NeedsMaterialization());
+ __ addsd(first.AsFpuRegister<XmmRegister>(),
+ codegen_->LiteralDoubleAddress(
+ const_area->GetConstant()->AsDoubleConstant()->GetValue(),
+ const_area->GetLocations()->InAt(0).AsRegister<Register>()));
+ } else {
+ DCHECK(second.IsDoubleStackSlot());
+ __ addsd(first.AsFpuRegister<XmmRegister>(), Address(ESP, second.GetStackIndex()));
}
break;
}
@@ -2305,7 +2314,7 @@
case Primitive::kPrimFloat:
case Primitive::kPrimDouble: {
locations->SetInAt(0, Location::RequiresFpuRegister());
- locations->SetInAt(1, Location::RequiresFpuRegister());
+ locations->SetInAt(1, Location::Any());
locations->SetOut(Location::SameAsFirstInput());
break;
}
@@ -2351,12 +2360,36 @@
}
case Primitive::kPrimFloat: {
- __ subss(first.AsFpuRegister<XmmRegister>(), second.AsFpuRegister<XmmRegister>());
+ if (second.IsFpuRegister()) {
+ __ subss(first.AsFpuRegister<XmmRegister>(), second.AsFpuRegister<XmmRegister>());
+ } else if (sub->InputAt(1)->IsX86LoadFromConstantTable()) {
+ HX86LoadFromConstantTable* const_area = sub->InputAt(1)->AsX86LoadFromConstantTable();
+ DCHECK(!const_area->NeedsMaterialization());
+ __ subss(first.AsFpuRegister<XmmRegister>(),
+ codegen_->LiteralFloatAddress(
+ const_area->GetConstant()->AsFloatConstant()->GetValue(),
+ const_area->GetLocations()->InAt(0).AsRegister<Register>()));
+ } else {
+ DCHECK(second.IsStackSlot());
+ __ subss(first.AsFpuRegister<XmmRegister>(), Address(ESP, second.GetStackIndex()));
+ }
break;
}
case Primitive::kPrimDouble: {
- __ subsd(first.AsFpuRegister<XmmRegister>(), second.AsFpuRegister<XmmRegister>());
+ if (second.IsFpuRegister()) {
+ __ subsd(first.AsFpuRegister<XmmRegister>(), second.AsFpuRegister<XmmRegister>());
+ } else if (sub->InputAt(1)->IsX86LoadFromConstantTable()) {
+ HX86LoadFromConstantTable* const_area = sub->InputAt(1)->AsX86LoadFromConstantTable();
+ DCHECK(!const_area->NeedsMaterialization());
+ __ subsd(first.AsFpuRegister<XmmRegister>(),
+ codegen_->LiteralDoubleAddress(
+ const_area->GetConstant()->AsDoubleConstant()->GetValue(),
+ const_area->GetLocations()->InAt(0).AsRegister<Register>()));
+ } else {
+ DCHECK(second.IsDoubleStackSlot());
+ __ subsd(first.AsFpuRegister<XmmRegister>(), Address(ESP, second.GetStackIndex()));
+ }
break;
}
@@ -2391,7 +2424,7 @@
case Primitive::kPrimFloat:
case Primitive::kPrimDouble: {
locations->SetInAt(0, Location::RequiresFpuRegister());
- locations->SetInAt(1, Location::RequiresFpuRegister());
+ locations->SetInAt(1, Location::Any());
locations->SetOut(Location::SameAsFirstInput());
break;
}
@@ -2507,12 +2540,38 @@
}
case Primitive::kPrimFloat: {
- __ mulss(first.AsFpuRegister<XmmRegister>(), second.AsFpuRegister<XmmRegister>());
+ DCHECK(first.Equals(locations->Out()));
+ if (second.IsFpuRegister()) {
+ __ mulss(first.AsFpuRegister<XmmRegister>(), second.AsFpuRegister<XmmRegister>());
+ } else if (mul->InputAt(1)->IsX86LoadFromConstantTable()) {
+ HX86LoadFromConstantTable* const_area = mul->InputAt(1)->AsX86LoadFromConstantTable();
+ DCHECK(!const_area->NeedsMaterialization());
+ __ mulss(first.AsFpuRegister<XmmRegister>(),
+ codegen_->LiteralFloatAddress(
+ const_area->GetConstant()->AsFloatConstant()->GetValue(),
+ const_area->GetLocations()->InAt(0).AsRegister<Register>()));
+ } else {
+ DCHECK(second.IsStackSlot());
+ __ mulss(first.AsFpuRegister<XmmRegister>(), Address(ESP, second.GetStackIndex()));
+ }
break;
}
case Primitive::kPrimDouble: {
- __ mulsd(first.AsFpuRegister<XmmRegister>(), second.AsFpuRegister<XmmRegister>());
+ DCHECK(first.Equals(locations->Out()));
+ if (second.IsFpuRegister()) {
+ __ mulsd(first.AsFpuRegister<XmmRegister>(), second.AsFpuRegister<XmmRegister>());
+ } else if (mul->InputAt(1)->IsX86LoadFromConstantTable()) {
+ HX86LoadFromConstantTable* const_area = mul->InputAt(1)->AsX86LoadFromConstantTable();
+ DCHECK(!const_area->NeedsMaterialization());
+ __ mulsd(first.AsFpuRegister<XmmRegister>(),
+ codegen_->LiteralDoubleAddress(
+ const_area->GetConstant()->AsDoubleConstant()->GetValue(),
+ const_area->GetLocations()->InAt(0).AsRegister<Register>()));
+ } else {
+ DCHECK(second.IsDoubleStackSlot());
+ __ mulsd(first.AsFpuRegister<XmmRegister>(), Address(ESP, second.GetStackIndex()));
+ }
break;
}
@@ -2855,7 +2914,7 @@
case Primitive::kPrimFloat:
case Primitive::kPrimDouble: {
locations->SetInAt(0, Location::RequiresFpuRegister());
- locations->SetInAt(1, Location::RequiresFpuRegister());
+ locations->SetInAt(1, Location::Any());
locations->SetOut(Location::SameAsFirstInput());
break;
}
@@ -2867,7 +2926,6 @@
void InstructionCodeGeneratorX86::VisitDiv(HDiv* div) {
LocationSummary* locations = div->GetLocations();
- Location out = locations->Out();
Location first = locations->InAt(0);
Location second = locations->InAt(1);
@@ -2879,14 +2937,36 @@
}
case Primitive::kPrimFloat: {
- DCHECK(first.Equals(out));
- __ divss(first.AsFpuRegister<XmmRegister>(), second.AsFpuRegister<XmmRegister>());
+ if (second.IsFpuRegister()) {
+ __ divss(first.AsFpuRegister<XmmRegister>(), second.AsFpuRegister<XmmRegister>());
+ } else if (div->InputAt(1)->IsX86LoadFromConstantTable()) {
+ HX86LoadFromConstantTable* const_area = div->InputAt(1)->AsX86LoadFromConstantTable();
+ DCHECK(!const_area->NeedsMaterialization());
+ __ divss(first.AsFpuRegister<XmmRegister>(),
+ codegen_->LiteralFloatAddress(
+ const_area->GetConstant()->AsFloatConstant()->GetValue(),
+ const_area->GetLocations()->InAt(0).AsRegister<Register>()));
+ } else {
+ DCHECK(second.IsStackSlot());
+ __ divss(first.AsFpuRegister<XmmRegister>(), Address(ESP, second.GetStackIndex()));
+ }
break;
}
case Primitive::kPrimDouble: {
- DCHECK(first.Equals(out));
- __ divsd(first.AsFpuRegister<XmmRegister>(), second.AsFpuRegister<XmmRegister>());
+ if (second.IsFpuRegister()) {
+ __ divsd(first.AsFpuRegister<XmmRegister>(), second.AsFpuRegister<XmmRegister>());
+ } else if (div->InputAt(1)->IsX86LoadFromConstantTable()) {
+ HX86LoadFromConstantTable* const_area = div->InputAt(1)->AsX86LoadFromConstantTable();
+ DCHECK(!const_area->NeedsMaterialization());
+ __ divsd(first.AsFpuRegister<XmmRegister>(),
+ codegen_->LiteralDoubleAddress(
+ const_area->GetConstant()->AsDoubleConstant()->GetValue(),
+ const_area->GetLocations()->InAt(0).AsRegister<Register>()));
+ } else {
+ DCHECK(second.IsDoubleStackSlot());
+ __ divsd(first.AsFpuRegister<XmmRegister>(), Address(ESP, second.GetStackIndex()));
+ }
break;
}
@@ -3570,6 +3650,25 @@
DCHECK(!IsLeafMethod());
}
+void CodeGeneratorX86::GenerateVirtualCall(HInvokeVirtual* invoke, Location temp_in) {
+ Register temp = temp_in.AsRegister<Register>();
+ uint32_t method_offset = mirror::Class::EmbeddedVTableEntryOffset(
+ invoke->GetVTableIndex(), kX86PointerSize).Uint32Value();
+ LocationSummary* locations = invoke->GetLocations();
+ Location receiver = locations->InAt(0);
+ uint32_t class_offset = mirror::Object::ClassOffset().Int32Value();
+ // temp = object->GetClass();
+ DCHECK(receiver.IsRegister());
+ __ movl(temp, Address(receiver.AsRegister<Register>(), class_offset));
+ MaybeRecordImplicitNullCheck(invoke);
+ __ MaybeUnpoisonHeapReference(temp);
+ // temp = temp->GetMethodAt(method_offset);
+ __ movl(temp, Address(temp, method_offset));
+ // call temp->GetEntryPoint();
+ __ call(Address(
+ temp, ArtMethod::EntryPointFromQuickCompiledCodeOffset(kX86WordSize).Int32Value()));
+}
+
void CodeGeneratorX86::EmitLinkerPatches(ArenaVector<LinkerPatch>* linker_patches) {
DCHECK(linker_patches->empty());
linker_patches->reserve(method_patches_.size() + relative_call_patches_.size());
@@ -5085,6 +5184,245 @@
// Will be generated at use site.
}
+void LocationsBuilderX86::VisitX86ComputeBaseMethodAddress(
+ HX86ComputeBaseMethodAddress* insn) {
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(insn, LocationSummary::kNoCall);
+ locations->SetOut(Location::RequiresRegister());
+}
+
+void InstructionCodeGeneratorX86::VisitX86ComputeBaseMethodAddress(
+ HX86ComputeBaseMethodAddress* insn) {
+ LocationSummary* locations = insn->GetLocations();
+ Register reg = locations->Out().AsRegister<Register>();
+
+ // Generate call to next instruction.
+ Label next_instruction;
+ __ call(&next_instruction);
+ __ Bind(&next_instruction);
+
+ // Remember this offset for later use with constant area.
+ codegen_->SetMethodAddressOffset(GetAssembler()->CodeSize());
+
+ // Grab the return address off the stack.
+ __ popl(reg);
+}
+
+void LocationsBuilderX86::VisitX86LoadFromConstantTable(
+ HX86LoadFromConstantTable* insn) {
+ LocationSummary* locations =
+ new (GetGraph()->GetArena()) LocationSummary(insn, LocationSummary::kNoCall);
+
+ locations->SetInAt(0, Location::RequiresRegister());
+ locations->SetInAt(1, Location::ConstantLocation(insn->GetConstant()));
+
+ // If we don't need to be materialized, we only need the inputs to be set.
+ if (!insn->NeedsMaterialization()) {
+ return;
+ }
+
+ switch (insn->GetType()) {
+ case Primitive::kPrimFloat:
+ case Primitive::kPrimDouble:
+ locations->SetOut(Location::RequiresFpuRegister());
+ break;
+
+ case Primitive::kPrimInt:
+ locations->SetOut(Location::RequiresRegister());
+ break;
+
+ default:
+ LOG(FATAL) << "Unsupported x86 constant area type " << insn->GetType();
+ }
+}
+
+void InstructionCodeGeneratorX86::VisitX86LoadFromConstantTable(HX86LoadFromConstantTable* insn) {
+ if (!insn->NeedsMaterialization()) {
+ return;
+ }
+
+ LocationSummary* locations = insn->GetLocations();
+ Location out = locations->Out();
+ Register const_area = locations->InAt(0).AsRegister<Register>();
+ HConstant *value = insn->GetConstant();
+
+ switch (insn->GetType()) {
+ case Primitive::kPrimFloat:
+ __ movss(out.AsFpuRegister<XmmRegister>(),
+ codegen_->LiteralFloatAddress(value->AsFloatConstant()->GetValue(), const_area));
+ break;
+
+ case Primitive::kPrimDouble:
+ __ movsd(out.AsFpuRegister<XmmRegister>(),
+ codegen_->LiteralDoubleAddress(value->AsDoubleConstant()->GetValue(), const_area));
+ break;
+
+ case Primitive::kPrimInt:
+ __ movl(out.AsRegister<Register>(),
+ codegen_->LiteralInt32Address(value->AsIntConstant()->GetValue(), const_area));
+ break;
+
+ default:
+ LOG(FATAL) << "Unsupported x86 constant area type " << insn->GetType();
+ }
+}
+
+void CodeGeneratorX86::Finalize(CodeAllocator* allocator) {
+ // Generate the constant area if needed.
+ X86Assembler* assembler = GetAssembler();
+ if (!assembler->IsConstantAreaEmpty()) {
+ // Align to 4 byte boundary to reduce cache misses, as the data is 4 and 8
+ // byte values.
+ assembler->Align(4, 0);
+ constant_area_start_ = assembler->CodeSize();
+ assembler->AddConstantArea();
+ }
+
+ // And finish up.
+ CodeGenerator::Finalize(allocator);
+}
+
+/**
+ * Class to handle late fixup of offsets into constant area.
+ */
+class RIPFixup : public AssemblerFixup, public ArenaObject<kArenaAllocMisc> {
+ public:
+ RIPFixup(const CodeGeneratorX86& codegen, int offset)
+ : codegen_(codegen), offset_into_constant_area_(offset) {}
+
+ private:
+ void Process(const MemoryRegion& region, int pos) OVERRIDE {
+ // Patch the correct offset for the instruction. The place to patch is the
+ // last 4 bytes of the instruction.
+ // The value to patch is the distance from the offset in the constant area
+ // from the address computed by the HX86ComputeBaseMethodAddress instruction.
+ int32_t constant_offset = codegen_.ConstantAreaStart() + offset_into_constant_area_;
+ int32_t relative_position = constant_offset - codegen_.GetMethodAddressOffset();;
+
+ // Patch in the right value.
+ region.StoreUnaligned<int32_t>(pos - 4, relative_position);
+ }
+
+ const CodeGeneratorX86& codegen_;
+
+ // Location in constant area that the fixup refers to.
+ int offset_into_constant_area_;
+};
+
+Address CodeGeneratorX86::LiteralDoubleAddress(double v, Register reg) {
+ AssemblerFixup* fixup = new (GetGraph()->GetArena()) RIPFixup(*this, __ AddDouble(v));
+ return Address(reg, kDummy32BitOffset, fixup);
+}
+
+Address CodeGeneratorX86::LiteralFloatAddress(float v, Register reg) {
+ AssemblerFixup* fixup = new (GetGraph()->GetArena()) RIPFixup(*this, __ AddFloat(v));
+ return Address(reg, kDummy32BitOffset, fixup);
+}
+
+Address CodeGeneratorX86::LiteralInt32Address(int32_t v, Register reg) {
+ AssemblerFixup* fixup = new (GetGraph()->GetArena()) RIPFixup(*this, __ AddInt32(v));
+ return Address(reg, kDummy32BitOffset, fixup);
+}
+
+Address CodeGeneratorX86::LiteralInt64Address(int64_t v, Register reg) {
+ AssemblerFixup* fixup = new (GetGraph()->GetArena()) RIPFixup(*this, __ AddInt64(v));
+ return Address(reg, kDummy32BitOffset, fixup);
+}
+
+/**
+ * Finds instructions that need the constant area base as an input.
+ */
+class ConstantHandlerVisitor : public HGraphVisitor {
+ public:
+ explicit ConstantHandlerVisitor(HGraph* graph) : HGraphVisitor(graph), base_(nullptr) {}
+
+ private:
+ void VisitAdd(HAdd* add) OVERRIDE {
+ BinaryFP(add);
+ }
+
+ void VisitSub(HSub* sub) OVERRIDE {
+ BinaryFP(sub);
+ }
+
+ void VisitMul(HMul* mul) OVERRIDE {
+ BinaryFP(mul);
+ }
+
+ void VisitDiv(HDiv* div) OVERRIDE {
+ BinaryFP(div);
+ }
+
+ void VisitReturn(HReturn* ret) OVERRIDE {
+ HConstant* value = ret->InputAt(0)->AsConstant();
+ if ((value != nullptr && Primitive::IsFloatingPointType(value->GetType()))) {
+ ReplaceInput(ret, value, 0, true);
+ }
+ }
+
+ void VisitInvokeStaticOrDirect(HInvokeStaticOrDirect* invoke) OVERRIDE {
+ HandleInvoke(invoke);
+ }
+
+ void VisitInvokeVirtual(HInvokeVirtual* invoke) OVERRIDE {
+ HandleInvoke(invoke);
+ }
+
+ void VisitInvokeInterface(HInvokeInterface* invoke) OVERRIDE {
+ HandleInvoke(invoke);
+ }
+
+ void BinaryFP(HBinaryOperation* bin) {
+ HConstant* rhs = bin->InputAt(1)->AsConstant();
+ if (rhs != nullptr && Primitive::IsFloatingPointType(bin->GetResultType())) {
+ ReplaceInput(bin, rhs, 1, false);
+ }
+ }
+
+ void InitializeConstantAreaPointer(HInstruction* user) {
+ // Ensure we only initialize the pointer once.
+ if (base_ != nullptr) {
+ return;
+ }
+
+ HGraph* graph = GetGraph();
+ HBasicBlock* entry = graph->GetEntryBlock();
+ base_ = new (graph->GetArena()) HX86ComputeBaseMethodAddress();
+ HInstruction* insert_pos = (user->GetBlock() == entry) ? user : entry->GetLastInstruction();
+ entry->InsertInstructionBefore(base_, insert_pos);
+ DCHECK(base_ != nullptr);
+ }
+
+ void ReplaceInput(HInstruction* insn, HConstant* value, int input_index, bool materialize) {
+ InitializeConstantAreaPointer(insn);
+ HGraph* graph = GetGraph();
+ HBasicBlock* block = insn->GetBlock();
+ HX86LoadFromConstantTable* load_constant =
+ new (graph->GetArena()) HX86LoadFromConstantTable(base_, value, materialize);
+ block->InsertInstructionBefore(load_constant, insn);
+ insn->ReplaceInput(load_constant, input_index);
+ }
+
+ void HandleInvoke(HInvoke* invoke) {
+ // Ensure that we can load FP arguments from the constant area.
+ for (size_t i = 0, e = invoke->InputCount(); i < e; i++) {
+ HConstant* input = invoke->InputAt(i)->AsConstant();
+ if (input != nullptr && Primitive::IsFloatingPointType(input->GetType())) {
+ ReplaceInput(invoke, input, i, true);
+ }
+ }
+ }
+
+ // The generated HX86ComputeBaseMethodAddress in the entry block needed as an
+ // input to the HX86LoadFromConstantTable instructions.
+ HX86ComputeBaseMethodAddress* base_;
+};
+
+void ConstantAreaFixups::Run() {
+ ConstantHandlerVisitor visitor(graph_);
+ visitor.VisitInsertionOrder();
+}
+
#undef __
} // namespace x86
diff --git a/compiler/optimizing/code_generator_x86.h b/compiler/optimizing/code_generator_x86.h
index 17787a8..bd7cb12 100644
--- a/compiler/optimizing/code_generator_x86.h
+++ b/compiler/optimizing/code_generator_x86.h
@@ -294,6 +294,8 @@
// Generate a call to a static or direct method.
void GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Location temp);
+ // Generate a call to a virtual method.
+ void GenerateVirtualCall(HInvokeVirtual* invoke, Location temp);
// Emit linker patches.
void EmitLinkerPatches(ArenaVector<LinkerPatch>* linker_patches) OVERRIDE;
@@ -325,6 +327,25 @@
return isa_features_;
}
+ void SetMethodAddressOffset(int32_t offset) {
+ method_address_offset_ = offset;
+ }
+
+ int32_t GetMethodAddressOffset() const {
+ return method_address_offset_;
+ }
+
+ int32_t ConstantAreaStart() const {
+ return constant_area_start_;
+ }
+
+ Address LiteralDoubleAddress(double v, Register reg);
+ Address LiteralFloatAddress(float v, Register reg);
+ Address LiteralInt32Address(int32_t v, Register reg);
+ Address LiteralInt64Address(int64_t v, Register reg);
+
+ void Finalize(CodeAllocator* allocator) OVERRIDE;
+
private:
// Labels for each block that will be compiled.
GrowableArray<Label> block_labels_;
@@ -339,6 +360,20 @@
ArenaDeque<MethodPatchInfo<Label>> method_patches_;
ArenaDeque<MethodPatchInfo<Label>> relative_call_patches_;
+ // Offset to the start of the constant area in the assembled code.
+ // Used for fixups to the constant area.
+ int32_t constant_area_start_;
+
+ // If there is a HX86ComputeBaseMethodAddress instruction in the graph
+ // (which shall be the sole instruction of this kind), subtracting this offset
+ // from the value contained in the out register of this HX86ComputeBaseMethodAddress
+ // instruction gives the address of the start of this method.
+ int32_t method_address_offset_;
+
+ // When we don't know the proper offset for the value, we use kDummy32BitOffset.
+ // The correct value will be inserted when processing Assembler fixups.
+ static constexpr int32_t kDummy32BitOffset = 256;
+
DISALLOW_COPY_AND_ASSIGN(CodeGeneratorX86);
};
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index e1ec2ea..0f3eb74 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -475,6 +475,25 @@
DCHECK(!IsLeafMethod());
}
+void CodeGeneratorX86_64::GenerateVirtualCall(HInvokeVirtual* invoke, Location temp_in) {
+ CpuRegister temp = temp_in.AsRegister<CpuRegister>();
+ size_t method_offset = mirror::Class::EmbeddedVTableEntryOffset(
+ invoke->GetVTableIndex(), kX86_64PointerSize).SizeValue();
+ LocationSummary* locations = invoke->GetLocations();
+ Location receiver = locations->InAt(0);
+ size_t class_offset = mirror::Object::ClassOffset().SizeValue();
+ // temp = object->GetClass();
+ DCHECK(receiver.IsRegister());
+ __ movl(temp, Address(receiver.AsRegister<CpuRegister>(), class_offset));
+ MaybeRecordImplicitNullCheck(invoke);
+ __ MaybeUnpoisonHeapReference(temp);
+ // temp = temp->GetMethodAt(method_offset);
+ __ movq(temp, Address(temp, method_offset));
+ // call temp->GetEntryPoint();
+ __ call(Address(temp, ArtMethod::EntryPointFromQuickCompiledCodeOffset(
+ kX86_64WordSize).SizeValue()));
+}
+
void CodeGeneratorX86_64::EmitLinkerPatches(ArenaVector<LinkerPatch>* linker_patches) {
DCHECK(linker_patches->empty());
size_t size =
@@ -1709,22 +1728,7 @@
return;
}
- CpuRegister temp = invoke->GetLocations()->GetTemp(0).AsRegister<CpuRegister>();
- size_t method_offset = mirror::Class::EmbeddedVTableEntryOffset(
- invoke->GetVTableIndex(), kX86_64PointerSize).SizeValue();
- LocationSummary* locations = invoke->GetLocations();
- Location receiver = locations->InAt(0);
- size_t class_offset = mirror::Object::ClassOffset().SizeValue();
- // temp = object->GetClass();
- DCHECK(receiver.IsRegister());
- __ movl(temp, Address(receiver.AsRegister<CpuRegister>(), class_offset));
- codegen_->MaybeRecordImplicitNullCheck(invoke);
- __ MaybeUnpoisonHeapReference(temp);
- // temp = temp->GetMethodAt(method_offset);
- __ movq(temp, Address(temp, method_offset));
- // call temp->GetEntryPoint();
- __ call(Address(temp, ArtMethod::EntryPointFromQuickCompiledCodeOffset(
- kX86_64WordSize).SizeValue()));
+ codegen_->GenerateVirtualCall(invoke, invoke->GetLocations()->GetTemp(0));
DCHECK(!codegen_->IsLeafMethod());
codegen_->RecordPcInfo(invoke, invoke->GetDexPc());
diff --git a/compiler/optimizing/code_generator_x86_64.h b/compiler/optimizing/code_generator_x86_64.h
index 21357be..f9d8e04 100644
--- a/compiler/optimizing/code_generator_x86_64.h
+++ b/compiler/optimizing/code_generator_x86_64.h
@@ -305,6 +305,7 @@
}
void GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Location temp);
+ void GenerateVirtualCall(HInvokeVirtual* invoke, Location temp);
void EmitLinkerPatches(ArenaVector<LinkerPatch>* linker_patches) OVERRIDE;
diff --git a/compiler/optimizing/constant_area_fixups_x86.h b/compiler/optimizing/constant_area_fixups_x86.h
new file mode 100644
index 0000000..4138039
--- /dev/null
+++ b/compiler/optimizing/constant_area_fixups_x86.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_COMPILER_OPTIMIZING_CONSTANT_AREA_FIXUPS_X86_H_
+#define ART_COMPILER_OPTIMIZING_CONSTANT_AREA_FIXUPS_X86_H_
+
+#include "nodes.h"
+#include "optimization.h"
+
+namespace art {
+namespace x86 {
+
+class ConstantAreaFixups : public HOptimization {
+ public:
+ ConstantAreaFixups(HGraph* graph, OptimizingCompilerStats* stats)
+ : HOptimization(graph, "constant_area_fixups_x86", stats) {}
+
+ void Run() OVERRIDE;
+};
+
+} // namespace x86
+} // namespace art
+
+#endif // ART_COMPILER_OPTIMIZING_CONSTANT_AREA_FIXUPS_X86_H_
diff --git a/compiler/optimizing/intrinsics.cc b/compiler/optimizing/intrinsics.cc
index 075ec1e..41c239d 100644
--- a/compiler/optimizing/intrinsics.cc
+++ b/compiler/optimizing/intrinsics.cc
@@ -16,12 +16,17 @@
#include "intrinsics.h"
+#include "art_method.h"
+#include "class_linker.h"
#include "dex/quick/dex_file_method_inliner.h"
#include "dex/quick/dex_file_to_method_inliner_map.h"
#include "driver/compiler_driver.h"
#include "invoke_type.h"
+#include "mirror/dex_cache-inl.h"
#include "nodes.h"
#include "quick/inline_method_analyser.h"
+#include "scoped_thread_state_change.h"
+#include "thread-inl.h"
#include "utils.h"
namespace art {
@@ -328,14 +333,23 @@
return Intrinsics::kNone;
}
-static bool CheckInvokeType(Intrinsics intrinsic, HInvoke* invoke) {
+static bool CheckInvokeType(Intrinsics intrinsic, HInvoke* invoke, const DexFile& dex_file) {
// The DexFileMethodInliner should have checked whether the methods are agreeing with
// what we expect, i.e., static methods are called as such. Add another check here for
// our expectations:
- // Whenever the intrinsic is marked as static-or-direct, report an error if we find an
- // InvokeVirtual. The other direction is not possible: we have intrinsics for virtual
- // functions that will perform a check inline. If the precise type is known, however,
- // the instruction will be sharpened to an InvokeStaticOrDirect.
+ //
+ // Whenever the intrinsic is marked as static, report an error if we find an InvokeVirtual.
+ //
+ // Whenever the intrinsic is marked as direct and we find an InvokeVirtual, a devirtualization
+ // failure occured. We might be in a situation where we have inlined a method that calls an
+ // intrinsic, but that method is in a different dex file on which we do not have a
+ // verified_method that would have helped the compiler driver sharpen the call. In that case,
+ // make sure that the intrinsic is actually for some final method (or in a final class), as
+ // otherwise the intrinsics setup is broken.
+ //
+ // For the last direction, we have intrinsics for virtual functions that will perform a check
+ // inline. If the precise type is known, however, the instruction will be sharpened to an
+ // InvokeStaticOrDirect.
InvokeType intrinsic_type = GetIntrinsicInvokeType(intrinsic);
InvokeType invoke_type = invoke->IsInvokeStaticOrDirect() ?
invoke->AsInvokeStaticOrDirect()->GetInvokeType() :
@@ -343,8 +357,22 @@
switch (intrinsic_type) {
case kStatic:
return (invoke_type == kStatic);
+
case kDirect:
- return (invoke_type == kDirect);
+ if (invoke_type == kDirect) {
+ return true;
+ }
+ if (invoke_type == kVirtual) {
+ ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+ ScopedObjectAccess soa(Thread::Current());
+ ArtMethod* art_method =
+ class_linker->FindDexCache(soa.Self(), dex_file)->GetResolvedMethod(
+ invoke->GetDexMethodIndex(), class_linker->GetImagePointerSize());
+ return art_method != nullptr &&
+ (art_method->IsFinal() || art_method->GetDeclaringClass()->IsFinal());
+ }
+ return false;
+
case kVirtual:
// Call might be devirtualized.
return (invoke_type == kVirtual || invoke_type == kDirect);
@@ -364,17 +392,18 @@
if (inst->IsInvoke()) {
HInvoke* invoke = inst->AsInvoke();
InlineMethod method;
- DexFileMethodInliner* inliner =
- driver_->GetMethodInlinerMap()->GetMethodInliner(&invoke->GetDexFile());
+ const DexFile& dex_file = invoke->GetDexFile();
+ DexFileMethodInliner* inliner = driver_->GetMethodInlinerMap()->GetMethodInliner(&dex_file);
DCHECK(inliner != nullptr);
if (inliner->IsIntrinsic(invoke->GetDexMethodIndex(), &method)) {
Intrinsics intrinsic = GetIntrinsic(method, graph_->GetInstructionSet());
if (intrinsic != Intrinsics::kNone) {
- if (!CheckInvokeType(intrinsic, invoke)) {
+ if (!CheckInvokeType(intrinsic, invoke, dex_file)) {
LOG(WARNING) << "Found an intrinsic with unexpected invoke type: "
- << intrinsic << " for "
- << PrettyMethod(invoke->GetDexMethodIndex(), invoke->GetDexFile());
+ << intrinsic << " for "
+ << PrettyMethod(invoke->GetDexMethodIndex(), invoke->GetDexFile())
+ << invoke->DebugName();
} else {
invoke->SetIntrinsic(intrinsic, NeedsEnvironmentOrCache(intrinsic));
}
diff --git a/compiler/optimizing/intrinsics_arm.cc b/compiler/optimizing/intrinsics_arm.cc
index 69a3e62..6040a40 100644
--- a/compiler/optimizing/intrinsics_arm.cc
+++ b/compiler/optimizing/intrinsics_arm.cc
@@ -103,11 +103,11 @@
if (invoke_->IsInvokeStaticOrDirect()) {
codegen->GenerateStaticOrDirectCall(invoke_->AsInvokeStaticOrDirect(),
Location::RegisterLocation(kArtMethodRegister));
- codegen->RecordPcInfo(invoke_, invoke_->GetDexPc(), this);
} else {
- UNIMPLEMENTED(FATAL) << "Non-direct intrinsic slow-path not yet implemented";
- UNREACHABLE();
+ codegen->GenerateVirtualCall(invoke_->AsInvokeVirtual(),
+ Location::RegisterLocation(kArtMethodRegister));
}
+ codegen->RecordPcInfo(invoke_, invoke_->GetDexPc(), this);
// Copy the result back to the expected output.
Location out = invoke_->GetLocations()->Out();
diff --git a/compiler/optimizing/intrinsics_arm64.cc b/compiler/optimizing/intrinsics_arm64.cc
index 0171d69..1dbca34 100644
--- a/compiler/optimizing/intrinsics_arm64.cc
+++ b/compiler/optimizing/intrinsics_arm64.cc
@@ -112,11 +112,10 @@
if (invoke_->IsInvokeStaticOrDirect()) {
codegen->GenerateStaticOrDirectCall(invoke_->AsInvokeStaticOrDirect(),
LocationFrom(kArtMethodRegister));
- codegen->RecordPcInfo(invoke_, invoke_->GetDexPc(), this);
} else {
- UNIMPLEMENTED(FATAL) << "Non-direct intrinsic slow-path not yet implemented";
- UNREACHABLE();
+ codegen->GenerateVirtualCall(invoke_->AsInvokeVirtual(), LocationFrom(kArtMethodRegister));
}
+ codegen->RecordPcInfo(invoke_, invoke_->GetDexPc(), this);
// Copy the result back to the expected output.
Location out = invoke_->GetLocations()->Out();
diff --git a/compiler/optimizing/intrinsics_x86.cc b/compiler/optimizing/intrinsics_x86.cc
index be076cd..daf56d0 100644
--- a/compiler/optimizing/intrinsics_x86.cc
+++ b/compiler/optimizing/intrinsics_x86.cc
@@ -141,11 +141,10 @@
if (invoke_->IsInvokeStaticOrDirect()) {
codegen->GenerateStaticOrDirectCall(invoke_->AsInvokeStaticOrDirect(),
Location::RegisterLocation(EAX));
- codegen->RecordPcInfo(invoke_, invoke_->GetDexPc(), this);
} else {
- UNIMPLEMENTED(FATAL) << "Non-direct intrinsic slow-path not yet implemented";
- UNREACHABLE();
+ codegen->GenerateVirtualCall(invoke_->AsInvokeVirtual(), Location::RegisterLocation(EAX));
}
+ codegen->RecordPcInfo(invoke_, invoke_->GetDexPc(), this);
// Copy the result back to the expected output.
Location out = invoke_->GetLocations()->Out();
diff --git a/compiler/optimizing/intrinsics_x86_64.cc b/compiler/optimizing/intrinsics_x86_64.cc
index 1f35b59..f78a726 100644
--- a/compiler/optimizing/intrinsics_x86_64.cc
+++ b/compiler/optimizing/intrinsics_x86_64.cc
@@ -132,11 +132,10 @@
if (invoke_->IsInvokeStaticOrDirect()) {
codegen->GenerateStaticOrDirectCall(
invoke_->AsInvokeStaticOrDirect(), Location::RegisterLocation(RDI));
- codegen->RecordPcInfo(invoke_, invoke_->GetDexPc(), this);
} else {
- UNIMPLEMENTED(FATAL) << "Non-direct intrinsic slow-path not yet implemented";
- UNREACHABLE();
+ codegen->GenerateVirtualCall(invoke_->AsInvokeVirtual(), Location::RegisterLocation(RDI));
}
+ codegen->RecordPcInfo(invoke_, invoke_->GetDexPc(), this);
// Copy the result back to the expected output.
Location out = invoke_->GetLocations()->Out();
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc
index 4332d7e..650c8e5 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -207,7 +207,7 @@
// Insert a new node between `block` and `successor` to split the
// critical edge.
HBasicBlock* new_block = SplitEdge(block, successor);
- new_block->AddInstruction(new (arena_) HGoto());
+ new_block->AddInstruction(new (arena_) HGoto(successor->GetDexPc()));
if (successor->IsLoopHeader()) {
// If we split at a back edge boundary, make the new block the back edge.
HLoopInformation* info = successor->GetLoopInformation();
@@ -228,7 +228,7 @@
if (number_of_incomings != 1) {
HBasicBlock* pre_header = new (arena_) HBasicBlock(this, header->GetDexPc());
AddBlock(pre_header);
- pre_header->AddInstruction(new (arena_) HGoto());
+ pre_header->AddInstruction(new (arena_) HGoto(header->GetDexPc()));
for (size_t pred = 0; pred < header->GetPredecessors().Size(); ++pred) {
HBasicBlock* predecessor = header->GetPredecessors().Get(pred);
@@ -409,12 +409,12 @@
}
}
-HNullConstant* HGraph::GetNullConstant() {
+HNullConstant* HGraph::GetNullConstant(uint32_t dex_pc) {
// For simplicity, don't bother reviving the cached null constant if it is
// not null and not in a block. Otherwise, we need to clear the instruction
// id and/or any invariants the graph is assuming when adding new instructions.
if ((cached_null_constant_ == nullptr) || (cached_null_constant_->GetBlock() == nullptr)) {
- cached_null_constant_ = new (arena_) HNullConstant();
+ cached_null_constant_ = new (arena_) HNullConstant(dex_pc);
InsertConstant(cached_null_constant_);
}
return cached_null_constant_;
@@ -426,7 +426,8 @@
// id and/or any invariants the graph is assuming when adding new instructions.
if ((cached_current_method_ == nullptr) || (cached_current_method_->GetBlock() == nullptr)) {
cached_current_method_ = new (arena_) HCurrentMethod(
- Is64BitInstructionSet(instruction_set_) ? Primitive::kPrimLong : Primitive::kPrimInt);
+ Is64BitInstructionSet(instruction_set_) ? Primitive::kPrimLong : Primitive::kPrimInt,
+ entry_block_->GetDexPc());
if (entry_block_->GetFirstInstruction() == nullptr) {
entry_block_->AddInstruction(cached_current_method_);
} else {
@@ -437,7 +438,7 @@
return cached_current_method_;
}
-HConstant* HGraph::GetConstant(Primitive::Type type, int64_t value) {
+HConstant* HGraph::GetConstant(Primitive::Type type, int64_t value, uint32_t dex_pc) {
switch (type) {
case Primitive::Type::kPrimBoolean:
DCHECK(IsUint<1>(value));
@@ -447,10 +448,10 @@
case Primitive::Type::kPrimShort:
case Primitive::Type::kPrimInt:
DCHECK(IsInt(Primitive::ComponentSize(type) * kBitsPerByte, value));
- return GetIntConstant(static_cast<int32_t>(value));
+ return GetIntConstant(static_cast<int32_t>(value), dex_pc);
case Primitive::Type::kPrimLong:
- return GetLongConstant(value);
+ return GetLongConstant(value, dex_pc);
default:
LOG(FATAL) << "Unsupported constant type";
@@ -944,11 +945,11 @@
int32_t value = GetInput()->AsIntConstant()->GetValue();
switch (GetResultType()) {
case Primitive::kPrimLong:
- return graph->GetLongConstant(static_cast<int64_t>(value));
+ return graph->GetLongConstant(static_cast<int64_t>(value), GetDexPc());
case Primitive::kPrimFloat:
- return graph->GetFloatConstant(static_cast<float>(value));
+ return graph->GetFloatConstant(static_cast<float>(value), GetDexPc());
case Primitive::kPrimDouble:
- return graph->GetDoubleConstant(static_cast<double>(value));
+ return graph->GetDoubleConstant(static_cast<double>(value), GetDexPc());
default:
return nullptr;
}
@@ -956,11 +957,11 @@
int64_t value = GetInput()->AsLongConstant()->GetValue();
switch (GetResultType()) {
case Primitive::kPrimInt:
- return graph->GetIntConstant(static_cast<int32_t>(value));
+ return graph->GetIntConstant(static_cast<int32_t>(value), GetDexPc());
case Primitive::kPrimFloat:
- return graph->GetFloatConstant(static_cast<float>(value));
+ return graph->GetFloatConstant(static_cast<float>(value), GetDexPc());
case Primitive::kPrimDouble:
- return graph->GetDoubleConstant(static_cast<double>(value));
+ return graph->GetDoubleConstant(static_cast<double>(value), GetDexPc());
default:
return nullptr;
}
@@ -969,22 +970,22 @@
switch (GetResultType()) {
case Primitive::kPrimInt:
if (std::isnan(value))
- return graph->GetIntConstant(0);
+ return graph->GetIntConstant(0, GetDexPc());
if (value >= kPrimIntMax)
- return graph->GetIntConstant(kPrimIntMax);
+ return graph->GetIntConstant(kPrimIntMax, GetDexPc());
if (value <= kPrimIntMin)
- return graph->GetIntConstant(kPrimIntMin);
- return graph->GetIntConstant(static_cast<int32_t>(value));
+ return graph->GetIntConstant(kPrimIntMin, GetDexPc());
+ return graph->GetIntConstant(static_cast<int32_t>(value), GetDexPc());
case Primitive::kPrimLong:
if (std::isnan(value))
- return graph->GetLongConstant(0);
+ return graph->GetLongConstant(0, GetDexPc());
if (value >= kPrimLongMax)
- return graph->GetLongConstant(kPrimLongMax);
+ return graph->GetLongConstant(kPrimLongMax, GetDexPc());
if (value <= kPrimLongMin)
- return graph->GetLongConstant(kPrimLongMin);
- return graph->GetLongConstant(static_cast<int64_t>(value));
+ return graph->GetLongConstant(kPrimLongMin, GetDexPc());
+ return graph->GetLongConstant(static_cast<int64_t>(value), GetDexPc());
case Primitive::kPrimDouble:
- return graph->GetDoubleConstant(static_cast<double>(value));
+ return graph->GetDoubleConstant(static_cast<double>(value), GetDexPc());
default:
return nullptr;
}
@@ -993,22 +994,22 @@
switch (GetResultType()) {
case Primitive::kPrimInt:
if (std::isnan(value))
- return graph->GetIntConstant(0);
+ return graph->GetIntConstant(0, GetDexPc());
if (value >= kPrimIntMax)
- return graph->GetIntConstant(kPrimIntMax);
+ return graph->GetIntConstant(kPrimIntMax, GetDexPc());
if (value <= kPrimLongMin)
- return graph->GetIntConstant(kPrimIntMin);
- return graph->GetIntConstant(static_cast<int32_t>(value));
+ return graph->GetIntConstant(kPrimIntMin, GetDexPc());
+ return graph->GetIntConstant(static_cast<int32_t>(value), GetDexPc());
case Primitive::kPrimLong:
if (std::isnan(value))
- return graph->GetLongConstant(0);
+ return graph->GetLongConstant(0, GetDexPc());
if (value >= kPrimLongMax)
- return graph->GetLongConstant(kPrimLongMax);
+ return graph->GetLongConstant(kPrimLongMax, GetDexPc());
if (value <= kPrimLongMin)
- return graph->GetLongConstant(kPrimLongMin);
- return graph->GetLongConstant(static_cast<int64_t>(value));
+ return graph->GetLongConstant(kPrimLongMin, GetDexPc());
+ return graph->GetLongConstant(static_cast<int64_t>(value), GetDexPc());
case Primitive::kPrimFloat:
- return graph->GetFloatConstant(static_cast<float>(value));
+ return graph->GetFloatConstant(static_cast<float>(value), GetDexPc());
default:
return nullptr;
}
@@ -1122,7 +1123,8 @@
DCHECK(!graph_->IsInSsaForm()) << "Support for SSA form not implemented";
DCHECK_EQ(cursor->GetBlock(), this);
- HBasicBlock* new_block = new (GetGraph()->GetArena()) HBasicBlock(GetGraph(), GetDexPc());
+ HBasicBlock* new_block = new (GetGraph()->GetArena()) HBasicBlock(GetGraph(),
+ cursor->GetDexPc());
new_block->instructions_.first_instruction_ = cursor;
new_block->instructions_.last_instruction_ = instructions_.last_instruction_;
instructions_.last_instruction_ = cursor->previous_;
@@ -1134,7 +1136,7 @@
}
new_block->instructions_.SetBlockOfInstructions(new_block);
- AddInstruction(new (GetGraph()->GetArena()) HGoto());
+ AddInstruction(new (GetGraph()->GetArena()) HGoto(new_block->GetDexPc()));
for (size_t i = 0, e = GetSuccessors().Size(); i < e; ++i) {
HBasicBlock* successor = GetSuccessors().Get(i);
@@ -1309,7 +1311,7 @@
predecessor->RemoveSuccessor(this);
if (predecessor->GetSuccessors().Size() == 1u) {
DCHECK(last_instruction->IsIf());
- predecessor->AddInstruction(new (graph_->GetArena()) HGoto());
+ predecessor->AddInstruction(new (graph_->GetArena()) HGoto(last_instruction->GetDexPc()));
} else {
// The predecessor has no remaining successors and therefore must be dead.
// We deliberately leave it without a control-flow instruction so that the
@@ -1562,13 +1564,13 @@
if (!returns_void) {
return_value = last->InputAt(0);
}
- predecessor->AddInstruction(new (allocator) HGoto());
+ predecessor->AddInstruction(new (allocator) HGoto(last->GetDexPc()));
predecessor->RemoveInstruction(last);
} else {
if (!returns_void) {
// There will be multiple returns.
return_value = new (allocator) HPhi(
- allocator, kNoRegNumber, 0, HPhi::ToPhiType(invoke->GetType()));
+ allocator, kNoRegNumber, 0, HPhi::ToPhiType(invoke->GetType()), to->GetDexPc());
to->AddPhi(return_value->AsPhi());
}
for (size_t i = 0, e = to->GetPredecessors().Size(); i < e; ++i) {
@@ -1577,7 +1579,7 @@
if (!returns_void) {
return_value->AsPhi()->AddInput(last->InputAt(0));
}
- predecessor->AddInstruction(new (allocator) HGoto());
+ predecessor->AddInstruction(new (allocator) HGoto(last->GetDexPc()));
predecessor->RemoveInstruction(last);
}
}
@@ -1659,15 +1661,19 @@
for (HInstructionIterator it(entry_block_->GetInstructions()); !it.Done(); it.Advance()) {
HInstruction* current = it.Current();
if (current->IsNullConstant()) {
- current->ReplaceWith(outer_graph->GetNullConstant());
+ current->ReplaceWith(outer_graph->GetNullConstant(current->GetDexPc()));
} else if (current->IsIntConstant()) {
- current->ReplaceWith(outer_graph->GetIntConstant(current->AsIntConstant()->GetValue()));
+ current->ReplaceWith(outer_graph->GetIntConstant(
+ current->AsIntConstant()->GetValue(), current->GetDexPc()));
} else if (current->IsLongConstant()) {
- current->ReplaceWith(outer_graph->GetLongConstant(current->AsLongConstant()->GetValue()));
+ current->ReplaceWith(outer_graph->GetLongConstant(
+ current->AsLongConstant()->GetValue(), current->GetDexPc()));
} else if (current->IsFloatConstant()) {
- current->ReplaceWith(outer_graph->GetFloatConstant(current->AsFloatConstant()->GetValue()));
+ current->ReplaceWith(outer_graph->GetFloatConstant(
+ current->AsFloatConstant()->GetValue(), current->GetDexPc()));
} else if (current->IsDoubleConstant()) {
- current->ReplaceWith(outer_graph->GetDoubleConstant(current->AsDoubleConstant()->GetValue()));
+ current->ReplaceWith(outer_graph->GetDoubleConstant(
+ current->AsDoubleConstant()->GetValue(), current->GetDexPc()));
} else if (current->IsParameterValue()) {
if (kIsDebugBuild
&& invoke->IsInvokeStaticOrDirect()
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index fef6f21..23d605b 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -77,6 +77,8 @@
static constexpr InvokeType kInvalidInvokeType = static_cast<InvokeType>(-1);
+static constexpr uint32_t kNoDexPc = -1;
+
enum IfCondition {
kCondEQ,
kCondNE,
@@ -316,24 +318,24 @@
// Returns a constant of the given type and value. If it does not exist
// already, it is created and inserted into the graph. This method is only for
// integral types.
- HConstant* GetConstant(Primitive::Type type, int64_t value);
+ HConstant* GetConstant(Primitive::Type type, int64_t value, uint32_t dex_pc = kNoDexPc);
// TODO: This is problematic for the consistency of reference type propagation
// because it can be created anytime after the pass and thus it will be left
// with an invalid type.
- HNullConstant* GetNullConstant();
+ HNullConstant* GetNullConstant(uint32_t dex_pc = kNoDexPc);
- HIntConstant* GetIntConstant(int32_t value) {
- return CreateConstant(value, &cached_int_constants_);
+ HIntConstant* GetIntConstant(int32_t value, uint32_t dex_pc = kNoDexPc) {
+ return CreateConstant(value, &cached_int_constants_, dex_pc);
}
- HLongConstant* GetLongConstant(int64_t value) {
- return CreateConstant(value, &cached_long_constants_);
+ HLongConstant* GetLongConstant(int64_t value, uint32_t dex_pc = kNoDexPc) {
+ return CreateConstant(value, &cached_long_constants_, dex_pc);
}
- HFloatConstant* GetFloatConstant(float value) {
- return CreateConstant(bit_cast<int32_t, float>(value), &cached_float_constants_);
+ HFloatConstant* GetFloatConstant(float value, uint32_t dex_pc = kNoDexPc) {
+ return CreateConstant(bit_cast<int32_t, float>(value), &cached_float_constants_, dex_pc);
}
- HDoubleConstant* GetDoubleConstant(double value) {
- return CreateConstant(bit_cast<int64_t, double>(value), &cached_double_constants_);
+ HDoubleConstant* GetDoubleConstant(double value, uint32_t dex_pc = kNoDexPc) {
+ return CreateConstant(bit_cast<int64_t, double>(value), &cached_double_constants_, dex_pc);
}
HCurrentMethod* GetCurrentMethod();
@@ -372,7 +374,8 @@
template <class InstructionType, typename ValueType>
InstructionType* CreateConstant(ValueType value,
- ArenaSafeMap<ValueType, InstructionType*>* cache) {
+ ArenaSafeMap<ValueType, InstructionType*>* cache,
+ uint32_t dex_pc = kNoDexPc) {
// Try to find an existing constant of the given value.
InstructionType* constant = nullptr;
auto cached_constant = cache->find(value);
@@ -383,7 +386,7 @@
// If not found or previously deleted, create and cache a new instruction.
// Don't bother reviving a previously deleted instruction, for simplicity.
if (constant == nullptr || constant->GetBlock() == nullptr) {
- constant = new (arena_) InstructionType(value);
+ constant = new (arena_) InstructionType(value, dex_pc);
cache->Overwrite(value, constant);
InsertConstant(constant);
}
@@ -618,7 +621,6 @@
};
static constexpr size_t kNoLifetime = -1;
-static constexpr uint32_t kNoDexPc = -1;
// A block in a method. Contains the list of instructions represented
// as a double linked list. Each block knows its predecessors and
@@ -626,7 +628,7 @@
class HBasicBlock : public ArenaObject<kArenaAllocBasicBlock> {
public:
- explicit HBasicBlock(HGraph* graph, uint32_t dex_pc = kNoDexPc)
+ HBasicBlock(HGraph* graph, uint32_t dex_pc = kNoDexPc)
: graph_(graph),
predecessors_(graph->GetArena(), kDefaultNumberOfPredecessors),
successors_(graph->GetArena(), kDefaultNumberOfSuccessors),
@@ -683,6 +685,7 @@
int GetBlockId() const { return block_id_; }
void SetBlockId(int id) { block_id_ = id; }
+ uint32_t GetDexPc() const { return dex_pc_; }
HBasicBlock* GetDominator() const { return dominator_; }
void SetDominator(HBasicBlock* dominator) { dominator_ = dominator; }
@@ -943,7 +946,6 @@
void SetLifetimeStart(size_t start) { lifetime_start_ = start; }
void SetLifetimeEnd(size_t end) { lifetime_end_ = end; }
- uint32_t GetDexPc() const { return dex_pc_; }
bool EndsWithControlFlowInstruction() const;
bool EndsWithIf() const;
@@ -1076,7 +1078,9 @@
#define FOR_EACH_CONCRETE_INSTRUCTION_MIPS64(M)
-#define FOR_EACH_CONCRETE_INSTRUCTION_X86(M)
+#define FOR_EACH_CONCRETE_INSTRUCTION_X86(M) \
+ M(X86ComputeBaseMethodAddress, Instruction) \
+ M(X86LoadFromConstantTable, Instruction)
#define FOR_EACH_CONCRETE_INSTRUCTION_X86_64(M)
@@ -1689,10 +1693,11 @@
class HInstruction : public ArenaObject<kArenaAllocInstruction> {
public:
- explicit HInstruction(SideEffects side_effects)
+ HInstruction(SideEffects side_effects, uint32_t dex_pc = kNoDexPc)
: previous_(nullptr),
next_(nullptr),
block_(nullptr),
+ dex_pc_(dex_pc),
id_(-1),
ssa_index_(-1),
environment_(nullptr),
@@ -1735,9 +1740,9 @@
}
virtual bool NeedsEnvironment() const { return false; }
- virtual uint32_t GetDexPc() const {
- return kNoDexPc;
- }
+
+ uint32_t GetDexPc() const { return dex_pc_; }
+
virtual bool IsControlFlow() const { return false; }
virtual bool CanThrow() const { return false; }
@@ -1940,6 +1945,7 @@
HInstruction* previous_;
HInstruction* next_;
HBasicBlock* block_;
+ const uint32_t dex_pc_;
// An instruction gets an id when it is added to the graph.
// It reflects creation order. A negative id means the instruction
@@ -2044,8 +2050,8 @@
template<size_t N>
class HTemplateInstruction: public HInstruction {
public:
- HTemplateInstruction<N>(SideEffects side_effects)
- : HInstruction(side_effects), inputs_() {}
+ HTemplateInstruction<N>(SideEffects side_effects, uint32_t dex_pc = kNoDexPc)
+ : HInstruction(side_effects, dex_pc), inputs_() {}
virtual ~HTemplateInstruction() {}
size_t InputCount() const OVERRIDE { return N; }
@@ -2071,7 +2077,9 @@
template<>
class HTemplateInstruction<0>: public HInstruction {
public:
- explicit HTemplateInstruction(SideEffects side_effects) : HInstruction(side_effects) {}
+ explicit HTemplateInstruction<0>(SideEffects side_effects, uint32_t dex_pc = kNoDexPc)
+ : HInstruction(side_effects, dex_pc) {}
+
virtual ~HTemplateInstruction() {}
size_t InputCount() const OVERRIDE { return 0; }
@@ -2095,8 +2103,8 @@
template<intptr_t N>
class HExpression : public HTemplateInstruction<N> {
public:
- HExpression<N>(Primitive::Type type, SideEffects side_effects)
- : HTemplateInstruction<N>(side_effects), type_(type) {}
+ HExpression<N>(Primitive::Type type, SideEffects side_effects, uint32_t dex_pc = kNoDexPc)
+ : HTemplateInstruction<N>(side_effects, dex_pc), type_(type) {}
virtual ~HExpression() {}
Primitive::Type GetType() const OVERRIDE { return type_; }
@@ -2109,7 +2117,8 @@
// instruction that branches to the exit block.
class HReturnVoid : public HTemplateInstruction<0> {
public:
- HReturnVoid() : HTemplateInstruction(SideEffects::None()) {}
+ explicit HReturnVoid(uint32_t dex_pc = kNoDexPc)
+ : HTemplateInstruction(SideEffects::None(), dex_pc) {}
bool IsControlFlow() const OVERRIDE { return true; }
@@ -2123,7 +2132,8 @@
// instruction that branches to the exit block.
class HReturn : public HTemplateInstruction<1> {
public:
- explicit HReturn(HInstruction* value) : HTemplateInstruction(SideEffects::None()) {
+ explicit HReturn(HInstruction* value, uint32_t dex_pc = kNoDexPc)
+ : HTemplateInstruction(SideEffects::None(), dex_pc) {
SetRawInputAt(0, value);
}
@@ -2140,7 +2150,7 @@
// exit block.
class HExit : public HTemplateInstruction<0> {
public:
- HExit() : HTemplateInstruction(SideEffects::None()) {}
+ explicit HExit(uint32_t dex_pc = kNoDexPc) : HTemplateInstruction(SideEffects::None(), dex_pc) {}
bool IsControlFlow() const OVERRIDE { return true; }
@@ -2153,7 +2163,7 @@
// Jumps from one block to another.
class HGoto : public HTemplateInstruction<0> {
public:
- HGoto() : HTemplateInstruction(SideEffects::None()) {}
+ explicit HGoto(uint32_t dex_pc = kNoDexPc) : HTemplateInstruction(SideEffects::None(), dex_pc) {}
bool IsControlFlow() const OVERRIDE { return true; }
@@ -2169,7 +2179,8 @@
class HConstant : public HExpression<0> {
public:
- explicit HConstant(Primitive::Type type) : HExpression(type, SideEffects::None()) {}
+ explicit HConstant(Primitive::Type type, uint32_t dex_pc = kNoDexPc)
+ : HExpression(type, SideEffects::None(), dex_pc) {}
bool CanBeMoved() const OVERRIDE { return true; }
@@ -2194,7 +2205,7 @@
DECLARE_INSTRUCTION(NullConstant);
private:
- HNullConstant() : HConstant(Primitive::kPrimNot) {}
+ explicit HNullConstant(uint32_t dex_pc = kNoDexPc) : HConstant(Primitive::kPrimNot, dex_pc) {}
friend class HGraph;
DISALLOW_COPY_AND_ASSIGN(HNullConstant);
@@ -2220,8 +2231,10 @@
DECLARE_INSTRUCTION(IntConstant);
private:
- explicit HIntConstant(int32_t value) : HConstant(Primitive::kPrimInt), value_(value) {}
- explicit HIntConstant(bool value) : HConstant(Primitive::kPrimInt), value_(value ? 1 : 0) {}
+ explicit HIntConstant(int32_t value, uint32_t dex_pc = kNoDexPc)
+ : HConstant(Primitive::kPrimInt, dex_pc), value_(value) {}
+ explicit HIntConstant(bool value, uint32_t dex_pc = kNoDexPc)
+ : HConstant(Primitive::kPrimInt, dex_pc), value_(value ? 1 : 0) {}
const int32_t value_;
@@ -2249,7 +2262,8 @@
DECLARE_INSTRUCTION(LongConstant);
private:
- explicit HLongConstant(int64_t value) : HConstant(Primitive::kPrimLong), value_(value) {}
+ explicit HLongConstant(int64_t value, uint32_t dex_pc = kNoDexPc)
+ : HConstant(Primitive::kPrimLong, dex_pc), value_(value) {}
const int64_t value_;
@@ -2261,7 +2275,8 @@
// two successors.
class HIf : public HTemplateInstruction<1> {
public:
- explicit HIf(HInstruction* input) : HTemplateInstruction(SideEffects::None()) {
+ explicit HIf(HInstruction* input, uint32_t dex_pc = kNoDexPc)
+ : HTemplateInstruction(SideEffects::None(), dex_pc) {
SetRawInputAt(0, input);
}
@@ -2294,8 +2309,8 @@
kExit,
};
- explicit HTryBoundary(BoundaryKind kind)
- : HTemplateInstruction(SideEffects::None()), kind_(kind) {}
+ explicit HTryBoundary(BoundaryKind kind, uint32_t dex_pc = kNoDexPc)
+ : HTemplateInstruction(SideEffects::None(), dex_pc), kind_(kind) {}
bool IsControlFlow() const OVERRIDE { return true; }
@@ -2352,21 +2367,17 @@
// Deoptimize to interpreter, upon checking a condition.
class HDeoptimize : public HTemplateInstruction<1> {
public:
- HDeoptimize(HInstruction* cond, uint32_t dex_pc)
- : HTemplateInstruction(SideEffects::None()),
- dex_pc_(dex_pc) {
+ explicit HDeoptimize(HInstruction* cond, uint32_t dex_pc)
+ : HTemplateInstruction(SideEffects::None(), dex_pc) {
SetRawInputAt(0, cond);
}
bool NeedsEnvironment() const OVERRIDE { return true; }
bool CanThrow() const OVERRIDE { return true; }
- uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
DECLARE_INSTRUCTION(Deoptimize);
private:
- uint32_t dex_pc_;
-
DISALLOW_COPY_AND_ASSIGN(HDeoptimize);
};
@@ -2375,7 +2386,8 @@
// instructions that work with the dex cache.
class HCurrentMethod : public HExpression<0> {
public:
- explicit HCurrentMethod(Primitive::Type type) : HExpression(type, SideEffects::None()) {}
+ explicit HCurrentMethod(Primitive::Type type, uint32_t dex_pc = kNoDexPc)
+ : HExpression(type, SideEffects::None(), dex_pc) {}
DECLARE_INSTRUCTION(CurrentMethod);
@@ -2385,8 +2397,8 @@
class HUnaryOperation : public HExpression<1> {
public:
- HUnaryOperation(Primitive::Type result_type, HInstruction* input)
- : HExpression(result_type, SideEffects::None()) {
+ HUnaryOperation(Primitive::Type result_type, HInstruction* input, uint32_t dex_pc = kNoDexPc)
+ : HExpression(result_type, SideEffects::None(), dex_pc) {
SetRawInputAt(0, input);
}
@@ -2419,8 +2431,9 @@
HBinaryOperation(Primitive::Type result_type,
HInstruction* left,
HInstruction* right,
- SideEffects side_effects = SideEffects::None())
- : HExpression(result_type, side_effects) {
+ SideEffects side_effects = SideEffects::None(),
+ uint32_t dex_pc = kNoDexPc)
+ : HExpression(result_type, side_effects, dex_pc) {
SetRawInputAt(0, left);
SetRawInputAt(1, right);
}
@@ -2512,8 +2525,8 @@
class HCondition : public HBinaryOperation {
public:
- HCondition(HInstruction* first, HInstruction* second)
- : HBinaryOperation(Primitive::kPrimBoolean, first, second),
+ HCondition(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
+ : HBinaryOperation(Primitive::kPrimBoolean, first, second, SideEffects::None(), dex_pc),
needs_materialization_(true),
bias_(ComparisonBias::kNoBias) {}
@@ -2564,18 +2577,20 @@
// Instruction to check if two inputs are equal to each other.
class HEqual : public HCondition {
public:
- HEqual(HInstruction* first, HInstruction* second)
- : HCondition(first, second) {}
+ HEqual(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
+ : HCondition(first, second, dex_pc) {}
bool IsCommutative() const OVERRIDE { return true; }
template <typename T> bool Compute(T x, T y) const { return x == y; }
HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue(), y->GetValue()));
+ return GetBlock()->GetGraph()->GetIntConstant(
+ Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue(), y->GetValue()));
+ return GetBlock()->GetGraph()->GetIntConstant(
+ Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
DECLARE_INSTRUCTION(Equal);
@@ -2594,18 +2609,20 @@
class HNotEqual : public HCondition {
public:
- HNotEqual(HInstruction* first, HInstruction* second)
- : HCondition(first, second) {}
+ HNotEqual(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
+ : HCondition(first, second, dex_pc) {}
bool IsCommutative() const OVERRIDE { return true; }
template <typename T> bool Compute(T x, T y) const { return x != y; }
HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue(), y->GetValue()));
+ return GetBlock()->GetGraph()->GetIntConstant(
+ Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue(), y->GetValue()));
+ return GetBlock()->GetGraph()->GetIntConstant(
+ Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
DECLARE_INSTRUCTION(NotEqual);
@@ -2624,16 +2641,18 @@
class HLessThan : public HCondition {
public:
- HLessThan(HInstruction* first, HInstruction* second)
- : HCondition(first, second) {}
+ HLessThan(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
+ : HCondition(first, second, dex_pc) {}
template <typename T> bool Compute(T x, T y) const { return x < y; }
HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue(), y->GetValue()));
+ return GetBlock()->GetGraph()->GetIntConstant(
+ Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue(), y->GetValue()));
+ return GetBlock()->GetGraph()->GetIntConstant(
+ Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
DECLARE_INSTRUCTION(LessThan);
@@ -2652,16 +2671,18 @@
class HLessThanOrEqual : public HCondition {
public:
- HLessThanOrEqual(HInstruction* first, HInstruction* second)
- : HCondition(first, second) {}
+ HLessThanOrEqual(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
+ : HCondition(first, second, dex_pc) {}
template <typename T> bool Compute(T x, T y) const { return x <= y; }
HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue(), y->GetValue()));
+ return GetBlock()->GetGraph()->GetIntConstant(
+ Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue(), y->GetValue()));
+ return GetBlock()->GetGraph()->GetIntConstant(
+ Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
DECLARE_INSTRUCTION(LessThanOrEqual);
@@ -2680,16 +2701,18 @@
class HGreaterThan : public HCondition {
public:
- HGreaterThan(HInstruction* first, HInstruction* second)
- : HCondition(first, second) {}
+ HGreaterThan(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
+ : HCondition(first, second, dex_pc) {}
template <typename T> bool Compute(T x, T y) const { return x > y; }
HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue(), y->GetValue()));
+ return GetBlock()->GetGraph()->GetIntConstant(
+ Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue(), y->GetValue()));
+ return GetBlock()->GetGraph()->GetIntConstant(
+ Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
DECLARE_INSTRUCTION(GreaterThan);
@@ -2708,16 +2731,18 @@
class HGreaterThanOrEqual : public HCondition {
public:
- HGreaterThanOrEqual(HInstruction* first, HInstruction* second)
- : HCondition(first, second) {}
+ HGreaterThanOrEqual(HInstruction* first, HInstruction* second, uint32_t dex_pc = kNoDexPc)
+ : HCondition(first, second, dex_pc) {}
template <typename T> bool Compute(T x, T y) const { return x >= y; }
HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue(), y->GetValue()));
+ return GetBlock()->GetGraph()->GetIntConstant(
+ Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue(), y->GetValue()));
+ return GetBlock()->GetGraph()->GetIntConstant(
+ Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
DECLARE_INSTRUCTION(GreaterThanOrEqual);
@@ -2744,9 +2769,12 @@
HInstruction* second,
ComparisonBias bias,
uint32_t dex_pc)
- : HBinaryOperation(Primitive::kPrimInt, first, second, SideEffectsForArchRuntimeCalls(type)),
- bias_(bias),
- dex_pc_(dex_pc) {
+ : HBinaryOperation(Primitive::kPrimInt,
+ first,
+ second,
+ SideEffectsForArchRuntimeCalls(type),
+ dex_pc),
+ bias_(bias) {
DCHECK_EQ(type, first->GetType());
DCHECK_EQ(type, second->GetType());
}
@@ -2755,10 +2783,12 @@
int32_t Compute(T x, T y) const { return x == y ? 0 : x > y ? 1 : -1; }
HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue(), y->GetValue()));
+ return GetBlock()->GetGraph()->GetIntConstant(
+ Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue(), y->GetValue()));
+ return GetBlock()->GetGraph()->GetIntConstant(
+ Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
@@ -2769,7 +2799,6 @@
bool IsGtBias() { return bias_ == ComparisonBias::kGtBias; }
- uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
static SideEffects SideEffectsForArchRuntimeCalls(Primitive::Type type) {
// MIPS64 uses a runtime call for FP comparisons.
@@ -2780,7 +2809,6 @@
private:
const ComparisonBias bias_;
- const uint32_t dex_pc_;
DISALLOW_COPY_AND_ASSIGN(HCompare);
};
@@ -2789,7 +2817,7 @@
class HLocal : public HTemplateInstruction<0> {
public:
explicit HLocal(uint16_t reg_number)
- : HTemplateInstruction(SideEffects::None()), reg_number_(reg_number) {}
+ : HTemplateInstruction(SideEffects::None(), kNoDexPc), reg_number_(reg_number) {}
DECLARE_INSTRUCTION(Local);
@@ -2805,8 +2833,8 @@
// Load a given local. The local is an input of this instruction.
class HLoadLocal : public HExpression<1> {
public:
- HLoadLocal(HLocal* local, Primitive::Type type)
- : HExpression(type, SideEffects::None()) {
+ HLoadLocal(HLocal* local, Primitive::Type type, uint32_t dex_pc = kNoDexPc)
+ : HExpression(type, SideEffects::None(), dex_pc) {
SetRawInputAt(0, local);
}
@@ -2822,7 +2850,8 @@
// and the local.
class HStoreLocal : public HTemplateInstruction<2> {
public:
- HStoreLocal(HLocal* local, HInstruction* value) : HTemplateInstruction(SideEffects::None()) {
+ HStoreLocal(HLocal* local, HInstruction* value, uint32_t dex_pc = kNoDexPc)
+ : HTemplateInstruction(SideEffects::None(), dex_pc) {
SetRawInputAt(0, local);
SetRawInputAt(1, value);
}
@@ -2863,9 +2892,10 @@
DECLARE_INSTRUCTION(FloatConstant);
private:
- explicit HFloatConstant(float value) : HConstant(Primitive::kPrimFloat), value_(value) {}
- explicit HFloatConstant(int32_t value)
- : HConstant(Primitive::kPrimFloat), value_(bit_cast<float, int32_t>(value)) {}
+ explicit HFloatConstant(float value, uint32_t dex_pc = kNoDexPc)
+ : HConstant(Primitive::kPrimFloat, dex_pc), value_(value) {}
+ explicit HFloatConstant(int32_t value, uint32_t dex_pc = kNoDexPc)
+ : HConstant(Primitive::kPrimFloat, dex_pc), value_(bit_cast<float, int32_t>(value)) {}
const float value_;
@@ -2903,9 +2933,10 @@
DECLARE_INSTRUCTION(DoubleConstant);
private:
- explicit HDoubleConstant(double value) : HConstant(Primitive::kPrimDouble), value_(value) {}
- explicit HDoubleConstant(int64_t value)
- : HConstant(Primitive::kPrimDouble), value_(bit_cast<double, int64_t>(value)) {}
+ explicit HDoubleConstant(double value, uint32_t dex_pc = kNoDexPc)
+ : HConstant(Primitive::kPrimDouble, dex_pc), value_(value) {}
+ explicit HDoubleConstant(int64_t value, uint32_t dex_pc = kNoDexPc)
+ : HConstant(Primitive::kPrimDouble, dex_pc), value_(bit_cast<double, int64_t>(value)) {}
const double value_;
@@ -2952,7 +2983,6 @@
Primitive::Type GetType() const OVERRIDE { return return_type_; }
- uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
uint32_t GetDexMethodIndex() const { return dex_method_index_; }
const DexFile& GetDexFile() const { return GetEnvironment()->GetDexFile(); }
@@ -2985,11 +3015,10 @@
uint32_t dex_method_index,
InvokeType original_invoke_type)
: HInstruction(
- SideEffects::AllExceptGCDependency()), // Assume write/read on all fields/arrays.
+ SideEffects::AllExceptGCDependency(), dex_pc), // Assume write/read on all fields/arrays.
number_of_arguments_(number_of_arguments),
inputs_(arena, number_of_arguments),
return_type_(return_type),
- dex_pc_(dex_pc),
dex_method_index_(dex_method_index),
original_invoke_type_(original_invoke_type),
intrinsic_(Intrinsics::kNone),
@@ -3006,7 +3035,6 @@
uint32_t number_of_arguments_;
GrowableArray<HUserRecord<HInstruction*> > inputs_;
const Primitive::Type return_type_;
- const uint32_t dex_pc_;
const uint32_t dex_method_index_;
const InvokeType original_invoke_type_;
Intrinsics intrinsic_;
@@ -3307,15 +3335,13 @@
uint16_t type_index,
const DexFile& dex_file,
QuickEntrypointEnum entrypoint)
- : HExpression(Primitive::kPrimNot, SideEffects::CanTriggerGC()),
- dex_pc_(dex_pc),
+ : HExpression(Primitive::kPrimNot, SideEffects::CanTriggerGC(), dex_pc),
type_index_(type_index),
dex_file_(dex_file),
entrypoint_(entrypoint) {
SetRawInputAt(0, current_method);
}
- uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
uint16_t GetTypeIndex() const { return type_index_; }
const DexFile& GetDexFile() const { return dex_file_; }
@@ -3334,7 +3360,6 @@
DECLARE_INSTRUCTION(NewInstance);
private:
- const uint32_t dex_pc_;
const uint16_t type_index_;
const DexFile& dex_file_;
const QuickEntrypointEnum entrypoint_;
@@ -3344,16 +3369,16 @@
class HNeg : public HUnaryOperation {
public:
- HNeg(Primitive::Type result_type, HInstruction* input)
- : HUnaryOperation(result_type, input) {}
+ HNeg(Primitive::Type result_type, HInstruction* input, uint32_t dex_pc = kNoDexPc)
+ : HUnaryOperation(result_type, input, dex_pc) {}
template <typename T> T Compute(T x) const { return -x; }
HConstant* Evaluate(HIntConstant* x) const OVERRIDE {
- return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue()));
+ return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue()), GetDexPc());
}
HConstant* Evaluate(HLongConstant* x) const OVERRIDE {
- return GetBlock()->GetGraph()->GetLongConstant(Compute(x->GetValue()));
+ return GetBlock()->GetGraph()->GetLongConstant(Compute(x->GetValue()), GetDexPc());
}
DECLARE_INSTRUCTION(Neg);
@@ -3370,8 +3395,7 @@
uint16_t type_index,
const DexFile& dex_file,
QuickEntrypointEnum entrypoint)
- : HExpression(Primitive::kPrimNot, SideEffects::CanTriggerGC()),
- dex_pc_(dex_pc),
+ : HExpression(Primitive::kPrimNot, SideEffects::CanTriggerGC(), dex_pc),
type_index_(type_index),
dex_file_(dex_file),
entrypoint_(entrypoint) {
@@ -3379,7 +3403,6 @@
SetRawInputAt(1, current_method);
}
- uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
uint16_t GetTypeIndex() const { return type_index_; }
const DexFile& GetDexFile() const { return dex_file_; }
@@ -3396,7 +3419,6 @@
DECLARE_INSTRUCTION(NewArray);
private:
- const uint32_t dex_pc_;
const uint16_t type_index_;
const DexFile& dex_file_;
const QuickEntrypointEnum entrypoint_;
@@ -3406,18 +3428,23 @@
class HAdd : public HBinaryOperation {
public:
- HAdd(Primitive::Type result_type, HInstruction* left, HInstruction* right)
- : HBinaryOperation(result_type, left, right) {}
+ HAdd(Primitive::Type result_type,
+ HInstruction* left,
+ HInstruction* right,
+ uint32_t dex_pc = kNoDexPc)
+ : HBinaryOperation(result_type, left, right, SideEffects::None(), dex_pc) {}
bool IsCommutative() const OVERRIDE { return true; }
template <typename T> T Compute(T x, T y) const { return x + y; }
HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue(), y->GetValue()));
+ return GetBlock()->GetGraph()->GetIntConstant(
+ Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetLongConstant(Compute(x->GetValue(), y->GetValue()));
+ return GetBlock()->GetGraph()->GetLongConstant(
+ Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
DECLARE_INSTRUCTION(Add);
@@ -3428,16 +3455,21 @@
class HSub : public HBinaryOperation {
public:
- HSub(Primitive::Type result_type, HInstruction* left, HInstruction* right)
- : HBinaryOperation(result_type, left, right) {}
+ HSub(Primitive::Type result_type,
+ HInstruction* left,
+ HInstruction* right,
+ uint32_t dex_pc = kNoDexPc)
+ : HBinaryOperation(result_type, left, right, SideEffects::None(), dex_pc) {}
template <typename T> T Compute(T x, T y) const { return x - y; }
HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue(), y->GetValue()));
+ return GetBlock()->GetGraph()->GetIntConstant(
+ Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetLongConstant(Compute(x->GetValue(), y->GetValue()));
+ return GetBlock()->GetGraph()->GetLongConstant(
+ Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
DECLARE_INSTRUCTION(Sub);
@@ -3448,18 +3480,23 @@
class HMul : public HBinaryOperation {
public:
- HMul(Primitive::Type result_type, HInstruction* left, HInstruction* right)
- : HBinaryOperation(result_type, left, right) {}
+ HMul(Primitive::Type result_type,
+ HInstruction* left,
+ HInstruction* right,
+ uint32_t dex_pc = kNoDexPc)
+ : HBinaryOperation(result_type, left, right, SideEffects::None(), dex_pc) {}
bool IsCommutative() const OVERRIDE { return true; }
template <typename T> T Compute(T x, T y) const { return x * y; }
HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue(), y->GetValue()));
+ return GetBlock()->GetGraph()->GetIntConstant(
+ Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetLongConstant(Compute(x->GetValue(), y->GetValue()));
+ return GetBlock()->GetGraph()->GetLongConstant(
+ Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
DECLARE_INSTRUCTION(Mul);
@@ -3470,9 +3507,11 @@
class HDiv : public HBinaryOperation {
public:
- HDiv(Primitive::Type result_type, HInstruction* left, HInstruction* right, uint32_t dex_pc)
- : HBinaryOperation(result_type, left, right, SideEffectsForArchRuntimeCalls()),
- dex_pc_(dex_pc) {}
+ HDiv(Primitive::Type result_type,
+ HInstruction* left,
+ HInstruction* right,
+ uint32_t dex_pc)
+ : HBinaryOperation(result_type, left, right, SideEffectsForArchRuntimeCalls(), dex_pc) {}
template <typename T>
T Compute(T x, T y) const {
@@ -3484,14 +3523,14 @@
}
HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue(), y->GetValue()));
+ return GetBlock()->GetGraph()->GetIntConstant(
+ Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetLongConstant(Compute(x->GetValue(), y->GetValue()));
+ return GetBlock()->GetGraph()->GetLongConstant(
+ Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
- uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
-
static SideEffects SideEffectsForArchRuntimeCalls() {
// The generated code can use a runtime call.
return SideEffects::CanTriggerGC();
@@ -3500,16 +3539,16 @@
DECLARE_INSTRUCTION(Div);
private:
- const uint32_t dex_pc_;
-
DISALLOW_COPY_AND_ASSIGN(HDiv);
};
class HRem : public HBinaryOperation {
public:
- HRem(Primitive::Type result_type, HInstruction* left, HInstruction* right, uint32_t dex_pc)
- : HBinaryOperation(result_type, left, right, SideEffectsForArchRuntimeCalls()),
- dex_pc_(dex_pc) {}
+ HRem(Primitive::Type result_type,
+ HInstruction* left,
+ HInstruction* right,
+ uint32_t dex_pc)
+ : HBinaryOperation(result_type, left, right, SideEffectsForArchRuntimeCalls(), dex_pc) {}
template <typename T>
T Compute(T x, T y) const {
@@ -3521,13 +3560,14 @@
}
HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue(), y->GetValue()));
+ return GetBlock()->GetGraph()->GetIntConstant(
+ Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetLongConstant(Compute(x->GetValue(), y->GetValue()));
+ return GetBlock()->GetGraph()->GetLongConstant(
+ Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
- uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
static SideEffects SideEffectsForArchRuntimeCalls() {
return SideEffects::CanTriggerGC();
@@ -3536,15 +3576,13 @@
DECLARE_INSTRUCTION(Rem);
private:
- const uint32_t dex_pc_;
-
DISALLOW_COPY_AND_ASSIGN(HRem);
};
class HDivZeroCheck : public HExpression<1> {
public:
HDivZeroCheck(HInstruction* value, uint32_t dex_pc)
- : HExpression(value->GetType(), SideEffects::None()), dex_pc_(dex_pc) {
+ : HExpression(value->GetType(), SideEffects::None(), dex_pc) {
SetRawInputAt(0, value);
}
@@ -3560,20 +3598,19 @@
bool NeedsEnvironment() const OVERRIDE { return true; }
bool CanThrow() const OVERRIDE { return true; }
- uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
-
DECLARE_INSTRUCTION(DivZeroCheck);
private:
- const uint32_t dex_pc_;
-
DISALLOW_COPY_AND_ASSIGN(HDivZeroCheck);
};
class HShl : public HBinaryOperation {
public:
- HShl(Primitive::Type result_type, HInstruction* left, HInstruction* right)
- : HBinaryOperation(result_type, left, right) {}
+ HShl(Primitive::Type result_type,
+ HInstruction* left,
+ HInstruction* right,
+ uint32_t dex_pc = kNoDexPc)
+ : HBinaryOperation(result_type, left, right, SideEffects::None(), dex_pc) {}
template <typename T, typename U, typename V>
T Compute(T x, U y, V max_shift_value) const {
@@ -3584,17 +3621,17 @@
HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
return GetBlock()->GetGraph()->GetIntConstant(
- Compute(x->GetValue(), y->GetValue(), kMaxIntShiftValue));
+ Compute(x->GetValue(), y->GetValue(), kMaxIntShiftValue), GetDexPc());
}
// There is no `Evaluate(HIntConstant* x, HLongConstant* y)`, as this
// case is handled as `x << static_cast<int>(y)`.
HConstant* Evaluate(HLongConstant* x, HIntConstant* y) const OVERRIDE {
return GetBlock()->GetGraph()->GetLongConstant(
- Compute(x->GetValue(), y->GetValue(), kMaxLongShiftValue));
+ Compute(x->GetValue(), y->GetValue(), kMaxLongShiftValue), GetDexPc());
}
HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
return GetBlock()->GetGraph()->GetLongConstant(
- Compute(x->GetValue(), y->GetValue(), kMaxLongShiftValue));
+ Compute(x->GetValue(), y->GetValue(), kMaxLongShiftValue), GetDexPc());
}
DECLARE_INSTRUCTION(Shl);
@@ -3605,8 +3642,11 @@
class HShr : public HBinaryOperation {
public:
- HShr(Primitive::Type result_type, HInstruction* left, HInstruction* right)
- : HBinaryOperation(result_type, left, right) {}
+ HShr(Primitive::Type result_type,
+ HInstruction* left,
+ HInstruction* right,
+ uint32_t dex_pc = kNoDexPc)
+ : HBinaryOperation(result_type, left, right, SideEffects::None(), dex_pc) {}
template <typename T, typename U, typename V>
T Compute(T x, U y, V max_shift_value) const {
@@ -3617,17 +3657,17 @@
HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
return GetBlock()->GetGraph()->GetIntConstant(
- Compute(x->GetValue(), y->GetValue(), kMaxIntShiftValue));
+ Compute(x->GetValue(), y->GetValue(), kMaxIntShiftValue), GetDexPc());
}
// There is no `Evaluate(HIntConstant* x, HLongConstant* y)`, as this
// case is handled as `x >> static_cast<int>(y)`.
HConstant* Evaluate(HLongConstant* x, HIntConstant* y) const OVERRIDE {
return GetBlock()->GetGraph()->GetLongConstant(
- Compute(x->GetValue(), y->GetValue(), kMaxLongShiftValue));
+ Compute(x->GetValue(), y->GetValue(), kMaxLongShiftValue), GetDexPc());
}
HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
return GetBlock()->GetGraph()->GetLongConstant(
- Compute(x->GetValue(), y->GetValue(), kMaxLongShiftValue));
+ Compute(x->GetValue(), y->GetValue(), kMaxLongShiftValue), GetDexPc());
}
DECLARE_INSTRUCTION(Shr);
@@ -3638,8 +3678,11 @@
class HUShr : public HBinaryOperation {
public:
- HUShr(Primitive::Type result_type, HInstruction* left, HInstruction* right)
- : HBinaryOperation(result_type, left, right) {}
+ HUShr(Primitive::Type result_type,
+ HInstruction* left,
+ HInstruction* right,
+ uint32_t dex_pc = kNoDexPc)
+ : HBinaryOperation(result_type, left, right, SideEffects::None(), dex_pc) {}
template <typename T, typename U, typename V>
T Compute(T x, U y, V max_shift_value) const {
@@ -3651,17 +3694,17 @@
HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
return GetBlock()->GetGraph()->GetIntConstant(
- Compute(x->GetValue(), y->GetValue(), kMaxIntShiftValue));
+ Compute(x->GetValue(), y->GetValue(), kMaxIntShiftValue), GetDexPc());
}
// There is no `Evaluate(HIntConstant* x, HLongConstant* y)`, as this
// case is handled as `x >>> static_cast<int>(y)`.
HConstant* Evaluate(HLongConstant* x, HIntConstant* y) const OVERRIDE {
return GetBlock()->GetGraph()->GetLongConstant(
- Compute(x->GetValue(), y->GetValue(), kMaxLongShiftValue));
+ Compute(x->GetValue(), y->GetValue(), kMaxLongShiftValue), GetDexPc());
}
HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
return GetBlock()->GetGraph()->GetLongConstant(
- Compute(x->GetValue(), y->GetValue(), kMaxLongShiftValue));
+ Compute(x->GetValue(), y->GetValue(), kMaxLongShiftValue), GetDexPc());
}
DECLARE_INSTRUCTION(UShr);
@@ -3672,8 +3715,11 @@
class HAnd : public HBinaryOperation {
public:
- HAnd(Primitive::Type result_type, HInstruction* left, HInstruction* right)
- : HBinaryOperation(result_type, left, right) {}
+ HAnd(Primitive::Type result_type,
+ HInstruction* left,
+ HInstruction* right,
+ uint32_t dex_pc = kNoDexPc)
+ : HBinaryOperation(result_type, left, right, SideEffects::None(), dex_pc) {}
bool IsCommutative() const OVERRIDE { return true; }
@@ -3681,16 +3727,20 @@
auto Compute(T x, U y) const -> decltype(x & y) { return x & y; }
HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue(), y->GetValue()));
+ return GetBlock()->GetGraph()->GetIntConstant(
+ Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
HConstant* Evaluate(HIntConstant* x, HLongConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetLongConstant(Compute(x->GetValue(), y->GetValue()));
+ return GetBlock()->GetGraph()->GetLongConstant(
+ Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
HConstant* Evaluate(HLongConstant* x, HIntConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetLongConstant(Compute(x->GetValue(), y->GetValue()));
+ return GetBlock()->GetGraph()->GetLongConstant(
+ Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetLongConstant(Compute(x->GetValue(), y->GetValue()));
+ return GetBlock()->GetGraph()->GetLongConstant(
+ Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
DECLARE_INSTRUCTION(And);
@@ -3701,8 +3751,11 @@
class HOr : public HBinaryOperation {
public:
- HOr(Primitive::Type result_type, HInstruction* left, HInstruction* right)
- : HBinaryOperation(result_type, left, right) {}
+ HOr(Primitive::Type result_type,
+ HInstruction* left,
+ HInstruction* right,
+ uint32_t dex_pc = kNoDexPc)
+ : HBinaryOperation(result_type, left, right, SideEffects::None(), dex_pc) {}
bool IsCommutative() const OVERRIDE { return true; }
@@ -3710,16 +3763,20 @@
auto Compute(T x, U y) const -> decltype(x | y) { return x | y; }
HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue(), y->GetValue()));
+ return GetBlock()->GetGraph()->GetIntConstant(
+ Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
HConstant* Evaluate(HIntConstant* x, HLongConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetLongConstant(Compute(x->GetValue(), y->GetValue()));
+ return GetBlock()->GetGraph()->GetLongConstant(
+ Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
HConstant* Evaluate(HLongConstant* x, HIntConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetLongConstant(Compute(x->GetValue(), y->GetValue()));
+ return GetBlock()->GetGraph()->GetLongConstant(
+ Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetLongConstant(Compute(x->GetValue(), y->GetValue()));
+ return GetBlock()->GetGraph()->GetLongConstant(
+ Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
DECLARE_INSTRUCTION(Or);
@@ -3730,8 +3787,11 @@
class HXor : public HBinaryOperation {
public:
- HXor(Primitive::Type result_type, HInstruction* left, HInstruction* right)
- : HBinaryOperation(result_type, left, right) {}
+ HXor(Primitive::Type result_type,
+ HInstruction* left,
+ HInstruction* right,
+ uint32_t dex_pc = kNoDexPc)
+ : HBinaryOperation(result_type, left, right, SideEffects::None(), dex_pc) {}
bool IsCommutative() const OVERRIDE { return true; }
@@ -3739,16 +3799,20 @@
auto Compute(T x, U y) const -> decltype(x ^ y) { return x ^ y; }
HConstant* Evaluate(HIntConstant* x, HIntConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue(), y->GetValue()));
+ return GetBlock()->GetGraph()->GetIntConstant(
+ Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
HConstant* Evaluate(HIntConstant* x, HLongConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetLongConstant(Compute(x->GetValue(), y->GetValue()));
+ return GetBlock()->GetGraph()->GetLongConstant(
+ Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
HConstant* Evaluate(HLongConstant* x, HIntConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetLongConstant(Compute(x->GetValue(), y->GetValue()));
+ return GetBlock()->GetGraph()->GetLongConstant(
+ Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
HConstant* Evaluate(HLongConstant* x, HLongConstant* y) const OVERRIDE {
- return GetBlock()->GetGraph()->GetLongConstant(Compute(x->GetValue(), y->GetValue()));
+ return GetBlock()->GetGraph()->GetLongConstant(
+ Compute(x->GetValue(), y->GetValue()), GetDexPc());
}
DECLARE_INSTRUCTION(Xor);
@@ -3761,8 +3825,10 @@
// the calling convention.
class HParameterValue : public HExpression<0> {
public:
- HParameterValue(uint8_t index, Primitive::Type parameter_type, bool is_this = false)
- : HExpression(parameter_type, SideEffects::None()),
+ HParameterValue(uint8_t index,
+ Primitive::Type parameter_type,
+ bool is_this = false)
+ : HExpression(parameter_type, SideEffects::None(), kNoDexPc),
index_(index),
is_this_(is_this),
can_be_null_(!is_this) {}
@@ -3791,8 +3857,8 @@
class HNot : public HUnaryOperation {
public:
- HNot(Primitive::Type result_type, HInstruction* input)
- : HUnaryOperation(result_type, input) {}
+ HNot(Primitive::Type result_type, HInstruction* input, uint32_t dex_pc = kNoDexPc)
+ : HUnaryOperation(result_type, input, dex_pc) {}
bool CanBeMoved() const OVERRIDE { return true; }
bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
@@ -3803,10 +3869,10 @@
template <typename T> T Compute(T x) const { return ~x; }
HConstant* Evaluate(HIntConstant* x) const OVERRIDE {
- return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue()));
+ return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue()), GetDexPc());
}
HConstant* Evaluate(HLongConstant* x) const OVERRIDE {
- return GetBlock()->GetGraph()->GetLongConstant(Compute(x->GetValue()));
+ return GetBlock()->GetGraph()->GetLongConstant(Compute(x->GetValue()), GetDexPc());
}
DECLARE_INSTRUCTION(Not);
@@ -3817,8 +3883,8 @@
class HBooleanNot : public HUnaryOperation {
public:
- explicit HBooleanNot(HInstruction* input)
- : HUnaryOperation(Primitive::Type::kPrimBoolean, input) {}
+ explicit HBooleanNot(HInstruction* input, uint32_t dex_pc = kNoDexPc)
+ : HUnaryOperation(Primitive::Type::kPrimBoolean, input, dex_pc) {}
bool CanBeMoved() const OVERRIDE { return true; }
bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
@@ -3832,7 +3898,7 @@
}
HConstant* Evaluate(HIntConstant* x) const OVERRIDE {
- return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue()));
+ return GetBlock()->GetGraph()->GetIntConstant(Compute(x->GetValue()), GetDexPc());
}
HConstant* Evaluate(HLongConstant* x ATTRIBUTE_UNUSED) const OVERRIDE {
LOG(FATAL) << DebugName() << " is not defined for long values";
@@ -3849,8 +3915,9 @@
public:
// Instantiate a type conversion of `input` to `result_type`.
HTypeConversion(Primitive::Type result_type, HInstruction* input, uint32_t dex_pc)
- : HExpression(result_type, SideEffectsForArchRuntimeCalls(input->GetType(), result_type)),
- dex_pc_(dex_pc) {
+ : HExpression(result_type,
+ SideEffectsForArchRuntimeCalls(input->GetType(), result_type),
+ dex_pc) {
SetRawInputAt(0, input);
DCHECK_NE(input->GetType(), result_type);
}
@@ -3861,7 +3928,6 @@
// Required by the x86 and ARM code generators when producing calls
// to the runtime.
- uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
bool CanBeMoved() const OVERRIDE { return true; }
bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE { return true; }
@@ -3885,8 +3951,6 @@
DECLARE_INSTRUCTION(TypeConversion);
private:
- const uint32_t dex_pc_;
-
DISALLOW_COPY_AND_ASSIGN(HTypeConversion);
};
@@ -3894,8 +3958,12 @@
class HPhi : public HInstruction {
public:
- HPhi(ArenaAllocator* arena, uint32_t reg_number, size_t number_of_inputs, Primitive::Type type)
- : HInstruction(SideEffects::None()),
+ HPhi(ArenaAllocator* arena,
+ uint32_t reg_number,
+ size_t number_of_inputs,
+ Primitive::Type type,
+ uint32_t dex_pc = kNoDexPc)
+ : HInstruction(SideEffects::None(), dex_pc),
inputs_(arena, number_of_inputs),
reg_number_(reg_number),
type_(type),
@@ -3973,7 +4041,7 @@
class HNullCheck : public HExpression<1> {
public:
HNullCheck(HInstruction* value, uint32_t dex_pc)
- : HExpression(value->GetType(), SideEffects::None()), dex_pc_(dex_pc) {
+ : HExpression(value->GetType(), SideEffects::None(), dex_pc) {
SetRawInputAt(0, value);
}
@@ -3989,13 +4057,10 @@
bool CanBeNull() const OVERRIDE { return false; }
- uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
DECLARE_INSTRUCTION(NullCheck);
private:
- const uint32_t dex_pc_;
-
DISALLOW_COPY_AND_ASSIGN(HNullCheck);
};
@@ -4038,10 +4103,11 @@
bool is_volatile,
uint32_t field_idx,
const DexFile& dex_file,
- Handle<mirror::DexCache> dex_cache)
+ Handle<mirror::DexCache> dex_cache,
+ uint32_t dex_pc = kNoDexPc)
: HExpression(
field_type,
- SideEffects::FieldReadOfType(field_type, is_volatile)),
+ SideEffects::FieldReadOfType(field_type, is_volatile), dex_pc),
field_info_(field_offset, field_type, is_volatile, field_idx, dex_file, dex_cache) {
SetRawInputAt(0, value);
}
@@ -4083,9 +4149,10 @@
bool is_volatile,
uint32_t field_idx,
const DexFile& dex_file,
- Handle<mirror::DexCache> dex_cache)
+ Handle<mirror::DexCache> dex_cache,
+ uint32_t dex_pc = kNoDexPc)
: HTemplateInstruction(
- SideEffects::FieldWriteOfType(field_type, is_volatile)),
+ SideEffects::FieldWriteOfType(field_type, is_volatile), dex_pc),
field_info_(field_offset, field_type, is_volatile, field_idx, dex_file, dex_cache),
value_can_be_null_(true) {
SetRawInputAt(0, object);
@@ -4115,8 +4182,11 @@
class HArrayGet : public HExpression<2> {
public:
- HArrayGet(HInstruction* array, HInstruction* index, Primitive::Type type)
- : HExpression(type, SideEffects::ArrayReadOfType(type)) {
+ HArrayGet(HInstruction* array,
+ HInstruction* index,
+ Primitive::Type type,
+ uint32_t dex_pc = kNoDexPc)
+ : HExpression(type, SideEffects::ArrayReadOfType(type), dex_pc) {
SetRawInputAt(0, array);
SetRawInputAt(1, index);
}
@@ -4156,8 +4226,7 @@
uint32_t dex_pc)
: HTemplateInstruction(
SideEffects::ArrayWriteOfType(expected_component_type).Union(
- SideEffectsForArchRuntimeCalls(value->GetType()))),
- dex_pc_(dex_pc),
+ SideEffectsForArchRuntimeCalls(value->GetType())), dex_pc),
expected_component_type_(expected_component_type),
needs_type_check_(value->GetType() == Primitive::kPrimNot),
value_can_be_null_(true) {
@@ -4192,8 +4261,6 @@
bool GetValueCanBeNull() const { return value_can_be_null_; }
bool NeedsTypeCheck() const { return needs_type_check_; }
- uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
-
HInstruction* GetArray() const { return InputAt(0); }
HInstruction* GetIndex() const { return InputAt(1); }
HInstruction* GetValue() const { return InputAt(2); }
@@ -4216,7 +4283,6 @@
DECLARE_INSTRUCTION(ArraySet);
private:
- const uint32_t dex_pc_;
const Primitive::Type expected_component_type_;
bool needs_type_check_;
bool value_can_be_null_;
@@ -4226,8 +4292,8 @@
class HArrayLength : public HExpression<1> {
public:
- explicit HArrayLength(HInstruction* array)
- : HExpression(Primitive::kPrimInt, SideEffects::None()) {
+ explicit HArrayLength(HInstruction* array, uint32_t dex_pc = kNoDexPc)
+ : HExpression(Primitive::kPrimInt, SideEffects::None(), dex_pc) {
// Note that arrays do not change length, so the instruction does not
// depend on any write.
SetRawInputAt(0, array);
@@ -4251,7 +4317,7 @@
class HBoundsCheck : public HExpression<2> {
public:
HBoundsCheck(HInstruction* index, HInstruction* length, uint32_t dex_pc)
- : HExpression(index->GetType(), SideEffects::None()), dex_pc_(dex_pc) {
+ : HExpression(index->GetType(), SideEffects::None(), dex_pc) {
DCHECK(index->GetType() == Primitive::kPrimInt);
SetRawInputAt(0, index);
SetRawInputAt(1, length);
@@ -4267,13 +4333,10 @@
bool CanThrow() const OVERRIDE { return true; }
- uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
DECLARE_INSTRUCTION(BoundsCheck);
private:
- const uint32_t dex_pc_;
-
DISALLOW_COPY_AND_ASSIGN(HBoundsCheck);
};
@@ -4286,7 +4349,8 @@
*/
class HTemporary : public HTemplateInstruction<0> {
public:
- explicit HTemporary(size_t index) : HTemplateInstruction(SideEffects::None()), index_(index) {}
+ explicit HTemporary(size_t index, uint32_t dex_pc = kNoDexPc)
+ : HTemplateInstruction(SideEffects::None(), dex_pc), index_(index) {}
size_t GetIndex() const { return index_; }
@@ -4300,28 +4364,24 @@
private:
const size_t index_;
-
DISALLOW_COPY_AND_ASSIGN(HTemporary);
};
class HSuspendCheck : public HTemplateInstruction<0> {
public:
explicit HSuspendCheck(uint32_t dex_pc)
- : HTemplateInstruction(SideEffects::CanTriggerGC()), dex_pc_(dex_pc), slow_path_(nullptr) {}
+ : HTemplateInstruction(SideEffects::CanTriggerGC(), dex_pc), slow_path_(nullptr) {}
bool NeedsEnvironment() const OVERRIDE {
return true;
}
- uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
void SetSlowPath(SlowPathCode* slow_path) { slow_path_ = slow_path; }
SlowPathCode* GetSlowPath() const { return slow_path_; }
DECLARE_INSTRUCTION(SuspendCheck);
private:
- const uint32_t dex_pc_;
-
// Only used for code generation, in order to share the same slow path between back edges
// of a same loop.
SlowPathCode* slow_path_;
@@ -4339,11 +4399,10 @@
const DexFile& dex_file,
bool is_referrers_class,
uint32_t dex_pc)
- : HExpression(Primitive::kPrimNot, SideEffectsForArchRuntimeCalls()),
+ : HExpression(Primitive::kPrimNot, SideEffectsForArchRuntimeCalls(), dex_pc),
type_index_(type_index),
dex_file_(dex_file),
is_referrers_class_(is_referrers_class),
- dex_pc_(dex_pc),
generate_clinit_check_(false),
loaded_class_rti_(ReferenceTypeInfo::CreateInvalid()) {
SetRawInputAt(0, current_method);
@@ -4357,7 +4416,6 @@
size_t ComputeHashCode() const OVERRIDE { return type_index_; }
- uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
uint16_t GetTypeIndex() const { return type_index_; }
bool IsReferrersClass() const { return is_referrers_class_; }
bool CanBeNull() const OVERRIDE { return false; }
@@ -4410,7 +4468,6 @@
const uint16_t type_index_;
const DexFile& dex_file_;
const bool is_referrers_class_;
- const uint32_t dex_pc_;
// Whether this instruction must generate the initialization check.
// Used for code generation.
bool generate_clinit_check_;
@@ -4423,9 +4480,8 @@
class HLoadString : public HExpression<1> {
public:
HLoadString(HCurrentMethod* current_method, uint32_t string_index, uint32_t dex_pc)
- : HExpression(Primitive::kPrimNot, SideEffectsForArchRuntimeCalls()),
- string_index_(string_index),
- dex_pc_(dex_pc) {
+ : HExpression(Primitive::kPrimNot, SideEffectsForArchRuntimeCalls(), dex_pc),
+ string_index_(string_index) {
SetRawInputAt(0, current_method);
}
@@ -4437,7 +4493,6 @@
size_t ComputeHashCode() const OVERRIDE { return string_index_; }
- uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
uint32_t GetStringIndex() const { return string_index_; }
// TODO: Can we deopt or debug when we resolve a string?
@@ -4453,7 +4508,6 @@
private:
const uint32_t string_index_;
- const uint32_t dex_pc_;
DISALLOW_COPY_AND_ASSIGN(HLoadString);
};
@@ -4466,8 +4520,8 @@
HClinitCheck(HLoadClass* constant, uint32_t dex_pc)
: HExpression(
Primitive::kPrimNot,
- SideEffects::AllChanges()), // Assume write/read on all fields/arrays.
- dex_pc_(dex_pc) {
+ SideEffects::AllChanges(), // Assume write/read on all fields/arrays.
+ dex_pc) {
SetRawInputAt(0, constant);
}
@@ -4482,15 +4536,12 @@
return true;
}
- uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
HLoadClass* GetLoadClass() const { return InputAt(0)->AsLoadClass(); }
DECLARE_INSTRUCTION(ClinitCheck);
private:
- const uint32_t dex_pc_;
-
DISALLOW_COPY_AND_ASSIGN(HClinitCheck);
};
@@ -4502,10 +4553,11 @@
bool is_volatile,
uint32_t field_idx,
const DexFile& dex_file,
- Handle<mirror::DexCache> dex_cache)
+ Handle<mirror::DexCache> dex_cache,
+ uint32_t dex_pc = kNoDexPc)
: HExpression(
field_type,
- SideEffects::FieldReadOfType(field_type, is_volatile)),
+ SideEffects::FieldReadOfType(field_type, is_volatile), dex_pc),
field_info_(field_offset, field_type, is_volatile, field_idx, dex_file, dex_cache) {
SetRawInputAt(0, cls);
}
@@ -4544,9 +4596,10 @@
bool is_volatile,
uint32_t field_idx,
const DexFile& dex_file,
- Handle<mirror::DexCache> dex_cache)
+ Handle<mirror::DexCache> dex_cache,
+ uint32_t dex_pc = kNoDexPc)
: HTemplateInstruction(
- SideEffects::FieldWriteOfType(field_type, is_volatile)),
+ SideEffects::FieldWriteOfType(field_type, is_volatile), dex_pc),
field_info_(field_offset, field_type, is_volatile, field_idx, dex_file, dex_cache),
value_can_be_null_(true) {
SetRawInputAt(0, cls);
@@ -4574,7 +4627,8 @@
// Implement the move-exception DEX instruction.
class HLoadException : public HExpression<0> {
public:
- HLoadException() : HExpression(Primitive::kPrimNot, SideEffects::None()) {}
+ explicit HLoadException(uint32_t dex_pc = kNoDexPc)
+ : HExpression(Primitive::kPrimNot, SideEffects::None(), dex_pc) {}
bool CanBeNull() const OVERRIDE { return false; }
@@ -4588,7 +4642,8 @@
// Must not be removed because the runtime expects the TLS to get cleared.
class HClearException : public HTemplateInstruction<0> {
public:
- HClearException() : HTemplateInstruction(SideEffects::AllWrites()) {}
+ explicit HClearException(uint32_t dex_pc = kNoDexPc)
+ : HTemplateInstruction(SideEffects::AllWrites(), dex_pc) {}
DECLARE_INSTRUCTION(ClearException);
@@ -4599,7 +4654,7 @@
class HThrow : public HTemplateInstruction<1> {
public:
HThrow(HInstruction* exception, uint32_t dex_pc)
- : HTemplateInstruction(SideEffects::CanTriggerGC()), dex_pc_(dex_pc) {
+ : HTemplateInstruction(SideEffects::CanTriggerGC(), dex_pc) {
SetRawInputAt(0, exception);
}
@@ -4609,13 +4664,10 @@
bool CanThrow() const OVERRIDE { return true; }
- uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
DECLARE_INSTRUCTION(Throw);
private:
- const uint32_t dex_pc_;
-
DISALLOW_COPY_AND_ASSIGN(HThrow);
};
@@ -4625,10 +4677,11 @@
HLoadClass* constant,
bool class_is_final,
uint32_t dex_pc)
- : HExpression(Primitive::kPrimBoolean, SideEffectsForArchRuntimeCalls(class_is_final)),
+ : HExpression(Primitive::kPrimBoolean,
+ SideEffectsForArchRuntimeCalls(class_is_final),
+ dex_pc),
class_is_final_(class_is_final),
- must_do_null_check_(true),
- dex_pc_(dex_pc) {
+ must_do_null_check_(true) {
SetRawInputAt(0, object);
SetRawInputAt(1, constant);
}
@@ -4643,8 +4696,6 @@
return false;
}
- uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
-
bool IsClassFinal() const { return class_is_final_; }
// Used only in code generation.
@@ -4660,7 +4711,6 @@
private:
const bool class_is_final_;
bool must_do_null_check_;
- const uint32_t dex_pc_;
DISALLOW_COPY_AND_ASSIGN(HInstanceOf);
};
@@ -4669,8 +4719,11 @@
public:
// Constructs an HBoundType with the given upper_bound.
// Ensures that the upper_bound is valid.
- HBoundType(HInstruction* input, ReferenceTypeInfo upper_bound, bool upper_can_be_null)
- : HExpression(Primitive::kPrimNot, SideEffects::None()),
+ HBoundType(HInstruction* input,
+ ReferenceTypeInfo upper_bound,
+ bool upper_can_be_null,
+ uint32_t dex_pc = kNoDexPc)
+ : HExpression(Primitive::kPrimNot, SideEffects::None(), dex_pc),
upper_bound_(upper_bound),
upper_can_be_null_(upper_can_be_null),
can_be_null_(upper_can_be_null) {
@@ -4714,10 +4767,9 @@
HLoadClass* constant,
bool class_is_final,
uint32_t dex_pc)
- : HTemplateInstruction(SideEffects::CanTriggerGC()),
+ : HTemplateInstruction(SideEffects::CanTriggerGC(), dex_pc),
class_is_final_(class_is_final),
- must_do_null_check_(true),
- dex_pc_(dex_pc) {
+ must_do_null_check_(true) {
SetRawInputAt(0, object);
SetRawInputAt(1, constant);
}
@@ -4738,7 +4790,6 @@
bool MustDoNullCheck() const { return must_do_null_check_; }
void ClearMustDoNullCheck() { must_do_null_check_ = false; }
- uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
bool IsClassFinal() const { return class_is_final_; }
@@ -4747,16 +4798,15 @@
private:
const bool class_is_final_;
bool must_do_null_check_;
- const uint32_t dex_pc_;
DISALLOW_COPY_AND_ASSIGN(HCheckCast);
};
class HMemoryBarrier : public HTemplateInstruction<0> {
public:
- explicit HMemoryBarrier(MemBarrierKind barrier_kind)
+ explicit HMemoryBarrier(MemBarrierKind barrier_kind, uint32_t dex_pc = kNoDexPc)
: HTemplateInstruction(
- SideEffects::AllWritesAndReads()), // Assume write/read on all fields/arrays.
+ SideEffects::AllWritesAndReads(), dex_pc), // Assume write/read on all fields/arrays.
barrier_kind_(barrier_kind) {}
MemBarrierKind GetBarrierKind() { return barrier_kind_; }
@@ -4778,8 +4828,8 @@
HMonitorOperation(HInstruction* object, OperationKind kind, uint32_t dex_pc)
: HTemplateInstruction(
- SideEffects::AllExceptGCDependency()), // Assume write/read on all fields/arrays.
- kind_(kind), dex_pc_(dex_pc) {
+ SideEffects::AllExceptGCDependency(), dex_pc), // Assume write/read on all fields/arrays.
+ kind_(kind) {
SetRawInputAt(0, object);
}
@@ -4793,7 +4843,6 @@
return IsEnter();
}
- uint32_t GetDexPc() const OVERRIDE { return dex_pc_; }
bool IsEnter() const { return kind_ == kEnter; }
@@ -4801,7 +4850,6 @@
private:
const OperationKind kind_;
- const uint32_t dex_pc_;
private:
DISALLOW_COPY_AND_ASSIGN(HMonitorOperation);
@@ -4816,7 +4864,8 @@
*/
class HFakeString : public HTemplateInstruction<0> {
public:
- HFakeString() : HTemplateInstruction(SideEffects::None()) {}
+ explicit HFakeString(uint32_t dex_pc = kNoDexPc)
+ : HTemplateInstruction(SideEffects::None(), dex_pc) {}
Primitive::Type GetType() const OVERRIDE { return Primitive::kPrimNot; }
@@ -4904,8 +4953,8 @@
class HParallelMove : public HTemplateInstruction<0> {
public:
- explicit HParallelMove(ArenaAllocator* arena)
- : HTemplateInstruction(SideEffects::None()), moves_(arena, kDefaultNumberOfMoves) {}
+ explicit HParallelMove(ArenaAllocator* arena, uint32_t dex_pc = kNoDexPc)
+ : HTemplateInstruction(SideEffects::None(), dex_pc), moves_(arena, kDefaultNumberOfMoves) {}
void AddMove(Location source,
Location destination,
@@ -4955,6 +5004,14 @@
DISALLOW_COPY_AND_ASSIGN(HParallelMove);
};
+} // namespace art
+
+#ifdef ART_ENABLE_CODEGEN_x86
+#include "nodes_x86.h"
+#endif
+
+namespace art {
+
class HGraphVisitor : public ValueObject {
public:
explicit HGraphVisitor(HGraph* graph) : graph_(graph) {}
diff --git a/compiler/optimizing/nodes_x86.h b/compiler/optimizing/nodes_x86.h
new file mode 100644
index 0000000..ddc5730
--- /dev/null
+++ b/compiler/optimizing/nodes_x86.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_COMPILER_OPTIMIZING_NODES_X86_H_
+#define ART_COMPILER_OPTIMIZING_NODES_X86_H_
+
+namespace art {
+
+// Compute the address of the method for X86 Constant area support.
+class HX86ComputeBaseMethodAddress : public HExpression<0> {
+ public:
+ // Treat the value as an int32_t, but it is really a 32 bit native pointer.
+ HX86ComputeBaseMethodAddress() : HExpression(Primitive::kPrimInt, SideEffects::None()) {}
+
+ DECLARE_INSTRUCTION(X86ComputeBaseMethodAddress);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(HX86ComputeBaseMethodAddress);
+};
+
+// Load a constant value from the constant table.
+class HX86LoadFromConstantTable : public HExpression<2> {
+ public:
+ HX86LoadFromConstantTable(HX86ComputeBaseMethodAddress* method_base,
+ HConstant* constant,
+ bool needs_materialization = true)
+ : HExpression(constant->GetType(), SideEffects::None()),
+ needs_materialization_(needs_materialization) {
+ SetRawInputAt(0, method_base);
+ SetRawInputAt(1, constant);
+ }
+
+ bool NeedsMaterialization() const { return needs_materialization_; }
+
+ HX86ComputeBaseMethodAddress* GetBaseMethodAddress() const {
+ return InputAt(0)->AsX86ComputeBaseMethodAddress();
+ }
+
+ HConstant* GetConstant() const {
+ return InputAt(1)->AsConstant();
+ }
+
+ DECLARE_INSTRUCTION(X86LoadFromConstantTable);
+
+ private:
+ const bool needs_materialization_;
+
+ DISALLOW_COPY_AND_ASSIGN(HX86LoadFromConstantTable);
+};
+
+} // namespace art
+
+#endif // ART_COMPILER_OPTIMIZING_NODES_X86_H_
diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc
index 91b03d4..f549ba8 100644
--- a/compiler/optimizing/optimizing_compiler.cc
+++ b/compiler/optimizing/optimizing_compiler.cc
@@ -23,6 +23,10 @@
#include "instruction_simplifier_arm64.h"
#endif
+#ifdef ART_ENABLE_CODEGEN_x86
+#include "constant_area_fixups_x86.h"
+#endif
+
#include "art_method-inl.h"
#include "base/arena_allocator.h"
#include "base/arena_containers.h"
@@ -424,6 +428,17 @@
break;
}
#endif
+#ifdef ART_ENABLE_CODEGEN_x86
+ case kX86: {
+ x86::ConstantAreaFixups* constant_area_fixups =
+ new (arena) x86::ConstantAreaFixups(graph, stats);
+ HOptimization* x86_optimizations[] = {
+ constant_area_fixups
+ };
+ RunOptimizations(x86_optimizations, arraysize(x86_optimizations), pass_observer);
+ break;
+ }
+#endif
default:
break;
}
diff --git a/compiler/utils/x86/assembler_x86.cc b/compiler/utils/x86/assembler_x86.cc
index a03f857..e3962b4 100644
--- a/compiler/utils/x86/assembler_x86.cc
+++ b/compiler/utils/x86/assembler_x86.cc
@@ -1750,6 +1750,10 @@
for (int i = 1; i < length; i++) {
EmitUint8(operand.encoding_[i]);
}
+ AssemblerFixup* fixup = operand.GetFixup();
+ if (fixup != nullptr) {
+ EmitFixup(fixup);
+ }
}
@@ -2322,5 +2326,56 @@
#undef __
}
+void X86Assembler::AddConstantArea() {
+ const std::vector<int32_t>& area = constant_area_.GetBuffer();
+ // Generate the data for the literal area.
+ for (size_t i = 0, e = area.size(); i < e; i++) {
+ AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+ EmitInt32(area[i]);
+ }
+}
+
+int ConstantArea::AddInt32(int32_t v) {
+ for (size_t i = 0, e = buffer_.size(); i < e; i++) {
+ if (v == buffer_[i]) {
+ return i * kEntrySize;
+ }
+ }
+
+ // Didn't match anything.
+ int result = buffer_.size() * kEntrySize;
+ buffer_.push_back(v);
+ return result;
+}
+
+int ConstantArea::AddInt64(int64_t v) {
+ int32_t v_low = Low32Bits(v);
+ int32_t v_high = High32Bits(v);
+ if (buffer_.size() > 1) {
+ // Ensure we don't pass the end of the buffer.
+ for (size_t i = 0, e = buffer_.size() - 1; i < e; i++) {
+ if (v_low == buffer_[i] && v_high == buffer_[i + 1]) {
+ return i * kEntrySize;
+ }
+ }
+ }
+
+ // Didn't match anything.
+ int result = buffer_.size() * kEntrySize;
+ buffer_.push_back(v_low);
+ buffer_.push_back(v_high);
+ return result;
+}
+
+int ConstantArea::AddDouble(double v) {
+ // Treat the value as a 64-bit integer value.
+ return AddInt64(bit_cast<int64_t, double>(v));
+}
+
+int ConstantArea::AddFloat(float v) {
+ // Treat the value as a 32-bit integer value.
+ return AddInt32(bit_cast<int32_t, float>(v));
+}
+
} // namespace x86
} // namespace art
diff --git a/compiler/utils/x86/assembler_x86.h b/compiler/utils/x86/assembler_x86.h
index 0c90f28..7d7b3d3 100644
--- a/compiler/utils/x86/assembler_x86.h
+++ b/compiler/utils/x86/assembler_x86.h
@@ -86,7 +86,7 @@
protected:
// Operand can be sub classed (e.g: Address).
- Operand() : length_(0) { }
+ Operand() : length_(0), fixup_(nullptr) { }
void SetModRM(int mod_in, Register rm_in) {
CHECK_EQ(mod_in & ~3, 0);
@@ -113,11 +113,23 @@
length_ += disp_size;
}
+ AssemblerFixup* GetFixup() const {
+ return fixup_;
+ }
+
+ void SetFixup(AssemblerFixup* fixup) {
+ fixup_ = fixup;
+ }
+
private:
uint8_t length_;
uint8_t encoding_[6];
- explicit Operand(Register reg) { SetModRM(3, reg); }
+ // A fixup can be associated with the operand, in order to be applied after the
+ // code has been generated. This is used for constant area fixups.
+ AssemblerFixup* fixup_;
+
+ explicit Operand(Register reg) : fixup_(nullptr) { SetModRM(3, reg); }
// Get the operand encoding byte at the given index.
uint8_t encoding_at(int index_in) const {
@@ -136,6 +148,11 @@
Init(base_in, disp);
}
+ Address(Register base_in, int32_t disp, AssemblerFixup *fixup) {
+ Init(base_in, disp);
+ SetFixup(fixup);
+ }
+
Address(Register base_in, Offset disp) {
Init(base_in, disp.Int32Value());
}
@@ -226,6 +243,50 @@
DISALLOW_COPY_AND_ASSIGN(NearLabel);
};
+/**
+ * Class to handle constant area values.
+ */
+class ConstantArea {
+ public:
+ ConstantArea() {}
+
+ // Add a double to the constant area, returning the offset into
+ // the constant area where the literal resides.
+ int AddDouble(double v);
+
+ // Add a float to the constant area, returning the offset into
+ // the constant area where the literal resides.
+ int AddFloat(float v);
+
+ // Add an int32_t to the constant area, returning the offset into
+ // the constant area where the literal resides.
+ int AddInt32(int32_t v);
+
+ // Add an int64_t to the constant area, returning the offset into
+ // the constant area where the literal resides.
+ int AddInt64(int64_t v);
+
+ bool IsEmpty() const {
+ return buffer_.size() == 0;
+ }
+
+ const std::vector<int32_t>& GetBuffer() const {
+ return buffer_;
+ }
+
+ void AddFixup(AssemblerFixup* fixup) {
+ fixups_.push_back(fixup);
+ }
+
+ const std::vector<AssemblerFixup*>& GetFixups() const {
+ return fixups_;
+ }
+
+ private:
+ static constexpr size_t kEntrySize = sizeof(int32_t);
+ std::vector<int32_t> buffer_;
+ std::vector<AssemblerFixup*> fixups_;
+};
class X86Assembler FINAL : public Assembler {
public:
@@ -667,6 +728,29 @@
}
}
+ // Add a double to the constant area, returning the offset into
+ // the constant area where the literal resides.
+ int AddDouble(double v) { return constant_area_.AddDouble(v); }
+
+ // Add a float to the constant area, returning the offset into
+ // the constant area where the literal resides.
+ int AddFloat(float v) { return constant_area_.AddFloat(v); }
+
+ // Add an int32_t to the constant area, returning the offset into
+ // the constant area where the literal resides.
+ int AddInt32(int32_t v) { return constant_area_.AddInt32(v); }
+
+ // Add an int64_t to the constant area, returning the offset into
+ // the constant area where the literal resides.
+ int AddInt64(int64_t v) { return constant_area_.AddInt64(v); }
+
+ // Add the contents of the constant area to the assembler buffer.
+ void AddConstantArea();
+
+ // Is the constant area empty? Return true if there are no literals in the constant area.
+ bool IsConstantAreaEmpty() const { return constant_area_.IsEmpty(); }
+ void AddConstantAreaFixup(AssemblerFixup* fixup) { constant_area_.AddFixup(fixup); }
+
private:
inline void EmitUint8(uint8_t value);
inline void EmitInt32(int32_t value);
@@ -685,6 +769,8 @@
void EmitGenericShift(int rm, const Operand& operand, const Immediate& imm);
void EmitGenericShift(int rm, const Operand& operand, Register shifter);
+ ConstantArea constant_area_;
+
DISALLOW_COPY_AND_ASSIGN(X86Assembler);
};
diff --git a/runtime/java_vm_ext.cc b/runtime/java_vm_ext.cc
index 92eef39..63e8887 100644
--- a/runtime/java_vm_ext.cc
+++ b/runtime/java_vm_ext.cc
@@ -580,9 +580,12 @@
}
inline bool JavaVMExt::MayAccessWeakGlobalsUnlocked(Thread* self) const {
- return kUseReadBarrier
- ? self->GetWeakRefAccessEnabled()
- : allow_accessing_weak_globals_.LoadSequentiallyConsistent();
+ if (kUseReadBarrier) {
+ // self can be null during a runtime shutdown. ~Runtime()->~ClassLinker()->DecodeWeakGlobal().
+ return self != nullptr ? self->GetWeakRefAccessEnabled() : true;
+ } else {
+ return allow_accessing_weak_globals_.LoadSequentiallyConsistent();
+ }
}
mirror::Object* JavaVMExt::DecodeWeakGlobal(Thread* self, IndirectRef ref) {