diff options
| -rw-r--r-- | compiler/dex/verified_method.cc | 62 | ||||
| -rw-r--r-- | compiler/dex/verified_method.h | 7 | ||||
| -rw-r--r-- | runtime/mirror/art_method.h | 5 | ||||
| -rw-r--r-- | runtime/verifier/method_verifier.cc | 2 | ||||
| -rw-r--r-- | runtime/verifier/method_verifier.h | 9 |
5 files changed, 59 insertions, 26 deletions
diff --git a/compiler/dex/verified_method.cc b/compiler/dex/verified_method.cc index 17328c4a5b..d684bc9006 100644 --- a/compiler/dex/verified_method.cc +++ b/compiler/dex/verified_method.cc @@ -82,13 +82,13 @@ bool VerifiedMethod::GenerateGcMap(verifier::MethodVerifier* method_verifier) { size_t num_entries, ref_bitmap_bits, pc_bits; ComputeGcMapSizes(method_verifier, &num_entries, &ref_bitmap_bits, &pc_bits); // There's a single byte to encode the size of each bitmap. - if (ref_bitmap_bits >= (8 /* bits per byte */ * 8192 /* 13-bit size */ )) { + if (ref_bitmap_bits >= kBitsPerByte * 8192 /* 13-bit size */) { // TODO: either a better GC map format or per method failures method_verifier->Fail(verifier::VERIFY_ERROR_BAD_CLASS_HARD) << "Cannot encode GC map for method with " << ref_bitmap_bits << " registers"; return false; } - size_t ref_bitmap_bytes = (ref_bitmap_bits + 7) / 8; + size_t ref_bitmap_bytes = RoundUp(ref_bitmap_bits, kBitsPerByte) / kBitsPerByte; // There are 2 bytes to encode the number of entries. if (num_entries >= 65536) { // TODO: Either a better GC map format or per method failures. @@ -98,10 +98,10 @@ bool VerifiedMethod::GenerateGcMap(verifier::MethodVerifier* method_verifier) { } size_t pc_bytes; verifier::RegisterMapFormat format; - if (pc_bits <= 8) { + if (pc_bits <= kBitsPerByte) { format = verifier::kRegMapFormatCompact8; pc_bytes = 1; - } else if (pc_bits <= 16) { + } else if (pc_bits <= kBitsPerByte * 2) { format = verifier::kRegMapFormatCompact16; pc_bytes = 2; } else { @@ -152,10 +152,10 @@ void VerifiedMethod::VerifyGcMap(verifier::MethodVerifier* method_verifier, verifier::RegisterLine* line = method_verifier->GetRegLine(i); for (size_t j = 0; j < code_item->registers_size_; j++) { if (line->GetRegisterType(method_verifier, j).IsNonZeroReferenceTypes()) { - DCHECK_LT(j / 8, map.RegWidth()); - DCHECK_EQ((reg_bitmap[j / 8] >> (j % 8)) & 1, 1); - } else if ((j / 8) < map.RegWidth()) { - DCHECK_EQ((reg_bitmap[j / 8] >> (j % 8)) & 1, 0); + DCHECK_LT(j / kBitsPerByte, map.RegWidth()); + DCHECK_EQ((reg_bitmap[j / kBitsPerByte] >> (j % kBitsPerByte)) & 1, 1); + } else if ((j / kBitsPerByte) < map.RegWidth()) { + DCHECK_EQ((reg_bitmap[j / kBitsPerByte] >> (j % kBitsPerByte)) & 1, 0); } else { // If a register doesn't contain a reference then the bitmap may be shorter than the line. } @@ -190,6 +190,31 @@ void VerifiedMethod::ComputeGcMapSizes(verifier::MethodVerifier* method_verifier *log2_max_gc_pc = i; } +void VerifiedMethod::GenerateDeQuickenMap(verifier::MethodVerifier* method_verifier) { + 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_quick = inst->Opcode() == Instruction::INVOKE_VIRTUAL_QUICK; + const bool is_range_quick = inst->Opcode() == Instruction::INVOKE_VIRTUAL_RANGE_QUICK; + if (is_virtual_quick || is_range_quick) { + uint32_t dex_pc = inst->GetDexPc(insns); + verifier::RegisterLine* line = method_verifier->GetRegLine(dex_pc); + mirror::ArtMethod* method = method_verifier->GetQuickInvokedMethod(inst, line, + is_range_quick); + CHECK(method != nullptr); + // The verifier must know what the type of the object was or else we would have gotten a + // failure. Put the dex method index in the dequicken map since we need this to get number of + // arguments in the compiler. + dequicken_map_.Put(dex_pc, method->ToMethodReference()); + } + } +} + 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. @@ -203,10 +228,10 @@ void VerifiedMethod::GenerateDevirtMap(verifier::MethodVerifier* method_verifier const Instruction* end = Instruction::At(insns + code_item->insns_size_in_code_units_); for (; inst < end; inst = inst->Next()) { - bool is_virtual = (inst->Opcode() == Instruction::INVOKE_VIRTUAL) || - (inst->Opcode() == Instruction::INVOKE_VIRTUAL_RANGE); - bool is_interface = (inst->Opcode() == Instruction::INVOKE_INTERFACE) || - (inst->Opcode() == Instruction::INVOKE_INTERFACE_RANGE); + 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; @@ -214,8 +239,8 @@ void VerifiedMethod::GenerateDevirtMap(verifier::MethodVerifier* method_verifier // 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); - bool is_range = (inst->Opcode() == Instruction::INVOKE_VIRTUAL_RANGE) || - (inst->Opcode() == Instruction::INVOKE_INTERFACE_RANGE); + 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())); @@ -241,14 +266,14 @@ void VerifiedMethod::GenerateDevirtMap(verifier::MethodVerifier* method_verifier continue; } // Find the concrete method. - mirror::ArtMethod* concrete_method = NULL; + mirror::ArtMethod* concrete_method = nullptr; if (is_interface) { concrete_method = reg_type.GetClass()->FindVirtualMethodForInterface(abstract_method); } if (is_virtual) { concrete_method = reg_type.GetClass()->FindVirtualMethodForVirtual(abstract_method); } - if (concrete_method == NULL || concrete_method->IsAbstract()) { + if (concrete_method == nullptr || concrete_method->IsAbstract()) { // In cases where concrete_method is not found, or is abstract, continue to the next invoke. continue; } @@ -256,10 +281,7 @@ void VerifiedMethod::GenerateDevirtMap(verifier::MethodVerifier* method_verifier 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. - MethodReference concrete_ref( - concrete_method->GetDeclaringClass()->GetDexCache()->GetDexFile(), - concrete_method->GetDexMethodIndex()); - devirt_map_.Put(dex_pc, concrete_ref); + devirt_map_.Put(dex_pc, concrete_method->ToMethodReference()); } } } diff --git a/compiler/dex/verified_method.h b/compiler/dex/verified_method.h index 257e70ce93..fe9dfd1cb0 100644 --- a/compiler/dex/verified_method.h +++ b/compiler/dex/verified_method.h @@ -85,12 +85,19 @@ class VerifiedMethod { void GenerateDevirtMap(verifier::MethodVerifier* method_verifier) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + // Generate dequickening map into dequicken_map_. + void GenerateDeQuickenMap(verifier::MethodVerifier* method_verifier) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + // Generate safe case set into safe_cast_set_. void GenerateSafeCastSet(verifier::MethodVerifier* method_verifier) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); std::vector<uint8_t> dex_gc_map_; DevirtualizationMap devirt_map_; + // Dequicken map is required for having the compiler compiled quickened invokes. The quicken map + // enables us to get the dex method index so that we can get the required argument count. + DevirtualizationMap dequicken_map_; SafeCastSet safe_cast_set_; }; diff --git a/runtime/mirror/art_method.h b/runtime/mirror/art_method.h index 64663ed0cc..9b982b769b 100644 --- a/runtime/mirror/art_method.h +++ b/runtime/mirror/art_method.h @@ -20,6 +20,7 @@ #include "dex_file.h" #include "gc_root.h" #include "invoke_type.h" +#include "method_reference.h" #include "modifiers.h" #include "object.h" #include "object_callbacks.h" @@ -522,6 +523,10 @@ class MANAGED ArtMethod FINAL : public Object { uintptr_t ToNativeQuickPc(const uint32_t dex_pc, bool abort_on_failure = true) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + MethodReference ToMethodReference() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + return MethodReference(GetDexFile(), GetDexMethodIndex()); + } + // Find the catch block for the given exception type and dex_pc. When a catch block is found, // indicates whether the found catch block is responsible for clearing the exception or whether // a move-exception instruction is present. diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc index 59efebf20d..65c5c21743 100644 --- a/runtime/verifier/method_verifier.cc +++ b/runtime/verifier/method_verifier.cc @@ -3408,7 +3408,7 @@ mirror::ArtMethod* MethodVerifier::GetQuickInvokedMethod(const Instruction* inst return nullptr; } mirror::ArtMethod* res_method = dispatch_class->GetVTableEntry(vtable_index); - if (FailOrAbort(this, !Thread::Current()->IsExceptionPending(), + if (FailOrAbort(this, !self_->IsExceptionPending(), "Unexpected exception pending for quickened invoke at ", work_insn_idx_)) { return nullptr; diff --git a/runtime/verifier/method_verifier.h b/runtime/verifier/method_verifier.h index 0c4bf3c703..c3bd4af21a 100644 --- a/runtime/verifier/method_verifier.h +++ b/runtime/verifier/method_verifier.h @@ -238,6 +238,10 @@ class MethodVerifier { bool HasFailures() const; const RegType& ResolveCheckedClass(uint32_t class_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + mirror::ArtMethod* GetQuickInvokedMethod(const Instruction* inst, + RegisterLine* reg_line, + bool is_range) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); private: // Private constructor for dumping. @@ -586,11 +590,6 @@ class MethodVerifier { mirror::ArtMethod* res_method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - mirror::ArtMethod* GetQuickInvokedMethod(const Instruction* inst, - RegisterLine* reg_line, - bool is_range) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - mirror::ArtMethod* VerifyInvokeVirtualQuickArgs(const Instruction* inst, bool is_range) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); |