From e295e6ec5beaea31be5d7d3c996cd8cfa2053129 Mon Sep 17 00:00:00 2001 From: Mingyao Yang Date: Sat, 7 Mar 2015 06:37:59 -0800 Subject: Deoptimization-based bce. A mechanism is introduced that a runtime method can be called from code compiled with optimizing compiler to deoptimize into interpreter. This can be used to establish invariants in the managed code If the invariant does not hold at runtime, we will deoptimize and continue execution in the interpreter. This allows to optimize the managed code as if the invariant was proven during compile time. However, the exception will be thrown according to the semantics demanded by the spec. The invariant and optimization included in this patch are based on the length of an array. Given a set of array accesses with constant indices {c1, ..., cn}, we can optimize away all bounds checks iff all 0 <= min(ci) and max(ci) < array-length. The first can be proven statically. The second can be established with a deoptimization-based invariant. This replaces n bounds checks with one invariant check (plus slow-path code). Change-Id: I8c6e34b56c85d25b91074832d13dba1db0a81569 --- compiler/optimizing/nodes.h | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) (limited to 'compiler/optimizing/nodes.h') diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h index 07ff8ba010..b10231e0c6 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -616,6 +616,7 @@ class HBasicBlock : public ArenaObject { M(ClinitCheck, Instruction) \ M(Compare, BinaryOperation) \ M(Condition, BinaryOperation) \ + M(Deoptimize, Instruction) \ M(Div, BinaryOperation) \ M(DivZeroCheck, Instruction) \ M(DoubleConstant, Constant) \ @@ -1478,12 +1479,31 @@ class HIf : public HTemplateInstruction<1> { DECLARE_INSTRUCTION(If); - virtual bool IsIfInstruction() const { return true; } - private: DISALLOW_COPY_AND_ASSIGN(HIf); }; +// Deoptimize to interpreter, upon checking a condition. +class HDeoptimize : public HTemplateInstruction<1> { + public: + HDeoptimize(HInstruction* cond, uint32_t dex_pc) + : HTemplateInstruction(SideEffects::None()), + dex_pc_(dex_pc) { + SetRawInputAt(0, cond); + } + + bool NeedsEnvironment() const OVERRIDE { return true; } + bool CanThrow() const OVERRIDE { return true; } + uint32_t GetDexPc() const { return dex_pc_; } + + DECLARE_INSTRUCTION(Deoptimize); + + private: + uint32_t dex_pc_; + + DISALLOW_COPY_AND_ASSIGN(HDeoptimize); +}; + class HUnaryOperation : public HExpression<1> { public: HUnaryOperation(Primitive::Type result_type, HInstruction* input) @@ -1601,8 +1621,8 @@ class HCondition : public HBinaryOperation { void ClearNeedsMaterialization() { needs_materialization_ = false; } // For code generation purposes, returns whether this instruction is just before - // `if_`, and disregard moves in between. - bool IsBeforeWhenDisregardMoves(HIf* if_) const; + // `instruction`, and disregard moves in between. + bool IsBeforeWhenDisregardMoves(HInstruction* instruction) const; DECLARE_INSTRUCTION(Condition); -- cgit v1.2.3-59-g8ed1b