diff options
Diffstat (limited to 'compiler/optimizing/nodes.h')
| -rw-r--r-- | compiler/optimizing/nodes.h | 263 |
1 files changed, 233 insertions, 30 deletions
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h index ecf8c370f0..7d52d7d221 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -90,7 +90,7 @@ class HGraph : public ArenaObject<kArenaAllocMisc> { maximum_number_of_out_vregs_(0), number_of_vregs_(0), number_of_in_vregs_(0), - number_of_temporaries_(0), + temporaries_vreg_slots_(0), current_instruction_id_(0) {} ArenaAllocator* GetArena() const { return arena_; } @@ -129,12 +129,12 @@ class HGraph : public ArenaObject<kArenaAllocMisc> { maximum_number_of_out_vregs_ = std::max(new_value, maximum_number_of_out_vregs_); } - void UpdateNumberOfTemporaries(size_t count) { - number_of_temporaries_ = std::max(count, number_of_temporaries_); + void UpdateTemporariesVRegSlots(size_t slots) { + temporaries_vreg_slots_ = std::max(slots, temporaries_vreg_slots_); } - size_t GetNumberOfTemporaries() const { - return number_of_temporaries_; + size_t GetTemporariesVRegSlots() const { + return temporaries_vreg_slots_; } void SetNumberOfVRegs(uint16_t number_of_vregs) { @@ -192,8 +192,8 @@ class HGraph : public ArenaObject<kArenaAllocMisc> { // The number of virtual registers used by parameters of this method. uint16_t number_of_in_vregs_; - // The number of temporaries that will be needed for the baseline compiler. - size_t number_of_temporaries_; + // Number of vreg size slots that the temporaries use (used in baseline compiler). + size_t temporaries_vreg_slots_; // The current id to assign to a newly added instruction. See HInstruction.id_. int current_instruction_id_; @@ -475,10 +475,12 @@ class HBasicBlock : public ArenaObject<kArenaAllocMisc> { #define FOR_EACH_CONCRETE_INSTRUCTION(M) \ M(Add, BinaryOperation) \ + M(And, BinaryOperation) \ M(ArrayGet, Instruction) \ M(ArrayLength, Instruction) \ M(ArraySet, Instruction) \ M(BoundsCheck, Instruction) \ + M(CheckCast, Instruction) \ M(ClinitCheck, Instruction) \ M(Compare, BinaryOperation) \ M(Condition, BinaryOperation) \ @@ -494,7 +496,9 @@ class HBasicBlock : public ArenaObject<kArenaAllocMisc> { M(If, Instruction) \ M(InstanceFieldGet, Instruction) \ M(InstanceFieldSet, Instruction) \ + M(InstanceOf, Instruction) \ M(IntConstant, Constant) \ + M(InvokeInterface, Invoke) \ M(InvokeStatic, Invoke) \ M(InvokeVirtual, Invoke) \ M(LessThan, Condition) \ @@ -505,6 +509,7 @@ class HBasicBlock : public ArenaObject<kArenaAllocMisc> { M(LoadString, Instruction) \ M(Local, Instruction) \ M(LongConstant, Constant) \ + M(MonitorOperation, Instruction) \ M(Mul, BinaryOperation) \ M(Neg, UnaryOperation) \ M(NewArray, Instruction) \ @@ -512,9 +517,11 @@ class HBasicBlock : public ArenaObject<kArenaAllocMisc> { M(Not, UnaryOperation) \ M(NotEqual, Condition) \ M(NullCheck, Instruction) \ + M(Or, BinaryOperation) \ M(ParallelMove, Instruction) \ M(ParameterValue, Instruction) \ M(Phi, Instruction) \ + M(Rem, BinaryOperation) \ M(Return, Instruction) \ M(ReturnVoid, Instruction) \ M(StaticFieldGet, Instruction) \ @@ -524,8 +531,8 @@ class HBasicBlock : public ArenaObject<kArenaAllocMisc> { M(SuspendCheck, Instruction) \ M(Temporary, Instruction) \ M(Throw, Instruction) \ - M(TypeCheck, Instruction) \ M(TypeConversion, Instruction) \ + M(Xor, BinaryOperation) \ #define FOR_EACH_INSTRUCTION(M) \ FOR_EACH_CONCRETE_INSTRUCTION(M) \ @@ -1604,6 +1611,30 @@ class HInvokeVirtual : public HInvoke { DISALLOW_COPY_AND_ASSIGN(HInvokeVirtual); }; +class HInvokeInterface : public HInvoke { + public: + HInvokeInterface(ArenaAllocator* arena, + uint32_t number_of_arguments, + Primitive::Type return_type, + uint32_t dex_pc, + uint32_t dex_method_index, + uint32_t imt_index) + : HInvoke(arena, number_of_arguments, return_type, dex_pc), + dex_method_index_(dex_method_index), + imt_index_(imt_index) {} + + uint32_t GetImtIndex() const { return imt_index_; } + uint32_t GetDexMethodIndex() const { return dex_method_index_; } + + DECLARE_INSTRUCTION(InvokeInterface); + + private: + const uint32_t dex_method_index_; + const uint32_t imt_index_; + + DISALLOW_COPY_AND_ASSIGN(HInvokeInterface); +}; + class HNewInstance : public HExpression<0> { public: HNewInstance(uint32_t dex_pc, uint16_t type_index) @@ -1720,23 +1751,59 @@ class HMul : public HBinaryOperation { class HDiv : public HBinaryOperation { public: - HDiv(Primitive::Type result_type, HInstruction* left, HInstruction* right) - : HBinaryOperation(result_type, left, right) {} + HDiv(Primitive::Type result_type, HInstruction* left, HInstruction* right, uint32_t dex_pc) + : HBinaryOperation(result_type, left, right), dex_pc_(dex_pc) {} virtual int32_t Evaluate(int32_t x, int32_t y) const { // Our graph structure ensures we never have 0 for `y` during constant folding. DCHECK_NE(y, 0); - // Special case -1 to avoid getting a SIGFPE on x86. + // Special case -1 to avoid getting a SIGFPE on x86(_64). + return (y == -1) ? -x : x / y; + } + + virtual int64_t Evaluate(int64_t x, int64_t y) const { + DCHECK_NE(y, 0); + // Special case -1 to avoid getting a SIGFPE on x86(_64). return (y == -1) ? -x : x / y; } - virtual int64_t Evaluate(int64_t x, int64_t y) const { return x / y; } + + uint32_t GetDexPc() const { return dex_pc_; } DECLARE_INSTRUCTION(Div); private: + const uint32_t dex_pc_; + DISALLOW_COPY_AND_ASSIGN(HDiv); }; +class HRem : public HBinaryOperation { + public: + HRem(Primitive::Type result_type, HInstruction* left, HInstruction* right, uint32_t dex_pc) + : HBinaryOperation(result_type, left, right), dex_pc_(dex_pc) {} + + virtual int32_t Evaluate(int32_t x, int32_t y) const { + DCHECK_NE(y, 0); + // Special case -1 to avoid getting a SIGFPE on x86(_64). + return (y == -1) ? 0 : x % y; + } + + virtual int64_t Evaluate(int64_t x, int64_t y) const { + DCHECK_NE(y, 0); + // Special case -1 to avoid getting a SIGFPE on x86(_64). + return (y == -1) ? 0 : x % y; + } + + uint32_t GetDexPc() const { return dex_pc_; } + + DECLARE_INSTRUCTION(Rem); + + private: + const uint32_t dex_pc_; + + DISALLOW_COPY_AND_ASSIGN(HRem); +}; + class HDivZeroCheck : public HExpression<1> { public: HDivZeroCheck(HInstruction* value, uint32_t dex_pc) @@ -1764,6 +1831,54 @@ class HDivZeroCheck : public HExpression<1> { DISALLOW_COPY_AND_ASSIGN(HDivZeroCheck); }; +class HAnd : public HBinaryOperation { + public: + HAnd(Primitive::Type result_type, HInstruction* left, HInstruction* right) + : HBinaryOperation(result_type, left, right) {} + + bool IsCommutative() OVERRIDE { return true; } + + int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x & y; } + int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x & y; } + + DECLARE_INSTRUCTION(And); + + private: + DISALLOW_COPY_AND_ASSIGN(HAnd); +}; + +class HOr : public HBinaryOperation { + public: + HOr(Primitive::Type result_type, HInstruction* left, HInstruction* right) + : HBinaryOperation(result_type, left, right) {} + + bool IsCommutative() OVERRIDE { return true; } + + int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x | y; } + int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x | y; } + + DECLARE_INSTRUCTION(Or); + + private: + DISALLOW_COPY_AND_ASSIGN(HOr); +}; + +class HXor : public HBinaryOperation { + public: + HXor(Primitive::Type result_type, HInstruction* left, HInstruction* right) + : HBinaryOperation(result_type, left, right) {} + + bool IsCommutative() OVERRIDE { return true; } + + int32_t Evaluate(int32_t x, int32_t y) const OVERRIDE { return x ^ y; } + int64_t Evaluate(int64_t x, int64_t y) const OVERRIDE { return x ^ y; } + + DECLARE_INSTRUCTION(Xor); + + private: + DISALLOW_COPY_AND_ASSIGN(HXor); +}; + // The value of a parameter in this method. Its location depends on // the calling convention. class HParameterValue : public HExpression<0> { @@ -1952,6 +2067,8 @@ class HInstanceFieldSet : public HTemplateInstruction<2> { MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); } Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); } + HInstruction* GetValue() const { return InputAt(1); } + DECLARE_INSTRUCTION(InstanceFieldSet); private: @@ -1968,13 +2085,16 @@ class HArrayGet : public HExpression<2> { SetRawInputAt(1, index); } - virtual bool CanBeMoved() const { return true; } - virtual bool InstructionDataEquals(HInstruction* other) const { + bool CanBeMoved() const OVERRIDE { return true; } + bool InstructionDataEquals(HInstruction* other) const OVERRIDE { UNUSED(other); return true; } void SetType(Primitive::Type type) { type_ = type; } + HInstruction* GetArray() const { return InputAt(0); } + HInstruction* GetIndex() const { return InputAt(1); } + DECLARE_INSTRUCTION(ArrayGet); private: @@ -1990,20 +2110,29 @@ class HArraySet : public HTemplateInstruction<3> { uint32_t dex_pc) : HTemplateInstruction(SideEffects::ChangesSomething()), dex_pc_(dex_pc), - expected_component_type_(expected_component_type) { + expected_component_type_(expected_component_type), + needs_type_check_(value->GetType() == Primitive::kPrimNot) { SetRawInputAt(0, array); SetRawInputAt(1, index); SetRawInputAt(2, value); } - virtual bool NeedsEnvironment() const { + bool NeedsEnvironment() const { // We currently always call a runtime method to catch array store // exceptions. - return InputAt(2)->GetType() == Primitive::kPrimNot; + return needs_type_check_; + } + + void ClearNeedsTypeCheck() { + needs_type_check_ = false; } + bool NeedsTypeCheck() const { return needs_type_check_; } + uint32_t GetDexPc() const { return dex_pc_; } + HInstruction* GetArray() const { return InputAt(0); } + HInstruction* GetIndex() const { return InputAt(1); } HInstruction* GetValue() const { return InputAt(2); } Primitive::Type GetComponentType() const { @@ -2022,6 +2151,7 @@ class HArraySet : public HTemplateInstruction<3> { private: const uint32_t dex_pc_; const Primitive::Type expected_component_type_; + bool needs_type_check_; DISALLOW_COPY_AND_ASSIGN(HArraySet); }; @@ -2080,8 +2210,8 @@ class HBoundsCheck : public HExpression<2> { * Some DEX instructions are folded into multiple HInstructions that need * to stay live until the last HInstruction. This class * is used as a marker for the baseline compiler to ensure its preceding - * HInstruction stays live. `index` is the temporary number that is used - * for knowing the stack offset where to store the instruction. + * HInstruction stays live. `index` represents the stack location index of the + * instruction (the actual offset is computed as index * vreg_size). */ class HTemporary : public HTemplateInstruction<0> { public: @@ -2089,7 +2219,11 @@ class HTemporary : public HTemplateInstruction<0> { size_t GetIndex() const { return index_; } - Primitive::Type GetType() const OVERRIDE { return GetPrevious()->GetType(); } + Primitive::Type GetType() const OVERRIDE { + // The previous instruction is the one that will be stored in the temporary location. + DCHECK(GetPrevious() != nullptr); + return GetPrevious()->GetType(); + } DECLARE_INSTRUCTION(Temporary); @@ -2286,6 +2420,8 @@ class HStaticFieldSet : public HTemplateInstruction<2> { MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); } Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); } + HInstruction* GetValue() const { return InputAt(1); } + DECLARE_INSTRUCTION(StaticFieldSet); private: @@ -2326,12 +2462,12 @@ class HThrow : public HTemplateInstruction<1> { DISALLOW_COPY_AND_ASSIGN(HThrow); }; -class HTypeCheck : public HExpression<2> { +class HInstanceOf : public HExpression<2> { public: - explicit HTypeCheck(HInstruction* object, - HLoadClass* constant, - bool class_is_final, - uint32_t dex_pc) + HInstanceOf(HInstruction* object, + HLoadClass* constant, + bool class_is_final, + uint32_t dex_pc) : HExpression(Primitive::kPrimBoolean, SideEffects::None()), class_is_final_(class_is_final), dex_pc_(dex_pc) { @@ -2341,13 +2477,11 @@ class HTypeCheck : public HExpression<2> { bool CanBeMoved() const OVERRIDE { return true; } - bool InstructionDataEquals(HInstruction* other) const OVERRIDE { - UNUSED(other); + bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE { return true; } bool NeedsEnvironment() const OVERRIDE { - // TODO: Can we debug when doing a runtime instanceof check? return false; } @@ -2355,13 +2489,82 @@ class HTypeCheck : public HExpression<2> { bool IsClassFinal() const { return class_is_final_; } - DECLARE_INSTRUCTION(TypeCheck); + DECLARE_INSTRUCTION(InstanceOf); + + private: + const bool class_is_final_; + const uint32_t dex_pc_; + + DISALLOW_COPY_AND_ASSIGN(HInstanceOf); +}; + +class HCheckCast : public HTemplateInstruction<2> { + public: + HCheckCast(HInstruction* object, + HLoadClass* constant, + bool class_is_final, + uint32_t dex_pc) + : HTemplateInstruction(SideEffects::None()), + class_is_final_(class_is_final), + dex_pc_(dex_pc) { + SetRawInputAt(0, object); + SetRawInputAt(1, constant); + } + + bool CanBeMoved() const OVERRIDE { return true; } + + bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE { + return true; + } + + bool NeedsEnvironment() const OVERRIDE { + // Instruction may throw a CheckCastError. + return true; + } + + bool CanThrow() const OVERRIDE { return true; } + + uint32_t GetDexPc() const { return dex_pc_; } + + bool IsClassFinal() const { return class_is_final_; } + + DECLARE_INSTRUCTION(CheckCast); private: const bool class_is_final_; const uint32_t dex_pc_; - DISALLOW_COPY_AND_ASSIGN(HTypeCheck); + DISALLOW_COPY_AND_ASSIGN(HCheckCast); +}; + +class HMonitorOperation : public HTemplateInstruction<1> { + public: + enum OperationKind { + kEnter, + kExit, + }; + + HMonitorOperation(HInstruction* object, OperationKind kind, uint32_t dex_pc) + : HTemplateInstruction(SideEffects::None()), kind_(kind), dex_pc_(dex_pc) { + SetRawInputAt(0, object); + } + + // Instruction may throw a Java exception, so we need an environment. + bool NeedsEnvironment() const OVERRIDE { return true; } + bool CanThrow() const OVERRIDE { return true; } + + uint32_t GetDexPc() const { return dex_pc_; } + + bool IsEnter() const { return kind_ == kEnter; } + + DECLARE_INSTRUCTION(MonitorOperation); + + protected: + const OperationKind kind_; + const uint32_t dex_pc_; + + private: + DISALLOW_COPY_AND_ASSIGN(HMonitorOperation); }; |