Move V8 to external/v8

Change-Id: If68025d67453785a651c5dfb34fad298c16676a4
diff --git a/src/frames.cc b/src/frames.cc
new file mode 100644
index 0000000..5cd8332
--- /dev/null
+++ b/src/frames.cc
@@ -0,0 +1,743 @@
+// Copyright 2006-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.
+
+#include "v8.h"
+
+#include "frames-inl.h"
+#include "mark-compact.h"
+#include "scopeinfo.h"
+#include "string-stream.h"
+#include "top.h"
+#include "zone-inl.h"
+
+namespace v8 {
+namespace internal {
+
+// Iterator that supports traversing the stack handlers of a
+// particular frame. Needs to know the top of the handler chain.
+class StackHandlerIterator BASE_EMBEDDED {
+ public:
+  StackHandlerIterator(const StackFrame* frame, StackHandler* handler)
+      : limit_(frame->fp()), handler_(handler) {
+    // Make sure the handler has already been unwound to this frame.
+    ASSERT(frame->sp() <= handler->address());
+  }
+
+  StackHandler* handler() const { return handler_; }
+
+  bool done() {
+    return handler_ == NULL || handler_->address() > limit_;
+  }
+  void Advance() {
+    ASSERT(!done());
+    handler_ = handler_->next();
+  }
+
+ private:
+  const Address limit_;
+  StackHandler* handler_;
+};
+
+
+// -------------------------------------------------------------------------
+
+
+#define INITIALIZE_SINGLETON(type, field) field##_(this),
+StackFrameIterator::StackFrameIterator()
+    : STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
+      frame_(NULL), handler_(NULL), thread_(Top::GetCurrentThread()),
+      fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler) {
+  Reset();
+}
+StackFrameIterator::StackFrameIterator(ThreadLocalTop* t)
+    : STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
+      frame_(NULL), handler_(NULL), thread_(t),
+      fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler) {
+  Reset();
+}
+StackFrameIterator::StackFrameIterator(bool use_top, Address fp, Address sp)
+    : STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
+      frame_(NULL), handler_(NULL),
+      thread_(use_top ? Top::GetCurrentThread() : NULL),
+      fp_(use_top ? NULL : fp), sp_(sp),
+      advance_(use_top ? &StackFrameIterator::AdvanceWithHandler :
+               &StackFrameIterator::AdvanceWithoutHandler) {
+  if (use_top || fp != NULL) {
+    Reset();
+  }
+  JavaScriptFrame_.DisableHeapAccess();
+}
+
+#undef INITIALIZE_SINGLETON
+
+
+void StackFrameIterator::AdvanceWithHandler() {
+  ASSERT(!done());
+  // Compute the state of the calling frame before restoring
+  // callee-saved registers and unwinding handlers. This allows the
+  // frame code that computes the caller state to access the top
+  // handler and the value of any callee-saved register if needed.
+  StackFrame::State state;
+  StackFrame::Type type = frame_->GetCallerState(&state);
+
+  // Unwind handlers corresponding to the current frame.
+  StackHandlerIterator it(frame_, handler_);
+  while (!it.done()) it.Advance();
+  handler_ = it.handler();
+
+  // Advance to the calling frame.
+  frame_ = SingletonFor(type, &state);
+
+  // When we're done iterating over the stack frames, the handler
+  // chain must have been completely unwound.
+  ASSERT(!done() || handler_ == NULL);
+}
+
+
+void StackFrameIterator::AdvanceWithoutHandler() {
+  // A simpler version of Advance which doesn't care about handler.
+  ASSERT(!done());
+  StackFrame::State state;
+  StackFrame::Type type = frame_->GetCallerState(&state);
+  frame_ = SingletonFor(type, &state);
+}
+
+
+void StackFrameIterator::Reset() {
+  StackFrame::State state;
+  StackFrame::Type type;
+  if (thread_ != NULL) {
+    type = ExitFrame::GetStateForFramePointer(Top::c_entry_fp(thread_), &state);
+    handler_ = StackHandler::FromAddress(Top::handler(thread_));
+  } else {
+    ASSERT(fp_ != NULL);
+    state.fp = fp_;
+    state.sp = sp_;
+    state.pc_address =
+        reinterpret_cast<Address*>(StandardFrame::ComputePCAddress(fp_));
+    type = StackFrame::ComputeType(&state);
+    if (SingletonFor(type) == NULL) return;
+  }
+  frame_ = SingletonFor(type, &state);
+}
+
+
+StackFrame* StackFrameIterator::SingletonFor(StackFrame::Type type,
+                                             StackFrame::State* state) {
+  if (type == StackFrame::NONE) return NULL;
+  StackFrame* result = SingletonFor(type);
+  ASSERT(result != NULL);
+  result->state_ = *state;
+  return result;
+}
+
+
+StackFrame* StackFrameIterator::SingletonFor(StackFrame::Type type) {
+#define FRAME_TYPE_CASE(type, field) \
+  case StackFrame::type: result = &field##_; break;
+
+  StackFrame* result = NULL;
+  switch (type) {
+    case StackFrame::NONE: return NULL;
+    STACK_FRAME_TYPE_LIST(FRAME_TYPE_CASE)
+    default: break;
+  }
+  return result;
+
+#undef FRAME_TYPE_CASE
+}
+
+
+// -------------------------------------------------------------------------
+
+
+StackTraceFrameIterator::StackTraceFrameIterator() {
+  if (!done() && !frame()->function()->IsJSFunction()) Advance();
+}
+
+
+void StackTraceFrameIterator::Advance() {
+  while (true) {
+    JavaScriptFrameIterator::Advance();
+    if (done()) return;
+    if (frame()->function()->IsJSFunction()) return;
+  }
+}
+
+
+// -------------------------------------------------------------------------
+
+
+SafeStackFrameIterator::SafeStackFrameIterator(
+    Address fp, Address sp, Address low_bound, Address high_bound) :
+    low_bound_(low_bound), high_bound_(high_bound),
+    is_valid_top_(
+        IsWithinBounds(low_bound, high_bound,
+                       Top::c_entry_fp(Top::GetCurrentThread())) &&
+        Top::handler(Top::GetCurrentThread()) != NULL),
+    is_valid_fp_(IsWithinBounds(low_bound, high_bound, fp)),
+    is_working_iterator_(is_valid_top_ || is_valid_fp_),
+    iteration_done_(!is_working_iterator_),
+    iterator_(is_valid_top_, is_valid_fp_ ? fp : NULL, sp) {
+}
+
+
+void SafeStackFrameIterator::Advance() {
+  ASSERT(is_working_iterator_);
+  ASSERT(!done());
+  StackFrame* last_frame = iterator_.frame();
+  Address last_sp = last_frame->sp(), last_fp = last_frame->fp();
+  // Before advancing to the next stack frame, perform pointer validity tests
+  iteration_done_ = !IsValidFrame(last_frame) ||
+      !CanIterateHandles(last_frame, iterator_.handler()) ||
+      !IsValidCaller(last_frame);
+  if (iteration_done_) return;
+
+  iterator_.Advance();
+  if (iterator_.done()) return;
+  // Check that we have actually moved to the previous frame in the stack
+  StackFrame* prev_frame = iterator_.frame();
+  iteration_done_ = prev_frame->sp() < last_sp || prev_frame->fp() < last_fp;
+}
+
+
+bool SafeStackFrameIterator::CanIterateHandles(StackFrame* frame,
+                                               StackHandler* handler) {
+  // If StackIterator iterates over StackHandles, verify that
+  // StackHandlerIterator can be instantiated (see StackHandlerIterator
+  // constructor.)
+  return !is_valid_top_ || (frame->sp() <= handler->address());
+}
+
+
+bool SafeStackFrameIterator::IsValidFrame(StackFrame* frame) const {
+  return IsValidStackAddress(frame->sp()) && IsValidStackAddress(frame->fp());
+}
+
+
+bool SafeStackFrameIterator::IsValidCaller(StackFrame* frame) {
+  StackFrame::State state;
+  if (frame->is_entry() || frame->is_entry_construct()) {
+    // See EntryFrame::GetCallerState. It computes the caller FP address
+    // and calls ExitFrame::GetStateForFramePointer on it. We need to be
+    // sure that caller FP address is valid.
+    Address caller_fp = Memory::Address_at(
+        frame->fp() + EntryFrameConstants::kCallerFPOffset);
+    if (!IsValidStackAddress(caller_fp)) {
+      return false;
+    }
+  } else if (frame->is_arguments_adaptor()) {
+    // See ArgumentsAdaptorFrame::GetCallerStackPointer. It assumes that
+    // the number of arguments is stored on stack as Smi. We need to check
+    // that it really an Smi.
+    Object* number_of_args = reinterpret_cast<ArgumentsAdaptorFrame*>(frame)->
+        GetExpression(0);
+    if (!number_of_args->IsSmi()) {
+      return false;
+    }
+  }
+  frame->ComputeCallerState(&state);
+  return IsValidStackAddress(state.sp) && IsValidStackAddress(state.fp) &&
+      iterator_.SingletonFor(frame->GetCallerState(&state)) != NULL;
+}
+
+
+void SafeStackFrameIterator::Reset() {
+  if (is_working_iterator_) {
+    iterator_.Reset();
+    iteration_done_ = false;
+  }
+}
+
+
+// -------------------------------------------------------------------------
+
+
+#ifdef ENABLE_LOGGING_AND_PROFILING
+SafeStackTraceFrameIterator::SafeStackTraceFrameIterator(
+    Address fp, Address sp, Address low_bound, Address high_bound) :
+    SafeJavaScriptFrameIterator(fp, sp, low_bound, high_bound) {
+  if (!done() && !frame()->is_java_script()) Advance();
+}
+
+
+void SafeStackTraceFrameIterator::Advance() {
+  while (true) {
+    SafeJavaScriptFrameIterator::Advance();
+    if (done()) return;
+    if (frame()->is_java_script()) return;
+  }
+}
+#endif
+
+
+// -------------------------------------------------------------------------
+
+
+void StackHandler::Cook(Code* code) {
+  ASSERT(MarkCompactCollector::IsCompacting());
+  ASSERT(code->contains(pc()));
+  set_pc(AddressFrom<Address>(pc() - code->instruction_start()));
+}
+
+
+void StackHandler::Uncook(Code* code) {
+  ASSERT(MarkCompactCollector::IsCompacting());
+  set_pc(code->instruction_start() + OffsetFrom(pc()));
+  ASSERT(code->contains(pc()));
+}
+
+
+// -------------------------------------------------------------------------
+
+
+bool StackFrame::HasHandler() const {
+  StackHandlerIterator it(this, top_handler());
+  return !it.done();
+}
+
+
+void StackFrame::CookFramesForThread(ThreadLocalTop* thread) {
+  // Only cooking frames when the collector is compacting and thus moving code
+  // around.
+  ASSERT(MarkCompactCollector::IsCompacting());
+  ASSERT(!thread->stack_is_cooked());
+  for (StackFrameIterator it(thread); !it.done(); it.Advance()) {
+    it.frame()->Cook();
+  }
+  thread->set_stack_is_cooked(true);
+}
+
+
+void StackFrame::UncookFramesForThread(ThreadLocalTop* thread) {
+  // Only uncooking frames when the collector is compacting and thus moving code
+  // around.
+  ASSERT(MarkCompactCollector::IsCompacting());
+  ASSERT(thread->stack_is_cooked());
+  for (StackFrameIterator it(thread); !it.done(); it.Advance()) {
+    it.frame()->Uncook();
+  }
+  thread->set_stack_is_cooked(false);
+}
+
+
+void StackFrame::Cook() {
+  Code* code = this->code();
+  for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) {
+    it.handler()->Cook(code);
+  }
+  ASSERT(code->contains(pc()));
+  set_pc(AddressFrom<Address>(pc() - code->instruction_start()));
+}
+
+
+void StackFrame::Uncook() {
+  Code* code = this->code();
+  for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) {
+    it.handler()->Uncook(code);
+  }
+  set_pc(code->instruction_start() + OffsetFrom(pc()));
+  ASSERT(code->contains(pc()));
+}
+
+
+StackFrame::Type StackFrame::GetCallerState(State* state) const {
+  ComputeCallerState(state);
+  return ComputeType(state);
+}
+
+
+Code* EntryFrame::code() const {
+  return Heap::js_entry_code();
+}
+
+
+void EntryFrame::ComputeCallerState(State* state) const {
+  GetCallerState(state);
+}
+
+
+StackFrame::Type EntryFrame::GetCallerState(State* state) const {
+  const int offset = EntryFrameConstants::kCallerFPOffset;
+  Address fp = Memory::Address_at(this->fp() + offset);
+  return ExitFrame::GetStateForFramePointer(fp, state);
+}
+
+
+Code* EntryConstructFrame::code() const {
+  return Heap::js_construct_entry_code();
+}
+
+
+Code* ExitFrame::code() const {
+  return Heap::c_entry_code();
+}
+
+
+void ExitFrame::ComputeCallerState(State* state) const {
+  // Setup the caller state.
+  state->sp = caller_sp();
+  state->fp = Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset);
+  state->pc_address
+      = reinterpret_cast<Address*>(fp() + ExitFrameConstants::kCallerPCOffset);
+}
+
+
+Address ExitFrame::GetCallerStackPointer() const {
+  return fp() + ExitFrameConstants::kCallerSPDisplacement;
+}
+
+
+Code* ExitDebugFrame::code() const {
+  return Heap::c_entry_debug_break_code();
+}
+
+
+Address StandardFrame::GetExpressionAddress(int n) const {
+  const int offset = StandardFrameConstants::kExpressionsOffset;
+  return fp() + offset - n * kPointerSize;
+}
+
+
+int StandardFrame::ComputeExpressionsCount() const {
+  const int offset =
+      StandardFrameConstants::kExpressionsOffset + kPointerSize;
+  Address base = fp() + offset;
+  Address limit = sp();
+  ASSERT(base >= limit);  // stack grows downwards
+  // Include register-allocated locals in number of expressions.
+  return (base - limit) / kPointerSize;
+}
+
+
+void StandardFrame::ComputeCallerState(State* state) const {
+  state->sp = caller_sp();
+  state->fp = caller_fp();
+  state->pc_address = reinterpret_cast<Address*>(ComputePCAddress(fp()));
+}
+
+
+bool StandardFrame::IsExpressionInsideHandler(int n) const {
+  Address address = GetExpressionAddress(n);
+  for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) {
+    if (it.handler()->includes(address)) return true;
+  }
+  return false;
+}
+
+
+Object* JavaScriptFrame::GetParameter(int index) const {
+  ASSERT(index >= 0 && index < ComputeParametersCount());
+  const int offset = JavaScriptFrameConstants::kParam0Offset;
+  return Memory::Object_at(caller_sp() + offset - (index * kPointerSize));
+}
+
+
+int JavaScriptFrame::ComputeParametersCount() const {
+  Address base  = caller_sp() + JavaScriptFrameConstants::kReceiverOffset;
+  Address limit = fp() + JavaScriptFrameConstants::kSavedRegistersOffset;
+  return (base - limit) / kPointerSize;
+}
+
+
+bool JavaScriptFrame::IsConstructor() const {
+  Address fp = caller_fp();
+  if (has_adapted_arguments()) {
+    // Skip the arguments adaptor frame and look at the real caller.
+    fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset);
+  }
+  return IsConstructFrame(fp);
+}
+
+
+Code* JavaScriptFrame::code() const {
+  JSFunction* function = JSFunction::cast(this->function());
+  return function->shared()->code();
+}
+
+
+Code* ArgumentsAdaptorFrame::code() const {
+  return Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline);
+}
+
+
+Code* InternalFrame::code() const {
+  const int offset = InternalFrameConstants::kCodeOffset;
+  Object* code = Memory::Object_at(fp() + offset);
+  ASSERT(code != NULL);
+  return Code::cast(code);
+}
+
+
+void StackFrame::PrintIndex(StringStream* accumulator,
+                            PrintMode mode,
+                            int index) {
+  accumulator->Add((mode == OVERVIEW) ? "%5d: " : "[%d]: ", index);
+}
+
+
+void JavaScriptFrame::Print(StringStream* accumulator,
+                            PrintMode mode,
+                            int index) const {
+  HandleScope scope;
+  Object* receiver = this->receiver();
+  Object* function = this->function();
+
+  accumulator->PrintSecurityTokenIfChanged(function);
+  PrintIndex(accumulator, mode, index);
+  Code* code = NULL;
+  if (IsConstructor()) accumulator->Add("new ");
+  accumulator->PrintFunction(function, receiver, &code);
+  accumulator->Add("(this=%o", receiver);
+
+  // Get scope information for nicer output, if possible. If code is
+  // NULL, or doesn't contain scope info, info will return 0 for the
+  // number of parameters, stack slots, or context slots.
+  ScopeInfo<PreallocatedStorage> info(code);
+
+  // Print the parameters.
+  int parameters_count = ComputeParametersCount();
+  for (int i = 0; i < parameters_count; i++) {
+    accumulator->Add(",");
+    // If we have a name for the parameter we print it. Nameless
+    // parameters are either because we have more actual parameters
+    // than formal parameters or because we have no scope information.
+    if (i < info.number_of_parameters()) {
+      accumulator->PrintName(*info.parameter_name(i));
+      accumulator->Add("=");
+    }
+    accumulator->Add("%o", GetParameter(i));
+  }
+
+  accumulator->Add(")");
+  if (mode == OVERVIEW) {
+    accumulator->Add("\n");
+    return;
+  }
+  accumulator->Add(" {\n");
+
+  // Compute the number of locals and expression stack elements.
+  int stack_locals_count = info.number_of_stack_slots();
+  int heap_locals_count = info.number_of_context_slots();
+  int expressions_count = ComputeExpressionsCount();
+
+  // Print stack-allocated local variables.
+  if (stack_locals_count > 0) {
+    accumulator->Add("  // stack-allocated locals\n");
+  }
+  for (int i = 0; i < stack_locals_count; i++) {
+    accumulator->Add("  var ");
+    accumulator->PrintName(*info.stack_slot_name(i));
+    accumulator->Add(" = ");
+    if (i < expressions_count) {
+      accumulator->Add("%o", GetExpression(i));
+    } else {
+      accumulator->Add("// no expression found - inconsistent frame?");
+    }
+    accumulator->Add("\n");
+  }
+
+  // Try to get hold of the context of this frame.
+  Context* context = NULL;
+  if (this->context() != NULL && this->context()->IsContext()) {
+    context = Context::cast(this->context());
+  }
+
+  // Print heap-allocated local variables.
+  if (heap_locals_count > Context::MIN_CONTEXT_SLOTS) {
+    accumulator->Add("  // heap-allocated locals\n");
+  }
+  for (int i = Context::MIN_CONTEXT_SLOTS; i < heap_locals_count; i++) {
+    accumulator->Add("  var ");
+    accumulator->PrintName(*info.context_slot_name(i));
+    accumulator->Add(" = ");
+    if (context != NULL) {
+      if (i < context->length()) {
+        accumulator->Add("%o", context->get(i));
+      } else {
+        accumulator->Add(
+            "// warning: missing context slot - inconsistent frame?");
+      }
+    } else {
+      accumulator->Add("// warning: no context found - inconsistent frame?");
+    }
+    accumulator->Add("\n");
+  }
+
+  // Print the expression stack.
+  int expressions_start = stack_locals_count;
+  if (expressions_start < expressions_count) {
+    accumulator->Add("  // expression stack (top to bottom)\n");
+  }
+  for (int i = expressions_count - 1; i >= expressions_start; i--) {
+    if (IsExpressionInsideHandler(i)) continue;
+    accumulator->Add("  [%02d] : %o\n", i, GetExpression(i));
+  }
+
+  // Print details about the function.
+  if (FLAG_max_stack_trace_source_length != 0 && code != NULL) {
+    SharedFunctionInfo* shared = JSFunction::cast(function)->shared();
+    accumulator->Add("--------- s o u r c e   c o d e ---------\n");
+    shared->SourceCodePrint(accumulator, FLAG_max_stack_trace_source_length);
+    accumulator->Add("\n-----------------------------------------\n");
+  }
+
+  accumulator->Add("}\n\n");
+}
+
+
+void ArgumentsAdaptorFrame::Print(StringStream* accumulator,
+                                  PrintMode mode,
+                                  int index) const {
+  int actual = ComputeParametersCount();
+  int expected = -1;
+  Object* function = this->function();
+  if (function->IsJSFunction()) {
+    expected = JSFunction::cast(function)->shared()->formal_parameter_count();
+  }
+
+  PrintIndex(accumulator, mode, index);
+  accumulator->Add("arguments adaptor frame: %d->%d", actual, expected);
+  if (mode == OVERVIEW) {
+    accumulator->Add("\n");
+    return;
+  }
+  accumulator->Add(" {\n");
+
+  // Print actual arguments.
+  if (actual > 0) accumulator->Add("  // actual arguments\n");
+  for (int i = 0; i < actual; i++) {
+    accumulator->Add("  [%02d] : %o", i, GetParameter(i));
+    if (expected != -1 && i >= expected) {
+      accumulator->Add("  // not passed to callee");
+    }
+    accumulator->Add("\n");
+  }
+
+  accumulator->Add("}\n\n");
+}
+
+
+void EntryFrame::Iterate(ObjectVisitor* v) const {
+  StackHandlerIterator it(this, top_handler());
+  ASSERT(!it.done());
+  StackHandler* handler = it.handler();
+  ASSERT(handler->is_entry());
+  handler->Iterate(v);
+  // Make sure that there's the entry frame does not contain more than
+  // one stack handler.
+#ifdef DEBUG
+  it.Advance();
+  ASSERT(it.done());
+#endif
+}
+
+
+void StandardFrame::IterateExpressions(ObjectVisitor* v) const {
+  const int offset = StandardFrameConstants::kContextOffset;
+  Object** base = &Memory::Object_at(sp());
+  Object** limit = &Memory::Object_at(fp() + offset) + 1;
+  for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) {
+    StackHandler* handler = it.handler();
+    // Traverse pointers down to - but not including - the next
+    // handler in the handler chain. Update the base to skip the
+    // handler and allow the handler to traverse its own pointers.
+    const Address address = handler->address();
+    v->VisitPointers(base, reinterpret_cast<Object**>(address));
+    base = reinterpret_cast<Object**>(address + StackHandlerConstants::kSize);
+    // Traverse the pointers in the handler itself.
+    handler->Iterate(v);
+  }
+  v->VisitPointers(base, limit);
+}
+
+
+void JavaScriptFrame::Iterate(ObjectVisitor* v) const {
+  IterateExpressions(v);
+
+  // Traverse callee-saved registers, receiver, and parameters.
+  const int kBaseOffset = JavaScriptFrameConstants::kSavedRegistersOffset;
+  const int kLimitOffset = JavaScriptFrameConstants::kReceiverOffset;
+  Object** base = &Memory::Object_at(fp() + kBaseOffset);
+  Object** limit = &Memory::Object_at(caller_sp() + kLimitOffset) + 1;
+  v->VisitPointers(base, limit);
+}
+
+
+void InternalFrame::Iterate(ObjectVisitor* v) const {
+  // Internal frames only have object pointers on the expression stack
+  // as they never have any arguments.
+  IterateExpressions(v);
+}
+
+
+// -------------------------------------------------------------------------
+
+
+JavaScriptFrame* StackFrameLocator::FindJavaScriptFrame(int n) {
+  ASSERT(n >= 0);
+  for (int i = 0; i <= n; i++) {
+    while (!iterator_.frame()->is_java_script()) iterator_.Advance();
+    if (i == n) return JavaScriptFrame::cast(iterator_.frame());
+    iterator_.Advance();
+  }
+  UNREACHABLE();
+  return NULL;
+}
+
+
+// -------------------------------------------------------------------------
+
+
+int NumRegs(RegList reglist) {
+  int n = 0;
+  while (reglist != 0) {
+    n++;
+    reglist &= reglist - 1;  // clear one bit
+  }
+  return n;
+}
+
+
+int JSCallerSavedCode(int n) {
+  static int reg_code[kNumJSCallerSaved];
+  static bool initialized = false;
+  if (!initialized) {
+    initialized = true;
+    int i = 0;
+    for (int r = 0; r < kNumRegs; r++)
+      if ((kJSCallerSaved & (1 << r)) != 0)
+        reg_code[i++] = r;
+
+    ASSERT(i == kNumJSCallerSaved);
+  }
+  ASSERT(0 <= n && n < kNumJSCallerSaved);
+  return reg_code[n];
+}
+
+
+} }  // namespace v8::internal