Index: src/mips/codegen-mips.h |
=================================================================== |
--- src/mips/codegen-mips.h (revision 4138) |
+++ src/mips/codegen-mips.h (working copy) |
@@ -42,7 +42,77 @@ |
enum TypeofState { INSIDE_TYPEOF, NOT_INSIDE_TYPEOF }; |
-// ------------------------------------------------------------------------- |
+// ----------------------------------------------------------------------------- |
+// Reference support |
+ |
+// A reference is a C++ stack-allocated object that keeps an ECMA |
+// reference on the execution stack while in scope. For variables |
+// the reference is empty, indicating that it isn't necessary to |
+// store state on the stack for keeping track of references to those. |
+// For properties, we keep either one (named) or two (indexed) values |
+// on the execution stack to represent the reference. |
+class Reference BASE_EMBEDDED { |
+ public: |
+ // The values of the types is important, see size(). |
+ enum Type { UNLOADED = -2, ILLEGAL = -1, SLOT = 0, NAMED = 1, KEYED = 2 }; |
+ Reference(CodeGenerator* cgen, |
+ Expression* expression, |
+ bool persist_after_get = false); |
+ ~Reference(); |
+ |
+ Expression* expression() const { return expression_; } |
+ Type type() const { return type_; } |
+ void set_type(Type value) { |
+ ASSERT_EQ(ILLEGAL, type_); |
+ type_ = value; |
+ } |
+ |
+ void set_unloaded() { |
+ ASSERT_NE(ILLEGAL, type_); |
+ ASSERT_NE(UNLOADED, type_); |
+ type_ = UNLOADED; |
+ } |
+ // The size the reference takes up on the stack. |
+ int size() const { |
+ return (type_ < SLOT) ? 0 : type_; |
+ } |
+ |
+ bool is_illegal() const { return type_ == ILLEGAL; } |
+ bool is_slot() const { return type_ == SLOT; } |
+ bool is_property() const { return type_ == NAMED || type_ == KEYED; } |
+ bool is_unloaded() const { return type_ == UNLOADED; } |
+ |
+ // Return the name. Only valid for named property references. |
+ Handle<String> GetName(); |
+ |
+ // Generate code to push the value of the reference on top of the |
+ // expression stack. The reference is expected to be already on top of |
+ // the expression stack, and it is consumed by the call unless the |
+ // reference is for a compound assignment. |
+ // If the reference is not consumed, it is left in place under its value. |
+ void GetValue(); |
+ |
+ // Generate code to pop a reference, push the value of the reference, |
+ // and then spill the stack frame. |
+ inline void GetValueAndSpill(); |
+ |
+ // Generate code to store the value on top of the expression stack in the |
+ // reference. The reference is expected to be immediately below the value |
+ // on the expression stack. The value is stored in the location specified |
+ // by the reference, and is left on top of the stack, after the reference |
+ // is popped from beneath it (unloaded). |
+ void SetValue(InitState init_state); |
+ |
+ private: |
+ CodeGenerator* cgen_; |
+ Expression* expression_; |
+ Type type_; |
+ // Keep the reference on the stack after get, so it can be used by set later. |
+ bool persist_after_get_; |
+}; |
+ |
+ |
+// ----------------------------------------------------------------------------- |
// Code generation state |
// The state is passed down the AST by the code generator (and back up, in |
@@ -89,7 +159,7 @@ |
-// ------------------------------------------------------------------------- |
+// ----------------------------------------------------------------------------- |
// CodeGenerator |
class CodeGenerator: public AstVisitor { |
@@ -152,7 +222,7 @@ |
// Number of instructions used for the JS return sequence. The constant is |
// used by the debugger to patch the JS return sequence. |
- static const int kJSReturnSequenceLength = 6; |
+ static const int kJSReturnSequenceLength = 7; |
// If the name is an inline runtime function call return the number of |
// expected arguments. Otherwise return -1. |
@@ -186,9 +256,51 @@ |
AST_NODE_LIST(DEF_VISIT) |
#undef DEF_VISIT |
+ // Visit a statement and then spill the virtual frame if control flow can |
+ // reach the end of the statement (ie, it does not exit via break, |
+ // continue, return, or throw). This function is used temporarily while |
+ // the code generator is being transformed. |
+ inline void VisitAndSpill(Statement* statement); |
+ |
+ // Visit a list of statements and then spill the virtual frame if control |
+ // flow can reach the end of the list. |
+ inline void VisitStatementsAndSpill(ZoneList<Statement*>* statements); |
+ |
// Main code generation function |
void Generate(CompilationInfo* info); |
+ // The following are used by class Reference. |
+ void LoadReference(Reference* ref); |
+ void UnloadReference(Reference* ref); |
+ |
+ MemOperand ContextOperand(Register context, int index) const { |
+ return MemOperand(context, Context::SlotOffset(index)); |
+ } |
+ |
+ MemOperand SlotOperand(Slot* slot, Register tmp); |
+ |
+ // Expressions |
+ MemOperand GlobalObject() const { |
+ return ContextOperand(cp, Context::GLOBAL_INDEX); |
+ } |
+ |
+ void LoadCondition(Expression* x, |
+ JumpTarget* true_target, |
+ JumpTarget* false_target, |
+ bool force_cc); |
+ void Load(Expression* x); |
+ void LoadGlobal(); |
+ |
+ // Generate code to push the value of an expression on top of the frame |
+ // and then spill the frame fully to memory. This function is used |
+ // temporarily while the code generator is being transformed. |
+ inline void LoadAndSpill(Expression* expression); |
+ |
+ // Read a value from a slot and leave it on top of the expression stack. |
+ void LoadFromSlot(Slot* slot, TypeofState typeof_state); |
+ // Store the value on top of the stack to a slot. |
+ void StoreToSlot(Slot* slot, InitState init_state); |
+ |
struct InlineRuntimeLUT { |
void (CodeGenerator::*method)(ZoneList<Expression*>*); |
const char* name; |
@@ -290,7 +402,6 @@ |
CompilationInfo* info_; |
// Code generation state |
- Scope* scope_; |
VirtualFrame* frame_; |
RegisterAllocator* allocator_; |
Condition cc_reg_; |