Revision: 3448
Author: [email protected]
Date: Thu Dec 10 06:06:08 2009
Log: Fast codegen: Working break and continue.
Started framework for all intra-functional outward control transfers,
including handling of try/finally.

Review URL: http://codereview.chromium.org/466033

http://code.google.com/p/v8/source/detail?r=3448

Modified:
  /branches/bleeding_edge/src/arm/fast-codegen-arm.cc
  /branches/bleeding_edge/src/arm/macro-assembler-arm.cc
  /branches/bleeding_edge/src/arm/macro-assembler-arm.h
  /branches/bleeding_edge/src/compiler.cc
  /branches/bleeding_edge/src/fast-codegen.cc
  /branches/bleeding_edge/src/fast-codegen.h
  /branches/bleeding_edge/src/ia32/fast-codegen-ia32.cc
  /branches/bleeding_edge/src/ia32/macro-assembler-ia32.cc
  /branches/bleeding_edge/src/ia32/macro-assembler-ia32.h
  /branches/bleeding_edge/src/x64/fast-codegen-x64.cc
  /branches/bleeding_edge/src/x64/macro-assembler-x64.cc
  /branches/bleeding_edge/src/x64/macro-assembler-x64.h

=======================================
--- /branches/bleeding_edge/src/arm/fast-codegen-arm.cc Wed Dec  9 05:06:08  
2009
+++ /branches/bleeding_edge/src/arm/fast-codegen-arm.cc Thu Dec 10 06:06:08  
2009
@@ -519,21 +519,6 @@
    __ CallRuntime(Runtime::kDeclareGlobals, 3);
    // Return value is ignored.
  }
-
-
-void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
-  Comment cmnt(masm_, "[ ReturnStatement");
-  Expression* expr = stmt->expression();
-  // Complete the statement based on the type of the subexpression.
-  if (expr->AsLiteral() != NULL) {
-    __ mov(r0, Operand(expr->AsLiteral()->handle()));
-  } else {
-    ASSERT_EQ(Expression::kValue, expr->context());
-    Visit(expr);
-    __ pop(r0);
-  }
-  EmitReturnSequence(stmt->statement_pos());
-}


  void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
@@ -1667,6 +1652,8 @@
    Move(expr->context(), r0);
  }

+
+Register FastCodeGenerator::result_register() { return r0; }

  #undef __

=======================================
--- /branches/bleeding_edge/src/arm/macro-assembler-arm.cc      Wed Dec  9  
03:14:45 2009
+++ /branches/bleeding_edge/src/arm/macro-assembler-arm.cc      Thu Dec 10  
06:06:08 2009
@@ -162,6 +162,21 @@
  }


+void MacroAssembler::Drop(int stack_elements, Condition cond) {
+  if (stack_elements > 0) {
+    add(sp, sp, Operand(stack_elements * kPointerSize), LeaveCC, cond);
+  }
+}
+
+
+void MacroAssembler::Call(Label* target) {
+  bl(target);
+}
+
+
+void MacroAssembler::Move(Register dst, Handle<Object> value) {
+  mov(dst, Operand(value));
+}


  void MacroAssembler::SmiJumpTable(Register index, Vector<Label*> targets) {
@@ -626,6 +641,15 @@
      str(sp, MemOperand(r7));
    }
  }
+
+
+void MacroAssembler::PopTryHandler() {
+  ASSERT_EQ(0, StackHandlerConstants::kNextOffset);
+  pop(r1);
+  mov(ip, Operand(ExternalReference(Top::k_handler_address)));
+  add(sp, sp, Operand(StackHandlerConstants::kSize - kPointerSize));
+  str(r1, MemOperand(ip));
+}


  Register MacroAssembler::CheckMaps(JSObject* object, Register object_reg,
=======================================
--- /branches/bleeding_edge/src/arm/macro-assembler-arm.h       Thu Nov 26  
02:28:32 2009
+++ /branches/bleeding_edge/src/arm/macro-assembler-arm.h       Thu Dec 10  
06:06:08 2009
@@ -64,6 +64,9 @@
    void Call(byte* target, RelocInfo::Mode rmode, Condition cond = al);
    void Call(Handle<Code> code, RelocInfo::Mode rmode, Condition cond = al);
    void Ret(Condition cond = al);
+  void Drop(int stack_elements, Condition cond = al);
+  void Call(Label* target);
+  void Move(Register dst, Handle<Object> value);
    // Jumps to the label at the index given by the Smi in "index".
    void SmiJumpTable(Register index, Vector<Label*> targets);
    // Load an object from the root table.
@@ -148,6 +151,9 @@
    // On exit, r0 contains TOS (code slot).
    void PushTryHandler(CodeLocation try_location, HandlerType type);

+  // Unlink the stack handler on top of the stack from the try handler  
chain.
+  // Must preserve the result register.
+  void PopTryHandler();

    //  
---------------------------------------------------------------------------
    // Inline caching support
=======================================
--- /branches/bleeding_edge/src/compiler.cc     Thu Dec 10 05:12:13 2009
+++ /branches/bleeding_edge/src/compiler.cc     Thu Dec 10 06:06:08 2009
@@ -690,12 +690,10 @@


  void CodeGenSelector::VisitContinueStatement(ContinueStatement* stmt) {
-  BAILOUT("ContinueStatement");
  }


  void CodeGenSelector::VisitBreakStatement(BreakStatement* stmt) {
-  BAILOUT("BreakStatement");
  }


=======================================
--- /branches/bleeding_edge/src/fast-codegen.cc Thu Dec 10 05:12:13 2009
+++ /branches/bleeding_edge/src/fast-codegen.cc Thu Dec 10 06:06:08 2009
@@ -36,7 +36,7 @@
  namespace v8 {
  namespace internal {

-#define __ ACCESS_MASM(masm_)
+#define __ ACCESS_MASM(masm())

  Handle<Code> FastCodeGenerator::MakeCode(FunctionLiteral* fun,
                                           Handle<Script> script,
@@ -232,8 +232,10 @@

  void FastCodeGenerator::VisitBlock(Block* stmt) {
    Comment cmnt(masm_, "[ Block");
+  Breakable nested_statement(this, stmt);
    SetStatementPosition(stmt);
    VisitStatements(stmt->statements());
+  __ bind(nested_statement.break_target());
  }


@@ -278,15 +280,62 @@


  void FastCodeGenerator::VisitContinueStatement(ContinueStatement* stmt) {
-  UNREACHABLE();
+  Comment cmnt(masm_,  "[ ContinueStatement");
+  NestedStatement* current = nesting_stack_;
+  int stack_depth = 0;
+  while (!current->IsContinueTarget(stmt->target())) {
+    stack_depth = current->Exit(stack_depth);
+    current = current->outer();
+  }
+  __ Drop(stack_depth);
+
+  Iteration* loop = current->AsIteration();
+  __ jmp(loop->continue_target());
  }


  void FastCodeGenerator::VisitBreakStatement(BreakStatement* stmt) {
-  UNREACHABLE();
+  Comment cmnt(masm_,  "[ BreakStatement");
+  NestedStatement* current = nesting_stack_;
+  int stack_depth = 0;
+  while (!current->IsBreakTarget(stmt->target())) {
+    stack_depth = current->Exit(stack_depth);
+    current = current->outer();
+  }
+  __ Drop(stack_depth);
+
+  Breakable* target = current->AsBreakable();
+  __ jmp(target->break_target());
  }


+void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
+  Comment cmnt(masm_, "[ ReturnStatement");
+  Expression* expr = stmt->expression();
+  // Complete the statement based on the type of the subexpression.
+  if (expr->AsLiteral() != NULL) {
+    __ Move(result_register(), expr->AsLiteral()->handle());
+  } else {
+    ASSERT_EQ(Expression::kValue, expr->context());
+    Visit(expr);
+    __ pop(result_register());
+  }
+
+  // Exit all nested statements.
+  NestedStatement* current = nesting_stack_;
+  int stack_depth = 0;
+  while (current != NULL) {
+    stack_depth = current->Exit(stack_depth);
+    current = current->outer();
+  }
+  __ Drop(stack_depth);
+
+  EmitReturnSequence(stmt->statement_pos());
+}
+
+
+
+
  void FastCodeGenerator::VisitWithEnterStatement(WithEnterStatement* stmt) {
    UNREACHABLE();
  }
@@ -304,8 +353,10 @@

  void FastCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
    Comment cmnt(masm_, "[ DoWhileStatement");
+  Label body, stack_limit_hit, stack_check_success;
+
+  Iteration loop_statement(this, stmt);
    increment_loop_depth();
-  Label body, exit, stack_limit_hit, stack_check_success;

    __ bind(&body);
    Visit(stmt->body());
@@ -316,10 +367,11 @@

    // We are not in an expression context because we have been compiling
    // statements.  Set up a test expression context for the condition.
+  __ bind(loop_statement.continue_target());
    ASSERT_EQ(NULL, true_label_);
    ASSERT_EQ(NULL, false_label_);
    true_label_ = &body;
-  false_label_ = &exit;
+  false_label_ = loop_statement.break_target();
    ASSERT(stmt->cond()->context() == Expression::kTest);
    Visit(stmt->cond());
    true_label_ = NULL;
@@ -330,7 +382,7 @@
    __ CallStub(&stack_stub);
    __ jmp(&stack_check_success);

-  __ bind(&exit);
+  __ bind(loop_statement.break_target());

    decrement_loop_depth();
  }
@@ -338,16 +390,18 @@

  void FastCodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
    Comment cmnt(masm_, "[ WhileStatement");
+  Label body, stack_limit_hit, stack_check_success;
+
+  Iteration loop_statement(this, stmt);
    increment_loop_depth();
-  Label test, body, exit, stack_limit_hit, stack_check_success;

    // Emit the test at the bottom of the loop.
-  __ jmp(&test);
+  __ jmp(loop_statement.continue_target());

    __ bind(&body);
    Visit(stmt->body());

-  __ bind(&test);
+  __ bind(loop_statement.continue_target());
    // Check stack before looping.
    __ StackLimitCheck(&stack_limit_hit);
    __ bind(&stack_check_success);
@@ -357,7 +411,7 @@
    ASSERT_EQ(NULL, true_label_);
    ASSERT_EQ(NULL, false_label_);
    true_label_ = &body;
-  false_label_ = &exit;
+  false_label_ = loop_statement.break_target();
    ASSERT(stmt->cond()->context() == Expression::kTest);
    Visit(stmt->cond());
    true_label_ = NULL;
@@ -368,8 +422,7 @@
    __ CallStub(&stack_stub);
    __ jmp(&stack_check_success);

-  __ bind(&exit);
-
+  __ bind(loop_statement.break_target());
    decrement_loop_depth();
  }

@@ -511,6 +564,23 @@
  void FastCodeGenerator::VisitThrow(Throw* expr) {
    UNREACHABLE();
  }
+
+
+int FastCodeGenerator::TryFinally::Exit(int stack_depth) {
+  // The macros used here must preserve the result register.
+  __ Drop(stack_depth);
+  __ PopTryHandler();
+  __ Call(finally_entry_);
+  return 0;
+}
+
+
+int FastCodeGenerator::TryCatch::Exit(int stack_depth) {
+  // The macros used here must preserve the result register.
+  __ Drop(stack_depth);
+  __ PopTryHandler();
+  return 0;
+}


  #undef __
=======================================
--- /branches/bleeding_edge/src/fast-codegen.h  Thu Nov 26 02:28:32 2009
+++ /branches/bleeding_edge/src/fast-codegen.h  Thu Dec 10 06:06:08 2009
@@ -35,6 +35,8 @@
  namespace v8 {
  namespace internal {

+//  
-----------------------------------------------------------------------------
+// Fast code generator.

  class FastCodeGenerator: public AstVisitor {
   public:
@@ -43,6 +45,7 @@
          function_(NULL),
          script_(script),
          is_eval_(is_eval),
+        nesting_stack_(NULL),
          loop_depth_(0),
          true_label_(NULL),
          false_label_(NULL) {
@@ -55,6 +58,159 @@
    void Generate(FunctionLiteral* fun);

   private:
+  class Breakable;
+  class Iteration;
+  class TryCatch;
+  class TryFinally;
+  class Finally;
+  class ForIn;
+
+  class NestedStatement BASE_EMBEDDED {
+   public:
+    explicit NestedStatement(FastCodeGenerator* codegen) :  
codegen_(codegen) {
+      // Link into codegen's nesting stack.
+      previous_ = codegen->nesting_stack_;
+      codegen->nesting_stack_ = this;
+    }
+    virtual ~NestedStatement() {
+      // Unlink from codegen's nesting stack.
+      ASSERT_EQ(this, codegen_->nesting_stack_);
+      codegen_->nesting_stack_ = previous_;
+    }
+
+    virtual Breakable* AsBreakable() { return NULL; }
+    virtual Iteration* AsIteration() { return NULL; }
+    virtual TryCatch* AsTryCatch() { return NULL; }
+    virtual TryFinally* AsTryFinally() { return NULL; }
+    virtual Finally* AsFinally() { return NULL; }
+    virtual ForIn* AsForIn() { return NULL; }
+
+    virtual bool IsContinueTarget(Statement* target) { return false; }
+    virtual bool IsBreakTarget(Statement* target) { return false; }
+
+    // Generate code to leave the nested statement. This includes
+    // cleaning up any stack elements in use and restoring the
+    // stack to the expectations of the surrounding statements.
+    // Takes a number of stack elements currently on top of the
+    // nested statement's stack, and returns a number of stack
+    // elements left on top of the surrounding statement's stack.
+    // The generated code must preserve the result register (which
+    // contains the value in case of a return).
+    virtual int Exit(int stack_depth) {
+      // Default implementation for the case where there is
+      // nothing to clean up.
+      return stack_depth;
+    }
+    NestedStatement* outer() { return previous_; }
+   protected:
+    MacroAssembler* masm() { return codegen_->masm(); }
+   private:
+    FastCodeGenerator* codegen_;
+    NestedStatement* previous_;
+    DISALLOW_COPY_AND_ASSIGN(NestedStatement);
+  };
+
+  class Breakable : public NestedStatement {
+   public:
+    Breakable(FastCodeGenerator* codegen,
+              BreakableStatement* break_target)
+        : NestedStatement(codegen),
+          target_(break_target) {}
+    virtual ~Breakable() {}
+    virtual Breakable* AsBreakable() { return this; }
+    virtual bool IsBreakTarget(Statement* statement) {
+      return target_ == statement;
+    }
+    BreakableStatement* statement() { return target_; }
+    Label* break_target() { return &break_target_label_; }
+   private:
+    BreakableStatement* target_;
+    Label break_target_label_;
+    DISALLOW_COPY_AND_ASSIGN(Breakable);
+  };
+
+  class Iteration : public Breakable {
+   public:
+    Iteration(FastCodeGenerator* codegen,
+              IterationStatement* iteration_statement)
+        : Breakable(codegen, iteration_statement) {}
+    virtual ~Iteration() {}
+    virtual Iteration* AsIteration() { return this; }
+    virtual bool IsContinueTarget(Statement* statement) {
+      return this->statement() == statement;
+    }
+    Label* continue_target() { return &continue_target_label_; }
+   private:
+    Label continue_target_label_;
+    DISALLOW_COPY_AND_ASSIGN(Iteration);
+  };
+
+  // The environment inside the try block of a try/catch statement.
+  class TryCatch : public NestedStatement {
+   public:
+    explicit TryCatch(FastCodeGenerator* codegen, Label* catch_entry)
+        : NestedStatement(codegen), catch_entry_(catch_entry) { }
+    virtual ~TryCatch() {}
+    virtual TryCatch* AsTryCatch() { return this; }
+    Label* catch_entry() { return catch_entry_; }
+    virtual int Exit(int stack_depth);
+   private:
+    Label* catch_entry_;
+    DISALLOW_COPY_AND_ASSIGN(TryCatch);
+  };
+
+  // The environment inside the try block of a try/finally statement.
+  class TryFinally : public NestedStatement {
+   public:
+    explicit TryFinally(FastCodeGenerator* codegen, Label* finally_entry)
+        : NestedStatement(codegen), finally_entry_(finally_entry) { }
+    virtual ~TryFinally() {}
+    virtual TryFinally* AsTryFinally() { return this; }
+    Label* finally_entry() { return finally_entry_; }
+    virtual int Exit(int stack_depth);
+   private:
+    Label* finally_entry_;
+    DISALLOW_COPY_AND_ASSIGN(TryFinally);
+  };
+
+  // A FinallyEnvironment represents being inside a finally block.
+  // Abnormal termination of the finally block needs to clean up
+  // the block's parameters from the stack.
+  class Finally : public NestedStatement {
+   public:
+    explicit Finally(FastCodeGenerator* codegen) :  
NestedStatement(codegen) { }
+    virtual ~Finally() {}
+    virtual Finally* AsFinally() { return this; }
+    virtual int Exit(int stack_depth) {
+      return stack_depth + kFinallyStackElementCount;
+    }
+   private:
+    // Number of extra stack slots occupied during a finally block.
+    static const int kFinallyStackElementCount = 2;
+    DISALLOW_COPY_AND_ASSIGN(Finally);
+  };
+
+  // A ForInEnvironment represents being inside a for-in loop.
+  // Abnormal termination of the for-in block needs to clean up
+  // the block's temporary storage from the stack.
+  class ForIn : public Iteration {
+   public:
+    ForIn(FastCodeGenerator* codegen,
+          ForInStatement* statement)
+        : Iteration(codegen, statement) { }
+    virtual ~ForIn() {}
+    virtual ForIn* AsForIn() { return this; }
+    virtual int Exit(int stack_depth) {
+      return stack_depth + kForInStackElementCount;
+    }
+   private:
+    // TODO(lrn): Check that this value is correct when implementing
+    // for-in.
+    static const int kForInStackElementCount = 5;
+    DISALLOW_COPY_AND_ASSIGN(ForIn);
+  };
+
+
    int SlotOffset(Slot* slot);
    void Move(Expression::Context destination, Register source);
    void Move(Expression::Context destination, Slot* source, Register  
scratch);
@@ -111,12 +267,14 @@
      ASSERT(loop_depth_ > 0);
      loop_depth_--;
    }
+
+  MacroAssembler* masm() { return masm_; }
+  static Register result_register();

    // AST node visit functions.
  #define DECLARE_VISIT(type) virtual void Visit##type(type* node);
    AST_NODE_LIST(DECLARE_VISIT)
  #undef DECLARE_VISIT
-
    // Handles the shortcutted logical binary operations in  
VisitBinaryOperation.
    void EmitLogicalOperation(BinaryOperation* expr);

@@ -125,11 +283,14 @@
    Handle<Script> script_;
    bool is_eval_;
    Label return_label_;
+  NestedStatement* nesting_stack_;
    int loop_depth_;

    Label* true_label_;
    Label* false_label_;

+  friend class NestedStatement;
+
    DISALLOW_COPY_AND_ASSIGN(FastCodeGenerator);
  };

=======================================
--- /branches/bleeding_edge/src/ia32/fast-codegen-ia32.cc       Wed Dec  9  
05:06:08 2009
+++ /branches/bleeding_edge/src/ia32/fast-codegen-ia32.cc       Thu Dec 10  
06:06:08 2009
@@ -513,20 +513,6 @@
    __ CallRuntime(Runtime::kDeclareGlobals, 3);
    // Return value is ignored.
  }
-
-
-void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
-  Comment cmnt(masm_, "[ ReturnStatement");
-  Expression* expr = stmt->expression();
-  if (expr->AsLiteral() != NULL) {
-    __ mov(eax, expr->AsLiteral()->handle());
-  } else {
-    ASSERT_EQ(Expression::kValue, expr->context());
-    Visit(expr);
-    __ pop(eax);
-  }
-  EmitReturnSequence(stmt->statement_pos());
-}


  void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
@@ -1639,6 +1625,7 @@
    // Convert current context to test context: End post-test code.
  }

+Register FastCodeGenerator::result_register() { return eax; }

  void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) {
    __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
=======================================
--- /branches/bleeding_edge/src/ia32/macro-assembler-ia32.cc    Wed Dec  9  
06:54:34 2009
+++ /branches/bleeding_edge/src/ia32/macro-assembler-ia32.cc    Thu Dec 10  
06:06:08 2009
@@ -502,6 +502,13 @@
    // Link this handler as the new current one.
    mov(Operand::StaticVariable(ExternalReference(Top::k_handler_address)),  
esp);
  }
+
+
+void MacroAssembler::PopTryHandler() {
+  ASSERT_EQ(0, StackHandlerConstants::kNextOffset);
+  pop(Operand::StaticVariable(ExternalReference(Top::k_handler_address)));
+  add(Operand(esp), Immediate(StackHandlerConstants::kSize -  
kPointerSize));
+}


  Register MacroAssembler::CheckMaps(JSObject* object, Register object_reg,
@@ -1348,6 +1355,18 @@
  void MacroAssembler::Ret() {
    ret(0);
  }
+
+
+void MacroAssembler::Drop(int stack_elements) {
+  if (stack_elements > 0) {
+    add(Operand(esp), Immediate(stack_elements * kPointerSize));
+  }
+}
+
+
+void MacroAssembler::Move(Register dst, Handle<Object> value) {
+  mov(dst, value);
+}


  void MacroAssembler::SetCounter(StatsCounter* counter, int value) {
=======================================
--- /branches/bleeding_edge/src/ia32/macro-assembler-ia32.h     Wed Dec  9  
06:54:34 2009
+++ /branches/bleeding_edge/src/ia32/macro-assembler-ia32.h     Thu Dec 10  
06:06:08 2009
@@ -149,6 +149,9 @@
    // address must be pushed before calling this helper.
    void PushTryHandler(CodeLocation try_location, HandlerType type);

+  // Unlink the stack handler on top of the stack from the try handler  
chain.
+  void PopTryHandler();
+

    //  
---------------------------------------------------------------------------
    // Inline caching support
@@ -333,6 +336,12 @@

    void Ret();

+  void Drop(int element_count);
+
+  void Call(Label* target) { call(target); }
+
+  void Move(Register target, Handle<Object> value);
+
    struct Unresolved {
      int pc;
      uint32_t flags;  // see Bootstrapper::FixupFlags decoders/encoders.
=======================================
--- /branches/bleeding_edge/src/x64/fast-codegen-x64.cc Wed Dec  9 05:06:08  
2009
+++ /branches/bleeding_edge/src/x64/fast-codegen-x64.cc Thu Dec 10 06:06:08  
2009
@@ -523,20 +523,6 @@
    __ CallRuntime(Runtime::kDeclareGlobals, 3);
    // Return value is ignored.
  }
-
-
-void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
-  Comment cmnt(masm_, "[ ReturnStatement");
-  Expression* expr = stmt->expression();
-  if (expr->AsLiteral() != NULL) {
-    __ Move(rax, expr->AsLiteral()->handle());
-  } else {
-    Visit(expr);
-    ASSERT_EQ(Expression::kValue, expr->context());
-    __ pop(rax);
-  }
-  EmitReturnSequence(stmt->statement_pos());
-}


  void FastCodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
@@ -1649,6 +1635,8 @@
    Move(expr->context(), rax);
  }

+
+Register FastCodeGenerator::result_register() { return rax; }

  #undef __

=======================================
--- /branches/bleeding_edge/src/x64/macro-assembler-x64.cc      Wed Dec  9  
01:35:41 2009
+++ /branches/bleeding_edge/src/x64/macro-assembler-x64.cc      Thu Dec 10  
06:06:08 2009
@@ -1343,6 +1343,13 @@
      push(kScratchRegister);
    }
  }
+
+
+void MacroAssembler::Drop(int stack_elements) {
+  if (stack_elements > 0) {
+    addq(rsp, Immediate(stack_elements * kPointerSize));
+  }
+}


  void MacroAssembler::Test(const Operand& src, Smi* source) {
@@ -1429,6 +1436,14 @@
    // Link this handler.
    movq(Operand(kScratchRegister, 0), rsp);
  }
+
+
+void MacroAssembler::PopTryHandler() {
+  ASSERT_EQ(0, StackHandlerConstants::kNextOffset);
+  movq(kScratchRegister, ExternalReference(Top::k_handler_address));
+  pop(Operand(kScratchRegister, 0));
+  addq(rsp, Immediate(StackHandlerConstants::kSize - kPointerSize));
+}


  void MacroAssembler::Ret() {
=======================================
--- /branches/bleeding_edge/src/x64/macro-assembler-x64.h       Wed Dec  9  
01:35:41 2009
+++ /branches/bleeding_edge/src/x64/macro-assembler-x64.h       Thu Dec 10  
06:06:08 2009
@@ -400,7 +400,7 @@
    void Test(const Operand& dst, Smi* source);

    //  
---------------------------------------------------------------------------
-  // Macro instructions
+  // Macro instructions.

    // Load a register with a long value as efficiently as possible.
    void Set(Register dst, int64_t x);
@@ -412,6 +412,8 @@
    void Cmp(Register dst, Handle<Object> source);
    void Cmp(const Operand& dst, Handle<Object> source);
    void Push(Handle<Object> source);
+  void Drop(int stack_elements);
+  void Call(Label* target) { call(target); }

    // Control Flow
    void Jump(Address destination, RelocInfo::Mode rmode);
@@ -443,6 +445,8 @@
    // address must be pushed before calling this helper.
    void PushTryHandler(CodeLocation try_location, HandlerType type);

+  // Unlink the stack handler on top of the stack from the try handler  
chain.
+  void PopTryHandler();

    //  
---------------------------------------------------------------------------
    // Inline caching support

-- 
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to