Recognize getClass() in RTP.
Also always keep around the resolved field
in related HInstructions to avoid resolving it again
and again.
Test: test-art-host, 631-checker-get-class
Change-Id: I3bc6be11f3eb175c635e746006f39865947e0669
diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc
index 439e3b6..1d3c5bf 100644
--- a/compiler/optimizing/instruction_simplifier.cc
+++ b/compiler/optimizing/instruction_simplifier.cc
@@ -1118,7 +1118,66 @@
VisitCondition(condition);
}
+// Recognize the following pattern:
+// obj.getClass() ==/!= Foo.class
+// And replace it with a constant value if the type of `obj` is statically known.
+static bool RecognizeAndSimplifyClassCheck(HCondition* condition) {
+ HInstruction* input_one = condition->InputAt(0);
+ HInstruction* input_two = condition->InputAt(1);
+ HLoadClass* load_class = input_one->IsLoadClass()
+ ? input_one->AsLoadClass()
+ : input_two->AsLoadClass();
+ if (load_class == nullptr) {
+ return false;
+ }
+
+ ReferenceTypeInfo class_rti = load_class->GetLoadedClassRTI();
+ if (!class_rti.IsValid()) {
+ // Unresolved class.
+ return false;
+ }
+
+ HInstanceFieldGet* field_get = (load_class == input_one)
+ ? input_two->AsInstanceFieldGet()
+ : input_one->AsInstanceFieldGet();
+ if (field_get == nullptr) {
+ return false;
+ }
+
+ HInstruction* receiver = field_get->InputAt(0);
+ ReferenceTypeInfo receiver_type = receiver->GetReferenceTypeInfo();
+ if (!receiver_type.IsExact()) {
+ return false;
+ }
+
+ {
+ ScopedObjectAccess soa(Thread::Current());
+ ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+ ArtField* field = class_linker->GetClassRoot(ClassLinker::kJavaLangObject)->GetInstanceField(0);
+ DCHECK_EQ(std::string(field->GetName()), "shadow$_klass_");
+ if (field_get->GetFieldInfo().GetField() != field) {
+ return false;
+ }
+
+ // We can replace the compare.
+ int value = 0;
+ if (receiver_type.IsEqual(class_rti)) {
+ value = condition->IsEqual() ? 1 : 0;
+ } else {
+ value = condition->IsNotEqual() ? 1 : 0;
+ }
+ condition->ReplaceWith(condition->GetBlock()->GetGraph()->GetIntConstant(value));
+ return true;
+ }
+}
+
void InstructionSimplifierVisitor::VisitCondition(HCondition* condition) {
+ if (condition->IsEqual() || condition->IsNotEqual()) {
+ if (RecognizeAndSimplifyClassCheck(condition)) {
+ return;
+ }
+ }
+
// Reverse condition if left is constant. Our code generators prefer constant
// on the right hand side.
if (condition->GetLeft()->IsConstant() && !condition->GetRight()->IsConstant()) {