diff options
author | 2016-11-25 15:46:48 +0000 | |
---|---|---|
committer | 2017-01-03 14:00:16 -0800 | |
commit | c51c7ca7a779563d153c137c6bf01c3ea532a6c9 (patch) | |
tree | 3b562794d33e2f8f2adb9b4450e2c5d7043a1318 | |
parent | 00797355fa88299db5b4ac941bbda17cd97ab39e (diff) |
Clean up VerifiedMethod.
Remove unused methods, and devirt map.
Results on a large well-known app in speed compile with -j4:
Before:
dex2oat took [...] native alloc=149MB [...] swap=208MB (218103808B)
After:
dex2oat took [...] native alloc=84MB [...] swap=208MB (218103808B)
Bug: 34053922
Test: m clean-oat-host && m test-art-host
Change-Id: I0791c1e4ec7a98ae3c98321c582974db8e26617d
-rw-r--r-- | compiler/dex/verification_results.cc | 5 | ||||
-rw-r--r-- | compiler/dex/verified_method.cc | 104 | ||||
-rw-r--r-- | compiler/dex/verified_method.h | 37 |
3 files changed, 4 insertions, 142 deletions
diff --git a/compiler/dex/verification_results.cc b/compiler/dex/verification_results.cc index 9d39bf2c7a..00a7d44bac 100644 --- a/compiler/dex/verification_results.cc +++ b/compiler/dex/verification_results.cc @@ -46,9 +46,7 @@ VerificationResults::~VerificationResults() { void VerificationResults::ProcessVerifiedMethod(verifier::MethodVerifier* method_verifier) { DCHECK(method_verifier != nullptr); MethodReference ref = method_verifier->GetMethodReference(); - bool compile = IsCandidateForCompilation(ref, method_verifier->GetAccessFlags()); - std::unique_ptr<const VerifiedMethod> verified_method( - VerifiedMethod::Create(method_verifier, compile)); + std::unique_ptr<const VerifiedMethod> verified_method(VerifiedMethod::Create(method_verifier)); if (verified_method == nullptr) { // We'll punt this later. return; @@ -84,7 +82,6 @@ void VerificationResults::ProcessVerifiedMethod(verifier::MethodVerifier* method // TODO: Investigate why are we doing the work again for this method and try to avoid it. LOG(WARNING) << "Method processed more than once: " << ref.PrettyMethod(); if (!Runtime::Current()->UseJitCompilation()) { - DCHECK_EQ(existing->GetDevirtMap().size(), verified_method->GetDevirtMap().size()); DCHECK_EQ(existing->GetSafeCastSet().size(), verified_method->GetSafeCastSet().size()); } // Let the unique_ptr delete the new verified method since there was already an existing one diff --git a/compiler/dex/verified_method.cc b/compiler/dex/verified_method.cc index fdcafe8a15..188209bfb8 100644 --- a/compiler/dex/verified_method.cc +++ b/compiler/dex/verified_method.cc @@ -42,25 +42,12 @@ VerifiedMethod::VerifiedMethod(uint32_t encountered_error_types, bool has_runtim has_runtime_throw_(has_runtime_throw) { } -const VerifiedMethod* VerifiedMethod::Create(verifier::MethodVerifier* method_verifier, - bool compile) { +const VerifiedMethod* VerifiedMethod::Create(verifier::MethodVerifier* method_verifier) { + DCHECK(Runtime::Current()->IsAotCompiler()); std::unique_ptr<VerifiedMethod> verified_method( new VerifiedMethod(method_verifier->GetEncounteredFailureTypes(), method_verifier->HasInstructionThatWillThrow())); - if (compile) { - // TODO: move this out when DEX-to-DEX supports devirtualization. - if (method_verifier->HasVirtualOrInterfaceInvokes()) { - verified_method->GenerateDevirtMap(method_verifier); - } - - // Only need dequicken info for JIT so far. - if (Runtime::Current()->UseJitCompilation() && - !verified_method->GenerateDequickenMap(method_verifier)) { - return nullptr; - } - } - if (method_verifier->HasCheckCasts()) { verified_method->GenerateSafeCastSet(method_verifier); } @@ -68,17 +55,6 @@ const VerifiedMethod* VerifiedMethod::Create(verifier::MethodVerifier* method_ve return verified_method.release(); } -const MethodReference* VerifiedMethod::GetDevirtTarget(uint32_t dex_pc) const { - auto it = devirt_map_.find(dex_pc); - return (it != devirt_map_.end()) ? &it->second : nullptr; -} - -const DexFileReference* VerifiedMethod::GetDequickenIndex(uint32_t dex_pc) const { - DCHECK(Runtime::Current()->UseJitCompilation()); - auto it = dequicken_map_.find(dex_pc); - return (it != dequicken_map_.end()) ? &it->second : nullptr; -} - bool VerifiedMethod::IsSafeCast(uint32_t pc) const { return std::binary_search(safe_cast_set_.begin(), safe_cast_set_.end(), pc); } @@ -126,82 +102,6 @@ bool VerifiedMethod::GenerateDequickenMap(verifier::MethodVerifier* method_verif return true; } -void VerifiedMethod::GenerateDevirtMap(verifier::MethodVerifier* method_verifier) { - // It is risky to rely on reg_types for sharpening in cases of soft - // verification, we might end up sharpening to a wrong implementation. Just abort. - if (method_verifier->HasFailures()) { - return; - } - - const DexFile::CodeItem* code_item = method_verifier->CodeItem(); - const uint16_t* insns = code_item->insns_; - const Instruction* inst = Instruction::At(insns); - const Instruction* end = Instruction::At(insns + code_item->insns_size_in_code_units_); - - for (; inst < end; inst = inst->Next()) { - const bool is_virtual = inst->Opcode() == Instruction::INVOKE_VIRTUAL || - inst->Opcode() == Instruction::INVOKE_VIRTUAL_RANGE; - const bool is_interface = inst->Opcode() == Instruction::INVOKE_INTERFACE || - inst->Opcode() == Instruction::INVOKE_INTERFACE_RANGE; - - if (!is_interface && !is_virtual) { - continue; - } - // Get reg type for register holding the reference to the object that will be dispatched upon. - uint32_t dex_pc = inst->GetDexPc(insns); - verifier::RegisterLine* line = method_verifier->GetRegLine(dex_pc); - const bool is_range = inst->Opcode() == Instruction::INVOKE_VIRTUAL_RANGE || - inst->Opcode() == Instruction::INVOKE_INTERFACE_RANGE; - const verifier::RegType& - reg_type(line->GetRegisterType(method_verifier, - is_range ? inst->VRegC_3rc() : inst->VRegC_35c())); - - if (!reg_type.HasClass()) { - // We will compute devirtualization information only when we know the Class of the reg type. - continue; - } - mirror::Class* reg_class = reg_type.GetClass(); - if (reg_class->IsInterface()) { - // We can't devirtualize when the known type of the register is an interface. - continue; - } - if (reg_class->IsAbstract() && !reg_class->IsArrayClass()) { - // We can't devirtualize abstract classes except on arrays of abstract classes. - continue; - } - auto* cl = Runtime::Current()->GetClassLinker(); - PointerSize pointer_size = cl->GetImagePointerSize(); - ArtMethod* abstract_method = method_verifier->GetDexCache()->GetResolvedMethod( - is_range ? inst->VRegB_3rc() : inst->VRegB_35c(), pointer_size); - if (abstract_method == nullptr) { - // If the method is not found in the cache this means that it was never found - // by ResolveMethodAndCheckAccess() called when verifying invoke_*. - continue; - } - // Find the concrete method. - ArtMethod* concrete_method = nullptr; - if (is_interface) { - concrete_method = reg_type.GetClass()->FindVirtualMethodForInterface( - abstract_method, pointer_size); - } - if (is_virtual) { - concrete_method = reg_type.GetClass()->FindVirtualMethodForVirtual( - abstract_method, pointer_size); - } - if (concrete_method == nullptr || !concrete_method->IsInvokable()) { - // In cases where concrete_method is not found, or is not invokable, continue to the next - // invoke. - continue; - } - if (reg_type.IsPreciseReference() || concrete_method->IsFinal() || - concrete_method->GetDeclaringClass()->IsFinal()) { - // If we knew exactly the class being dispatched upon, or if the target method cannot be - // overridden record the target to be used in the compiler driver. - devirt_map_.Put(dex_pc, concrete_method->ToMethodReference()); - } - } -} - void VerifiedMethod::GenerateSafeCastSet(verifier::MethodVerifier* method_verifier) { /* * Walks over the method code and adds any cast instructions in which diff --git a/compiler/dex/verified_method.h b/compiler/dex/verified_method.h index ce53417185..0530a8cc18 100644 --- a/compiler/dex/verified_method.h +++ b/compiler/dex/verified_method.h @@ -39,31 +39,17 @@ class VerifiedMethod { // is better for performance (not just memory usage), especially for large sets. typedef std::vector<uint32_t> SafeCastSet; - // Devirtualization map type maps dex offset to concrete method reference. - typedef SafeMap<uint32_t, MethodReference> DevirtualizationMap; - // Devirtualization map type maps dex offset to field / method idx. typedef SafeMap<uint32_t, DexFileReference> DequickenMap; - static const VerifiedMethod* Create(verifier::MethodVerifier* method_verifier, bool compile) + static const VerifiedMethod* Create(verifier::MethodVerifier* method_verifier) REQUIRES_SHARED(Locks::mutator_lock_); ~VerifiedMethod() = default; - const DevirtualizationMap& GetDevirtMap() const { - return devirt_map_; - } - const SafeCastSet& GetSafeCastSet() const { return safe_cast_set_; } - // Returns the devirtualization target method, or null if none. - const MethodReference* GetDevirtTarget(uint32_t dex_pc) const; - - // Returns the dequicken field / method for a quick invoke / field get. Returns null if there is - // no entry for that dex pc. - const DexFileReference* GetDequickenIndex(uint32_t dex_pc) const; - // Returns true if the cast can statically be verified to be redundant // by using the check-cast elision peephole optimization in the verifier. bool IsSafeCast(uint32_t pc) const; @@ -82,26 +68,6 @@ class VerifiedMethod { } private: - /* - * Generate the GC map for a method that has just been verified (i.e. we're doing this as part of - * verification). For type-precise determination we have all the data we need, so we just need to - * encode it in some clever fashion. - * Stores the data in dex_gc_map_, returns true on success and false on failure. - */ - bool GenerateGcMap(verifier::MethodVerifier* method_verifier); - - // Verify that the GC map associated with method_ is well formed. - static void VerifyGcMap(verifier::MethodVerifier* method_verifier, - const std::vector<uint8_t>& data); - - // Compute sizes for GC map data. - static void ComputeGcMapSizes(verifier::MethodVerifier* method_verifier, - size_t* gc_points, size_t* ref_bitmap_bits, size_t* log2_max_gc_pc); - - // Generate devirtualizaion map into devirt_map_. - void GenerateDevirtMap(verifier::MethodVerifier* method_verifier) - REQUIRES_SHARED(Locks::mutator_lock_); - // Generate dequickening map into dequicken_map_. Returns false if there is an error. bool GenerateDequickenMap(verifier::MethodVerifier* method_verifier) REQUIRES_SHARED(Locks::mutator_lock_); @@ -110,7 +76,6 @@ class VerifiedMethod { void GenerateSafeCastSet(verifier::MethodVerifier* method_verifier) REQUIRES_SHARED(Locks::mutator_lock_); - DevirtualizationMap devirt_map_; // Dequicken map is required for compiling quickened byte codes. The quicken maps from // dex PC to dex method index or dex field index based on the instruction. DequickenMap dequicken_map_; |