Add support for static fields in optimizing compiler.
Change-Id: Id2f010589e2bd6faf42c05bb33abf6816ebe9fa9
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index f530708..86c36b8 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -472,6 +472,7 @@
M(ArrayLength, Instruction) \
M(ArraySet, Instruction) \
M(BoundsCheck, Instruction) \
+ M(ClinitCheck, Instruction) \
M(Compare, BinaryOperation) \
M(Condition, BinaryOperation) \
M(Div, BinaryOperation) \
@@ -488,6 +489,7 @@
M(IntConstant, Constant) \
M(InvokeStatic, Invoke) \
M(InvokeVirtual, Invoke) \
+ M(LoadClass, Instruction) \
M(LessThan, Condition) \
M(LessThanOrEqual, Condition) \
M(LoadLocal, Instruction) \
@@ -505,6 +507,8 @@
M(Phi, Instruction) \
M(Return, Instruction) \
M(ReturnVoid, Instruction) \
+ M(StaticFieldGet, Instruction) \
+ M(StaticFieldSet, Instruction) \
M(StoreLocal, Instruction) \
M(Sub, BinaryOperation) \
M(SuspendCheck, Instruction) \
@@ -2017,6 +2021,132 @@
DISALLOW_COPY_AND_ASSIGN(HSuspendCheck);
};
+// TODO: Make this class handle the case the load is null (dex cache
+// is null).
+/**
+ * Instruction to load a Class object.
+ */
+class HLoadClass : public HExpression<0> {
+ public:
+ HLoadClass(uint16_t type_index,
+ bool is_referrers_class,
+ bool is_initialized,
+ uint32_t dex_pc)
+ : HExpression(Primitive::kPrimNot, SideEffects::None()),
+ type_index_(type_index),
+ is_referrers_class_(is_referrers_class),
+ is_initialized_(is_initialized),
+ dex_pc_(dex_pc) {}
+
+ bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
+ return other->AsLoadClass()->type_index_ == type_index_;
+ }
+
+ size_t ComputeHashCode() const OVERRIDE { return type_index_; }
+
+ uint32_t GetDexPc() const { return dex_pc_; }
+ uint16_t GetTypeIndex() const { return type_index_; }
+
+ bool NeedsInitialization() const {
+ return !is_initialized_ && !is_referrers_class_;
+ }
+
+ bool IsReferrersClass() const { return is_referrers_class_; }
+
+ DECLARE_INSTRUCTION(LoadClass);
+
+ private:
+ const uint16_t type_index_;
+ const bool is_referrers_class_;
+ const bool is_initialized_;
+ const uint32_t dex_pc_;
+
+ DISALLOW_COPY_AND_ASSIGN(HLoadClass);
+};
+
+// TODO: Pass this check to HInvokeStatic nodes.
+/**
+ * Performs an initialization check on its Class object input.
+ */
+class HClinitCheck : public HExpression<1> {
+ public:
+ explicit HClinitCheck(HLoadClass* constant, uint32_t dex_pc)
+ : HExpression(Primitive::kPrimNot, SideEffects::All()),
+ dex_pc_(dex_pc) {
+ SetRawInputAt(0, constant);
+ }
+
+ bool NeedsEnvironment() const OVERRIDE {
+ // May call runtime to initialize the class.
+ return true;
+ }
+
+ uint32_t GetDexPc() const { return dex_pc_; }
+
+ HLoadClass* GetLoadClass() const { return InputAt(0)->AsLoadClass(); }
+
+ DECLARE_INSTRUCTION(ClinitCheck);
+
+ private:
+ const uint32_t dex_pc_;
+
+ DISALLOW_COPY_AND_ASSIGN(HClinitCheck);
+};
+
+class HStaticFieldGet : public HExpression<1> {
+ public:
+ HStaticFieldGet(HInstruction* cls,
+ Primitive::Type field_type,
+ MemberOffset field_offset)
+ : HExpression(field_type, SideEffects::DependsOnSomething()),
+ field_info_(field_offset, field_type) {
+ SetRawInputAt(0, cls);
+ }
+
+ bool CanBeMoved() const OVERRIDE { return true; }
+ bool InstructionDataEquals(HInstruction* other) const OVERRIDE {
+ size_t other_offset = other->AsStaticFieldGet()->GetFieldOffset().SizeValue();
+ return other_offset == GetFieldOffset().SizeValue();
+ }
+
+ size_t ComputeHashCode() const OVERRIDE {
+ return (HInstruction::ComputeHashCode() << 7) | GetFieldOffset().SizeValue();
+ }
+
+ MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
+ Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); }
+
+ DECLARE_INSTRUCTION(StaticFieldGet);
+
+ private:
+ const FieldInfo field_info_;
+
+ DISALLOW_COPY_AND_ASSIGN(HStaticFieldGet);
+};
+
+class HStaticFieldSet : public HTemplateInstruction<2> {
+ public:
+ HStaticFieldSet(HInstruction* cls,
+ HInstruction* value,
+ Primitive::Type field_type,
+ MemberOffset field_offset)
+ : HTemplateInstruction(SideEffects::ChangesSomething()),
+ field_info_(field_offset, field_type) {
+ SetRawInputAt(0, cls);
+ SetRawInputAt(1, value);
+ }
+
+ MemberOffset GetFieldOffset() const { return field_info_.GetFieldOffset(); }
+ Primitive::Type GetFieldType() const { return field_info_.GetFieldType(); }
+
+ DECLARE_INSTRUCTION(StaticFieldSet);
+
+ private:
+ const FieldInfo field_info_;
+
+ DISALLOW_COPY_AND_ASSIGN(HStaticFieldSet);
+};
+
class MoveOperands : public ArenaObject {
public:
MoveOperands(Location source, Location destination, HInstruction* instruction)