Index: src/full-codegen.h |
=================================================================== |
--- src/full-codegen.h (revision 5450) |
+++ src/full-codegen.h (working copy) |
@@ -71,10 +71,7 @@ |
info_(NULL), |
nesting_stack_(NULL), |
loop_depth_(0), |
- location_(kStack), |
- true_label_(NULL), |
- false_label_(NULL), |
- fall_through_(NULL) { |
+ context_(NULL) { |
} |
static Handle<Code> MakeCode(CompilationInfo* info); |
@@ -232,11 +229,6 @@ |
DISALLOW_COPY_AND_ASSIGN(ForIn); |
}; |
- enum Location { |
- kAccumulator, |
- kStack |
- }; |
- |
enum ConstantOperand { |
kNoConstants, |
kLeftConstant, |
@@ -256,39 +248,6 @@ |
Expression* left, |
Expression* right); |
- // Emit code to convert a pure value (in a register, slot, as a literal, |
- // or on top of the stack) into the result expected according to an |
- // expression context. |
- void Apply(Expression::Context context, Register reg); |
- |
- // Slot cannot have type Slot::LOOKUP. |
- void Apply(Expression::Context context, Slot* slot); |
- |
- void Apply(Expression::Context context, Literal* lit); |
- void ApplyTOS(Expression::Context context); |
- |
- // Emit code to discard count elements from the top of stack, then convert |
- // a pure value into the result expected according to an expression |
- // context. |
- void DropAndApply(int count, Expression::Context context, Register reg); |
- |
- // Set up branch labels for a test expression. |
- void PrepareTest(Label* materialize_true, |
- Label* materialize_false, |
- Label** if_true, |
- Label** if_false, |
- Label** fall_through); |
- |
- // Emit code to convert pure control flow to a pair of labels into the |
- // result expected according to an expression context. |
- void Apply(Expression::Context context, |
- Label* materialize_true, |
- Label* materialize_false); |
- |
- // Emit code to convert constant control flow (true or false) into |
- // the result expected according to an expression context. |
- void Apply(Expression::Context context, bool flag); |
- |
// Helper function to convert a pure value into a test context. The value |
// is expected on the stack or the accumulator, depending on the platform. |
// See the platform-specific implementation for details. |
@@ -310,39 +269,26 @@ |
MemOperand EmitSlotSearch(Slot* slot, Register scratch); |
void VisitForEffect(Expression* expr) { |
- Expression::Context saved_context = context_; |
- context_ = Expression::kEffect; |
+ EffectContext context(this); |
Visit(expr); |
- context_ = saved_context; |
} |
- void VisitForValue(Expression* expr, Location where) { |
- Expression::Context saved_context = context_; |
- Location saved_location = location_; |
- context_ = Expression::kValue; |
- location_ = where; |
+ void VisitForAccumulatorValue(Expression* expr) { |
+ AccumulatorValueContext context(this); |
Visit(expr); |
- context_ = saved_context; |
- location_ = saved_location; |
} |
+ void VisitForStackValue(Expression* expr) { |
+ StackValueContext context(this); |
+ Visit(expr); |
+ } |
+ |
void VisitForControl(Expression* expr, |
Label* if_true, |
Label* if_false, |
Label* fall_through) { |
- Expression::Context saved_context = context_; |
- Label* saved_true = true_label_; |
- Label* saved_false = false_label_; |
- Label* saved_fall_through = fall_through_; |
- context_ = Expression::kTest; |
- true_label_ = if_true; |
- false_label_ = if_false; |
- fall_through_ = fall_through; |
+ TestContext context(this, if_true, if_false, fall_through); |
Visit(expr); |
- context_ = saved_context; |
- true_label_ = saved_true; |
- false_label_ = saved_false; |
- fall_through_ = saved_fall_through; |
} |
void VisitDeclarations(ZoneList<Declaration*>* declarations); |
@@ -389,7 +335,7 @@ |
TypeofState typeof_state, |
Label* slow, |
Label* done); |
- void EmitVariableLoad(Variable* expr, Expression::Context context); |
+ void EmitVariableLoad(Variable* expr); |
// Platform-specific support for allocating a new closure based on |
// the given function info. |
@@ -408,14 +354,12 @@ |
// Apply the compound assignment operator. Expects the left operand on top |
// of the stack and the right one in the accumulator. |
void EmitBinaryOp(Token::Value op, |
- Expression::Context context, |
OverwriteMode mode); |
// Helper functions for generating inlined smi code for certain |
// binary operations. |
void EmitInlineSmiBinaryOp(Expression* expr, |
Token::Value op, |
- Expression::Context context, |
OverwriteMode mode, |
Expression* left, |
Expression* right, |
@@ -423,31 +367,26 @@ |
void EmitConstantSmiBinaryOp(Expression* expr, |
Token::Value op, |
- Expression::Context context, |
OverwriteMode mode, |
bool left_is_constant_smi, |
Smi* value); |
void EmitConstantSmiBitOp(Expression* expr, |
Token::Value op, |
- Expression::Context context, |
OverwriteMode mode, |
Smi* value); |
void EmitConstantSmiShiftOp(Expression* expr, |
Token::Value op, |
- Expression::Context context, |
OverwriteMode mode, |
Smi* value); |
void EmitConstantSmiAdd(Expression* expr, |
- Expression::Context context, |
OverwriteMode mode, |
bool left_is_constant_smi, |
Smi* value); |
void EmitConstantSmiSub(Expression* expr, |
- Expression::Context context, |
OverwriteMode mode, |
bool left_is_constant_smi, |
Smi* value); |
@@ -459,8 +398,7 @@ |
// Complete a variable assignment. The right-hand-side value is expected |
// in the accumulator. |
void EmitVariableAssignment(Variable* var, |
- Token::Value op, |
- Expression::Context context); |
+ Token::Value op); |
// Complete a named property assignment. The receiver is expected on top |
// of the stack and the right-hand-side value in the accumulator. |
@@ -492,6 +430,10 @@ |
MacroAssembler* masm() { return masm_; } |
+ class ExpressionContext; |
+ const ExpressionContext* context() { return context_; } |
+ void set_new_context(const ExpressionContext* context) { context_ = context; } |
+ |
Handle<Script> script() { return info_->script(); } |
bool is_eval() { return info_->is_eval(); } |
FunctionLiteral* function() { return info_->function(); } |
@@ -518,14 +460,8 @@ |
// Handles the shortcutted logical binary operations in VisitBinaryOperation. |
void EmitLogicalOperation(BinaryOperation* expr); |
- void VisitForTypeofValue(Expression* expr, Location where); |
+ void VisitForTypeofValue(Expression* expr); |
- void VisitLogicalForValue(Expression* expr, |
- Token::Value op, |
- Location where, |
- Label* done); |
- |
- |
MacroAssembler* masm_; |
CompilationInfo* info_; |
@@ -533,12 +469,178 @@ |
NestedStatement* nesting_stack_; |
int loop_depth_; |
- Expression::Context context_; |
- Location location_; |
- Label* true_label_; |
- Label* false_label_; |
- Label* fall_through_; |
+ class ExpressionContext { |
+ public: |
+ explicit ExpressionContext(FullCodeGenerator* codegen) |
+ : masm_(codegen->masm()), old_(codegen->context()), codegen_(codegen) { |
+ codegen->set_new_context(this); |
+ } |
+ virtual ~ExpressionContext() { |
+ codegen_->set_new_context(old_); |
+ } |
+ |
+ // Convert constant control flow (true or false) to the result expected for |
+ // this expression context. |
+ virtual void Plug(bool flag) const = 0; |
+ |
+ // Emit code to convert a pure value (in a register, slot, as a literal, |
+ // or on top of the stack) into the result expected according to this |
+ // expression context. |
+ virtual void Plug(Register reg) const = 0; |
+ |
+ // Emit code to convert pure control flow to a pair of labels into the |
+ // result expected according to this expression context. |
+ virtual void Plug(Label* materialize_true, |
+ Label* materialize_false) const = 0; |
+ |
+ virtual void Plug(Slot* slot) const = 0; |
+ virtual void Plug(Handle<Object> lit) const = 0; |
+ virtual void Plug(Heap::RootListIndex index) const = 0; |
+ virtual void PlugTOS() const = 0; |
+ |
+ // Emit code to discard count elements from the top of stack, then convert |
+ // a pure value into the result expected according to this expression |
+ // context. |
+ virtual void DropAndPlug(int count, Register reg) const = 0; |
+ |
+ // For shortcutting operations || and &&. |
+ virtual void EmitLogicalLeft(BinaryOperation* expr, |
+ Label* eval_right, |
+ Label* done) const = 0; |
+ |
+ // Set up branch labels for a test expression. |
+ virtual void PrepareTest(Label* materialize_true, |
+ Label* materialize_false, |
+ Label** if_true, |
+ Label** if_false, |
+ Label** fall_through) const = 0; |
+ |
+ // Returns true if we are evaluating only for side effects (ie if the result |
+ // will be discarded. |
+ virtual bool IsEffect() const { return false; } |
+ |
+ // Returns true if we are branching on the value rather than materializing |
+ // it. |
+ virtual bool IsTest() const { return false; } |
+ |
+ protected: |
+ FullCodeGenerator* codegen() const { return codegen_; } |
+ MacroAssembler* masm() const { return masm_; } |
+ MacroAssembler* masm_; |
+ |
+ private: |
+ const ExpressionContext* old_; |
+ FullCodeGenerator* codegen_; |
+ }; |
+ |
+ class AccumulatorValueContext : public ExpressionContext { |
+ public: |
+ explicit AccumulatorValueContext(FullCodeGenerator* codegen) |
+ : ExpressionContext(codegen) { } |
+ |
+ virtual void Plug(bool flag) const; |
+ virtual void Plug(Register reg) const; |
+ virtual void Plug(Label* materialize_true, Label* materialize_false) const; |
+ virtual void Plug(Slot* slot) const; |
+ virtual void Plug(Handle<Object> lit) const; |
+ virtual void Plug(Heap::RootListIndex) const; |
+ virtual void PlugTOS() const; |
+ virtual void DropAndPlug(int count, Register reg) const; |
+ virtual void EmitLogicalLeft(BinaryOperation* expr, |
+ Label* eval_right, |
+ Label* done) const; |
+ virtual void PrepareTest(Label* t, |
+ Label* f, |
+ Label** i_t, |
+ Label** i_f, |
+ Label** ft) const; |
+ }; |
+ |
+ class StackValueContext : public ExpressionContext { |
+ public: |
+ explicit StackValueContext(FullCodeGenerator* codegen) |
+ : ExpressionContext(codegen) { } |
+ |
+ virtual void Plug(bool flag) const; |
+ virtual void Plug(Register reg) const; |
+ virtual void Plug(Label* materialize_true, Label* materialize_false) const; |
+ virtual void Plug(Slot* slot) const; |
+ virtual void Plug(Handle<Object> lit) const; |
+ virtual void Plug(Heap::RootListIndex) const; |
+ virtual void PlugTOS() const; |
+ virtual void DropAndPlug(int count, Register reg) const; |
+ virtual void EmitLogicalLeft(BinaryOperation* expr, |
+ Label* eval_right, |
+ Label* done) const; |
+ virtual void PrepareTest(Label* t, |
+ Label* f, |
+ Label** i_t, |
+ Label** i_f, |
+ Label** ft) const; |
+ }; |
+ |
+ class TestContext : public ExpressionContext { |
+ public: |
+ explicit TestContext(FullCodeGenerator* codegen, |
+ Label* true_label, |
+ Label* false_label, |
+ Label* fall_through) |
+ : ExpressionContext(codegen), |
+ true_label_(true_label), |
+ false_label_(false_label), |
+ fall_through_(fall_through) { } |
+ |
+ virtual void Plug(bool flag) const; |
+ virtual void Plug(Register reg) const; |
+ virtual void Plug(Label* materialize_true, Label* materialize_false) const; |
+ virtual void Plug(Slot* slot) const; |
+ virtual void Plug(Handle<Object> lit) const; |
+ virtual void Plug(Heap::RootListIndex) const; |
+ virtual void PlugTOS() const; |
+ virtual void DropAndPlug(int count, Register reg) const; |
+ virtual void EmitLogicalLeft(BinaryOperation* expr, |
+ Label* eval_right, |
+ Label* done) const; |
+ virtual void PrepareTest(Label* t, |
+ Label* f, |
+ Label** i_t, |
+ Label** i_f, |
+ Label** ft) const; |
+ virtual bool IsTest() const { return true; } |
+ |
+ private: |
+ Label* true_label_; |
+ Label* false_label_; |
+ Label* fall_through_; |
+ }; |
+ |
+ class EffectContext : public ExpressionContext { |
+ public: |
+ explicit EffectContext(FullCodeGenerator* codegen) |
+ : ExpressionContext(codegen) { } |
+ |
+ virtual void Plug(bool flag) const; |
+ virtual void Plug(Register reg) const; |
+ virtual void Plug(Label* materialize_true, Label* materialize_false) const; |
+ virtual void Plug(Slot* slot) const; |
+ virtual void Plug(Handle<Object> lit) const; |
+ virtual void Plug(Heap::RootListIndex) const; |
+ virtual void PlugTOS() const; |
+ virtual void DropAndPlug(int count, Register reg) const; |
+ virtual void EmitLogicalLeft(BinaryOperation* expr, |
+ Label* eval_right, |
+ Label* done) const; |
+ virtual void PrepareTest(Label* t, |
+ Label* f, |
+ Label** i_t, |
+ Label** i_f, |
+ Label** ft) const; |
+ virtual bool IsEffect() const { return true; } |
+ }; |
+ |
+ const ExpressionContext* context_; |
+ |
friend class NestedStatement; |
DISALLOW_COPY_AND_ASSIGN(FullCodeGenerator); |