diff options
author | 2015-06-29 10:56:34 +0100 | |
---|---|---|
committer | 2015-06-29 10:59:19 +0100 | |
commit | 30eb58c548bee08468f68eb140a74a51dd7d9b43 (patch) | |
tree | 28412484547b9bfb4a4773df103cef5f485c3a67 /compiler/optimizing | |
parent | 8d1a8c00b89775a251ac5e26a557f81ac1491a44 (diff) |
Do not update the type of something we already know.
This is both an optimization to avoid unneeded nodes,
and correctness to avoid replacing the second input
of `HInstanceOf` and `HCheckCast` to something that is
not `HLoadClass`.
bug:22116987
Change-Id: I4907197a9002883d7cae8265a9642512b6201396
Diffstat (limited to 'compiler/optimizing')
-rw-r--r-- | compiler/optimizing/graph_checker.cc | 26 | ||||
-rw-r--r-- | compiler/optimizing/graph_checker.h | 4 | ||||
-rw-r--r-- | compiler/optimizing/graph_visualizer.cc | 2 | ||||
-rw-r--r-- | compiler/optimizing/reference_type_propagation.cc | 9 |
4 files changed, 40 insertions, 1 deletions
diff --git a/compiler/optimizing/graph_checker.cc b/compiler/optimizing/graph_checker.cc index d7e6bd8161..9679d0ab70 100644 --- a/compiler/optimizing/graph_checker.cc +++ b/compiler/optimizing/graph_checker.cc @@ -257,6 +257,7 @@ void GraphChecker::VisitInvokeStaticOrDirect(HInvokeStaticOrDirect* invoke) { } void GraphChecker::VisitReturn(HReturn* ret) { + VisitInstruction(ret); if (!ret->GetBlock()->GetSingleSuccessor()->IsExitBlock()) { AddError(StringPrintf("%s:%d does not jump to the exit block.", ret->DebugName(), @@ -265,6 +266,7 @@ void GraphChecker::VisitReturn(HReturn* ret) { } void GraphChecker::VisitReturnVoid(HReturnVoid* ret) { + VisitInstruction(ret); if (!ret->GetBlock()->GetSingleSuccessor()->IsExitBlock()) { AddError(StringPrintf("%s:%d does not jump to the exit block.", ret->DebugName(), @@ -272,6 +274,30 @@ void GraphChecker::VisitReturnVoid(HReturnVoid* ret) { } } +void GraphChecker::VisitCheckCast(HCheckCast* check) { + VisitInstruction(check); + HInstruction* input = check->InputAt(1); + if (!input->IsLoadClass()) { + AddError(StringPrintf("%s:%d expects a HLoadClass as second input, not %s:%d.", + check->DebugName(), + check->GetId(), + input->DebugName(), + input->GetId())); + } +} + +void GraphChecker::VisitInstanceOf(HInstanceOf* instruction) { + VisitInstruction(instruction); + HInstruction* input = instruction->InputAt(1); + if (!input->IsLoadClass()) { + AddError(StringPrintf("%s:%d expects a HLoadClass as second input, not %s:%d.", + instruction->DebugName(), + instruction->GetId(), + input->DebugName(), + input->GetId())); + } +} + void SSAChecker::VisitBasicBlock(HBasicBlock* block) { super_type::VisitBasicBlock(block); diff --git a/compiler/optimizing/graph_checker.h b/compiler/optimizing/graph_checker.h index bafa69d422..7c72e23e2d 100644 --- a/compiler/optimizing/graph_checker.h +++ b/compiler/optimizing/graph_checker.h @@ -48,6 +48,10 @@ class GraphChecker : public HGraphDelegateVisitor { // Check that the HasBoundsChecks() flag is set for bounds checks. void VisitBoundsCheck(HBoundsCheck* check) OVERRIDE; + // Check that HCheckCast and HInstanceOf have HLoadClass as second input. + void VisitCheckCast(HCheckCast* check) OVERRIDE; + void VisitInstanceOf(HInstanceOf* check) OVERRIDE; + // Check that the Return and ReturnVoid jump to the exit block. void VisitReturn(HReturn* ret) OVERRIDE; void VisitReturnVoid(HReturnVoid* ret) OVERRIDE; diff --git a/compiler/optimizing/graph_visualizer.cc b/compiler/optimizing/graph_visualizer.cc index 30d61ef040..c41574c93c 100644 --- a/compiler/optimizing/graph_visualizer.cc +++ b/compiler/optimizing/graph_visualizer.cc @@ -462,7 +462,7 @@ class HGraphVisualizerPrinter : public HGraphVisitor { ReferenceTypeInfo info = instruction->AsLoadClass()->GetLoadedClassRTI(); ScopedObjectAccess soa(Thread::Current()); if (info.GetTypeHandle().GetReference() != nullptr) { - StartAttributeStream("klass") << info.GetTypeHandle().Get(); + StartAttributeStream("klass") << PrettyClass(info.GetTypeHandle().Get()); } else { StartAttributeStream("klass") << "unresolved"; } diff --git a/compiler/optimizing/reference_type_propagation.cc b/compiler/optimizing/reference_type_propagation.cc index 67840984b1..3d6606b8dc 100644 --- a/compiler/optimizing/reference_type_propagation.cc +++ b/compiler/optimizing/reference_type_propagation.cc @@ -151,6 +151,15 @@ void ReferenceTypePropagation::BoundTypeForIfInstanceOf(HBasicBlock* block) { HBoundType* bound_type = nullptr; HInstruction* obj = instanceOf->InputAt(0); + if (obj->GetReferenceTypeInfo().IsExact() && !obj->IsPhi()) { + // This method is being called while doing a fixed-point calculation + // over phis. Non-phis instruction whose type is already known do + // not need to be bound to another type. + // Not that this also prevents replacing `HLoadClass` with a `HBoundType`. + // `HCheckCast` and `HInstanceOf` expect a `HLoadClass` as a second + // input. + return; + } for (HUseIterator<HInstruction*> it(obj->GetUses()); !it.Done(); it.Advance()) { HInstruction* user = it.Current()->GetUser(); if (instanceOfTrueBlock->Dominates(user->GetBlock())) { |