From 3abd437507f8ba30a238a52c273c9944dcb9d5a1 Mon Sep 17 00:00:00 2001 From: Nicolas Geoffray Date: Thu, 2 Jul 2015 15:48:27 +0100 Subject: [PATCH] Do not create a HBoundType when the instruction is non-null. We don't need to refine the type after a null check, if the instruction is known non null or null. As a side effect, this avoids replacing HLoadClass instructions with HBoundType instructions. bug:22116987 Change-Id: I565ae95db5a64faec30e026674636e398e0bf445 --- compiler/optimizing/nodes.h | 1 + compiler/optimizing/reference_type_propagation.cc | 7 +++++++ test/519-bound-load-class/src/Main.java | 15 +++++++++++++++ 3 files changed, 23 insertions(+) diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h index 01ba1101f..f8149d16e 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -3437,6 +3437,7 @@ class HLoadClass : public HExpression<0> { uint32_t GetDexPc() const OVERRIDE { return dex_pc_; } uint16_t GetTypeIndex() const { return type_index_; } bool IsReferrersClass() const { return is_referrers_class_; } + bool CanBeNull() const OVERRIDE { return false; } bool NeedsEnvironment() const OVERRIDE { // Will call runtime and load the class if the class is not loaded yet. diff --git a/compiler/optimizing/reference_type_propagation.cc b/compiler/optimizing/reference_type_propagation.cc index 302366e71..40ec46c16 100644 --- a/compiler/optimizing/reference_type_propagation.cc +++ b/compiler/optimizing/reference_type_propagation.cc @@ -78,6 +78,12 @@ void ReferenceTypePropagation::BoundTypeForIfNotNull(HBasicBlock* block) { return; } + if (!obj->CanBeNull() || obj->IsNullConstant()) { + // Null check is dead code and will be removed by DCE. + return; + } + DCHECK(!obj->IsLoadClass()) << "We should not replace HLoadClass instructions"; + // We only need to bound the type if we have uses in the relevant block. // So start with null and create the HBoundType lazily, only if it's needed. HBoundType* bound_type = nullptr; @@ -139,6 +145,7 @@ void ReferenceTypePropagation::BoundTypeForIfInstanceOf(HBasicBlock* block) { // input. return; } + DCHECK(!obj->IsLoadClass()) << "We should not replace HLoadClass instructions"; for (HUseIterator it(obj->GetUses()); !it.Done(); it.Advance()) { HInstruction* user = it.Current()->GetUser(); if (instanceOfTrueBlock->Dominates(user->GetBlock())) { diff --git a/test/519-bound-load-class/src/Main.java b/test/519-bound-load-class/src/Main.java index 41bb951cf..cddeb093f 100644 --- a/test/519-bound-load-class/src/Main.java +++ b/test/519-bound-load-class/src/Main.java @@ -16,9 +16,24 @@ public class Main { public static void main(String[] args) { + testInstanceOf(); + try { + testNull(); + throw new Error("Expected ClassClastException"); + } catch (ClassCastException e) { /* ignore */ } + } + + public static void testInstanceOf() { Object o = Main.class; if (o instanceof Main) { System.out.println((Main)o); } } + + public static void testNull() { + Object o = Main.class; + if (o != null) { + System.out.println((Main)o); + } + } } -- 2.11.0