Simplify isolates access during stack iteration (WAS: Move SafeStackFrameIterator...
authormikhail.naganov@gmail.com <mikhail.naganov@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 5 Apr 2011 09:01:47 +0000 (09:01 +0000)
committermikhail.naganov@gmail.com <mikhail.naganov@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 5 Apr 2011 09:01:47 +0000 (09:01 +0000)
While trying to fix Mac and Windows versions for this change:
http://codereview.chromium.org/6771047/, I figured out, that we
already store an isolate in StackFrameIterator, so we can use it in
frame objects, instead of requiring it from caller.

I've changed iterators usage to the following scheme: whenever a
caller maintains an isolate pointer, it just passes it to stack
iterator, and no more worries about passing it to frame content
accessors.  If a caller uses current isolate, it can omit passing it
to iterator, in this case, an iterator will use the current isolate,
too.

There was a special case with LiveEdit, which creates
detached copies of frame objects.

R=vitalyr@chromium.org
BUG=none
TEST=none

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

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

18 files changed:
src/accessors.cc
src/compiler.cc
src/cpu-profiler.cc
src/debug.cc
src/debug.h
src/execution.cc
src/frames-inl.h
src/frames.cc
src/frames.h
src/isolate.h
src/liveedit.cc
src/log.cc
src/mark-compact.cc
src/runtime-profiler.cc
src/runtime.cc
src/top.cc
src/v8threads.h
test/cctest/test-accessors.cc

index ee7636e..5f9bf74 100644 (file)
@@ -603,7 +603,7 @@ MaybeObject* Accessors::FunctionGetArguments(Object* object, void*) {
 
   // Find the top invocation of the function by traversing frames.
   List<JSFunction*> functions(2);
-  for (JavaScriptFrameIterator it; !it.done(); it.Advance()) {
+  for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) {
     JavaScriptFrame* frame = it.frame();
     frame->GetFunctions(&functions);
     for (int i = functions.length() - 1; i >= 0; i--) {
@@ -692,7 +692,7 @@ MaybeObject* Accessors::FunctionGetCaller(Object* object, void*) {
   Handle<JSFunction> function(holder, isolate);
 
   List<JSFunction*> functions(2);
-  for (JavaScriptFrameIterator it; !it.done(); it.Advance()) {
+  for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) {
     JavaScriptFrame* frame = it.frame();
     frame->GetFunctions(&functions);
     for (int i = functions.length() - 1; i >= 0; i--) {
index dea94fa..4d90c97 100755 (executable)
@@ -367,11 +367,11 @@ static Handle<SharedFunctionInfo> MakeFunctionInfo(CompilationInfo* info) {
     // For eval scripts add information on the function from which eval was
     // called.
     if (info->is_eval()) {
-      StackTraceFrameIterator it;
+      StackTraceFrameIterator it(isolate);
       if (!it.done()) {
         script->set_eval_from_shared(
             JSFunction::cast(it.frame()->function())->shared());
-        Code* code = it.frame()->LookupCode(isolate);
+        Code* code = it.frame()->LookupCode();
         int offset = static_cast<int>(
             it.frame()->pc() - code->instruction_start());
         script->set_eval_from_instructions_offset(Smi::FromInt(offset));
index 082e253..3894748 100644 (file)
@@ -184,12 +184,13 @@ void ProfilerEventsProcessor::RegExpCodeCreateEvent(
 void ProfilerEventsProcessor::AddCurrentStack() {
   TickSampleEventRecord record;
   TickSample* sample = &record.sample;
-  sample->state = Isolate::Current()->current_vm_state();
+  Isolate* isolate = Isolate::Current();
+  sample->state = isolate->current_vm_state();
   sample->pc = reinterpret_cast<Address>(sample);  // Not NULL.
   sample->tos = NULL;
   sample->has_external_callback = false;
   sample->frames_count = 0;
-  for (StackTraceFrameIterator it;
+  for (StackTraceFrameIterator it(isolate);
        !it.done() && sample->frames_count < TickSample::kMaxFramesCount;
        it.Advance()) {
     sample->stack[sample->frames_count++] = it.frame()->pc();
index 8edd16e..d6f91d8 100644 (file)
@@ -925,7 +925,7 @@ Object* Debug::Break(Arguments args) {
   thread_local_.frame_drop_mode_ = FRAMES_UNTOUCHED;
 
   // Get the top-most JavaScript frame.
-  JavaScriptFrameIterator it;
+  JavaScriptFrameIterator it(isolate_);
   JavaScriptFrame* frame = it.frame();
 
   // Just continue if breaks are disabled or debugger cannot be loaded.
@@ -1224,7 +1224,7 @@ void Debug::FloodHandlerWithOneShot() {
     // If there is no JavaScript stack don't do anything.
     return;
   }
-  for (JavaScriptFrameIterator it(id); !it.done(); it.Advance()) {
+  for (JavaScriptFrameIterator it(isolate_, id); !it.done(); it.Advance()) {
     JavaScriptFrame* frame = it.frame();
     if (frame->HasHandler()) {
       Handle<SharedFunctionInfo> shared =
@@ -1280,7 +1280,7 @@ void Debug::PrepareStep(StepAction step_action, int step_count) {
     // If there is no JavaScript stack don't do anything.
     return;
   }
-  JavaScriptFrameIterator frames_it(id);
+  JavaScriptFrameIterator frames_it(isolate_, id);
   JavaScriptFrame* frame = frames_it.frame();
 
   // First of all ensure there is one-shot break points in the top handler
@@ -1777,7 +1777,7 @@ void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) {
   Handle<Code> original_code(debug_info->original_code());
 #ifdef DEBUG
   // Get the code which is actually executing.
-  Handle<Code> frame_code(frame->LookupCode(isolate_));
+  Handle<Code> frame_code(frame->LookupCode());
   ASSERT(frame_code.is_identical_to(code));
 #endif
 
@@ -1859,7 +1859,7 @@ bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) {
   Handle<Code> code(debug_info->code());
 #ifdef DEBUG
   // Get the code which is actually executing.
-  Handle<Code> frame_code(frame->LookupCode(Isolate::Current()));
+  Handle<Code> frame_code(frame->LookupCode());
   ASSERT(frame_code.is_identical_to(code));
 #endif
 
index fb60cc4..9366fc3 100644 (file)
@@ -863,6 +863,7 @@ class EnterDebugger BASE_EMBEDDED {
   EnterDebugger()
       : isolate_(Isolate::Current()),
         prev_(isolate_->debug()->debugger_entry()),
+        it_(isolate_),
         has_js_frames_(!it_.done()),
         save_(isolate_) {
     Debug* debug = isolate_->debug();
index ad4466e..e1b3624 100644 (file)
@@ -711,7 +711,7 @@ Object* Execution::DebugBreakHelper() {
   }
 
   {
-    JavaScriptFrameIterator it;
+    JavaScriptFrameIterator it(isolate);
     ASSERT(!it.done());
     Object* fun = it.frame()->function();
     if (fun && fun->IsJSFunction()) {
index e6eaec0..236db05 100644 (file)
@@ -88,6 +88,11 @@ inline Address* StackHandler::pc_address() const {
 }
 
 
+inline StackFrame::StackFrame(StackFrameIterator* iterator)
+    : iterator_(iterator), isolate_(iterator_->isolate()) {
+}
+
+
 inline StackHandler* StackFrame::top_handler() const {
   return iterator_->handler();
 }
@@ -168,6 +173,13 @@ inline Object* JavaScriptFrame::function() const {
 
 
 template<typename Iterator>
+inline JavaScriptFrameIteratorTemp<Iterator>::JavaScriptFrameIteratorTemp(
+    Isolate* isolate)
+    : iterator_(isolate) {
+  if (!done()) Advance();
+}
+
+template<typename Iterator>
 inline JavaScriptFrame* JavaScriptFrameIteratorTemp<Iterator>::frame() const {
   // TODO(1233797): The frame hierarchy needs to change. It's
   // problematic that we can't use the safe-cast operator to cast to
@@ -181,11 +193,9 @@ inline JavaScriptFrame* JavaScriptFrameIteratorTemp<Iterator>::frame() const {
 
 template<typename Iterator>
 JavaScriptFrameIteratorTemp<Iterator>::JavaScriptFrameIteratorTemp(
-    StackFrame::Id id) {
-  while (!done()) {
-    Advance();
-    if (frame()->id() == id) return;
-  }
+    Isolate* isolate, StackFrame::Id id)
+    : iterator_(isolate) {
+  AdvanceToId(id);
 }
 
 
@@ -206,6 +216,15 @@ void JavaScriptFrameIteratorTemp<Iterator>::AdvanceToArgumentsFrame() {
 
 
 template<typename Iterator>
+void JavaScriptFrameIteratorTemp<Iterator>::AdvanceToId(StackFrame::Id id) {
+  while (!done()) {
+    Advance();
+    if (frame()->id() == id) return;
+  }
+}
+
+
+template<typename Iterator>
 void JavaScriptFrameIteratorTemp<Iterator>::Reset() {
   iterator_.Reset();
   if (!done()) Advance();
index 8acc1e6..1672b1d 100644 (file)
@@ -39,9 +39,6 @@
 namespace v8 {
 namespace internal {
 
-
-int SafeStackFrameIterator::active_count_ = 0;
-
 // Iterator that supports traversing the stack handlers of a
 // particular frame. Needs to know the top of the handler chain.
 class StackHandlerIterator BASE_EMBEDDED {
@@ -73,23 +70,34 @@ class StackHandlerIterator BASE_EMBEDDED {
 
 #define INITIALIZE_SINGLETON(type, field) field##_(this),
 StackFrameIterator::StackFrameIterator()
-    : STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
+    : isolate_(Isolate::Current()),
+      STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
       frame_(NULL), handler_(NULL),
-      thread_(Isolate::Current()->thread_local_top()),
+      thread_(isolate_->thread_local_top()),
       fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler) {
   Reset();
 }
-StackFrameIterator::StackFrameIterator(ThreadLocalTop* t)
-    : STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
+StackFrameIterator::StackFrameIterator(Isolate* isolate)
+    : isolate_(isolate),
+      STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
+      frame_(NULL), handler_(NULL),
+      thread_(isolate_->thread_local_top()),
+      fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler) {
+  Reset();
+}
+StackFrameIterator::StackFrameIterator(Isolate* isolate, ThreadLocalTop* t)
+    : isolate_(isolate),
+      STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
       frame_(NULL), handler_(NULL), thread_(t),
       fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler) {
   Reset();
 }
 StackFrameIterator::StackFrameIterator(Isolate* isolate,
                                        bool use_top, Address fp, Address sp)
-    : STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
+    : isolate_(isolate),
+      STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
       frame_(NULL), handler_(NULL),
-      thread_(use_top ? isolate->thread_local_top() : NULL),
+      thread_(use_top ? isolate_->thread_local_top() : NULL),
       fp_(use_top ? NULL : fp), sp_(sp),
       advance_(use_top ? &StackFrameIterator::AdvanceWithHandler :
                &StackFrameIterator::AdvanceWithoutHandler) {
@@ -147,7 +155,7 @@ void StackFrameIterator::Reset() {
     state.sp = sp_;
     state.pc_address =
         reinterpret_cast<Address*>(StandardFrame::ComputePCAddress(fp_));
-    type = StackFrame::ComputeType(&state);
+    type = StackFrame::ComputeType(isolate(), &state);
   }
   if (SingletonFor(type) == NULL) return;
   frame_ = SingletonFor(type, &state);
@@ -188,6 +196,12 @@ StackTraceFrameIterator::StackTraceFrameIterator() {
 }
 
 
+StackTraceFrameIterator::StackTraceFrameIterator(Isolate* isolate)
+    : JavaScriptFrameIterator(isolate) {
+  if (!done() && !IsValidFrame()) Advance();
+}
+
+
 void StackTraceFrameIterator::Advance() {
   while (true) {
     JavaScriptFrameIterator::Advance();
@@ -221,10 +235,24 @@ bool SafeStackFrameIterator::ExitFrameValidator::IsValidFP(Address fp) {
 }
 
 
+SafeStackFrameIterator::ActiveCountMaintainer::ActiveCountMaintainer(
+    Isolate* isolate)
+    : isolate_(isolate) {
+  isolate_->set_safe_stack_iterator_counter(
+      isolate_->safe_stack_iterator_counter() + 1);
+}
+
+
+SafeStackFrameIterator::ActiveCountMaintainer::~ActiveCountMaintainer() {
+  isolate_->set_safe_stack_iterator_counter(
+      isolate_->safe_stack_iterator_counter() - 1);
+}
+
+
 SafeStackFrameIterator::SafeStackFrameIterator(
     Isolate* isolate,
     Address fp, Address sp, Address low_bound, Address high_bound) :
-    maintainer_(),
+    maintainer_(isolate),
     stack_validator_(low_bound, high_bound),
     is_valid_top_(IsValidTop(isolate, low_bound, high_bound)),
     is_valid_fp_(IsWithinBounds(low_bound, high_bound, fp)),
@@ -233,6 +261,10 @@ SafeStackFrameIterator::SafeStackFrameIterator(
     iterator_(isolate, is_valid_top_, is_valid_fp_ ? fp : NULL, sp) {
 }
 
+bool SafeStackFrameIterator::is_active(Isolate* isolate) {
+  return isolate->safe_stack_iterator_counter() > 0;
+}
+
 
 bool SafeStackFrameIterator::IsValidTop(Isolate* isolate,
                                         Address low_bound, Address high_bound) {
@@ -333,10 +365,10 @@ void SafeStackTraceFrameIterator::Advance() {
 #endif
 
 
-Code* StackFrame::GetSafepointData(Address pc,
+Code* StackFrame::GetSafepointData(Isolate* isolate,
+                                   Address pc,
                                    SafepointEntry* safepoint_entry,
                                    unsigned* stack_slots) {
-  Isolate* isolate = Isolate::Current();
   PcToCodeCache::PcToCodeCacheEntry* entry =
       isolate->pc_to_code_cache()->GetCacheEntry(pc);
   SafepointEntry cached_safepoint_entry = entry->safepoint_entry;
@@ -377,7 +409,7 @@ void StackFrame::IteratePc(ObjectVisitor* v,
 }
 
 
-StackFrame::Type StackFrame::ComputeType(State* state) {
+StackFrame::Type StackFrame::ComputeType(Isolate* isolate, State* state) {
   ASSERT(state->fp != NULL);
   if (StandardFrame::IsArgumentsAdaptorFrame(state->fp)) {
     return ARGUMENTS_ADAPTOR;
@@ -392,9 +424,8 @@ StackFrame::Type StackFrame::ComputeType(State* state) {
     // frames as normal JavaScript frames to avoid having to look
     // into the heap to determine the state. This is safe as long
     // as nobody tries to GC...
-    if (SafeStackFrameIterator::is_active()) return JAVA_SCRIPT;
-    Code::Kind kind = GetContainingCode(Isolate::Current(),
-                                        *(state->pc_address))->kind();
+    if (SafeStackFrameIterator::is_active(isolate)) return JAVA_SCRIPT;
+    Code::Kind kind = GetContainingCode(isolate, *(state->pc_address))->kind();
     ASSERT(kind == Code::FUNCTION || kind == Code::OPTIMIZED_FUNCTION);
     return (kind == Code::OPTIMIZED_FUNCTION) ? OPTIMIZED : JAVA_SCRIPT;
   }
@@ -405,7 +436,7 @@ StackFrame::Type StackFrame::ComputeType(State* state) {
 
 StackFrame::Type StackFrame::GetCallerState(State* state) const {
   ComputeCallerState(state);
-  return ComputeType(state);
+  return ComputeType(isolate(), state);
 }
 
 
@@ -465,7 +496,7 @@ void ExitFrame::SetCallerFp(Address caller_fp) {
 void ExitFrame::Iterate(ObjectVisitor* v) const {
   // The arguments are traversed as part of the expression stack of
   // the calling frame.
-  IteratePc(v, pc_address(), LookupCode(Isolate::Current()));
+  IteratePc(v, pc_address(), LookupCode());
   v->VisitPointer(&code_slot());
 }
 
@@ -539,13 +570,13 @@ void OptimizedFrame::Iterate(ObjectVisitor* v) const {
 
   // Make sure that we're not doing "safe" stack frame iteration. We cannot
   // possibly find pointers in optimized frames in that state.
-  ASSERT(!SafeStackFrameIterator::is_active());
+  ASSERT(!SafeStackFrameIterator::is_active(isolate()));
 
   // Compute the safepoint information.
   unsigned stack_slots = 0;
   SafepointEntry safepoint_entry;
   Code* code = StackFrame::GetSafepointData(
-      pc(), &safepoint_entry, &stack_slots);
+      isolate(), pc(), &safepoint_entry, &stack_slots);
   unsigned slot_space = stack_slots * kPointerSize;
 
   // Visit the outgoing parameters. This is usually dealt with by the
@@ -640,8 +671,8 @@ Code* JavaScriptFrame::unchecked_code() const {
 
 Address JavaScriptFrame::GetCallerStackPointer() const {
   int arguments;
-  if (SafeStackFrameIterator::is_active() ||
-      HEAP->gc_state() != Heap::NOT_IN_GC) {
+  if (SafeStackFrameIterator::is_active(isolate()) ||
+      isolate()->heap()->gc_state() != Heap::NOT_IN_GC) {
     // If the we are currently iterating the safe stack the
     // arguments for frames are traversed as if they were
     // expression stack elements of the calling frame. The reason for
@@ -670,7 +701,7 @@ void JavaScriptFrame::GetFunctions(List<JSFunction*>* functions) {
 
 void JavaScriptFrame::Summarize(List<FrameSummary>* functions) {
   ASSERT(functions->length() == 0);
-  Code* code_pointer = LookupCode(Isolate::Current());
+  Code* code_pointer = LookupCode();
   int offset = static_cast<int>(pc() - code_pointer->address());
   FrameSummary summary(receiver(),
                        JSFunction::cast(function()),
@@ -789,7 +820,7 @@ DeoptimizationInputData* OptimizedFrame::GetDeoptimizationData(
   // back to a slow search in this case to find the original optimized
   // code object.
   if (!code->contains(pc())) {
-    code = Isolate::Current()->pc_to_code_cache()->GcSafeFindCodeForPc(pc());
+    code = isolate()->pc_to_code_cache()->GcSafeFindCodeForPc(pc());
   }
   ASSERT(code != NULL);
   ASSERT(code->kind() == Code::OPTIMIZED_FUNCTION);
@@ -850,7 +881,7 @@ Address InternalFrame::GetCallerStackPointer() const {
 
 
 Code* ArgumentsAdaptorFrame::unchecked_code() const {
-  return Isolate::Current()->builtins()->builtin(
+  return isolate()->builtins()->builtin(
       Builtins::kArgumentsAdaptorTrampoline);
 }
 
@@ -1045,14 +1076,14 @@ void EntryFrame::Iterate(ObjectVisitor* v) const {
   ASSERT(!it.done());
   StackHandler* handler = it.handler();
   ASSERT(handler->is_entry());
-  handler->Iterate(v, LookupCode(Isolate::Current()));
+  handler->Iterate(v, LookupCode());
 #ifdef DEBUG
   // Make sure that the entry frame does not contain more than one
   // stack handler.
   it.Advance();
   ASSERT(it.done());
 #endif
-  IteratePc(v, pc_address(), LookupCode(Isolate::Current()));
+  IteratePc(v, pc_address(), LookupCode());
 }
 
 
@@ -1069,7 +1100,7 @@ void StandardFrame::IterateExpressions(ObjectVisitor* v) const {
     v->VisitPointers(base, reinterpret_cast<Object**>(address));
     base = reinterpret_cast<Object**>(address + StackHandlerConstants::kSize);
     // Traverse the pointers in the handler itself.
-    handler->Iterate(v, LookupCode(Isolate::Current()));
+    handler->Iterate(v, LookupCode());
   }
   v->VisitPointers(base, limit);
 }
@@ -1077,7 +1108,7 @@ void StandardFrame::IterateExpressions(ObjectVisitor* v) const {
 
 void JavaScriptFrame::Iterate(ObjectVisitor* v) const {
   IterateExpressions(v);
-  IteratePc(v, pc_address(), LookupCode(Isolate::Current()));
+  IteratePc(v, pc_address(), LookupCode());
   IterateArguments(v);
 }
 
@@ -1096,7 +1127,7 @@ void InternalFrame::Iterate(ObjectVisitor* v) const {
   // Internal frames only have object pointers on the expression stack
   // as they never have any arguments.
   IterateExpressions(v);
-  IteratePc(v, pc_address(), LookupCode(Isolate::Current()));
+  IteratePc(v, pc_address(), LookupCode());
 }
 
 
index 3294eee..d6307f0 100644 (file)
@@ -158,10 +158,12 @@ class StackFrame BASE_EMBEDDED {
     Address* pc_address;
   };
 
-  // Copy constructor; it breaks the connection to host iterator.
+  // Copy constructor; it breaks the connection to host iterator
+  // (as an iterator usually lives on stack).
   StackFrame(const StackFrame& original) {
     this->state_ = original.state_;
     this->iterator_ = NULL;
+    this->isolate_ = original.isolate_;
   }
 
   // Type testers.
@@ -205,8 +207,8 @@ class StackFrame BASE_EMBEDDED {
   virtual Code* unchecked_code() const = 0;
 
   // Get the code associated with this frame.
-  Code* LookupCode(Isolate* isolate) const {
-    return GetContainingCode(isolate, pc());
+  Code* LookupCode() const {
+    return GetContainingCode(isolate(), pc());
   }
 
   // Get the code object that contains the given pc.
@@ -215,7 +217,8 @@ class StackFrame BASE_EMBEDDED {
   // Get the code object containing the given pc and fill in the
   // safepoint entry and the number of stack slots. The pc must be at
   // a safepoint.
-  static Code* GetSafepointData(Address pc,
+  static Code* GetSafepointData(Isolate* isolate,
+                                Address pc,
                                 SafepointEntry* safepoint_entry,
                                 unsigned* stack_slots);
 
@@ -230,9 +233,11 @@ class StackFrame BASE_EMBEDDED {
                      int index) const { }
 
  protected:
-  explicit StackFrame(StackFrameIterator* iterator) : iterator_(iterator) { }
+  inline explicit StackFrame(StackFrameIterator* iterator);
   virtual ~StackFrame() { }
 
+  Isolate* isolate() const { return isolate_; }
+
   // Compute the stack pointer for the calling frame.
   virtual Address GetCallerStackPointer() const = 0;
 
@@ -245,10 +250,11 @@ class StackFrame BASE_EMBEDDED {
   inline StackHandler* top_handler() const;
 
   // Compute the stack frame type for the given state.
-  static Type ComputeType(State* state);
+  static Type ComputeType(Isolate* isolate, State* state);
 
  private:
   const StackFrameIterator* iterator_;
+  Isolate* isolate_;
   State state_;
 
   // Fill in the state of the calling frame.
@@ -257,6 +263,8 @@ class StackFrame BASE_EMBEDDED {
   // Get the type and the state of the calling frame.
   virtual Type GetCallerState(State* state) const;
 
+  static const intptr_t kIsolateTag = 1;
+
   friend class StackFrameIterator;
   friend class StackHandlerIterator;
   friend class SafeStackFrameIterator;
@@ -609,11 +617,15 @@ class ConstructFrame: public InternalFrame {
 
 class StackFrameIterator BASE_EMBEDDED {
  public:
-  // An iterator that iterates over the current thread's stack.
+  // An iterator that iterates over the current thread's stack,
+  // and uses current isolate.
   StackFrameIterator();
 
+  // An iterator that iterates over the isolate's current thread's stack,
+  explicit StackFrameIterator(Isolate* isolate);
+
   // An iterator that iterates over a given thread's stack.
-  explicit StackFrameIterator(ThreadLocalTop* thread);
+  StackFrameIterator(Isolate* isolate, ThreadLocalTop* t);
 
   // An iterator that can start from a given FP address.
   // If use_top, then work as usual, if fp isn't NULL, use it,
@@ -625,6 +637,8 @@ class StackFrameIterator BASE_EMBEDDED {
     return frame_;
   }
 
+  Isolate* isolate() const { return isolate_; }
+
   bool done() const { return frame_ == NULL; }
   void Advance() { (this->*advance_)(); }
 
@@ -632,6 +646,7 @@ class StackFrameIterator BASE_EMBEDDED {
   void Reset();
 
  private:
+  Isolate* isolate_;
 #define DECLARE_SINGLETON(ignore, type) type type##_;
   STACK_FRAME_TYPE_LIST(DECLARE_SINGLETON)
 #undef DECLARE_SINGLETON
@@ -667,13 +682,12 @@ class JavaScriptFrameIteratorTemp BASE_EMBEDDED {
  public:
   JavaScriptFrameIteratorTemp() { if (!done()) Advance(); }
 
-  explicit JavaScriptFrameIteratorTemp(ThreadLocalTop* thread) :
-      iterator_(thread) {
-    if (!done()) Advance();
-  }
+  inline explicit JavaScriptFrameIteratorTemp(Isolate* isolate);
 
   // Skip frames until the frame with the given id is reached.
-  explicit JavaScriptFrameIteratorTemp(StackFrame::Id id);
+  explicit JavaScriptFrameIteratorTemp(StackFrame::Id id) { AdvanceToId(id); }
+
+  inline JavaScriptFrameIteratorTemp(Isolate* isolate, StackFrame::Id id);
 
   JavaScriptFrameIteratorTemp(Address fp, Address sp,
                               Address low_bound, Address high_bound) :
@@ -702,6 +716,8 @@ class JavaScriptFrameIteratorTemp BASE_EMBEDDED {
   void Reset();
 
  private:
+  inline void AdvanceToId(StackFrame::Id id);
+
   Iterator iterator_;
 };
 
@@ -716,6 +732,7 @@ typedef JavaScriptFrameIteratorTemp<StackFrameIterator> JavaScriptFrameIterator;
 class StackTraceFrameIterator: public JavaScriptFrameIterator {
  public:
   StackTraceFrameIterator();
+  explicit StackTraceFrameIterator(Isolate* isolate);
   void Advance();
 
  private:
@@ -739,7 +756,7 @@ class SafeStackFrameIterator BASE_EMBEDDED {
   void Advance();
   void Reset();
 
-  static bool is_active() { return active_count_ > 0; }
+  static bool is_active(Isolate* isolate);
 
   static bool IsWithinBounds(
       Address low_bound, Address high_bound, Address addr) {
@@ -786,13 +803,13 @@ class SafeStackFrameIterator BASE_EMBEDDED {
   // heap objects.
   class ActiveCountMaintainer BASE_EMBEDDED {
    public:
-    ActiveCountMaintainer() { active_count_++; }
-    ~ActiveCountMaintainer() { active_count_--; }
+    explicit ActiveCountMaintainer(Isolate* isolate);
+    ~ActiveCountMaintainer();
+   private:
+    Isolate* isolate_;
   };
 
   ActiveCountMaintainer maintainer_;
-  // TODO(isolates): this is dangerous.
-  static int active_count_;
   StackAddressValidator stack_validator_;
   const bool is_valid_top_;
   const bool is_valid_fp_;
index a9962c3..638658b 100644 (file)
@@ -316,6 +316,8 @@ typedef List<HeapObject*, PreallocatedStorage> DebugObjectCache;
   /* AstNode state. */                                                         \
   V(unsigned, ast_node_id, 0)                                                  \
   V(unsigned, ast_node_count, 0)                                               \
+  /* SafeStackFrameIterator activations count. */                              \
+  V(int, safe_stack_iterator_counter, 0)                                       \
   ISOLATE_PLATFORM_INIT_LIST(V)                                                \
   ISOLATE_LOGGING_INIT_LIST(V)                                                 \
   ISOLATE_DEBUGGER_INIT_LIST(V)
@@ -1142,7 +1144,7 @@ class SaveContext BASE_EMBEDDED {
     isolate->set_save_context(this);
 
     // If there is no JS frame under the current C frame, use the value 0.
-    JavaScriptFrameIterator it;
+    JavaScriptFrameIterator it(isolate);
     js_sp_ = it.done() ? 0 : it.frame()->sp();
   }
 
index dc50357..1466766 100644 (file)
@@ -1396,17 +1396,18 @@ static const char* DropFrames(Vector<StackFrame*> frames,
   ASSERT(bottom_js_frame->is_java_script());
 
   // Check the nature of the top frame.
-  Code* pre_top_frame_code = pre_top_frame->LookupCode(Isolate::Current());
+  Isolate* isolate = Isolate::Current();
+  Code* pre_top_frame_code = pre_top_frame->LookupCode();
   if (pre_top_frame_code->is_inline_cache_stub() &&
       pre_top_frame_code->ic_state() == DEBUG_BREAK) {
     // OK, we can drop inline cache calls.
     *mode = Debug::FRAME_DROPPED_IN_IC_CALL;
   } else if (pre_top_frame_code ==
-             Isolate::Current()->debug()->debug_break_slot()) {
+             isolate->debug()->debug_break_slot()) {
     // OK, we can drop debug break slot.
     *mode = Debug::FRAME_DROPPED_IN_DEBUG_SLOT_CALL;
   } else if (pre_top_frame_code ==
-      Isolate::Current()->builtins()->builtin(
+      isolate->builtins()->builtin(
           Builtins::kFrameDropper_LiveEdit)) {
     // OK, we can drop our own code.
     *mode = Debug::FRAME_DROPPED_IN_DIRECT_CALL;
@@ -1570,8 +1571,8 @@ class InactiveThreadActivationsChecker : public ThreadVisitor {
       : shared_info_array_(shared_info_array), result_(result),
         has_blocked_functions_(false) {
   }
-  void VisitThread(ThreadLocalTop* top) {
-    for (StackFrameIterator it(top); !it.done(); it.Advance()) {
+  void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
+    for (StackFrameIterator it(isolate, top); !it.done(); it.Advance()) {
       has_blocked_functions_ |= CheckActivation(
           shared_info_array_, result_, it.frame(),
           LiveEdit::FUNCTION_BLOCKED_ON_OTHER_STACK);
index 3ca00a6..5e8c738 100644 (file)
@@ -191,7 +191,7 @@ void StackTracer::Trace(Isolate* isolate, TickSample* sample) {
 //
 class Ticker: public Sampler {
  public:
-  explicit Ticker(Isolate* isolate, int interval):
+  Ticker(Isolate* isolate, int interval):
       Sampler(isolate, interval),
       window_(NULL),
       profiler_(NULL) {}
index 3770bc3..73bf2f2 100644 (file)
@@ -890,8 +890,8 @@ class CodeMarkingVisitor : public ThreadVisitor {
   explicit CodeMarkingVisitor(MarkCompactCollector* collector)
       : collector_(collector) {}
 
-  void VisitThread(ThreadLocalTop* top) {
-    for (StackFrameIterator it(top); !it.done(); it.Advance()) {
+  void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
+    for (StackFrameIterator it(isolate, top); !it.done(); it.Advance()) {
       collector_->MarkObject(it.frame()->unchecked_code());
     }
   }
index c6e2b46..28755e3 100644 (file)
@@ -258,7 +258,7 @@ void RuntimeProfiler::OptimizeNow() {
   JSFunction* samples[kSamplerFrameCount];
   int sample_count = 0;
   int frame_count = 0;
-  for (JavaScriptFrameIterator it;
+  for (JavaScriptFrameIterator it(isolate_);
        frame_count++ < kSamplerFrameCount && !it.done();
        it.Advance()) {
     JavaScriptFrame* frame = it.frame();
index ddfdb7f..410a437 100644 (file)
@@ -681,7 +681,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SetHiddenPrototype) {
 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsConstructCall) {
   NoHandleAllocation ha;
   ASSERT(args.length() == 0);
-  JavaScriptFrameIterator it;
+  JavaScriptFrameIterator it(isolate);
   return isolate->heap()->ToBoolean(it.frame()->IsConstructor());
 }
 
@@ -4484,7 +4484,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArgumentsProperty) {
   ASSERT(args.length() == 1);
 
   // Compute the frame holding the arguments.
-  JavaScriptFrameIterator it;
+  JavaScriptFrameIterator it(isolate);
   it.AdvanceToArgumentsFrame();
   JavaScriptFrame* frame = it.frame();
 
@@ -7323,7 +7323,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_NotifyDeoptimized) {
   ASSERT(isolate->heap()->IsAllocationAllowed());
   int frames = deoptimizer->output_count();
 
-  JavaScriptFrameIterator it;
+  JavaScriptFrameIterator it(isolate);
   JavaScriptFrame* frame = NULL;
   for (int i = 0; i < frames; i++) {
     if (i != 0) it.Advance();
@@ -7425,7 +7425,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileForOnStackReplacement) {
     // indirectly recursive and (b) an optimized invocation has been
     // deoptimized so that we are currently in an unoptimized activation.
     // Check for optimized activations of this function.
-    JavaScriptFrameIterator it;
+    JavaScriptFrameIterator it(isolate);
     while (succeeded && !it.done()) {
       JavaScriptFrame* frame = it.frame();
       succeeded = !frame->is_optimized() || frame->function() != *function;
@@ -7437,10 +7437,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileForOnStackReplacement) {
   if (succeeded) {
     // The top JS function is this one, the PC is somewhere in the
     // unoptimized code.
-    JavaScriptFrameIterator it;
+    JavaScriptFrameIterator it(isolate);
     JavaScriptFrame* frame = it.frame();
     ASSERT(frame->function() == *function);
-    ASSERT(frame->LookupCode(isolate) == *unoptimized);
+    ASSERT(frame->LookupCode() == *unoptimized);
     ASSERT(unoptimized->contains(frame->pc()));
 
     // Use linear search of the unoptimized code's stack check table to find
@@ -8001,7 +8001,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrint) {
   if (args[0]->IsString()) {
     // If we have a string, assume it's a code "marker"
     // and print some interesting cpu debugging info.
-    JavaScriptFrameIterator it;
+    JavaScriptFrameIterator it(isolate);
     JavaScriptFrame* frame = it.frame();
     PrintF("fp = %p, sp = %p, caller_sp = %p: ",
            frame->fp(), frame->sp(), frame->caller_sp());
@@ -9337,7 +9337,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameCount) {
     // If there is no JavaScript stack frame count is 0.
     return Smi::FromInt(0);
   }
-  for (JavaScriptFrameIterator it(id); !it.done(); it.Advance()) n++;
+  for (JavaScriptFrameIterator it(isolate, id); !it.done(); it.Advance()) n++;
   return Smi::FromInt(n);
 }
 
@@ -9390,7 +9390,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
     return heap->undefined_value();
   }
   int count = 0;
-  JavaScriptFrameIterator it(id);
+  JavaScriptFrameIterator it(isolate, id);
   for (; !it.done(); it.Advance()) {
     if (count == index) break;
     count++;
@@ -9398,7 +9398,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
   if (it.done()) return heap->undefined_value();
 
   bool is_optimized_frame =
-      it.frame()->LookupCode(isolate)->kind() == Code::OPTIMIZED_FUNCTION;
+      it.frame()->LookupCode()->kind() == Code::OPTIMIZED_FUNCTION;
 
   // Traverse the saved contexts chain to find the active context for the
   // selected frame.
@@ -9413,7 +9413,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
 
   // Find source position.
   int position =
-      it.frame()->LookupCode(isolate)->SourcePosition(it.frame()->pc());
+      it.frame()->LookupCode()->SourcePosition(it.frame()->pc());
 
   // Check for constructor frame.
   bool constructor = it.frame()->IsConstructor();
@@ -9475,7 +9475,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
   // to the frame information.
   Handle<Object> return_value = isolate->factory()->undefined_value();
   if (at_return) {
-    StackFrameIterator it2;
+    StackFrameIterator it2(isolate);
     Address internal_frame_sp = NULL;
     while (!it2.done()) {
       if (it2.frame()->is_internal()) {
@@ -10008,7 +10008,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeCount) {
 
   // Get the frame where the debugging is performed.
   StackFrame::Id id = UnwrapFrameId(wrapped_id);
-  JavaScriptFrameIterator it(id);
+  JavaScriptFrameIterator it(isolate, id);
   JavaScriptFrame* frame = it.frame();
 
   // Count the visible scopes.
@@ -10048,7 +10048,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeDetails) {
 
   // Get the frame where the debugging is performed.
   StackFrame::Id id = UnwrapFrameId(wrapped_id);
-  JavaScriptFrameIterator frame_it(id);
+  JavaScriptFrameIterator frame_it(isolate, id);
   JavaScriptFrame* frame = frame_it.frame();
 
   // Find the requested scope.
@@ -10536,7 +10536,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
 
   // Get the frame where the debugging is performed.
   StackFrame::Id id = UnwrapFrameId(wrapped_id);
-  JavaScriptFrameIterator it(id);
+  JavaScriptFrameIterator it(isolate, id);
   JavaScriptFrame* frame = it.frame();
   Handle<JSFunction> function(JSFunction::cast(frame->function()));
   Handle<SerializedScopeInfo> scope_info(function->shared()->scope_info());
@@ -11604,7 +11604,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CollectStackTrace) {
   Handle<FixedArray> elements =
       factory->NewFixedArrayWithHoles(initial_size * 4);
 
-  StackFrameIterator iter;
+  StackFrameIterator iter(isolate);
   // If the caller parameter is a function we skip frames until we're
   // under it before starting to collect.
   bool seen_caller = !caller->IsJSFunction();
index ff29cad..9932318 100644 (file)
@@ -89,13 +89,13 @@ char* Isolate::Iterate(ObjectVisitor* v, char* thread_storage) {
 
 
 void Isolate::IterateThread(ThreadVisitor* v) {
-  v->VisitThread(thread_local_top());
+  v->VisitThread(this, thread_local_top());
 }
 
 
 void Isolate::IterateThread(ThreadVisitor* v, char* t) {
   ThreadLocalTop* thread = reinterpret_cast<ThreadLocalTop*>(t);
-  v->VisitThread(thread);
+  v->VisitThread(this, thread);
 }
 
 
@@ -125,7 +125,7 @@ void Isolate::Iterate(ObjectVisitor* v, ThreadLocalTop* thread) {
   }
 
   // Iterate over pointers on native execution stack.
-  for (StackFrameIterator it(thread); !it.done(); it.Advance()) {
+  for (StackFrameIterator it(this, thread); !it.done(); it.Advance()) {
     it.frame()->Iterate(v);
   }
 }
@@ -204,7 +204,7 @@ Handle<JSArray> Isolate::CaptureCurrentStackTrace(
   Handle<String> constructor_key =
       factory()->LookupAsciiSymbol("isConstructor");
 
-  StackTraceFrameIterator it;
+  StackTraceFrameIterator it(this);
   int frames_seen = 0;
   while (!it.done() && (frames_seen < limit)) {
     JavaScriptFrame* frame = it.frame();
@@ -584,12 +584,12 @@ Failure* Isolate::PromoteScheduledException() {
 
 
 void Isolate::PrintCurrentStackTrace(FILE* out) {
-  StackTraceFrameIterator it;
+  StackTraceFrameIterator it(this);
   while (!it.done()) {
     HandleScope scope;
     // Find code position if recorded in relocation info.
     JavaScriptFrame* frame = it.frame();
-    int pos = frame->LookupCode(this)->SourcePosition(frame->pc());
+    int pos = frame->LookupCode()->SourcePosition(frame->pc());
     Handle<Object> pos_obj(Smi::FromInt(pos));
     // Fetch function and receiver.
     Handle<JSFunction> fun(JSFunction::cast(frame->function()));
@@ -613,14 +613,14 @@ void Isolate::PrintCurrentStackTrace(FILE* out) {
 
 void Isolate::ComputeLocation(MessageLocation* target) {
   *target = MessageLocation(Handle<Script>(heap_.empty_script()), -1, -1);
-  StackTraceFrameIterator it;
+  StackTraceFrameIterator it(this);
   if (!it.done()) {
     JavaScriptFrame* frame = it.frame();
     JSFunction* fun = JSFunction::cast(frame->function());
     Object* script = fun->shared()->script();
     if (script->IsScript() &&
         !(Script::cast(script)->source()->IsUndefined())) {
-      int pos = frame->LookupCode(this)->SourcePosition(frame->pc());
+      int pos = frame->LookupCode()->SourcePosition(frame->pc());
       // Compute the location from the function and the reloc info.
       Handle<Script> casted_script(Script::cast(script));
       *target = MessageLocation(casted_script, pos, pos + 1);
index f1992ad..1266af7 100644 (file)
@@ -78,7 +78,7 @@ class ThreadLocalTop;
 class ThreadVisitor {
  public:
   // ThreadLocalTop may be only available during this call.
-  virtual void VisitThread(ThreadLocalTop* top) = 0;
+  virtual void VisitThread(Isolate* isolate, ThreadLocalTop* top) = 0;
 
  protected:
   virtual ~ThreadVisitor() {}
index b74f166..028f82f 100644 (file)
@@ -397,7 +397,7 @@ static v8::Handle<Value> StackCheck(Local<String> name,
   for (int i = 0; !iter.done(); i++) {
     i::StackFrame* frame = iter.frame();
     CHECK(i != 0 || (frame->type() == i::StackFrame::EXIT));
-    i::Code* code = frame->LookupCode(i::Isolate::Current());
+    i::Code* code = frame->LookupCode();
     CHECK(code->IsCode());
     i::Address pc = frame->pc();
     CHECK(code->contains(pc));