Reviewers: Roger McFarlane (Chromium),

https://chromiumcodereview.appspot.com/9401019/diff/1004/src/platform-win32.cc
File src/platform-win32.cc (right):

https://chromiumcodereview.appspot.com/9401019/diff/1004/src/platform-win32.cc#newcode131
src/platform-win32.cc:131: // TODO(siggi): Check for the presence of the
Syzygy instrumentation by
On 2012/02/15 21:19:03, Roger McFarlane (Chromium) wrote:
Another way to do this would be to introduce and reference a known
symbol that
is set to NULL by default in the source code, but rewritten to point
to the
imported resolution function during instrumentation.

That way less knowledge of the profiler is required here.

i.e.,
   // Declared non-const, at global scope, and marked extern.
   extern "C" ReturnAddressResolutionFunction address_resolution_func =
NULL;

Usage below is then simplified:

   Address* OS::ResolveReturnAddressLocation(Address* pc_address) {
     if (address_resolution_func == NULL)
       return pc_address;
     return address_resolution_func(pc_address);
   }

It's the responsiblity of the instrumenter to recognize the symbol and
rewrite
all references/relocs to it.

To expand on my email reply, the issue is that binary rewriting is so
far outside the ABI that results are totally unpredictable.
With WPO, the linker has sufficient information to know that nothing in
the binary refers to the pointer above, so the whole thing can and will
be folded to a noop.
As V8 is compiled by many users to in many different ways, and both to
executables and DLLs (as in the Chrome case), I hesitate to add
mandatory exports, especially a data export. There are all sorts of
considerations that come into play at that point. Even for a function
export, it's not commonplace to see those on EXEs, and the
compiler/linker has freedom to duplicate functions, so you could e.g.
get a trivial inline at usage, in addition to an export.
I feel binary rewriting by the instrumenter is not the way to go here.

Description:
Outline for adding Syzygy profiler support to V8.


Please review this at https://chromiumcodereview.appspot.com/9401019/

SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge

Affected files:
  M src/frames.cc
  M src/platform-win32.cc
  M src/platform.h


Index: src/frames.cc
diff --git a/src/frames.cc b/src/frames.cc
index 40df12c437281bb6006c66af0e8a55871c14623d..2473b6691d38f0fd4deed18b586d49a30854fdbb 100644
--- a/src/frames.cc
+++ b/src/frames.cc
@@ -155,8 +155,8 @@ void StackFrameIterator::Reset() {
     ASSERT(fp_ != NULL);
     state.fp = fp_;
     state.sp = sp_;
-    state.pc_address =
-        reinterpret_cast<Address*>(StandardFrame::ComputePCAddress(fp_));
+    state.pc_address = OS::ResolveReturnAddressLocation(
+        reinterpret_cast<Address*>(StandardFrame::ComputePCAddress(fp_)));
     type = StackFrame::ComputeType(isolate(), &state);
   }
   if (SingletonFor(type) == NULL) return;
@@ -488,8 +488,8 @@ void ExitFrame::ComputeCallerState(State* state) const {
   // Set up the caller state.
   state->sp = caller_sp();
state->fp = Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset);
-  state->pc_address
- = reinterpret_cast<Address*>(fp() + ExitFrameConstants::kCallerPCOffset);
+  state->pc_address = OS::ResolveReturnAddressLocation(
+ reinterpret_cast<Address*>(fp() + ExitFrameConstants::kCallerPCOffset));
 }


@@ -523,7 +523,8 @@ StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State* state) {
 void ExitFrame::FillState(Address fp, Address sp, State* state) {
   state->sp = sp;
   state->fp = fp;
-  state->pc_address = reinterpret_cast<Address*>(sp - 1 * kPointerSize);
+  state->pc_address = OS::ResolveReturnAddressLocation(
+      reinterpret_cast<Address*>(sp - 1 * kPointerSize));
 }


@@ -558,7 +559,8 @@ int StandardFrame::ComputeExpressionsCount() const {
 void StandardFrame::ComputeCallerState(State* state) const {
   state->sp = caller_sp();
   state->fp = caller_fp();
-  state->pc_address = reinterpret_cast<Address*>(ComputePCAddress(fp()));
+  state->pc_address = OS::ResolveReturnAddressLocation(
+      reinterpret_cast<Address*>(ComputePCAddress(fp())));
 }


Index: src/platform-win32.cc
diff --git a/src/platform-win32.cc b/src/platform-win32.cc
index f16b5e74fda8705cd36db689eab1d2e94d0f0f17..8af41a0039a49990875ea634ece2b7ac6c963b2e 100644
--- a/src/platform-win32.cc
+++ b/src/platform-win32.cc
@@ -124,6 +124,19 @@ int random() {
 namespace v8 {
 namespace internal {

+typedef Address* (*ReturnAddressResolutionFunction)(Address*);
+static ReturnAddressResolutionFunction
+    LookupProfilerReturnAddressResolutionFunction() {
+  // DO NOT SUBMIT
+  // TODO(siggi): Check for the presence of the Syzygy instrumentation by
+  //    testing for the presence of the .thunks segment. This is quick as
+  //    we're only looking at the image headers.
+ // If instrumentation is present, look for the export we want on one of
+  //    the modules we import.
+  return NULL;
+}
+
+
 intptr_t OS::MaxVirtualMemory() {
   return 0;
 }
@@ -1241,6 +1254,31 @@ void OS::SignalCodeMovingGC() {
 }


+Address* OS::ResolveReturnAddressLocation(Address* pc_address) {
+  // Make the normal case where there is no profiling in effect very fast.
+  static bool no_profiling = false;
+  if (no_profiling)
+    return pc_address;
+
+  // Either profiling is in effect, or we haven't checked for the presence
+  // of the profiler yet.
+  static bool profiler_check_finished = false;
+  ReturnAddressResolutionFunction resolve_return_address = NULL;
+  if (!profiler_check_finished) {
+ resolve_return_address = LookupProfilerReturnAddressResolutionFunction();
+    profiler_check_finished = true;
+  }
+  ASSERT(profiler_check_finished);
+
+  if (resolve_return_address == NULL) {
+    no_profiling = true;
+    return pc_address;
+  }
+
+  return resolve_return_address(pc_address);
+}
+
+
 // Walk the stack using the facilities in dbghelp.dll and tlhelp32.dll

// Switch off warning 4748 (/GS can not protect parameters and local variables
Index: src/platform.h
diff --git a/src/platform.h b/src/platform.h
index a0186d580fe32c6573d7dc3031011bd0244b0ea8..691c42a468d6f23e5f8ca10f5f784c1546b35881 100644
--- a/src/platform.h
+++ b/src/platform.h
@@ -256,6 +256,20 @@ class OS {
   // using --never-compact) if accurate profiling is desired.
   static void SignalCodeMovingGC();

+ // Support for profilers that change the return address for functions under + // profiling. The input is a pointer to a return address on the stack, and the
+  // return value is either that same pointer, or a pointer to the location
+  // where the profiler has stashed the actual return address.
+ // This is implemented only for the Syzygy instrumenting performance profiler
+  // on Win32 at present.
+#ifdef _WIN32
+  static Address* ResolveReturnAddressLocation(Address* pc_address);
+#else
+  static Address* ResolveReturnAddressLocation(Address* pc_address) {
+    return pc_address;
+  }
+#endif
+
// The return value indicates the CPU features we are sure of because of the // OS. For example MacOSX doesn't run on any x86 CPUs that don't have SSE2
   // instructions.


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

Reply via email to