First step towards making JumpTarget work on ARM. Instead
authorerik.corry@gmail.com <erik.corry@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 10 May 2010 11:32:25 +0000 (11:32 +0000)
committererik.corry@gmail.com <erik.corry@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 10 May 2010 11:32:25 +0000 (11:32 +0000)
of having a list of virtual frame pointers in the jump
target we have one virtual frame, which is the frame that
all have to merge to to branch to that frame.  The virtual
frame in the JumpTarget is inside the JumpTarget, rather than
being an allocated object that is pointed to.  Unfortunately
this means that the JumpTarget class has to be able to see
the size of a VirtualFrame object to compile, which in turn
lead to a major reorganization of related .h files.  The
actual change of functionality in this change is intended
to be minimal (we now assert that the virtual frames match
when using JumpTarget instead of just assuming that they do).
Review URL: http://codereview.chromium.org/1961004

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4631 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

30 files changed:
src/arm/codegen-arm.cc
src/arm/codegen-arm.h
src/arm/jump-target-arm.cc
src/arm/virtual-frame-arm-inl.h [new file with mode: 0644]
src/arm/virtual-frame-arm.cc
src/arm/virtual-frame-arm.h
src/ast-inl.h [new file with mode: 0644]
src/ast.cc
src/ast.h
src/codegen.h
src/ia32/codegen-ia32.h
src/ia32/virtual-frame-ia32.h
src/jump-target-heavy.cc
src/jump-target-heavy.h [new file with mode: 0644]
src/jump-target-light-inl.h
src/jump-target-light.cc
src/jump-target-light.h [new file with mode: 0644]
src/jump-target.cc
src/jump-target.h
src/parser.cc
src/register-allocator.cc
src/virtual-frame-heavy-inl.h
src/virtual-frame-light-inl.h
src/virtual-frame-light.cc
src/x64/codegen-x64.h
src/x64/virtual-frame-x64.h
tools/gyp/v8.gyp
tools/visual_studio/v8_base.vcproj
tools/visual_studio/v8_base_arm.vcproj
tools/visual_studio/v8_base_x64.vcproj

index b5778cf88b6a588156fbcd9cd12568ff3967f791..21d1432de04c3f423a53d49a189869697867648e 100644 (file)
@@ -33,6 +33,7 @@
 #include "debug.h"
 #include "ic-inl.h"
 #include "jsregexp.h"
+#include "jump-target-light-inl.h"
 #include "parser.h"
 #include "regexp-macro-assembler.h"
 #include "regexp-stack.h"
 #include "runtime.h"
 #include "scopes.h"
 #include "virtual-frame-inl.h"
+#include "virtual-frame-arm-inl.h"
 
 namespace v8 {
 namespace internal {
 
+
 #define __ ACCESS_MASM(masm_)
 
 static void EmitIdenticalObjectComparison(MacroAssembler* masm,
@@ -274,7 +277,7 @@ void CodeGenerator::Generate(CompilationInfo* info) {
 
     // Initialize the function return target after the locals are set
     // up, because it needs the expected frame height from the frame.
-    function_return_.set_direction(JumpTarget::BIDIRECTIONAL);
+    function_return_.SetExpectedHeight();
     function_return_is_shadowed_ = false;
 
     // Generate code to 'execute' declarations and initialize functions
@@ -1549,7 +1552,7 @@ void CodeGenerator::VisitBlock(Block* node) {
   VirtualFrame::SpilledScope spilled_scope(frame_);
   Comment cmnt(masm_, "[ Block");
   CodeForStatementPosition(node);
-  node->break_target()->set_direction(JumpTarget::FORWARD_ONLY);
+  node->break_target()->SetExpectedHeight();
   VisitStatementsAndSpill(node->statements());
   if (node->break_target()->is_linked()) {
     node->break_target()->Bind();
@@ -1836,7 +1839,7 @@ void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) {
   VirtualFrame::SpilledScope spilled_scope(frame_);
   Comment cmnt(masm_, "[ SwitchStatement");
   CodeForStatementPosition(node);
-  node->break_target()->set_direction(JumpTarget::FORWARD_ONLY);
+  node->break_target()->SetExpectedHeight();
 
   LoadAndSpill(node->tag());
 
@@ -1925,7 +1928,7 @@ void CodeGenerator::VisitDoWhileStatement(DoWhileStatement* node) {
   VirtualFrame::SpilledScope spilled_scope(frame_);
   Comment cmnt(masm_, "[ DoWhileStatement");
   CodeForStatementPosition(node);
-  node->break_target()->set_direction(JumpTarget::FORWARD_ONLY);
+  node->break_target()->SetExpectedHeight();
   JumpTarget body(JumpTarget::BIDIRECTIONAL);
   IncrementLoopNesting();
 
@@ -1935,14 +1938,14 @@ void CodeGenerator::VisitDoWhileStatement(DoWhileStatement* node) {
   ConditionAnalysis info = AnalyzeCondition(node->cond());
   switch (info) {
     case ALWAYS_TRUE:
-      node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL);
+      node->continue_target()->SetExpectedHeight();
       node->continue_target()->Bind();
       break;
     case ALWAYS_FALSE:
-      node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
+      node->continue_target()->SetExpectedHeight();
       break;
     case DONT_KNOW:
-      node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
+      node->continue_target()->SetExpectedHeight();
       body.Bind();
       break;
   }
@@ -2006,12 +2009,12 @@ void CodeGenerator::VisitWhileStatement(WhileStatement* node) {
   ConditionAnalysis info = AnalyzeCondition(node->cond());
   if (info == ALWAYS_FALSE) return;
 
-  node->break_target()->set_direction(JumpTarget::FORWARD_ONLY);
+  node->break_target()->SetExpectedHeight();
   IncrementLoopNesting();
 
   // Label the top of the loop with the continue target for the backward
   // CFG edge.
-  node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL);
+  node->continue_target()->SetExpectedHeight();
   node->continue_target()->Bind();
 
   if (info == DONT_KNOW) {
@@ -2060,17 +2063,17 @@ void CodeGenerator::VisitForStatement(ForStatement* node) {
   ConditionAnalysis info = AnalyzeCondition(node->cond());
   if (info == ALWAYS_FALSE) return;
 
-  node->break_target()->set_direction(JumpTarget::FORWARD_ONLY);
+  node->break_target()->SetExpectedHeight();
   IncrementLoopNesting();
 
   // If there is no update statement, label the top of the loop with the
   // continue target, otherwise with the loop target.
   JumpTarget loop(JumpTarget::BIDIRECTIONAL);
   if (node->next() == NULL) {
-    node->continue_target()->set_direction(JumpTarget::BIDIRECTIONAL);
+    node->continue_target()->SetExpectedHeight();
     node->continue_target()->Bind();
   } else {
-    node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
+    node->continue_target()->SetExpectedHeight();
     loop.Bind();
   }
 
@@ -2275,8 +2278,8 @@ void CodeGenerator::VisitForInStatement(ForInStatement* node) {
   // sp[4] : enumerable
   // Grab the current frame's height for the break and continue
   // targets only after all the state is pushed on the frame.
-  node->break_target()->set_direction(JumpTarget::FORWARD_ONLY);
-  node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY);
+  node->break_target()->SetExpectedHeight();
+  node->continue_target()->SetExpectedHeight();
 
   // Load the current count to r0, load the length to r1.
   __ ldrd(r0, frame_->ElementAt(0));
index 34eae4d2ef2f55058c44f00a87289fdd39a3c629..ab1b844b36351a67c5405bfb3ae2d6067ec7eb99 100644 (file)
@@ -29,6 +29,7 @@
 #define V8_ARM_CODEGEN_ARM_H_
 
 #include "ic-inl.h"
+#include "ast.h"
 
 namespace v8 {
 namespace internal {
@@ -36,6 +37,7 @@ namespace internal {
 // Forward declarations
 class CompilationInfo;
 class DeferredCode;
+class JumpTarget;
 class RegisterAllocator;
 class RegisterFile;
 
index a13de0e2a6e0ce4a1a532411afb4d35993826bb6..8d182bea1be9fa7c12187b6d3f7849194a4fff17 100644 (file)
@@ -47,28 +47,15 @@ void JumpTarget::DoJump() {
   // which are still live in the C++ code.
   ASSERT(cgen()->HasValidEntryRegisters());
 
-  if (is_bound()) {
-    // Backward jump.  There already a frame expectation at the target.
-    ASSERT(direction_ == BIDIRECTIONAL);
-    cgen()->frame()->MergeTo(entry_frame_);
+  if (entry_frame_set_) {
+    // There already a frame expectation at the target.
+    cgen()->frame()->MergeTo(&entry_frame_);
     cgen()->DeleteFrame();
   } else {
-    // Use the current frame as the expected one at the target if necessary.
-    if (entry_frame_ == NULL) {
-      entry_frame_ = cgen()->frame();
-      RegisterFile empty;
-      cgen()->SetFrame(NULL, &empty);
-    } else {
-      cgen()->frame()->MergeTo(entry_frame_);
-      cgen()->DeleteFrame();
-    }
-
-    // The predicate is_linked() should be made true.  Its implementation
-    // detects the presence of a frame pointer in the reaching_frames_ list.
-    if (!is_linked()) {
-      reaching_frames_.Add(NULL);
-      ASSERT(is_linked());
-    }
+    // Clone the current frame to use as the expected one at the target.
+    set_entry_frame(cgen()->frame());
+    RegisterFile empty;
+    cgen()->SetFrame(NULL, &empty);
   }
   __ jmp(&entry_label_);
 }
@@ -77,23 +64,19 @@ void JumpTarget::DoJump() {
 void JumpTarget::DoBranch(Condition cc, Hint ignored) {
   ASSERT(cgen()->has_valid_frame());
 
-  if (is_bound()) {
-    ASSERT(direction_ == BIDIRECTIONAL);
+  if (entry_frame_set_) {
     // Backward branch.  We have an expected frame to merge to on the
     // backward edge.
-    cgen()->frame()->MergeTo(entry_frame_);
-  } else {
-    // Clone the current frame to use as the expected one at the target if
-    // necessary.
-    if (entry_frame_ == NULL) {
-      entry_frame_ = new VirtualFrame(cgen()->frame());
-    }
-    // The predicate is_linked() should be made true.  Its implementation
-    // detects the presence of a frame pointer in the reaching_frames_ list.
-    if (!is_linked()) {
-      reaching_frames_.Add(NULL);
-      ASSERT(is_linked());
+    if (cc == al) {
+      cgen()->frame()->MergeTo(&entry_frame_);
+    } else {
+      // We can't do conditional merges yet so you have to ensure that all
+      // conditional branches to the JumpTarget have the same virtual frame.
+      ASSERT(cgen()->frame()->Equals(&entry_frame_));
     }
+  } else {
+    // Clone the current frame to use as the expected one at the target.
+    set_entry_frame(cgen()->frame());
   }
   __ b(cc, &entry_label_);
 }
@@ -113,15 +96,10 @@ void JumpTarget::Call() {
 
   // Calls are always 'forward' so we use a copy of the current frame (plus
   // one for a return address) as the expected frame.
-  ASSERT(entry_frame_ == NULL);
-  VirtualFrame* target_frame = new VirtualFrame(cgen()->frame());
-  target_frame->Adjust(1);
-  entry_frame_ = target_frame;
-
-  // The predicate is_linked() should now be made true.  Its implementation
-  // detects the presence of a frame pointer in the reaching_frames_ list.
-  reaching_frames_.Add(NULL);
-  ASSERT(is_linked());
+  ASSERT(!entry_frame_set_);
+  VirtualFrame target_frame = *cgen()->frame();
+  target_frame.Adjust(1);
+  set_entry_frame(&target_frame);
 
   __ bl(&entry_label_);
 }
@@ -136,76 +114,24 @@ void JumpTarget::DoBind() {
 
   if (cgen()->has_valid_frame()) {
     // If there is a current frame we can use it on the fall through.
-    if (entry_frame_ == NULL) {
-      entry_frame_ = new VirtualFrame(cgen()->frame());
+    if (!entry_frame_set_) {
+      entry_frame_ = *cgen()->frame();
+      entry_frame_set_ = true;
     } else {
-      ASSERT(cgen()->frame()->Equals(entry_frame_));
+      cgen()->frame()->MergeTo(&entry_frame_);
     }
   } else {
     // If there is no current frame we must have an entry frame which we can
     // copy.
-    ASSERT(entry_frame_ != NULL);
+    ASSERT(entry_frame_set_);
     RegisterFile empty;
-    cgen()->SetFrame(new VirtualFrame(entry_frame_), &empty);
-  }
-
-  // The predicate is_linked() should be made false.  Its implementation
-  // detects the presence (or absence) of frame pointers in the
-  // reaching_frames_ list.  If we inserted a bogus frame to make
-  // is_linked() true, remove it now.
-  if (is_linked()) {
-    reaching_frames_.Clear();
+    cgen()->SetFrame(new VirtualFrame(&entry_frame_), &empty);
   }
 
   __ bind(&entry_label_);
 }
 
 
-void BreakTarget::Jump() {
-  // On ARM we do not currently emit merge code for jumps, so we need to do
-  // it explicitly here.  The only merging necessary is to drop extra
-  // statement state from the stack.
-  ASSERT(cgen()->has_valid_frame());
-  int count = cgen()->frame()->height() - expected_height_;
-  cgen()->frame()->Drop(count);
-  DoJump();
-}
-
-
-void BreakTarget::Jump(Result* arg) {
-  UNIMPLEMENTED();
-}
-
-
-void BreakTarget::Bind() {
-#ifdef DEBUG
-  // All the forward-reaching frames should have been adjusted at the
-  // jumps to this target.
-  for (int i = 0; i < reaching_frames_.length(); i++) {
-    ASSERT(reaching_frames_[i] == NULL ||
-           reaching_frames_[i]->height() == expected_height_);
-  }
-#endif
-  // Drop leftover statement state from the frame before merging, even
-  // on the fall through.  This is so we can bind the return target
-  // with state on the frame.
-  if (cgen()->has_valid_frame()) {
-    int count = cgen()->frame()->height() - expected_height_;
-    // On ARM we do not currently emit merge code at binding sites, so we need
-    // to do it explicitly here.  The only merging necessary is to drop extra
-    // statement state from the stack.
-    cgen()->frame()->Drop(count);
-  }
-
-  DoBind();
-}
-
-
-void BreakTarget::Bind(Result* arg) {
-  UNIMPLEMENTED();
-}
-
-
 #undef __
 
 
diff --git a/src/arm/virtual-frame-arm-inl.h b/src/arm/virtual-frame-arm-inl.h
new file mode 100644 (file)
index 0000000..a97cde4
--- /dev/null
@@ -0,0 +1,53 @@
+// Copyright 2010 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_VIRTUAL_FRAME_ARM_INL_H_
+#define V8_VIRTUAL_FRAME_ARM_INL_H_
+
+#include "assembler-arm.h"
+#include "virtual-frame-arm.h"
+
+namespace v8 {
+namespace internal {
+
+// These VirtualFrame methods should actually be in a virtual-frame-arm-inl.h
+// file if such a thing existed.
+MemOperand VirtualFrame::ParameterAt(int index) {
+  // Index -1 corresponds to the receiver.
+  ASSERT(-1 <= index);  // -1 is the receiver.
+  ASSERT(index <= parameter_count());
+  return MemOperand(fp, (1 + parameter_count() - index) * kPointerSize);
+}
+
+  // The receiver frame slot.
+MemOperand VirtualFrame::Receiver() {
+  return ParameterAt(-1);
+}
+
+} }  // namespace v8::internal
+
+#endif  // V8_VIRTUAL_FRAME_ARM_INL_H_
index 0ec6e203d2dd38af492592f2e259ea287c66b513..d1559b3020af9c1e414ba1bc908950734f691ee1 100644 (file)
@@ -418,7 +418,7 @@ void VirtualFrame::Pop() {
 
 
 void VirtualFrame::EmitPop(Register reg) {
-  ASSERT(!is_used(reg));
+  ASSERT(!is_used(RegisterAllocator::ToNumber(reg)));
   if (top_of_stack_state_ == NO_TOS_REGISTERS) {
     __ pop(reg);
   } else {
index b255929e2b2e154506a22b6866072146de59bb17..52b94f724040ddf89b7b81de636b77996874fa0b 100644 (file)
 #define V8_ARM_VIRTUAL_FRAME_ARM_H_
 
 #include "register-allocator.h"
-#include "scopes.h"
 
 namespace v8 {
 namespace internal {
 
+// This dummy class is only used to create invalid virtual frames.
+extern class InvalidVirtualFrameInitializer {}* kInvalidVirtualFrameInitializer;
+
+
 // -------------------------------------------------------------------------
 // Virtual frames
 //
@@ -82,26 +85,8 @@ class VirtualFrame : public ZoneObject {
     // is not spilled, ie. where register allocation occurs.  Eventually
     // when RegisterAllocationScope is ubiquitous it can be removed
     // along with the (by then unused) SpilledScope class.
-    explicit RegisterAllocationScope(CodeGenerator* cgen)
-      : cgen_(cgen),
-        old_is_spilled_(SpilledScope::is_spilled_) {
-      SpilledScope::is_spilled_ = false;
-      if (old_is_spilled_) {
-        VirtualFrame* frame = cgen->frame();
-        if (frame != NULL) {
-          frame->AssertIsSpilled();
-        }
-      }
-    }
-    ~RegisterAllocationScope() {
-      SpilledScope::is_spilled_ = old_is_spilled_;
-      if (old_is_spilled_) {
-        VirtualFrame* frame = cgen_->frame();
-        if (frame != NULL) {
-          frame->SpillAll();
-        }
-      }
-    }
+    inline explicit RegisterAllocationScope(CodeGenerator* cgen);
+    inline ~RegisterAllocationScope();
 
    private:
     CodeGenerator* cgen_;
@@ -116,19 +101,20 @@ class VirtualFrame : public ZoneObject {
   // Construct an initial virtual frame on entry to a JS function.
   inline VirtualFrame();
 
+  // Construct an invalid virtual frame, used by JumpTargets.
+  inline VirtualFrame(InvalidVirtualFrameInitializer* dummy);
+
   // Construct a virtual frame as a clone of an existing one.
   explicit inline VirtualFrame(VirtualFrame* original);
 
-  CodeGenerator* cgen() { return CodeGeneratorScope::Current(); }
-  MacroAssembler* masm() { return cgen()->masm(); }
+  inline CodeGenerator* cgen();
+  inline MacroAssembler* masm();
 
   // The number of elements on the virtual frame.
   int element_count() { return element_count_; }
 
   // The height of the virtual expression stack.
-  int height() {
-    return element_count() - expression_base_index();
-  }
+  inline int height();
 
   bool is_used(int num) {
     switch (num) {
@@ -160,10 +146,6 @@ class VirtualFrame : public ZoneObject {
     }
   }
 
-  bool is_used(Register reg) {
-    return is_used(RegisterAllocator::ToNumber(reg));
-  }
-
   // Add extra in-memory elements to the top of the frame to match an actual
   // frame (eg, the frame after an exception handler is pushed).  No code is
   // emitted.
@@ -252,11 +234,7 @@ class VirtualFrame : public ZoneObject {
   }
 
   // A frame-allocated local as an assembly operand.
-  MemOperand LocalAt(int index) {
-    ASSERT(0 <= index);
-    ASSERT(index < local_count());
-    return MemOperand(fp, kLocal0Offset - index * kPointerSize);
-  }
+  inline MemOperand LocalAt(int index);
 
   // Push the address of the receiver slot on the frame.
   void PushReceiverSlotAddress();
@@ -268,26 +246,17 @@ class VirtualFrame : public ZoneObject {
   MemOperand Context() { return MemOperand(fp, kContextOffset); }
 
   // A parameter as an assembly operand.
-  MemOperand ParameterAt(int index) {
-    // Index -1 corresponds to the receiver.
-    ASSERT(-1 <= index);  // -1 is the receiver.
-    ASSERT(index <= parameter_count());
-    return MemOperand(fp, (1 + parameter_count() - index) * kPointerSize);
-  }
+  inline MemOperand ParameterAt(int index);
 
   // The receiver frame slot.
-  MemOperand Receiver() { return ParameterAt(-1); }
+  inline MemOperand Receiver();
 
   // Push a try-catch or try-finally handler on top of the virtual frame.
   void PushTryHandler(HandlerType type);
 
   // Call stub given the number of arguments it expects on (and
   // removes from) the stack.
-  void CallStub(CodeStub* stub, int arg_count) {
-    if (arg_count != 0) Forget(arg_count);
-    ASSERT(cgen()->HasValidEntryRegisters());
-    masm()->CallStub(stub);
-  }
+  inline void CallStub(CodeStub* stub, int arg_count);
 
   // Call JS function from top of the stack with arguments
   // taken from the stack.
@@ -449,13 +418,13 @@ class VirtualFrame : public ZoneObject {
   int stack_pointer() { return element_count_ - 1; }
 
   // The number of frame-allocated locals and parameters respectively.
-  int parameter_count() { return cgen()->scope()->num_parameters(); }
-  int local_count() { return cgen()->scope()->num_stack_slots(); }
+  inline int parameter_count();
+  inline int local_count();
 
   // The index of the element that is at the processor's frame pointer
   // (the fp register).  The parameters, receiver, function, and context
   // are below the frame pointer.
-  int frame_pointer() { return parameter_count() + 3; }
+  inline int frame_pointer();
 
   // The index of the first parameter.  The receiver lies below the first
   // parameter.
@@ -463,26 +432,22 @@ class VirtualFrame : public ZoneObject {
 
   // The index of the context slot in the frame.  It is immediately
   // below the frame pointer.
-  int context_index() { return frame_pointer() - 1; }
+  inline int context_index();
 
   // The index of the function slot in the frame.  It is below the frame
   // pointer and context slot.
-  int function_index() { return frame_pointer() - 2; }
+  inline int function_index();
 
   // The index of the first local.  Between the frame pointer and the
   // locals lies the return address.
-  int local0_index() { return frame_pointer() + 2; }
+  inline int local0_index();
 
   // The index of the base of the expression stack.
-  int expression_base_index() { return local0_index() + local_count(); }
+  inline int expression_base_index();
 
   // Convert a frame index into a frame pointer relative offset into the
   // actual stack.
-  int fp_relative(int index) {
-    ASSERT(index < element_count());
-    ASSERT(frame_pointer() < element_count());  // FP is on the frame.
-    return (frame_pointer() - index) * kPointerSize;
-  }
+  inline int fp_relative(int index);
 
   // Spill all elements in registers. Spill the top spilled_args elements
   // on the frame.  Sync all other frame elements.
@@ -497,7 +462,6 @@ class VirtualFrame : public ZoneObject {
   inline bool Equals(VirtualFrame* other);
 
   friend class JumpTarget;
-  friend class DeferredCode;
 };
 
 
diff --git a/src/ast-inl.h b/src/ast-inl.h
new file mode 100644 (file)
index 0000000..2b5d7c4
--- /dev/null
@@ -0,0 +1,79 @@
+// Copyright 2010 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "v8.h"
+
+#include "ast.h"
+
+namespace v8 {
+namespace internal {
+
+BreakableStatement::BreakableStatement(ZoneStringList* labels, Type type)
+    : labels_(labels), type_(type) {
+  ASSERT(labels == NULL || labels->length() > 0);
+}
+
+
+SwitchStatement::SwitchStatement(ZoneStringList* labels)
+    : BreakableStatement(labels, TARGET_FOR_ANONYMOUS),
+      tag_(NULL), cases_(NULL) {
+}
+
+
+IterationStatement::IterationStatement(ZoneStringList* labels)
+    : BreakableStatement(labels, TARGET_FOR_ANONYMOUS), body_(NULL) {
+}
+
+
+Block::Block(ZoneStringList* labels, int capacity, bool is_initializer_block)
+    : BreakableStatement(labels, TARGET_FOR_NAMED_ONLY),
+      statements_(capacity),
+      is_initializer_block_(is_initializer_block) {
+}
+
+
+ForStatement::ForStatement(ZoneStringList* labels)
+    : IterationStatement(labels),
+      init_(NULL),
+      cond_(NULL),
+      next_(NULL),
+      may_have_function_literal_(true),
+      loop_variable_(NULL),
+      peel_this_loop_(false) {
+}
+
+
+ForInStatement::ForInStatement(ZoneStringList* labels)
+    : IterationStatement(labels), each_(NULL), enumerable_(NULL) {
+}
+
+
+DoWhileStatement::DoWhileStatement(ZoneStringList* labels)
+    : IterationStatement(labels), cond_(NULL), condition_position_(-1) {
+}
+
+} }  // namespace v8::internal
index 75b2945d9cb859a911a6a4387fcc88742cc1da3d..92df990063ae418ce5ece78ffce915c0cdb611d0 100644 (file)
@@ -32,6 +32,8 @@
 #include "parser.h"
 #include "scopes.h"
 #include "string-stream.h"
+#include "ast-inl.h"
+#include "jump-target-inl.h"
 
 namespace v8 {
 namespace internal {
@@ -786,6 +788,13 @@ Block::Block(Block* other, ZoneList<Statement*>* statements)
 }
 
 
+WhileStatement::WhileStatement(ZoneStringList* labels)
+    : IterationStatement(labels),
+      cond_(NULL),
+      may_have_function_literal_(true) {
+}
+
+
 ExpressionStatement::ExpressionStatement(ExpressionStatement* other,
                                          Expression* expression)
     : Statement(other), expression_(expression) {}
@@ -809,6 +818,11 @@ IterationStatement::IterationStatement(IterationStatement* other,
     : BreakableStatement(other), body_(body) {}
 
 
+CaseClause::CaseClause(Expression* label, ZoneList<Statement*>* statements)
+    : label_(label), statements_(statements) {
+}
+
+
 ForStatement::ForStatement(ForStatement* other,
                            Statement* init,
                            Expression* cond,
index dfc08ee07140a250874c51434d333d6c0020e8c6..a3a97341dd34971f899017add3a4e08bca82df22 100644 (file)
--- a/src/ast.h
+++ b/src/ast.h
@@ -351,10 +351,7 @@ class BreakableStatement: public Statement {
   bool is_target_for_anonymous() const { return type_ == TARGET_FOR_ANONYMOUS; }
 
  protected:
-  BreakableStatement(ZoneStringList* labels, Type type)
-      : labels_(labels), type_(type) {
-    ASSERT(labels == NULL || labels->length() > 0);
-  }
+  inline BreakableStatement(ZoneStringList* labels, Type type);
 
   explicit BreakableStatement(BreakableStatement* other);
 
@@ -367,10 +364,7 @@ class BreakableStatement: public Statement {
 
 class Block: public BreakableStatement {
  public:
-  Block(ZoneStringList* labels, int capacity, bool is_initializer_block)
-      : BreakableStatement(labels, TARGET_FOR_NAMED_ONLY),
-        statements_(capacity),
-        is_initializer_block_(is_initializer_block) { }
+  inline Block(ZoneStringList* labels, int capacity, bool is_initializer_block);
 
   // Construct a clone initialized from the original block and
   // a deep copy of all statements of the original block.
@@ -437,8 +431,7 @@ class IterationStatement: public BreakableStatement {
   BreakTarget* continue_target()  { return &continue_target_; }
 
  protected:
-  explicit IterationStatement(ZoneStringList* labels)
-      : BreakableStatement(labels, TARGET_FOR_ANONYMOUS), body_(NULL) { }
+  explicit inline IterationStatement(ZoneStringList* labels);
 
   // Construct a clone initialized from  original and
   // a deep copy of the original body.
@@ -456,9 +449,7 @@ class IterationStatement: public BreakableStatement {
 
 class DoWhileStatement: public IterationStatement {
  public:
-  explicit DoWhileStatement(ZoneStringList* labels)
-      : IterationStatement(labels), cond_(NULL), condition_position_(-1) {
-  }
+  explicit inline DoWhileStatement(ZoneStringList* labels);
 
   void Initialize(Expression* cond, Statement* body) {
     IterationStatement::Initialize(body);
@@ -482,11 +473,7 @@ class DoWhileStatement: public IterationStatement {
 
 class WhileStatement: public IterationStatement {
  public:
-  explicit WhileStatement(ZoneStringList* labels)
-      : IterationStatement(labels),
-        cond_(NULL),
-        may_have_function_literal_(true) {
-  }
+  explicit WhileStatement(ZoneStringList* labels);
 
   void Initialize(Expression* cond, Statement* body) {
     IterationStatement::Initialize(body);
@@ -511,14 +498,7 @@ class WhileStatement: public IterationStatement {
 
 class ForStatement: public IterationStatement {
  public:
-  explicit ForStatement(ZoneStringList* labels)
-      : IterationStatement(labels),
-        init_(NULL),
-        cond_(NULL),
-        next_(NULL),
-        may_have_function_literal_(true),
-        loop_variable_(NULL),
-        peel_this_loop_(false) {}
+  explicit inline ForStatement(ZoneStringList* labels);
 
   // Construct a for-statement initialized from another for-statement
   // and deep copies of all parts of the original statement.
@@ -574,8 +554,7 @@ class ForStatement: public IterationStatement {
 
 class ForInStatement: public IterationStatement {
  public:
-  explicit ForInStatement(ZoneStringList* labels)
-      : IterationStatement(labels), each_(NULL), enumerable_(NULL) { }
+  explicit inline ForInStatement(ZoneStringList* labels);
 
   void Initialize(Expression* each, Expression* enumerable, Statement* body) {
     IterationStatement::Initialize(body);
@@ -691,8 +670,7 @@ class WithExitStatement: public Statement {
 
 class CaseClause: public ZoneObject {
  public:
-  CaseClause(Expression* label, ZoneList<Statement*>* statements)
-      : label_(label), statements_(statements) { }
+  CaseClause(Expression* label, ZoneList<Statement*>* statements);
 
   bool is_default() const  { return label_ == NULL; }
   Expression* label() const  {
@@ -711,9 +689,7 @@ class CaseClause: public ZoneObject {
 
 class SwitchStatement: public BreakableStatement {
  public:
-  explicit SwitchStatement(ZoneStringList* labels)
-      : BreakableStatement(labels, TARGET_FOR_ANONYMOUS),
-        tag_(NULL), cases_(NULL) { }
+  explicit inline SwitchStatement(ZoneStringList* labels);
 
   void Initialize(Expression* tag, ZoneList<CaseClause*>* cases) {
     tag_ = tag;
index a5bb31f1415cfb77cf178185d4b2269fbb4213f1..667d1008c827b7a480a21e9bc7d8ab4a07b44a7f 100644 (file)
@@ -28,7 +28,6 @@
 #ifndef V8_CODEGEN_H_
 #define V8_CODEGEN_H_
 
-#include "ast.h"
 #include "code-stubs.h"
 #include "runtime.h"
 #include "type-info.h"
index 5967338da2d407c4996f98bf4af198bf1b5f7119..53bb6c28e19acba1378f1c1c2f02651f3eb3e7b4 100644 (file)
@@ -28,7 +28,9 @@
 #ifndef V8_IA32_CODEGEN_IA32_H_
 #define V8_IA32_CODEGEN_IA32_H_
 
+#include "ast.h"
 #include "ic-inl.h"
+#include "jump-target-heavy.h"
 
 namespace v8 {
 namespace internal {
index 14fe4662dc2ca69ca80bdd4a790a83ebb5f5c4bd..51a802c74e2198458160c931769ba080e5425613 100644 (file)
 #ifndef V8_IA32_VIRTUAL_FRAME_IA32_H_
 #define V8_IA32_VIRTUAL_FRAME_IA32_H_
 
-#include "type-info.h"
+#include "codegen.h"
 #include "register-allocator.h"
 #include "scopes.h"
+#include "type-info.h"
 
 namespace v8 {
 namespace internal {
@@ -97,23 +98,16 @@ class VirtualFrame: public ZoneObject {
     return register_locations_[num];
   }
 
-  int register_location(Register reg) {
-    return register_locations_[RegisterAllocator::ToNumber(reg)];
-  }
+  inline int register_location(Register reg);
 
-  void set_register_location(Register reg, int index) {
-    register_locations_[RegisterAllocator::ToNumber(reg)] = index;
-  }
+  inline void set_register_location(Register reg, int index);
 
   bool is_used(int num) {
     ASSERT(num >= 0 && num < RegisterAllocator::kNumRegisters);
     return register_locations_[num] != kIllegalIndex;
   }
 
-  bool is_used(Register reg) {
-    return register_locations_[RegisterAllocator::ToNumber(reg)]
-        != kIllegalIndex;
-  }
+  inline bool is_used(Register reg);
 
   // Add extra in-memory elements to the top of the frame to match an actual
   // frame (eg, the frame after an exception handler is pushed).  No code is
@@ -217,10 +211,7 @@ class VirtualFrame: public ZoneObject {
   void SetElementAt(int index, Result* value);
 
   // Set a frame element to a constant.  The index is frame-top relative.
-  void SetElementAt(int index, Handle<Object> value) {
-    Result temp(value);
-    SetElementAt(index, &temp);
-  }
+  inline void SetElementAt(int index, Handle<Object> value);
 
   void PushElementAt(int index) {
     PushFrameSlotAt(element_count() - index - 1);
@@ -315,10 +306,7 @@ class VirtualFrame: public ZoneObject {
 
   // Call stub given the number of arguments it expects on (and
   // removes from) the stack.
-  Result CallStub(CodeStub* stub, int arg_count) {
-    PrepareForCall(arg_count, arg_count);
-    return RawCallStub(stub);
-  }
+  inline Result CallStub(CodeStub* stub, int arg_count);
 
   // Call stub that takes a single argument passed in eax.  The
   // argument is given as a result which does not have to be eax or
@@ -473,12 +461,9 @@ class VirtualFrame: public ZoneObject {
   int register_locations_[RegisterAllocator::kNumRegisters];
 
   // The number of frame-allocated locals and parameters respectively.
-  int parameter_count() {
-    return cgen()->scope()->num_parameters();
-  }
-  int local_count() {
-    return cgen()->scope()->num_stack_slots();
-  }
+  inline int parameter_count();
+
+  inline int local_count();
 
   // The index of the element that is at the processor's frame pointer
   // (the ebp register).  The parameters, receiver, and return address
index 85620a2d96fadea5c44dd2a545262126777d60e5..468cf4a5425a403bfe65b5ce4e974ff457030cc3 100644 (file)
@@ -35,6 +35,9 @@ namespace v8 {
 namespace internal {
 
 
+bool JumpTarget::compiling_deferred_code_ = false;
+
+
 void JumpTarget::Jump(Result* arg) {
   ASSERT(cgen()->has_valid_frame());
 
@@ -360,4 +363,64 @@ DeferredCode::DeferredCode()
   }
 }
 
+
+void JumpTarget::Unuse() {
+  reaching_frames_.Clear();
+  merge_labels_.Clear();
+  entry_frame_ = NULL;
+  entry_label_.Unuse();
+}
+
+
+void JumpTarget::AddReachingFrame(VirtualFrame* frame) {
+  ASSERT(reaching_frames_.length() == merge_labels_.length());
+  ASSERT(entry_frame_ == NULL);
+  Label fresh;
+  merge_labels_.Add(fresh);
+  reaching_frames_.Add(frame);
+}
+
+
+// -------------------------------------------------------------------------
+// BreakTarget implementation.
+
+void BreakTarget::set_direction(Directionality direction) {
+  JumpTarget::set_direction(direction);
+  ASSERT(cgen()->has_valid_frame());
+  expected_height_ = cgen()->frame()->height();
+}
+
+
+void BreakTarget::CopyTo(BreakTarget* destination) {
+  ASSERT(destination != NULL);
+  destination->direction_ = direction_;
+  destination->reaching_frames_.Rewind(0);
+  destination->reaching_frames_.AddAll(reaching_frames_);
+  destination->merge_labels_.Rewind(0);
+  destination->merge_labels_.AddAll(merge_labels_);
+  destination->entry_frame_ = entry_frame_;
+  destination->entry_label_ = entry_label_;
+  destination->expected_height_ = expected_height_;
+}
+
+
+void BreakTarget::Branch(Condition cc, Hint hint) {
+  ASSERT(cgen()->has_valid_frame());
+
+  int count = cgen()->frame()->height() - expected_height_;
+  if (count > 0) {
+    // We negate and branch here rather than using DoBranch's negate
+    // and branch.  This gives us a hook to remove statement state
+    // from the frame.
+    JumpTarget fall_through;
+    // Branch to fall through will not negate, because it is a
+    // forward-only target.
+    fall_through.Branch(NegateCondition(cc), NegateHint(hint));
+    Jump();  // May emit merge code here.
+    fall_through.Bind();
+  } else {
+    DoBranch(cc, hint);
+  }
+}
+
 } }  // namespace v8::internal
diff --git a/src/jump-target-heavy.h b/src/jump-target-heavy.h
new file mode 100644 (file)
index 0000000..b923fe5
--- /dev/null
@@ -0,0 +1,242 @@
+// Copyright 2008 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_JUMP_TARGET_HEAVY_H_
+#define V8_JUMP_TARGET_HEAVY_H_
+
+#include "macro-assembler.h"
+#include "zone-inl.h"
+
+namespace v8 {
+namespace internal {
+
+// Forward declarations.
+class FrameElement;
+class Result;
+class VirtualFrame;
+
+// -------------------------------------------------------------------------
+// Jump targets
+//
+// A jump target is an abstraction of a basic-block entry in generated
+// code.  It collects all the virtual frames reaching the block by
+// forward jumps and pairs them with labels for the merge code along
+// all forward-reaching paths.  When bound, an expected frame for the
+// block is determined and code is generated to merge to the expected
+// frame.  For backward jumps, the merge code is generated at the edge
+// leaving the predecessor block.
+//
+// A jump target must have been reached via control flow (either by
+// jumping, branching, or falling through) at the time it is bound.
+// In particular, this means that at least one of the control-flow
+// graph edges reaching the target must be a forward edge.
+
+class JumpTarget : public ZoneObject {  // Shadows are dynamically allocated.
+ public:
+  // Forward-only jump targets can only be reached by forward CFG edges.
+  enum Directionality { FORWARD_ONLY, BIDIRECTIONAL };
+
+  // Construct a jump target used to generate code and to provide
+  // access to a current frame.
+  explicit JumpTarget(Directionality direction)
+      : direction_(direction),
+        reaching_frames_(0),
+        merge_labels_(0),
+        entry_frame_(NULL) {
+  }
+
+  // Construct a jump target.
+  JumpTarget()
+      : direction_(FORWARD_ONLY),
+        reaching_frames_(0),
+        merge_labels_(0),
+        entry_frame_(NULL) {
+  }
+
+  virtual ~JumpTarget() {}
+
+  // Set the direction of the jump target.
+  virtual void set_direction(Directionality direction) {
+    direction_ = direction;
+  }
+
+  // Treat the jump target as a fresh one.  The state is reset.
+  void Unuse();
+
+  inline CodeGenerator* cgen();
+
+  Label* entry_label() { return &entry_label_; }
+
+  VirtualFrame* entry_frame() const { return entry_frame_; }
+  void set_entry_frame(VirtualFrame* frame) {
+    entry_frame_ = frame;
+  }
+
+  // Predicates testing the state of the encapsulated label.
+  bool is_bound() const { return entry_label_.is_bound(); }
+  bool is_linked() const {
+    return !is_bound() && !reaching_frames_.is_empty();
+  }
+  bool is_unused() const {
+    // This is !is_bound() && !is_linked().
+    return !is_bound() && reaching_frames_.is_empty();
+  }
+
+  // Emit a jump to the target.  There must be a current frame at the
+  // jump and there will be no current frame after the jump.
+  virtual void Jump();
+  virtual void Jump(Result* arg);
+
+  // Emit a conditional branch to the target.  There must be a current
+  // frame at the branch.  The current frame will fall through to the
+  // code after the branch.  The arg is a result that is live both at
+  // the target and the fall-through.
+  virtual void Branch(Condition cc, Hint hint = no_hint);
+  virtual void Branch(Condition cc, Result* arg, Hint hint = no_hint);
+  virtual void Branch(Condition cc,
+                      Result* arg0,
+                      Result* arg1,
+                      Hint hint = no_hint);
+
+  // Bind a jump target.  If there is no current frame at the binding
+  // site, there must be at least one frame reaching via a forward
+  // jump.
+  virtual void Bind();
+  virtual void Bind(Result* arg);
+  virtual void Bind(Result* arg0, Result* arg1);
+
+  // Emit a call to a jump target.  There must be a current frame at
+  // the call.  The frame at the target is the same as the current
+  // frame except for an extra return address on top of it.  The frame
+  // after the call is the same as the frame before the call.
+  void Call();
+
+  static void set_compiling_deferred_code(bool flag) {
+    compiling_deferred_code_ = flag;
+  }
+
+ protected:
+  // Directionality flag set at initialization time.
+  Directionality direction_;
+
+  // A list of frames reaching this block via forward jumps.
+  ZoneList<VirtualFrame*> reaching_frames_;
+
+  // A parallel list of labels for merge code.
+  ZoneList<Label> merge_labels_;
+
+  // The frame used on entry to the block and expected at backward
+  // jumps to the block.  Set when the jump target is bound, but may
+  // or may not be set for forward-only blocks.
+  VirtualFrame* entry_frame_;
+
+  // The actual entry label of the block.
+  Label entry_label_;
+
+  // Implementations of Jump, Branch, and Bind with all arguments and
+  // return values using the virtual frame.
+  void DoJump();
+  void DoBranch(Condition cc, Hint hint);
+  void DoBind();
+
+ private:
+  static bool compiling_deferred_code_;
+
+  // Add a virtual frame reaching this labeled block via a forward jump,
+  // and a corresponding merge code label.
+  void AddReachingFrame(VirtualFrame* frame);
+
+  // Perform initialization required during entry frame computation
+  // after setting the virtual frame element at index in frame to be
+  // target.
+  inline void InitializeEntryElement(int index, FrameElement* target);
+
+  // Compute a frame to use for entry to this block.
+  void ComputeEntryFrame();
+
+  DISALLOW_COPY_AND_ASSIGN(JumpTarget);
+};
+
+
+// -------------------------------------------------------------------------
+// Break targets
+//
+// A break target is a jump target that can be used to break out of a
+// statement that keeps extra state on the stack (eg, for/in or
+// try/finally).  They know the expected stack height at the target
+// and will drop state from nested statements as part of merging.
+//
+// Break targets are used for return, break, and continue targets.
+
+class BreakTarget : public JumpTarget {
+ public:
+  // Construct a break target.
+  BreakTarget() {}
+
+  virtual ~BreakTarget() {}
+
+  // Set the direction of the break target.
+  virtual void set_direction(Directionality direction);
+
+  // Copy the state of this break target to the destination.  The
+  // lists of forward-reaching frames and merge-point labels are
+  // copied.  All virtual frame pointers are copied, not the
+  // pointed-to frames.  The previous state of the destination is
+  // overwritten, without deallocating pointed-to virtual frames.
+  void CopyTo(BreakTarget* destination);
+
+  // Emit a jump to the target.  There must be a current frame at the
+  // jump and there will be no current frame after the jump.
+  virtual void Jump();
+  virtual void Jump(Result* arg);
+
+  // Emit a conditional branch to the target.  There must be a current
+  // frame at the branch.  The current frame will fall through to the
+  // code after the branch.
+  virtual void Branch(Condition cc, Hint hint = no_hint);
+  virtual void Branch(Condition cc, Result* arg, Hint hint = no_hint);
+
+  // Bind a break target.  If there is no current frame at the binding
+  // site, there must be at least one frame reaching via a forward
+  // jump.
+  virtual void Bind();
+  virtual void Bind(Result* arg);
+
+  // Setter for expected height.
+  void set_expected_height(int expected) { expected_height_ = expected; }
+
+ private:
+  // The expected height of the expression stack where the target will
+  // be bound, statically known at initialization time.
+  int expected_height_;
+
+  DISALLOW_COPY_AND_ASSIGN(BreakTarget);
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_JUMP_TARGET_HEAVY_H_
index 8d6c3ac516ae36b6fce0820cb52174ce9b2cd311..0b4eee40c8e75949be39f1dc442ab2bac1e4e770 100644 (file)
 namespace v8 {
 namespace internal {
 
-void JumpTarget::InitializeEntryElement(int index, FrameElement* target) {
-  UNIMPLEMENTED();
+// Construct a jump target.
+JumpTarget::JumpTarget(Directionality direction)
+    : entry_frame_set_(false),
+      entry_frame_(kInvalidVirtualFrameInitializer) {
 }
 
+JumpTarget::JumpTarget()
+    : entry_frame_set_(false),
+      entry_frame_(kInvalidVirtualFrameInitializer) {
+}
+
+
+BreakTarget::BreakTarget() { }
+
 } }  // namespace v8::internal
 
 #endif  // V8_JUMP_TARGET_LIGHT_INL_H_
index befb4307367117b90d16af5b8672373bf0bc1d21..76c3cb7f6b667c9b510086a1606cede981dc5fc8 100644 (file)
@@ -34,53 +34,76 @@ namespace v8 {
 namespace internal {
 
 
-void JumpTarget::Jump(Result* arg) {
-  UNIMPLEMENTED();
-}
+DeferredCode::DeferredCode()
+    : masm_(CodeGeneratorScope::Current()->masm()),
+      statement_position_(masm_->current_statement_position()),
+      position_(masm_->current_position()) {
+  ASSERT(statement_position_ != RelocInfo::kNoPosition);
+  ASSERT(position_ != RelocInfo::kNoPosition);
 
+  CodeGeneratorScope::Current()->AddDeferred(this);
 
-void JumpTarget::Branch(Condition cc, Result* arg, Hint hint) {
-  UNIMPLEMENTED();
+#ifdef DEBUG
+  CodeGeneratorScope::Current()->frame()->AssertIsSpilled();
+#endif
 }
 
 
-void JumpTarget::Branch(Condition cc, Result* arg0, Result* arg1, Hint hint) {
-  UNIMPLEMENTED();
-}
+// -------------------------------------------------------------------------
+// BreakTarget implementation.
 
 
-void BreakTarget::Branch(Condition cc, Result* arg, Hint hint) {
-  UNIMPLEMENTED();
+void BreakTarget::SetExpectedHeight() {
+  expected_height_ = cgen()->frame()->height();
 }
 
 
-void JumpTarget::Bind(Result* arg) {
-  UNIMPLEMENTED();
-}
-
+void BreakTarget::Jump() {
+  ASSERT(cgen()->has_valid_frame());
 
-void JumpTarget::Bind(Result* arg0, Result* arg1) {
-  UNIMPLEMENTED();
+  int count = cgen()->frame()->height() - expected_height_;
+  if (count > 0) {
+    cgen()->frame()->Drop(count);
+  }
+  DoJump();
 }
 
 
-void JumpTarget::ComputeEntryFrame() {
-  UNIMPLEMENTED();
+void BreakTarget::Branch(Condition cc, Hint hint) {
+  if (cc == al) {
+    Jump();
+    return;
+  }
+
+  ASSERT(cgen()->has_valid_frame());
+
+  int count = cgen()->frame()->height() - expected_height_;
+  if (count > 0) {
+    // We negate and branch here rather than using DoBranch's negate
+    // and branch.  This gives us a hook to remove statement state
+    // from the frame.
+    JumpTarget fall_through;
+    // Branch to fall through will not negate, because it is a
+    // forward-only target.
+    fall_through.Branch(NegateCondition(cc), NegateHint(hint));
+    // Emit merge code.
+    cgen()->frame()->Drop(count);
+    DoJump();
+    fall_through.Bind();
+  } else {
+    DoBranch(cc, hint);
+  }
 }
 
 
-DeferredCode::DeferredCode()
-    : masm_(CodeGeneratorScope::Current()->masm()),
-      statement_position_(masm_->current_statement_position()),
-      position_(masm_->current_position()) {
-  ASSERT(statement_position_ != RelocInfo::kNoPosition);
-  ASSERT(position_ != RelocInfo::kNoPosition);
-
-  CodeGeneratorScope::Current()->AddDeferred(this);
-
-#ifdef DEBUG
-  CodeGeneratorScope::Current()->frame()->AssertIsSpilled();
-#endif
+void BreakTarget::Bind() {
+  if (cgen()->has_valid_frame()) {
+    int count = cgen()->frame()->height() - expected_height_;
+    if (count > 0) {
+      cgen()->frame()->Drop(count);
+    }
+  }
+  DoBind();
 }
 
 } }  // namespace v8::internal
diff --git a/src/jump-target-light.h b/src/jump-target-light.h
new file mode 100644 (file)
index 0000000..656ec75
--- /dev/null
@@ -0,0 +1,187 @@
+// Copyright 2008 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_JUMP_TARGET_LIGHT_H_
+#define V8_JUMP_TARGET_LIGHT_H_
+
+#include "macro-assembler.h"
+#include "zone-inl.h"
+#include "virtual-frame.h"
+
+namespace v8 {
+namespace internal {
+
+// Forward declarations.
+class FrameElement;
+class Result;
+
+// -------------------------------------------------------------------------
+// Jump targets
+//
+// A jump target is an abstraction of a basic-block entry in generated
+// code.  It collects all the virtual frames reaching the block by
+// forward jumps and pairs them with labels for the merge code along
+// all forward-reaching paths.  When bound, an expected frame for the
+// block is determined and code is generated to merge to the expected
+// frame.  For backward jumps, the merge code is generated at the edge
+// leaving the predecessor block.
+//
+// A jump target must have been reached via control flow (either by
+// jumping, branching, or falling through) at the time it is bound.
+// In particular, this means that at least one of the control-flow
+// graph edges reaching the target must be a forward edge.
+
+class JumpTarget : public ZoneObject {  // Shadows are dynamically allocated.
+ public:
+  // Forward-only jump targets can only be reached by forward CFG edges.
+  enum Directionality { FORWARD_ONLY, BIDIRECTIONAL };
+
+  // Construct a jump target.
+  explicit inline JumpTarget(Directionality direction);
+
+  inline JumpTarget();
+
+  virtual ~JumpTarget() {}
+
+  void Unuse() {
+    entry_frame_set_ = false;
+    entry_label_.Unuse();
+  }
+
+  inline CodeGenerator* cgen();
+
+  const VirtualFrame* entry_frame() const {
+    return entry_frame_set_ ? &entry_frame_ : NULL;
+  }
+
+  void set_entry_frame(VirtualFrame* frame) {
+    entry_frame_ = *frame;
+    entry_frame_set_ = true;
+  }
+
+  // Predicates testing the state of the encapsulated label.
+  bool is_bound() const { return entry_label_.is_bound(); }
+  bool is_linked() const { return entry_label_.is_linked(); }
+  bool is_unused() const { return entry_label_.is_unused(); }
+
+  // Copy the state of this jump target to the destination.
+  inline void CopyTo(JumpTarget* destination) {
+    *destination = *this;
+  }
+
+  // Emit a jump to the target.  There must be a current frame at the
+  // jump and there will be no current frame after the jump.
+  virtual void Jump();
+
+  // Emit a conditional branch to the target.  There must be a current
+  // frame at the branch.  The current frame will fall through to the
+  // code after the branch.  The arg is a result that is live both at
+  // the target and the fall-through.
+  virtual void Branch(Condition cc, Hint hint = no_hint);
+
+  // Bind a jump target.  If there is no current frame at the binding
+  // site, there must be at least one frame reaching via a forward
+  // jump.
+  virtual void Bind();
+
+  // Emit a call to a jump target.  There must be a current frame at
+  // the call.  The frame at the target is the same as the current
+  // frame except for an extra return address on top of it.  The frame
+  // after the call is the same as the frame before the call.
+  void Call();
+
+ protected:
+  // Has an entry frame been found?
+  bool entry_frame_set_;
+
+  // The frame used on entry to the block and expected at backward
+  // jumps to the block.  Set the first time something branches to this
+  // jump target.
+  VirtualFrame entry_frame_;
+
+  // The actual entry label of the block.
+  Label entry_label_;
+
+  // Implementations of Jump, Branch, and Bind with all arguments and
+  // return values using the virtual frame.
+  void DoJump();
+  void DoBranch(Condition cc, Hint hint);
+  void DoBind();
+};
+
+
+// -------------------------------------------------------------------------
+// Break targets
+//
+// A break target is a jump target that can be used to break out of a
+// statement that keeps extra state on the stack (eg, for/in or
+// try/finally).  They know the expected stack height at the target
+// and will drop state from nested statements as part of merging.
+//
+// Break targets are used for return, break, and continue targets.
+
+class BreakTarget : public JumpTarget {
+ public:
+  // Construct a break target.
+  inline BreakTarget();
+
+  virtual ~BreakTarget() {}
+
+  // Copy the state of this jump target to the destination.
+  inline void CopyTo(BreakTarget* destination) {
+    *destination = *this;
+  }
+
+  // Emit a jump to the target.  There must be a current frame at the
+  // jump and there will be no current frame after the jump.
+  virtual void Jump();
+
+  // Emit a conditional branch to the target.  There must be a current
+  // frame at the branch.  The current frame will fall through to the
+  // code after the branch.
+  virtual void Branch(Condition cc, Hint hint = no_hint);
+
+  // Bind a break target.  If there is no current frame at the binding
+  // site, there must be at least one frame reaching via a forward
+  // jump.
+  virtual void Bind();
+
+  // Setter for expected height.
+  void set_expected_height(int expected) { expected_height_ = expected; }
+
+  // Uses the current frame to set the expected height.
+  void SetExpectedHeight();
+
+ private:
+  // The expected height of the expression stack where the target will
+  // be bound, statically known at initialization time.
+  int expected_height_;
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_JUMP_TARGET_LIGHT_H_
index 8b2999549e8b9ea861d6c74f296747ec63bbfff3..72aada8abff1d159d9fc0e92a47f14758070a85f 100644 (file)
@@ -37,17 +37,6 @@ namespace internal {
 // -------------------------------------------------------------------------
 // JumpTarget implementation.
 
-bool JumpTarget::compiling_deferred_code_ = false;
-
-
-void JumpTarget::Unuse() {
-  reaching_frames_.Clear();
-  merge_labels_.Clear();
-  entry_frame_ = NULL;
-  entry_label_.Unuse();
-}
-
-
 void JumpTarget::Jump() {
   DoJump();
 }
@@ -63,58 +52,6 @@ void JumpTarget::Bind() {
 }
 
 
-void JumpTarget::AddReachingFrame(VirtualFrame* frame) {
-  ASSERT(reaching_frames_.length() == merge_labels_.length());
-  ASSERT(entry_frame_ == NULL);
-  Label fresh;
-  merge_labels_.Add(fresh);
-  reaching_frames_.Add(frame);
-}
-
-
-// -------------------------------------------------------------------------
-// BreakTarget implementation.
-
-void BreakTarget::set_direction(Directionality direction) {
-  JumpTarget::set_direction(direction);
-  ASSERT(cgen()->has_valid_frame());
-  expected_height_ = cgen()->frame()->height();
-}
-
-
-void BreakTarget::CopyTo(BreakTarget* destination) {
-  ASSERT(destination != NULL);
-  destination->direction_ = direction_;
-  destination->reaching_frames_.Rewind(0);
-  destination->reaching_frames_.AddAll(reaching_frames_);
-  destination->merge_labels_.Rewind(0);
-  destination->merge_labels_.AddAll(merge_labels_);
-  destination->entry_frame_ = entry_frame_;
-  destination->entry_label_ = entry_label_;
-  destination->expected_height_ = expected_height_;
-}
-
-
-void BreakTarget::Branch(Condition cc, Hint hint) {
-  ASSERT(cgen()->has_valid_frame());
-
-  int count = cgen()->frame()->height() - expected_height_;
-  if (count > 0) {
-    // We negate and branch here rather than using DoBranch's negate
-    // and branch.  This gives us a hook to remove statement state
-    // from the frame.
-    JumpTarget fall_through;
-    // Branch to fall through will not negate, because it is a
-    // forward-only target.
-    fall_through.Branch(NegateCondition(cc), NegateHint(hint));
-    Jump();  // May emit merge code here.
-    fall_through.Bind();
-  } else {
-    DoBranch(cc, hint);
-  }
-}
-
-
 // -------------------------------------------------------------------------
 // ShadowTarget implementation.
 
@@ -151,5 +88,4 @@ void ShadowTarget::StopShadowing() {
 #endif
 }
 
-
 } }  // namespace v8::internal
index db523b55ba8932663ad65410de89b34372585487..a0d2686b0f57136688994992bc44975d004a874c 100644 (file)
 #ifndef V8_JUMP_TARGET_H_
 #define V8_JUMP_TARGET_H_
 
-#include "macro-assembler.h"
-#include "zone-inl.h"
+#if V8_TARGET_ARCH_IA32
+#include "jump-target-heavy.h"
+#elif V8_TARGET_ARCH_X64
+#include "jump-target-heavy.h"
+#elif V8_TARGET_ARCH_ARM
+#include "jump-target-light.h"
+#elif V8_TARGET_ARCH_MIPS
+#include "jump-target-light.h"
+#else
+#error Unsupported target architecture.
+#endif
 
 namespace v8 {
 namespace internal {
 
-// Forward declarations.
-class FrameElement;
-class Result;
-class VirtualFrame;
-
-// -------------------------------------------------------------------------
-// Jump targets
-//
-// A jump target is an abstraction of a basic-block entry in generated
-// code.  It collects all the virtual frames reaching the block by
-// forward jumps and pairs them with labels for the merge code along
-// all forward-reaching paths.  When bound, an expected frame for the
-// block is determined and code is generated to merge to the expected
-// frame.  For backward jumps, the merge code is generated at the edge
-// leaving the predecessor block.
-//
-// A jump target must have been reached via control flow (either by
-// jumping, branching, or falling through) at the time it is bound.
-// In particular, this means that at least one of the control-flow
-// graph edges reaching the target must be a forward edge.
-
-class JumpTarget : public ZoneObject {  // Shadows are dynamically allocated.
- public:
-  // Forward-only jump targets can only be reached by forward CFG edges.
-  enum Directionality { FORWARD_ONLY, BIDIRECTIONAL };
-
-  // Construct a jump target used to generate code and to provide
-  // access to a current frame.
-  explicit JumpTarget(Directionality direction)
-      : direction_(direction),
-        reaching_frames_(0),
-        merge_labels_(0),
-        entry_frame_(NULL) {
-  }
-
-  // Construct a jump target.
-  JumpTarget()
-      : direction_(FORWARD_ONLY),
-        reaching_frames_(0),
-        merge_labels_(0),
-        entry_frame_(NULL) {
-  }
-
-  virtual ~JumpTarget() {}
-
-  // Set the direction of the jump target.
-  virtual void set_direction(Directionality direction) {
-    direction_ = direction;
-  }
-
-  // Treat the jump target as a fresh one.  The state is reset.
-  void Unuse();
-
-  inline CodeGenerator* cgen();
-
-  Label* entry_label() { return &entry_label_; }
-
-  VirtualFrame* entry_frame() const { return entry_frame_; }
-  void set_entry_frame(VirtualFrame* frame) {
-    entry_frame_ = frame;
-  }
-
-  // Predicates testing the state of the encapsulated label.
-  bool is_bound() const { return entry_label_.is_bound(); }
-  bool is_linked() const {
-    return !is_bound() && !reaching_frames_.is_empty();
-  }
-  bool is_unused() const {
-    // This is !is_bound() && !is_linked().
-    return !is_bound() && reaching_frames_.is_empty();
-  }
-
-  // Emit a jump to the target.  There must be a current frame at the
-  // jump and there will be no current frame after the jump.
-  virtual void Jump();
-  virtual void Jump(Result* arg);
-
-  // Emit a conditional branch to the target.  There must be a current
-  // frame at the branch.  The current frame will fall through to the
-  // code after the branch.  The arg is a result that is live both at
-  // the target and the fall-through.
-  virtual void Branch(Condition cc, Hint hint = no_hint);
-  virtual void Branch(Condition cc, Result* arg, Hint hint = no_hint);
-  virtual void Branch(Condition cc,
-                      Result* arg0,
-                      Result* arg1,
-                      Hint hint = no_hint);
-
-  // Bind a jump target.  If there is no current frame at the binding
-  // site, there must be at least one frame reaching via a forward
-  // jump.
-  virtual void Bind();
-  virtual void Bind(Result* arg);
-  virtual void Bind(Result* arg0, Result* arg1);
-
-  // Emit a call to a jump target.  There must be a current frame at
-  // the call.  The frame at the target is the same as the current
-  // frame except for an extra return address on top of it.  The frame
-  // after the call is the same as the frame before the call.
-  void Call();
-
-  static void set_compiling_deferred_code(bool flag) {
-    compiling_deferred_code_ = flag;
-  }
-
- protected:
-  // Directionality flag set at initialization time.
-  Directionality direction_;
-
-  // A list of frames reaching this block via forward jumps.
-  ZoneList<VirtualFrame*> reaching_frames_;
-
-  // A parallel list of labels for merge code.
-  ZoneList<Label> merge_labels_;
-
-  // The frame used on entry to the block and expected at backward
-  // jumps to the block.  Set when the jump target is bound, but may
-  // or may not be set for forward-only blocks.
-  VirtualFrame* entry_frame_;
-
-  // The actual entry label of the block.
-  Label entry_label_;
-
-  // Implementations of Jump, Branch, and Bind with all arguments and
-  // return values using the virtual frame.
-  void DoJump();
-  void DoBranch(Condition cc, Hint hint);
-  void DoBind();
-
- private:
-  static bool compiling_deferred_code_;
-
-  // Add a virtual frame reaching this labeled block via a forward jump,
-  // and a corresponding merge code label.
-  void AddReachingFrame(VirtualFrame* frame);
-
-  // Perform initialization required during entry frame computation
-  // after setting the virtual frame element at index in frame to be
-  // target.
-  inline void InitializeEntryElement(int index, FrameElement* target);
-
-  // Compute a frame to use for entry to this block.
-  void ComputeEntryFrame();
-
-  DISALLOW_COPY_AND_ASSIGN(JumpTarget);
-};
-
-
-// -------------------------------------------------------------------------
-// Break targets
-//
-// A break target is a jump target that can be used to break out of a
-// statement that keeps extra state on the stack (eg, for/in or
-// try/finally).  They know the expected stack height at the target
-// and will drop state from nested statements as part of merging.
-//
-// Break targets are used for return, break, and continue targets.
-
-class BreakTarget : public JumpTarget {
- public:
-  // Construct a break target.
-  BreakTarget() {}
-
-  virtual ~BreakTarget() {}
-
-  // Set the direction of the break target.
-  virtual void set_direction(Directionality direction);
-
-  // Copy the state of this break target to the destination.  The
-  // lists of forward-reaching frames and merge-point labels are
-  // copied.  All virtual frame pointers are copied, not the
-  // pointed-to frames.  The previous state of the destination is
-  // overwritten, without deallocating pointed-to virtual frames.
-  void CopyTo(BreakTarget* destination);
-
-  // Emit a jump to the target.  There must be a current frame at the
-  // jump and there will be no current frame after the jump.
-  virtual void Jump();
-  virtual void Jump(Result* arg);
-
-  // Emit a conditional branch to the target.  There must be a current
-  // frame at the branch.  The current frame will fall through to the
-  // code after the branch.
-  virtual void Branch(Condition cc, Hint hint = no_hint);
-  virtual void Branch(Condition cc, Result* arg, Hint hint = no_hint);
-
-  // Bind a break target.  If there is no current frame at the binding
-  // site, there must be at least one frame reaching via a forward
-  // jump.
-  virtual void Bind();
-  virtual void Bind(Result* arg);
-
-  // Setter for expected height.
-  void set_expected_height(int expected) { expected_height_ = expected; }
-
- private:
-  // The expected height of the expression stack where the target will
-  // be bound, statically known at initialization time.
-  int expected_height_;
-
-  DISALLOW_COPY_AND_ASSIGN(BreakTarget);
-};
-
-
 // -------------------------------------------------------------------------
 // Shadow break targets
 //
@@ -280,7 +85,6 @@ class ShadowTarget : public BreakTarget {
   DISALLOW_COPY_AND_ASSIGN(ShadowTarget);
 };
 
-
 } }  // namespace v8::internal
 
 #endif  // V8_JUMP_TARGET_H_
index 089eeeea60ebdcdab83e81d3ab70a442d733f1cd..c482fdf5f98f06c7bb4d3af0194c2e7a71e694d1 100644 (file)
 #include "codegen.h"
 #include "compiler.h"
 #include "messages.h"
+#include "parser.h"
 #include "platform.h"
 #include "runtime.h"
-#include "parser.h"
 #include "scopes.h"
 #include "string-stream.h"
 
+#include "ast-inl.h"
+#include "jump-target-inl.h"
+
 namespace v8 {
 namespace internal {
 
index b9989a5dde0de5d3c8760eaf7bb6fe67bf5b5998..31d0a49fa55f7ddbf7d07290d59a656a52b9f9e9 100644 (file)
@@ -84,15 +84,16 @@ Result RegisterAllocator::Allocate() {
 
 Result RegisterAllocator::Allocate(Register target) {
   // If the target is not referenced, it can simply be allocated.
-  if (!is_used(target)) {
+  if (!is_used(RegisterAllocator::ToNumber(target))) {
     return Result(target);
   }
   // If the target is only referenced in the frame, it can be spilled and
   // then allocated.
   ASSERT(cgen_->has_valid_frame());
-  if (cgen_->frame()->is_used(target) && count(target) == 1)  {
+  if (cgen_->frame()->is_used(RegisterAllocator::ToNumber(target)) &&
+      count(target) == 1)  {
     cgen_->frame()->Spill(target);
-    ASSERT(!is_used(target));
+    ASSERT(!is_used(RegisterAllocator::ToNumber(target)));
     return Result(target);
   }
   // Otherwise (if it's referenced outside the frame) we cannot allocate it.
index 6381d0126683dc4c2e7fa77e7d290e3d96400b85..2755eee648d37e1b4e9bef13bcffbb4f1fecf169 100644 (file)
@@ -31,6 +31,8 @@
 #include "type-info.h"
 #include "register-allocator.h"
 #include "scopes.h"
+#include "register-allocator-inl.h"
+#include "codegen-inl.h"
 
 namespace v8 {
 namespace internal {
@@ -147,6 +149,44 @@ void VirtualFrame::Push(Smi* value) {
   Push(Handle<Object> (value));
 }
 
+
+int VirtualFrame::register_location(Register reg) {
+  return register_locations_[RegisterAllocator::ToNumber(reg)];
+}
+
+
+void VirtualFrame::set_register_location(Register reg, int index) {
+  register_locations_[RegisterAllocator::ToNumber(reg)] = index;
+}
+
+
+bool VirtualFrame::is_used(Register reg) {
+  return register_locations_[RegisterAllocator::ToNumber(reg)]
+      != kIllegalIndex;
+}
+
+
+void VirtualFrame::SetElementAt(int index, Handle<Object> value) {
+  Result temp(value);
+  SetElementAt(index, &temp);
+}
+
+
+Result VirtualFrame::CallStub(CodeStub* stub, int arg_count) {
+  PrepareForCall(arg_count, arg_count);
+  return RawCallStub(stub);
+}
+
+
+int VirtualFrame::parameter_count() {
+  return cgen()->scope()->num_parameters();
+}
+
+
+int VirtualFrame::local_count() {
+  return cgen()->scope()->num_stack_slots();
+}
+
 } }  // namespace v8::internal
 
 #endif  // V8_VIRTUAL_FRAME_HEAVY_INL_H_
index c50e6c8cf89fc0fbb5a92d41110680a2183ea255..17b1c504396b02db003a1f4b4f580a57e62f0ecd 100644 (file)
 #ifndef V8_VIRTUAL_FRAME_LIGHT_INL_H_
 #define V8_VIRTUAL_FRAME_LIGHT_INL_H_
 
-#include "type-info.h"
+#include "codegen.h"
 #include "register-allocator.h"
 #include "scopes.h"
+#include "type-info.h"
+
+#include "codegen-inl.h"
+#include "jump-target-light-inl.h"
 
 namespace v8 {
 namespace internal {
 
+VirtualFrame::VirtualFrame(InvalidVirtualFrameInitializer* dummy)
+    : element_count_(0),
+      top_of_stack_state_(NO_TOS_REGISTERS),
+      register_allocation_map_(0) { }
+
+
 // On entry to a function, the virtual frame already contains the receiver,
 // the parameters, and a return address.  All frame elements are in memory.
 VirtualFrame::VirtualFrame()
@@ -64,6 +74,87 @@ void VirtualFrame::PrepareForReturn() {
 }
 
 
+VirtualFrame::RegisterAllocationScope::RegisterAllocationScope(
+    CodeGenerator* cgen)
+  : cgen_(cgen),
+    old_is_spilled_(SpilledScope::is_spilled_) {
+  SpilledScope::is_spilled_ = false;
+  if (old_is_spilled_) {
+    VirtualFrame* frame = cgen->frame();
+    if (frame != NULL) {
+      frame->AssertIsSpilled();
+    }
+  }
+}
+
+
+VirtualFrame::RegisterAllocationScope::~RegisterAllocationScope() {
+  SpilledScope::is_spilled_ = old_is_spilled_;
+  if (old_is_spilled_) {
+    VirtualFrame* frame = cgen_->frame();
+    if (frame != NULL) {
+      frame->SpillAll();
+    }
+  }
+}
+
+
+CodeGenerator* VirtualFrame::cgen() { return CodeGeneratorScope::Current(); }
+
+
+MacroAssembler* VirtualFrame::masm() { return cgen()->masm(); }
+
+
+void VirtualFrame::CallStub(CodeStub* stub, int arg_count) {
+  if (arg_count != 0) Forget(arg_count);
+  ASSERT(cgen()->HasValidEntryRegisters());
+  masm()->CallStub(stub);
+}
+
+
+int VirtualFrame::parameter_count() {
+  return cgen()->scope()->num_parameters();
+}
+
+
+int VirtualFrame::local_count() { return cgen()->scope()->num_stack_slots(); }
+
+
+int VirtualFrame::frame_pointer() { return parameter_count() + 3; }
+
+
+int VirtualFrame::context_index() { return frame_pointer() - 1; }
+
+
+int VirtualFrame::function_index() { return frame_pointer() - 2; }
+
+
+int VirtualFrame::local0_index() { return frame_pointer() + 2; }
+
+
+int VirtualFrame::fp_relative(int index) {
+  ASSERT(index < element_count());
+  ASSERT(frame_pointer() < element_count());  // FP is on the frame.
+  return (frame_pointer() - index) * kPointerSize;
+}
+
+
+int VirtualFrame::expression_base_index() {
+  return local0_index() + local_count();
+}
+
+
+int VirtualFrame::height() {
+  return element_count() - expression_base_index();
+}
+
+
+MemOperand VirtualFrame::LocalAt(int index) {
+  ASSERT(0 <= index);
+  ASSERT(index < local_count());
+  return MemOperand(fp, kLocal0Offset - index * kPointerSize);
+}
+
 } }  // namespace v8::internal
 
 #endif  // V8_VIRTUAL_FRAME_LIGHT_INL_H_
index 27c48a537c72ae1298f5645fe24632472a470e03..9c019cf7ff895c5e4a229d3379b5c172bbccaeb2 100644 (file)
@@ -46,4 +46,7 @@ Register VirtualFrame::SpillAnyRegister() {
   return no_reg;
 }
 
+
+InvalidVirtualFrameInitializer* kInvalidVirtualFrameInitializer = NULL;
+
 } }  // namespace v8::internal
index 5d9861ba65fbb3bb02bc4bd46352003b372f492e..a89f23eda8fb570a03c5f7de897b25197d785d40 100644 (file)
@@ -28,7 +28,9 @@
 #ifndef V8_X64_CODEGEN_X64_H_
 #define V8_X64_CODEGEN_X64_H_
 
+#include "ast.h"
 #include "ic-inl.h"
+#include "jump-target-heavy.h"
 
 namespace v8 {
 namespace internal {
index 7cda181865a9f5b5944b481e28e12e526871c5a1..529f47a82c5e38832534fa1c91b5c20da01b6449 100644 (file)
@@ -31,6 +31,7 @@
 #include "type-info.h"
 #include "register-allocator.h"
 #include "scopes.h"
+#include "codegen.h"
 
 namespace v8 {
 namespace internal {
@@ -98,23 +99,16 @@ class VirtualFrame : public ZoneObject {
     return register_locations_[num];
   }
 
-  int register_location(Register reg) {
-    return register_locations_[RegisterAllocator::ToNumber(reg)];
-  }
+  inline int register_location(Register reg);
 
-  void set_register_location(Register reg, int index) {
-    register_locations_[RegisterAllocator::ToNumber(reg)] = index;
-  }
+  inline void set_register_location(Register reg, int index);
 
   bool is_used(int num) {
     ASSERT(num >= 0 && num < RegisterAllocator::kNumRegisters);
     return register_locations_[num] != kIllegalIndex;
   }
 
-  bool is_used(Register reg) {
-    return register_locations_[RegisterAllocator::ToNumber(reg)]
-        != kIllegalIndex;
-  }
+  inline bool is_used(Register reg);
 
   // Add extra in-memory elements to the top of the frame to match an actual
   // frame (eg, the frame after an exception handler is pushed).  No code is
@@ -218,10 +212,7 @@ class VirtualFrame : public ZoneObject {
   void SetElementAt(int index, Result* value);
 
   // Set a frame element to a constant.  The index is frame-top relative.
-  void SetElementAt(int index, Handle<Object> value) {
-    Result temp(value);
-    SetElementAt(index, &temp);
-  }
+  inline void SetElementAt(int index, Handle<Object> value);
 
   void PushElementAt(int index) {
     PushFrameSlotAt(element_count() - index - 1);
@@ -302,10 +293,7 @@ class VirtualFrame : public ZoneObject {
 
   // Call stub given the number of arguments it expects on (and
   // removes from) the stack.
-  Result CallStub(CodeStub* stub, int arg_count) {
-    PrepareForCall(arg_count, arg_count);
-    return RawCallStub(stub);
-  }
+  inline Result CallStub(CodeStub* stub, int arg_count);
 
   // Call stub that takes a single argument passed in eax.  The
   // argument is given as a result which does not have to be eax or
@@ -446,8 +434,8 @@ class VirtualFrame : public ZoneObject {
   int register_locations_[RegisterAllocator::kNumRegisters];
 
   // The number of frame-allocated locals and parameters respectively.
-  int parameter_count() { return cgen()->scope()->num_parameters(); }
-  int local_count() { return cgen()->scope()->num_stack_slots(); }
+  inline int parameter_count();
+  inline int local_count();
 
   // The index of the element that is at the processor's frame pointer
   // (the ebp register).  The parameters, receiver, and return address
index 25ba5ebf8ec6f3ec32bf7059ec7d63840eeaa92d..aa32e0cf5fff0b59c4f492704da97d9132045163 100644 (file)
         '../../src/assembler.cc',
         '../../src/assembler.h',
         '../../src/ast.cc',
+        '../../src/ast-inl.h',
         '../../src/ast.h',
         '../../src/bootstrapper.cc',
         '../../src/bootstrapper.h',
           ],
           'sources': [
             '../../src/fast-codegen.cc',
+            '../../src/jump-target-light.h',
             '../../src/jump-target-light-inl.h',
             '../../src/jump-target-light.cc',
             '../../src/virtual-frame-light-inl.h',
             '../../src/arm/register-allocator-arm.cc',
             '../../src/arm/simulator-arm.cc',
             '../../src/arm/stub-cache-arm.cc',
+            '../../src/arm/virtual-frame-arm-inl.h',
             '../../src/arm/virtual-frame-arm.cc',
             '../../src/arm/virtual-frame-arm.h',
           ],
             '../../src/ia32',
           ],
           'sources': [
+            '../../src/jump-target-heavy.h',
             '../../src/jump-target-heavy-inl.h',
             '../../src/jump-target-heavy.cc',
             '../../src/virtual-frame-heavy-inl.h',
           ],
           'sources': [
             '../../src/fast-codegen.cc',
+            '../../src/jump-target-heavy.h',
             '../../src/jump-target-heavy-inl.h',
             '../../src/jump-target-heavy.cc',
             '../../src/virtual-frame-heavy-inl.h',
index e0845276c89c256575156779d4ab482927d183e0..004e16ee0ef973f0057eb842b54ba29e3fae5ab8 100644 (file)
                                RelativePath="..\..\src\assembler.h"
                                >
                        </File>
+                       <File
+                               RelativePath="..\..\src\ast-inl.h"
+                               >
+                       </File>
                        <File
                                RelativePath="..\..\src\ast.cc"
                                >
                                RelativePath="..\..\src\jump-target-heavy-inl.h"
                                >
                        </File>
+                       <File
+                               RelativePath="..\..\src\jump-target-heavy.h"
+                               >
+                       </File>
                        <File
                                RelativePath="..\..\src\jump-target.cc"
                                >
index e035392cf2d118165deb1a8468e60bc3c9dd4ed0..39cd42afe1f133c07d0f827d9368fde0d4ba6922 100644 (file)
                                RelativePath="..\..\src\assembler.h"
                                >
                        </File>
+                       <File
+                               RelativePath="..\..\src\ast-inl.h"
+                               >
+                       </File>
                        <File
                                RelativePath="..\..\src\ast.cc"
                                >
                                RelativePath="..\..\src\jump-target-light-inl.h"
                                >
                        </File>
+                       <File
+                               RelativePath="..\..\src\jump-target-light.h"
+                               >
+                       </File>
                        <File
                                RelativePath="..\..\src\jump-target.cc"
                                >
                                RelativePath="..\..\src\virtual-frame.h"
                                >
                        </File>
+                       <File
+                               RelativePath="..\..\src\arm\virtual-frame-arm-inl.h"
+                               >
+                       </File>
                        <File
                                RelativePath="..\..\src\arm\virtual-frame-arm.h"
                                >
index 25cac8ed9e613add6e2f743af02c6fb860f87702..46078179e1857ab6e10ac57dc7775e333a8fc4b7 100644 (file)
                                RelativePath="..\..\src\assembler.h"
                                >
                        </File>
+                       <File
+                               RelativePath="..\..\src\ast-inl.h"
+                               >
+                       </File>
                        <File
                                RelativePath="..\..\src\ast.cc"
                                >
                                RelativePath="..\..\src\jump-target-heavy-inl.h"
                                >
                        </File>
+                       <File
+                               RelativePath="..\..\src\jump-target-heavy.h"
+                               >
+                       </File>
                        <File
                                RelativePath="..\..\src\jump-target.cc"
                                >