Various extension-related cleanup and simplifications.
authorsvenpanne@chromium.org <svenpanne@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 17 Jan 2014 10:52:00 +0000 (10:52 +0000)
committersvenpanne@chromium.org <svenpanne@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 17 Jan 2014 10:52:00 +0000 (10:52 +0000)
Removes the embarrassing "static"s, shuffles some code around, doing various cleanups on the way.

R=dcarney@chromium.org

Review URL: https://codereview.chromium.org/130213009

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

28 files changed:
include/v8.h
src/bootstrapper.cc
src/bootstrapper.h
src/extensions/externalize-string-extension.cc
src/extensions/externalize-string-extension.h
src/extensions/free-buffer-extension.cc
src/extensions/free-buffer-extension.h
src/extensions/gc-extension.cc
src/extensions/gc-extension.h
src/extensions/statistics-extension.cc
src/extensions/statistics-extension.h
src/extensions/trigger-failure-extension.cc
src/extensions/trigger-failure-extension.h
src/v8.cc
test/cctest/cctest.cc
test/cctest/cctest.gyp
test/cctest/cctest.h
test/cctest/print-extension.cc [new file with mode: 0644]
test/cctest/print-extension.h [new file with mode: 0644]
test/cctest/profiler-extension.cc
test/cctest/profiler-extension.h
test/cctest/test-compiler.cc
test/cctest/test-cpu-profiler.cc
test/cctest/test-heap-profiler.cc
test/cctest/test-log-stack-tracer.cc
test/cctest/test-profile-generator.cc
test/cctest/trace-extension.cc [new file with mode: 0644]
test/cctest/trace-extension.h [new file with mode: 0644]

index 8f19498..fbdc82f 100644 (file)
@@ -3718,17 +3718,6 @@ class V8_EXPORT Extension {  // NOLINT
 void V8_EXPORT RegisterExtension(Extension* extension);
 
 
-/**
- * Ignore
- */
-class V8_EXPORT DeclareExtension {
- public:
-  V8_INLINE DeclareExtension(Extension* extension) {
-    RegisterExtension(extension);
-  }
-};
-
-
 // --- Statics ---
 
 V8_INLINE Handle<Primitive> Undefined(Isolate* isolate);
index 288cac2..97364ca 100644 (file)
@@ -101,12 +101,39 @@ void Bootstrapper::Initialize(bool create_heap_objects) {
 }
 
 
+static const char* GCFunctionName() {
+  bool flag_given = FLAG_expose_gc_as != NULL && strlen(FLAG_expose_gc_as) != 0;
+  return flag_given ? FLAG_expose_gc_as : "gc";
+}
+
+
+v8::Extension* Bootstrapper::free_buffer_extension_ = NULL;
+v8::Extension* Bootstrapper::gc_extension_ = NULL;
+v8::Extension* Bootstrapper::externalize_string_extension_ = NULL;
+v8::Extension* Bootstrapper::statistics_extension_ = NULL;
+v8::Extension* Bootstrapper::trigger_failure_extension_ = NULL;
+
+
 void Bootstrapper::InitializeOncePerProcess() {
-  FreeBufferExtension::Register();
-  GCExtension::Register();
-  ExternalizeStringExtension::Register();
-  StatisticsExtension::Register();
-  TriggerFailureExtension::Register();
+  free_buffer_extension_ = new FreeBufferExtension;
+  v8::RegisterExtension(free_buffer_extension_);
+  gc_extension_ = new GCExtension(GCFunctionName());
+  v8::RegisterExtension(gc_extension_);
+  externalize_string_extension_ = new ExternalizeStringExtension;
+  v8::RegisterExtension(externalize_string_extension_);
+  statistics_extension_ = new StatisticsExtension;
+  v8::RegisterExtension(statistics_extension_);
+  trigger_failure_extension_ = new TriggerFailureExtension;
+  v8::RegisterExtension(trigger_failure_extension_);
+}
+
+
+void Bootstrapper::TearDownExtensions() {
+  delete free_buffer_extension_;
+  delete gc_extension_;
+  delete externalize_string_extension_;
+  delete statistics_extension_;
+  delete trigger_failure_extension_;
 }
 
 
index 4f63c87..14dd1bd 100644 (file)
@@ -90,6 +90,7 @@ class SourceCodeCache BASE_EMBEDDED {
 class Bootstrapper {
  public:
   static void InitializeOncePerProcess();
+  static void TearDownExtensions();
 
   // Requires: Heap::SetUp has been called.
   void Initialize(bool create_heap_objects);
@@ -146,6 +147,12 @@ class Bootstrapper {
 
   explicit Bootstrapper(Isolate* isolate);
 
+  static v8::Extension* free_buffer_extension_;
+  static v8::Extension* gc_extension_;
+  static v8::Extension* externalize_string_extension_;
+  static v8::Extension* statistics_extension_;
+  static v8::Extension* trigger_failure_extension_;
+
   DISALLOW_COPY_AND_ASSIGN(Bootstrapper);
 };
 
index 7dc7a3c..d372cf0 100644 (file)
@@ -145,10 +145,4 @@ void ExternalizeStringExtension::IsAscii(
   args.GetReturnValue().Set(is_one_byte);
 }
 
-
-void ExternalizeStringExtension::Register() {
-  static ExternalizeStringExtension externalize_extension;
-  static v8::DeclareExtension declaration(&externalize_extension);
-}
-
 } }  // namespace v8::internal
index 3d1e438..d0cb5e4 100644 (file)
@@ -41,7 +41,7 @@ class ExternalizeStringExtension : public v8::Extension {
       v8::Handle<v8::String> name);
   static void Externalize(const v8::FunctionCallbackInfo<v8::Value>& args);
   static void IsAscii(const v8::FunctionCallbackInfo<v8::Value>& args);
-  static void Register();
+
  private:
   static const char* const kSource;
 };
index c2e3102..b4abaaf 100644 (file)
@@ -47,14 +47,4 @@ void FreeBufferExtension::FreeBuffer(
   V8::ArrayBufferAllocator()->Free(contents.Data(), contents.ByteLength());
 }
 
-
-void FreeBufferExtension::Register() {
-  static char buffer[100];
-  Vector<char> temp_vector(buffer, sizeof(buffer));
-  OS::SNPrintF(temp_vector, "native function freeBuffer();");
-
-  static FreeBufferExtension buffer_free_extension(buffer);
-  static v8::DeclareExtension declaration(&buffer_free_extension);
-}
-
 } }  // namespace v8::internal
index 22d466f..26ff7d1 100644 (file)
@@ -35,13 +35,12 @@ namespace internal {
 
 class FreeBufferExtension : public v8::Extension {
  public:
-  explicit FreeBufferExtension(const char* source)
-      : v8::Extension("v8/free-buffer", source) {}
+  FreeBufferExtension()
+      : v8::Extension("v8/free-buffer", "native function freeBuffer();") {}
   virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate(
       v8::Isolate* isolate,
       v8::Handle<v8::String> name);
   static void FreeBuffer(const v8::FunctionCallbackInfo<v8::Value>& args);
-  static void Register();
 };
 
 } }  // namespace v8::internal
index 205587f..1b5fb5d 100644 (file)
@@ -50,18 +50,4 @@ void GCExtension::GC(const v8::FunctionCallbackInfo<v8::Value>& args) {
   }
 }
 
-
-void GCExtension::Register() {
-  static char buffer[50];
-  Vector<char> temp_vector(buffer, sizeof(buffer));
-  if (FLAG_expose_gc_as != NULL && strlen(FLAG_expose_gc_as) != 0) {
-    OS::SNPrintF(temp_vector, "native function %s();", FLAG_expose_gc_as);
-  } else {
-    OS::SNPrintF(temp_vector, "native function gc();");
-  }
-
-  static GCExtension gc_extension(buffer);
-  static v8::DeclareExtension declaration(&gc_extension);
-}
-
 } }  // namespace v8::internal
index 8c25e7d..adc79fe 100644 (file)
@@ -35,12 +35,21 @@ namespace internal {
 
 class GCExtension : public v8::Extension {
  public:
-  explicit GCExtension(const char* source) : v8::Extension("v8/gc", source) {}
+  explicit GCExtension(const char* fun_name)
+      : v8::Extension("v8/gc",
+                      BuildSource(buffer_, sizeof(buffer_), fun_name)) {}
   virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate(
       v8::Isolate* isolate,
       v8::Handle<v8::String> name);
   static void GC(const v8::FunctionCallbackInfo<v8::Value>& args);
-  static void Register();
+
+ private:
+  static const char* BuildSource(char* buf, size_t size, const char* fun_name) {
+    OS::SNPrintF(Vector<char>(buf, size), "native function %s();", fun_name);
+    return buf;
+  }
+
+  char buffer_[50];
 };
 
 } }  // namespace v8::internal
index a2e07ef..e10dddf 100644 (file)
@@ -170,10 +170,4 @@ void StatisticsExtension::GetCounters(
   args.GetReturnValue().Set(result);
 }
 
-
-void StatisticsExtension::Register() {
-  static StatisticsExtension statistics_extension;
-  static v8::DeclareExtension declaration(&statistics_extension);
-}
-
 } }  // namespace v8::internal
index f05e768..9e97b45 100644 (file)
@@ -40,7 +40,7 @@ class StatisticsExtension : public v8::Extension {
       v8::Isolate* isolate,
       v8::Handle<v8::String> name);
   static void GetCounters(const v8::FunctionCallbackInfo<v8::Value>& args);
-  static void Register();
+
  private:
   static const char* const kSource;
 };
index 68dea93..83894b9 100644 (file)
@@ -76,10 +76,4 @@ void TriggerFailureExtension::TriggerSlowAssertFalse(
   SLOW_ASSERT(false);
 }
 
-
-void TriggerFailureExtension::Register() {
-  static TriggerFailureExtension trigger_failure_extension;
-  static v8::DeclareExtension declaration(&trigger_failure_extension);
-}
-
 } }  // namespace v8::internal
index 5a4223f..467b7d2 100644 (file)
@@ -45,7 +45,6 @@ class TriggerFailureExtension : public v8::Extension {
       const v8::FunctionCallbackInfo<v8::Value>& args);
   static void TriggerSlowAssertFalse(
       const v8::FunctionCallbackInfo<v8::Value>& args);
-  static void Register();
 
  private:
   static const char* const kSource;
index 76a6cb7..b89bb7a 100644 (file)
--- a/src/v8.cc
+++ b/src/v8.cc
@@ -99,6 +99,7 @@ void V8::TearDown() {
   isolate->TearDown();
   delete isolate;
 
+  Bootstrapper::TearDownExtensions();
   ElementsAccessor::TearDown();
   LOperand::TearDownCaches();
   ExternalReference::TearDownMathExpData();
index 4aa9c7e..865bc6d 100644 (file)
 
 #include <v8.h>
 #include "cctest.h"
+
+#include "print-extension.h"
+#include "profiler-extension.h"
+#include "trace-extension.h"
 #include "debug.h"
 
 enum InitializationState {kUnset, kUnintialized, kInitialized};
@@ -141,6 +145,13 @@ int main(int argc, char* argv[]) {
   CcTestArrayBufferAllocator array_buffer_allocator;
   v8::V8::SetArrayBufferAllocator(&array_buffer_allocator);
 
+  i::PrintExtension print_extension;
+  v8::RegisterExtension(&print_extension);
+  i::ProfilerExtension profiler_extension;
+  v8::RegisterExtension(&profiler_extension);
+  i::TraceExtension trace_extension;
+  v8::RegisterExtension(&trace_extension);
+
   int tests_run = 0;
   bool print_run_count = true;
   for (int i = 1; i < argc; i++) {
index 8f4a160..921c1a4 100644 (file)
@@ -47,6 +47,7 @@
         'gay-fixed.cc',
         'gay-precision.cc',
         'gay-shortest.cc',
+        'print-extension.cc',
         'profiler-extension.cc',
         'test-accessors.cc',
         'test-alloc.cc',
         'test-version.cc',
         'test-weakmaps.cc',
         'test-weaksets.cc',
-        'test-weaktypedarrays.cc'
+        'test-weaktypedarrays.cc',
+        'trace-extension.cc'
       ],
       'conditions': [
         ['v8_target_arch=="ia32"', {
index 7b44a98..6d2c552 100644 (file)
   static void Test##Name()
 #endif
 
-#define EXTENSION_LIST(V)                                                \
-  V(GC_EXTENSION,    "v8/gc")                                            \
-  V(PRINT_EXTENSION, "v8/print")                                         \
-  V(TRACE_EXTENSION, "v8/trace")
+#define EXTENSION_LIST(V)                                                      \
+  V(GC_EXTENSION,       "v8/gc")                                               \
+  V(PRINT_EXTENSION,    "v8/print")                                            \
+  V(PROFILER_EXTENSION, "v8/profiler")                                         \
+  V(TRACE_EXTENSION,    "v8/trace")
 
 #define DEFINE_EXTENSION_ID(Name, Ident) Name##_ID,
 enum CcTestExtensionIds {
diff --git a/test/cctest/print-extension.cc b/test/cctest/print-extension.cc
new file mode 100644 (file)
index 0000000..9f62919
--- /dev/null
@@ -0,0 +1,51 @@
+// Copyright 2014 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 "print-extension.h"
+
+namespace v8 {
+namespace internal {
+
+v8::Handle<v8::FunctionTemplate> PrintExtension::GetNativeFunctionTemplate(
+    v8::Isolate* isolate,
+    v8::Handle<v8::String> str) {
+  return v8::FunctionTemplate::New(isolate, PrintExtension::Print);
+}
+
+
+void PrintExtension::Print(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  for (int i = 0; i < args.Length(); i++) {
+    if (i != 0) printf(" ");
+    v8::HandleScope scope(args.GetIsolate());
+    v8::String::Utf8Value str(args[i]);
+    if (*str == NULL) return;
+    printf("%s", *str);
+  }
+  printf("\n");
+}
+
+} }  // namespace v8::internal
diff --git a/test/cctest/print-extension.h b/test/cctest/print-extension.h
new file mode 100644 (file)
index 0000000..7fe9226
--- /dev/null
@@ -0,0 +1,47 @@
+// Copyright 2014 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_TEST_CCTEST_PRINT_EXTENSION_H_
+#define V8_TEST_CCTEST_PRINT_EXTENSION_H_
+
+#include "v8.h"
+
+namespace v8 {
+namespace internal {
+
+class PrintExtension : public v8::Extension {
+ public:
+  PrintExtension() : v8::Extension("v8/print", "native function print();") { }
+  virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate(
+      v8::Isolate* isolate,
+      v8::Handle<v8::String> name);
+  static void Print(const v8::FunctionCallbackInfo<v8::Value>& args);
+};
+
+} }  // namespace v8::internal
+
+#endif
index 193b1ce..80d9f90 100644 (file)
 // Tests of profiles generator and utilities.
 
 #include "profiler-extension.h"
+#include "checks.h"
+
+namespace v8 {
+namespace internal {
 
-#include "cctest.h"
 
 const v8::CpuProfile* ProfilerExtension::last_profile = NULL;
 const char* ProfilerExtension::kSource =
@@ -69,6 +72,4 @@ void ProfilerExtension::StopProfiling(
       : v8::String::Empty(args.GetIsolate()));
 }
 
-
-static ProfilerExtension kProfilerExtension;
-v8::DeclareExtension kProfilerExtensionDeclaration(&kProfilerExtension);
+} }  // namespace v8::internal
index 00960b9..392a7ef 100644 (file)
 //
 // Tests of profiles generator and utilities.
 
+#ifndef V8_TEST_CCTEST_PROFILER_EXTENSION_H_
+#define V8_TEST_CCTEST_PROFILER_EXTENSION_H_
+
 #include "../include/v8-profiler.h"
 
+namespace v8 {
+namespace internal {
+
 class ProfilerExtension : public v8::Extension {
  public:
   ProfilerExtension() : v8::Extension("v8/profiler", kSource) { }
@@ -41,3 +47,8 @@ class ProfilerExtension : public v8::Extension {
  private:
   static const char* kSource;
 };
+
+
+} }  // namespace v8::internal
+
+#endif
index f15ed3c..7df8511 100644 (file)
 
 #include "compiler.h"
 #include "disasm.h"
-#include "disassembler.h"
-#include "execution.h"
-#include "factory.h"
-#include "platform.h"
 #include "cctest.h"
 
 using namespace v8::internal;
 
-// --- P r i n t   E x t e n s i o n ---
-
-class PrintExtension : public v8::Extension {
- public:
-  PrintExtension() : v8::Extension("v8/print", kSource) { }
-  virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate(
-      v8::Isolate* isolate,
-      v8::Handle<v8::String> name);
-  static void Print(const v8::FunctionCallbackInfo<v8::Value>& args);
- private:
-  static const char* kSource;
-};
-
-
-const char* PrintExtension::kSource = "native function print();";
-
-
-v8::Handle<v8::FunctionTemplate> PrintExtension::GetNativeFunctionTemplate(
-    v8::Isolate* isolate,
-    v8::Handle<v8::String> str) {
-  return v8::FunctionTemplate::New(isolate, PrintExtension::Print);
-}
-
-
-void PrintExtension::Print(const v8::FunctionCallbackInfo<v8::Value>& args) {
-  for (int i = 0; i < args.Length(); i++) {
-    if (i != 0) printf(" ");
-    v8::HandleScope scope(args.GetIsolate());
-    v8::String::Utf8Value str(args[i]);
-    if (*str == NULL) return;
-    printf("%s", *str);
-  }
-  printf("\n");
-}
-
-
-static PrintExtension kPrintExtension;
-v8::DeclareExtension kPrintExtensionDeclaration(&kPrintExtension);
-
-
 static MaybeObject* GetGlobalProperty(const char* name) {
   Isolate* isolate = CcTest::i_isolate();
   Handle<String> internalized_name =
index 4c6dabe..3bba514 100644 (file)
@@ -400,7 +400,7 @@ TEST(ProfileStartEndTime) {
 
 
 static const v8::CpuProfile* RunProfiler(
-    LocalContext& env, v8::Handle<v8::Function> function,
+    v8::Handle<v8::Context> env, v8::Handle<v8::Function> function,
     v8::Handle<v8::Value> argv[], int argc,
     unsigned min_js_samples) {
   v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler();
@@ -554,7 +554,7 @@ TEST(CollectCpuProfile) {
     v8::Integer::New(env->GetIsolate(), profiling_interval_ms)
   };
   const v8::CpuProfile* profile =
-      RunProfiler(env, function, args, ARRAY_SIZE(args), 200);
+      RunProfiler(env.local(), function, args, ARRAY_SIZE(args), 200);
   function->Call(env->Global(), ARRAY_SIZE(args), args);
 
   const v8::CpuProfileNode* root = profile->GetTopDownRoot();
@@ -628,7 +628,7 @@ TEST(SampleWhenFrameIsNotSetup) {
     v8::Integer::New(env->GetIsolate(), repeat_count)
   };
   const v8::CpuProfile* profile =
-      RunProfiler(env, function, args, ARRAY_SIZE(args), 100);
+      RunProfiler(env.local(), function, args, ARRAY_SIZE(args), 100);
 
   const v8::CpuProfileNode* root = profile->GetTopDownRoot();
 
@@ -748,7 +748,7 @@ TEST(NativeAccessorUninitializedIC) {
   int32_t repeat_count = 1;
   v8::Handle<v8::Value> args[] = { v8::Integer::New(isolate, repeat_count) };
   const v8::CpuProfile* profile =
-      RunProfiler(env, function, args, ARRAY_SIZE(args), 180);
+      RunProfiler(env.local(), function, args, ARRAY_SIZE(args), 180);
 
   const v8::CpuProfileNode* root = profile->GetTopDownRoot();
   const v8::CpuProfileNode* startNode =
@@ -805,7 +805,7 @@ TEST(NativeAccessorMonomorphicIC) {
   int32_t repeat_count = 100;
   v8::Handle<v8::Value> args[] = { v8::Integer::New(isolate, repeat_count) };
   const v8::CpuProfile* profile =
-      RunProfiler(env, function, args, ARRAY_SIZE(args), 200);
+      RunProfiler(env.local(), function, args, ARRAY_SIZE(args), 200);
 
   const v8::CpuProfileNode* root = profile->GetTopDownRoot();
   const v8::CpuProfileNode* startNode =
@@ -859,7 +859,7 @@ TEST(NativeMethodUninitializedIC) {
   int32_t repeat_count = 1;
   v8::Handle<v8::Value> args[] = { v8::Integer::New(isolate, repeat_count) };
   const v8::CpuProfile* profile =
-      RunProfiler(env, function, args, ARRAY_SIZE(args), 100);
+      RunProfiler(env.local(), function, args, ARRAY_SIZE(args), 100);
 
   const v8::CpuProfileNode* root = profile->GetTopDownRoot();
   const v8::CpuProfileNode* startNode =
@@ -916,7 +916,7 @@ TEST(NativeMethodMonomorphicIC) {
   int32_t repeat_count = 100;
   v8::Handle<v8::Value> args[] = { v8::Integer::New(isolate, repeat_count) };
   const v8::CpuProfile* profile =
-      RunProfiler(env, function, args, ARRAY_SIZE(args), 100);
+      RunProfiler(env.local(), function, args, ARRAY_SIZE(args), 100);
 
   const v8::CpuProfileNode* root = profile->GetTopDownRoot();
   GetChild(isolate, root, "start");
@@ -957,7 +957,7 @@ TEST(BoundFunctionCall) {
     v8::Integer::New(env->GetIsolate(), duration_ms)
   };
   const v8::CpuProfile* profile =
-      RunProfiler(env, function, args, ARRAY_SIZE(args), 100);
+      RunProfiler(env.local(), function, args, ARRAY_SIZE(args), 100);
 
   const v8::CpuProfileNode* root = profile->GetTopDownRoot();
   ScopedVector<v8::Handle<v8::String> > names(3);
@@ -1018,7 +1018,7 @@ TEST(FunctionCallSample) {
     v8::Integer::New(env->GetIsolate(), duration_ms)
   };
   const v8::CpuProfile* profile =
-      RunProfiler(env, function, args, ARRAY_SIZE(args), 100);
+      RunProfiler(env.local(), function, args, ARRAY_SIZE(args), 100);
 
   const v8::CpuProfileNode* root = profile->GetTopDownRoot();
   {
@@ -1101,7 +1101,7 @@ TEST(FunctionApplySample) {
   };
 
   const v8::CpuProfile* profile =
-      RunProfiler(env, function, args, ARRAY_SIZE(args), 100);
+      RunProfiler(env.local(), function, args, ARRAY_SIZE(args), 100);
 
   const v8::CpuProfileNode* root = profile->GetTopDownRoot();
   {
@@ -1187,10 +1187,9 @@ static void CallJsFunction(const v8::FunctionCallbackInfo<v8::Value>& info) {
 //    55     1        bar #16 5
 //    54    54          foo #16 6
 TEST(JsNativeJsSample) {
-  const char* extensions[] = { "v8/profiler" };
-  v8::ExtensionConfiguration config(1, extensions);
-  LocalContext env(&config);
-  v8::HandleScope scope(env->GetIsolate());
+  v8::HandleScope scope(CcTest::isolate());
+  v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION);
+  v8::Context::Scope context_scope(env);
 
   v8::Local<v8::FunctionTemplate> func_template = v8::FunctionTemplate::New(
       env->GetIsolate(), CallJsFunction);
@@ -1272,10 +1271,9 @@ static const char* js_native_js_runtime_js_test_source =
 //    51    51          foo #16 6
 //     2     2    (program) #0 2
 TEST(JsNativeJsRuntimeJsSample) {
-  const char* extensions[] = { "v8/profiler" };
-  v8::ExtensionConfiguration config(1, extensions);
-  LocalContext env(&config);
-  v8::HandleScope scope(env->GetIsolate());
+  v8::HandleScope scope(CcTest::isolate());
+  v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION);
+  v8::Context::Scope context_scope(env);
 
   v8::Local<v8::FunctionTemplate> func_template = v8::FunctionTemplate::New(
       env->GetIsolate(), CallJsFunction);
@@ -1361,10 +1359,9 @@ static const char* js_native1_js_native2_js_test_source =
 //    54    54            foo #16 7
 //     2     2    (program) #0 2
 TEST(JsNative1JsNative2JsSample) {
-  const char* extensions[] = { "v8/profiler" };
-  v8::ExtensionConfiguration config(1, extensions);
-  LocalContext env(&config);
-  v8::HandleScope scope(env->GetIsolate());
+  v8::HandleScope scope(CcTest::isolate());
+  v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION);
+  v8::Context::Scope context_scope(env);
 
   v8::Local<v8::FunctionTemplate> func_template = v8::FunctionTemplate::New(
       env->GetIsolate(), CallJsFunction);
@@ -1494,10 +1491,9 @@ static void CheckFunctionDetails(v8::Isolate* isolate,
 
 
 TEST(FunctionDetails) {
-  const char* extensions[] = { "v8/profiler" };
-  v8::ExtensionConfiguration config(1, extensions);
-  LocalContext env(&config);
-  v8::HandleScope handleScope(env->GetIsolate());
+  v8::HandleScope scope(CcTest::isolate());
+  v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION);
+  v8::Context::Scope context_scope(env);
 
   v8::Handle<v8::Script> script_a = v8::Script::Compile(
       v8::String::NewFromUtf8(
@@ -1514,7 +1510,7 @@ TEST(FunctionDetails) {
           "stopProfiling();\n"),
       v8::String::NewFromUtf8(env->GetIsolate(), "script_b"));
   script_b->Run();
-  const v8::CpuProfile* profile = ProfilerExtension::last_profile;
+  const v8::CpuProfile* profile = i::ProfilerExtension::last_profile;
   const v8::CpuProfileNode* current = profile->GetTopDownRoot();
   reinterpret_cast<ProfileNode*>(
       const_cast<v8::CpuProfileNode*>(current))->Print(0);
@@ -1543,11 +1539,10 @@ TEST(FunctionDetails) {
 
 
 TEST(DontStopOnFinishedProfileDelete) {
-  const char* extensions[] = { "v8/profiler" };
-  v8::ExtensionConfiguration config(1, extensions);
-  LocalContext env(&config);
+  v8::HandleScope scope(CcTest::isolate());
+  v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION);
+  v8::Context::Scope context_scope(env);
   v8::Isolate* isolate = env->GetIsolate();
-  v8::HandleScope handleScope(isolate);
 
   v8::CpuProfiler* profiler = env->GetIsolate()->GetCpuProfiler();
   i::CpuProfiler* iprofiler = reinterpret_cast<i::CpuProfiler*>(profiler);
index 8a02399..754d9a5 100644 (file)
@@ -2070,57 +2070,6 @@ TEST(JSFunctionHasCodeLink) {
 }
 
 
-
-class HeapProfilerExtension : public v8::Extension {
- public:
-  static const char* kName;
-  HeapProfilerExtension() : v8::Extension(kName, kSource) { }
-  virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate(
-      v8::Isolate* isolate,
-      v8::Handle<v8::String> name);
-  static void FindUntrackedObjects(
-      const v8::FunctionCallbackInfo<v8::Value>& args);
- private:
-  static const char* kSource;
-};
-
-const char* HeapProfilerExtension::kName = "v8/heap-profiler";
-
-
-const char* HeapProfilerExtension::kSource =
-    "native function findUntrackedObjects();";
-
-
-v8::Handle<v8::FunctionTemplate>
-HeapProfilerExtension::GetNativeFunctionTemplate(v8::Isolate* isolate,
-                                                 v8::Handle<v8::String> name) {
-  if (name->Equals(v8::String::NewFromUtf8(isolate, "findUntrackedObjects"))) {
-    return v8::FunctionTemplate::New(
-        isolate,
-        HeapProfilerExtension::FindUntrackedObjects);
-  } else {
-    CHECK(false);
-    return v8::Handle<v8::FunctionTemplate>();
-  }
-}
-
-
-void HeapProfilerExtension::FindUntrackedObjects(
-    const v8::FunctionCallbackInfo<v8::Value>& args) {
-  i::HeapProfiler* heap_profiler =
-      reinterpret_cast<i::HeapProfiler*>(args.GetIsolate()->GetHeapProfiler());
-  int untracked_objects =
-      heap_profiler->heap_object_map()->FindUntrackedObjects();
-  args.GetReturnValue().Set(untracked_objects);
-  CHECK_EQ(0, untracked_objects);
-}
-
-
-static HeapProfilerExtension kHeapProfilerExtension;
-v8::DeclareExtension kHeapProfilerExtensionDeclaration(
-    &kHeapProfilerExtension);
-
-
 static const v8::HeapGraphNode* GetNodeByPath(const v8::HeapSnapshot* snapshot,
                                               const char* path[],
                                               int depth) {
index c3752ff..5b6858e 100644 (file)
@@ -38,6 +38,7 @@
 #include "isolate.h"
 #include "log.h"
 #include "sampler.h"
+#include "trace-extension.h"
 #include "vm-state-inl.h"
 
 using v8::Function;
@@ -52,137 +53,9 @@ using v8::internal::Address;
 using v8::internal::Handle;
 using v8::internal::Isolate;
 using v8::internal::JSFunction;
-using v8::internal::RegisterState;
 using v8::internal::TickSample;
 
 
-static struct {
-  TickSample* sample;
-} trace_env = { NULL };
-
-
-static void InitTraceEnv(TickSample* sample) {
-  trace_env.sample = sample;
-}
-
-
-static void DoTrace(Address fp) {
-  RegisterState regs;
-  regs.fp = fp;
-  // sp is only used to define stack high bound
-  regs.sp =
-      reinterpret_cast<Address>(trace_env.sample) - 10240;
-  trace_env.sample->Init(CcTest::i_isolate(), regs);
-}
-
-
-// Hide c_entry_fp to emulate situation when sampling is done while
-// pure JS code is being executed
-static void DoTraceHideCEntryFPAddress(Address fp) {
-  v8::internal::Address saved_c_frame_fp =
-      *(CcTest::i_isolate()->c_entry_fp_address());
-  CHECK(saved_c_frame_fp);
-  *(CcTest::i_isolate()->c_entry_fp_address()) = 0;
-  DoTrace(fp);
-  *(CcTest::i_isolate()->c_entry_fp_address()) = saved_c_frame_fp;
-}
-
-
-// --- T r a c e   E x t e n s i o n ---
-
-class TraceExtension : public v8::Extension {
- public:
-  TraceExtension() : v8::Extension("v8/trace", kSource) { }
-  virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate(
-      v8::Isolate* isolate,
-      v8::Handle<String> name);
-  static void Trace(const v8::FunctionCallbackInfo<v8::Value>& args);
-  static void JSTrace(const v8::FunctionCallbackInfo<v8::Value>& args);
-  static void JSEntrySP(const v8::FunctionCallbackInfo<v8::Value>& args);
-  static void JSEntrySPLevel2(const v8::FunctionCallbackInfo<v8::Value>& args);
- private:
-  static Address GetFP(const v8::FunctionCallbackInfo<v8::Value>& args);
-  static const char* kSource;
-};
-
-
-const char* TraceExtension::kSource =
-    "native function trace();"
-    "native function js_trace();"
-    "native function js_entry_sp();"
-    "native function js_entry_sp_level2();";
-
-v8::Handle<v8::FunctionTemplate> TraceExtension::GetNativeFunctionTemplate(
-    v8::Isolate* isolate, v8::Handle<String> name) {
-  if (name->Equals(String::NewFromUtf8(isolate, "trace"))) {
-    return v8::FunctionTemplate::New(isolate, TraceExtension::Trace);
-  } else if (name->Equals(
-                 String::NewFromUtf8(isolate, "js_trace"))) {
-    return v8::FunctionTemplate::New(isolate, TraceExtension::JSTrace);
-  } else if (name->Equals(String::NewFromUtf8(isolate, "js_entry_sp"))) {
-    return v8::FunctionTemplate::New(isolate, TraceExtension::JSEntrySP);
-  } else if (name->Equals(String::NewFromUtf8(isolate, "js_entry_sp_level2"))) {
-    return v8::FunctionTemplate::New(isolate, TraceExtension::JSEntrySPLevel2);
-  } else {
-    CHECK(false);
-    return v8::Handle<v8::FunctionTemplate>();
-  }
-}
-
-
-Address TraceExtension::GetFP(const v8::FunctionCallbackInfo<v8::Value>& args) {
-  // Convert frame pointer from encoding as smis in the arguments to a pointer.
-  CHECK_EQ(2, args.Length());  // Ignore second argument on 32-bit platform.
-#if defined(V8_HOST_ARCH_32_BIT)
-  Address fp = *reinterpret_cast<Address*>(*args[0]);
-#elif defined(V8_HOST_ARCH_64_BIT)
-  int64_t low_bits = *reinterpret_cast<uint64_t*>(*args[0]) >> 32;
-  int64_t high_bits = *reinterpret_cast<uint64_t*>(*args[1]);
-  Address fp = reinterpret_cast<Address>(high_bits | low_bits);
-#else
-#error Host architecture is neither 32-bit nor 64-bit.
-#endif
-  printf("Trace: %p\n", fp);
-  return fp;
-}
-
-
-void TraceExtension::Trace(const v8::FunctionCallbackInfo<v8::Value>& args) {
-  DoTrace(GetFP(args));
-}
-
-
-void TraceExtension::JSTrace(const v8::FunctionCallbackInfo<v8::Value>& args) {
-  DoTraceHideCEntryFPAddress(GetFP(args));
-}
-
-
-static Address GetJsEntrySp() {
-  CHECK_NE(NULL, CcTest::i_isolate()->thread_local_top());
-  return CcTest::i_isolate()->js_entry_sp();
-}
-
-
-void TraceExtension::JSEntrySP(
-    const v8::FunctionCallbackInfo<v8::Value>& args) {
-  CHECK_NE(0, GetJsEntrySp());
-}
-
-
-void TraceExtension::JSEntrySPLevel2(
-    const v8::FunctionCallbackInfo<v8::Value>& args) {
-  v8::HandleScope scope(args.GetIsolate());
-  const Address js_entry_sp = GetJsEntrySp();
-  CHECK_NE(0, js_entry_sp);
-  CompileRun("js_entry_sp();");
-  CHECK_EQ(js_entry_sp, GetJsEntrySp());
-}
-
-
-static TraceExtension kTraceExtension;
-v8::DeclareExtension kTraceExtensionDeclaration(&kTraceExtension);
-
-
 static bool IsAddressWithinFuncCode(JSFunction* function, Address addr) {
   i::Code* code = function->code();
   return code->contains(addr);
@@ -271,7 +144,7 @@ TEST(CFromJSStackTrace) {
   i::FLAG_use_inlining = false;
 
   TickSample sample;
-  InitTraceEnv(&sample);
+  i::TraceExtension::InitTraceEnv(&sample);
 
   v8::HandleScope scope(CcTest::isolate());
   v8::Local<v8::Context> context = CcTest::NewContext(TRACE_EXTENSION);
@@ -296,7 +169,7 @@ TEST(CFromJSStackTrace) {
   //           TickSample::Trace
 
   CHECK(sample.has_external_callback);
-  CHECK_EQ(FUNCTION_ADDR(TraceExtension::Trace), sample.external_callback);
+  CHECK_EQ(FUNCTION_ADDR(i::TraceExtension::Trace), sample.external_callback);
 
   // Stack tracing will start from the first JS function, i.e. "JSFuncDoTrace"
   int base = 0;
@@ -319,7 +192,7 @@ TEST(PureJSStackTrace) {
   i::FLAG_use_inlining = false;
 
   TickSample sample;
-  InitTraceEnv(&sample);
+  i::TraceExtension::InitTraceEnv(&sample);
 
   v8::HandleScope scope(CcTest::isolate());
   v8::Local<v8::Context> context = CcTest::NewContext(TRACE_EXTENSION);
@@ -349,7 +222,7 @@ TEST(PureJSStackTrace) {
   //
 
   CHECK(sample.has_external_callback);
-  CHECK_EQ(FUNCTION_ADDR(TraceExtension::JSTrace), sample.external_callback);
+  CHECK_EQ(FUNCTION_ADDR(i::TraceExtension::JSTrace), sample.external_callback);
 
   // Stack sampling will start from the caller of JSFuncDoTrace, i.e. "JSTrace"
   int base = 0;
@@ -371,7 +244,7 @@ static void CFuncDoTrace(byte dummy_parameter) {
 #else
 #error Unexpected platform.
 #endif
-  DoTrace(fp);
+  i::TraceExtension::DoTrace(fp);
 }
 
 
@@ -390,7 +263,7 @@ static int CFunc(int depth) {
 // get any meaningful info here.
 TEST(PureCStackTrace) {
   TickSample sample;
-  InitTraceEnv(&sample);
+  i::TraceExtension::InitTraceEnv(&sample);
   v8::HandleScope scope(CcTest::isolate());
   v8::Local<v8::Context> context = CcTest::NewContext(TRACE_EXTENSION);
   v8::Context::Scope context_scope(context);
@@ -403,11 +276,11 @@ TEST(JsEntrySp) {
   v8::HandleScope scope(CcTest::isolate());
   v8::Local<v8::Context> context = CcTest::NewContext(TRACE_EXTENSION);
   v8::Context::Scope context_scope(context);
-  CHECK_EQ(0, GetJsEntrySp());
+  CHECK_EQ(0, i::TraceExtension::GetJsEntrySp());
   CompileRun("a = 1; b = a + 1;");
-  CHECK_EQ(0, GetJsEntrySp());
+  CHECK_EQ(0, i::TraceExtension::GetJsEntrySp());
   CompileRun("js_entry_sp();");
-  CHECK_EQ(0, GetJsEntrySp());
+  CHECK_EQ(0, i::TraceExtension::GetJsEntrySp());
   CompileRun("js_entry_sp_level2();");
-  CHECK_EQ(0, GetJsEntrySp());
+  CHECK_EQ(0, i::TraceExtension::GetJsEntrySp());
 }
index 0cd30ef..e06063d 100644 (file)
@@ -552,12 +552,9 @@ TEST(RecordStackTraceAtStartProfiling) {
   // don't appear in the stack trace.
   i::FLAG_use_inlining = false;
 
-  v8::Isolate* isolate = CcTest::isolate();
-  v8::HandleScope scope(isolate);
-  const char* extensions[] = { "v8/profiler" };
-  v8::ExtensionConfiguration config(1, extensions);
-  v8::Local<v8::Context> context = v8::Context::New(isolate, &config);
-  context->Enter();
+  v8::HandleScope scope(CcTest::isolate());
+  v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION);
+  v8::Context::Scope context_scope(env);
 
   CpuProfiler* profiler = CcTest::i_isolate()->cpu_profiler();
   CHECK_EQ(0, profiler->GetProfilesCount());
@@ -630,10 +627,9 @@ TEST(ProfileNodeScriptId) {
   // don't appear in the stack trace.
   i::FLAG_use_inlining = false;
 
-  const char* extensions[] = { "v8/profiler" };
-  v8::ExtensionConfiguration config(1, extensions);
-  LocalContext env(&config);
-  v8::HandleScope hs(env->GetIsolate());
+  v8::HandleScope scope(CcTest::isolate());
+  v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION);
+  v8::Context::Scope context_scope(env);
 
   v8::CpuProfiler* profiler = env->GetIsolate()->GetCpuProfiler();
   i::CpuProfiler* iprofiler = reinterpret_cast<i::CpuProfiler*>(profiler);
@@ -648,7 +644,7 @@ TEST(ProfileNodeScriptId) {
                                                   "stopProfiling();\n"));
   script_b->Run();
   CHECK_EQ(1, iprofiler->GetProfilesCount());
-  const v8::CpuProfile* profile = ProfilerExtension::last_profile;
+  const v8::CpuProfile* profile = i::ProfilerExtension::last_profile;
   const v8::CpuProfileNode* current = profile->GetTopDownRoot();
   reinterpret_cast<ProfileNode*>(
       const_cast<v8::CpuProfileNode*>(current))->Print(0);
@@ -733,10 +729,9 @@ TEST(LineNumber) {
 
 
 TEST(BailoutReason) {
-  const char* extensions[] = { "v8/profiler" };
-  v8::ExtensionConfiguration config(1, extensions);
-  LocalContext env(&config);
-  v8::HandleScope hs(env->GetIsolate());
+  v8::HandleScope scope(CcTest::isolate());
+  v8::Local<v8::Context> env = CcTest::NewContext(PROFILER_EXTENSION);
+  v8::Context::Scope context_scope(env);
 
   v8::CpuProfiler* profiler = env->GetIsolate()->GetCpuProfiler();
   i::CpuProfiler* iprofiler = reinterpret_cast<i::CpuProfiler*>(profiler);
@@ -757,7 +752,7 @@ TEST(BailoutReason) {
                                                   "stopProfiling();"));
   script->Run();
   CHECK_EQ(1, iprofiler->GetProfilesCount());
-  const v8::CpuProfile* profile = ProfilerExtension::last_profile;
+  const v8::CpuProfile* profile = i::ProfilerExtension::last_profile;
   CHECK(profile);
   const v8::CpuProfileNode* current = profile->GetTopDownRoot();
   reinterpret_cast<ProfileNode*>(
diff --git a/test/cctest/trace-extension.cc b/test/cctest/trace-extension.cc
new file mode 100644 (file)
index 0000000..2da6813
--- /dev/null
@@ -0,0 +1,142 @@
+// Copyright 2014 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 "trace-extension.h"
+
+#include "cctest.h"
+#include "sampler.h"
+
+namespace v8 {
+namespace internal {
+
+const char* TraceExtension::kSource =
+    "native function trace();"
+    "native function js_trace();"
+    "native function js_entry_sp();"
+    "native function js_entry_sp_level2();";
+
+
+v8::Handle<v8::FunctionTemplate> TraceExtension::GetNativeFunctionTemplate(
+    v8::Isolate* isolate, v8::Handle<v8::String> name) {
+  if (name->Equals(v8::String::NewFromUtf8(isolate, "trace"))) {
+    return v8::FunctionTemplate::New(isolate, TraceExtension::Trace);
+  } else if (name->Equals(v8::String::NewFromUtf8(isolate, "js_trace"))) {
+    return v8::FunctionTemplate::New(isolate, TraceExtension::JSTrace);
+  } else if (name->Equals(v8::String::NewFromUtf8(isolate, "js_entry_sp"))) {
+    return v8::FunctionTemplate::New(isolate, TraceExtension::JSEntrySP);
+  } else if (name->Equals(v8::String::NewFromUtf8(isolate,
+                                                  "js_entry_sp_level2"))) {
+    return v8::FunctionTemplate::New(isolate, TraceExtension::JSEntrySPLevel2);
+  } else {
+    CHECK(false);
+    return v8::Handle<v8::FunctionTemplate>();
+  }
+}
+
+
+Address TraceExtension::GetFP(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  // Convert frame pointer from encoding as smis in the arguments to a pointer.
+  CHECK_EQ(2, args.Length());  // Ignore second argument on 32-bit platform.
+#if defined(V8_HOST_ARCH_32_BIT)
+  Address fp = *reinterpret_cast<Address*>(*args[0]);
+#elif defined(V8_HOST_ARCH_64_BIT)
+  int64_t low_bits = *reinterpret_cast<uint64_t*>(*args[0]) >> 32;
+  int64_t high_bits = *reinterpret_cast<uint64_t*>(*args[1]);
+  Address fp = reinterpret_cast<Address>(high_bits | low_bits);
+#else
+#error Host architecture is neither 32-bit nor 64-bit.
+#endif
+  printf("Trace: %p\n", fp);
+  return fp;
+}
+
+
+static struct {
+  TickSample* sample;
+} trace_env = { NULL };
+
+
+void TraceExtension::InitTraceEnv(TickSample* sample) {
+  trace_env.sample = sample;
+}
+
+
+void TraceExtension::DoTrace(Address fp) {
+  RegisterState regs;
+  regs.fp = fp;
+  // sp is only used to define stack high bound
+  regs.sp =
+      reinterpret_cast<Address>(trace_env.sample) - 10240;
+  trace_env.sample->Init(CcTest::i_isolate(), regs);
+}
+
+
+void TraceExtension::Trace(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  DoTrace(GetFP(args));
+}
+
+
+// Hide c_entry_fp to emulate situation when sampling is done while
+// pure JS code is being executed
+static void DoTraceHideCEntryFPAddress(Address fp) {
+  v8::internal::Address saved_c_frame_fp =
+      *(CcTest::i_isolate()->c_entry_fp_address());
+  CHECK(saved_c_frame_fp);
+  *(CcTest::i_isolate()->c_entry_fp_address()) = 0;
+  i::TraceExtension::DoTrace(fp);
+  *(CcTest::i_isolate()->c_entry_fp_address()) = saved_c_frame_fp;
+}
+
+
+void TraceExtension::JSTrace(const v8::FunctionCallbackInfo<v8::Value>& args) {
+  DoTraceHideCEntryFPAddress(GetFP(args));
+}
+
+
+Address TraceExtension::GetJsEntrySp() {
+  CHECK_NE(NULL, CcTest::i_isolate()->thread_local_top());
+  return CcTest::i_isolate()->js_entry_sp();
+}
+
+
+void TraceExtension::JSEntrySP(
+    const v8::FunctionCallbackInfo<v8::Value>& args) {
+  CHECK_NE(0, GetJsEntrySp());
+}
+
+
+void TraceExtension::JSEntrySPLevel2(
+    const v8::FunctionCallbackInfo<v8::Value>& args) {
+  v8::HandleScope scope(args.GetIsolate());
+  const Address js_entry_sp = GetJsEntrySp();
+  CHECK_NE(0, js_entry_sp);
+  CompileRun("js_entry_sp();");
+  CHECK_EQ(js_entry_sp, GetJsEntrySp());
+}
+
+
+} }  // namespace v8::internal
diff --git a/test/cctest/trace-extension.h b/test/cctest/trace-extension.h
new file mode 100644 (file)
index 0000000..b80b3d4
--- /dev/null
@@ -0,0 +1,56 @@
+// Copyright 2014 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_TEST_CCTEST_TRACE_EXTENSION_H_
+#define V8_TEST_CCTEST_TRACE_EXTENSION_H_
+
+#include "v8.h"
+
+namespace v8 {
+namespace internal {
+
+class TraceExtension : public v8::Extension {
+ public:
+  TraceExtension() : v8::Extension("v8/trace", kSource) { }
+  virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate(
+      v8::Isolate* isolate,
+      v8::Handle<v8::String> name);
+  static void Trace(const v8::FunctionCallbackInfo<v8::Value>& args);
+  static void JSTrace(const v8::FunctionCallbackInfo<v8::Value>& args);
+  static void JSEntrySP(const v8::FunctionCallbackInfo<v8::Value>& args);
+  static void JSEntrySPLevel2(const v8::FunctionCallbackInfo<v8::Value>& args);
+  static Address GetJsEntrySp();
+  static void InitTraceEnv(TickSample* sample);
+  static void DoTrace(Address fp);
+ private:
+  static Address GetFP(const v8::FunctionCallbackInfo<v8::Value>& args);
+  static const char* kSource;
+};
+
+} }  // namespace v8::internal
+
+#endif