diff options
author | Ian Rogers <irogers@google.com> | 2014-02-21 16:40:21 +0000 |
---|---|---|
committer | Ian Rogers <irogers@google.com> | 2014-02-21 09:00:50 -0800 |
commit | 9c86a0279aaf953377aa9e2277592e68bf814989 (patch) | |
tree | bb9c9ae4b6916d89d0f95c6cf4a654ad0b469e9c | |
parent | bf5b4b3a2d216e1dc7f693bf8efe223472136bb0 (diff) | |
download | art-9c86a0279aaf953377aa9e2277592e68bf814989.zip art-9c86a0279aaf953377aa9e2277592e68bf814989.tar.gz art-9c86a0279aaf953377aa9e2277592e68bf814989.tar.bz2 |
Revert "Annotate used fields."
This reverts commit 7f6cf56942c8469958b273ea968db253051c5b05.
Change-Id: Ic389a194c3404ecb5bb563a405bf4a0d6336ea0d
-rw-r--r-- | compiler/Android.mk | 1 | ||||
-rw-r--r-- | compiler/dex/bb_optimizations.h | 14 | ||||
-rw-r--r-- | compiler/dex/local_value_numbering.cc | 73 | ||||
-rw-r--r-- | compiler/dex/local_value_numbering_test.cc | 39 | ||||
-rw-r--r-- | compiler/dex/mir_analysis.cc | 110 | ||||
-rw-r--r-- | compiler/dex/mir_annotations.cc | 195 | ||||
-rw-r--r-- | compiler/dex/mir_annotations.h | 219 | ||||
-rw-r--r-- | compiler/dex/mir_graph.cc | 4 | ||||
-rw-r--r-- | compiler/dex/mir_graph.h | 22 | ||||
-rw-r--r-- | compiler/dex/pass_driver.cc | 1 | ||||
-rw-r--r-- | compiler/dex/quick/gen_common.cc | 124 | ||||
-rw-r--r-- | compiler/dex/quick/mir_to_lir.cc | 36 | ||||
-rw-r--r-- | compiler/dex/quick/mir_to_lir.h | 8 | ||||
-rw-r--r-- | compiler/driver/compiler_driver.cc | 18 | ||||
-rw-r--r-- | compiler/driver/compiler_driver.h | 3 |
15 files changed, 121 insertions, 746 deletions
diff --git a/compiler/Android.mk b/compiler/Android.mk index 12b8afb..77dc367 100644 --- a/compiler/Android.mk +++ b/compiler/Android.mk @@ -50,7 +50,6 @@ LIBART_COMPILER_SRC_FILES := \ dex/quick/x86/target_x86.cc \ dex/quick/x86/utility_x86.cc \ dex/dex_to_dex_compiler.cc \ - dex/mir_annotations.cc \ dex/mir_dataflow.cc \ dex/mir_optimization.cc \ dex/pass_driver.cc \ diff --git a/compiler/dex/bb_optimizations.h b/compiler/dex/bb_optimizations.h index f336231..1286a8e 100644 --- a/compiler/dex/bb_optimizations.h +++ b/compiler/dex/bb_optimizations.h @@ -23,20 +23,6 @@ namespace art { /** - * @class AnnotateUsedFields - * @brief Perform the annotation of fields for IGET/IPUT/SGET/SPUT insns. - */ -class AnnotateUsedFields : public Pass { - public: - AnnotateUsedFields() : Pass("AnnotateInstanceFields", kNoNodes) { - } - - void Start(CompilationUnit* cUnit) const { - cUnit->mir_graph->DoAnnotateUsedFields(); - } -}; - -/** * @class CodeLayout * @brief Perform the code layout pass. */ diff --git a/compiler/dex/local_value_numbering.cc b/compiler/dex/local_value_numbering.cc index 1384643..a3ea034 100644 --- a/compiler/dex/local_value_numbering.cc +++ b/compiler/dex/local_value_numbering.cc @@ -16,7 +16,6 @@ #include "local_value_numbering.h" -#include "mir_annotations.h" #include "mir_graph.h" namespace art { @@ -535,24 +534,16 @@ uint16_t LocalValueNumbering::GetValueNumber(MIR* mir) { case Instruction::IGET_BYTE: case Instruction::IGET_CHAR: case Instruction::IGET_SHORT: { - uint16_t type = opcode - Instruction::IGET; uint16_t base = GetOperandValue(mir->ssa_rep->uses[0]); HandleNullCheck(mir, base); - const IFieldAnnotation& annotation = cu_->mir_graph->GetIFieldAnnotation(mir); uint16_t memory_version; uint16_t field_id; - if (annotation.IsVolatile()) { - // Volatile fields always get a new memory version; field id is irrelevant. - // Unresolved fields are always marked as volatile and handled the same way here. - field_id = 0u; - memory_version = next_memory_version_; - ++next_memory_version_; - } else { - DCHECK(annotation.IsResolved()); - field_id = GetFieldId(annotation.DeclaringDexFile(), annotation.DeclaringFieldIndex()); - memory_version = std::max(unresolved_ifield_version_[type], - GetMemoryVersion(base, field_id, type)); - } + // TODO: all gets treated as volatile. + // Volatile fields always get a new memory version; field id is irrelevant. + // Unresolved fields are always marked as volatile and handled the same way here. + field_id = 0u; + memory_version = next_memory_version_; + ++next_memory_version_; if (opcode == Instruction::IGET_WIDE) { res = LookupValue(Instruction::IGET_WIDE, base, field_id, memory_version); SetOperandValueWide(mir->ssa_rep->defs[0], res); @@ -576,18 +567,10 @@ uint16_t LocalValueNumbering::GetValueNumber(MIR* mir) { int base_reg = (opcode == Instruction::IPUT_WIDE) ? 2 : 1; uint16_t base = GetOperandValue(mir->ssa_rep->uses[base_reg]); HandleNullCheck(mir, base); - const IFieldAnnotation& annotation = cu_->mir_graph->GetIFieldAnnotation(mir); - if (!annotation.IsResolved()) { - // Unresolved fields always alias with everything of the same type. - unresolved_ifield_version_[type] = next_memory_version_; - ++next_memory_version_; - } else if (annotation.IsVolatile()) { - // Nothing to do, resolved volatile fields always get a new memory version anyway and - // can't alias with resolved non-volatile fields. - } else { - AdvanceMemoryVersion(base, GetFieldId(annotation.DeclaringDexFile(), - annotation.DeclaringFieldIndex()), type); - } + // TODO: all puts treated as unresolved. + // Unresolved fields always alias with everything of the same type. + unresolved_ifield_version_[type] = next_memory_version_; + ++next_memory_version_; } break; @@ -598,22 +581,14 @@ uint16_t LocalValueNumbering::GetValueNumber(MIR* mir) { case Instruction::SGET_BYTE: case Instruction::SGET_CHAR: case Instruction::SGET_SHORT: { - uint16_t type = opcode - Instruction::SGET; - const SFieldAnnotation& annotation = cu_->mir_graph->GetSFieldAnnotation(mir); uint16_t memory_version; uint16_t field_id; - if (annotation.IsVolatile()) { - // Volatile fields always get a new memory version; field id is irrelevant. - // Unresolved fields are always marked as volatile and handled the same way here. - field_id = 0u; - memory_version = next_memory_version_; - ++next_memory_version_; - } else { - DCHECK(annotation.IsResolved()); - field_id = GetFieldId(annotation.DeclaringDexFile(), annotation.DeclaringFieldIndex()); - memory_version = std::max(unresolved_sfield_version_[type], - GetMemoryVersion(NO_VALUE, field_id, type)); - } + // TODO: all gets treated as volatile. + // Volatile fields always get a new memory version; field id is irrelevant. + // Unresolved fields are always marked as volatile and handled the same way here. + field_id = 0u; + memory_version = next_memory_version_; + ++next_memory_version_; if (opcode == Instruction::SGET_WIDE) { res = LookupValue(Instruction::SGET_WIDE, NO_VALUE, field_id, memory_version); SetOperandValueWide(mir->ssa_rep->defs[0], res); @@ -634,18 +609,10 @@ uint16_t LocalValueNumbering::GetValueNumber(MIR* mir) { case Instruction::SPUT_CHAR: case Instruction::SPUT_SHORT: { uint16_t type = opcode - Instruction::SPUT; - const SFieldAnnotation& annotation = cu_->mir_graph->GetSFieldAnnotation(mir); - if (!annotation.IsResolved()) { - // Unresolved fields always alias with everything of the same type. - unresolved_sfield_version_[type] = next_memory_version_; - ++next_memory_version_; - } else if (annotation.IsVolatile()) { - // Nothing to do, resolved volatile fields always get a new memory version anyway and - // can't alias with resolved non-volatile fields. - } else { - AdvanceMemoryVersion(NO_VALUE, GetFieldId(annotation.DeclaringDexFile(), - annotation.DeclaringFieldIndex()), type); - } + // TODO: all puts treated as unresolved. + // Unresolved fields always alias with everything of the same type. + unresolved_sfield_version_[type] = next_memory_version_; + ++next_memory_version_; } break; } diff --git a/compiler/dex/local_value_numbering_test.cc b/compiler/dex/local_value_numbering_test.cc index 230c012..6ab6c51 100644 --- a/compiler/dex/local_value_numbering_test.cc +++ b/compiler/dex/local_value_numbering_test.cc @@ -77,18 +77,6 @@ class LocalValueNumberingTest : public testing::Test { { opcode, 0u, 0u, 0, { }, 1, { reg } } // CONST_CLASS, CONST_STRING, NEW_ARRAY, ... void DoPrepareIFields(const IFieldDef* defs, size_t count) { - cu_.mir_graph->ifield_annotations_.Reset(); - cu_.mir_graph->ifield_annotations_.Resize(count); - for (size_t i = 0u; i != count; ++i) { - const IFieldDef* def = &defs[i]; - IFieldAnnotation annotation(def->field_idx); - if (def->declaring_dex_file != 0u) { - annotation.declaring_dex_file_ = reinterpret_cast<const DexFile*>(def->declaring_dex_file); - annotation.declaring_field_idx_ = def->declaring_field_idx; - annotation.is_volatile_ = def->is_volatile ? 1u : 0u; - } - cu_.mir_graph->ifield_annotations_.Insert(annotation); - } } template <size_t count> @@ -97,18 +85,6 @@ class LocalValueNumberingTest : public testing::Test { } void DoPrepareSFields(const SFieldDef* defs, size_t count) { - cu_.mir_graph->sfield_annotations_.Reset(); - cu_.mir_graph->sfield_annotations_.Resize(count); - for (size_t i = 0u; i != count; ++i) { - const SFieldDef* def = &defs[i]; - SFieldAnnotation annotation(def->field_idx); - if (def->declaring_dex_file != 0u) { - annotation.declaring_dex_file_ = reinterpret_cast<const DexFile*>(def->declaring_dex_file); - annotation.declaring_field_idx_ = def->declaring_field_idx; - annotation.is_volatile_ = def->is_volatile ? 1u : 0u; - } - cu_.mir_graph->sfield_annotations_.Insert(annotation); - } } template <size_t count> @@ -126,13 +102,6 @@ class LocalValueNumberingTest : public testing::Test { mir->dalvikInsn.opcode = def->opcode; mir->dalvikInsn.vB = static_cast<int32_t>(def->value); mir->dalvikInsn.vB_wide = def->value; - if (def->opcode >= Instruction::IGET && def->opcode <= Instruction::IPUT_SHORT) { - ASSERT_LT(def->field_annotation, cu_.mir_graph->ifield_annotations_.Size()); - mir->meta.ifield_annotation = def->field_annotation; - } else if (def->opcode >= Instruction::SGET && def->opcode <= Instruction::SPUT_SHORT) { - ASSERT_LT(def->field_annotation, cu_.mir_graph->sfield_annotations_.Size()); - mir->meta.sfield_annotation = def->field_annotation; - } mir->ssa_rep = &ssa_reps_[i]; mir->ssa_rep->num_uses = def->num_uses; mir->ssa_rep->uses = const_cast<int32_t*>(def->uses); // Not modified by LVN. @@ -177,6 +146,7 @@ class LocalValueNumberingTest : public testing::Test { LocalValueNumbering lvn_; }; +#if 0 // TODO: re-enable when LVN is handling memory igets. TEST_F(LocalValueNumberingTest, TestIGetIGetInvokeIGet) { static const IFieldDef ifields[] = { { 1u, 1u, 1u, false } @@ -199,6 +169,7 @@ TEST_F(LocalValueNumberingTest, TestIGetIGetInvokeIGet) { EXPECT_EQ(mirs_[2].optimization_flags, 0u); EXPECT_EQ(mirs_[3].optimization_flags, MIR_IGNORE_NULL_CHECK); } +#endif TEST_F(LocalValueNumberingTest, TestIGetIPutIGetIGetIGet) { static const IFieldDef ifields[] = { @@ -226,6 +197,7 @@ TEST_F(LocalValueNumberingTest, TestIGetIPutIGetIGetIGet) { EXPECT_EQ(mirs_[4].optimization_flags, 0u); } +#if 0 // TODO: re-enable when LVN is handling memory igets. TEST_F(LocalValueNumberingTest, TestUniquePreserve1) { static const IFieldDef ifields[] = { { 1u, 1u, 1u, false }, @@ -246,7 +218,9 @@ TEST_F(LocalValueNumberingTest, TestUniquePreserve1) { EXPECT_EQ(mirs_[2].optimization_flags, 0u); EXPECT_EQ(mirs_[3].optimization_flags, MIR_IGNORE_NULL_CHECK); } +#endif +#if 0 // TODO: re-enable when LVN is handling memory igets. TEST_F(LocalValueNumberingTest, TestUniquePreserve2) { static const IFieldDef ifields[] = { { 1u, 1u, 1u, false }, @@ -267,7 +241,9 @@ TEST_F(LocalValueNumberingTest, TestUniquePreserve2) { EXPECT_EQ(mirs_[2].optimization_flags, MIR_IGNORE_NULL_CHECK); EXPECT_EQ(mirs_[3].optimization_flags, MIR_IGNORE_NULL_CHECK); } +#endif +#if 0 // TODO: re-enable when LVN is handling memory igets. TEST_F(LocalValueNumberingTest, TestUniquePreserveAndEscape) { static const IFieldDef ifields[] = { { 1u, 1u, 1u, false }, @@ -291,6 +267,7 @@ TEST_F(LocalValueNumberingTest, TestUniquePreserveAndEscape) { EXPECT_EQ(mirs_[3].optimization_flags, MIR_IGNORE_NULL_CHECK); EXPECT_EQ(mirs_[5].optimization_flags, MIR_IGNORE_NULL_CHECK); } +#endif TEST_F(LocalValueNumberingTest, TestVolatile) { static const IFieldDef ifields[] = { diff --git a/compiler/dex/mir_analysis.cc b/compiler/dex/mir_analysis.cc index b739d5f..ab55333 100644 --- a/compiler/dex/mir_analysis.cc +++ b/compiler/dex/mir_analysis.cc @@ -14,14 +14,10 @@ * limitations under the License. */ -#include <algorithm> #include "compiler_internals.h" #include "dataflow_iterator-inl.h" -#include "dex_instruction.h" -#include "dex_instruction-inl.h" #include "dex/quick/dex_file_method_inliner.h" #include "dex/quick/dex_file_to_method_inliner_map.h" -#include "UniquePtr.h" namespace art { @@ -1086,110 +1082,4 @@ bool MIRGraph::SkipCompilation(Runtime::CompilerFilter compiler_filter) { return ComputeSkipCompilation(&stats, skip_compilation); } -void MIRGraph::DoAnnotateUsedFields() { - // Try to use stack-allocated array, resort to heap if we exceed the initial size. - static constexpr size_t kInitialSize = 32; - uint16_t stack_idxs[kInitialSize]; - UniquePtr<uint16_t[]> allocated_idxs; - uint16_t* field_idxs = stack_idxs; - size_t size = kInitialSize; - - // Find IGET/IPUT/SGET/SPUT insns, store IGET/IPUT fields at the beginning, SGET/SPUT at the end. - size_t ifield_pos = 0u; - size_t sfield_pos = size; - AllNodesIterator iter(this); - for (BasicBlock* bb = iter.Next(); bb != nullptr; bb = iter.Next()) { - if (bb->block_type != kDalvikByteCode) { - continue; - } - for (MIR* mir = bb->first_mir_insn; mir != nullptr; mir = mir->next) { - if (mir->dalvikInsn.opcode >= Instruction::IGET && - mir->dalvikInsn.opcode <= Instruction::SPUT_SHORT) { - bool need_alloc = false; - const Instruction* insn = Instruction::At(current_code_item_->insns_ + mir->offset); - uint16_t field_idx; - // Get field index and try to find it among existing indexes. If found, it's usually among - // the last few added, so we'll start the search from ifield_pos/sfield_pos. Though this - // is a linear search, it actually performs much better than map based approach. - if (mir->dalvikInsn.opcode <= Instruction::IPUT_SHORT) { - field_idx = insn->VRegC_22c(); - size_t i = ifield_pos; - while (i != 0u && field_idxs[i - 1] != field_idx) { - --i; - } - if (i != 0u) { - mir->meta.ifield_annotation = i - 1; - } else { - mir->meta.ifield_annotation = ifield_pos; - if (UNLIKELY(ifield_pos == sfield_pos)) { - need_alloc = true; - } else { - field_idxs[ifield_pos++] = field_idx; - } - } - } else { - field_idx = insn->VRegB_21c(); - size_t i = sfield_pos; - while (i != size && field_idxs[i] != field_idx) { - ++i; - } - if (i != size) { - mir->meta.sfield_annotation = size - i - 1u; - } else { - mir->meta.sfield_annotation = size - sfield_pos; - if (UNLIKELY(ifield_pos == sfield_pos)) { - need_alloc = true; - } else { - field_idxs[--sfield_pos] = field_idx; - } - } - } - if (UNLIKELY(need_alloc)) { - DCHECK(field_idxs == stack_idxs); - // All IGET/IPUT/SGET/SPUT instructions take 2 code units and there must also be a RETURN. - uint32_t max_refs = (current_code_item_->insns_size_in_code_units_ - 1u) / 2u; - allocated_idxs.reset(new uint16_t[max_refs]); - field_idxs = allocated_idxs.get(); - size_t sfield_count = size - sfield_pos; - sfield_pos = max_refs - sfield_count; - size = max_refs; - memcpy(field_idxs, stack_idxs, ifield_pos * sizeof(field_idxs[0])); - memcpy(field_idxs + sfield_pos, stack_idxs + ifield_pos, - sfield_count * sizeof(field_idxs[0])); - if (mir->dalvikInsn.opcode <= Instruction::IPUT_SHORT) { - field_idxs[ifield_pos++] = field_idx; - } else { - field_idxs[--sfield_pos] = field_idx; - } - } - DCHECK_LE(ifield_pos, sfield_pos); - } - } - } - - if (ifield_pos != 0u) { - // Annotate instance fields. - DCHECK_EQ(ifield_annotations_.Size(), 0u); - ifield_annotations_.Resize(ifield_pos); - for (size_t pos = 0u; pos != ifield_pos; ++pos) { - ifield_annotations_.Insert(IFieldAnnotation(field_idxs[pos])); - } - IFieldAnnotation::Resolve(GetCurrentDexCompilationUnit(), - ifield_annotations_.GetRawStorage(), ifield_pos); - } - - if (sfield_pos != size) { - // Annotate static fields. - DCHECK_EQ(sfield_annotations_.Size(), 0u); - sfield_annotations_.Resize(size - sfield_pos); - for (size_t pos = size; pos != sfield_pos;) { - --pos; - sfield_annotations_.Insert(SFieldAnnotation(field_idxs[pos])); - } - SFieldAnnotation::Resolve(GetCurrentDexCompilationUnit(), - sfield_annotations_.GetRawStorage(), - size - sfield_pos); - } -} - } // namespace art diff --git a/compiler/dex/mir_annotations.cc b/compiler/dex/mir_annotations.cc deleted file mode 100644 index eba64d7..0000000 --- a/compiler/dex/mir_annotations.cc +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright (C) 2014 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. - */ - -#include "mir_annotations.h" - -#include <string.h> - -#include "base/logging.h" -#include "class_linker.h" -#include "compiler_ir.h" -#include "driver/dex_compilation_unit.h" -#include "mirror/class.h" -#include "mirror/class-inl.h" -#include "mirror/art_field.h" -#include "mirror/art_field-inl.h" -#include "mirror/art_method.h" -#include "mirror/art_method-inl.h" -#include "scoped_thread_state_change.h" - -namespace art { - -void IFieldAnnotation::Resolve(const DexCompilationUnit* mUnit, - IFieldAnnotation* annotations, size_t count) { - if (kIsDebugBuild) { - DCHECK(annotations != nullptr); - DCHECK_NE(count, 0u); - for (auto it = annotations, end = annotations + count; it != end; ++it) { - IFieldAnnotation unresolved(it->field_idx_); - DCHECK_EQ(memcmp(&unresolved, &*it, sizeof(*it)), 0); - } - } - - const DexFile* dex_file = mUnit->GetDexFile(); - ClassLinker* class_linker = mUnit->GetClassLinker(); - uint32_t referrer_class_idx = dex_file->GetMethodId(mUnit->GetDexMethodIndex()).class_idx_; - - // We're going to resolve fields and check access in a tight loop. It's better to hold - // the lock and needed references once than re-acquiring them again and again. - ScopedObjectAccess soa(Thread::Current()); - SirtRef<mirror::DexCache> dex_cache(soa.Self(), class_linker->FindDexCache(*dex_file)); - SirtRef<mirror::ClassLoader> class_loader( - soa.Self(), soa.Decode<mirror::ClassLoader*>(mUnit->GetClassLoader())); - SirtRef<mirror::Class> referrer_class(soa.Self(), - class_linker->ResolveType(*dex_file, referrer_class_idx, dex_cache, class_loader)); - if (UNLIKELY(referrer_class.get() == nullptr)) { - // Clean up any exception left by type resolution - DCHECK(soa.Self()->IsExceptionPending()); - soa.Self()->ClearException(); - // We're compiling a method without class definition. We may still resolve fields - // and update annotations, so fall through and check again in the loop. - } - - for (auto it = annotations, end = annotations + count; it != end; ++it) { - uint32_t field_idx = it->field_idx_; - mirror::ArtField* resolved_field = - class_linker->ResolveField(*dex_file, field_idx, dex_cache, class_loader, false); - if (UNLIKELY(resolved_field == nullptr)) { - DCHECK(soa.Self()->IsExceptionPending()); - soa.Self()->ClearException(); - continue; - } - DCHECK(!soa.Self()->IsExceptionPending()); - if (UNLIKELY(resolved_field->IsStatic())) { - continue; - } - mirror::Class* fields_class = resolved_field->GetDeclaringClass(); - it->is_volatile_ = resolved_field->IsVolatile() ? 1u : 0u; - it->field_offset_ = resolved_field->GetOffset(); - it->declaring_dex_file_ = fields_class->GetDexCache()->GetDexFile(); - it->declaring_class_idx_ = fields_class->GetDexTypeIndex(); - it->declaring_field_idx_ = resolved_field->GetDexFieldIndex(); - if (UNLIKELY(referrer_class.get() == nullptr)) { - continue; - } - if (referrer_class->CanAccessResolvedField(fields_class, resolved_field, - dex_cache.get(), field_idx)) { - it->fast_get_ = 1u; - if (!resolved_field->IsFinal() || fields_class == referrer_class.get()) { - it->fast_put_ = 1u; - } - } - } -} - -void SFieldAnnotation::Resolve(const DexCompilationUnit* mUnit, - SFieldAnnotation* annotations, size_t count) { - if (kIsDebugBuild) { - DCHECK(annotations != nullptr); - DCHECK_NE(count, 0u); - for (auto it = annotations, end = annotations + count; it != end; ++it) { - SFieldAnnotation unresolved(it->field_idx_); - DCHECK_EQ(memcmp(&unresolved, &*it, sizeof(*it)), 0); - } - } - - const DexFile* dex_file = mUnit->GetDexFile(); - ClassLinker* class_linker = mUnit->GetClassLinker(); - uint32_t referrer_class_idx = dex_file->GetMethodId(mUnit->GetDexMethodIndex()).class_idx_; - - // We're going to resolve fields and check access in a tight loop. It's better to hold - // the lock and needed references once than re-acquiring them again and again. - ScopedObjectAccess soa(Thread::Current()); - SirtRef<mirror::DexCache> dex_cache(soa.Self(), class_linker->FindDexCache(*dex_file)); - SirtRef<mirror::ClassLoader> class_loader( - soa.Self(), soa.Decode<mirror::ClassLoader*>(mUnit->GetClassLoader())); - SirtRef<mirror::Class> referrer_class(soa.Self(), - class_linker->ResolveType(*dex_file, referrer_class_idx, dex_cache, class_loader)); - if (UNLIKELY(referrer_class.get() == nullptr)) { - DCHECK(soa.Self()->IsExceptionPending()); - soa.Self()->ClearException(); - // We're compiling a method without class definition. We may still resolve fields - // and update annotations, so fall through and check again in the loop. - } - - for (auto it = annotations, end = annotations + count; it != end; ++it) { - uint32_t field_idx = it->field_idx_; - mirror::ArtField* resolved_field = - class_linker->ResolveField(*dex_file, field_idx, dex_cache, class_loader, true); - if (UNLIKELY(resolved_field == nullptr)) { - // Clean up the exception left by field resolution - DCHECK(soa.Self()->IsExceptionPending()); - soa.Self()->ClearException(); - continue; - } - DCHECK(!soa.Self()->IsExceptionPending()); - if (UNLIKELY(!resolved_field->IsStatic())) { - continue; - } - mirror::Class* fields_class = resolved_field->GetDeclaringClass(); - it->is_volatile_ = resolved_field->IsVolatile() ? 1u : 0u; - it->field_offset_ = resolved_field->GetOffset(); - it->declaring_dex_file_ = fields_class->GetDexCache()->GetDexFile(); - it->declaring_class_idx_ = fields_class->GetDexTypeIndex(); - it->declaring_field_idx_ = resolved_field->GetDexFieldIndex(); - if (UNLIKELY(referrer_class.get() == nullptr)) { - continue; - } - if (fields_class == referrer_class.get()) { - it->fast_get_ = 1u; - it->fast_put_ = 1u; - it->is_referrers_class_ = 1u; // implies no worrying about class initialization - it->is_initialized_ = 1u; - it->storage_index_ = fields_class->GetDexTypeIndex(); - continue; - } - if (referrer_class->CanAccessResolvedField(fields_class, resolved_field, - dex_cache.get(), field_idx)) { - // We have the resolved field, we must make it into a index for the referrer - // in its static storage (which may fail if it doesn't have a slot for it) - // TODO: for images we can elide the static storage base null check - // if we know there's a non-null entry in the image - if (LIKELY(fields_class->GetDexCache() == dex_cache.get())) { - // common case where the dex cache of both the referrer and the field are the same, - // no need to search the dex file - it->storage_index_ = fields_class->GetDexTypeIndex(); - } else { - // Search dex file for localized ssb index, may fail if field's class is a parent - // of the class mentioned in the dex file and there is no dex cache entry. - const DexFile::StringId* string_id = - dex_file->FindStringId(FieldHelper(resolved_field).GetDeclaringClassDescriptor()); - if (string_id == nullptr) { - continue; - } - const DexFile::TypeId* type_id = - dex_file->FindTypeId(dex_file->GetIndexForStringId(*string_id)); - if (type_id == nullptr) { - continue; - } - // medium path, needs check of static storage base being initialized - it->storage_index_ = dex_file->GetIndexForTypeId(*type_id); - } - it->fast_get_ = 1u; - it->fast_put_ = resolved_field->IsFinal() ? 0u : 1u; - DCHECK_EQ(it->is_referrers_class_, 0u); - it->is_initialized_ = fields_class->IsInitialized() && - mUnit->GetCompilationUnit()->compiler_driver->CanAssumeTypeIsPresentInDexCache( - *dex_file, it->storage_index_); - } - } -} - -} // namespace art diff --git a/compiler/dex/mir_annotations.h b/compiler/dex/mir_annotations.h deleted file mode 100644 index cb7b589..0000000 --- a/compiler/dex/mir_annotations.h +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright (C) 2014 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_DEX_MIR_ANNOTATIONS_H_ -#define ART_COMPILER_DEX_MIR_ANNOTATIONS_H_ - -#include "base/macros.h" -#include "dex_file.h" -#include "offsets.h" - -namespace art { - -class DexCompilationUnit; - -/* - * Annotations are calculated from the perspective of the compilation unit that - * accesses the fields or methods. Since they are stored with that unit, they do not - * need to reference the dex file or method for which they have been calculated. - * However, we do store the dex file, declaring class index and field index of the - * resolved field to help distinguish between fields. - */ - -class IFieldAnnotation { - public: - // For each requested instance field compute whether we can fast path the access with IGET/IPUT. - // If yes (at least for IGET), computes the offset and volatility. - static void Resolve(const DexCompilationUnit* mUnit, IFieldAnnotation* annotations, size_t count) - LOCKS_EXCLUDED(Locks::mutator_lock_); - - // Construct an unresolved instance field annotation. - explicit IFieldAnnotation(uint16_t field_idx) - : field_idx_(field_idx), - fast_get_(0u), - fast_put_(0u), - is_volatile_(1u), - reserved_(0u), - field_offset_(0u), - declaring_dex_file_(nullptr), - declaring_class_idx_(0u), - declaring_field_idx_(0u) { - } - - uint16_t FieldIndex() const { - return field_idx_; - } - - bool FastGet() const { - return fast_get_ != 0u; - } - - bool FastPut() const { - return fast_put_ != 0u; - } - - bool IsVolatile() const { - return is_volatile_ != 0u; - } - - MemberOffset FieldOffset() const { - return field_offset_; - } - - bool IsResolved() const { - return declaring_dex_file_ != nullptr; - } - - const DexFile* DeclaringDexFile() const { - return declaring_dex_file_; - } - - uint16_t DeclaringClassIndex() const { - return declaring_class_idx_; - } - - uint16_t DeclaringFieldIndex() const { - return declaring_field_idx_; - } - - private: - // The field index in the compiling method's dex file. - uint16_t field_idx_; - // Can the compiling method fast-path IGET from this field? - uint16_t fast_get_ : 1; - // Can the compiling method fast-path IPUT from this field? - uint16_t fast_put_ : 1; - // Is the field volatile? Unknown if unresolved, so treated as volatile. - uint16_t is_volatile_ : 1; - // Reserved. - uint16_t reserved_ : 13; - // The member offset of the field, MemberOffset(static_cast<size_t>(-1)) if unresolved. - MemberOffset field_offset_; - // The dex file that defines the class containing the field and the field, nullptr if unresolved. - const DexFile* declaring_dex_file_; - // The type index of the class declaring the field, 0 if unresolved. - uint16_t declaring_class_idx_; - // The field index in the dex file that defines field, 0 if unresolved. - uint16_t declaring_field_idx_; - - friend class LocalValueNumberingTest; -}; - -class SFieldAnnotation { - public: - // For each requested static field compute whether we can fast path the access with SGET/SPUT. - // If yes (at least for SGET), computes the offset and volatility, storage index, and whether - // the access is from the same class or the class can be assumed initialized. - static void Resolve(const DexCompilationUnit* mUnit, SFieldAnnotation* annotations, size_t count) - LOCKS_EXCLUDED(Locks::mutator_lock_); - - // Construct an unresolved static field annotation. - explicit SFieldAnnotation(uint16_t field_idx) - : field_idx_(field_idx), - fast_get_(0u), - fast_put_(0u), - is_volatile_(1u), - is_referrers_class_(0u), - is_initialized_(0u), - reserved_(0u), - field_offset_(0u), - storage_index_(DexFile::kDexNoIndex), - declaring_dex_file_(nullptr), - declaring_class_idx_(0u), - declaring_field_idx_(0u) { - } - - uint16_t FieldIndex() const { - return field_idx_; - } - - bool FastGet() const { - return fast_get_ != 0u; - } - - bool FastPut() const { - return fast_put_ != 0u; - } - - bool IsVolatile() const { - return is_volatile_ != 0u; - } - - bool IsReferrersClass() const { - return is_referrers_class_ != 0u; - } - - bool IsInitialized() const { - return is_initialized_ != 0u; - } - - MemberOffset FieldOffset() const { - return field_offset_; - } - - uint32_t StorageIndex() const { - return storage_index_; - } - - bool IsResolved() const { - return declaring_dex_file_ != nullptr; - } - - const DexFile* DeclaringDexFile() const { - return declaring_dex_file_; - } - - uint16_t DeclaringClassIndex() const { - return declaring_class_idx_; - } - - uint16_t DeclaringFieldIndex() const { - return declaring_field_idx_; - } - - private: - // The field index in the compiling method's dex file. - uint16_t field_idx_; - // Can the compiling method fast-path IGET from this field? - uint16_t fast_get_ : 1; - // Can the compiling method fast-path IPUT from this field? - uint16_t fast_put_ : 1; - // Is the field volatile? Unknown if unresolved, so treated as volatile (true). - uint16_t is_volatile_ : 1; - // Is the field in the referrer's class? false if unresolved. - uint16_t is_referrers_class_ : 1; - // Can we assume that the field's class is already initialized? false if unresolved. - uint16_t is_initialized_ : 1; - // Reserved. - uint16_t reserved_ : 11; - // The member offset of the field, static_cast<size_t>(-1) if unresolved. - MemberOffset field_offset_; - // The type index of the declaring class in the compiling method's dex file, - // -1 if the field is unresolved or there's no appropriate TypeId in that dex file. - uint32_t storage_index_; - // The dex file that defines the class containing the field and the field, nullptr if unresolved. - const DexFile* declaring_dex_file_; - // The type index of the class declaring the field, 0 if unresolved. - uint16_t declaring_class_idx_; - // The field index in the dex file that defines field, 0 if unresolved. - uint16_t declaring_field_idx_; - - friend class LocalValueNumberingTest; -}; - -} // namespace art - -#endif // ART_COMPILER_DEX_MIR_ANNOTATIONS_H_ diff --git a/compiler/dex/mir_graph.cc b/compiler/dex/mir_graph.cc index 39f2d0e..e4550d1 100644 --- a/compiler/dex/mir_graph.cc +++ b/compiler/dex/mir_graph.cc @@ -86,9 +86,7 @@ MIRGraph::MIRGraph(CompilationUnit* cu, ArenaAllocator* arena) forward_branches_(0), compiler_temps_(arena, 6, kGrowableArrayMisc), num_non_special_compiler_temps_(0), - max_available_non_special_compiler_temps_(0), - ifield_annotations_(arena, 0u), - sfield_annotations_(arena, 0u) { + max_available_non_special_compiler_temps_(0) { try_block_addr_ = new (arena_) ArenaBitVector(arena_, 0, true /* expandable */); max_available_special_compiler_temps_ = std::abs(static_cast<int>(kVRegNonSpecialTempBaseReg)) - std::abs(static_cast<int>(kVRegTempBaseReg)); diff --git a/compiler/dex/mir_graph.h b/compiler/dex/mir_graph.h index df48f7e..d844aac 100644 --- a/compiler/dex/mir_graph.h +++ b/compiler/dex/mir_graph.h @@ -22,8 +22,6 @@ #include "compiler_ir.h" #include "arena_bit_vector.h" #include "utils/growable_array.h" -#include "invoke_type.h" -#include "mir_annotations.h" namespace art { @@ -260,12 +258,6 @@ struct MIR { MIR* throw_insn; // Fused cmp branch condition. ConditionCode ccode; - // IGET/IPUT annotation index, points to MIRGraph::ifield_annotations_. Due to limit on the - // number of code points (64K) and size of IGET/IPUT insn (2), this will never exceed 32K. - uint32_t ifield_annotation; - // SGET/SPUT annotation index, points to MIRGraph::sfield_annotations_. Due to limit on the - // number of code points (64K) and size of SGET/SPUT insn (2), this will never exceed 32K. - uint32_t sfield_annotation; } meta; }; @@ -474,18 +466,6 @@ class MIRGraph { */ void DumpCFG(const char* dir_prefix, bool all_blocks, const char* suffix = nullptr); - void DoAnnotateUsedFields(); - - const IFieldAnnotation& GetIFieldAnnotation(MIR* mir) { - DCHECK_LT(mir->meta.ifield_annotation, ifield_annotations_.Size()); - return ifield_annotations_.GetRawStorage()[mir->meta.ifield_annotation]; - } - - const SFieldAnnotation& GetSFieldAnnotation(MIR* mir) { - DCHECK_LT(mir->meta.sfield_annotation, sfield_annotations_.Size()); - return sfield_annotations_.GetRawStorage()[mir->meta.sfield_annotation]; - } - void InitRegLocations(); void RemapRegLocations(); @@ -937,8 +917,6 @@ class MIRGraph { size_t num_non_special_compiler_temps_; size_t max_available_non_special_compiler_temps_; size_t max_available_special_compiler_temps_; - GrowableArray<IFieldAnnotation> ifield_annotations_; - GrowableArray<SFieldAnnotation> sfield_annotations_; friend class LocalValueNumberingTest; }; diff --git a/compiler/dex/pass_driver.cc b/compiler/dex/pass_driver.cc index 4302fe2..4f8739a 100644 --- a/compiler/dex/pass_driver.cc +++ b/compiler/dex/pass_driver.cc @@ -91,7 +91,6 @@ void PassDriver::CreatePasses() { * - This is not yet an issue: no current pass would require it. */ static const Pass* const passes[] = { - GetPassInstance<AnnotateUsedFields>(), GetPassInstance<CodeLayout>(), GetPassInstance<SSATransformation>(), GetPassInstance<ConstantPropagation>(), diff --git a/compiler/dex/quick/gen_common.cc b/compiler/dex/quick/gen_common.cc index a0a83db..0533fbf 100644 --- a/compiler/dex/quick/gen_common.cc +++ b/compiler/dex/quick/gen_common.cc @@ -381,14 +381,20 @@ class StaticFieldSlowPath : public Mir2Lir::LIRSlowPath { const int r_base_; }; -void Mir2Lir::GenSput(MIR* mir, RegLocation rl_src, bool is_long_or_double, +void Mir2Lir::GenSput(uint32_t field_idx, RegLocation rl_src, bool is_long_or_double, bool is_object) { - const SFieldAnnotation& annotation = mir_graph_->GetSFieldAnnotation(mir); - cu_->compiler_driver->ProcessedStaticField(annotation.FastPut(), annotation.IsReferrersClass()); - if (annotation.FastPut() && !SLOW_FIELD_PATH) { - DCHECK_GE(annotation.FieldOffset().Int32Value(), 0); + int field_offset; + int storage_index; + bool is_volatile; + bool is_referrers_class; + bool is_initialized; + bool fast_path = cu_->compiler_driver->ComputeStaticFieldInfo( + field_idx, mir_graph_->GetCurrentDexCompilationUnit(), true, + &field_offset, &storage_index, &is_referrers_class, &is_volatile, &is_initialized); + if (fast_path && !SLOW_FIELD_PATH) { + DCHECK_GE(field_offset, 0); int r_base; - if (annotation.IsReferrersClass()) { + if (is_referrers_class) { // Fast path, static storage base is this method's class RegLocation rl_method = LoadCurrMethod(); r_base = AllocTemp(); @@ -401,7 +407,7 @@ void Mir2Lir::GenSput(MIR* mir, RegLocation rl_src, bool is_long_or_double, // Medium path, static storage base in a different class which requires checks that the other // class is initialized. // TODO: remove initialized check now that we are initializing classes in the compiler driver. - DCHECK_NE(annotation.StorageIndex(), DexFile::kDexNoIndex); + DCHECK_GE(storage_index, 0); // May do runtime call so everything to home locations. FlushAllRegs(); // Using fixed register to sync with possible call to runtime support. @@ -414,9 +420,9 @@ void Mir2Lir::GenSput(MIR* mir, RegLocation rl_src, bool is_long_or_double, mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value(), r_base); LoadWordDisp(r_base, mirror::Array::DataOffset(sizeof(mirror::Object*)).Int32Value() + - sizeof(int32_t*) * annotation.StorageIndex(), r_base); + sizeof(int32_t*) * storage_index, r_base); // r_base now points at static storage (Class*) or NULL if the type is not yet resolved. - if (!annotation.IsInitialized()) { + if (!is_initialized) { // Check if r_base is NULL or a not yet initialized class. // The slow path is invoked if the r_base is NULL or the class pointed @@ -431,7 +437,7 @@ void Mir2Lir::GenSput(MIR* mir, RegLocation rl_src, bool is_long_or_double, AddSlowPath(new (arena_) StaticFieldSlowPath(this, unresolved_branch, uninit_branch, cont, - annotation.StorageIndex(), r_base)); + storage_index, r_base)); FreeTemp(r_tmp); } @@ -443,16 +449,16 @@ void Mir2Lir::GenSput(MIR* mir, RegLocation rl_src, bool is_long_or_double, } else { rl_src = LoadValue(rl_src, kAnyReg); } - if (annotation.IsVolatile()) { + if (is_volatile) { GenMemBarrier(kStoreStore); } if (is_long_or_double) { - StoreBaseDispWide(r_base, annotation.FieldOffset().Int32Value(), rl_src.low_reg, + StoreBaseDispWide(r_base, field_offset, rl_src.low_reg, rl_src.high_reg); } else { - StoreWordDisp(r_base, annotation.FieldOffset().Int32Value(), rl_src.low_reg); + StoreWordDisp(r_base, field_offset, rl_src.low_reg); } - if (annotation.IsVolatile()) { + if (is_volatile) { GenMemBarrier(kStoreLoad); } if (is_object && !mir_graph_->IsConstantNullRef(rl_src)) { @@ -465,18 +471,24 @@ void Mir2Lir::GenSput(MIR* mir, RegLocation rl_src, bool is_long_or_double, is_long_or_double ? QUICK_ENTRYPOINT_OFFSET(pSet64Static) : (is_object ? QUICK_ENTRYPOINT_OFFSET(pSetObjStatic) : QUICK_ENTRYPOINT_OFFSET(pSet32Static)); - CallRuntimeHelperImmRegLocation(setter_offset, annotation.FieldIndex(), rl_src, true); + CallRuntimeHelperImmRegLocation(setter_offset, field_idx, rl_src, true); } } -void Mir2Lir::GenSget(MIR* mir, RegLocation rl_dest, +void Mir2Lir::GenSget(uint32_t field_idx, RegLocation rl_dest, bool is_long_or_double, bool is_object) { - const SFieldAnnotation& annotation = mir_graph_->GetSFieldAnnotation(mir); - cu_->compiler_driver->ProcessedStaticField(annotation.FastGet(), annotation.IsReferrersClass()); - if (annotation.FastGet() && !SLOW_FIELD_PATH) { - DCHECK_GE(annotation.FieldOffset().Int32Value(), 0); + int field_offset; + int storage_index; + bool is_volatile; + bool is_referrers_class; + bool is_initialized; + bool fast_path = cu_->compiler_driver->ComputeStaticFieldInfo( + field_idx, mir_graph_->GetCurrentDexCompilationUnit(), false, + &field_offset, &storage_index, &is_referrers_class, &is_volatile, &is_initialized); + if (fast_path && !SLOW_FIELD_PATH) { + DCHECK_GE(field_offset, 0); int r_base; - if (annotation.IsReferrersClass()) { + if (is_referrers_class) { // Fast path, static storage base is this method's class RegLocation rl_method = LoadCurrMethod(); r_base = AllocTemp(); @@ -485,7 +497,7 @@ void Mir2Lir::GenSget(MIR* mir, RegLocation rl_dest, } else { // Medium path, static storage base in a different class which requires checks that the other // class is initialized - DCHECK_NE(annotation.StorageIndex(), DexFile::kDexNoIndex); + DCHECK_GE(storage_index, 0); // May do runtime call so everything to home locations. FlushAllRegs(); // Using fixed register to sync with possible call to runtime support. @@ -498,9 +510,9 @@ void Mir2Lir::GenSget(MIR* mir, RegLocation rl_dest, mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value(), r_base); LoadWordDisp(r_base, mirror::Array::DataOffset(sizeof(mirror::Object*)).Int32Value() + - sizeof(int32_t*) * annotation.StorageIndex(), r_base); + sizeof(int32_t*) * storage_index, r_base); // r_base now points at static storage (Class*) or NULL if the type is not yet resolved. - if (!annotation.IsInitialized()) { + if (!is_initialized) { // Check if r_base is NULL or a not yet initialized class. // The slow path is invoked if the r_base is NULL or the class pointed @@ -515,7 +527,7 @@ void Mir2Lir::GenSget(MIR* mir, RegLocation rl_dest, AddSlowPath(new (arena_) StaticFieldSlowPath(this, unresolved_branch, uninit_branch, cont, - annotation.StorageIndex(), r_base)); + storage_index, r_base)); FreeTemp(r_tmp); } @@ -523,14 +535,14 @@ void Mir2Lir::GenSget(MIR* mir, RegLocation rl_dest, } // r_base now holds static storage base RegLocation rl_result = EvalLoc(rl_dest, kAnyReg, true); - if (annotation.IsVolatile()) { + if (is_volatile) { GenMemBarrier(kLoadLoad); } if (is_long_or_double) { - LoadBaseDispWide(r_base, annotation.FieldOffset().Int32Value(), rl_result.low_reg, + LoadBaseDispWide(r_base, field_offset, rl_result.low_reg, rl_result.high_reg, INVALID_SREG); } else { - LoadWordDisp(r_base, annotation.FieldOffset().Int32Value(), rl_result.low_reg); + LoadWordDisp(r_base, field_offset, rl_result.low_reg); } FreeTemp(r_base); if (is_long_or_double) { @@ -544,7 +556,7 @@ void Mir2Lir::GenSget(MIR* mir, RegLocation rl_dest, is_long_or_double ? QUICK_ENTRYPOINT_OFFSET(pGet64Static) :(is_object ? QUICK_ENTRYPOINT_OFFSET(pGetObjStatic) : QUICK_ENTRYPOINT_OFFSET(pGet32Static)); - CallRuntimeHelperImm(getterOffset, annotation.FieldIndex(), true); + CallRuntimeHelperImm(getterOffset, field_idx, true); if (is_long_or_double) { RegLocation rl_result = GetReturnWide(rl_dest.fp); StoreValueWide(rl_dest, rl_result); @@ -686,15 +698,18 @@ void Mir2Lir::HandleThrowLaunchPads() { } } -void Mir2Lir::GenIGet(MIR* mir, int opt_flags, OpSize size, +void Mir2Lir::GenIGet(uint32_t field_idx, int opt_flags, OpSize size, RegLocation rl_dest, RegLocation rl_obj, bool is_long_or_double, bool is_object) { - const IFieldAnnotation& annotation = mir_graph_->GetIFieldAnnotation(mir); - cu_->compiler_driver->ProcessedInstanceField(annotation.FastGet()); - if (annotation.FastGet() && !SLOW_FIELD_PATH) { + int field_offset; + bool is_volatile; + + bool fast_path = FastInstance(field_idx, false, &field_offset, &is_volatile); + + if (fast_path && !SLOW_FIELD_PATH) { RegLocation rl_result; RegisterClass reg_class = oat_reg_class_by_size(size); - DCHECK_GE(annotation.FieldOffset().Int32Value(), 0); + DCHECK_GE(field_offset, 0); rl_obj = LoadValue(rl_obj, kCoreReg); if (is_long_or_double) { DCHECK(rl_dest.wide); @@ -702,17 +717,17 @@ void Mir2Lir::GenIGet(MIR* mir, int opt_flags, OpSize size, if (cu_->instruction_set == kX86) { rl_result = EvalLoc(rl_dest, reg_class, true); GenNullCheck(rl_obj.s_reg_low, rl_obj.low_reg, opt_flags); - LoadBaseDispWide(rl_obj.low_reg, annotation.FieldOffset().Int32Value(), rl_result.low_reg, + LoadBaseDispWide(rl_obj.low_reg, field_offset, rl_result.low_reg, rl_result.high_reg, rl_obj.s_reg_low); - if (annotation.IsVolatile()) { + if (is_volatile) { GenMemBarrier(kLoadLoad); } } else { int reg_ptr = AllocTemp(); - OpRegRegImm(kOpAdd, reg_ptr, rl_obj.low_reg, annotation.FieldOffset().Int32Value()); + OpRegRegImm(kOpAdd, reg_ptr, rl_obj.low_reg, field_offset); rl_result = EvalLoc(rl_dest, reg_class, true); LoadBaseDispWide(reg_ptr, 0, rl_result.low_reg, rl_result.high_reg, INVALID_SREG); - if (annotation.IsVolatile()) { + if (is_volatile) { GenMemBarrier(kLoadLoad); } FreeTemp(reg_ptr); @@ -721,9 +736,9 @@ void Mir2Lir::GenIGet(MIR* mir, int opt_flags, OpSize size, } else { rl_result = EvalLoc(rl_dest, reg_class, true); GenNullCheck(rl_obj.s_reg_low, rl_obj.low_reg, opt_flags); - LoadBaseDisp(rl_obj.low_reg, annotation.FieldOffset().Int32Value(), rl_result.low_reg, + LoadBaseDisp(rl_obj.low_reg, field_offset, rl_result.low_reg, kWord, rl_obj.s_reg_low); - if (annotation.IsVolatile()) { + if (is_volatile) { GenMemBarrier(kLoadLoad); } StoreValue(rl_dest, rl_result); @@ -733,7 +748,7 @@ void Mir2Lir::GenIGet(MIR* mir, int opt_flags, OpSize size, is_long_or_double ? QUICK_ENTRYPOINT_OFFSET(pGet64Instance) : (is_object ? QUICK_ENTRYPOINT_OFFSET(pGetObjInstance) : QUICK_ENTRYPOINT_OFFSET(pGet32Instance)); - CallRuntimeHelperImmRegLocation(getterOffset, annotation.FieldIndex(), rl_obj, true); + CallRuntimeHelperImmRegLocation(getterOffset, field_idx, rl_obj, true); if (is_long_or_double) { RegLocation rl_result = GetReturnWide(rl_dest.fp); StoreValueWide(rl_dest, rl_result); @@ -744,37 +759,39 @@ void Mir2Lir::GenIGet(MIR* mir, int opt_flags, OpSize size, } } -void Mir2Lir::GenIPut(MIR* mir, int opt_flags, OpSize size, +void Mir2Lir::GenIPut(uint32_t field_idx, int opt_flags, OpSize size, RegLocation rl_src, RegLocation rl_obj, bool is_long_or_double, bool is_object) { - const IFieldAnnotation& annotation = mir_graph_->GetIFieldAnnotation(mir); - cu_->compiler_driver->ProcessedInstanceField(annotation.FastPut()); - if (annotation.FastPut() && !SLOW_FIELD_PATH) { + int field_offset; + bool is_volatile; + + bool fast_path = FastInstance(field_idx, true, &field_offset, &is_volatile); + if (fast_path && !SLOW_FIELD_PATH) { RegisterClass reg_class = oat_reg_class_by_size(size); - DCHECK_GE(annotation.FieldOffset().Int32Value(), 0); + DCHECK_GE(field_offset, 0); rl_obj = LoadValue(rl_obj, kCoreReg); if (is_long_or_double) { int reg_ptr; rl_src = LoadValueWide(rl_src, kAnyReg); GenNullCheck(rl_obj.s_reg_low, rl_obj.low_reg, opt_flags); reg_ptr = AllocTemp(); - OpRegRegImm(kOpAdd, reg_ptr, rl_obj.low_reg, annotation.FieldOffset().Int32Value()); - if (annotation.IsVolatile()) { + OpRegRegImm(kOpAdd, reg_ptr, rl_obj.low_reg, field_offset); + if (is_volatile) { GenMemBarrier(kStoreStore); } StoreBaseDispWide(reg_ptr, 0, rl_src.low_reg, rl_src.high_reg); - if (annotation.IsVolatile()) { + if (is_volatile) { GenMemBarrier(kLoadLoad); } FreeTemp(reg_ptr); } else { rl_src = LoadValue(rl_src, reg_class); GenNullCheck(rl_obj.s_reg_low, rl_obj.low_reg, opt_flags); - if (annotation.IsVolatile()) { + if (is_volatile) { GenMemBarrier(kStoreStore); } - StoreBaseDisp(rl_obj.low_reg, annotation.FieldOffset().Int32Value(), rl_src.low_reg, kWord); - if (annotation.IsVolatile()) { + StoreBaseDisp(rl_obj.low_reg, field_offset, rl_src.low_reg, kWord); + if (is_volatile) { GenMemBarrier(kLoadLoad); } if (is_object && !mir_graph_->IsConstantNullRef(rl_src)) { @@ -786,8 +803,7 @@ void Mir2Lir::GenIPut(MIR* mir, int opt_flags, OpSize size, is_long_or_double ? QUICK_ENTRYPOINT_OFFSET(pSet64Instance) : (is_object ? QUICK_ENTRYPOINT_OFFSET(pSetObjInstance) : QUICK_ENTRYPOINT_OFFSET(pSet32Instance)); - CallRuntimeHelperImmRegLocationRegLocation(setter_offset, annotation.FieldIndex(), - rl_obj, rl_src, true); + CallRuntimeHelperImmRegLocationRegLocation(setter_offset, field_idx, rl_obj, rl_src, true); } } diff --git a/compiler/dex/quick/mir_to_lir.cc b/compiler/dex/quick/mir_to_lir.cc index 00518bd..8c2ed36 100644 --- a/compiler/dex/quick/mir_to_lir.cc +++ b/compiler/dex/quick/mir_to_lir.cc @@ -596,72 +596,72 @@ void Mir2Lir::CompileDalvikInstruction(MIR* mir, BasicBlock* bb, LIR* label_list break; case Instruction::IGET_OBJECT: - GenIGet(mir, opt_flags, kWord, rl_dest, rl_src[0], false, true); + GenIGet(vC, opt_flags, kWord, rl_dest, rl_src[0], false, true); break; case Instruction::IGET_WIDE: - GenIGet(mir, opt_flags, kLong, rl_dest, rl_src[0], true, false); + GenIGet(vC, opt_flags, kLong, rl_dest, rl_src[0], true, false); break; case Instruction::IGET: - GenIGet(mir, opt_flags, kWord, rl_dest, rl_src[0], false, false); + GenIGet(vC, opt_flags, kWord, rl_dest, rl_src[0], false, false); break; case Instruction::IGET_CHAR: - GenIGet(mir, opt_flags, kUnsignedHalf, rl_dest, rl_src[0], false, false); + GenIGet(vC, opt_flags, kUnsignedHalf, rl_dest, rl_src[0], false, false); break; case Instruction::IGET_SHORT: - GenIGet(mir, opt_flags, kSignedHalf, rl_dest, rl_src[0], false, false); + GenIGet(vC, opt_flags, kSignedHalf, rl_dest, rl_src[0], false, false); break; case Instruction::IGET_BOOLEAN: case Instruction::IGET_BYTE: - GenIGet(mir, opt_flags, kUnsignedByte, rl_dest, rl_src[0], false, false); + GenIGet(vC, opt_flags, kUnsignedByte, rl_dest, rl_src[0], false, false); break; case Instruction::IPUT_WIDE: - GenIPut(mir, opt_flags, kLong, rl_src[0], rl_src[1], true, false); + GenIPut(vC, opt_flags, kLong, rl_src[0], rl_src[1], true, false); break; case Instruction::IPUT_OBJECT: - GenIPut(mir, opt_flags, kWord, rl_src[0], rl_src[1], false, true); + GenIPut(vC, opt_flags, kWord, rl_src[0], rl_src[1], false, true); break; case Instruction::IPUT: - GenIPut(mir, opt_flags, kWord, rl_src[0], rl_src[1], false, false); + GenIPut(vC, opt_flags, kWord, rl_src[0], rl_src[1], false, false); break; case Instruction::IPUT_BOOLEAN: case Instruction::IPUT_BYTE: - GenIPut(mir, opt_flags, kUnsignedByte, rl_src[0], rl_src[1], false, false); + GenIPut(vC, opt_flags, kUnsignedByte, rl_src[0], rl_src[1], false, false); break; case Instruction::IPUT_CHAR: - GenIPut(mir, opt_flags, kUnsignedHalf, rl_src[0], rl_src[1], false, false); + GenIPut(vC, opt_flags, kUnsignedHalf, rl_src[0], rl_src[1], false, false); break; case Instruction::IPUT_SHORT: - GenIPut(mir, opt_flags, kSignedHalf, rl_src[0], rl_src[1], false, false); + GenIPut(vC, opt_flags, kSignedHalf, rl_src[0], rl_src[1], false, false); break; case Instruction::SGET_OBJECT: - GenSget(mir, rl_dest, false, true); + GenSget(vB, rl_dest, false, true); break; case Instruction::SGET: case Instruction::SGET_BOOLEAN: case Instruction::SGET_BYTE: case Instruction::SGET_CHAR: case Instruction::SGET_SHORT: - GenSget(mir, rl_dest, false, false); + GenSget(vB, rl_dest, false, false); break; case Instruction::SGET_WIDE: - GenSget(mir, rl_dest, true, false); + GenSget(vB, rl_dest, true, false); break; case Instruction::SPUT_OBJECT: - GenSput(mir, rl_src[0], false, true); + GenSput(vB, rl_src[0], false, true); break; case Instruction::SPUT: @@ -669,11 +669,11 @@ void Mir2Lir::CompileDalvikInstruction(MIR* mir, BasicBlock* bb, LIR* label_list case Instruction::SPUT_BYTE: case Instruction::SPUT_CHAR: case Instruction::SPUT_SHORT: - GenSput(mir, rl_src[0], false, false); + GenSput(vB, rl_src[0], false, false); break; case Instruction::SPUT_WIDE: - GenSput(mir, rl_src[0], true, false); + GenSput(vB, rl_src[0], true, false); break; case Instruction::INVOKE_STATIC_RANGE: diff --git a/compiler/dex/quick/mir_to_lir.h b/compiler/dex/quick/mir_to_lir.h index 8eb67aa..6e97c53 100644 --- a/compiler/dex/quick/mir_to_lir.h +++ b/compiler/dex/quick/mir_to_lir.h @@ -558,13 +558,13 @@ class Mir2Lir : public Backend { void GenNewArray(uint32_t type_idx, RegLocation rl_dest, RegLocation rl_src); void GenFilledNewArray(CallInfo* info); - void GenSput(MIR* mir, RegLocation rl_src, + void GenSput(uint32_t field_idx, RegLocation rl_src, bool is_long_or_double, bool is_object); - void GenSget(MIR* mir, RegLocation rl_dest, + void GenSget(uint32_t field_idx, RegLocation rl_dest, bool is_long_or_double, bool is_object); - void GenIGet(MIR* mir, int opt_flags, OpSize size, + void GenIGet(uint32_t field_idx, int opt_flags, OpSize size, RegLocation rl_dest, RegLocation rl_obj, bool is_long_or_double, bool is_object); - void GenIPut(MIR* mir, int opt_flags, OpSize size, + void GenIPut(uint32_t field_idx, int opt_flags, OpSize size, RegLocation rl_src, RegLocation rl_obj, bool is_long_or_double, bool is_object); void GenArrayObjPut(int opt_flags, RegLocation rl_array, RegLocation rl_index, RegLocation rl_src); diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc index c7bf952..5adb792 100644 --- a/compiler/driver/compiler_driver.cc +++ b/compiler/driver/compiler_driver.cc @@ -881,24 +881,6 @@ bool CompilerDriver::CanEmbedTypeInCode(const DexFile& dex_file, uint32_t type_i } } -void CompilerDriver::ProcessedInstanceField(bool resolved) { - if (!resolved) { - stats_->UnresolvedInstanceField(); - } else { - stats_->ResolvedInstanceField(); - } -} - -void CompilerDriver::ProcessedStaticField(bool resolved, bool local) { - if (!resolved) { - stats_->UnresolvedStaticField(); - } else if (local) { - stats_->ResolvedLocalStaticField(); - } else { - stats_->ResolvedStaticField(); - } -} - static mirror::Class* ComputeCompilingMethodsClass(ScopedObjectAccess& soa, SirtRef<mirror::DexCache>& dex_cache, const DexCompilationUnit* mUnit) diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h index 5c5382b..092fe52 100644 --- a/compiler/driver/compiler_driver.h +++ b/compiler/driver/compiler_driver.h @@ -197,9 +197,6 @@ class CompilerDriver { bool* is_type_initialized, bool* use_direct_type_ptr, uintptr_t* direct_type_ptr); - void ProcessedInstanceField(bool resolved); - void ProcessedStaticField(bool resolved, bool local); - // Can we fast path instance field access in a verified accessor? // If yes, computes field's offset and volatility and whether the method is static or not. static bool ComputeSpecialAccessorInfo(uint32_t field_idx, bool is_put, |