| Index: src/cfg.h
|
| ===================================================================
|
| --- src/cfg.h (revision 2635)
|
| +++ src/cfg.h (working copy)
|
| @@ -43,21 +43,23 @@
|
| // Instructions are described by the following grammar.
|
| //
|
| // <Instruction> ::=
|
| -// BinaryOpInstr <Location> Token::Value <Value> <Value>
|
| -// | ReturnInstr Effect <Value>
|
| +// MoveInstr <Location> <Value>
|
| +// | BinaryOpInstr <Location> Token::Value <Value> <Value>
|
| +// | ReturnInstr Nowhere <Value>
|
| +// | PositionInstr <Int>
|
| //
|
| // Values are trivial expressions:
|
| //
|
| // <Value> ::= Constant | <Location>
|
| //
|
| // Locations are storable values ('lvalues'). They can be slots,
|
| -// compiler-generated temporaries, or the special location 'Effect'
|
| +// compiler-generated temporaries, or the special location 'Nowhere'
|
| // indicating that no value is needed.
|
| //
|
| // <Location> ::=
|
| // SlotLocation Slot::Type <Index>
|
| // | TempLocation
|
| -// | Effect
|
| +// | Nowhere
|
|
|
|
|
| // Administrative nodes: There are several types of 'administrative' nodes
|
| @@ -95,8 +97,8 @@
|
| // The shared global exit node for all exits from the function.
|
| ExitNode* exit() { return global_exit_; }
|
|
|
| - // A singleton effect location.
|
| - Location* effect_location() { return effect_; }
|
| + // A singleton.
|
| + Location* nowhere() { return nowhere_; }
|
|
|
| #ifdef DEBUG
|
| int next_node_number() { return node_counter_++; }
|
| @@ -107,7 +109,7 @@
|
| static CfgGlobals* top_;
|
| FunctionLiteral* global_fun_;
|
| ExitNode* global_exit_;
|
| - Location* effect_;
|
| + Location* nowhere_;
|
|
|
| #ifdef DEBUG
|
| // Used to number nodes and temporaries when printing.
|
| @@ -119,6 +121,8 @@
|
| };
|
|
|
|
|
| +class SlotLocation;
|
| +
|
| // Values represent trivial source expressions: ones with no side effects
|
| // and that do not require code to be generated.
|
| class Value : public ZoneObject {
|
| @@ -134,6 +138,9 @@
|
| // True if the value is a compiler-generated temporary location.
|
| virtual bool is_temporary() { return false; }
|
|
|
| + // True if the value is a slot location.
|
| + virtual bool is_slot() { return false; }
|
| +
|
| // Support for fast-compilation mode:
|
|
|
| // Move the value into a register.
|
| @@ -142,6 +149,9 @@
|
| // Push the value on the stack.
|
| virtual void Push(MacroAssembler* masm) = 0;
|
|
|
| + // Move the value into a slot location.
|
| + virtual void MoveToSlot(MacroAssembler* masm, SlotLocation* loc) = 0;
|
| +
|
| #ifdef DEBUG
|
| virtual void Print() = 0;
|
| #endif
|
| @@ -158,6 +168,7 @@
|
| // Support for fast-compilation mode.
|
| void Get(MacroAssembler* masm, Register reg);
|
| void Push(MacroAssembler* masm);
|
| + void MoveToSlot(MacroAssembler* masm, SlotLocation* loc);
|
|
|
| #ifdef DEBUG
|
| void Print();
|
| @@ -173,9 +184,9 @@
|
| public:
|
| virtual ~Location() {}
|
|
|
| - // Static factory function returning the singleton effect location.
|
| - static Location* Effect() {
|
| - return CfgGlobals::current()->effect_location();
|
| + // Static factory function returning the singleton nowhere location.
|
| + static Location* Nowhere() {
|
| + return CfgGlobals::current()->nowhere();
|
| }
|
|
|
| // Support for fast-compilation mode:
|
| @@ -191,29 +202,34 @@
|
| // temporary it was not allocated to the stack.
|
| virtual void Push(MacroAssembler* masm) = 0;
|
|
|
| + // Emit code to move a value into this location.
|
| + virtual void Move(MacroAssembler* masm, Value* value) = 0;
|
| +
|
| #ifdef DEBUG
|
| virtual void Print() = 0;
|
| #endif
|
| };
|
|
|
|
|
| -// Effect is a special (singleton) location that indicates the value of a
|
| +// Nowhere is a special (singleton) location that indicates the value of a
|
| // computation is not needed (though its side effects are).
|
| -class Effect : public Location {
|
| +class Nowhere : public Location {
|
| public:
|
| - // We should not try to emit code to read Effect.
|
| + // We should not try to emit code to read Nowhere.
|
| void Get(MacroAssembler* masm, Register reg) { UNREACHABLE(); }
|
| void Push(MacroAssembler* masm) { UNREACHABLE(); }
|
| + void MoveToSlot(MacroAssembler* masm, SlotLocation* loc) { UNREACHABLE(); }
|
|
|
| - // Setting Effect is ignored.
|
| + // Setting Nowhere is ignored.
|
| void Set(MacroAssembler* masm, Register reg) {}
|
| + void Move(MacroAssembler* masm, Value* value) {}
|
|
|
| #ifdef DEBUG
|
| void Print();
|
| #endif
|
|
|
| private:
|
| - Effect() {}
|
| + Nowhere() {}
|
|
|
| friend class CfgGlobals;
|
| };
|
| @@ -225,14 +241,25 @@
|
| public:
|
| SlotLocation(Slot::Type type, int index) : type_(type), index_(index) {}
|
|
|
| + // Cast accessor.
|
| + static SlotLocation* cast(Value* value) {
|
| + ASSERT(value->is_slot());
|
| + return reinterpret_cast<SlotLocation*>(value);
|
| + }
|
| +
|
| // Accessors.
|
| Slot::Type type() { return type_; }
|
| int index() { return index_; }
|
|
|
| + // Predicates.
|
| + bool is_slot() { return true; }
|
| +
|
| // Support for fast-compilation mode.
|
| void Get(MacroAssembler* masm, Register reg);
|
| void Set(MacroAssembler* masm, Register reg);
|
| void Push(MacroAssembler* masm);
|
| + void Move(MacroAssembler* masm, Value* value);
|
| + void MoveToSlot(MacroAssembler* masm, SlotLocation* loc);
|
|
|
| #ifdef DEBUG
|
| void Print();
|
| @@ -252,21 +279,21 @@
|
| public:
|
| // Fast-compilation mode allocation decisions.
|
| enum Where {
|
| - NOWHERE, // Not yet allocated.
|
| - ACCUMULATOR, // Allocated to the dedicated accumulator register.
|
| - STACK // " " " " stack.
|
| + NOT_ALLOCATED, // Not yet allocated.
|
| + ACCUMULATOR, // Allocated to the dedicated accumulator register.
|
| + STACK // " " " " stack.
|
| };
|
|
|
| - TempLocation() : where_(NOWHERE) {
|
| + TempLocation() : where_(NOT_ALLOCATED) {
|
| #ifdef DEBUG
|
| number_ = -1;
|
| #endif
|
| }
|
|
|
| // Cast accessor.
|
| - static TempLocation* cast(Location* loc) {
|
| - ASSERT(loc->is_temporary());
|
| - return reinterpret_cast<TempLocation*>(loc);
|
| + static TempLocation* cast(Value* value) {
|
| + ASSERT(value->is_temporary());
|
| + return reinterpret_cast<TempLocation*>(value);
|
| }
|
|
|
| // Accessors.
|
| @@ -281,6 +308,8 @@
|
| void Get(MacroAssembler* masm, Register reg);
|
| void Set(MacroAssembler* masm, Register reg);
|
| void Push(MacroAssembler* masm);
|
| + void Move(MacroAssembler* masm, Value* value);
|
| + void MoveToSlot(MacroAssembler* masm, SlotLocation* loc);
|
|
|
| #ifdef DEBUG
|
| int number() {
|
| @@ -306,16 +335,16 @@
|
| class Instruction : public ZoneObject {
|
| public:
|
| // Every instruction has a location where its result is stored (which may
|
| - // be Effect, the default).
|
| - Instruction() : loc_(CfgGlobals::current()->effect_location()) {}
|
| + // be Nowhere, the default).
|
| + Instruction() : location_(CfgGlobals::current()->nowhere()) {}
|
|
|
| - explicit Instruction(Location* loc) : loc_(loc) {}
|
| + explicit Instruction(Location* location) : location_(location) {}
|
|
|
| virtual ~Instruction() {}
|
|
|
| // Accessors.
|
| - Location* location() { return loc_; }
|
| - void set_location(Location* loc) { loc_ = loc; }
|
| + Location* location() { return location_; }
|
| + void set_location(Location* location) { location_ = location; }
|
|
|
| // Support for fast-compilation mode:
|
|
|
| @@ -332,7 +361,7 @@
|
| #endif
|
|
|
| protected:
|
| - Location* loc_;
|
| + Location* location_;
|
| };
|
|
|
|
|
| @@ -360,14 +389,40 @@
|
| };
|
|
|
|
|
| +// Move a value to a location.
|
| +class MoveInstr : public Instruction {
|
| + public:
|
| + MoveInstr(Location* loc, Value* value) : Instruction(loc), value_(value) {}
|
| +
|
| + // Accessors.
|
| + Value* value() { return value_; }
|
| +
|
| + // Support for fast-compilation mode.
|
| + void Compile(MacroAssembler* masm);
|
| + void FastAllocate(TempLocation* temp);
|
| +
|
| +#ifdef DEBUG
|
| + void Print();
|
| +#endif
|
| +
|
| + private:
|
| + Value* value_;
|
| +};
|
| +
|
| +
|
| // Perform a (non-short-circuited) binary operation on a pair of values,
|
| // leaving the result in a location.
|
| class BinaryOpInstr : public Instruction {
|
| public:
|
| - BinaryOpInstr(Location* loc, Token::Value op, Value* val0, Value* val1)
|
| - : Instruction(loc), op_(op), val0_(val0), val1_(val1) {
|
| + BinaryOpInstr(Location* loc, Token::Value op, Value* value0, Value* value1)
|
| + : Instruction(loc), op_(op), value0_(value0), value1_(value1) {
|
| }
|
|
|
| + // Accessors.
|
| + Token::Value op() { return op_; }
|
| + Value* value0() { return value0_; }
|
| + Value* value1() { return value1_; }
|
| +
|
| // Support for fast-compilation mode.
|
| void Compile(MacroAssembler* masm);
|
| void FastAllocate(TempLocation* temp);
|
| @@ -378,8 +433,8 @@
|
|
|
| private:
|
| Token::Value op_;
|
| - Value* val0_;
|
| - Value* val1_;
|
| + Value* value0_;
|
| + Value* value1_;
|
| };
|
|
|
|
|
| @@ -390,7 +445,6 @@
|
| // successor is the global exit node for the current function.
|
| class ReturnInstr : public Instruction {
|
| public:
|
| - // Location is always Effect.
|
| explicit ReturnInstr(Value* value) : value_(value) {}
|
|
|
| virtual ~ReturnInstr() {}
|
| @@ -605,6 +659,52 @@
|
| };
|
|
|
|
|
| +// An implementation of a set of locations (currently slot locations).
|
| +class LocationSet BASE_EMBEDDED {
|
| + public:
|
| + // Construct an empty location set.
|
| + LocationSet() : parameters_(0), locals_(0) {}
|
| +
|
| + // Raw accessors.
|
| + uintptr_t parameters() { return parameters_; }
|
| + uintptr_t locals() { return locals_; }
|
| +
|
| + // Insert an element.
|
| + void AddElement(SlotLocation* location) {
|
| + if (location->type() == Slot::PARAMETER) {
|
| + // Parameter indexes begin with -1 ('this').
|
| + ASSERT(location->index() < kPointerSize - 1);
|
| + parameters_ |= (1 << (location->index() + 1));
|
| + } else {
|
| + ASSERT(location->type() == Slot::LOCAL);
|
| + ASSERT(location->index() < kPointerSize);
|
| + locals_ |= (1 << location->index());
|
| + }
|
| + }
|
| +
|
| + // (Destructively) compute the union with another set.
|
| + void Union(LocationSet* other) {
|
| + parameters_ |= other->parameters();
|
| + locals_ |= other->locals();
|
| + }
|
| +
|
| + bool Contains(SlotLocation* location) {
|
| + if (location->type() == Slot::PARAMETER) {
|
| + ASSERT(location->index() < kPointerSize - 1);
|
| + return (parameters_ & (1 << (location->index() + 1)));
|
| + } else {
|
| + ASSERT(location->type() == Slot::LOCAL);
|
| + ASSERT(location->index() < kPointerSize);
|
| + return (locals_ & (1 << location->index()));
|
| + }
|
| + }
|
| +
|
| + private:
|
| + uintptr_t parameters_;
|
| + uintptr_t locals_;
|
| +};
|
| +
|
| +
|
| // An ExpressionBuilder traverses an expression and returns an open CFG
|
| // fragment (currently a possibly empty list of instructions represented by
|
| // a singleton instruction block) and the expression's value.
|
| @@ -612,15 +712,23 @@
|
| // Failure is to build the CFG is indicated by a NULL CFG.
|
| class ExpressionBuilder : public AstVisitor {
|
| public:
|
| - ExpressionBuilder() : value_(NULL), cfg_(NULL) {}
|
| + ExpressionBuilder() : value_(NULL), graph_(NULL), destination_(NULL) {}
|
|
|
| // Result accessors.
|
| Value* value() { return value_; }
|
| - Cfg* cfg() { return cfg_; }
|
| + Cfg* graph() { return graph_; }
|
| + LocationSet* assigned_vars() { return &assigned_vars_; }
|
|
|
| - void Build(Expression* expr) {
|
| + // Build the cfg for an expression and remember its value. The
|
| + // destination is a 'hint' where the value should go which may be ignored.
|
| + // NULL is used to indicate no preference.
|
| + //
|
| + // Concretely, if the expression needs to generate a temporary for its
|
| + // value, it should use the passed destination or generate one if NULL.
|
| + void Build(Expression* expr, Location* destination) {
|
| value_ = NULL;
|
| - cfg_ = new Cfg();
|
| + graph_ = new Cfg();
|
| + destination_ = destination;
|
| Visit(expr);
|
| }
|
|
|
| @@ -630,8 +738,13 @@
|
| #undef DECLARE_VISIT
|
|
|
| private:
|
| + // State for the visitor. Output parameters.
|
| Value* value_;
|
| - Cfg* cfg_;
|
| + Cfg* graph_;
|
| + LocationSet assigned_vars_;
|
| +
|
| + // Input parameters.
|
| + Location* destination_;
|
| };
|
|
|
|
|
| @@ -640,9 +753,9 @@
|
| // accumulator.
|
| class StatementBuilder : public AstVisitor {
|
| public:
|
| - StatementBuilder() : cfg_(new Cfg()) {}
|
| + StatementBuilder() : graph_(new Cfg()) {}
|
|
|
| - Cfg* cfg() { return cfg_; }
|
| + Cfg* graph() { return graph_; }
|
|
|
| void VisitStatements(ZoneList<Statement*>* stmts);
|
|
|
| @@ -652,7 +765,7 @@
|
| #undef DECLARE_VISIT
|
|
|
| private:
|
| - Cfg* cfg_;
|
| + Cfg* graph_;
|
| };
|
|
|
|
|
|
|