Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1603)

Unified Diff: runtime/vm/intermediate_language.h

Issue 10905015: Change the order of definitions in intermediate_language.h. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Rebased to HEAD. Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/intermediate_language.h
diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h
index 3cb88931a46315cd33e82f6f792ecf05df1915f3..17bec51d74c5c7d32c7c60db8d739427f80f17e6 100644
--- a/runtime/vm/intermediate_language.h
+++ b/runtime/vm/intermediate_language.h
@@ -14,6 +14,20 @@
namespace dart {
+class BindInstr;
+class BitVector;
+class BlockEntryInstr;
+class BufferFormatter;
+class ComparisonComp;
+class Computation;
+class Definition;
+class Environment;
+class FlowGraphCompiler;
+class FlowGraphVisitor;
+class Instruction;
+class LocalVariable;
+
+
// TODO(srdjan): Add _ByteArrayBase, get:length.
#define RECOGNIZED_LIST(V) \
@@ -42,293 +56,316 @@ RECOGNIZED_LIST(DEFINE_ENUM_LIST)
};
-class BitVector;
-class FlowGraphAllocator;
-class FlowGraphCompiler;
-class FlowGraphVisitor;
-class Function;
-class LocalVariable;
-
-// M is a two argument macro. It is applied to each concrete instruction's
-// (including the values) typename and classname.
-#define FOR_EACH_COMPUTATION(M) \
- M(AssertAssignable, AssertAssignableComp) \
- M(AssertBoolean, AssertBooleanComp) \
- M(ArgumentDefinitionTest, ArgumentDefinitionTestComp) \
- M(CurrentContext, CurrentContextComp) \
- M(StoreContext, StoreContextComp) \
- M(ClosureCall, ClosureCallComp) \
- M(InstanceCall, InstanceCallComp) \
- M(PolymorphicInstanceCall, PolymorphicInstanceCallComp) \
- M(StaticCall, StaticCallComp) \
- M(LoadLocal, LoadLocalComp) \
- M(StoreLocal, StoreLocalComp) \
- M(StrictCompare, StrictCompareComp) \
- M(EqualityCompare, EqualityCompareComp) \
- M(RelationalOp, RelationalOpComp) \
- M(NativeCall, NativeCallComp) \
- M(LoadIndexed, LoadIndexedComp) \
- M(StoreIndexed, StoreIndexedComp) \
- M(LoadInstanceField, LoadInstanceFieldComp) \
- M(StoreInstanceField, StoreInstanceFieldComp) \
- M(LoadStaticField, LoadStaticFieldComp) \
- M(StoreStaticField, StoreStaticFieldComp) \
- M(BooleanNegate, BooleanNegateComp) \
- M(InstanceOf, InstanceOfComp) \
- M(CreateArray, CreateArrayComp) \
- M(CreateClosure, CreateClosureComp) \
- M(AllocateObject, AllocateObjectComp) \
- M(AllocateObjectWithBoundsCheck, AllocateObjectWithBoundsCheckComp) \
- M(LoadVMField, LoadVMFieldComp) \
- M(StoreVMField, StoreVMFieldComp) \
- M(InstantiateTypeArguments, InstantiateTypeArgumentsComp) \
- M(ExtractConstructorTypeArguments, ExtractConstructorTypeArgumentsComp) \
- M(ExtractConstructorInstantiator, ExtractConstructorInstantiatorComp) \
- M(AllocateContext, AllocateContextComp) \
- M(ChainContext, ChainContextComp) \
- M(CloneContext, CloneContextComp) \
- M(CatchEntry, CatchEntryComp) \
- M(BinarySmiOp, BinarySmiOpComp) \
- M(BinaryMintOp, BinaryMintOpComp) \
- M(BinaryDoubleOp, BinaryDoubleOpComp) \
- M(UnarySmiOp, UnarySmiOpComp) \
- M(NumberNegate, NumberNegateComp) \
- M(CheckStackOverflow, CheckStackOverflowComp) \
- M(DoubleToDouble, DoubleToDoubleComp) \
- M(SmiToDouble, SmiToDoubleComp) \
- M(CheckClass, CheckClassComp) \
- M(CheckSmi, CheckSmiComp) \
- M(Constant, ConstantComp) \
- M(CheckEitherNonSmi, CheckEitherNonSmiComp) \
- M(UnboxedDoubleBinaryOp, UnboxedDoubleBinaryOpComp) \
- M(UnboxDouble, UnboxDoubleComp) \
- M(BoxDouble, BoxDoubleComp) \
- M(CheckArrayBound, CheckArrayBoundComp)
-
+class Value : public ZoneAllocated {
+ public:
+ explicit Value(Definition* definition)
+ : definition_(definition),
+ next_use_(NULL),
+ instruction_(NULL),
+ use_index_(-1) { }
-#define FORWARD_DECLARATION(ShortName, ClassName) class ClassName;
-FOR_EACH_COMPUTATION(FORWARD_DECLARATION)
-#undef FORWARD_DECLARATION
+ Definition* definition() const { return definition_; }
+ void set_definition(Definition* definition) { definition_ = definition; }
-// Forward declarations.
-class BindInstr;
-class BranchInstr;
-class BufferFormatter;
-class ComparisonComp;
-class Definition;
-class Definition;
-class Instruction;
-class PhiInstr;
-class PushArgumentInstr;
-class Value;
+ Value* next_use() const { return next_use_; }
+ void set_next_use(Value* next) { next_use_ = next; }
+ Instruction* instruction() const { return instruction_; }
+ void set_instruction(Instruction* instruction) { instruction_ = instruction; }
-enum Representation {
- kTagged, kUnboxedDouble
-};
+ intptr_t use_index() const { return use_index_; }
+ void set_use_index(intptr_t index) { use_index_ = index; }
+ void AddToInputUseList();
+ void AddToEnvUseList();
-class Computation : public ZoneAllocated {
- public:
- Computation()
- : deopt_id_(Isolate::Current()->GetNextDeoptId()), locs_(NULL) { }
+ Value* Copy() { return new Value(definition_); }
- // Unique id used for deoptimization.
- virtual intptr_t deopt_id() const {
- ASSERT(CanDeoptimize());
- return deopt_id_;
- }
+ RawAbstractType* CompileType() const;
+ intptr_t ResultCid() const;
- // Visiting support.
- virtual void Accept(FlowGraphVisitor* visitor, BindInstr* instr) = 0;
+ void PrintTo(BufferFormatter* f) const;
- virtual intptr_t InputCount() const = 0;
- virtual Value* InputAt(intptr_t i) const = 0;
- virtual void SetInputAt(intptr_t i, Value* value) = 0;
+ const char* DebugName() const { return "Value"; }
- // Call computations override this function and return the
- // number of pushed arguments.
- virtual intptr_t ArgumentCount() const = 0;
+ // Returns true if the value represents a constant.
+ bool BindsToConstant() const;
- // Returns true, if this computation can deoptimize.
- virtual bool CanDeoptimize() const = 0;
+ // Returns true if the value represents the constant null.
+ bool BindsToConstantNull() const;
- // Returns a replacement for the instruction that wraps this computation.
- // Returns NULL if instr can be eliminated.
- // By default returns instr (input parameter) which means no change.
- virtual Definition* TryReplace(BindInstr* instr) const;
+ // Assert if BindsToConstant() is false, otherwise returns the constant value.
+ const Object& BoundConstant() const;
- // Compares two computations. Returns true, if:
- // 1. They are of the same kind.
- // 2. All input operands match.
- // 3. All other attributes match.
- bool Equals(Computation* other) const;
+ // Reminder: The type of the constant null is the bottom type, which is more
+ // specific than any type.
+ bool CompileTypeIsMoreSpecificThan(const AbstractType& dst_type) const;
- // Returns a hash code for use with hash maps.
- virtual intptr_t Hashcode() const;
+ // Compile time constants, Bool, Smi and Nulls do not need to update
+ // the store buffer.
+ bool NeedsStoreBuffer() const;
- // Compare attributes of an computation (except input operands and kind).
- // All computations that participate in CSE have to override this function.
- virtual bool AttributesEqual(Computation* other) const {
- UNREACHABLE();
- return false;
- }
+ bool Equals(Value* other) const;
- // Returns true if the instruction may have side effects.
- // TODO(fschneider): Make this abstract and implement for all computations
- // instead of returning the safe default (true).
- virtual bool HasSideEffect() const { return true; }
+ private:
+ Definition* definition_;
+ Value* next_use_;
+ Instruction* instruction_;
+ intptr_t use_index_;
- // Compile time type of the computation, which typically depends on the
- // compile time types (and possibly propagated types) of its inputs.
- virtual RawAbstractType* CompileType() const = 0;
- virtual intptr_t ResultCid() const = 0;
+ DISALLOW_COPY_AND_ASSIGN(Value);
+};
- // Mutate assigned_vars to add the local variable index for all
- // frame-allocated locals assigned to by the computation.
- virtual void RecordAssignedVars(BitVector* assigned_vars,
- intptr_t fixed_parameter_count);
- virtual const char* DebugName() const = 0;
+enum Representation {
+ kTagged, kUnboxedDouble
+};
- // Printing support. These functions are sometimes overridden for custom
- // formatting. Otherwise, it prints in the format "opcode(op1, op2, op3)".
- virtual void PrintTo(BufferFormatter* f) const;
- virtual void PrintOperandsTo(BufferFormatter* f) const;
- // Returns structure describing location constraints required
- // to emit native code for this computation.
- LocationSummary* locs() {
- if (locs_ == NULL) {
- locs_ = MakeLocationSummary();
- }
- return locs_;
+// An embedded container with N elements of type T. Used (with partial
+// specialization for N=0) because embedded arrays cannot have size 0.
+template<typename T, intptr_t N>
+class EmbeddedArray {
+ public:
+ EmbeddedArray() {
+ for (intptr_t i = 0; i < N; i++) elements_[i] = NULL;
}
- virtual ComparisonComp* AsComparison() { return NULL; }
-
- // Create a location summary for this computation.
- // TODO(fschneider): Temporarily returns NULL for instructions
- // that are not yet converted to the location based code generation.
- virtual LocationSummary* MakeLocationSummary() const = 0;
-
- // TODO(fschneider): Make EmitNativeCode and locs const.
- virtual void EmitNativeCode(FlowGraphCompiler* compiler) = 0;
+ intptr_t length() const { return N; }
- virtual void EmitBranchCode(FlowGraphCompiler* compiler,
- BranchInstr* branch) {
- UNREACHABLE();
+ const T& operator[](intptr_t i) const {
+ ASSERT(i < length());
+ return elements_[i];
}
- static LocationSummary* MakeCallSummary();
+ T& operator[](intptr_t i) {
+ ASSERT(i < length());
+ return elements_[i];
+ }
- // Declare an enum value used to define kind-test predicates.
- enum ComputationKind {
-#define DECLARE_COMPUTATION_KIND(ShortName, ClassName) k##ShortName,
+ const T& At(intptr_t i) const {
+ return (*this)[i];
+ }
- FOR_EACH_COMPUTATION(DECLARE_COMPUTATION_KIND)
+ void SetAt(intptr_t i, const T& val) {
+ (*this)[i] = val;
+ }
-#undef DECLARE_COMPUTATION_KIND
- };
+ private:
+ T elements_[N];
+};
- virtual ComputationKind computation_kind() const = 0;
- // Returns representation expected for the input operand at the given index.
- virtual Representation RequiredInputRepresentation(intptr_t idx) const {
- return kTagged;
+template<typename T>
+class EmbeddedArray<T, 0> {
+ public:
+ intptr_t length() const { return 0; }
+ const T& operator[](intptr_t i) const {
+ UNREACHABLE();
+ static T sentinel = 0;
+ return sentinel;
}
-
- // Representation of the value produced by this computation.
- virtual Representation representation() const {
- return kTagged;
+ T& operator[](intptr_t i) {
+ UNREACHABLE();
+ static T sentinel = 0;
+ return sentinel;
}
+};
- // Returns deoptimization id that corresponds to the deoptimization target
- // that input operands conversions inserted for this instruction can jump
- // to. Can return kNoDeoptId.
- virtual intptr_t DeoptimizationTarget() const {
- UNREACHABLE();
- return Isolate::kNoDeoptId;
- }
- // Declare predicate for each computation.
-#define DECLARE_PREDICATE(ShortName, ClassName) \
- inline bool Is##ShortName() const; \
- inline const ClassName* As##ShortName() const; \
- inline ClassName* As##ShortName();
-FOR_EACH_COMPUTATION(DECLARE_PREDICATE)
-#undef DECLARE_PREDICATE
+// Instructions.
- protected:
- // Fetch deopt id without checking if this computation can deoptimize.
- intptr_t GetDeoptId() const {
- return deopt_id_;
- }
+// M is a single argument macro. It is applied to each concrete instruction
+// type name. The concrete instruction classes are the name with Instr
+// concatenated.
+#define FOR_EACH_INSTRUCTION(M) \
+ M(GraphEntry) \
+ M(JoinEntry) \
+ M(TargetEntry) \
+ M(Phi) \
+ M(Bind) \
+ M(Parameter) \
+ M(ParallelMove) \
+ M(PushArgument) \
+ M(Return) \
+ M(Throw) \
+ M(ReThrow) \
+ M(Goto) \
+ M(Branch) \
- private:
- friend class BranchInstr;
- intptr_t deopt_id_;
- LocationSummary* locs_;
+#define FORWARD_DECLARATION(type) class type##Instr;
+FOR_EACH_INSTRUCTION(FORWARD_DECLARATION)
+#undef FORWARD_DECLARATION
- DISALLOW_COPY_AND_ASSIGN(Computation);
-};
+
+// Functions required in all concrete instruction classes.
+#define DECLARE_INSTRUCTION(type) \
+ virtual void Accept(FlowGraphVisitor* visitor); \
+ virtual bool Is##type() const { return true; } \
+ virtual type##Instr* As##type() { return this; } \
+ virtual const char* DebugName() const { return #type; } \
+ virtual void PrintTo(BufferFormatter* f) const; \
+ virtual void PrintToVisualizer(BufferFormatter* f) const;
-// An embedded container with N elements of type T. Used (with partial
-// specialization for N=0) because embedded arrays cannot have size 0.
-template<typename T, intptr_t N>
-class EmbeddedArray {
+class Instruction : public ZoneAllocated {
public:
- EmbeddedArray() {
- for (intptr_t i = 0; i < N; i++) elements_[i] = NULL;
+ Instruction()
+ : lifetime_position_(-1), previous_(NULL), next_(NULL), env_(NULL) { }
+
+ virtual bool IsBlockEntry() const { return false; }
+ BlockEntryInstr* AsBlockEntry() {
+ return IsBlockEntry() ? reinterpret_cast<BlockEntryInstr*>(this) : NULL;
}
+ virtual bool IsDefinition() const { return false; }
+ virtual Definition* AsDefinition() { return NULL; }
+ virtual bool IsControl() const { return false; }
- intptr_t length() const { return N; }
+ virtual intptr_t InputCount() const = 0;
+ virtual Value* InputAt(intptr_t i) const = 0;
+ virtual void SetInputAt(intptr_t i, Value* value) = 0;
- const T& operator[](intptr_t i) const {
- ASSERT(i < length());
- return elements_[i];
+ // Call instructions override this function and return the
+ // number of pushed arguments.
+ virtual intptr_t ArgumentCount() const = 0;
+
+ // Returns true, if this instruction can deoptimize.
+ virtual bool CanDeoptimize() const = 0;
+
+ // Visiting support.
+ virtual void Accept(FlowGraphVisitor* visitor) = 0;
+
+ Instruction* previous() const { return previous_; }
+ void set_previous(Instruction* instr) {
+ ASSERT(!IsBlockEntry());
+ previous_ = instr;
}
- T& operator[](intptr_t i) {
- ASSERT(i < length());
- return elements_[i];
+ Instruction* next() const { return next_; }
+ void set_next(Instruction* instr) {
+ ASSERT(!IsGraphEntry());
+ ASSERT(!IsReturn());
+ ASSERT(!IsControl());
+ ASSERT(!IsPhi());
+ ASSERT(instr == NULL || !instr->IsBlockEntry());
+ // TODO(fschneider): Also add Throw and ReThrow to the list of instructions
+ // that do not have a successor. Currently, the graph builder will continue
+ // to append instruction in case of a Throw inside an expression. This
+ // condition should be handled in the graph builder
+ next_ = instr;
}
- const T& At(intptr_t i) const {
- return (*this)[i];
+ // Removed this instruction from the graph.
+ Instruction* RemoveFromGraph(bool return_previous = true);
+
+ // Normal instructions can have 0 (inside a block) or 1 (last instruction in
+ // a block) successors. Branch instruction with >1 successors override this
+ // function.
+ virtual intptr_t SuccessorCount() const;
+ virtual BlockEntryInstr* SuccessorAt(intptr_t index) const;
+
+ void Goto(JoinEntryInstr* entry);
+
+ // Discover basic-block structure by performing a recursive depth first
+ // traversal of the instruction graph reachable from this instruction. As
+ // a side effect, the block entry instructions in the graph are assigned
+ // numbers in both preorder and postorder. The array 'preorder' maps
+ // preorder block numbers to the block entry instruction with that number
+ // and analogously for the array 'postorder'. The depth first spanning
+ // tree is recorded in the array 'parent', which maps preorder block
+ // numbers to the preorder number of the block's spanning-tree parent.
+ // The array 'assigned_vars' maps preorder block numbers to the set of
+ // assigned frame-allocated local variables in the block. As a side
+ // effect of this function, the set of basic block predecessors (e.g.,
+ // block entry instructions of predecessor blocks) and also the last
+ // instruction in the block is recorded in each entry instruction.
+ virtual void DiscoverBlocks(
+ BlockEntryInstr* current_block,
+ GrowableArray<BlockEntryInstr*>* preorder,
+ GrowableArray<BlockEntryInstr*>* postorder,
+ GrowableArray<intptr_t>* parent,
+ GrowableArray<BitVector*>* assigned_vars,
+ intptr_t variable_count,
+ intptr_t fixed_parameter_count) {
+ // Never called for instructions except block entries and branches.
+ UNREACHABLE();
}
- void SetAt(intptr_t i, const T& val) {
- (*this)[i] = val;
+ // Mutate assigned_vars to add the local variable index for all
+ // frame-allocated locals assigned to by the instruction.
+ virtual void RecordAssignedVars(BitVector* assigned_vars,
+ intptr_t fixed_parameter_count);
+
+ // Printing support.
+ virtual void PrintTo(BufferFormatter* f) const = 0;
+ virtual void PrintToVisualizer(BufferFormatter* f) const = 0;
+
+#define INSTRUCTION_TYPE_CHECK(type) \
+ virtual bool Is##type() const { return false; } \
+ virtual type##Instr* As##type() { return NULL; }
+FOR_EACH_INSTRUCTION(INSTRUCTION_TYPE_CHECK)
+#undef INSTRUCTION_TYPE_CHECK
+
+ // Returns structure describing location constraints required
+ // to emit native code for this instruction.
+ virtual LocationSummary* locs() {
+ // TODO(vegorov): This should be pure virtual method.
+ // However we are temporary using NULL for instructions that
+ // were not converted to the location based code generation yet.
+ return NULL;
}
- private:
- T elements_[N];
-};
+ virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
+ UNIMPLEMENTED();
+ }
+ Environment* env() const { return env_; }
+ void set_env(Environment* env) { env_ = env; }
-template<typename T>
-class EmbeddedArray<T, 0> {
- public:
- intptr_t length() const { return 0; }
- const T& operator[](intptr_t i) const {
- UNREACHABLE();
- static T sentinel = 0;
- return sentinel;
+ intptr_t lifetime_position() const { return lifetime_position_; }
+ void set_lifetime_position(intptr_t pos) {
+ lifetime_position_ = pos;
}
- T& operator[](intptr_t i) {
+
+ // Returns representation expected for the input operand at the given index.
+ virtual Representation RequiredInputRepresentation(intptr_t idx) const {
+ return kTagged;
+ }
+
+ // Representation of the value produced by this computation.
+ virtual Representation representation() const {
+ return kTagged;
+ }
+
+ bool WasEliminated() const {
+ return next() == NULL;
+ }
+
+ // Returns deoptimization id that corresponds to the deoptimization target
+ // that input operands conversions inserted for this instruction can jump
+ // to.
+ virtual intptr_t DeoptimizationTarget() const {
UNREACHABLE();
- static T sentinel = 0;
- return sentinel;
+ return Isolate::kNoDeoptId;
}
+
+ private:
+ friend class BindInstr; // Needed for BindInstr::InsertBefore.
+
+ intptr_t lifetime_position_; // Position used by register allocator.
+ Instruction* previous_;
+ Instruction* next_;
+ Environment* env_;
+ DISALLOW_COPY_AND_ASSIGN(Instruction);
};
template<intptr_t N>
-class TemplateComputation : public Computation {
+class TemplateInstruction: public Instruction {
public:
+ TemplateInstruction<N>() : locs_(NULL) { }
+
virtual intptr_t InputCount() const { return N; }
virtual Value* InputAt(intptr_t i) const { return inputs_[i]; }
virtual void SetInputAt(intptr_t i, Value* value) {
@@ -336,1158 +373,1238 @@ class TemplateComputation : public Computation {
inputs_[i] = value;
}
+ virtual LocationSummary* locs() {
+ if (locs_ == NULL) {
+ locs_ = MakeLocationSummary();
+ }
+ return locs_;
+ }
+
+ virtual LocationSummary* MakeLocationSummary() const = 0;
+
protected:
EmbeddedArray<Value*, N> inputs_;
+
+ private:
+ LocationSummary* locs_;
};
-class Value : public ZoneAllocated {
+class MoveOperands : public ZoneAllocated {
public:
- explicit Value(Definition* definition)
- : definition_(definition),
- next_use_(NULL),
- instruction_(NULL),
- use_index_(-1) { }
-
- Definition* definition() const { return definition_; }
- void set_definition(Definition* definition) { definition_ = definition; }
+ MoveOperands(Location dest, Location src) : dest_(dest), src_(src) { }
- Value* next_use() const { return next_use_; }
- void set_next_use(Value* next) { next_use_ = next; }
+ Location src() const { return src_; }
+ Location dest() const { return dest_; }
- Instruction* instruction() const { return instruction_; }
- void set_instruction(Instruction* instruction) { instruction_ = instruction; }
+ Location* src_slot() { return &src_; }
+ Location* dest_slot() { return &dest_; }
- intptr_t use_index() const { return use_index_; }
- void set_use_index(intptr_t index) { use_index_ = index; }
+ void set_src(const Location& value) { src_ = value; }
+ void set_dest(const Location& value) { dest_ = value; }
- void AddToInputUseList();
- void AddToEnvUseList();
-
- Value* Copy() { return new Value(definition_); }
-
- RawAbstractType* CompileType() const;
- intptr_t ResultCid() const;
-
- void PrintTo(BufferFormatter* f) const;
-
- const char* DebugName() const { return "Value"; }
-
- // Returns true if the value represents a constant.
- bool BindsToConstant() const;
+ // The parallel move resolver marks moves as "in-progress" by clearing the
+ // destination (but not the source).
+ Location MarkPending() {
+ ASSERT(!IsPending());
+ Location dest = dest_;
+ dest_ = Location::NoLocation();
+ return dest;
+ }
- // Returns true if the value represents the constant null.
- bool BindsToConstantNull() const;
+ void ClearPending(Location dest) {
+ ASSERT(IsPending());
+ dest_ = dest;
+ }
- // Assert if BindsToConstant() is false, otherwise returns the constant value.
- const Object& BoundConstant() const;
+ bool IsPending() const {
+ ASSERT(!src_.IsInvalid() || dest_.IsInvalid());
+ return dest_.IsInvalid() && !src_.IsInvalid();
+ }
- // Reminder: The type of the constant null is the bottom type, which is more
- // specific than any type.
- bool CompileTypeIsMoreSpecificThan(const AbstractType& dst_type) const;
+ // True if this move a move from the given location.
+ bool Blocks(Location loc) const {
+ return !IsEliminated() && src_.Equals(loc);
+ }
- // Compile time constants, Bool, Smi and Nulls do not need to update
- // the store buffer.
- bool NeedsStoreBuffer() const;
+ // A move is redundant if it's been eliminated, if its source and
+ // destination are the same, or if its destination is unneeded.
+ bool IsRedundant() const {
+ return IsEliminated() || dest_.IsInvalid() || src_.Equals(dest_);
+ }
- bool Equals(Value* other) const;
+ // We clear both operands to indicate move that's been eliminated.
+ void Eliminate() { src_ = dest_ = Location::NoLocation(); }
+ bool IsEliminated() const {
+ ASSERT(!src_.IsInvalid() || dest_.IsInvalid());
+ return src_.IsInvalid();
+ }
private:
- Definition* definition_;
- Value* next_use_;
- Instruction* instruction_;
- intptr_t use_index_;
+ Location dest_;
+ Location src_;
- DISALLOW_COPY_AND_ASSIGN(Value);
+ DISALLOW_COPY_AND_ASSIGN(MoveOperands);
};
-// Functions defined in all concrete computation classes.
-#define DECLARE_COMPUTATION(ShortName) \
- virtual void Accept(FlowGraphVisitor* visitor, BindInstr* instr); \
- virtual ComputationKind computation_kind() const { \
- return Computation::k##ShortName; \
- } \
- virtual intptr_t ArgumentCount() const { return 0; } \
- virtual const char* DebugName() const { return #ShortName; } \
- virtual RawAbstractType* CompileType() const; \
- virtual LocationSummary* MakeLocationSummary() const; \
- virtual void EmitNativeCode(FlowGraphCompiler* compiler);
-
+class ParallelMoveInstr : public TemplateInstruction<0> {
+ public:
+ ParallelMoveInstr() : moves_(4) { }
-// Function defined in all call computation classes.
-#define DECLARE_CALL_COMPUTATION(ShortName) \
- virtual void Accept(FlowGraphVisitor* visitor, BindInstr* instr); \
- virtual ComputationKind computation_kind() const { \
- return Computation::k##ShortName; \
- } \
- virtual const char* DebugName() const { return #ShortName; } \
- virtual RawAbstractType* CompileType() const; \
- virtual LocationSummary* MakeLocationSummary() const; \
- virtual void EmitNativeCode(FlowGraphCompiler* compiler);
+ DECLARE_INSTRUCTION(ParallelMove)
+ virtual intptr_t ArgumentCount() const { return 0; }
-class ConstantComp : public TemplateComputation<0> {
- public:
- explicit ConstantComp(const Object& value) : value_(value) { }
+ virtual bool CanDeoptimize() const { return false; }
- DECLARE_COMPUTATION(Constant)
+ MoveOperands* AddMove(Location dest, Location src) {
+ MoveOperands* move = new MoveOperands(dest, src);
+ moves_.Add(move);
+ return move;
+ }
- const Object& value() const { return value_; }
+ MoveOperands* MoveOperandsAt(intptr_t index) const { return moves_[index]; }
- virtual void PrintOperandsTo(BufferFormatter* f) const;
+ void SetSrcSlotAt(intptr_t index, const Location& loc);
+ void SetDestSlotAt(intptr_t index, const Location& loc);
- virtual bool CanDeoptimize() const { return false; }
+ intptr_t NumMoves() const { return moves_.length(); }
- virtual intptr_t ResultCid() const;
+ LocationSummary* MakeLocationSummary() const { return NULL; }
- virtual bool AttributesEqual(Computation* other) const;
+ void EmitNativeCode(FlowGraphCompiler* compiler) { UNREACHABLE(); }
private:
- const Object& value_;
+ GrowableArray<MoveOperands*> moves_; // Elements cannot be null.
- DISALLOW_COPY_AND_ASSIGN(ConstantComp);
+ DISALLOW_COPY_AND_ASSIGN(ParallelMoveInstr);
};
-class AssertAssignableComp : public TemplateComputation<3> {
+// Basic block entries are administrative nodes. There is a distinguished
+// graph entry with no predecessor. Joins are the only nodes with multiple
+// predecessors. Targets are all other basic block entries. The types
+// enforce edge-split form---joins are forbidden as the successors of
+// branches.
+class BlockEntryInstr : public Instruction {
public:
- AssertAssignableComp(intptr_t token_pos,
- Value* value,
- Value* instantiator,
- Value* instantiator_type_arguments,
- const AbstractType& dst_type,
- const String& dst_name)
- : token_pos_(token_pos),
- dst_type_(dst_type),
- dst_name_(dst_name),
- is_eliminated_(false) {
- ASSERT(value != NULL);
- ASSERT(instantiator != NULL);
- ASSERT(instantiator_type_arguments != NULL);
- ASSERT(!dst_type.IsNull());
- ASSERT(!dst_name.IsNull());
- inputs_[0] = value;
- inputs_[1] = instantiator;
- inputs_[2] = instantiator_type_arguments;
- }
+ virtual bool IsBlockEntry() const { return true; }
- DECLARE_COMPUTATION(AssertAssignable)
+ virtual intptr_t PredecessorCount() const = 0;
+ virtual BlockEntryInstr* PredecessorAt(intptr_t index) const = 0;
+ virtual void AddPredecessor(BlockEntryInstr* predecessor) = 0;
+ virtual void PrepareEntry(FlowGraphCompiler* compiler) = 0;
- Value* value() const { return inputs_[0]; }
- Value* instantiator() const { return inputs_[1]; }
- Value* instantiator_type_arguments() const { return inputs_[2]; }
+ intptr_t preorder_number() const { return preorder_number_; }
+ void set_preorder_number(intptr_t number) { preorder_number_ = number; }
- intptr_t token_pos() const { return token_pos_; }
- const AbstractType& dst_type() const { return dst_type_; }
- const String& dst_name() const { return dst_name_; }
+ intptr_t postorder_number() const { return postorder_number_; }
+ void set_postorder_number(intptr_t number) { postorder_number_ = number; }
- bool is_eliminated() const {
- return is_eliminated_;
- }
- void eliminate() {
- ASSERT(!is_eliminated_);
- is_eliminated_ = true;
- }
+ intptr_t block_id() const { return block_id_; }
+ void set_block_id(intptr_t value) { block_id_ = value; }
- virtual void PrintOperandsTo(BufferFormatter* f) const;
+ void set_start_pos(intptr_t pos) { start_pos_ = pos; }
+ intptr_t start_pos() const { return start_pos_; }
+ void set_end_pos(intptr_t pos) { end_pos_ = pos; }
+ intptr_t end_pos() const { return end_pos_; }
- virtual bool CanDeoptimize() const { return false; }
- virtual intptr_t ResultCid() const { return kDynamicCid; }
+ BlockEntryInstr* dominator() const { return dominator_; }
+ void set_dominator(BlockEntryInstr* instr) { dominator_ = instr; }
- private:
- const intptr_t token_pos_;
- const AbstractType& dst_type_;
- const String& dst_name_;
- bool is_eliminated_;
+ const GrowableArray<BlockEntryInstr*>& dominated_blocks() {
+ return dominated_blocks_;
+ }
- DISALLOW_COPY_AND_ASSIGN(AssertAssignableComp);
-};
+ void AddDominatedBlock(BlockEntryInstr* block) {
+ dominated_blocks_.Add(block);
+ }
+ Instruction* last_instruction() const { return last_instruction_; }
+ void set_last_instruction(Instruction* instr) { last_instruction_ = instr; }
-class AssertBooleanComp : public TemplateComputation<1> {
- public:
- AssertBooleanComp(intptr_t token_pos,
- Value* value)
- : token_pos_(token_pos),
- is_eliminated_(false) {
- ASSERT(value != NULL);
- inputs_[0] = value;
+ ParallelMoveInstr* parallel_move() const {
+ return parallel_move_;
}
- DECLARE_COMPUTATION(AssertBoolean)
-
- intptr_t token_pos() const { return token_pos_; }
- Value* value() const { return inputs_[0]; }
+ bool HasParallelMove() const {
+ return parallel_move_ != NULL;
+ }
- bool is_eliminated() const {
- return is_eliminated_;
+ ParallelMoveInstr* GetParallelMove() {
+ if (parallel_move_ == NULL) {
+ parallel_move_ = new ParallelMoveInstr();
+ }
+ return parallel_move_;
}
- void eliminate() {
- ASSERT(!is_eliminated_);
- is_eliminated_ = true;
+
+ virtual void DiscoverBlocks(
+ BlockEntryInstr* current_block,
+ GrowableArray<BlockEntryInstr*>* preorder,
+ GrowableArray<BlockEntryInstr*>* postorder,
+ GrowableArray<intptr_t>* parent,
+ GrowableArray<BitVector*>* assigned_vars,
+ intptr_t variable_count,
+ intptr_t fixed_parameter_count);
+
+ virtual intptr_t InputCount() const { return 0; }
+ virtual Value* InputAt(intptr_t i) const {
+ UNREACHABLE();
+ return NULL;
}
+ virtual void SetInputAt(intptr_t i, Value* value) { UNREACHABLE(); }
- virtual void PrintOperandsTo(BufferFormatter* f) const;
+ virtual intptr_t ArgumentCount() const { return 0; }
virtual bool CanDeoptimize() const { return false; }
- virtual intptr_t ResultCid() const { return kBoolCid; }
-
- private:
- const intptr_t token_pos_;
- bool is_eliminated_;
- DISALLOW_COPY_AND_ASSIGN(AssertBooleanComp);
-};
+ intptr_t try_index() const { return try_index_; }
-
-class ArgumentDefinitionTestComp : public TemplateComputation<1> {
- public:
- ArgumentDefinitionTestComp(ArgumentDefinitionTestNode* node,
- Value* saved_arguments_descriptor)
- : ast_node_(*node) {
- ASSERT(saved_arguments_descriptor != NULL);
- inputs_[0] = saved_arguments_descriptor;
- }
-
- DECLARE_COMPUTATION(ArgumentDefinitionTest)
-
- intptr_t token_pos() const { return ast_node_.token_pos(); }
- intptr_t formal_parameter_index() const {
- return ast_node_.formal_parameter_index();
- }
- const String& formal_parameter_name() const {
- return ast_node_.formal_parameter_name();
- }
- Value* saved_arguments_descriptor() const { return inputs_[0]; }
-
- virtual void PrintOperandsTo(BufferFormatter* f) const;
-
- virtual bool CanDeoptimize() const { return false; }
- virtual intptr_t ResultCid() const { return kBoolCid; }
+ protected:
+ explicit BlockEntryInstr(intptr_t try_index)
+ : try_index_(try_index),
+ preorder_number_(-1),
+ postorder_number_(-1),
+ block_id_(-1),
+ dominator_(NULL),
+ dominated_blocks_(1),
+ last_instruction_(NULL),
+ parallel_move_(NULL) { }
private:
- const ArgumentDefinitionTestNode& ast_node_;
+ const intptr_t try_index_;
+ intptr_t preorder_number_;
+ intptr_t postorder_number_;
+ // Starting and ending lifetime positions for this block. Used by
+ // the linear scan register allocator.
+ intptr_t block_id_;
+ intptr_t start_pos_;
+ intptr_t end_pos_;
+ BlockEntryInstr* dominator_; // Immediate dominator, NULL for graph entry.
+ // TODO(fschneider): Optimize the case of one child to save space.
+ GrowableArray<BlockEntryInstr*> dominated_blocks_;
+ Instruction* last_instruction_;
- DISALLOW_COPY_AND_ASSIGN(ArgumentDefinitionTestComp);
+ // Parallel move that will be used by linear scan register allocator to
+ // connect live ranges at the start of the block.
+ ParallelMoveInstr* parallel_move_;
+
+ DISALLOW_COPY_AND_ASSIGN(BlockEntryInstr);
};
-// Denotes the current context, normally held in a register. This is
-// a computation, not a value, because it's mutable.
-class CurrentContextComp : public TemplateComputation<0> {
+class ForwardInstructionIterator : public ValueObject {
public:
- CurrentContextComp() { }
+ explicit ForwardInstructionIterator(BlockEntryInstr* block_entry)
+ : block_entry_(block_entry), current_(block_entry) {
+ ASSERT(block_entry_->last_instruction()->next() == NULL);
+ Advance();
+ }
- DECLARE_COMPUTATION(CurrentContext)
+ void Advance() {
+ ASSERT(!Done());
+ current_ = current_->next();
+ }
- virtual bool CanDeoptimize() const { return false; }
- virtual intptr_t ResultCid() const { return kDynamicCid; }
+ bool Done() const { return current_ == NULL; }
+
+ // Removes 'current_' from graph and sets 'current_' to previous instruction.
+ void RemoveCurrentFromGraph();
+
+ Instruction* Current() const { return current_; }
private:
- DISALLOW_COPY_AND_ASSIGN(CurrentContextComp);
+ BlockEntryInstr* block_entry_;
+ Instruction* current_;
};
-class StoreContextComp : public TemplateComputation<1> {
+class BackwardInstructionIterator : public ValueObject {
public:
- explicit StoreContextComp(Value* value) {
- ASSERT(value != NULL);
- inputs_[0] = value;
+ explicit BackwardInstructionIterator(BlockEntryInstr* block_entry)
+ : block_entry_(block_entry), current_(block_entry->last_instruction()) {
+ ASSERT(block_entry_->previous() == NULL);
}
- DECLARE_COMPUTATION(StoreContext);
+ void Advance() {
+ ASSERT(!Done());
+ current_ = current_->previous();
+ }
- Value* value() const { return inputs_[0]; }
+ bool Done() const { return current_ == block_entry_; }
- virtual bool CanDeoptimize() const { return false; }
- virtual intptr_t ResultCid() const { return kIllegalCid; }
+ Instruction* Current() const { return current_; }
private:
- DISALLOW_COPY_AND_ASSIGN(StoreContextComp);
+ BlockEntryInstr* block_entry_;
+ Instruction* current_;
};
-class ClosureCallComp : public TemplateComputation<0> {
+class GraphEntryInstr : public BlockEntryInstr {
public:
- ClosureCallComp(ClosureCallNode* node,
- ZoneGrowableArray<PushArgumentInstr*>* arguments)
- : ast_node_(*node),
- arguments_(arguments) { }
-
- DECLARE_CALL_COMPUTATION(ClosureCall)
+ explicit GraphEntryInstr(TargetEntryInstr* normal_entry);
- const Array& argument_names() const { return ast_node_.arguments()->names(); }
- intptr_t token_pos() const { return ast_node_.token_pos(); }
+ DECLARE_INSTRUCTION(GraphEntry)
- virtual intptr_t ArgumentCount() const { return arguments_->length(); }
- PushArgumentInstr* ArgumentAt(intptr_t index) const {
- return (*arguments_)[index];
+ virtual intptr_t PredecessorCount() const { return 0; }
+ virtual BlockEntryInstr* PredecessorAt(intptr_t index) const {
+ UNREACHABLE();
+ return NULL;
}
+ virtual void AddPredecessor(BlockEntryInstr* predecessor) { UNREACHABLE(); }
- virtual void PrintOperandsTo(BufferFormatter* f) const;
-
- virtual bool CanDeoptimize() const { return true; }
- virtual intptr_t ResultCid() const { return kDynamicCid; }
-
- private:
- const ClosureCallNode& ast_node_;
- ZoneGrowableArray<PushArgumentInstr*>* arguments_;
+ virtual intptr_t SuccessorCount() const;
+ virtual BlockEntryInstr* SuccessorAt(intptr_t index) const;
- DISALLOW_COPY_AND_ASSIGN(ClosureCallComp);
-};
+ virtual void DiscoverBlocks(
+ BlockEntryInstr* current_block,
+ GrowableArray<BlockEntryInstr*>* preorder,
+ GrowableArray<BlockEntryInstr*>* postorder,
+ GrowableArray<intptr_t>* parent,
+ GrowableArray<BitVector*>* assigned_vars,
+ intptr_t variable_count,
+ intptr_t fixed_parameter_count);
+ void AddCatchEntry(TargetEntryInstr* entry) { catch_entries_.Add(entry); }
-class InstanceCallComp : public TemplateComputation<0> {
- public:
- InstanceCallComp(intptr_t token_pos,
- const String& function_name,
- Token::Kind token_kind,
- ZoneGrowableArray<PushArgumentInstr*>* arguments,
- const Array& argument_names,
- intptr_t checked_argument_count)
- : ic_data_(Isolate::Current()->GetICDataForDeoptId(deopt_id())),
- token_pos_(token_pos),
- function_name_(function_name),
- token_kind_(token_kind),
- arguments_(arguments),
- argument_names_(argument_names),
- checked_argument_count_(checked_argument_count) {
- ASSERT(function_name.IsZoneHandle());
- ASSERT(!arguments->is_empty());
- ASSERT(argument_names.IsZoneHandle());
- ASSERT(Token::IsBinaryToken(token_kind) ||
- Token::IsUnaryToken(token_kind) ||
- Token::IsIndexOperator(token_kind) ||
- token_kind == Token::kGET ||
- token_kind == Token::kSET ||
- token_kind == Token::kILLEGAL);
- }
+ virtual void PrepareEntry(FlowGraphCompiler* compiler);
- DECLARE_CALL_COMPUTATION(InstanceCall)
+ Environment* start_env() const { return start_env_; }
+ void set_start_env(Environment* env) { start_env_ = env; }
- const ICData* ic_data() const { return ic_data_; }
- bool HasICData() const {
- return (ic_data() != NULL) && !ic_data()->IsNull();
- }
+ Definition* constant_null() const { return constant_null_; }
- intptr_t token_pos() const { return token_pos_; }
- const String& function_name() const { return function_name_; }
- Token::Kind token_kind() const { return token_kind_; }
- virtual intptr_t ArgumentCount() const { return arguments_->length(); }
- PushArgumentInstr* ArgumentAt(intptr_t index) const {
- return (*arguments_)[index];
+ intptr_t spill_slot_count() const { return spill_slot_count_; }
+ void set_spill_slot_count(intptr_t count) {
+ ASSERT(count >= 0);
+ spill_slot_count_ = count;
}
- const Array& argument_names() const { return argument_names_; }
- intptr_t checked_argument_count() const { return checked_argument_count_; }
-
- virtual void PrintOperandsTo(BufferFormatter* f) const;
- virtual bool CanDeoptimize() const { return true; }
- virtual intptr_t ResultCid() const { return kDynamicCid; }
+ TargetEntryInstr* normal_entry() const { return normal_entry_; }
private:
- const ICData* ic_data_;
- const intptr_t token_pos_;
- const String& function_name_;
- const Token::Kind token_kind_; // Binary op, unary op, kGET or kILLEGAL.
- ZoneGrowableArray<PushArgumentInstr*>* const arguments_;
- const Array& argument_names_;
- const intptr_t checked_argument_count_;
+ TargetEntryInstr* normal_entry_;
+ GrowableArray<TargetEntryInstr*> catch_entries_;
+ Environment* start_env_;
+ Definition* constant_null_;
+ intptr_t spill_slot_count_;
- DISALLOW_COPY_AND_ASSIGN(InstanceCallComp);
+ DISALLOW_COPY_AND_ASSIGN(GraphEntryInstr);
};
-class PolymorphicInstanceCallComp : public TemplateComputation<0> {
+class JoinEntryInstr : public BlockEntryInstr {
public:
- PolymorphicInstanceCallComp(InstanceCallComp* comp,
- const ICData& ic_data,
- bool with_checks)
- : instance_call_(comp), ic_data_(ic_data), with_checks_(with_checks) {
- ASSERT(instance_call_ != NULL);
- }
-
- InstanceCallComp* instance_call() const { return instance_call_; }
- bool with_checks() const { return with_checks_; }
+ explicit JoinEntryInstr(intptr_t try_index)
+ : BlockEntryInstr(try_index),
+ predecessors_(2), // Two is the assumed to be the common case.
+ phis_(NULL),
+ phi_count_(0) { }
- void PrintTo(BufferFormatter* f) const;
+ DECLARE_INSTRUCTION(JoinEntry)
- virtual intptr_t ArgumentCount() const {
- return instance_call()->ArgumentCount();
+ virtual intptr_t PredecessorCount() const { return predecessors_.length(); }
+ virtual BlockEntryInstr* PredecessorAt(intptr_t index) const {
+ return predecessors_[index];
+ }
+ virtual void AddPredecessor(BlockEntryInstr* predecessor) {
+ predecessors_.Add(predecessor);
}
- DECLARE_CALL_COMPUTATION(PolymorphicInstanceCall)
+ // Returns -1 if pred is not in the list.
+ intptr_t IndexOfPredecessor(BlockEntryInstr* pred) const;
- const ICData& ic_data() const { return ic_data_; }
+ ZoneGrowableArray<PhiInstr*>* phis() const { return phis_; }
- virtual bool CanDeoptimize() const { return true; }
- virtual intptr_t ResultCid() const { return kDynamicCid; }
+ virtual void PrepareEntry(FlowGraphCompiler* compiler);
+
+ void InsertPhi(intptr_t var_index, intptr_t var_count);
+ void RemoveDeadPhis();
+
+ intptr_t phi_count() const { return phi_count_; }
private:
- InstanceCallComp* instance_call_;
- const ICData& ic_data_;
- const bool with_checks_;
+ GrowableArray<BlockEntryInstr*> predecessors_;
+ ZoneGrowableArray<PhiInstr*>* phis_;
+ intptr_t phi_count_;
- DISALLOW_COPY_AND_ASSIGN(PolymorphicInstanceCallComp);
+ DISALLOW_COPY_AND_ASSIGN(JoinEntryInstr);
};
-class ComparisonComp : public TemplateComputation<2> {
+class TargetEntryInstr : public BlockEntryInstr {
public:
- ComparisonComp(Token::Kind kind, Value* left, Value* right) : kind_(kind) {
- ASSERT(left != NULL);
- ASSERT(right != NULL);
- inputs_[0] = left;
- inputs_[1] = right;
- }
-
- Value* left() const { return inputs_[0]; }
- Value* right() const { return inputs_[1]; }
+ explicit TargetEntryInstr(intptr_t try_index)
+ : BlockEntryInstr(try_index),
+ predecessor_(NULL),
+ catch_try_index_(CatchClauseNode::kInvalidTryIndex) { }
- virtual ComparisonComp* AsComparison() { return this; }
+ // Used for exception catch entries.
+ TargetEntryInstr(intptr_t try_index, intptr_t catch_try_index)
+ : BlockEntryInstr(try_index),
+ predecessor_(NULL),
+ catch_try_index_(catch_try_index) { }
- Token::Kind kind() const { return kind_; }
+ DECLARE_INSTRUCTION(TargetEntry)
+
+ virtual intptr_t PredecessorCount() const {
+ return (predecessor_ == NULL) ? 0 : 1;
+ }
+ virtual BlockEntryInstr* PredecessorAt(intptr_t index) const {
+ ASSERT((index == 0) && (predecessor_ != NULL));
+ return predecessor_;
+ }
+ virtual void AddPredecessor(BlockEntryInstr* predecessor) {
+ ASSERT(predecessor_ == NULL);
+ predecessor_ = predecessor;
+ }
+
+ // Returns true if this Block is an entry of a catch handler.
+ bool IsCatchEntry() const {
+ return catch_try_index_ != CatchClauseNode::kInvalidTryIndex;
+ }
+
+ // Returns try index for the try block to which this catch handler
+ // corresponds.
+ intptr_t catch_try_index() const {
+ ASSERT(IsCatchEntry());
+ return catch_try_index_;
+ }
+
+ virtual void PrepareEntry(FlowGraphCompiler* compiler);
private:
- Token::Kind kind_;
+ BlockEntryInstr* predecessor_;
+ const intptr_t catch_try_index_;
+
+ DISALLOW_COPY_AND_ASSIGN(TargetEntryInstr);
};
-class StrictCompareComp : public ComparisonComp {
+// Abstract super-class of all instructions that define a value (Bind, Phi).
+class Definition : public Instruction {
public:
- StrictCompareComp(Token::Kind kind, Value* left, Value* right)
- : ComparisonComp(kind, left, right) {
- ASSERT((kind == Token::kEQ_STRICT) || (kind == Token::kNE_STRICT));
+ Definition()
+ : temp_index_(-1),
+ ssa_temp_index_(-1),
+ propagated_type_(AbstractType::Handle()),
+ propagated_cid_(kIllegalCid),
+ input_use_list_(NULL),
+ env_use_list_(NULL) { }
+
+ virtual bool IsDefinition() const { return true; }
+ virtual Definition* AsDefinition() { return this; }
+
+ intptr_t temp_index() const { return temp_index_; }
+ void set_temp_index(intptr_t index) { temp_index_ = index; }
+
+ intptr_t ssa_temp_index() const { return ssa_temp_index_; }
+ void set_ssa_temp_index(intptr_t index) {
+ ASSERT(index >= 0);
+ ssa_temp_index_ = index;
}
+ bool HasSSATemp() const { return ssa_temp_index_ >= 0; }
- DECLARE_COMPUTATION(StrictCompare)
+ // Compile time type of the definition, which may be requested before type
+ // propagation during graph building.
+ virtual RawAbstractType* CompileType() const = 0;
- virtual void PrintOperandsTo(BufferFormatter* f) const;
+ bool HasPropagatedType() const {
+ return !propagated_type_.IsNull();
+ }
+ RawAbstractType* PropagatedType() const {
+ ASSERT(HasPropagatedType());
+ return propagated_type_.raw();
+ }
+ // Returns true if the propagated type has changed.
+ bool SetPropagatedType(const AbstractType& propagated_type) {
+ if (propagated_type.IsNull()) {
+ // Not a typed definition, e.g. access to a VM field.
+ return false;
+ }
+ const bool changed =
+ propagated_type_.IsNull() || !propagated_type.Equals(propagated_type_);
+ propagated_type_ = propagated_type.raw();
+ return changed;
+ }
- virtual bool CanDeoptimize() const { return false; }
+ bool has_propagated_cid() const { return propagated_cid_ != kIllegalCid; }
+ intptr_t propagated_cid() const { return propagated_cid_; }
+ // May compute and set propagated cid.
+ virtual intptr_t GetPropagatedCid() = 0;
- virtual Definition* TryReplace(BindInstr* instr) const;
+ // Returns true if the propagated cid has changed.
+ bool SetPropagatedCid(intptr_t cid);
- virtual intptr_t ResultCid() const { return kBoolCid; }
+ Value* input_use_list() { return input_use_list_; }
+ void set_input_use_list(Value* head) { input_use_list_ = head; }
- virtual void EmitBranchCode(FlowGraphCompiler* compiler,
- BranchInstr* branch);
+ Value* env_use_list() { return env_use_list_; }
+ void set_env_use_list(Value* head) { env_use_list_ = head; }
+
+ // Replace uses of this definition with uses of other definition or value.
+ // Precondition: use lists must be properly calculated.
+ // Postcondition: use lists and use values are still valid.
+ void ReplaceUsesWith(Definition* other);
private:
- DISALLOW_COPY_AND_ASSIGN(StrictCompareComp);
+ intptr_t temp_index_;
+ intptr_t ssa_temp_index_;
+ // TODO(regis): GrowableArray<const AbstractType*> propagated_types_;
+ // For now:
+ AbstractType& propagated_type_;
+ intptr_t propagated_cid_;
+ Value* input_use_list_;
+ Value* env_use_list_;
+
+ DISALLOW_COPY_AND_ASSIGN(Definition);
};
-class EqualityCompareComp : public ComparisonComp {
+class BindInstr : public Definition {
public:
- EqualityCompareComp(intptr_t token_pos,
- Token::Kind kind,
- Value* left,
- Value* right)
- : ComparisonComp(kind, left, right),
- ic_data_(Isolate::Current()->GetICDataForDeoptId(deopt_id())),
- token_pos_(token_pos),
- receiver_class_id_(kIllegalCid) {
- ASSERT((kind == Token::kEQ) || (kind == Token::kNE));
- }
-
- DECLARE_COMPUTATION(EqualityCompare)
+ enum UseKind { kUnused, kUsed };
- const ICData* ic_data() const { return ic_data_; }
- bool HasICData() const {
- return (ic_data() != NULL) && !ic_data()->IsNull();
+ BindInstr(UseKind used, Computation* computation)
+ : computation_(computation), is_used_(used != kUnused) {
+ ASSERT(computation != NULL);
}
- intptr_t token_pos() const { return token_pos_; }
+ DECLARE_INSTRUCTION(Bind)
- // Receiver class id is computed from collected ICData.
- void set_receiver_class_id(intptr_t value) { receiver_class_id_ = value; }
- intptr_t receiver_class_id() const { return receiver_class_id_; }
+ virtual intptr_t ArgumentCount() const;
+ intptr_t InputCount() const;
+ Value* InputAt(intptr_t i) const;
+ void SetInputAt(intptr_t i, Value* value);
+ virtual bool CanDeoptimize() const;
- virtual void PrintOperandsTo(BufferFormatter* f) const;
+ Computation* computation() const { return computation_; }
+ void set_computation(Computation* value) { computation_ = value; }
+ bool is_used() const { return is_used_; }
- virtual bool CanDeoptimize() const {
- return (receiver_class_id() != kDoubleCid);
- }
+ virtual RawAbstractType* CompileType() const;
+ virtual intptr_t GetPropagatedCid();
- virtual intptr_t ResultCid() const;
+ virtual void RecordAssignedVars(BitVector* assigned_vars,
+ intptr_t fixed_parameter_count);
- virtual void EmitBranchCode(FlowGraphCompiler* compiler,
- BranchInstr* branch);
+ intptr_t Hashcode() const;
+ bool Equals(BindInstr* other) const;
+ virtual LocationSummary* locs();
+ virtual void EmitNativeCode(FlowGraphCompiler* compiler);
- virtual intptr_t DeoptimizationTarget() const {
- return GetDeoptId();
- }
+ // Insert this instruction before 'next'.
+ void InsertBefore(Instruction* next);
- virtual Representation RequiredInputRepresentation(intptr_t idx) const {
- ASSERT((idx == 0) || (idx == 1));
- return (receiver_class_id() == kDoubleCid) ? kUnboxedDouble : kTagged;
- }
+ // Insert this instruction after 'prev'.
+ void InsertAfter(Instruction* prev);
+
+ virtual Representation RequiredInputRepresentation(intptr_t i) const;
+ virtual Representation representation() const;
+ virtual intptr_t DeoptimizationTarget() const;
private:
- const ICData* ic_data_;
- const intptr_t token_pos_;
- intptr_t receiver_class_id_; // Set by optimizer.
+ Computation* computation_;
+ const bool is_used_;
- DISALLOW_COPY_AND_ASSIGN(EqualityCompareComp);
+ DISALLOW_COPY_AND_ASSIGN(BindInstr);
};
-class RelationalOpComp : public ComparisonComp {
+class PhiInstr : public Definition {
public:
- RelationalOpComp(intptr_t token_pos,
- Token::Kind kind,
- Value* left,
- Value* right)
- : ComparisonComp(kind, left, right),
- ic_data_(Isolate::Current()->GetICDataForDeoptId(deopt_id())),
- token_pos_(token_pos),
- operands_class_id_(kIllegalCid) {
- ASSERT(Token::IsRelationalOperator(kind));
+ explicit PhiInstr(JoinEntryInstr* block, intptr_t num_inputs)
+ : block_(block),
+ inputs_(num_inputs),
+ is_alive_(false),
+ representation_(kTagged) {
+ for (intptr_t i = 0; i < num_inputs; ++i) {
+ inputs_.Add(NULL);
+ }
}
- DECLARE_COMPUTATION(RelationalOp)
+ JoinEntryInstr* block() const { return block_; }
- const ICData* ic_data() const { return ic_data_; }
- bool HasICData() const {
- return (ic_data() != NULL) && !ic_data()->IsNull();
- }
+ virtual RawAbstractType* CompileType() const;
+ virtual intptr_t GetPropagatedCid() { return propagated_cid(); }
- intptr_t token_pos() const { return token_pos_; }
+ virtual intptr_t ArgumentCount() const { return 0; }
- // TODO(srdjan): instead of class-id pass an enum that can differentiate
- // between boxed and unboxed doubles and integers.
- void set_operands_class_id(intptr_t value) {
- operands_class_id_ = value;
- }
+ intptr_t InputCount() const { return inputs_.length(); }
- intptr_t operands_class_id() const { return operands_class_id_; }
+ Value* InputAt(intptr_t i) const { return inputs_[i]; }
- virtual void PrintOperandsTo(BufferFormatter* f) const;
+ void SetInputAt(intptr_t i, Value* value) { inputs_[i] = value; }
- virtual bool CanDeoptimize() const {
- return operands_class_id() != kDoubleCid;
- }
+ virtual bool CanDeoptimize() const { return false; }
- virtual intptr_t ResultCid() const;
+ // TODO(regis): This helper will be removed once we support type sets.
+ RawAbstractType* LeastSpecificInputType() const;
- virtual void EmitBranchCode(FlowGraphCompiler* compiler,
- BranchInstr* branch);
+ // Phi is alive if it reaches a non-environment use.
+ bool is_alive() const { return is_alive_; }
+ void mark_alive() { is_alive_ = true; }
+ virtual Representation RequiredInputRepresentation(intptr_t i) const {
+ return representation_;
+ }
- virtual intptr_t DeoptimizationTarget() const {
- return GetDeoptId();
+ virtual Representation representation() const {
+ return representation_;
}
- virtual Representation RequiredInputRepresentation(intptr_t idx) const {
- ASSERT((idx == 0) || (idx == 1));
- return (operands_class_id() == kDoubleCid) ? kUnboxedDouble : kTagged;
+ virtual void set_representation(Representation r) {
+ representation_ = r;
}
+ DECLARE_INSTRUCTION(Phi)
+
private:
- const ICData* ic_data_;
- const intptr_t token_pos_;
- intptr_t operands_class_id_; // class id of both operands.
+ JoinEntryInstr* block_;
+ GrowableArray<Value*> inputs_;
+ bool is_alive_;
+ Representation representation_;
- DISALLOW_COPY_AND_ASSIGN(RelationalOpComp);
+ DISALLOW_COPY_AND_ASSIGN(PhiInstr);
};
-class StaticCallComp : public TemplateComputation<0> {
+class ParameterInstr : public Definition {
public:
- StaticCallComp(intptr_t token_pos,
- const Function& function,
- const Array& argument_names,
- ZoneGrowableArray<PushArgumentInstr*>* arguments)
- : token_pos_(token_pos),
- function_(function),
- argument_names_(argument_names),
- arguments_(arguments),
- recognized_(MethodRecognizer::kUnknown) {
- ASSERT(function.IsZoneHandle());
- ASSERT(argument_names.IsZoneHandle());
- }
+ explicit ParameterInstr(intptr_t index) : index_(index) { }
- DECLARE_CALL_COMPUTATION(StaticCall)
+ DECLARE_INSTRUCTION(Parameter)
- // Accessors forwarded to the AST node.
- const Function& function() const { return function_; }
- const Array& argument_names() const { return argument_names_; }
- intptr_t token_pos() const { return token_pos_; }
+ intptr_t index() const { return index_; }
- virtual intptr_t ArgumentCount() const { return arguments_->length(); }
- PushArgumentInstr* ArgumentAt(intptr_t index) const {
- return (*arguments_)[index];
- }
+ // Compile type of the passed-in parameter.
+ virtual RawAbstractType* CompileType() const;
+ // No known propagated cid for parameters.
+ virtual intptr_t GetPropagatedCid() { return propagated_cid(); }
- MethodRecognizer::Kind recognized() const { return recognized_; }
- void set_recognized(MethodRecognizer::Kind kind) { recognized_ = kind; }
+ virtual intptr_t ArgumentCount() const { return 0; }
- virtual void PrintOperandsTo(BufferFormatter* f) const;
+ intptr_t InputCount() const { return 0; }
+ Value* InputAt(intptr_t i) const {
+ UNREACHABLE();
+ return NULL;
+ }
+ void SetInputAt(intptr_t i, Value* value) { UNREACHABLE(); }
- virtual bool CanDeoptimize() const { return true; }
- virtual intptr_t ResultCid() const { return kDynamicCid; }
+ virtual bool CanDeoptimize() const { return false; }
private:
- const intptr_t token_pos_;
- const Function& function_;
- const Array& argument_names_;
- ZoneGrowableArray<PushArgumentInstr*>* arguments_;
- MethodRecognizer::Kind recognized_;
+ const intptr_t index_;
- DISALLOW_COPY_AND_ASSIGN(StaticCallComp);
+ DISALLOW_COPY_AND_ASSIGN(ParameterInstr);
};
-class LoadLocalComp : public TemplateComputation<0> {
+class PushArgumentInstr : public Definition {
public:
- LoadLocalComp(const LocalVariable& local, intptr_t context_level)
- : local_(local),
- context_level_(context_level) { }
+ explicit PushArgumentInstr(Value* value) : value_(value), locs_(NULL) {
+ ASSERT(value != NULL);
+ }
- DECLARE_COMPUTATION(LoadLocal)
+ DECLARE_INSTRUCTION(PushArgument)
- const LocalVariable& local() const { return local_; }
- intptr_t context_level() const { return context_level_; }
+ intptr_t InputCount() const { return 1; }
+ Value* InputAt(intptr_t i) const {
+ ASSERT(i == 0);
+ return value_;
+ }
+ void SetInputAt(intptr_t i, Value* value) {
+ ASSERT(i == 0);
+ value_ = value;
+ }
- virtual void PrintOperandsTo(BufferFormatter* f) const;
+ virtual intptr_t ArgumentCount() const { return 0; }
+
+ virtual RawAbstractType* CompileType() const;
+ virtual intptr_t GetPropagatedCid() { return propagated_cid(); }
+
+ Value* value() const { return value_; }
+
+ virtual LocationSummary* locs() {
+ if (locs_ == NULL) {
+ locs_ = MakeLocationSummary();
+ }
+ return locs_;
+ }
+
+ LocationSummary* MakeLocationSummary() const;
+
+ virtual void EmitNativeCode(FlowGraphCompiler* compiler);
virtual bool CanDeoptimize() const { return false; }
- virtual intptr_t ResultCid() const { return kDynamicCid; }
private:
- const LocalVariable& local_;
- const intptr_t context_level_;
+ Value* value_;
+ LocationSummary* locs_;
- DISALLOW_COPY_AND_ASSIGN(LoadLocalComp);
+ DISALLOW_COPY_AND_ASSIGN(PushArgumentInstr);
};
-class StoreLocalComp : public TemplateComputation<1> {
+class ReturnInstr : public TemplateInstruction<1> {
public:
- StoreLocalComp(const LocalVariable& local,
- Value* value,
- intptr_t context_level)
- : local_(local),
- context_level_(context_level) {
+ ReturnInstr(intptr_t token_pos, Value* value)
+ : deopt_id_(Isolate::Current()->GetNextDeoptId()),
+ token_pos_(token_pos) {
ASSERT(value != NULL);
inputs_[0] = value;
}
- DECLARE_COMPUTATION(StoreLocal)
+ DECLARE_INSTRUCTION(Return)
- const LocalVariable& local() const { return local_; }
+ virtual intptr_t ArgumentCount() const { return 0; }
+
+ intptr_t deopt_id() const { return deopt_id_; }
+ intptr_t token_pos() const { return token_pos_; }
Value* value() const { return inputs_[0]; }
- intptr_t context_level() const { return context_level_; }
- virtual void RecordAssignedVars(BitVector* assigned_vars,
- intptr_t fixed_parameter_count);
+ virtual LocationSummary* MakeLocationSummary() const;
- virtual void PrintOperandsTo(BufferFormatter* f) const;
+ virtual void EmitNativeCode(FlowGraphCompiler* compiler);
virtual bool CanDeoptimize() const { return false; }
- virtual intptr_t ResultCid() const { return kDynamicCid; }
private:
- const LocalVariable& local_;
- const intptr_t context_level_;
+ const intptr_t deopt_id_;
+ const intptr_t token_pos_;
- DISALLOW_COPY_AND_ASSIGN(StoreLocalComp);
+ DISALLOW_COPY_AND_ASSIGN(ReturnInstr);
};
-class NativeCallComp : public TemplateComputation<0> {
+class ThrowInstr : public TemplateInstruction<0> {
public:
- explicit NativeCallComp(NativeBodyNode* node)
- : ast_node_(*node) {}
-
- DECLARE_COMPUTATION(NativeCall)
-
- intptr_t token_pos() const { return ast_node_.token_pos(); }
-
- const String& native_name() const {
- return ast_node_.native_c_function_name();
- }
+ explicit ThrowInstr(intptr_t token_pos) : token_pos_(token_pos) { }
- NativeFunction native_c_function() const {
- return ast_node_.native_c_function();
- }
+ DECLARE_INSTRUCTION(Throw)
- intptr_t argument_count() const { return ast_node_.argument_count(); }
+ virtual intptr_t ArgumentCount() const { return 1; }
- bool has_optional_parameters() const {
- return ast_node_.has_optional_parameters();
- }
+ intptr_t token_pos() const { return token_pos_; }
- bool is_native_instance_closure() const {
- return ast_node_.is_native_instance_closure();
- }
+ virtual LocationSummary* MakeLocationSummary() const;
- virtual void PrintOperandsTo(BufferFormatter* f) const;
+ virtual void EmitNativeCode(FlowGraphCompiler* compiler);
virtual bool CanDeoptimize() const { return false; }
- virtual intptr_t ResultCid() const { return kDynamicCid; }
private:
- const NativeBodyNode& ast_node_;
+ const intptr_t token_pos_;
- DISALLOW_COPY_AND_ASSIGN(NativeCallComp);
+ DISALLOW_COPY_AND_ASSIGN(ThrowInstr);
};
-class LoadInstanceFieldComp : public TemplateComputation<1> {
+class ReThrowInstr : public TemplateInstruction<0> {
public:
- LoadInstanceFieldComp(const Field& field, Value* instance) : field_(field) {
- ASSERT(instance != NULL);
- inputs_[0] = instance;
- }
+ explicit ReThrowInstr(intptr_t token_pos) : token_pos_(token_pos) { }
- DECLARE_COMPUTATION(LoadInstanceField)
+ DECLARE_INSTRUCTION(ReThrow)
- const Field& field() const { return field_; }
- Value* instance() const { return inputs_[0]; }
+ virtual intptr_t ArgumentCount() const { return 2; }
- virtual void PrintOperandsTo(BufferFormatter* f) const;
+ intptr_t token_pos() const { return token_pos_; }
+
+ virtual LocationSummary* MakeLocationSummary() const;
+
+ virtual void EmitNativeCode(FlowGraphCompiler* compiler);
virtual bool CanDeoptimize() const { return false; }
- virtual intptr_t ResultCid() const { return kDynamicCid; }
private:
- const Field& field_;
+ const intptr_t token_pos_;
- DISALLOW_COPY_AND_ASSIGN(LoadInstanceFieldComp);
+ DISALLOW_COPY_AND_ASSIGN(ReThrowInstr);
};
-class StoreInstanceFieldComp : public TemplateComputation<2> {
+class GotoInstr : public TemplateInstruction<0> {
public:
- StoreInstanceFieldComp(const Field& field,
- Value* instance,
- Value* value)
- : field_(field) {
- ASSERT(instance != NULL);
- ASSERT(value != NULL);
- inputs_[0] = instance;
- inputs_[1] = value;
- }
-
- DECLARE_COMPUTATION(StoreInstanceField)
-
- const Field& field() const { return field_; }
-
- Value* instance() const { return inputs_[0]; }
- Value* value() const { return inputs_[1]; }
-
- virtual void PrintOperandsTo(BufferFormatter* f) const;
+ explicit GotoInstr(JoinEntryInstr* entry)
+ : successor_(entry),
+ parallel_move_(NULL) { }
- virtual bool CanDeoptimize() const { return false; }
- virtual intptr_t ResultCid() const { return kDynamicCid; }
+ DECLARE_INSTRUCTION(Goto)
- private:
- const Field& field_;
+ virtual intptr_t ArgumentCount() const { return 0; }
- DISALLOW_COPY_AND_ASSIGN(StoreInstanceFieldComp);
-};
+ JoinEntryInstr* successor() const { return successor_; }
+ void set_successor(JoinEntryInstr* successor) { successor_ = successor; }
+ virtual intptr_t SuccessorCount() const;
+ virtual BlockEntryInstr* SuccessorAt(intptr_t index) const;
+ virtual LocationSummary* MakeLocationSummary() const;
-class LoadStaticFieldComp : public TemplateComputation<0> {
- public:
- explicit LoadStaticFieldComp(const Field& field) : field_(field) {}
+ virtual void EmitNativeCode(FlowGraphCompiler* compiler);
- DECLARE_COMPUTATION(LoadStaticField);
+ virtual bool CanDeoptimize() const { return false; }
- const Field& field() const { return field_; }
+ ParallelMoveInstr* parallel_move() const {
+ return parallel_move_;
+ }
- virtual void PrintOperandsTo(BufferFormatter* f) const;
+ bool HasParallelMove() const {
+ return parallel_move_ != NULL;
+ }
- virtual bool CanDeoptimize() const { return false; }
- virtual intptr_t ResultCid() const { return kDynamicCid; }
+ ParallelMoveInstr* GetParallelMove() {
+ if (parallel_move_ == NULL) {
+ parallel_move_ = new ParallelMoveInstr();
+ }
+ return parallel_move_;
+ }
private:
- const Field& field_;
+ JoinEntryInstr* successor_;
- DISALLOW_COPY_AND_ASSIGN(LoadStaticFieldComp);
+ // Parallel move that will be used by linear scan register allocator to
+ // connect live ranges at the end of the block and resolve phis.
+ ParallelMoveInstr* parallel_move_;
};
-class StoreStaticFieldComp : public TemplateComputation<1> {
+class ControlInstruction : public Instruction {
public:
- StoreStaticFieldComp(const Field& field, Value* value)
- : field_(field) {
- ASSERT(field.IsZoneHandle());
- ASSERT(value != NULL);
- inputs_[0] = value;
- }
+ ControlInstruction() : true_successor_(NULL), false_successor_(NULL) { }
- DECLARE_COMPUTATION(StoreStaticField);
-
- const Field& field() const { return field_; }
- Value* value() const { return inputs_[0]; }
-
- virtual void PrintOperandsTo(BufferFormatter* f) const;
-
- virtual bool CanDeoptimize() const { return false; }
- virtual intptr_t ResultCid() const { return kDynamicCid; }
-
- private:
- const Field& field_;
-
- DISALLOW_COPY_AND_ASSIGN(StoreStaticFieldComp);
-};
+ virtual bool IsControl() const { return true; }
+ TargetEntryInstr* true_successor() const { return true_successor_; }
+ TargetEntryInstr* false_successor() const { return false_successor_; }
-class LoadIndexedComp : public TemplateComputation<2> {
- public:
- LoadIndexedComp(Value* array,
- Value* index,
- intptr_t receiver_type)
- : receiver_type_(receiver_type) {
- ASSERT(array != NULL);
- ASSERT(index != NULL);
- inputs_[0] = array;
- inputs_[1] = index;
- }
+ TargetEntryInstr** true_successor_address() { return &true_successor_; }
+ TargetEntryInstr** false_successor_address() { return &false_successor_; }
- DECLARE_COMPUTATION(LoadIndexed)
+ virtual intptr_t SuccessorCount() const;
+ virtual BlockEntryInstr* SuccessorAt(intptr_t index) const;
- Value* array() const { return inputs_[0]; }
- Value* index() const { return inputs_[1]; }
+ virtual void DiscoverBlocks(
+ BlockEntryInstr* current_block,
+ GrowableArray<BlockEntryInstr*>* preorder,
+ GrowableArray<BlockEntryInstr*>* postorder,
+ GrowableArray<intptr_t>* parent,
+ GrowableArray<BitVector*>* assigned_vars,
+ intptr_t variable_count,
+ intptr_t fixed_parameter_count);
- intptr_t receiver_type() const { return receiver_type_; }
- virtual bool CanDeoptimize() const { return false; }
- virtual intptr_t ResultCid() const { return kDynamicCid; }
+ void EmitBranchOnCondition(FlowGraphCompiler* compiler,
+ Condition true_condition);
private:
- intptr_t receiver_type_;
+ TargetEntryInstr* true_successor_;
+ TargetEntryInstr* false_successor_;
- DISALLOW_COPY_AND_ASSIGN(LoadIndexedComp);
+ DISALLOW_COPY_AND_ASSIGN(ControlInstruction);
};
-class StoreIndexedComp : public TemplateComputation<3> {
+class BranchInstr : public ControlInstruction {
public:
- StoreIndexedComp(Value* array,
- Value* index,
- Value* value,
- intptr_t receiver_type)
- : receiver_type_(receiver_type) {
- ASSERT(array != NULL);
- ASSERT(index != NULL);
- ASSERT(value != NULL);
- inputs_[0] = array;
- inputs_[1] = index;
- inputs_[2] = value;
- }
+ explicit BranchInstr(ComparisonComp* computation)
+ : computation_(computation), locs_(NULL) { }
- DECLARE_COMPUTATION(StoreIndexed)
+ DECLARE_INSTRUCTION(Branch)
- Value* array() const { return inputs_[0]; }
- Value* index() const { return inputs_[1]; }
- Value* value() const { return inputs_[2]; }
+ virtual intptr_t ArgumentCount() const;
+ intptr_t InputCount() const;
+ Value* InputAt(intptr_t i) const;
+ void SetInputAt(intptr_t i, Value* value);
+ virtual bool CanDeoptimize() const;
- intptr_t receiver_type() const { return receiver_type_; }
+ ComparisonComp* computation() const { return computation_; }
+ void set_computation(ComparisonComp* value) { computation_ = value; }
- virtual bool CanDeoptimize() const { return false; }
- virtual intptr_t ResultCid() const { return kDynamicCid; }
+ virtual void EmitNativeCode(FlowGraphCompiler* compiler);
+
+ virtual LocationSummary* locs();
+ virtual intptr_t DeoptimizationTarget() const;
+ virtual Representation RequiredInputRepresentation(intptr_t i) const;
private:
- intptr_t receiver_type_;
+ ComparisonComp* computation_;
+ LocationSummary* locs_;
- DISALLOW_COPY_AND_ASSIGN(StoreIndexedComp);
+ DISALLOW_COPY_AND_ASSIGN(BranchInstr);
};
-// Note overrideable, built-in: value? false : true.
-class BooleanNegateComp : public TemplateComputation<1> {
- public:
- explicit BooleanNegateComp(Value* value) {
- ASSERT(value != NULL);
- inputs_[0] = value;
- }
+#undef DECLARE_INSTRUCTION
- DECLARE_COMPUTATION(BooleanNegate)
- Value* value() const { return inputs_[0]; }
+// M is a two argument macro. It is applied to each concrete instruction's
+// (including the values) typename and classname.
+#define FOR_EACH_COMPUTATION(M) \
+ M(AssertAssignable, AssertAssignableComp) \
+ M(AssertBoolean, AssertBooleanComp) \
+ M(ArgumentDefinitionTest, ArgumentDefinitionTestComp) \
+ M(CurrentContext, CurrentContextComp) \
+ M(StoreContext, StoreContextComp) \
+ M(ClosureCall, ClosureCallComp) \
+ M(InstanceCall, InstanceCallComp) \
+ M(PolymorphicInstanceCall, PolymorphicInstanceCallComp) \
+ M(StaticCall, StaticCallComp) \
+ M(LoadLocal, LoadLocalComp) \
+ M(StoreLocal, StoreLocalComp) \
+ M(StrictCompare, StrictCompareComp) \
+ M(EqualityCompare, EqualityCompareComp) \
+ M(RelationalOp, RelationalOpComp) \
+ M(NativeCall, NativeCallComp) \
+ M(LoadIndexed, LoadIndexedComp) \
+ M(StoreIndexed, StoreIndexedComp) \
+ M(LoadInstanceField, LoadInstanceFieldComp) \
+ M(StoreInstanceField, StoreInstanceFieldComp) \
+ M(LoadStaticField, LoadStaticFieldComp) \
+ M(StoreStaticField, StoreStaticFieldComp) \
+ M(BooleanNegate, BooleanNegateComp) \
+ M(InstanceOf, InstanceOfComp) \
+ M(CreateArray, CreateArrayComp) \
+ M(CreateClosure, CreateClosureComp) \
+ M(AllocateObject, AllocateObjectComp) \
+ M(AllocateObjectWithBoundsCheck, AllocateObjectWithBoundsCheckComp) \
+ M(LoadVMField, LoadVMFieldComp) \
+ M(StoreVMField, StoreVMFieldComp) \
+ M(InstantiateTypeArguments, InstantiateTypeArgumentsComp) \
+ M(ExtractConstructorTypeArguments, ExtractConstructorTypeArgumentsComp) \
+ M(ExtractConstructorInstantiator, ExtractConstructorInstantiatorComp) \
+ M(AllocateContext, AllocateContextComp) \
+ M(ChainContext, ChainContextComp) \
+ M(CloneContext, CloneContextComp) \
+ M(CatchEntry, CatchEntryComp) \
+ M(BinarySmiOp, BinarySmiOpComp) \
+ M(BinaryMintOp, BinaryMintOpComp) \
+ M(BinaryDoubleOp, BinaryDoubleOpComp) \
+ M(UnarySmiOp, UnarySmiOpComp) \
+ M(NumberNegate, NumberNegateComp) \
+ M(CheckStackOverflow, CheckStackOverflowComp) \
+ M(DoubleToDouble, DoubleToDoubleComp) \
+ M(SmiToDouble, SmiToDoubleComp) \
+ M(CheckClass, CheckClassComp) \
+ M(CheckSmi, CheckSmiComp) \
+ M(Constant, ConstantComp) \
+ M(CheckEitherNonSmi, CheckEitherNonSmiComp) \
+ M(UnboxedDoubleBinaryOp, UnboxedDoubleBinaryOpComp) \
+ M(UnboxDouble, UnboxDoubleComp) \
+ M(BoxDouble, BoxDoubleComp) \
+ M(CheckArrayBound, CheckArrayBoundComp)
- virtual bool CanDeoptimize() const { return false; }
- virtual intptr_t ResultCid() const { return kBoolCid; }
- private:
- DISALLOW_COPY_AND_ASSIGN(BooleanNegateComp);
-};
+#define FORWARD_DECLARATION(ShortName, ClassName) class ClassName;
+FOR_EACH_COMPUTATION(FORWARD_DECLARATION)
+#undef FORWARD_DECLARATION
-class InstanceOfComp : public TemplateComputation<3> {
+class Computation : public ZoneAllocated {
public:
- InstanceOfComp(intptr_t token_pos,
- Value* value,
- Value* instantiator,
- Value* instantiator_type_arguments,
- const AbstractType& type,
- bool negate_result)
- : token_pos_(token_pos),
- type_(type),
- negate_result_(negate_result) {
- ASSERT(value != NULL);
- ASSERT(instantiator != NULL);
- ASSERT(instantiator_type_arguments != NULL);
- ASSERT(!type.IsNull());
- inputs_[0] = value;
- inputs_[1] = instantiator;
- inputs_[2] = instantiator_type_arguments;
- }
+ Computation()
+ : deopt_id_(Isolate::Current()->GetNextDeoptId()), locs_(NULL) { }
- DECLARE_COMPUTATION(InstanceOf)
+ // Unique id used for deoptimization.
+ virtual intptr_t deopt_id() const {
+ ASSERT(CanDeoptimize());
+ return deopt_id_;
+ }
- Value* value() const { return inputs_[0]; }
- Value* instantiator() const { return inputs_[1]; }
- Value* instantiator_type_arguments() const { return inputs_[2]; }
+ // Visiting support.
+ virtual void Accept(FlowGraphVisitor* visitor, BindInstr* instr) = 0;
- bool negate_result() const { return negate_result_; }
- const AbstractType& type() const { return type_; }
- intptr_t token_pos() const { return token_pos_; }
+ virtual intptr_t InputCount() const = 0;
+ virtual Value* InputAt(intptr_t i) const = 0;
+ virtual void SetInputAt(intptr_t i, Value* value) = 0;
- virtual void PrintOperandsTo(BufferFormatter* f) const;
+ // Call computations override this function and return the
+ // number of pushed arguments.
+ virtual intptr_t ArgumentCount() const = 0;
- virtual bool CanDeoptimize() const { return false; }
- virtual intptr_t ResultCid() const { return kBoolCid; }
+ // Returns true, if this computation can deoptimize.
+ virtual bool CanDeoptimize() const = 0;
- private:
- const intptr_t token_pos_;
- Value* value_;
- Value* instantiator_;
- Value* type_arguments_;
- const AbstractType& type_;
- const bool negate_result_;
+ // Returns a replacement for the instruction that wraps this computation.
+ // Returns NULL if instr can be eliminated.
+ // By default returns instr (input parameter) which means no change.
+ virtual Definition* TryReplace(BindInstr* instr) const;
- DISALLOW_COPY_AND_ASSIGN(InstanceOfComp);
-};
+ // Compares two computations. Returns true, if:
+ // 1. They are of the same kind.
+ // 2. All input operands match.
+ // 3. All other attributes match.
+ bool Equals(Computation* other) const;
+ // Returns a hash code for use with hash maps.
+ virtual intptr_t Hashcode() const;
-class AllocateObjectComp : public TemplateComputation<0> {
- public:
- AllocateObjectComp(ConstructorCallNode* node,
- ZoneGrowableArray<PushArgumentInstr*>* arguments)
- : ast_node_(*node), arguments_(arguments) {
- // Either no arguments or one type-argument and one instantiator.
- ASSERT(arguments->is_empty() || (arguments->length() == 2));
+ // Compare attributes of an computation (except input operands and kind).
+ // All computations that participate in CSE have to override this function.
+ virtual bool AttributesEqual(Computation* other) const {
+ UNREACHABLE();
+ return false;
}
- DECLARE_CALL_COMPUTATION(AllocateObject)
+ // Returns true if the instruction may have side effects.
+ // TODO(fschneider): Make this abstract and implement for all computations
+ // instead of returning the safe default (true).
+ virtual bool HasSideEffect() const { return true; }
- virtual intptr_t ArgumentCount() const { return arguments_->length(); }
- PushArgumentInstr* ArgumentAt(intptr_t index) const {
- return (*arguments_)[index];
- }
+ // Compile time type of the computation, which typically depends on the
+ // compile time types (and possibly propagated types) of its inputs.
+ virtual RawAbstractType* CompileType() const = 0;
+ virtual intptr_t ResultCid() const = 0;
- const Function& constructor() const { return ast_node_.constructor(); }
- intptr_t token_pos() const { return ast_node_.token_pos(); }
+ // Mutate assigned_vars to add the local variable index for all
+ // frame-allocated locals assigned to by the computation.
+ virtual void RecordAssignedVars(BitVector* assigned_vars,
+ intptr_t fixed_parameter_count);
+ virtual const char* DebugName() const = 0;
+
+ // Printing support. These functions are sometimes overridden for custom
+ // formatting. Otherwise, it prints in the format "opcode(op1, op2, op3)".
+ virtual void PrintTo(BufferFormatter* f) const;
virtual void PrintOperandsTo(BufferFormatter* f) const;
- virtual bool CanDeoptimize() const { return false; }
- virtual intptr_t ResultCid() const { return kDynamicCid; }
+ // Returns structure describing location constraints required
+ // to emit native code for this computation.
+ LocationSummary* locs() {
+ if (locs_ == NULL) {
+ locs_ = MakeLocationSummary();
+ }
+ return locs_;
+ }
- private:
- const ConstructorCallNode& ast_node_;
- ZoneGrowableArray<PushArgumentInstr*>* const arguments_;
+ virtual ComparisonComp* AsComparison() { return NULL; }
- DISALLOW_COPY_AND_ASSIGN(AllocateObjectComp);
-};
+ // Create a location summary for this computation.
+ // TODO(fschneider): Temporarily returns NULL for instructions
+ // that are not yet converted to the location based code generation.
+ virtual LocationSummary* MakeLocationSummary() const = 0;
+ // TODO(fschneider): Make EmitNativeCode and locs const.
+ virtual void EmitNativeCode(FlowGraphCompiler* compiler) = 0;
-class AllocateObjectWithBoundsCheckComp : public TemplateComputation<2> {
- public:
- AllocateObjectWithBoundsCheckComp(ConstructorCallNode* node,
- Value* type_arguments,
- Value* instantiator)
- : ast_node_(*node) {
- ASSERT(type_arguments != NULL);
- ASSERT(instantiator != NULL);
- inputs_[0] = type_arguments;
- inputs_[1] = instantiator;
+ virtual void EmitBranchCode(FlowGraphCompiler* compiler,
+ BranchInstr* branch) {
+ UNREACHABLE();
}
- DECLARE_COMPUTATION(AllocateObjectWithBoundsCheck)
+ static LocationSummary* MakeCallSummary();
- const Function& constructor() const { return ast_node_.constructor(); }
- intptr_t token_pos() const { return ast_node_.token_pos(); }
+ // Declare an enum value used to define kind-test predicates.
+ enum ComputationKind {
+#define DECLARE_COMPUTATION_KIND(ShortName, ClassName) k##ShortName,
- virtual void PrintOperandsTo(BufferFormatter* f) const;
+ FOR_EACH_COMPUTATION(DECLARE_COMPUTATION_KIND)
- virtual bool CanDeoptimize() const { return false; }
- virtual intptr_t ResultCid() const { return kDynamicCid; }
+#undef DECLARE_COMPUTATION_KIND
+ };
+
+ virtual ComputationKind computation_kind() const = 0;
+
+ // Returns representation expected for the input operand at the given index.
+ virtual Representation RequiredInputRepresentation(intptr_t idx) const {
+ return kTagged;
+ }
+
+ // Representation of the value produced by this computation.
+ virtual Representation representation() const {
+ return kTagged;
+ }
+
+ // Returns deoptimization id that corresponds to the deoptimization target
+ // that input operands conversions inserted for this instruction can jump
+ // to. Can return kNoDeoptId.
+ virtual intptr_t DeoptimizationTarget() const {
+ UNREACHABLE();
+ return Isolate::kNoDeoptId;
+ }
+
+ // Declare predicate for each computation.
+#define DECLARE_PREDICATE(ShortName, ClassName) \
+ inline bool Is##ShortName() const; \
+ inline const ClassName* As##ShortName() const; \
+ inline ClassName* As##ShortName();
+FOR_EACH_COMPUTATION(DECLARE_PREDICATE)
+#undef DECLARE_PREDICATE
+
+ protected:
+ // Fetch deopt id without checking if this computation can deoptimize.
+ intptr_t GetDeoptId() const {
+ return deopt_id_;
+ }
private:
- const ConstructorCallNode& ast_node_;
+ friend class BranchInstr;
- DISALLOW_COPY_AND_ASSIGN(AllocateObjectWithBoundsCheckComp);
+ intptr_t deopt_id_;
+ LocationSummary* locs_;
+
+ DISALLOW_COPY_AND_ASSIGN(Computation);
};
-class CreateArrayComp : public TemplateComputation<1> {
- public:
- CreateArrayComp(intptr_t token_pos,
- ZoneGrowableArray<PushArgumentInstr*>* arguments,
- const AbstractType& type,
- Value* element_type)
- : token_pos_(token_pos),
- arguments_(arguments),
- type_(type) {
-#if defined(DEBUG)
- for (int i = 0; i < ArgumentCount(); ++i) {
- ASSERT(ArgumentAt(i) != NULL);
- }
- ASSERT(element_type != NULL);
- ASSERT(type_.IsZoneHandle());
- ASSERT(!type_.IsNull());
- ASSERT(type_.IsFinalized());
-#endif
- inputs_[0] = element_type;
- }
+// Inlined functions from class BindInstr that forward to their computation.
+inline intptr_t BindInstr::ArgumentCount() const {
+ return computation()->ArgumentCount();
+}
- DECLARE_CALL_COMPUTATION(CreateArray)
- virtual intptr_t ArgumentCount() const { return arguments_->length(); }
+inline intptr_t BindInstr::InputCount() const {
+ return computation()->InputCount();
+}
- intptr_t token_pos() const { return token_pos_; }
- PushArgumentInstr* ArgumentAt(intptr_t i) const { return (*arguments_)[i]; }
- const AbstractType& type() const { return type_; }
- Value* element_type() const { return inputs_[0]; }
- virtual void PrintOperandsTo(BufferFormatter* f) const;
+inline Value* BindInstr::InputAt(intptr_t i) const {
+ return computation()->InputAt(i);
+}
- virtual bool CanDeoptimize() const { return false; }
- virtual intptr_t ResultCid() const { return kDynamicCid; }
- private:
- const intptr_t token_pos_;
- ZoneGrowableArray<PushArgumentInstr*>* const arguments_;
- const AbstractType& type_;
+inline void BindInstr::SetInputAt(intptr_t i, Value* value) {
+ computation()->SetInputAt(i, value);
+}
- DISALLOW_COPY_AND_ASSIGN(CreateArrayComp);
-};
+inline bool BindInstr::CanDeoptimize() const {
+ return computation()->CanDeoptimize();
+}
-class CreateClosureComp : public TemplateComputation<0> {
- public:
- CreateClosureComp(ClosureNode* node,
- ZoneGrowableArray<PushArgumentInstr*>* arguments)
- : ast_node_(*node),
- arguments_(arguments) { }
+inline intptr_t BindInstr::Hashcode() const {
+ return computation()->Hashcode();
+}
- DECLARE_CALL_COMPUTATION(CreateClosure)
- intptr_t token_pos() const { return ast_node_.token_pos(); }
- const Function& function() const { return ast_node_.function(); }
+inline bool BindInstr::Equals(BindInstr* other) const {
+ return computation()->Equals(other->computation());
+}
- virtual intptr_t ArgumentCount() const { return arguments_->length(); }
- PushArgumentInstr* ArgumentAt(intptr_t index) const {
- return (*arguments_)[index];
- }
- virtual void PrintOperandsTo(BufferFormatter* f) const;
+inline LocationSummary* BindInstr::locs() {
+ return computation()->locs();
+}
- virtual bool CanDeoptimize() const { return false; }
- virtual intptr_t ResultCid() const { return kDynamicCid; }
- private:
- const ClosureNode& ast_node_;
- ZoneGrowableArray<PushArgumentInstr*>* arguments_;
+inline Representation BindInstr::RequiredInputRepresentation(intptr_t i) const {
+ return computation()->RequiredInputRepresentation(i);
+}
- DISALLOW_COPY_AND_ASSIGN(CreateClosureComp);
-};
+
+inline Representation BindInstr::representation() const {
+ return computation()->representation();
+}
-class LoadVMFieldComp : public TemplateComputation<1> {
+inline intptr_t BindInstr::DeoptimizationTarget() const {
+ return computation()->DeoptimizationTarget();
+}
+
+
+template<intptr_t N>
+class TemplateComputation : public Computation {
public:
- LoadVMFieldComp(Value* value,
- intptr_t offset_in_bytes,
- const AbstractType& type)
- : offset_in_bytes_(offset_in_bytes),
- type_(type),
- result_cid_(kDynamicCid) {
+ virtual intptr_t InputCount() const { return N; }
+ virtual Value* InputAt(intptr_t i) const { return inputs_[i]; }
+ virtual void SetInputAt(intptr_t i, Value* value) {
ASSERT(value != NULL);
- ASSERT(type.IsZoneHandle()); // May be null if field is not an instance.
- inputs_[0] = value;
+ inputs_[i] = value;
}
- DECLARE_COMPUTATION(LoadVMField)
-
- Value* value() const { return inputs_[0]; }
- intptr_t offset_in_bytes() const { return offset_in_bytes_; }
- const AbstractType& type() const { return type_; }
- void set_result_cid(intptr_t value) { result_cid_ = value; }
+ protected:
+ EmbeddedArray<Value*, N> inputs_;
+};
- virtual void PrintOperandsTo(BufferFormatter* f) const;
- virtual bool CanDeoptimize() const { return false; }
- virtual intptr_t ResultCid() const { return result_cid_; }
+// Functions defined in all concrete computation classes.
+#define DECLARE_COMPUTATION(ShortName) \
+ virtual void Accept(FlowGraphVisitor* visitor, BindInstr* instr); \
+ virtual ComputationKind computation_kind() const { \
+ return Computation::k##ShortName; \
+ } \
+ virtual intptr_t ArgumentCount() const { return 0; } \
+ virtual const char* DebugName() const { return #ShortName; } \
+ virtual RawAbstractType* CompileType() const; \
+ virtual LocationSummary* MakeLocationSummary() const; \
+ virtual void EmitNativeCode(FlowGraphCompiler* compiler);
- private:
- const intptr_t offset_in_bytes_;
- const AbstractType& type_;
- intptr_t result_cid_;
- DISALLOW_COPY_AND_ASSIGN(LoadVMFieldComp);
-};
+// Function defined in all call computation classes.
+#define DECLARE_CALL_COMPUTATION(ShortName) \
+ virtual void Accept(FlowGraphVisitor* visitor, BindInstr* instr); \
+ virtual ComputationKind computation_kind() const { \
+ return Computation::k##ShortName; \
+ } \
+ virtual const char* DebugName() const { return #ShortName; } \
+ virtual RawAbstractType* CompileType() const; \
+ virtual LocationSummary* MakeLocationSummary() const; \
+ virtual void EmitNativeCode(FlowGraphCompiler* compiler);
-class StoreVMFieldComp : public TemplateComputation<2> {
+class ConstantComp : public TemplateComputation<0> {
public:
- StoreVMFieldComp(Value* dest,
- intptr_t offset_in_bytes,
- Value* value,
- const AbstractType& type)
- : offset_in_bytes_(offset_in_bytes), type_(type) {
- ASSERT(value != NULL);
- ASSERT(dest != NULL);
- ASSERT(type.IsZoneHandle()); // May be null if field is not an instance.
- inputs_[0] = value;
- inputs_[1] = dest;
- }
+ explicit ConstantComp(const Object& value) : value_(value) { }
- DECLARE_COMPUTATION(StoreVMField)
+ DECLARE_COMPUTATION(Constant)
- Value* value() const { return inputs_[0]; }
- Value* dest() const { return inputs_[1]; }
- intptr_t offset_in_bytes() const { return offset_in_bytes_; }
- const AbstractType& type() const { return type_; }
+ const Object& value() const { return value_; }
virtual void PrintOperandsTo(BufferFormatter* f) const;
virtual bool CanDeoptimize() const { return false; }
- virtual intptr_t ResultCid() const { return kDynamicCid; }
+
+ virtual intptr_t ResultCid() const;
+
+ virtual bool AttributesEqual(Computation* other) const;
private:
- const intptr_t offset_in_bytes_;
- const AbstractType& type_;
+ const Object& value_;
- DISALLOW_COPY_AND_ASSIGN(StoreVMFieldComp);
+ DISALLOW_COPY_AND_ASSIGN(ConstantComp);
};
-class InstantiateTypeArgumentsComp : public TemplateComputation<1> {
+class AssertAssignableComp : public TemplateComputation<3> {
public:
- InstantiateTypeArgumentsComp(intptr_t token_pos,
- const AbstractTypeArguments& type_arguments,
- Value* instantiator)
- : token_pos_(token_pos),
- type_arguments_(type_arguments) {
- ASSERT(type_arguments.IsZoneHandle());
+ AssertAssignableComp(intptr_t token_pos,
+ Value* value,
+ Value* instantiator,
+ Value* instantiator_type_arguments,
+ const AbstractType& dst_type,
+ const String& dst_name)
+ : token_pos_(token_pos),
+ dst_type_(dst_type),
+ dst_name_(dst_name),
+ is_eliminated_(false) {
+ ASSERT(value != NULL);
ASSERT(instantiator != NULL);
- inputs_[0] = instantiator;
+ ASSERT(instantiator_type_arguments != NULL);
+ ASSERT(!dst_type.IsNull());
+ ASSERT(!dst_name.IsNull());
+ inputs_[0] = value;
+ inputs_[1] = instantiator;
+ inputs_[2] = instantiator_type_arguments;
}
- DECLARE_COMPUTATION(InstantiateTypeArguments)
+ DECLARE_COMPUTATION(AssertAssignable)
+
+ Value* value() const { return inputs_[0]; }
+ Value* instantiator() const { return inputs_[1]; }
+ Value* instantiator_type_arguments() const { return inputs_[2]; }
- Value* instantiator() const { return inputs_[0]; }
- const AbstractTypeArguments& type_arguments() const {
- return type_arguments_;
- }
intptr_t token_pos() const { return token_pos_; }
+ const AbstractType& dst_type() const { return dst_type_; }
+ const String& dst_name() const { return dst_name_; }
+
+ bool is_eliminated() const {
+ return is_eliminated_;
+ }
+ void eliminate() {
+ ASSERT(!is_eliminated_);
+ is_eliminated_ = true;
+ }
virtual void PrintOperandsTo(BufferFormatter* f) const;
@@ -1496,1782 +1613,1716 @@ class InstantiateTypeArgumentsComp : public TemplateComputation<1> {
private:
const intptr_t token_pos_;
- const AbstractTypeArguments& type_arguments_;
+ const AbstractType& dst_type_;
+ const String& dst_name_;
+ bool is_eliminated_;
- DISALLOW_COPY_AND_ASSIGN(InstantiateTypeArgumentsComp);
+ DISALLOW_COPY_AND_ASSIGN(AssertAssignableComp);
};
-class ExtractConstructorTypeArgumentsComp : public TemplateComputation<1> {
+class AssertBooleanComp : public TemplateComputation<1> {
public:
- ExtractConstructorTypeArgumentsComp(
- intptr_t token_pos,
- const AbstractTypeArguments& type_arguments,
- Value* instantiator)
+ AssertBooleanComp(intptr_t token_pos,
+ Value* value)
: token_pos_(token_pos),
- type_arguments_(type_arguments) {
- ASSERT(instantiator != NULL);
- inputs_[0] = instantiator;
+ is_eliminated_(false) {
+ ASSERT(value != NULL);
+ inputs_[0] = value;
}
- DECLARE_COMPUTATION(ExtractConstructorTypeArguments)
+ DECLARE_COMPUTATION(AssertBoolean)
- Value* instantiator() const { return inputs_[0]; }
- const AbstractTypeArguments& type_arguments() const {
- return type_arguments_;
- }
intptr_t token_pos() const { return token_pos_; }
+ Value* value() const { return inputs_[0]; }
+
+ bool is_eliminated() const {
+ return is_eliminated_;
+ }
+ void eliminate() {
+ ASSERT(!is_eliminated_);
+ is_eliminated_ = true;
+ }
virtual void PrintOperandsTo(BufferFormatter* f) const;
virtual bool CanDeoptimize() const { return false; }
- virtual intptr_t ResultCid() const { return kDynamicCid; }
+ virtual intptr_t ResultCid() const { return kBoolCid; }
private:
const intptr_t token_pos_;
- const AbstractTypeArguments& type_arguments_;
+ bool is_eliminated_;
- DISALLOW_COPY_AND_ASSIGN(ExtractConstructorTypeArgumentsComp);
+ DISALLOW_COPY_AND_ASSIGN(AssertBooleanComp);
};
-class ExtractConstructorInstantiatorComp : public TemplateComputation<1> {
+class ArgumentDefinitionTestComp : public TemplateComputation<1> {
public:
- ExtractConstructorInstantiatorComp(ConstructorCallNode* ast_node,
- Value* instantiator)
- : ast_node_(*ast_node) {
- ASSERT(instantiator != NULL);
- inputs_[0] = instantiator;
+ ArgumentDefinitionTestComp(ArgumentDefinitionTestNode* node,
+ Value* saved_arguments_descriptor)
+ : ast_node_(*node) {
+ ASSERT(saved_arguments_descriptor != NULL);
+ inputs_[0] = saved_arguments_descriptor;
}
- DECLARE_COMPUTATION(ExtractConstructorInstantiator)
+ DECLARE_COMPUTATION(ArgumentDefinitionTest)
- Value* instantiator() const { return inputs_[0]; }
- const AbstractTypeArguments& type_arguments() const {
- return ast_node_.type_arguments();
- }
- const Function& constructor() const { return ast_node_.constructor(); }
intptr_t token_pos() const { return ast_node_.token_pos(); }
+ intptr_t formal_parameter_index() const {
+ return ast_node_.formal_parameter_index();
+ }
+ const String& formal_parameter_name() const {
+ return ast_node_.formal_parameter_name();
+ }
+ Value* saved_arguments_descriptor() const { return inputs_[0]; }
+
+ virtual void PrintOperandsTo(BufferFormatter* f) const;
virtual bool CanDeoptimize() const { return false; }
- virtual intptr_t ResultCid() const { return kDynamicCid; }
+ virtual intptr_t ResultCid() const { return kBoolCid; }
private:
- const ConstructorCallNode& ast_node_;
+ const ArgumentDefinitionTestNode& ast_node_;
- DISALLOW_COPY_AND_ASSIGN(ExtractConstructorInstantiatorComp);
+ DISALLOW_COPY_AND_ASSIGN(ArgumentDefinitionTestComp);
};
-class AllocateContextComp : public TemplateComputation<0> {
+// Denotes the current context, normally held in a register. This is
+// a computation, not a value, because it's mutable.
+class CurrentContextComp : public TemplateComputation<0> {
public:
- AllocateContextComp(intptr_t token_pos,
- intptr_t num_context_variables)
- : token_pos_(token_pos),
- num_context_variables_(num_context_variables) {}
-
- DECLARE_COMPUTATION(AllocateContext);
-
- intptr_t token_pos() const { return token_pos_; }
- intptr_t num_context_variables() const { return num_context_variables_; }
+ CurrentContextComp() { }
- virtual void PrintOperandsTo(BufferFormatter* f) const;
+ DECLARE_COMPUTATION(CurrentContext)
virtual bool CanDeoptimize() const { return false; }
virtual intptr_t ResultCid() const { return kDynamicCid; }
private:
- const intptr_t token_pos_;
- const intptr_t num_context_variables_;
-
- DISALLOW_COPY_AND_ASSIGN(AllocateContextComp);
+ DISALLOW_COPY_AND_ASSIGN(CurrentContextComp);
};
-class ChainContextComp : public TemplateComputation<1> {
+class StoreContextComp : public TemplateComputation<1> {
public:
- explicit ChainContextComp(Value* context_value) {
- ASSERT(context_value != NULL);
- inputs_[0] = context_value;
+ explicit StoreContextComp(Value* value) {
+ ASSERT(value != NULL);
+ inputs_[0] = value;
}
- DECLARE_COMPUTATION(ChainContext)
+ DECLARE_COMPUTATION(StoreContext);
- Value* context_value() const { return inputs_[0]; }
+ Value* value() const { return inputs_[0]; }
virtual bool CanDeoptimize() const { return false; }
virtual intptr_t ResultCid() const { return kIllegalCid; }
private:
- DISALLOW_COPY_AND_ASSIGN(ChainContextComp);
+ DISALLOW_COPY_AND_ASSIGN(StoreContextComp);
};
-class CloneContextComp : public TemplateComputation<1> {
+class ClosureCallComp : public TemplateComputation<0> {
public:
- CloneContextComp(intptr_t token_pos,
- Value* context_value)
- : token_pos_(token_pos) {
- ASSERT(context_value != NULL);
- inputs_[0] = context_value;
- }
+ ClosureCallComp(ClosureCallNode* node,
+ ZoneGrowableArray<PushArgumentInstr*>* arguments)
+ : ast_node_(*node),
+ arguments_(arguments) { }
- intptr_t token_pos() const { return token_pos_; }
- Value* context_value() const { return inputs_[0]; }
+ DECLARE_CALL_COMPUTATION(ClosureCall)
- DECLARE_COMPUTATION(CloneContext)
+ const Array& argument_names() const { return ast_node_.arguments()->names(); }
+ intptr_t token_pos() const { return ast_node_.token_pos(); }
- virtual bool CanDeoptimize() const { return false; }
- virtual intptr_t ResultCid() const { return kIllegalCid; }
+ virtual intptr_t ArgumentCount() const { return arguments_->length(); }
+ PushArgumentInstr* ArgumentAt(intptr_t index) const {
+ return (*arguments_)[index];
+ }
+
+ virtual void PrintOperandsTo(BufferFormatter* f) const;
+
+ virtual bool CanDeoptimize() const { return true; }
+ virtual intptr_t ResultCid() const { return kDynamicCid; }
private:
- const intptr_t token_pos_;
+ const ClosureCallNode& ast_node_;
+ ZoneGrowableArray<PushArgumentInstr*>* arguments_;
- DISALLOW_COPY_AND_ASSIGN(CloneContextComp);
+ DISALLOW_COPY_AND_ASSIGN(ClosureCallComp);
};
-class CatchEntryComp : public TemplateComputation<0> {
+class InstanceCallComp : public TemplateComputation<0> {
public:
- CatchEntryComp(const LocalVariable& exception_var,
- const LocalVariable& stacktrace_var)
- : exception_var_(exception_var), stacktrace_var_(stacktrace_var) {}
+ InstanceCallComp(intptr_t token_pos,
+ const String& function_name,
+ Token::Kind token_kind,
+ ZoneGrowableArray<PushArgumentInstr*>* arguments,
+ const Array& argument_names,
+ intptr_t checked_argument_count)
+ : ic_data_(Isolate::Current()->GetICDataForDeoptId(deopt_id())),
+ token_pos_(token_pos),
+ function_name_(function_name),
+ token_kind_(token_kind),
+ arguments_(arguments),
+ argument_names_(argument_names),
+ checked_argument_count_(checked_argument_count) {
+ ASSERT(function_name.IsZoneHandle());
+ ASSERT(!arguments->is_empty());
+ ASSERT(argument_names.IsZoneHandle());
+ ASSERT(Token::IsBinaryToken(token_kind) ||
+ Token::IsUnaryToken(token_kind) ||
+ Token::IsIndexOperator(token_kind) ||
+ token_kind == Token::kGET ||
+ token_kind == Token::kSET ||
+ token_kind == Token::kILLEGAL);
+ }
- const LocalVariable& exception_var() const { return exception_var_; }
- const LocalVariable& stacktrace_var() const { return stacktrace_var_; }
+ DECLARE_CALL_COMPUTATION(InstanceCall)
- DECLARE_COMPUTATION(CatchEntry)
+ const ICData* ic_data() const { return ic_data_; }
+ bool HasICData() const {
+ return (ic_data() != NULL) && !ic_data()->IsNull();
+ }
+
+ intptr_t token_pos() const { return token_pos_; }
+ const String& function_name() const { return function_name_; }
+ Token::Kind token_kind() const { return token_kind_; }
+ virtual intptr_t ArgumentCount() const { return arguments_->length(); }
+ PushArgumentInstr* ArgumentAt(intptr_t index) const {
+ return (*arguments_)[index];
+ }
+ const Array& argument_names() const { return argument_names_; }
+ intptr_t checked_argument_count() const { return checked_argument_count_; }
virtual void PrintOperandsTo(BufferFormatter* f) const;
- virtual bool CanDeoptimize() const { return false; }
- virtual intptr_t ResultCid() const { return kIllegalCid; }
+ virtual bool CanDeoptimize() const { return true; }
+ virtual intptr_t ResultCid() const { return kDynamicCid; }
private:
- const LocalVariable& exception_var_;
- const LocalVariable& stacktrace_var_;
+ const ICData* ic_data_;
+ const intptr_t token_pos_;
+ const String& function_name_;
+ const Token::Kind token_kind_; // Binary op, unary op, kGET or kILLEGAL.
+ ZoneGrowableArray<PushArgumentInstr*>* const arguments_;
+ const Array& argument_names_;
+ const intptr_t checked_argument_count_;
- DISALLOW_COPY_AND_ASSIGN(CatchEntryComp);
+ DISALLOW_COPY_AND_ASSIGN(InstanceCallComp);
};
-class CheckEitherNonSmiComp : public TemplateComputation<2> {
+class PolymorphicInstanceCallComp : public TemplateComputation<0> {
public:
- CheckEitherNonSmiComp(Value* left,
- Value* right,
- InstanceCallComp* instance_call)
- : instance_call_(instance_call) {
- ASSERT(left != NULL);
- ASSERT(right != NULL);
- inputs_[0] = left;
- inputs_[1] = right;
- }
-
- DECLARE_COMPUTATION(CheckEitherNonSmi)
+ PolymorphicInstanceCallComp(InstanceCallComp* comp,
+ const ICData& ic_data,
+ bool with_checks)
+ : instance_call_(comp), ic_data_(ic_data), with_checks_(with_checks) {
+ ASSERT(instance_call_ != NULL);
+ }
- virtual bool CanDeoptimize() const { return true; }
- virtual intptr_t ResultCid() const { return kIllegalCid; }
+ InstanceCallComp* instance_call() const { return instance_call_; }
+ bool with_checks() const { return with_checks_; }
- virtual bool AttributesEqual(Computation* other) const { return true; }
+ void PrintTo(BufferFormatter* f) const;
- virtual bool HasSideEffect() const { return false; }
+ virtual intptr_t ArgumentCount() const {
+ return instance_call()->ArgumentCount();
+ }
- Value* left() const { return inputs_[0]; }
+ DECLARE_CALL_COMPUTATION(PolymorphicInstanceCall)
- Value* right() const { return inputs_[1]; }
+ const ICData& ic_data() const { return ic_data_; }
- virtual Definition* TryReplace(BindInstr* instr) const;
+ virtual bool CanDeoptimize() const { return true; }
+ virtual intptr_t ResultCid() const { return kDynamicCid; }
private:
InstanceCallComp* instance_call_;
+ const ICData& ic_data_;
+ const bool with_checks_;
- DISALLOW_COPY_AND_ASSIGN(CheckEitherNonSmiComp);
+ DISALLOW_COPY_AND_ASSIGN(PolymorphicInstanceCallComp);
};
-class BoxDoubleComp : public TemplateComputation<1> {
+class ComparisonComp : public TemplateComputation<2> {
public:
- BoxDoubleComp(Value* value, InstanceCallComp* instance_call)
- : token_pos_((instance_call != NULL) ? instance_call->token_pos() : 0) {
- ASSERT(value != NULL);
- inputs_[0] = value;
+ ComparisonComp(Token::Kind kind, Value* left, Value* right) : kind_(kind) {
+ ASSERT(left != NULL);
+ ASSERT(right != NULL);
+ inputs_[0] = left;
+ inputs_[1] = right;
}
- Value* value() const { return inputs_[0]; }
+ Value* left() const { return inputs_[0]; }
+ Value* right() const { return inputs_[1]; }
- intptr_t token_pos() const { return token_pos_; }
+ virtual ComparisonComp* AsComparison() { return this; }
- virtual bool CanDeoptimize() const { return false; }
- virtual bool HasSideEffect() const { return false; }
- virtual bool AttributesEqual(Computation* other) const { return true; }
+ Token::Kind kind() const { return kind_; }
- virtual intptr_t ResultCid() const;
+ private:
+ Token::Kind kind_;
+};
- virtual Representation RequiredInputRepresentation(intptr_t idx) const {
- ASSERT(idx == 0);
- return kUnboxedDouble;
- }
- DECLARE_COMPUTATION(BoxDouble)
+// Inlined functions from class BranchInstr that forward to their comparison.
+inline intptr_t BranchInstr::ArgumentCount() const {
+ return computation()->ArgumentCount();
+}
- private:
- const intptr_t token_pos_;
- DISALLOW_COPY_AND_ASSIGN(BoxDoubleComp);
-};
+inline intptr_t BranchInstr::InputCount() const {
+ return computation()->InputCount();
+}
-class UnboxDoubleComp : public TemplateComputation<1> {
- public:
- UnboxDoubleComp(Value* value, intptr_t deopt_id)
- : deopt_id_(deopt_id) {
- ASSERT(value != NULL);
- inputs_[0] = value;
- }
+inline Value* BranchInstr::InputAt(intptr_t i) const {
+ return computation()->InputAt(i);
+}
- Value* value() const { return inputs_[0]; }
- virtual bool CanDeoptimize() const {
- return value()->ResultCid() != kDoubleCid;
- }
+inline void BranchInstr::SetInputAt(intptr_t i, Value* value) {
+ computation()->SetInputAt(i, value);
+}
- // The output is not an instance but when it is boxed it becomes double.
- virtual intptr_t ResultCid() const { return kDoubleCid; }
- virtual Representation representation() const {
- return kUnboxedDouble;
+inline bool BranchInstr::CanDeoptimize() const {
+ return computation()->CanDeoptimize();
+}
+
+
+inline LocationSummary* BranchInstr::locs() {
+ if (computation_->locs_ == NULL) {
+ LocationSummary* summary = computation_->MakeLocationSummary();
+ // Branches don't produce a result.
+ summary->set_out(Location::NoLocation());
+ computation_->locs_ = summary;
}
+ return computation_->locs_;
+}
- virtual bool HasSideEffect() const { return false; }
- virtual bool AttributesEqual(Computation* other) const { return true; }
- DECLARE_COMPUTATION(UnboxDouble)
+inline intptr_t BranchInstr::DeoptimizationTarget() const {
+ return computation_->DeoptimizationTarget();
+}
- private:
- const intptr_t deopt_id_;
- DISALLOW_COPY_AND_ASSIGN(UnboxDoubleComp);
-};
+inline Representation BranchInstr::RequiredInputRepresentation(
+ intptr_t i) const {
+ return computation()->RequiredInputRepresentation(i);
+}
-class UnboxedDoubleBinaryOpComp : public TemplateComputation<2> {
+class StrictCompareComp : public ComparisonComp {
public:
- UnboxedDoubleBinaryOpComp(Token::Kind op_kind,
- Value* left,
- Value* right,
- InstanceCallComp* call)
- : op_kind_(op_kind), deopt_id_(call->deopt_id()) {
- ASSERT(left != NULL);
- ASSERT(right != NULL);
- inputs_[0] = left;
- inputs_[1] = right;
+ StrictCompareComp(Token::Kind kind, Value* left, Value* right)
+ : ComparisonComp(kind, left, right) {
+ ASSERT((kind == Token::kEQ_STRICT) || (kind == Token::kNE_STRICT));
}
- Value* left() const { return inputs_[0]; }
- Value* right() const { return inputs_[1]; }
-
- Token::Kind op_kind() const { return op_kind_; }
+ DECLARE_COMPUTATION(StrictCompare)
virtual void PrintOperandsTo(BufferFormatter* f) const;
virtual bool CanDeoptimize() const { return false; }
- virtual bool HasSideEffect() const { return false; }
-
- virtual bool AttributesEqual(Computation* other) const {
- return op_kind() == other->AsUnboxedDoubleBinaryOp()->op_kind();
- }
-
- // The output is not an instance but when it is boxed it becomes double.
- virtual intptr_t ResultCid() const { return kDoubleCid; }
- virtual Representation representation() const {
- return kUnboxedDouble;
- }
-
- virtual Representation RequiredInputRepresentation(intptr_t idx) const {
- ASSERT((idx == 0) || (idx == 1));
- return kUnboxedDouble;
- }
+ virtual Definition* TryReplace(BindInstr* instr) const;
- virtual intptr_t DeoptimizationTarget() const {
- return deopt_id_;
- }
+ virtual intptr_t ResultCid() const { return kBoolCid; }
- DECLARE_COMPUTATION(UnboxedDoubleBinaryOp)
+ virtual void EmitBranchCode(FlowGraphCompiler* compiler,
+ BranchInstr* branch);
private:
- const Token::Kind op_kind_;
- const intptr_t deopt_id_;
-
- DISALLOW_COPY_AND_ASSIGN(UnboxedDoubleBinaryOpComp);
+ DISALLOW_COPY_AND_ASSIGN(StrictCompareComp);
};
-class BinarySmiOpComp : public TemplateComputation<2> {
+class EqualityCompareComp : public ComparisonComp {
public:
- BinarySmiOpComp(Token::Kind op_kind,
- InstanceCallComp* instance_call,
- Value* left,
- Value* right)
- : op_kind_(op_kind),
- instance_call_(instance_call) {
- ASSERT(left != NULL);
- ASSERT(right != NULL);
- inputs_[0] = left;
- inputs_[1] = right;
+ EqualityCompareComp(intptr_t token_pos,
+ Token::Kind kind,
+ Value* left,
+ Value* right)
+ : ComparisonComp(kind, left, right),
+ ic_data_(Isolate::Current()->GetICDataForDeoptId(deopt_id())),
+ token_pos_(token_pos),
+ receiver_class_id_(kIllegalCid) {
+ ASSERT((kind == Token::kEQ) || (kind == Token::kNE));
}
- Value* left() const { return inputs_[0]; }
- Value* right() const { return inputs_[1]; }
+ DECLARE_COMPUTATION(EqualityCompare)
- Token::Kind op_kind() const { return op_kind_; }
+ const ICData* ic_data() const { return ic_data_; }
+ bool HasICData() const {
+ return (ic_data() != NULL) && !ic_data()->IsNull();
+ }
- InstanceCallComp* instance_call() const { return instance_call_; }
+ intptr_t token_pos() const { return token_pos_; }
- const ICData* ic_data() const { return instance_call()->ic_data(); }
+ // Receiver class id is computed from collected ICData.
+ void set_receiver_class_id(intptr_t value) { receiver_class_id_ = value; }
+ intptr_t receiver_class_id() const { return receiver_class_id_; }
virtual void PrintOperandsTo(BufferFormatter* f) const;
- DECLARE_COMPUTATION(BinarySmiOp)
-
- virtual bool CanDeoptimize() const;
+ virtual bool CanDeoptimize() const {
+ return (receiver_class_id() != kDoubleCid);
+ }
virtual intptr_t ResultCid() const;
+ virtual void EmitBranchCode(FlowGraphCompiler* compiler,
+ BranchInstr* branch);
+
+ virtual intptr_t DeoptimizationTarget() const {
+ return GetDeoptId();
+ }
+
+ virtual Representation RequiredInputRepresentation(intptr_t idx) const {
+ ASSERT((idx == 0) || (idx == 1));
+ return (receiver_class_id() == kDoubleCid) ? kUnboxedDouble : kTagged;
+ }
+
private:
- const Token::Kind op_kind_;
- InstanceCallComp* instance_call_;
+ const ICData* ic_data_;
+ const intptr_t token_pos_;
+ intptr_t receiver_class_id_; // Set by optimizer.
- DISALLOW_COPY_AND_ASSIGN(BinarySmiOpComp);
+ DISALLOW_COPY_AND_ASSIGN(EqualityCompareComp);
};
-class BinaryMintOpComp : public TemplateComputation<2> {
+class RelationalOpComp : public ComparisonComp {
public:
- BinaryMintOpComp(Token::Kind op_kind,
- InstanceCallComp* instance_call,
+ RelationalOpComp(intptr_t token_pos,
+ Token::Kind kind,
Value* left,
Value* right)
- : op_kind_(op_kind),
- instance_call_(instance_call) {
- ASSERT(left != NULL);
- ASSERT(right != NULL);
- inputs_[0] = left;
- inputs_[1] = right;
+ : ComparisonComp(kind, left, right),
+ ic_data_(Isolate::Current()->GetICDataForDeoptId(deopt_id())),
+ token_pos_(token_pos),
+ operands_class_id_(kIllegalCid) {
+ ASSERT(Token::IsRelationalOperator(kind));
}
- Value* left() const { return inputs_[0]; }
- Value* right() const { return inputs_[1]; }
+ DECLARE_COMPUTATION(RelationalOp)
- Token::Kind op_kind() const { return op_kind_; }
+ const ICData* ic_data() const { return ic_data_; }
+ bool HasICData() const {
+ return (ic_data() != NULL) && !ic_data()->IsNull();
+ }
- InstanceCallComp* instance_call() const { return instance_call_; }
+ intptr_t token_pos() const { return token_pos_; }
- const ICData* ic_data() const { return instance_call()->ic_data(); }
+ // TODO(srdjan): instead of class-id pass an enum that can differentiate
+ // between boxed and unboxed doubles and integers.
+ void set_operands_class_id(intptr_t value) {
+ operands_class_id_ = value;
+ }
+
+ intptr_t operands_class_id() const { return operands_class_id_; }
virtual void PrintOperandsTo(BufferFormatter* f) const;
- DECLARE_COMPUTATION(BinaryMintOp)
+ virtual bool CanDeoptimize() const {
+ return operands_class_id() != kDoubleCid;
+ }
- virtual bool CanDeoptimize() const { return true; }
virtual intptr_t ResultCid() const;
- private:
- const Token::Kind op_kind_;
- InstanceCallComp* instance_call_;
-
- DISALLOW_COPY_AND_ASSIGN(BinaryMintOpComp);
-};
+ virtual void EmitBranchCode(FlowGraphCompiler* compiler,
+ BranchInstr* branch);
-class BinaryDoubleOpComp : public TemplateComputation<0> {
- public:
- BinaryDoubleOpComp(Token::Kind op_kind, InstanceCallComp* instance_call)
- : op_kind_(op_kind), instance_call_(instance_call) { }
+ virtual intptr_t DeoptimizationTarget() const {
+ return GetDeoptId();
+ }
- Token::Kind op_kind() const { return op_kind_; }
+ virtual Representation RequiredInputRepresentation(intptr_t idx) const {
+ ASSERT((idx == 0) || (idx == 1));
+ return (operands_class_id() == kDoubleCid) ? kUnboxedDouble : kTagged;
+ }
- InstanceCallComp* instance_call() const { return instance_call_; }
+ private:
+ const ICData* ic_data_;
+ const intptr_t token_pos_;
+ intptr_t operands_class_id_; // class id of both operands.
- const ICData* ic_data() const { return instance_call()->ic_data(); }
+ DISALLOW_COPY_AND_ASSIGN(RelationalOpComp);
+};
- virtual void PrintOperandsTo(BufferFormatter* f) const;
- DECLARE_CALL_COMPUTATION(BinaryDoubleOp)
+class StaticCallComp : public TemplateComputation<0> {
+ public:
+ StaticCallComp(intptr_t token_pos,
+ const Function& function,
+ const Array& argument_names,
+ ZoneGrowableArray<PushArgumentInstr*>* arguments)
+ : token_pos_(token_pos),
+ function_(function),
+ argument_names_(argument_names),
+ arguments_(arguments),
+ recognized_(MethodRecognizer::kUnknown) {
+ ASSERT(function.IsZoneHandle());
+ ASSERT(argument_names.IsZoneHandle());
+ }
- virtual intptr_t ArgumentCount() const { return 2; }
+ DECLARE_CALL_COMPUTATION(StaticCall)
+
+ // Accessors forwarded to the AST node.
+ const Function& function() const { return function_; }
+ const Array& argument_names() const { return argument_names_; }
+ intptr_t token_pos() const { return token_pos_; }
+
+ virtual intptr_t ArgumentCount() const { return arguments_->length(); }
+ PushArgumentInstr* ArgumentAt(intptr_t index) const {
+ return (*arguments_)[index];
+ }
+
+ MethodRecognizer::Kind recognized() const { return recognized_; }
+ void set_recognized(MethodRecognizer::Kind kind) { recognized_ = kind; }
+
+ virtual void PrintOperandsTo(BufferFormatter* f) const;
virtual bool CanDeoptimize() const { return true; }
- virtual intptr_t ResultCid() const;
+ virtual intptr_t ResultCid() const { return kDynamicCid; }
private:
- const Token::Kind op_kind_;
- InstanceCallComp* instance_call_;
+ const intptr_t token_pos_;
+ const Function& function_;
+ const Array& argument_names_;
+ ZoneGrowableArray<PushArgumentInstr*>* arguments_;
+ MethodRecognizer::Kind recognized_;
- DISALLOW_COPY_AND_ASSIGN(BinaryDoubleOpComp);
+ DISALLOW_COPY_AND_ASSIGN(StaticCallComp);
};
-// Handles both Smi operations: BIT_OR and NEGATE.
-class UnarySmiOpComp : public TemplateComputation<1> {
+class LoadLocalComp : public TemplateComputation<0> {
public:
- UnarySmiOpComp(Token::Kind op_kind,
- InstanceCallComp* instance_call,
- Value* value)
- : op_kind_(op_kind), instance_call_(instance_call) {
- ASSERT((op_kind == Token::kNEGATE) || (op_kind == Token::kBIT_NOT));
- ASSERT(value != NULL);
- inputs_[0] = value;
- }
+ LoadLocalComp(const LocalVariable& local, intptr_t context_level)
+ : local_(local),
+ context_level_(context_level) { }
- Value* value() const { return inputs_[0]; }
- Token::Kind op_kind() const { return op_kind_; }
+ DECLARE_COMPUTATION(LoadLocal)
- InstanceCallComp* instance_call() const { return instance_call_; }
+ const LocalVariable& local() const { return local_; }
+ intptr_t context_level() const { return context_level_; }
virtual void PrintOperandsTo(BufferFormatter* f) const;
- DECLARE_COMPUTATION(UnarySmiOp)
-
- virtual bool CanDeoptimize() const { return op_kind() == Token::kNEGATE; }
- virtual intptr_t ResultCid() const { return kSmiCid; }
+ virtual bool CanDeoptimize() const { return false; }
+ virtual intptr_t ResultCid() const { return kDynamicCid; }
private:
- const Token::Kind op_kind_;
- InstanceCallComp* instance_call_;
+ const LocalVariable& local_;
+ const intptr_t context_level_;
- DISALLOW_COPY_AND_ASSIGN(UnarySmiOpComp);
+ DISALLOW_COPY_AND_ASSIGN(LoadLocalComp);
};
-// Handles non-Smi NEGATE operations
-class NumberNegateComp : public TemplateComputation<1> {
+class StoreLocalComp : public TemplateComputation<1> {
public:
- NumberNegateComp(InstanceCallComp* instance_call,
- Value* value) : instance_call_(instance_call) {
+ StoreLocalComp(const LocalVariable& local,
+ Value* value,
+ intptr_t context_level)
+ : local_(local),
+ context_level_(context_level) {
ASSERT(value != NULL);
inputs_[0] = value;
}
- Value* value() const { return inputs_[0]; }
+ DECLARE_COMPUTATION(StoreLocal)
- InstanceCallComp* instance_call() const { return instance_call_; }
+ const LocalVariable& local() const { return local_; }
+ Value* value() const { return inputs_[0]; }
+ intptr_t context_level() const { return context_level_; }
- const ICData* ic_data() const { return instance_call()->ic_data(); }
+ virtual void RecordAssignedVars(BitVector* assigned_vars,
+ intptr_t fixed_parameter_count);
- DECLARE_COMPUTATION(NumberNegate)
+ virtual void PrintOperandsTo(BufferFormatter* f) const;
- virtual bool CanDeoptimize() const { return true; }
- virtual intptr_t ResultCid() const { return kDoubleCid; }
+ virtual bool CanDeoptimize() const { return false; }
+ virtual intptr_t ResultCid() const { return kDynamicCid; }
private:
- InstanceCallComp* instance_call_;
+ const LocalVariable& local_;
+ const intptr_t context_level_;
- DISALLOW_COPY_AND_ASSIGN(NumberNegateComp);
+ DISALLOW_COPY_AND_ASSIGN(StoreLocalComp);
};
-class CheckStackOverflowComp : public TemplateComputation<0> {
+class NativeCallComp : public TemplateComputation<0> {
public:
- explicit CheckStackOverflowComp(intptr_t token_pos)
- : token_pos_(token_pos) {}
-
- intptr_t token_pos() const { return token_pos_; }
+ explicit NativeCallComp(NativeBodyNode* node)
+ : ast_node_(*node) {}
- DECLARE_COMPUTATION(CheckStackOverflow)
+ DECLARE_COMPUTATION(NativeCall)
- virtual bool CanDeoptimize() const { return false; }
- virtual intptr_t ResultCid() const { return kIllegalCid; }
+ intptr_t token_pos() const { return ast_node_.token_pos(); }
- private:
- const intptr_t token_pos_;
+ const String& native_name() const {
+ return ast_node_.native_c_function_name();
+ }
- DISALLOW_COPY_AND_ASSIGN(CheckStackOverflowComp);
-};
+ NativeFunction native_c_function() const {
+ return ast_node_.native_c_function();
+ }
+ intptr_t argument_count() const { return ast_node_.argument_count(); }
-class DoubleToDoubleComp : public TemplateComputation<1> {
- public:
- DoubleToDoubleComp(Value* value, InstanceCallComp* instance_call)
- : instance_call_(instance_call) {
- ASSERT(value != NULL);
- inputs_[0] = value;
+ bool has_optional_parameters() const {
+ return ast_node_.has_optional_parameters();
}
- Value* value() const { return inputs_[0]; }
-
- InstanceCallComp* instance_call() const { return instance_call_; }
+ bool is_native_instance_closure() const {
+ return ast_node_.is_native_instance_closure();
+ }
- DECLARE_COMPUTATION(DoubleToDouble)
+ virtual void PrintOperandsTo(BufferFormatter* f) const;
- virtual bool CanDeoptimize() const { return true; }
- virtual intptr_t ResultCid() const { return kDoubleCid; }
+ virtual bool CanDeoptimize() const { return false; }
+ virtual intptr_t ResultCid() const { return kDynamicCid; }
private:
- InstanceCallComp* instance_call_;
+ const NativeBodyNode& ast_node_;
- DISALLOW_COPY_AND_ASSIGN(DoubleToDoubleComp);
+ DISALLOW_COPY_AND_ASSIGN(NativeCallComp);
};
-class SmiToDoubleComp : public TemplateComputation<0> {
+class LoadInstanceFieldComp : public TemplateComputation<1> {
public:
- explicit SmiToDoubleComp(InstanceCallComp* instance_call)
- : instance_call_(instance_call) { }
+ LoadInstanceFieldComp(const Field& field, Value* instance) : field_(field) {
+ ASSERT(instance != NULL);
+ inputs_[0] = instance;
+ }
- InstanceCallComp* instance_call() const { return instance_call_; }
+ DECLARE_COMPUTATION(LoadInstanceField)
- DECLARE_CALL_COMPUTATION(SmiToDouble)
+ const Field& field() const { return field_; }
+ Value* instance() const { return inputs_[0]; }
- virtual intptr_t ArgumentCount() const { return 1; }
+ virtual void PrintOperandsTo(BufferFormatter* f) const;
- virtual bool CanDeoptimize() const { return true; }
- virtual intptr_t ResultCid() const { return kDoubleCid; }
+ virtual bool CanDeoptimize() const { return false; }
+ virtual intptr_t ResultCid() const { return kDynamicCid; }
private:
- InstanceCallComp* instance_call_;
+ const Field& field_;
- DISALLOW_COPY_AND_ASSIGN(SmiToDoubleComp);
+ DISALLOW_COPY_AND_ASSIGN(LoadInstanceFieldComp);
};
-class CheckClassComp : public TemplateComputation<1> {
+class StoreInstanceFieldComp : public TemplateComputation<2> {
public:
- CheckClassComp(Value* value,
- InstanceCallComp* instance_call,
- const ICData& unary_checks)
- : instance_call_(instance_call),
- unary_checks_(unary_checks) {
+ StoreInstanceFieldComp(const Field& field,
+ Value* instance,
+ Value* value)
+ : field_(field) {
+ ASSERT(instance != NULL);
ASSERT(value != NULL);
- inputs_[0] = value;
+ inputs_[0] = instance;
+ inputs_[1] = value;
}
- DECLARE_COMPUTATION(CheckClass)
+ DECLARE_COMPUTATION(StoreInstanceField)
- virtual bool CanDeoptimize() const { return true; }
- virtual intptr_t ResultCid() const { return kIllegalCid; }
+ const Field& field() const { return field_; }
- virtual bool AttributesEqual(Computation* other) const;
+ Value* instance() const { return inputs_[0]; }
+ Value* value() const { return inputs_[1]; }
- virtual bool HasSideEffect() const { return false; }
+ virtual void PrintOperandsTo(BufferFormatter* f) const;
- Value* value() const { return inputs_[0]; }
+ virtual bool CanDeoptimize() const { return false; }
+ virtual intptr_t ResultCid() const { return kDynamicCid; }
- const ICData& unary_checks() const { return unary_checks_; }
+ private:
+ const Field& field_;
- virtual intptr_t deopt_id() const { return instance_call_->deopt_id(); }
+ DISALLOW_COPY_AND_ASSIGN(StoreInstanceFieldComp);
+};
- virtual Definition* TryReplace(BindInstr* instr) const;
+
+class LoadStaticFieldComp : public TemplateComputation<0> {
+ public:
+ explicit LoadStaticFieldComp(const Field& field) : field_(field) {}
+
+ DECLARE_COMPUTATION(LoadStaticField);
+
+ const Field& field() const { return field_; }
virtual void PrintOperandsTo(BufferFormatter* f) const;
+ virtual bool CanDeoptimize() const { return false; }
+ virtual intptr_t ResultCid() const { return kDynamicCid; }
+
private:
- InstanceCallComp* instance_call_;
- const ICData& unary_checks_;
+ const Field& field_;
- DISALLOW_COPY_AND_ASSIGN(CheckClassComp);
+ DISALLOW_COPY_AND_ASSIGN(LoadStaticFieldComp);
};
-class CheckSmiComp : public TemplateComputation<1> {
+class StoreStaticFieldComp : public TemplateComputation<1> {
public:
- CheckSmiComp(Value* value, intptr_t original_deopt_id)
- : original_deopt_id_(original_deopt_id) {
+ StoreStaticFieldComp(const Field& field, Value* value)
+ : field_(field) {
+ ASSERT(field.IsZoneHandle());
ASSERT(value != NULL);
- ASSERT(original_deopt_id != Isolate::kNoDeoptId);
inputs_[0] = value;
}
- DECLARE_COMPUTATION(CheckSmi)
+ DECLARE_COMPUTATION(StoreStaticField);
- virtual bool CanDeoptimize() const { return true; }
- virtual intptr_t ResultCid() const { return kIllegalCid; }
+ const Field& field() const { return field_; }
+ Value* value() const { return inputs_[0]; }
- virtual bool AttributesEqual(Computation* other) const { return true; }
-
- virtual bool HasSideEffect() const { return false; }
-
- virtual Definition* TryReplace(BindInstr* instr) const;
-
- Value* value() const { return inputs_[0]; }
+ virtual void PrintOperandsTo(BufferFormatter* f) const;
- virtual intptr_t deopt_id() const { return original_deopt_id_; }
+ virtual bool CanDeoptimize() const { return false; }
+ virtual intptr_t ResultCid() const { return kDynamicCid; }
private:
- const intptr_t original_deopt_id_;
+ const Field& field_;
- DISALLOW_COPY_AND_ASSIGN(CheckSmiComp);
+ DISALLOW_COPY_AND_ASSIGN(StoreStaticFieldComp);
};
-class CheckArrayBoundComp : public TemplateComputation<2> {
+class LoadIndexedComp : public TemplateComputation<2> {
public:
- CheckArrayBoundComp(Value* array,
- Value* index,
- intptr_t array_type,
- InstanceCallComp* instance_call)
- : array_type_(array_type), instance_call_(instance_call) {
+ LoadIndexedComp(Value* array,
+ Value* index,
+ intptr_t receiver_type)
+ : receiver_type_(receiver_type) {
ASSERT(array != NULL);
ASSERT(index != NULL);
inputs_[0] = array;
inputs_[1] = index;
}
- DECLARE_COMPUTATION(CheckArrayBound)
-
- virtual bool CanDeoptimize() const { return true; }
- virtual intptr_t ResultCid() const { return kIllegalCid; }
-
- virtual bool AttributesEqual(Computation* other) const;
-
- virtual bool HasSideEffect() const { return false; }
+ DECLARE_COMPUTATION(LoadIndexed)
Value* array() const { return inputs_[0]; }
Value* index() const { return inputs_[1]; }
- intptr_t array_type() const { return array_type_; }
+ intptr_t receiver_type() const { return receiver_type_; }
- virtual intptr_t deopt_id() const { return instance_call_->deopt_id(); }
+ virtual bool CanDeoptimize() const { return false; }
+ virtual intptr_t ResultCid() const { return kDynamicCid; }
private:
- intptr_t array_type_;
- InstanceCallComp* instance_call_;
+ intptr_t receiver_type_;
- DISALLOW_COPY_AND_ASSIGN(CheckArrayBoundComp);
+ DISALLOW_COPY_AND_ASSIGN(LoadIndexedComp);
};
-#undef DECLARE_COMPUTATION
-
-
-// Implementation of type testers and cast functins.
-#define DEFINE_COMPUTATION_PREDICATE(ShortName, ClassName) \
-bool Computation::Is##ShortName() const { \
- return computation_kind() == k##ShortName; \
-} \
-const ClassName* Computation::As##ShortName() const { \
- if (!Is##ShortName()) return NULL; \
- return static_cast<const ClassName*>(this); \
-} \
-ClassName* Computation::As##ShortName() { \
- if (!Is##ShortName()) return NULL; \
- return static_cast<ClassName*>(this); \
-}
-FOR_EACH_COMPUTATION(DEFINE_COMPUTATION_PREDICATE)
-#undef DEFINE_COMPUTATION_PREDICATE
-
-// Instructions.
+class StoreIndexedComp : public TemplateComputation<3> {
+ public:
+ StoreIndexedComp(Value* array,
+ Value* index,
+ Value* value,
+ intptr_t receiver_type)
+ : receiver_type_(receiver_type) {
+ ASSERT(array != NULL);
+ ASSERT(index != NULL);
+ ASSERT(value != NULL);
+ inputs_[0] = array;
+ inputs_[1] = index;
+ inputs_[2] = value;
+ }
-// M is a single argument macro. It is applied to each concrete instruction
-// type name. The concrete instruction classes are the name with Instr
-// concatenated.
-#define FOR_EACH_INSTRUCTION(M) \
- M(GraphEntry) \
- M(JoinEntry) \
- M(TargetEntry) \
- M(Phi) \
- M(Bind) \
- M(Parameter) \
- M(ParallelMove) \
- M(PushArgument) \
- M(Return) \
- M(Throw) \
- M(ReThrow) \
- M(Goto) \
- M(Branch) \
+ DECLARE_COMPUTATION(StoreIndexed)
+ Value* array() const { return inputs_[0]; }
+ Value* index() const { return inputs_[1]; }
+ Value* value() const { return inputs_[2]; }
-// Forward declarations for Instruction classes.
-class BlockEntryInstr;
-class FlowGraphBuilder;
-class Environment;
+ intptr_t receiver_type() const { return receiver_type_; }
-#define FORWARD_DECLARATION(type) class type##Instr;
-FOR_EACH_INSTRUCTION(FORWARD_DECLARATION)
-#undef FORWARD_DECLARATION
+ virtual bool CanDeoptimize() const { return false; }
+ virtual intptr_t ResultCid() const { return kDynamicCid; }
+ private:
+ intptr_t receiver_type_;
-// Functions required in all concrete instruction classes.
-#define DECLARE_INSTRUCTION(type) \
- virtual void Accept(FlowGraphVisitor* visitor); \
- virtual bool Is##type() const { return true; } \
- virtual type##Instr* As##type() { return this; } \
- virtual const char* DebugName() const { return #type; } \
- virtual void PrintTo(BufferFormatter* f) const; \
- virtual void PrintToVisualizer(BufferFormatter* f) const;
+ DISALLOW_COPY_AND_ASSIGN(StoreIndexedComp);
+};
-class Instruction : public ZoneAllocated {
+// Note overrideable, built-in: value? false : true.
+class BooleanNegateComp : public TemplateComputation<1> {
public:
- Instruction()
- : lifetime_position_(-1), previous_(NULL), next_(NULL), env_(NULL) { }
-
- virtual bool IsBlockEntry() const { return false; }
- BlockEntryInstr* AsBlockEntry() {
- return IsBlockEntry() ? reinterpret_cast<BlockEntryInstr*>(this) : NULL;
+ explicit BooleanNegateComp(Value* value) {
+ ASSERT(value != NULL);
+ inputs_[0] = value;
}
- virtual bool IsDefinition() const { return false; }
- virtual Definition* AsDefinition() { return NULL; }
- virtual bool IsControl() const { return false; }
- virtual intptr_t InputCount() const = 0;
- virtual Value* InputAt(intptr_t i) const = 0;
- virtual void SetInputAt(intptr_t i, Value* value) = 0;
+ DECLARE_COMPUTATION(BooleanNegate)
- // Call instructions override this function and return the
- // number of pushed arguments.
- virtual intptr_t ArgumentCount() const = 0;
+ Value* value() const { return inputs_[0]; }
- // Returns true, if this instruction can deoptimize.
- virtual bool CanDeoptimize() const = 0;
+ virtual bool CanDeoptimize() const { return false; }
+ virtual intptr_t ResultCid() const { return kBoolCid; }
- // Visiting support.
- virtual void Accept(FlowGraphVisitor* visitor) = 0;
+ private:
+ DISALLOW_COPY_AND_ASSIGN(BooleanNegateComp);
+};
- Instruction* previous() const { return previous_; }
- void set_previous(Instruction* instr) {
- ASSERT(!IsBlockEntry());
- previous_ = instr;
- }
- Instruction* next() const { return next_; }
- void set_next(Instruction* instr) {
- ASSERT(!IsGraphEntry());
- ASSERT(!IsReturn());
- ASSERT(!IsControl());
- ASSERT(!IsPhi());
- ASSERT(instr == NULL || !instr->IsBlockEntry());
- // TODO(fschneider): Also add Throw and ReThrow to the list of instructions
- // that do not have a successor. Currently, the graph builder will continue
- // to append instruction in case of a Throw inside an expression. This
- // condition should be handled in the graph builder
- next_ = instr;
+class InstanceOfComp : public TemplateComputation<3> {
+ public:
+ InstanceOfComp(intptr_t token_pos,
+ Value* value,
+ Value* instantiator,
+ Value* instantiator_type_arguments,
+ const AbstractType& type,
+ bool negate_result)
+ : token_pos_(token_pos),
+ type_(type),
+ negate_result_(negate_result) {
+ ASSERT(value != NULL);
+ ASSERT(instantiator != NULL);
+ ASSERT(instantiator_type_arguments != NULL);
+ ASSERT(!type.IsNull());
+ inputs_[0] = value;
+ inputs_[1] = instantiator;
+ inputs_[2] = instantiator_type_arguments;
}
- // Removed this instruction from the graph.
- Instruction* RemoveFromGraph(bool return_previous = true);
+ DECLARE_COMPUTATION(InstanceOf)
- // Normal instructions can have 0 (inside a block) or 1 (last instruction in
- // a block) successors. Branch instruction with >1 successors override this
- // function.
- virtual intptr_t SuccessorCount() const;
- virtual BlockEntryInstr* SuccessorAt(intptr_t index) const;
+ Value* value() const { return inputs_[0]; }
+ Value* instantiator() const { return inputs_[1]; }
+ Value* instantiator_type_arguments() const { return inputs_[2]; }
- void Goto(JoinEntryInstr* entry);
+ bool negate_result() const { return negate_result_; }
+ const AbstractType& type() const { return type_; }
+ intptr_t token_pos() const { return token_pos_; }
- // Discover basic-block structure by performing a recursive depth first
- // traversal of the instruction graph reachable from this instruction. As
- // a side effect, the block entry instructions in the graph are assigned
- // numbers in both preorder and postorder. The array 'preorder' maps
- // preorder block numbers to the block entry instruction with that number
- // and analogously for the array 'postorder'. The depth first spanning
- // tree is recorded in the array 'parent', which maps preorder block
- // numbers to the preorder number of the block's spanning-tree parent.
- // The array 'assigned_vars' maps preorder block numbers to the set of
- // assigned frame-allocated local variables in the block. As a side
- // effect of this function, the set of basic block predecessors (e.g.,
- // block entry instructions of predecessor blocks) and also the last
- // instruction in the block is recorded in each entry instruction.
- virtual void DiscoverBlocks(
- BlockEntryInstr* current_block,
- GrowableArray<BlockEntryInstr*>* preorder,
- GrowableArray<BlockEntryInstr*>* postorder,
- GrowableArray<intptr_t>* parent,
- GrowableArray<BitVector*>* assigned_vars,
- intptr_t variable_count,
- intptr_t fixed_parameter_count) {
- // Never called for instructions except block entries and branches.
- UNREACHABLE();
- }
+ virtual void PrintOperandsTo(BufferFormatter* f) const;
- // Mutate assigned_vars to add the local variable index for all
- // frame-allocated locals assigned to by the instruction.
- virtual void RecordAssignedVars(BitVector* assigned_vars,
- intptr_t fixed_parameter_count);
+ virtual bool CanDeoptimize() const { return false; }
+ virtual intptr_t ResultCid() const { return kBoolCid; }
- // Printing support.
- virtual void PrintTo(BufferFormatter* f) const = 0;
- virtual void PrintToVisualizer(BufferFormatter* f) const = 0;
+ private:
+ const intptr_t token_pos_;
+ Value* value_;
+ Value* instantiator_;
+ Value* type_arguments_;
+ const AbstractType& type_;
+ const bool negate_result_;
-#define INSTRUCTION_TYPE_CHECK(type) \
- virtual bool Is##type() const { return false; } \
- virtual type##Instr* As##type() { return NULL; }
-FOR_EACH_INSTRUCTION(INSTRUCTION_TYPE_CHECK)
-#undef INSTRUCTION_TYPE_CHECK
+ DISALLOW_COPY_AND_ASSIGN(InstanceOfComp);
+};
- // Returns structure describing location constraints required
- // to emit native code for this instruction.
- virtual LocationSummary* locs() {
- // TODO(vegorov): This should be pure virtual method.
- // However we are temporary using NULL for instructions that
- // were not converted to the location based code generation yet.
- return NULL;
- }
- virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+class AllocateObjectComp : public TemplateComputation<0> {
+ public:
+ AllocateObjectComp(ConstructorCallNode* node,
+ ZoneGrowableArray<PushArgumentInstr*>* arguments)
+ : ast_node_(*node), arguments_(arguments) {
+ // Either no arguments or one type-argument and one instantiator.
+ ASSERT(arguments->is_empty() || (arguments->length() == 2));
}
- Environment* env() const { return env_; }
- void set_env(Environment* env) { env_ = env; }
-
- intptr_t lifetime_position() const { return lifetime_position_; }
- void set_lifetime_position(intptr_t pos) {
- lifetime_position_ = pos;
- }
+ DECLARE_CALL_COMPUTATION(AllocateObject)
- // Returns representation expected for the input operand at the given index.
- virtual Representation RequiredInputRepresentation(intptr_t idx) const {
- return kTagged;
+ virtual intptr_t ArgumentCount() const { return arguments_->length(); }
+ PushArgumentInstr* ArgumentAt(intptr_t index) const {
+ return (*arguments_)[index];
}
- // Representation of the value produced by this computation.
- virtual Representation representation() const {
- return kTagged;
- }
+ const Function& constructor() const { return ast_node_.constructor(); }
+ intptr_t token_pos() const { return ast_node_.token_pos(); }
- bool WasEliminated() const {
- return next() == NULL;
- }
+ virtual void PrintOperandsTo(BufferFormatter* f) const;
- // Returns deoptimization id that corresponds to the deoptimization target
- // that input operands conversions inserted for this instruction can jump
- // to.
- virtual intptr_t DeoptimizationTarget() const {
- UNREACHABLE();
- return Isolate::kNoDeoptId;
- }
+ virtual bool CanDeoptimize() const { return false; }
+ virtual intptr_t ResultCid() const { return kDynamicCid; }
private:
- friend class BindInstr; // Needed for BindInstr::InsertBefore.
+ const ConstructorCallNode& ast_node_;
+ ZoneGrowableArray<PushArgumentInstr*>* const arguments_;
- intptr_t lifetime_position_; // Position used by register allocator.
- Instruction* previous_;
- Instruction* next_;
- Environment* env_;
- DISALLOW_COPY_AND_ASSIGN(Instruction);
+ DISALLOW_COPY_AND_ASSIGN(AllocateObjectComp);
};
-template<intptr_t N>
-class TemplateInstruction: public Instruction {
+class AllocateObjectWithBoundsCheckComp : public TemplateComputation<2> {
public:
- TemplateInstruction<N>() : locs_(NULL) { }
-
- virtual intptr_t InputCount() const { return N; }
- virtual Value* InputAt(intptr_t i) const { return inputs_[i]; }
- virtual void SetInputAt(intptr_t i, Value* value) {
- ASSERT(value != NULL);
- inputs_[i] = value;
+ AllocateObjectWithBoundsCheckComp(ConstructorCallNode* node,
+ Value* type_arguments,
+ Value* instantiator)
+ : ast_node_(*node) {
+ ASSERT(type_arguments != NULL);
+ ASSERT(instantiator != NULL);
+ inputs_[0] = type_arguments;
+ inputs_[1] = instantiator;
}
- virtual LocationSummary* locs() {
- if (locs_ == NULL) {
- locs_ = MakeLocationSummary();
- }
- return locs_;
- }
+ DECLARE_COMPUTATION(AllocateObjectWithBoundsCheck)
- virtual LocationSummary* MakeLocationSummary() const = 0;
+ const Function& constructor() const { return ast_node_.constructor(); }
+ intptr_t token_pos() const { return ast_node_.token_pos(); }
- protected:
- EmbeddedArray<Value*, N> inputs_;
+ virtual void PrintOperandsTo(BufferFormatter* f) const;
+
+ virtual bool CanDeoptimize() const { return false; }
+ virtual intptr_t ResultCid() const { return kDynamicCid; }
private:
- LocationSummary* locs_;
+ const ConstructorCallNode& ast_node_;
+
+ DISALLOW_COPY_AND_ASSIGN(AllocateObjectWithBoundsCheckComp);
};
-class MoveOperands : public ZoneAllocated {
+class CreateArrayComp : public TemplateComputation<1> {
public:
- MoveOperands(Location dest, Location src) : dest_(dest), src_(src) { }
+ CreateArrayComp(intptr_t token_pos,
+ ZoneGrowableArray<PushArgumentInstr*>* arguments,
+ const AbstractType& type,
+ Value* element_type)
+ : token_pos_(token_pos),
+ arguments_(arguments),
+ type_(type) {
+#if defined(DEBUG)
+ for (int i = 0; i < ArgumentCount(); ++i) {
+ ASSERT(ArgumentAt(i) != NULL);
+ }
+ ASSERT(element_type != NULL);
+ ASSERT(type_.IsZoneHandle());
+ ASSERT(!type_.IsNull());
+ ASSERT(type_.IsFinalized());
+#endif
+ inputs_[0] = element_type;
+ }
- Location src() const { return src_; }
- Location dest() const { return dest_; }
+ DECLARE_CALL_COMPUTATION(CreateArray)
- Location* src_slot() { return &src_; }
- Location* dest_slot() { return &dest_; }
+ virtual intptr_t ArgumentCount() const { return arguments_->length(); }
- void set_src(const Location& value) { src_ = value; }
- void set_dest(const Location& value) { dest_ = value; }
+ intptr_t token_pos() const { return token_pos_; }
+ PushArgumentInstr* ArgumentAt(intptr_t i) const { return (*arguments_)[i]; }
+ const AbstractType& type() const { return type_; }
+ Value* element_type() const { return inputs_[0]; }
- // The parallel move resolver marks moves as "in-progress" by clearing the
- // destination (but not the source).
- Location MarkPending() {
- ASSERT(!IsPending());
- Location dest = dest_;
- dest_ = Location::NoLocation();
- return dest;
- }
+ virtual void PrintOperandsTo(BufferFormatter* f) const;
- void ClearPending(Location dest) {
- ASSERT(IsPending());
- dest_ = dest;
- }
+ virtual bool CanDeoptimize() const { return false; }
+ virtual intptr_t ResultCid() const { return kDynamicCid; }
- bool IsPending() const {
- ASSERT(!src_.IsInvalid() || dest_.IsInvalid());
- return dest_.IsInvalid() && !src_.IsInvalid();
- }
+ private:
+ const intptr_t token_pos_;
+ ZoneGrowableArray<PushArgumentInstr*>* const arguments_;
+ const AbstractType& type_;
- // True if this move a move from the given location.
- bool Blocks(Location loc) const {
- return !IsEliminated() && src_.Equals(loc);
- }
+ DISALLOW_COPY_AND_ASSIGN(CreateArrayComp);
+};
- // A move is redundant if it's been eliminated, if its source and
- // destination are the same, or if its destination is unneeded.
- bool IsRedundant() const {
- return IsEliminated() || dest_.IsInvalid() || src_.Equals(dest_);
- }
- // We clear both operands to indicate move that's been eliminated.
- void Eliminate() { src_ = dest_ = Location::NoLocation(); }
- bool IsEliminated() const {
- ASSERT(!src_.IsInvalid() || dest_.IsInvalid());
- return src_.IsInvalid();
+class CreateClosureComp : public TemplateComputation<0> {
+ public:
+ CreateClosureComp(ClosureNode* node,
+ ZoneGrowableArray<PushArgumentInstr*>* arguments)
+ : ast_node_(*node),
+ arguments_(arguments) { }
+
+ DECLARE_CALL_COMPUTATION(CreateClosure)
+
+ intptr_t token_pos() const { return ast_node_.token_pos(); }
+ const Function& function() const { return ast_node_.function(); }
+
+ virtual intptr_t ArgumentCount() const { return arguments_->length(); }
+ PushArgumentInstr* ArgumentAt(intptr_t index) const {
+ return (*arguments_)[index];
}
+ virtual void PrintOperandsTo(BufferFormatter* f) const;
+
+ virtual bool CanDeoptimize() const { return false; }
+ virtual intptr_t ResultCid() const { return kDynamicCid; }
+
private:
- Location dest_;
- Location src_;
+ const ClosureNode& ast_node_;
+ ZoneGrowableArray<PushArgumentInstr*>* arguments_;
- DISALLOW_COPY_AND_ASSIGN(MoveOperands);
+ DISALLOW_COPY_AND_ASSIGN(CreateClosureComp);
};
-class ParallelMoveInstr : public TemplateInstruction<0> {
+class LoadVMFieldComp : public TemplateComputation<1> {
public:
- ParallelMoveInstr() : moves_(4) { }
+ LoadVMFieldComp(Value* value,
+ intptr_t offset_in_bytes,
+ const AbstractType& type)
+ : offset_in_bytes_(offset_in_bytes),
+ type_(type),
+ result_cid_(kDynamicCid) {
+ ASSERT(value != NULL);
+ ASSERT(type.IsZoneHandle()); // May be null if field is not an instance.
+ inputs_[0] = value;
+ }
- DECLARE_INSTRUCTION(ParallelMove)
+ DECLARE_COMPUTATION(LoadVMField)
- virtual intptr_t ArgumentCount() const { return 0; }
+ Value* value() const { return inputs_[0]; }
+ intptr_t offset_in_bytes() const { return offset_in_bytes_; }
+ const AbstractType& type() const { return type_; }
+ void set_result_cid(intptr_t value) { result_cid_ = value; }
+
+ virtual void PrintOperandsTo(BufferFormatter* f) const;
virtual bool CanDeoptimize() const { return false; }
+ virtual intptr_t ResultCid() const { return result_cid_; }
- MoveOperands* AddMove(Location dest, Location src) {
- MoveOperands* move = new MoveOperands(dest, src);
- moves_.Add(move);
- return move;
- }
+ private:
+ const intptr_t offset_in_bytes_;
+ const AbstractType& type_;
+ intptr_t result_cid_;
- MoveOperands* MoveOperandsAt(intptr_t index) const { return moves_[index]; }
+ DISALLOW_COPY_AND_ASSIGN(LoadVMFieldComp);
+};
- void SetSrcSlotAt(intptr_t index, const Location& loc);
- void SetDestSlotAt(intptr_t index, const Location& loc);
- intptr_t NumMoves() const { return moves_.length(); }
+class StoreVMFieldComp : public TemplateComputation<2> {
+ public:
+ StoreVMFieldComp(Value* dest,
+ intptr_t offset_in_bytes,
+ Value* value,
+ const AbstractType& type)
+ : offset_in_bytes_(offset_in_bytes), type_(type) {
+ ASSERT(value != NULL);
+ ASSERT(dest != NULL);
+ ASSERT(type.IsZoneHandle()); // May be null if field is not an instance.
+ inputs_[0] = value;
+ inputs_[1] = dest;
+ }
- LocationSummary* MakeLocationSummary() const { return NULL; }
+ DECLARE_COMPUTATION(StoreVMField)
- void EmitNativeCode(FlowGraphCompiler* compiler) { UNREACHABLE(); }
+ Value* value() const { return inputs_[0]; }
+ Value* dest() const { return inputs_[1]; }
+ intptr_t offset_in_bytes() const { return offset_in_bytes_; }
+ const AbstractType& type() const { return type_; }
+
+ virtual void PrintOperandsTo(BufferFormatter* f) const;
+
+ virtual bool CanDeoptimize() const { return false; }
+ virtual intptr_t ResultCid() const { return kDynamicCid; }
private:
- GrowableArray<MoveOperands*> moves_; // Elements cannot be null.
+ const intptr_t offset_in_bytes_;
+ const AbstractType& type_;
- DISALLOW_COPY_AND_ASSIGN(ParallelMoveInstr);
+ DISALLOW_COPY_AND_ASSIGN(StoreVMFieldComp);
};
-// Basic block entries are administrative nodes. There is a distinguished
-// graph entry with no predecessor. Joins are the only nodes with multiple
-// predecessors. Targets are all other basic block entries. The types
-// enforce edge-split form---joins are forbidden as the successors of
-// branches.
-class BlockEntryInstr : public Instruction {
+class InstantiateTypeArgumentsComp : public TemplateComputation<1> {
public:
- virtual bool IsBlockEntry() const { return true; }
+ InstantiateTypeArgumentsComp(intptr_t token_pos,
+ const AbstractTypeArguments& type_arguments,
+ Value* instantiator)
+ : token_pos_(token_pos),
+ type_arguments_(type_arguments) {
+ ASSERT(type_arguments.IsZoneHandle());
+ ASSERT(instantiator != NULL);
+ inputs_[0] = instantiator;
+ }
- virtual intptr_t PredecessorCount() const = 0;
- virtual BlockEntryInstr* PredecessorAt(intptr_t index) const = 0;
- virtual void AddPredecessor(BlockEntryInstr* predecessor) = 0;
- virtual void PrepareEntry(FlowGraphCompiler* compiler) = 0;
+ DECLARE_COMPUTATION(InstantiateTypeArguments)
- intptr_t preorder_number() const { return preorder_number_; }
- void set_preorder_number(intptr_t number) { preorder_number_ = number; }
+ Value* instantiator() const { return inputs_[0]; }
+ const AbstractTypeArguments& type_arguments() const {
+ return type_arguments_;
+ }
+ intptr_t token_pos() const { return token_pos_; }
- intptr_t postorder_number() const { return postorder_number_; }
- void set_postorder_number(intptr_t number) { postorder_number_ = number; }
+ virtual void PrintOperandsTo(BufferFormatter* f) const;
- intptr_t block_id() const { return block_id_; }
- void set_block_id(intptr_t value) { block_id_ = value; }
+ virtual bool CanDeoptimize() const { return false; }
+ virtual intptr_t ResultCid() const { return kDynamicCid; }
- void set_start_pos(intptr_t pos) { start_pos_ = pos; }
- intptr_t start_pos() const { return start_pos_; }
- void set_end_pos(intptr_t pos) { end_pos_ = pos; }
- intptr_t end_pos() const { return end_pos_; }
+ private:
+ const intptr_t token_pos_;
+ const AbstractTypeArguments& type_arguments_;
- BlockEntryInstr* dominator() const { return dominator_; }
- void set_dominator(BlockEntryInstr* instr) { dominator_ = instr; }
+ DISALLOW_COPY_AND_ASSIGN(InstantiateTypeArgumentsComp);
+};
- const GrowableArray<BlockEntryInstr*>& dominated_blocks() {
- return dominated_blocks_;
- }
- void AddDominatedBlock(BlockEntryInstr* block) {
- dominated_blocks_.Add(block);
+class ExtractConstructorTypeArgumentsComp : public TemplateComputation<1> {
+ public:
+ ExtractConstructorTypeArgumentsComp(
+ intptr_t token_pos,
+ const AbstractTypeArguments& type_arguments,
+ Value* instantiator)
+ : token_pos_(token_pos),
+ type_arguments_(type_arguments) {
+ ASSERT(instantiator != NULL);
+ inputs_[0] = instantiator;
}
- Instruction* last_instruction() const { return last_instruction_; }
- void set_last_instruction(Instruction* instr) { last_instruction_ = instr; }
+ DECLARE_COMPUTATION(ExtractConstructorTypeArguments)
- ParallelMoveInstr* parallel_move() const {
- return parallel_move_;
+ Value* instantiator() const { return inputs_[0]; }
+ const AbstractTypeArguments& type_arguments() const {
+ return type_arguments_;
}
+ intptr_t token_pos() const { return token_pos_; }
- bool HasParallelMove() const {
- return parallel_move_ != NULL;
- }
+ virtual void PrintOperandsTo(BufferFormatter* f) const;
- ParallelMoveInstr* GetParallelMove() {
- if (parallel_move_ == NULL) {
- parallel_move_ = new ParallelMoveInstr();
- }
- return parallel_move_;
- }
+ virtual bool CanDeoptimize() const { return false; }
+ virtual intptr_t ResultCid() const { return kDynamicCid; }
- virtual void DiscoverBlocks(
- BlockEntryInstr* current_block,
- GrowableArray<BlockEntryInstr*>* preorder,
- GrowableArray<BlockEntryInstr*>* postorder,
- GrowableArray<intptr_t>* parent,
- GrowableArray<BitVector*>* assigned_vars,
- intptr_t variable_count,
- intptr_t fixed_parameter_count);
+ private:
+ const intptr_t token_pos_;
+ const AbstractTypeArguments& type_arguments_;
- virtual intptr_t InputCount() const { return 0; }
- virtual Value* InputAt(intptr_t i) const {
- UNREACHABLE();
- return NULL;
- }
- virtual void SetInputAt(intptr_t i, Value* value) { UNREACHABLE(); }
+ DISALLOW_COPY_AND_ASSIGN(ExtractConstructorTypeArgumentsComp);
+};
- virtual intptr_t ArgumentCount() const { return 0; }
- virtual bool CanDeoptimize() const { return false; }
+class ExtractConstructorInstantiatorComp : public TemplateComputation<1> {
+ public:
+ ExtractConstructorInstantiatorComp(ConstructorCallNode* ast_node,
+ Value* instantiator)
+ : ast_node_(*ast_node) {
+ ASSERT(instantiator != NULL);
+ inputs_[0] = instantiator;
+ }
- intptr_t try_index() const { return try_index_; }
+ DECLARE_COMPUTATION(ExtractConstructorInstantiator)
- protected:
- explicit BlockEntryInstr(intptr_t try_index)
- : try_index_(try_index),
- preorder_number_(-1),
- postorder_number_(-1),
- block_id_(-1),
- dominator_(NULL),
- dominated_blocks_(1),
- last_instruction_(NULL),
- parallel_move_(NULL) { }
+ Value* instantiator() const { return inputs_[0]; }
+ const AbstractTypeArguments& type_arguments() const {
+ return ast_node_.type_arguments();
+ }
+ const Function& constructor() const { return ast_node_.constructor(); }
+ intptr_t token_pos() const { return ast_node_.token_pos(); }
- private:
- const intptr_t try_index_;
- intptr_t preorder_number_;
- intptr_t postorder_number_;
- // Starting and ending lifetime positions for this block. Used by
- // the linear scan register allocator.
- intptr_t block_id_;
- intptr_t start_pos_;
- intptr_t end_pos_;
- BlockEntryInstr* dominator_; // Immediate dominator, NULL for graph entry.
- // TODO(fschneider): Optimize the case of one child to save space.
- GrowableArray<BlockEntryInstr*> dominated_blocks_;
- Instruction* last_instruction_;
+ virtual bool CanDeoptimize() const { return false; }
+ virtual intptr_t ResultCid() const { return kDynamicCid; }
- // Parallel move that will be used by linear scan register allocator to
- // connect live ranges at the start of the block.
- ParallelMoveInstr* parallel_move_;
+ private:
+ const ConstructorCallNode& ast_node_;
- DISALLOW_COPY_AND_ASSIGN(BlockEntryInstr);
+ DISALLOW_COPY_AND_ASSIGN(ExtractConstructorInstantiatorComp);
};
-class ForwardInstructionIterator : public ValueObject {
+class AllocateContextComp : public TemplateComputation<0> {
public:
- explicit ForwardInstructionIterator(BlockEntryInstr* block_entry)
- : block_entry_(block_entry), current_(block_entry) {
- ASSERT(block_entry_->last_instruction()->next() == NULL);
- Advance();
- }
+ AllocateContextComp(intptr_t token_pos,
+ intptr_t num_context_variables)
+ : token_pos_(token_pos),
+ num_context_variables_(num_context_variables) {}
- void Advance() {
- ASSERT(!Done());
- current_ = current_->next();
- }
+ DECLARE_COMPUTATION(AllocateContext);
- bool Done() const { return current_ == NULL; }
+ intptr_t token_pos() const { return token_pos_; }
+ intptr_t num_context_variables() const { return num_context_variables_; }
- // Removes 'current_' from graph and sets 'current_' to previous instruction.
- void RemoveCurrentFromGraph();
+ virtual void PrintOperandsTo(BufferFormatter* f) const;
- Instruction* Current() const { return current_; }
+ virtual bool CanDeoptimize() const { return false; }
+ virtual intptr_t ResultCid() const { return kDynamicCid; }
private:
- BlockEntryInstr* block_entry_;
- Instruction* current_;
+ const intptr_t token_pos_;
+ const intptr_t num_context_variables_;
+
+ DISALLOW_COPY_AND_ASSIGN(AllocateContextComp);
};
-class BackwardInstructionIterator : public ValueObject {
+class ChainContextComp : public TemplateComputation<1> {
public:
- explicit BackwardInstructionIterator(BlockEntryInstr* block_entry)
- : block_entry_(block_entry), current_(block_entry->last_instruction()) {
- ASSERT(block_entry_->previous() == NULL);
+ explicit ChainContextComp(Value* context_value) {
+ ASSERT(context_value != NULL);
+ inputs_[0] = context_value;
}
- void Advance() {
- ASSERT(!Done());
- current_ = current_->previous();
- }
+ DECLARE_COMPUTATION(ChainContext)
- bool Done() const { return current_ == block_entry_; }
+ Value* context_value() const { return inputs_[0]; }
- Instruction* Current() const { return current_; }
+ virtual bool CanDeoptimize() const { return false; }
+ virtual intptr_t ResultCid() const { return kIllegalCid; }
private:
- BlockEntryInstr* block_entry_;
- Instruction* current_;
+ DISALLOW_COPY_AND_ASSIGN(ChainContextComp);
};
-class GraphEntryInstr : public BlockEntryInstr {
+class CloneContextComp : public TemplateComputation<1> {
public:
- explicit GraphEntryInstr(TargetEntryInstr* normal_entry);
-
- DECLARE_INSTRUCTION(GraphEntry)
-
- virtual intptr_t PredecessorCount() const { return 0; }
- virtual BlockEntryInstr* PredecessorAt(intptr_t index) const {
- UNREACHABLE();
- return NULL;
+ CloneContextComp(intptr_t token_pos,
+ Value* context_value)
+ : token_pos_(token_pos) {
+ ASSERT(context_value != NULL);
+ inputs_[0] = context_value;
}
- virtual void AddPredecessor(BlockEntryInstr* predecessor) { UNREACHABLE(); }
-
- virtual intptr_t SuccessorCount() const;
- virtual BlockEntryInstr* SuccessorAt(intptr_t index) const;
-
- virtual void DiscoverBlocks(
- BlockEntryInstr* current_block,
- GrowableArray<BlockEntryInstr*>* preorder,
- GrowableArray<BlockEntryInstr*>* postorder,
- GrowableArray<intptr_t>* parent,
- GrowableArray<BitVector*>* assigned_vars,
- intptr_t variable_count,
- intptr_t fixed_parameter_count);
-
- void AddCatchEntry(TargetEntryInstr* entry) { catch_entries_.Add(entry); }
-
- virtual void PrepareEntry(FlowGraphCompiler* compiler);
-
- Environment* start_env() const { return start_env_; }
- void set_start_env(Environment* env) { start_env_ = env; }
- Definition* constant_null() const { return constant_null_; }
+ intptr_t token_pos() const { return token_pos_; }
+ Value* context_value() const { return inputs_[0]; }
- intptr_t spill_slot_count() const { return spill_slot_count_; }
- void set_spill_slot_count(intptr_t count) {
- ASSERT(count >= 0);
- spill_slot_count_ = count;
- }
+ DECLARE_COMPUTATION(CloneContext)
- TargetEntryInstr* normal_entry() const { return normal_entry_; }
+ virtual bool CanDeoptimize() const { return false; }
+ virtual intptr_t ResultCid() const { return kIllegalCid; }
private:
- TargetEntryInstr* normal_entry_;
- GrowableArray<TargetEntryInstr*> catch_entries_;
- Environment* start_env_;
- Definition* constant_null_;
- intptr_t spill_slot_count_;
+ const intptr_t token_pos_;
- DISALLOW_COPY_AND_ASSIGN(GraphEntryInstr);
+ DISALLOW_COPY_AND_ASSIGN(CloneContextComp);
};
-class JoinEntryInstr : public BlockEntryInstr {
+class CatchEntryComp : public TemplateComputation<0> {
public:
- explicit JoinEntryInstr(intptr_t try_index)
- : BlockEntryInstr(try_index),
- predecessors_(2), // Two is the assumed to be the common case.
- phis_(NULL),
- phi_count_(0) { }
-
- DECLARE_INSTRUCTION(JoinEntry)
-
- virtual intptr_t PredecessorCount() const { return predecessors_.length(); }
- virtual BlockEntryInstr* PredecessorAt(intptr_t index) const {
- return predecessors_[index];
- }
- virtual void AddPredecessor(BlockEntryInstr* predecessor) {
- predecessors_.Add(predecessor);
- }
-
- // Returns -1 if pred is not in the list.
- intptr_t IndexOfPredecessor(BlockEntryInstr* pred) const;
+ CatchEntryComp(const LocalVariable& exception_var,
+ const LocalVariable& stacktrace_var)
+ : exception_var_(exception_var), stacktrace_var_(stacktrace_var) {}
- ZoneGrowableArray<PhiInstr*>* phis() const { return phis_; }
+ const LocalVariable& exception_var() const { return exception_var_; }
+ const LocalVariable& stacktrace_var() const { return stacktrace_var_; }
- virtual void PrepareEntry(FlowGraphCompiler* compiler);
+ DECLARE_COMPUTATION(CatchEntry)
- void InsertPhi(intptr_t var_index, intptr_t var_count);
- void RemoveDeadPhis();
+ virtual void PrintOperandsTo(BufferFormatter* f) const;
- intptr_t phi_count() const { return phi_count_; }
+ virtual bool CanDeoptimize() const { return false; }
+ virtual intptr_t ResultCid() const { return kIllegalCid; }
private:
- GrowableArray<BlockEntryInstr*> predecessors_;
- ZoneGrowableArray<PhiInstr*>* phis_;
- intptr_t phi_count_;
+ const LocalVariable& exception_var_;
+ const LocalVariable& stacktrace_var_;
- DISALLOW_COPY_AND_ASSIGN(JoinEntryInstr);
+ DISALLOW_COPY_AND_ASSIGN(CatchEntryComp);
};
-class TargetEntryInstr : public BlockEntryInstr {
+class CheckEitherNonSmiComp : public TemplateComputation<2> {
public:
- explicit TargetEntryInstr(intptr_t try_index)
- : BlockEntryInstr(try_index),
- predecessor_(NULL),
- catch_try_index_(CatchClauseNode::kInvalidTryIndex) { }
+ CheckEitherNonSmiComp(Value* left,
+ Value* right,
+ InstanceCallComp* instance_call)
+ : instance_call_(instance_call) {
+ ASSERT(left != NULL);
+ ASSERT(right != NULL);
+ inputs_[0] = left;
+ inputs_[1] = right;
+ }
- // Used for exception catch entries.
- TargetEntryInstr(intptr_t try_index, intptr_t catch_try_index)
- : BlockEntryInstr(try_index),
- predecessor_(NULL),
- catch_try_index_(catch_try_index) { }
+ DECLARE_COMPUTATION(CheckEitherNonSmi)
- DECLARE_INSTRUCTION(TargetEntry)
+ virtual bool CanDeoptimize() const { return true; }
+ virtual intptr_t ResultCid() const { return kIllegalCid; }
- virtual intptr_t PredecessorCount() const {
- return (predecessor_ == NULL) ? 0 : 1;
- }
- virtual BlockEntryInstr* PredecessorAt(intptr_t index) const {
- ASSERT((index == 0) && (predecessor_ != NULL));
- return predecessor_;
- }
- virtual void AddPredecessor(BlockEntryInstr* predecessor) {
- ASSERT(predecessor_ == NULL);
- predecessor_ = predecessor;
- }
+ virtual bool AttributesEqual(Computation* other) const { return true; }
- // Returns true if this Block is an entry of a catch handler.
- bool IsCatchEntry() const {
- return catch_try_index_ != CatchClauseNode::kInvalidTryIndex;
- }
+ virtual bool HasSideEffect() const { return false; }
- // Returns try index for the try block to which this catch handler
- // corresponds.
- intptr_t catch_try_index() const {
- ASSERT(IsCatchEntry());
- return catch_try_index_;
- }
+ Value* left() const { return inputs_[0]; }
- virtual void PrepareEntry(FlowGraphCompiler* compiler);
+ Value* right() const { return inputs_[1]; }
+
+ virtual Definition* TryReplace(BindInstr* instr) const;
private:
- BlockEntryInstr* predecessor_;
- const intptr_t catch_try_index_;
+ InstanceCallComp* instance_call_;
- DISALLOW_COPY_AND_ASSIGN(TargetEntryInstr);
+ DISALLOW_COPY_AND_ASSIGN(CheckEitherNonSmiComp);
};
-// Abstract super-class of all instructions that define a value (Bind, Phi).
-class Definition : public Instruction {
+class BoxDoubleComp : public TemplateComputation<1> {
public:
- Definition()
- : temp_index_(-1),
- ssa_temp_index_(-1),
- propagated_type_(AbstractType::Handle()),
- propagated_cid_(kIllegalCid),
- input_use_list_(NULL),
- env_use_list_(NULL) { }
-
- virtual bool IsDefinition() const { return true; }
- virtual Definition* AsDefinition() { return this; }
-
- intptr_t temp_index() const { return temp_index_; }
- void set_temp_index(intptr_t index) { temp_index_ = index; }
-
- intptr_t ssa_temp_index() const { return ssa_temp_index_; }
- void set_ssa_temp_index(intptr_t index) {
- ASSERT(index >= 0);
- ssa_temp_index_ = index;
+ BoxDoubleComp(Value* value, InstanceCallComp* instance_call)
+ : token_pos_((instance_call != NULL) ? instance_call->token_pos() : 0) {
+ ASSERT(value != NULL);
+ inputs_[0] = value;
}
- bool HasSSATemp() const { return ssa_temp_index_ >= 0; }
-
- // Compile time type of the definition, which may be requested before type
- // propagation during graph building.
- virtual RawAbstractType* CompileType() const = 0;
- bool HasPropagatedType() const {
- return !propagated_type_.IsNull();
- }
- RawAbstractType* PropagatedType() const {
- ASSERT(HasPropagatedType());
- return propagated_type_.raw();
- }
- // Returns true if the propagated type has changed.
- bool SetPropagatedType(const AbstractType& propagated_type) {
- if (propagated_type.IsNull()) {
- // Not a typed definition, e.g. access to a VM field.
- return false;
- }
- const bool changed =
- propagated_type_.IsNull() || !propagated_type.Equals(propagated_type_);
- propagated_type_ = propagated_type.raw();
- return changed;
- }
+ Value* value() const { return inputs_[0]; }
- bool has_propagated_cid() const { return propagated_cid_ != kIllegalCid; }
- intptr_t propagated_cid() const { return propagated_cid_; }
- // May compute and set propagated cid.
- virtual intptr_t GetPropagatedCid() = 0;
+ intptr_t token_pos() const { return token_pos_; }
- // Returns true if the propagated cid has changed.
- bool SetPropagatedCid(intptr_t cid);
+ virtual bool CanDeoptimize() const { return false; }
+ virtual bool HasSideEffect() const { return false; }
+ virtual bool AttributesEqual(Computation* other) const { return true; }
- Value* input_use_list() { return input_use_list_; }
- void set_input_use_list(Value* head) { input_use_list_ = head; }
+ virtual intptr_t ResultCid() const;
- Value* env_use_list() { return env_use_list_; }
- void set_env_use_list(Value* head) { env_use_list_ = head; }
+ virtual Representation RequiredInputRepresentation(intptr_t idx) const {
+ ASSERT(idx == 0);
+ return kUnboxedDouble;
+ }
- // Replace uses of this definition with uses of other definition or value.
- // Precondition: use lists must be properly calculated.
- // Postcondition: use lists and use values are still valid.
- void ReplaceUsesWith(Definition* other);
+ DECLARE_COMPUTATION(BoxDouble)
private:
- intptr_t temp_index_;
- intptr_t ssa_temp_index_;
- // TODO(regis): GrowableArray<const AbstractType*> propagated_types_;
- // For now:
- AbstractType& propagated_type_;
- intptr_t propagated_cid_;
- Value* input_use_list_;
- Value* env_use_list_;
+ const intptr_t token_pos_;
- DISALLOW_COPY_AND_ASSIGN(Definition);
+ DISALLOW_COPY_AND_ASSIGN(BoxDoubleComp);
};
-class BindInstr : public Definition {
+class UnboxDoubleComp : public TemplateComputation<1> {
public:
- enum UseKind { kUnused, kUsed };
-
- BindInstr(UseKind used, Computation* computation)
- : computation_(computation), is_used_(used != kUnused) {
- ASSERT(computation != NULL);
+ UnboxDoubleComp(Value* value, intptr_t deopt_id)
+ : deopt_id_(deopt_id) {
+ ASSERT(value != NULL);
+ inputs_[0] = value;
}
- DECLARE_INSTRUCTION(Bind)
+ Value* value() const { return inputs_[0]; }
- virtual intptr_t ArgumentCount() const {
- return computation()->ArgumentCount();
+ virtual bool CanDeoptimize() const {
+ return value()->ResultCid() != kDoubleCid;
}
- intptr_t InputCount() const { return computation()->InputCount(); }
- Value* InputAt(intptr_t i) const { return computation()->InputAt(i); }
+ // The output is not an instance but when it is boxed it becomes double.
+ virtual intptr_t ResultCid() const { return kDoubleCid; }
- void SetInputAt(intptr_t i, Value* value) {
- computation()->SetInputAt(i, value);
+ virtual Representation representation() const {
+ return kUnboxedDouble;
}
- virtual bool CanDeoptimize() const { return computation()->CanDeoptimize(); }
+ virtual bool HasSideEffect() const { return false; }
+ virtual bool AttributesEqual(Computation* other) const { return true; }
- Computation* computation() const { return computation_; }
- void set_computation(Computation* value) { computation_ = value; }
- bool is_used() const { return is_used_; }
+ DECLARE_COMPUTATION(UnboxDouble)
- virtual RawAbstractType* CompileType() const;
- virtual intptr_t GetPropagatedCid();
+ private:
+ const intptr_t deopt_id_;
- virtual void RecordAssignedVars(BitVector* assigned_vars,
- intptr_t fixed_parameter_count);
+ DISALLOW_COPY_AND_ASSIGN(UnboxDoubleComp);
+};
- intptr_t Hashcode() const { return computation()->Hashcode(); }
- bool Equals(BindInstr* other) const {
- return computation()->Equals(other->computation());
+class UnboxedDoubleBinaryOpComp : public TemplateComputation<2> {
+ public:
+ UnboxedDoubleBinaryOpComp(Token::Kind op_kind,
+ Value* left,
+ Value* right,
+ InstanceCallComp* call)
+ : op_kind_(op_kind), deopt_id_(call->deopt_id()) {
+ ASSERT(left != NULL);
+ ASSERT(right != NULL);
+ inputs_[0] = left;
+ inputs_[1] = right;
}
- virtual LocationSummary* locs() {
- return computation()->locs();
- }
+ Value* left() const { return inputs_[0]; }
+ Value* right() const { return inputs_[1]; }
- virtual void EmitNativeCode(FlowGraphCompiler* compiler);
+ Token::Kind op_kind() const { return op_kind_; }
- // Insert this instruction before 'next'.
- void InsertBefore(Instruction* next);
+ virtual void PrintOperandsTo(BufferFormatter* f) const;
- // Insert this instruction after 'prev'.
- void InsertAfter(Instruction* prev);
+ virtual bool CanDeoptimize() const { return false; }
+ virtual bool HasSideEffect() const { return false; }
- virtual Representation RequiredInputRepresentation(intptr_t i) const {
- return computation()->RequiredInputRepresentation(i);
+ virtual bool AttributesEqual(Computation* other) const {
+ return op_kind() == other->AsUnboxedDoubleBinaryOp()->op_kind();
}
+ // The output is not an instance but when it is boxed it becomes double.
+ virtual intptr_t ResultCid() const { return kDoubleCid; }
+
virtual Representation representation() const {
- return computation()->representation();
+ return kUnboxedDouble;
+ }
+
+ virtual Representation RequiredInputRepresentation(intptr_t idx) const {
+ ASSERT((idx == 0) || (idx == 1));
+ return kUnboxedDouble;
}
virtual intptr_t DeoptimizationTarget() const {
- return computation()->DeoptimizationTarget();
+ return deopt_id_;
}
+ DECLARE_COMPUTATION(UnboxedDoubleBinaryOp)
+
private:
- Computation* computation_;
- const bool is_used_;
+ const Token::Kind op_kind_;
+ const intptr_t deopt_id_;
- DISALLOW_COPY_AND_ASSIGN(BindInstr);
+ DISALLOW_COPY_AND_ASSIGN(UnboxedDoubleBinaryOpComp);
};
-class PhiInstr : public Definition {
+class BinarySmiOpComp : public TemplateComputation<2> {
public:
- explicit PhiInstr(JoinEntryInstr* block, intptr_t num_inputs)
- : block_(block),
- inputs_(num_inputs),
- is_alive_(false),
- representation_(kTagged) {
- for (intptr_t i = 0; i < num_inputs; ++i) {
- inputs_.Add(NULL);
- }
+ BinarySmiOpComp(Token::Kind op_kind,
+ InstanceCallComp* instance_call,
+ Value* left,
+ Value* right)
+ : op_kind_(op_kind),
+ instance_call_(instance_call) {
+ ASSERT(left != NULL);
+ ASSERT(right != NULL);
+ inputs_[0] = left;
+ inputs_[1] = right;
}
- JoinEntryInstr* block() const { return block_; }
+ Value* left() const { return inputs_[0]; }
+ Value* right() const { return inputs_[1]; }
- virtual RawAbstractType* CompileType() const;
- virtual intptr_t GetPropagatedCid() { return propagated_cid(); }
+ Token::Kind op_kind() const { return op_kind_; }
- virtual intptr_t ArgumentCount() const { return 0; }
+ InstanceCallComp* instance_call() const { return instance_call_; }
- intptr_t InputCount() const { return inputs_.length(); }
+ const ICData* ic_data() const { return instance_call()->ic_data(); }
- Value* InputAt(intptr_t i) const { return inputs_[i]; }
+ virtual void PrintOperandsTo(BufferFormatter* f) const;
- void SetInputAt(intptr_t i, Value* value) { inputs_[i] = value; }
+ DECLARE_COMPUTATION(BinarySmiOp)
- virtual bool CanDeoptimize() const { return false; }
+ virtual bool CanDeoptimize() const;
- // TODO(regis): This helper will be removed once we support type sets.
- RawAbstractType* LeastSpecificInputType() const;
+ virtual intptr_t ResultCid() const;
- // Phi is alive if it reaches a non-environment use.
- bool is_alive() const { return is_alive_; }
- void mark_alive() { is_alive_ = true; }
+ private:
+ const Token::Kind op_kind_;
+ InstanceCallComp* instance_call_;
- virtual Representation RequiredInputRepresentation(intptr_t i) const {
- return representation_;
- }
+ DISALLOW_COPY_AND_ASSIGN(BinarySmiOpComp);
+};
- virtual Representation representation() const {
- return representation_;
- }
- virtual void set_representation(Representation r) {
- representation_ = r;
+class BinaryMintOpComp : public TemplateComputation<2> {
+ public:
+ BinaryMintOpComp(Token::Kind op_kind,
+ InstanceCallComp* instance_call,
+ Value* left,
+ Value* right)
+ : op_kind_(op_kind),
+ instance_call_(instance_call) {
+ ASSERT(left != NULL);
+ ASSERT(right != NULL);
+ inputs_[0] = left;
+ inputs_[1] = right;
}
- DECLARE_INSTRUCTION(Phi)
+ Value* left() const { return inputs_[0]; }
+ Value* right() const { return inputs_[1]; }
+
+ Token::Kind op_kind() const { return op_kind_; }
+
+ InstanceCallComp* instance_call() const { return instance_call_; }
+
+ const ICData* ic_data() const { return instance_call()->ic_data(); }
+
+ virtual void PrintOperandsTo(BufferFormatter* f) const;
+
+ DECLARE_COMPUTATION(BinaryMintOp)
+
+ virtual bool CanDeoptimize() const { return true; }
+ virtual intptr_t ResultCid() const;
private:
- JoinEntryInstr* block_;
- GrowableArray<Value*> inputs_;
- bool is_alive_;
- Representation representation_;
+ const Token::Kind op_kind_;
+ InstanceCallComp* instance_call_;
- DISALLOW_COPY_AND_ASSIGN(PhiInstr);
+ DISALLOW_COPY_AND_ASSIGN(BinaryMintOpComp);
};
-class ParameterInstr : public Definition {
+class BinaryDoubleOpComp : public TemplateComputation<0> {
public:
- explicit ParameterInstr(intptr_t index) : index_(index) { }
+ BinaryDoubleOpComp(Token::Kind op_kind, InstanceCallComp* instance_call)
+ : op_kind_(op_kind), instance_call_(instance_call) { }
- DECLARE_INSTRUCTION(Parameter)
+ Token::Kind op_kind() const { return op_kind_; }
- intptr_t index() const { return index_; }
+ InstanceCallComp* instance_call() const { return instance_call_; }
- // Compile type of the passed-in parameter.
- virtual RawAbstractType* CompileType() const;
- // No known propagated cid for parameters.
- virtual intptr_t GetPropagatedCid() { return propagated_cid(); }
+ const ICData* ic_data() const { return instance_call()->ic_data(); }
- virtual intptr_t ArgumentCount() const { return 0; }
+ virtual void PrintOperandsTo(BufferFormatter* f) const;
- intptr_t InputCount() const { return 0; }
- Value* InputAt(intptr_t i) const {
- UNREACHABLE();
- return NULL;
- }
- void SetInputAt(intptr_t i, Value* value) { UNREACHABLE(); }
+ DECLARE_CALL_COMPUTATION(BinaryDoubleOp)
- virtual bool CanDeoptimize() const { return false; }
+ virtual intptr_t ArgumentCount() const { return 2; }
+
+ virtual bool CanDeoptimize() const { return true; }
+ virtual intptr_t ResultCid() const;
private:
- const intptr_t index_;
+ const Token::Kind op_kind_;
+ InstanceCallComp* instance_call_;
- DISALLOW_COPY_AND_ASSIGN(ParameterInstr);
+ DISALLOW_COPY_AND_ASSIGN(BinaryDoubleOpComp);
};
-class PushArgumentInstr : public Definition {
+// Handles both Smi operations: BIT_OR and NEGATE.
+class UnarySmiOpComp : public TemplateComputation<1> {
public:
- explicit PushArgumentInstr(Value* value) : value_(value), locs_(NULL) {
+ UnarySmiOpComp(Token::Kind op_kind,
+ InstanceCallComp* instance_call,
+ Value* value)
+ : op_kind_(op_kind), instance_call_(instance_call) {
+ ASSERT((op_kind == Token::kNEGATE) || (op_kind == Token::kBIT_NOT));
ASSERT(value != NULL);
+ inputs_[0] = value;
}
- DECLARE_INSTRUCTION(PushArgument)
-
- intptr_t InputCount() const { return 1; }
- Value* InputAt(intptr_t i) const {
- ASSERT(i == 0);
- return value_;
- }
- void SetInputAt(intptr_t i, Value* value) {
- ASSERT(i == 0);
- value_ = value;
- }
-
- virtual intptr_t ArgumentCount() const { return 0; }
-
- virtual RawAbstractType* CompileType() const;
- virtual intptr_t GetPropagatedCid() { return propagated_cid(); }
-
- Value* value() const { return value_; }
-
- virtual LocationSummary* locs() {
- if (locs_ == NULL) {
- locs_ = MakeLocationSummary();
- }
- return locs_;
- }
+ Value* value() const { return inputs_[0]; }
+ Token::Kind op_kind() const { return op_kind_; }
- LocationSummary* MakeLocationSummary() const;
+ InstanceCallComp* instance_call() const { return instance_call_; }
- virtual void EmitNativeCode(FlowGraphCompiler* compiler);
+ virtual void PrintOperandsTo(BufferFormatter* f) const;
- virtual bool CanDeoptimize() const { return false; }
+ DECLARE_COMPUTATION(UnarySmiOp)
+
+ virtual bool CanDeoptimize() const { return op_kind() == Token::kNEGATE; }
+ virtual intptr_t ResultCid() const { return kSmiCid; }
private:
- Value* value_;
- LocationSummary* locs_;
+ const Token::Kind op_kind_;
+ InstanceCallComp* instance_call_;
- DISALLOW_COPY_AND_ASSIGN(PushArgumentInstr);
+ DISALLOW_COPY_AND_ASSIGN(UnarySmiOpComp);
};
-class ReturnInstr : public TemplateInstruction<1> {
+// Handles non-Smi NEGATE operations
+class NumberNegateComp : public TemplateComputation<1> {
public:
- ReturnInstr(intptr_t token_pos, Value* value)
- : deopt_id_(Isolate::Current()->GetNextDeoptId()),
- token_pos_(token_pos) {
+ NumberNegateComp(InstanceCallComp* instance_call,
+ Value* value) : instance_call_(instance_call) {
ASSERT(value != NULL);
inputs_[0] = value;
}
- DECLARE_INSTRUCTION(Return)
-
- virtual intptr_t ArgumentCount() const { return 0; }
-
- intptr_t deopt_id() const { return deopt_id_; }
- intptr_t token_pos() const { return token_pos_; }
Value* value() const { return inputs_[0]; }
- virtual LocationSummary* MakeLocationSummary() const;
+ InstanceCallComp* instance_call() const { return instance_call_; }
- virtual void EmitNativeCode(FlowGraphCompiler* compiler);
+ const ICData* ic_data() const { return instance_call()->ic_data(); }
- virtual bool CanDeoptimize() const { return false; }
+ DECLARE_COMPUTATION(NumberNegate)
+
+ virtual bool CanDeoptimize() const { return true; }
+ virtual intptr_t ResultCid() const { return kDoubleCid; }
private:
- const intptr_t deopt_id_;
- const intptr_t token_pos_;
+ InstanceCallComp* instance_call_;
- DISALLOW_COPY_AND_ASSIGN(ReturnInstr);
+ DISALLOW_COPY_AND_ASSIGN(NumberNegateComp);
};
-class ThrowInstr : public TemplateInstruction<0> {
+class CheckStackOverflowComp : public TemplateComputation<0> {
public:
- explicit ThrowInstr(intptr_t token_pos) : token_pos_(token_pos) { }
-
- DECLARE_INSTRUCTION(Throw)
-
- virtual intptr_t ArgumentCount() const { return 1; }
+ explicit CheckStackOverflowComp(intptr_t token_pos)
+ : token_pos_(token_pos) {}
intptr_t token_pos() const { return token_pos_; }
- virtual LocationSummary* MakeLocationSummary() const;
-
- virtual void EmitNativeCode(FlowGraphCompiler* compiler);
+ DECLARE_COMPUTATION(CheckStackOverflow)
virtual bool CanDeoptimize() const { return false; }
+ virtual intptr_t ResultCid() const { return kIllegalCid; }
private:
const intptr_t token_pos_;
- DISALLOW_COPY_AND_ASSIGN(ThrowInstr);
+ DISALLOW_COPY_AND_ASSIGN(CheckStackOverflowComp);
};
-class ReThrowInstr : public TemplateInstruction<0> {
+class DoubleToDoubleComp : public TemplateComputation<1> {
public:
- explicit ReThrowInstr(intptr_t token_pos) : token_pos_(token_pos) { }
+ DoubleToDoubleComp(Value* value, InstanceCallComp* instance_call)
+ : instance_call_(instance_call) {
+ ASSERT(value != NULL);
+ inputs_[0] = value;
+ }
- DECLARE_INSTRUCTION(ReThrow)
+ Value* value() const { return inputs_[0]; }
- virtual intptr_t ArgumentCount() const { return 2; }
+ InstanceCallComp* instance_call() const { return instance_call_; }
- intptr_t token_pos() const { return token_pos_; }
+ DECLARE_COMPUTATION(DoubleToDouble)
- virtual LocationSummary* MakeLocationSummary() const;
+ virtual bool CanDeoptimize() const { return true; }
+ virtual intptr_t ResultCid() const { return kDoubleCid; }
- virtual void EmitNativeCode(FlowGraphCompiler* compiler);
+ private:
+ InstanceCallComp* instance_call_;
- virtual bool CanDeoptimize() const { return false; }
+ DISALLOW_COPY_AND_ASSIGN(DoubleToDoubleComp);
+};
+
+
+class SmiToDoubleComp : public TemplateComputation<0> {
+ public:
+ explicit SmiToDoubleComp(InstanceCallComp* instance_call)
+ : instance_call_(instance_call) { }
+
+ InstanceCallComp* instance_call() const { return instance_call_; }
+
+ DECLARE_CALL_COMPUTATION(SmiToDouble)
+
+ virtual intptr_t ArgumentCount() const { return 1; }
+
+ virtual bool CanDeoptimize() const { return true; }
+ virtual intptr_t ResultCid() const { return kDoubleCid; }
private:
- const intptr_t token_pos_;
+ InstanceCallComp* instance_call_;
- DISALLOW_COPY_AND_ASSIGN(ReThrowInstr);
+ DISALLOW_COPY_AND_ASSIGN(SmiToDoubleComp);
};
-class GotoInstr : public TemplateInstruction<0> {
+class CheckClassComp : public TemplateComputation<1> {
public:
- explicit GotoInstr(JoinEntryInstr* entry)
- : successor_(entry),
- parallel_move_(NULL) { }
+ CheckClassComp(Value* value,
+ InstanceCallComp* instance_call,
+ const ICData& unary_checks)
+ : instance_call_(instance_call),
+ unary_checks_(unary_checks) {
+ ASSERT(value != NULL);
+ inputs_[0] = value;
+ }
- DECLARE_INSTRUCTION(Goto)
+ DECLARE_COMPUTATION(CheckClass)
- virtual intptr_t ArgumentCount() const { return 0; }
+ virtual bool CanDeoptimize() const { return true; }
+ virtual intptr_t ResultCid() const { return kIllegalCid; }
- JoinEntryInstr* successor() const { return successor_; }
- void set_successor(JoinEntryInstr* successor) { successor_ = successor; }
- virtual intptr_t SuccessorCount() const;
- virtual BlockEntryInstr* SuccessorAt(intptr_t index) const;
+ virtual bool AttributesEqual(Computation* other) const;
- virtual LocationSummary* MakeLocationSummary() const;
+ virtual bool HasSideEffect() const { return false; }
- virtual void EmitNativeCode(FlowGraphCompiler* compiler);
+ Value* value() const { return inputs_[0]; }
- virtual bool CanDeoptimize() const { return false; }
+ const ICData& unary_checks() const { return unary_checks_; }
- ParallelMoveInstr* parallel_move() const {
- return parallel_move_;
- }
+ virtual intptr_t deopt_id() const { return instance_call_->deopt_id(); }
- bool HasParallelMove() const {
- return parallel_move_ != NULL;
- }
+ virtual Definition* TryReplace(BindInstr* instr) const;
- ParallelMoveInstr* GetParallelMove() {
- if (parallel_move_ == NULL) {
- parallel_move_ = new ParallelMoveInstr();
- }
- return parallel_move_;
- }
+ virtual void PrintOperandsTo(BufferFormatter* f) const;
private:
- JoinEntryInstr* successor_;
+ InstanceCallComp* instance_call_;
+ const ICData& unary_checks_;
- // Parallel move that will be used by linear scan register allocator to
- // connect live ranges at the end of the block and resolve phis.
- ParallelMoveInstr* parallel_move_;
+ DISALLOW_COPY_AND_ASSIGN(CheckClassComp);
};
-class ControlInstruction : public Instruction {
+class CheckSmiComp : public TemplateComputation<1> {
public:
- ControlInstruction() : true_successor_(NULL), false_successor_(NULL) { }
+ CheckSmiComp(Value* value, intptr_t original_deopt_id)
+ : original_deopt_id_(original_deopt_id) {
+ ASSERT(value != NULL);
+ ASSERT(original_deopt_id != Isolate::kNoDeoptId);
+ inputs_[0] = value;
+ }
- virtual bool IsControl() const { return true; }
+ DECLARE_COMPUTATION(CheckSmi)
- TargetEntryInstr* true_successor() const { return true_successor_; }
- TargetEntryInstr* false_successor() const { return false_successor_; }
+ virtual bool CanDeoptimize() const { return true; }
+ virtual intptr_t ResultCid() const { return kIllegalCid; }
- TargetEntryInstr** true_successor_address() { return &true_successor_; }
- TargetEntryInstr** false_successor_address() { return &false_successor_; }
+ virtual bool AttributesEqual(Computation* other) const { return true; }
- virtual intptr_t SuccessorCount() const;
- virtual BlockEntryInstr* SuccessorAt(intptr_t index) const;
+ virtual bool HasSideEffect() const { return false; }
- virtual void DiscoverBlocks(
- BlockEntryInstr* current_block,
- GrowableArray<BlockEntryInstr*>* preorder,
- GrowableArray<BlockEntryInstr*>* postorder,
- GrowableArray<intptr_t>* parent,
- GrowableArray<BitVector*>* assigned_vars,
- intptr_t variable_count,
- intptr_t fixed_parameter_count);
+ virtual Definition* TryReplace(BindInstr* instr) const;
+ Value* value() const { return inputs_[0]; }
- void EmitBranchOnCondition(FlowGraphCompiler* compiler,
- Condition true_condition);
+ virtual intptr_t deopt_id() const { return original_deopt_id_; }
private:
- TargetEntryInstr* true_successor_;
- TargetEntryInstr* false_successor_;
+ const intptr_t original_deopt_id_;
- DISALLOW_COPY_AND_ASSIGN(ControlInstruction);
+ DISALLOW_COPY_AND_ASSIGN(CheckSmiComp);
};
-class BranchInstr : public ControlInstruction {
+class CheckArrayBoundComp : public TemplateComputation<2> {
public:
- explicit BranchInstr(ComparisonComp* computation)
- : computation_(computation), locs_(NULL) { }
-
- DECLARE_INSTRUCTION(Branch)
-
- virtual intptr_t ArgumentCount() const {
- return computation()->ArgumentCount();
+ CheckArrayBoundComp(Value* array,
+ Value* index,
+ intptr_t array_type,
+ InstanceCallComp* instance_call)
+ : array_type_(array_type), instance_call_(instance_call) {
+ ASSERT(array != NULL);
+ ASSERT(index != NULL);
+ inputs_[0] = array;
+ inputs_[1] = index;
}
- intptr_t InputCount() const { return computation()->InputCount(); }
-
- Value* InputAt(intptr_t i) const { return computation()->InputAt(i); }
- void SetInputAt(intptr_t i, Value* value) {
- computation()->SetInputAt(i, value);
- }
+ DECLARE_COMPUTATION(CheckArrayBound)
- virtual bool CanDeoptimize() const { return computation()->CanDeoptimize(); }
+ virtual bool CanDeoptimize() const { return true; }
+ virtual intptr_t ResultCid() const { return kIllegalCid; }
- ComparisonComp* computation() const { return computation_; }
- void set_computation(ComparisonComp* value) { computation_ = value; }
+ virtual bool AttributesEqual(Computation* other) const;
- virtual void EmitNativeCode(FlowGraphCompiler* compiler);
+ virtual bool HasSideEffect() const { return false; }
- virtual LocationSummary* locs() {
- if (computation_->locs_ == NULL) {
- LocationSummary* summary = computation_->MakeLocationSummary();
- // Branches don't produce a result.
- summary->set_out(Location::NoLocation());
- computation_->locs_ = summary;
- }
- return computation_->locs_;
- }
+ Value* array() const { return inputs_[0]; }
+ Value* index() const { return inputs_[1]; }
- virtual intptr_t DeoptimizationTarget() const {
- return computation_->DeoptimizationTarget();
- }
+ intptr_t array_type() const { return array_type_; }
- virtual Representation RequiredInputRepresentation(intptr_t i) const {
- return computation()->RequiredInputRepresentation(i);
- }
+ virtual intptr_t deopt_id() const { return instance_call_->deopt_id(); }
private:
- ComparisonComp* computation_;
- LocationSummary* locs_;
+ intptr_t array_type_;
+ InstanceCallComp* instance_call_;
- DISALLOW_COPY_AND_ASSIGN(BranchInstr);
+ DISALLOW_COPY_AND_ASSIGN(CheckArrayBoundComp);
};
-#undef DECLARE_INSTRUCTION
+#undef DECLARE_COMPUTATION
+
+
+// Implementation of type testers and cast functins.
+#define DEFINE_COMPUTATION_PREDICATE(ShortName, ClassName) \
+bool Computation::Is##ShortName() const { \
+ return computation_kind() == k##ShortName; \
+} \
+const ClassName* Computation::As##ShortName() const { \
+ if (!Is##ShortName()) return NULL; \
+ return static_cast<const ClassName*>(this); \
+} \
+ClassName* Computation::As##ShortName() { \
+ if (!Is##ShortName()) return NULL; \
+ return static_cast<ClassName*>(this); \
+}
+FOR_EACH_COMPUTATION(DEFINE_COMPUTATION_PREDICATE)
+#undef DEFINE_COMPUTATION_PREDICATE
class Environment : public ZoneAllocated {
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698