summaryrefslogtreecommitdiff
path: root/compiler/dex/inline_method_analyser.cc
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/dex/inline_method_analyser.cc')
-rw-r--r--compiler/dex/inline_method_analyser.cc178
1 files changed, 77 insertions, 101 deletions
diff --git a/compiler/dex/inline_method_analyser.cc b/compiler/dex/inline_method_analyser.cc
index 381db3d21d..43e984b5cb 100644
--- a/compiler/dex/inline_method_analyser.cc
+++ b/compiler/dex/inline_method_analyser.cc
@@ -152,8 +152,7 @@ ArtMethod* GetTargetConstructor(ArtMethod* method, const Instruction* invoke_dir
if (kIsDebugBuild && target_method != nullptr) {
CHECK(!target_method->IsStatic());
CHECK(target_method->IsConstructor());
- CHECK(target_method->GetDeclaringClass() == method->GetDeclaringClass() ||
- target_method->GetDeclaringClass() == method->GetDeclaringClass()->GetSuperClass());
+ CHECK(method->GetDeclaringClass()->IsSubClass(target_method->GetDeclaringClass()));
}
return target_method;
}
@@ -256,11 +255,11 @@ bool DoAnalyseConstructor(const CodeItemDataAccessor* code_item,
/*inout*/ ConstructorIPutData (&iputs)[kMaxConstructorIPuts])
REQUIRES_SHARED(Locks::mutator_lock_) {
// On entry we should not have any IPUTs yet.
- DCHECK_EQ(0, std::count_if(
+ DCHECK(std::all_of(
iputs,
iputs + arraysize(iputs),
[](const ConstructorIPutData& iput_data) {
- return iput_data.field_index != DexFile::kDexNoIndex16;
+ return iput_data.field_index == DexFile::kDexNoIndex16;
}));
// Limit the maximum number of code units we're willing to match.
@@ -396,56 +395,36 @@ bool AnalyseConstructor(const CodeItemDataAccessor* code_item,
return true;
}
-static_assert(InlineMethodAnalyser::IsInstructionIGet(Instruction::IGET), "iget type");
-static_assert(InlineMethodAnalyser::IsInstructionIGet(Instruction::IGET_WIDE), "iget_wide type");
-static_assert(InlineMethodAnalyser::IsInstructionIGet(Instruction::IGET_OBJECT),
- "iget_object type");
-static_assert(InlineMethodAnalyser::IsInstructionIGet(Instruction::IGET_BOOLEAN),
- "iget_boolean type");
-static_assert(InlineMethodAnalyser::IsInstructionIGet(Instruction::IGET_BYTE), "iget_byte type");
-static_assert(InlineMethodAnalyser::IsInstructionIGet(Instruction::IGET_CHAR), "iget_char type");
-static_assert(InlineMethodAnalyser::IsInstructionIGet(Instruction::IGET_SHORT), "iget_short type");
-static_assert(InlineMethodAnalyser::IsInstructionIPut(Instruction::IPUT), "iput type");
-static_assert(InlineMethodAnalyser::IsInstructionIPut(Instruction::IPUT_WIDE), "iput_wide type");
-static_assert(InlineMethodAnalyser::IsInstructionIPut(Instruction::IPUT_OBJECT),
- "iput_object type");
-static_assert(InlineMethodAnalyser::IsInstructionIPut(Instruction::IPUT_BOOLEAN),
- "iput_boolean type");
-static_assert(InlineMethodAnalyser::IsInstructionIPut(Instruction::IPUT_BYTE), "iput_byte type");
-static_assert(InlineMethodAnalyser::IsInstructionIPut(Instruction::IPUT_CHAR), "iput_char type");
-static_assert(InlineMethodAnalyser::IsInstructionIPut(Instruction::IPUT_SHORT), "iput_short type");
-static_assert(InlineMethodAnalyser::IGetVariant(Instruction::IGET) ==
- InlineMethodAnalyser::IPutVariant(Instruction::IPUT), "iget/iput variant");
-static_assert(InlineMethodAnalyser::IGetVariant(Instruction::IGET_WIDE) ==
- InlineMethodAnalyser::IPutVariant(Instruction::IPUT_WIDE), "iget/iput_wide variant");
-static_assert(InlineMethodAnalyser::IGetVariant(Instruction::IGET_OBJECT) ==
- InlineMethodAnalyser::IPutVariant(Instruction::IPUT_OBJECT), "iget/iput_object variant");
-static_assert(InlineMethodAnalyser::IGetVariant(Instruction::IGET_BOOLEAN) ==
- InlineMethodAnalyser::IPutVariant(Instruction::IPUT_BOOLEAN), "iget/iput_boolean variant");
-static_assert(InlineMethodAnalyser::IGetVariant(Instruction::IGET_BYTE) ==
- InlineMethodAnalyser::IPutVariant(Instruction::IPUT_BYTE), "iget/iput_byte variant");
-static_assert(InlineMethodAnalyser::IGetVariant(Instruction::IGET_CHAR) ==
- InlineMethodAnalyser::IPutVariant(Instruction::IPUT_CHAR), "iget/iput_char variant");
-static_assert(InlineMethodAnalyser::IGetVariant(Instruction::IGET_SHORT) ==
- InlineMethodAnalyser::IPutVariant(Instruction::IPUT_SHORT), "iget/iput_short variant");
-
-bool InlineMethodAnalyser::AnalyseMethodCode(ArtMethod* method, InlineMethod* result) {
- CodeItemDataAccessor code_item(method->DexInstructionData());
- if (!code_item.HasCodeItem()) {
- // Native or abstract.
- return false;
- }
- return AnalyseMethodCode(&code_item,
- MethodReference(method->GetDexFile(), method->GetDexMethodIndex()),
- method->IsStatic(),
- method,
- result);
-}
-
-bool InlineMethodAnalyser::AnalyseMethodCode(const CodeItemDataAccessor* code_item,
- const MethodReference& method_ref,
- bool is_static,
- ArtMethod* method,
+static_assert(IsInstructionIGet(Instruction::IGET));
+static_assert(IsInstructionIGet(Instruction::IGET_WIDE));
+static_assert(IsInstructionIGet(Instruction::IGET_OBJECT));
+static_assert(IsInstructionIGet(Instruction::IGET_BOOLEAN));
+static_assert(IsInstructionIGet(Instruction::IGET_BYTE));
+static_assert(IsInstructionIGet(Instruction::IGET_CHAR));
+static_assert(IsInstructionIGet(Instruction::IGET_SHORT));
+static_assert(IsInstructionIPut(Instruction::IPUT));
+static_assert(IsInstructionIPut(Instruction::IPUT_WIDE));
+static_assert(IsInstructionIPut(Instruction::IPUT_OBJECT));
+static_assert(IsInstructionIPut(Instruction::IPUT_BOOLEAN));
+static_assert(IsInstructionIPut(Instruction::IPUT_BYTE));
+static_assert(IsInstructionIPut(Instruction::IPUT_CHAR));
+static_assert(IsInstructionIPut(Instruction::IPUT_SHORT));
+static_assert(IGetMemAccessType(Instruction::IGET) == IPutMemAccessType(Instruction::IPUT));
+static_assert(
+ IGetMemAccessType(Instruction::IGET_WIDE) == IPutMemAccessType(Instruction::IPUT_WIDE));
+static_assert(
+ IGetMemAccessType(Instruction::IGET_OBJECT) == IPutMemAccessType(Instruction::IPUT_OBJECT));
+static_assert(
+ IGetMemAccessType(Instruction::IGET_BOOLEAN) == IPutMemAccessType(Instruction::IPUT_BOOLEAN));
+static_assert(
+ IGetMemAccessType(Instruction::IGET_BYTE) == IPutMemAccessType(Instruction::IPUT_BYTE));
+static_assert(
+ IGetMemAccessType(Instruction::IGET_CHAR) == IPutMemAccessType(Instruction::IPUT_CHAR));
+static_assert(
+ IGetMemAccessType(Instruction::IGET_SHORT) == IPutMemAccessType(Instruction::IPUT_SHORT));
+
+bool InlineMethodAnalyser::AnalyseMethodCode(ArtMethod* method,
+ const CodeItemDataAccessor* code_item,
InlineMethod* result) {
// We currently support only plain return or 2-instruction methods.
@@ -492,7 +471,7 @@ bool InlineMethodAnalyser::AnalyseMethodCode(const CodeItemDataAccessor* code_it
// case Instruction::IGET_QUICK:
// case Instruction::IGET_WIDE_QUICK:
// case Instruction::IGET_OBJECT_QUICK:
- return AnalyseIGetMethod(code_item, method_ref, is_static, method, result);
+ return AnalyseIGetMethod(method, code_item, result);
case Instruction::IPUT:
case Instruction::IPUT_OBJECT:
case Instruction::IPUT_BOOLEAN:
@@ -504,15 +483,16 @@ bool InlineMethodAnalyser::AnalyseMethodCode(const CodeItemDataAccessor* code_it
// case Instruction::IPUT_QUICK:
// case Instruction::IPUT_WIDE_QUICK:
// case Instruction::IPUT_OBJECT_QUICK:
- return AnalyseIPutMethod(code_item, method_ref, is_static, method, result);
+ return AnalyseIPutMethod(method, code_item, result);
default:
return false;
}
}
-bool InlineMethodAnalyser::IsSyntheticAccessor(MethodReference ref) {
- const dex::MethodId& method_id = ref.dex_file->GetMethodId(ref.index);
- const char* method_name = ref.dex_file->GetMethodName(method_id);
+bool InlineMethodAnalyser::IsSyntheticAccessor(ArtMethod* method) {
+ const DexFile* dex_file = method->GetDexFile();
+ const dex::MethodId& method_id = dex_file->GetMethodId(method->GetDexMethodIndex());
+ const char* method_name = dex_file->GetMethodName(method_id);
// javac names synthetic accessors "access$nnn",
// jack names them "-getN", "-putN", "-wrapN".
return strncmp(method_name, "access$", strlen("access$")) == 0 ||
@@ -572,10 +552,8 @@ bool InlineMethodAnalyser::AnalyseConstMethod(const CodeItemDataAccessor* code_i
return true;
}
-bool InlineMethodAnalyser::AnalyseIGetMethod(const CodeItemDataAccessor* code_item,
- const MethodReference& method_ref,
- bool is_static,
- ArtMethod* method,
+bool InlineMethodAnalyser::AnalyseIGetMethod(ArtMethod* method,
+ const CodeItemDataAccessor* code_item,
InlineMethod* result) {
DexInstructionIterator instruction = code_item->begin();
Instruction::Code opcode = instruction->Opcode();
@@ -607,39 +585,37 @@ bool InlineMethodAnalyser::AnalyseIGetMethod(const CodeItemDataAccessor* code_it
return false; // Not returning the value retrieved by IGET?
}
- if (is_static || object_arg != 0u) {
- // TODO: Implement inlining of IGET on non-"this" registers (needs correct stack trace for NPE).
- // Allow synthetic accessors. We don't care about losing their stack frame in NPE.
- if (!IsSyntheticAccessor(method_ref)) {
- return false;
- }
- }
-
// InlineIGetIPutData::object_arg is only 4 bits wide.
static constexpr uint16_t kMaxObjectArg = 15u;
if (object_arg > kMaxObjectArg) {
return false;
}
- if (result != nullptr) {
- InlineIGetIPutData* data = &result->d.ifield_data;
- if (!ComputeSpecialAccessorInfo(method, field_idx, false, data)) {
+ bool is_static = method->IsStatic();
+ if (is_static || object_arg != 0u) {
+ // TODO: Implement inlining of IGET on non-"this" registers (needs correct stack trace for NPE).
+ // Allow synthetic accessors. We don't care about losing their stack frame in NPE.
+ if (!IsSyntheticAccessor(method)) {
return false;
}
- result->opcode = kInlineOpIGet;
- data->op_variant = IGetVariant(opcode);
- data->method_is_static = is_static ? 1u : 0u;
- data->object_arg = object_arg; // Allow IGET on any register, not just "this".
- data->src_arg = 0u;
- data->return_arg_plus1 = 0u;
}
+
+ DCHECK(result != nullptr);
+ InlineIGetIPutData* data = &result->d.ifield_data;
+ if (!ComputeSpecialAccessorInfo(method, field_idx, false, data)) {
+ return false;
+ }
+ result->opcode = kInlineOpIGet;
+ data->op_variant = enum_cast<uint16_t>(IGetMemAccessType(opcode));
+ data->method_is_static = is_static ? 1u : 0u;
+ data->object_arg = object_arg; // Allow IGET on any register, not just "this".
+ data->src_arg = 0u;
+ data->return_arg_plus1 = 0u;
return true;
}
-bool InlineMethodAnalyser::AnalyseIPutMethod(const CodeItemDataAccessor* code_item,
- const MethodReference& method_ref,
- bool is_static,
- ArtMethod* method,
+bool InlineMethodAnalyser::AnalyseIPutMethod(ArtMethod* method,
+ const CodeItemDataAccessor* code_item,
InlineMethod* result) {
DexInstructionIterator instruction = code_item->begin();
Instruction::Code opcode = instruction->Opcode();
@@ -673,14 +649,6 @@ bool InlineMethodAnalyser::AnalyseIPutMethod(const CodeItemDataAccessor* code_it
uint32_t object_arg = object_reg - arg_start;
uint32_t src_arg = src_reg - arg_start;
- if (is_static || object_arg != 0u) {
- // TODO: Implement inlining of IPUT on non-"this" registers (needs correct stack trace for NPE).
- // Allow synthetic accessors. We don't care about losing their stack frame in NPE.
- if (!IsSyntheticAccessor(method_ref)) {
- return false;
- }
- }
-
// InlineIGetIPutData::object_arg/src_arg/return_arg_plus1 are each only 4 bits wide.
static constexpr uint16_t kMaxObjectArg = 15u;
static constexpr uint16_t kMaxSrcArg = 15u;
@@ -689,18 +657,26 @@ bool InlineMethodAnalyser::AnalyseIPutMethod(const CodeItemDataAccessor* code_it
return false;
}
- if (result != nullptr) {
- InlineIGetIPutData* data = &result->d.ifield_data;
- if (!ComputeSpecialAccessorInfo(method, field_idx, true, data)) {
+ bool is_static = method->IsStatic();
+ if (is_static || object_arg != 0u) {
+ // TODO: Implement inlining of IPUT on non-"this" registers (needs correct stack trace for NPE).
+ // Allow synthetic accessors. We don't care about losing their stack frame in NPE.
+ if (!IsSyntheticAccessor(method)) {
return false;
}
- result->opcode = kInlineOpIPut;
- data->op_variant = IPutVariant(opcode);
- data->method_is_static = is_static ? 1u : 0u;
- data->object_arg = object_arg; // Allow IPUT on any register, not just "this".
- data->src_arg = src_arg;
- data->return_arg_plus1 = return_arg_plus1;
}
+
+ DCHECK(result != nullptr);
+ InlineIGetIPutData* data = &result->d.ifield_data;
+ if (!ComputeSpecialAccessorInfo(method, field_idx, true, data)) {
+ return false;
+ }
+ result->opcode = kInlineOpIPut;
+ data->op_variant = enum_cast<uint16_t>(IPutMemAccessType(opcode));
+ data->method_is_static = is_static ? 1u : 0u;
+ data->object_arg = object_arg; // Allow IPUT on any register, not just "this".
+ data->src_arg = src_arg;
+ data->return_arg_plus1 = return_arg_plus1;
return true;
}