diff options
author | Andreas Gampe <agampe@google.com> | 2018-03-26 21:14:46 +0000 |
---|---|---|
committer | Andreas Gampe <agampe@google.com> | 2018-03-26 21:14:46 +0000 |
commit | 3fbd3ad99fad077e5c760e7238bcd55b07d4c06e (patch) | |
tree | e8bc33fa60c38f7e1c85f8d4acf6a738df9b426a /compiler/optimizing/instruction_builder.cc | |
parent | 3f41323cc9da335e9aa4f3fbad90a86caa82ee4d (diff) |
Revert^3 "Compiler changes for bitstring based type checks."
This reverts commit 3f41323cc9da335e9aa4f3fbad90a86caa82ee4d.
Reason for revert: Fails sporadically.
Bug: 26687569
Bug: 64692057
Bug: 76420366
Change-Id: I84d1e9e46c58aeecf17591ff71fbac6a1e583909
Diffstat (limited to 'compiler/optimizing/instruction_builder.cc')
-rw-r--r-- | compiler/optimizing/instruction_builder.cc | 107 |
1 files changed, 43 insertions, 64 deletions
diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc index 9647dd5d41..c7aef3779d 100644 --- a/compiler/optimizing/instruction_builder.cc +++ b/compiler/optimizing/instruction_builder.cc @@ -1815,6 +1815,29 @@ void HInstructionBuilder::BuildFillWideArrayData(HInstruction* object, } } +static TypeCheckKind ComputeTypeCheckKind(Handle<mirror::Class> cls) + REQUIRES_SHARED(Locks::mutator_lock_) { + if (cls == nullptr) { + return TypeCheckKind::kUnresolvedCheck; + } else if (cls->IsInterface()) { + return TypeCheckKind::kInterfaceCheck; + } else if (cls->IsArrayClass()) { + if (cls->GetComponentType()->IsObjectClass()) { + return TypeCheckKind::kArrayObjectCheck; + } else if (cls->CannotBeAssignedFromOtherTypes()) { + return TypeCheckKind::kExactCheck; + } else { + return TypeCheckKind::kArrayCheck; + } + } else if (cls->IsFinal()) { + return TypeCheckKind::kExactCheck; + } else if (cls->IsAbstract()) { + return TypeCheckKind::kAbstractClassCheck; + } else { + return TypeCheckKind::kClassHierarchyCheck; + } +} + void HInstructionBuilder::BuildLoadString(dex::StringIndex string_index, uint32_t dex_pc) { HLoadString* load_string = new (allocator_) HLoadString(graph_->GetCurrentMethod(), string_index, *dex_file_, dex_pc); @@ -1829,8 +1852,22 @@ void HInstructionBuilder::BuildLoadString(dex::StringIndex string_index, uint32_ HLoadClass* HInstructionBuilder::BuildLoadClass(dex::TypeIndex type_index, uint32_t dex_pc) { ScopedObjectAccess soa(Thread::Current()); const DexFile& dex_file = *dex_compilation_unit_->GetDexFile(); - Handle<mirror::Class> klass = ResolveClass(soa, type_index); - bool needs_access_check = LoadClassNeedsAccessCheck(klass); + Handle<mirror::ClassLoader> class_loader = dex_compilation_unit_->GetClassLoader(); + Handle<mirror::Class> klass = handles_->NewHandle(compiler_driver_->ResolveClass( + soa, dex_compilation_unit_->GetDexCache(), class_loader, type_index, dex_compilation_unit_)); + + bool needs_access_check = true; + if (klass != nullptr) { + if (klass->IsPublic()) { + needs_access_check = false; + } else { + ObjPtr<mirror::Class> compiling_class = GetCompilingClass(); + if (compiling_class != nullptr && compiling_class->CanAccess(klass.Get())) { + needs_access_check = false; + } + } + } + return BuildLoadClass(type_index, dex_file, klass, dex_pc, needs_access_check); } @@ -1875,83 +1912,25 @@ HLoadClass* HInstructionBuilder::BuildLoadClass(dex::TypeIndex type_index, return load_class; } -Handle<mirror::Class> HInstructionBuilder::ResolveClass(ScopedObjectAccess& soa, - dex::TypeIndex type_index) { - Handle<mirror::ClassLoader> class_loader = dex_compilation_unit_->GetClassLoader(); - ObjPtr<mirror::Class> klass = compiler_driver_->ResolveClass( - soa, dex_compilation_unit_->GetDexCache(), class_loader, type_index, dex_compilation_unit_); - // TODO: Avoid creating excessive handles if the method references the same class repeatedly. - // (Use a map on the local_allocator_.) - return handles_->NewHandle(klass); -} - -bool HInstructionBuilder::LoadClassNeedsAccessCheck(Handle<mirror::Class> klass) { - if (klass == nullptr) { - return true; - } else if (klass->IsPublic()) { - return false; - } else { - ObjPtr<mirror::Class> compiling_class = GetCompilingClass(); - return compiling_class == nullptr || !compiling_class->CanAccess(klass.Get()); - } -} - void HInstructionBuilder::BuildTypeCheck(const Instruction& instruction, uint8_t destination, uint8_t reference, dex::TypeIndex type_index, uint32_t dex_pc) { HInstruction* object = LoadLocal(reference, DataType::Type::kReference); + HLoadClass* cls = BuildLoadClass(type_index, dex_pc); ScopedObjectAccess soa(Thread::Current()); - const DexFile& dex_file = *dex_compilation_unit_->GetDexFile(); - Handle<mirror::Class> klass = ResolveClass(soa, type_index); - bool needs_access_check = LoadClassNeedsAccessCheck(klass); - TypeCheckKind check_kind = HSharpening::ComputeTypeCheckKind( - klass.Get(), code_generator_, compiler_driver_, needs_access_check); - - HInstruction* class_or_null = nullptr; - HIntConstant* bitstring_path_to_root = nullptr; - HIntConstant* bitstring_mask = nullptr; - if (check_kind == TypeCheckKind::kBitstringCheck) { - // TODO: Allow using the bitstring check also if we need an access check. - DCHECK(!needs_access_check); - class_or_null = graph_->GetNullConstant(dex_pc); - MutexLock subtype_check_lock(Thread::Current(), *Locks::subtype_check_lock_); - uint32_t path_to_root = - SubtypeCheck<ObjPtr<mirror::Class>>::GetEncodedPathToRootForTarget(klass.Get()); - uint32_t mask = SubtypeCheck<ObjPtr<mirror::Class>>::GetEncodedPathToRootMask(klass.Get()); - bitstring_path_to_root = graph_->GetIntConstant(static_cast<int32_t>(path_to_root), dex_pc); - bitstring_mask = graph_->GetIntConstant(static_cast<int32_t>(mask), dex_pc); - } else { - class_or_null = BuildLoadClass(type_index, dex_file, klass, dex_pc, needs_access_check); - } - DCHECK(class_or_null != nullptr); - + TypeCheckKind check_kind = ComputeTypeCheckKind(cls->GetClass()); if (instruction.Opcode() == Instruction::INSTANCE_OF) { - AppendInstruction(new (allocator_) HInstanceOf(object, - class_or_null, - check_kind, - klass, - dex_pc, - allocator_, - bitstring_path_to_root, - bitstring_mask)); + AppendInstruction(new (allocator_) HInstanceOf(object, cls, check_kind, dex_pc)); UpdateLocal(destination, current_block_->GetLastInstruction()); } else { DCHECK_EQ(instruction.Opcode(), Instruction::CHECK_CAST); // We emit a CheckCast followed by a BoundType. CheckCast is a statement // which may throw. If it succeeds BoundType sets the new type of `object` // for all subsequent uses. - AppendInstruction( - new (allocator_) HCheckCast(object, - class_or_null, - check_kind, - klass, - dex_pc, - allocator_, - bitstring_path_to_root, - bitstring_mask)); + AppendInstruction(new (allocator_) HCheckCast(object, cls, check_kind, dex_pc)); AppendInstruction(new (allocator_) HBoundType(object, dex_pc)); UpdateLocal(reference, current_block_->GetLastInstruction()); } |