Revert "Compiler changes for bitstring based type checks."
Bug: 64692057
Bug: 71853552
Bug: 26687569
This reverts commit eb0ebed72432b3c6b8c7b38f8937d7ba736f4567.
Change-Id: I7daeaa077960ba41b2ed42bc47f17501621be4be
diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc
index 0205c6a..64a1ecc 100644
--- a/compiler/optimizing/instruction_builder.cc
+++ b/compiler/optimizing/instruction_builder.cc
@@ -1811,6 +1811,29 @@
}
}
+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);
@@ -1825,8 +1848,22 @@
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);
}
@@ -1871,83 +1908,25 @@
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());
}