diff options
Diffstat (limited to 'compiler/dex/inline_method_analyser.cc')
-rw-r--r-- | compiler/dex/inline_method_analyser.cc | 178 |
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; } |