Revision: 5472
Author: [email protected]
Date: Thu Sep 16 03:01:13 2010
Log: Merge r5467..r5469 into branches/2.3.

A fix for profiler stack iterator (and subsequent build fixes).

BUG=crbug/55565

Review URL: http://codereview.chromium.org/3410012
http://code.google.com/p/v8/source/detail?r=5472

Modified:
 /branches/2.3/src/arm/frames-arm.cc
 /branches/2.3/src/frames.cc
 /branches/2.3/src/frames.h
 /branches/2.3/src/ia32/frames-ia32.cc
 /branches/2.3/src/log.cc
 /branches/2.3/src/mips/frames-mips.cc
 /branches/2.3/src/version.cc
 /branches/2.3/src/x64/frames-x64.cc
 /branches/2.3/test/cctest/test-log-stack-tracer.cc

=======================================
--- /branches/2.3/src/arm/frames-arm.cc Mon Aug 30 23:45:16 2010
+++ /branches/2.3/src/arm/frames-arm.cc Thu Sep 16 03:01:13 2010
@@ -52,17 +52,8 @@
 }


-StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State* state) {
-  if (fp == 0) return NONE;
-  // Compute frame type and stack pointer.
-  Address sp = fp + ExitFrameConstants::kSPOffset;
-
-  // Fill in the state.
-  state->sp = sp;
-  state->fp = fp;
-  state->pc_address = reinterpret_cast<Address*>(sp - 1 * kPointerSize);
-  ASSERT(*state->pc_address != NULL);
-  return EXIT;
+Address ExitFrame::ComputeStackPointer(Address fp) {
+  return fp + ExitFrameConstants::kSPOffset;
 }


=======================================
--- /branches/2.3/src/frames.cc Wed Aug 18 00:45:01 2010
+++ /branches/2.3/src/frames.cc Thu Sep 16 03:01:13 2010
@@ -139,8 +139,8 @@
     state.pc_address =
         reinterpret_cast<Address*>(StandardFrame::ComputePCAddress(fp_));
     type = StackFrame::ComputeType(&state);
-    if (SingletonFor(type) == NULL) return;
-  }
+  }
+  if (SingletonFor(type) == NULL) return;
   frame_ = SingletonFor(type, &state);
 }

@@ -199,18 +199,36 @@
// -------------------------------------------------------------------------


+bool SafeStackFrameIterator::ExitFrameValidator::IsValidFP(Address fp) {
+  if (!validator_.IsValid(fp)) return false;
+  Address sp = ExitFrame::ComputeStackPointer(fp);
+  if (!validator_.IsValid(sp)) return false;
+  StackFrame::State state;
+  ExitFrame::FillState(fp, sp, &state);
+  if (!validator_.IsValid(reinterpret_cast<Address>(state.pc_address))) {
+    return false;
+  }
+  return *state.pc_address != NULL;
+}
+
+
 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),
+    stack_validator_(low_bound, high_bound),
+    is_valid_top_(IsValidTop(low_bound, high_bound)),
     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) {
 }
+
+
+bool SafeStackFrameIterator::IsValidTop(Address low_bound, Address high_bound) {
+  Address fp = Top::c_entry_fp(Top::GetCurrentThread());
+  ExitFrameValidator validator(low_bound, high_bound);
+  if (!validator.IsValidFP(fp)) return false;
+  return Top::handler(Top::GetCurrentThread()) != NULL;
+}


 void SafeStackFrameIterator::Advance() {
@@ -254,9 +272,8 @@
     // sure that caller FP address is valid.
     Address caller_fp = Memory::Address_at(
         frame->fp() + EntryFrameConstants::kCallerFPOffset);
-    if (!IsValidStackAddress(caller_fp)) {
-      return false;
-    }
+    ExitFrameValidator validator(stack_validator_);
+    if (!validator.IsValidFP(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
@@ -428,6 +445,22 @@
 Address ExitFrame::GetCallerStackPointer() const {
   return fp() + ExitFrameConstants::kCallerSPDisplacement;
 }
+
+
+StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State* state) {
+  if (fp == 0) return NONE;
+  Address sp = ComputeStackPointer(fp);
+  FillState(fp, sp, state);
+  ASSERT(*state->pc_address != NULL);
+  return EXIT;
+}
+
+
+void ExitFrame::FillState(Address fp, Address sp, State* state) {
+  state->sp = sp;
+  state->fp = fp;
+  state->pc_address = reinterpret_cast<Address*>(sp - 1 * kPointerSize);
+}


 Address StandardFrame::GetExpressionAddress(int n) const {
=======================================
--- /branches/2.3/src/frames.h  Mon Aug 30 23:45:16 2010
+++ /branches/2.3/src/frames.h  Thu Sep 16 03:01:13 2010
@@ -120,6 +120,13 @@
     NO_ID = 0
   };

+  struct State {
+    State() : sp(NULL), fp(NULL), pc_address(NULL) { }
+    Address sp;
+    Address fp;
+    Address* pc_address;
+  };
+
   // Copy constructor; it breaks the connection to host iterator.
   StackFrame(const StackFrame& original) {
     this->state_ = original.state_;
@@ -179,12 +186,6 @@
                      int index) const { }

  protected:
-  struct State {
-    Address sp;
-    Address fp;
-    Address* pc_address;
-  };
-
explicit StackFrame(StackFrameIterator* iterator) : iterator_(iterator) { }
   virtual ~StackFrame() { }

@@ -300,6 +301,8 @@
   // pointer. Used when constructing the first stack frame seen by an
   // iterator and the frames following entry frames.
   static Type GetStateForFramePointer(Address fp, State* state);
+  static Address ComputeStackPointer(Address fp);
+  static void FillState(Address fp, Address sp, State* state);

  protected:
explicit ExitFrame(StackFrameIterator* iterator) : StackFrame(iterator) { }
@@ -433,6 +436,7 @@
   inline Object* function_slot_object() const;

   friend class StackFrameIterator;
+  friend class StackTracer;
 };


@@ -642,15 +646,38 @@
   }

  private:
+  class StackAddressValidator {
+   public:
+    StackAddressValidator(Address low_bound, Address high_bound)
+        : low_bound_(low_bound), high_bound_(high_bound) { }
+    bool IsValid(Address addr) const {
+      return IsWithinBounds(low_bound_, high_bound_, addr);
+    }
+   private:
+    Address low_bound_;
+    Address high_bound_;
+  };
+
+  class ExitFrameValidator {
+   public:
+    explicit ExitFrameValidator(const StackAddressValidator& validator)
+        : validator_(validator) { }
+    ExitFrameValidator(Address low_bound, Address high_bound)
+        : validator_(low_bound, high_bound) { }
+    bool IsValidFP(Address fp);
+   private:
+    StackAddressValidator validator_;
+  };
+
   bool IsValidStackAddress(Address addr) const {
-    return IsWithinBounds(low_bound_, high_bound_, addr);
+    return stack_validator_.IsValid(addr);
   }
   bool CanIterateHandles(StackFrame* frame, StackHandler* handler);
   bool IsValidFrame(StackFrame* frame) const;
   bool IsValidCaller(StackFrame* frame);
-
-  Address low_bound_;
-  Address high_bound_;
+  static bool IsValidTop(Address low_bound, Address high_bound);
+
+  StackAddressValidator stack_validator_;
   const bool is_valid_top_;
   const bool is_valid_fp_;
   const bool is_working_iterator_;
=======================================
--- /branches/2.3/src/ia32/frames-ia32.cc       Mon Aug 30 23:45:16 2010
+++ /branches/2.3/src/ia32/frames-ia32.cc       Thu Sep 16 03:01:13 2010
@@ -50,16 +50,8 @@
 }


-StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State* state) {
-  if (fp == 0) return NONE;
-  // Compute the stack pointer.
-  Address sp = Memory::Address_at(fp + ExitFrameConstants::kSPOffset);
-  // Fill in the state.
-  state->fp = fp;
-  state->sp = sp;
-  state->pc_address = reinterpret_cast<Address*>(sp - 1 * kPointerSize);
-  ASSERT(*state->pc_address != NULL);
-  return EXIT;
+Address ExitFrame::ComputeStackPointer(Address fp) {
+  return Memory::Address_at(fp + ExitFrameConstants::kSPOffset);
 }


=======================================
--- /branches/2.3/src/log.cc    Mon Jun 28 04:29:21 2010
+++ /branches/2.3/src/log.cc    Thu Sep 16 03:01:13 2010
@@ -170,7 +170,9 @@
   SafeStackTraceFrameIterator it(sample->fp, sample->sp,
                                  sample->sp, js_entry_sp);
   while (!it.done() && i < TickSample::kMaxFramesCount) {
-    sample->stack[i++] = reinterpret_cast<Address>(it.frame()->function());
+    sample->stack[i++] =
+        reinterpret_cast<Address>(it.frame()->function_slot_object()) -
+            kHeapObjectTag;
     it.Advance();
   }
   sample->frames_count = i;
=======================================
--- /branches/2.3/src/mips/frames-mips.cc       Fri May 21 05:58:28 2010
+++ /branches/2.3/src/mips/frames-mips.cc       Thu Sep 16 03:01:13 2010
@@ -52,9 +52,7 @@
 }


-StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State* state) {
-  if (fp == 0) return NONE;
-  // Compute frame type and stack pointer.
+Address ExitFrame::ComputeStackPointer(Address fp) {
   Address sp = fp + ExitFrameConstants::kSPDisplacement;
   const int offset = ExitFrameConstants::kCodeOffset;
   Object* code = Memory::Object_at(fp + offset);
@@ -62,11 +60,7 @@
   if (is_debug_exit) {
     sp -= kNumJSCallerSaved * kPointerSize;
   }
-  // Fill in the state.
-  state->sp = sp;
-  state->fp = fp;
-  state->pc_address = reinterpret_cast<Address*>(sp - 1 * kPointerSize);
-  return EXIT;
+  return sp;
 }


=======================================
--- /branches/2.3/src/version.cc        Tue Sep  7 03:13:55 2010
+++ /branches/2.3/src/version.cc        Thu Sep 16 03:01:13 2010
@@ -35,7 +35,7 @@
 #define MAJOR_VERSION     2
 #define MINOR_VERSION     3
 #define BUILD_NUMBER      11
-#define PATCH_LEVEL       6
+#define PATCH_LEVEL       7
 #define CANDIDATE_VERSION false

 // Define SONAME to have the SCons build the put a specific SONAME into the
=======================================
--- /branches/2.3/src/x64/frames-x64.cc Mon Aug 30 23:45:16 2010
+++ /branches/2.3/src/x64/frames-x64.cc Thu Sep 16 03:01:13 2010
@@ -50,17 +50,10 @@
 }


-StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State* state) {
-  if (fp == 0) return NONE;
-  // Compute the stack pointer.
-  Address sp = Memory::Address_at(fp + ExitFrameConstants::kSPOffset);
-  // Fill in the state.
-  state->fp = fp;
-  state->sp = sp;
-  state->pc_address = reinterpret_cast<Address*>(sp - 1 * kPointerSize);
-  ASSERT(*state->pc_address != NULL);
-  return EXIT;
-}
+Address ExitFrame::ComputeStackPointer(Address fp) {
+  return Memory::Address_at(fp + ExitFrameConstants::kSPOffset);
+}
+

 int JavaScriptFrame::GetProvidedParametersCount() const {
   return ComputeParametersCount();
=======================================
--- /branches/2.3/test/cctest/test-log-stack-tracer.cc Wed Aug 25 08:26:24 2010 +++ /branches/2.3/test/cctest/test-log-stack-tracer.cc Thu Sep 16 03:01:13 2010
@@ -175,21 +175,8 @@
 }


-static Local<Value> GetGlobalProperty(const char* name) {
-  return env->Global()->Get(String::New(name));
-}
-
-
-static Handle<JSFunction> GetGlobalJSFunction(const char* name) {
-  Handle<JSFunction> result(JSFunction::cast(
-      *v8::Utils::OpenHandle(*GetGlobalProperty(name))));
-  return result;
-}
-
-
-static void CheckObjectIsJSFunction(const char* func_name,
-                                    Address addr) {
-  i::Object* obj = reinterpret_cast<i::Object*>(addr);
+static void CheckJSFunctionAtAddress(const char* func_name, Address addr) {
+  i::Object* obj = i::HeapObject::FromAddress(addr);
   CHECK(obj->IsJSFunction());
   CHECK(JSFunction::cast(obj)->shared()->name()->IsString());
   i::SmartPointer<char> found_name =
@@ -264,7 +251,6 @@
 #endif

   SetGlobalProperty(func_name, v8::ToApi<Value>(func));
-  CHECK_EQ(*func, *GetGlobalJSFunction(func_name));
 }


@@ -298,13 +284,13 @@
   // script [JS]
   //   JSTrace() [JS]
   //     JSFuncDoTrace() [JS] [captures EBP value and encodes it as Smi]
-  //       trace(EBP encoded as Smi) [native (extension)]
+  //       trace(EBP) [native (extension)]
   //         DoTrace(EBP) [native]
   //           StackTracer::Trace
   CHECK_GT(sample.frames_count, 1);
// Stack tracing will start from the first JS function, i.e. "JSFuncDoTrace"
-  CheckObjectIsJSFunction("JSFuncDoTrace", sample.stack[0]);
-  CheckObjectIsJSFunction("JSTrace", sample.stack[1]);
+  CheckJSFunctionAtAddress("JSFuncDoTrace", sample.stack[0]);
+  CheckJSFunctionAtAddress("JSTrace", sample.stack[1]);
 }


@@ -342,19 +328,18 @@
   // script [JS]
   //   OuterJSTrace() [JS]
   //     JSTrace() [JS]
-  //       JSFuncDoTrace() [JS] [captures EBP value and encodes it as Smi]
-  //         js_trace(EBP encoded as Smi) [native (extension)]
+  //       JSFuncDoTrace() [JS]
+  //         js_trace(EBP) [native (extension)]
   //           DoTraceHideCEntryFPAddress(EBP) [native]
   //             StackTracer::Trace
   //
   // The last JS function called. It is only visible through
   // sample.function, as its return address is above captured EBP value.
-  CHECK_EQ(GetGlobalJSFunction("JSFuncDoTrace")->address(),
-           sample.function);
+  CheckJSFunctionAtAddress("JSFuncDoTrace", sample.function);
   CHECK_GT(sample.frames_count, 1);
// Stack sampling will start from the caller of JSFuncDoTrace, i.e. "JSTrace"
-  CheckObjectIsJSFunction("JSTrace", sample.stack[0]);
-  CheckObjectIsJSFunction("OuterJSTrace", sample.stack[1]);
+  CheckJSFunctionAtAddress("JSTrace", sample.stack[0]);
+  CheckJSFunctionAtAddress("OuterJSTrace", sample.stack[1]);
 }


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

Reply via email to