Revision: 4349
Author: [email protected]
Date: Tue Apr  6 07:54:20 2010
Log: C++ profiler: publish the new API, make compatible with WebKit / Chromium.

I succeeded at connecting the new implementation to Chromium, this
commit includes required (although, not all) adjustments.

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

Added:
 /branches/bleeding_edge/include/v8-profiler.h
Modified:
 /branches/bleeding_edge/src/api.cc
 /branches/bleeding_edge/src/cpu-profiler.cc
 /branches/bleeding_edge/src/cpu-profiler.h
 /branches/bleeding_edge/src/flag-definitions.h
 /branches/bleeding_edge/src/platform-linux.cc
 /branches/bleeding_edge/src/profile-generator-inl.h
 /branches/bleeding_edge/src/profile-generator.cc
 /branches/bleeding_edge/src/profile-generator.h

=======================================
--- /dev/null
+++ /branches/bleeding_edge/include/v8-profiler.h       Tue Apr  6 07:54:20 2010
@@ -0,0 +1,176 @@
+// Copyright 2010 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_V8_PROFILER_H_
+#define V8_V8_PROFILER_H_
+
+#include "v8.h"
+
+#ifdef _WIN32
+// Setup for Windows DLL export/import. See v8.h in this directory for
+// information on how to build/use V8 as a DLL.
+#if defined(BUILDING_V8_SHARED) && defined(USING_V8_SHARED)
+#error both BUILDING_V8_SHARED and USING_V8_SHARED are set - please check the\
+  build configuration to ensure that at most one of these is set
+#endif
+
+#ifdef BUILDING_V8_SHARED
+#define V8EXPORT __declspec(dllexport)
+#elif USING_V8_SHARED
+#define V8EXPORT __declspec(dllimport)
+#else
+#define V8EXPORT
+#endif
+
+#else  // _WIN32
+
+// Setup for Linux shared library export. See v8.h in this directory for
+// information on how to build/use V8 as shared library.
+#if defined(__GNUC__) && (__GNUC__ >= 4) && defined(V8_SHARED)
+#define V8EXPORT __attribute__ ((visibility("default")))
+#else  // defined(__GNUC__) && (__GNUC__ >= 4)
+#define V8EXPORT
+#endif  // defined(__GNUC__) && (__GNUC__ >= 4)
+
+#endif  // _WIN32
+
+
+/**
+ * Profiler support for the V8 JavaScript engine.
+ */
+namespace v8 {
+
+
+/**
+ * CpuProfileNode represents a node in a call graph.
+ */
+class V8EXPORT CpuProfileNode {
+ public:
+  /** Returns function name (empty string for anonymous functions.) */
+  Handle<String> GetFunctionName() const;
+
+ /** Returns resource name for script from where the function originates. */
+  Handle<String> GetScriptResourceName() const;
+
+  /**
+ * Returns the number, 1-based, of the line where the function originates.
+   * kNoLineNumberInfo if no line number information is available.
+   */
+  int GetLineNumber() const;
+
+  /**
+   * Returns total (self + children) execution time of the function,
+   * in milliseconds, estimated by samples count.
+   */
+  double GetTotalTime() const;
+
+  /**
+   * Returns self execution time of the function, in milliseconds,
+   * estimated by samples count.
+   */
+  double GetSelfTime() const;
+
+  /** Returns the count of samples where function exists. */
+  double GetTotalSamplesCount() const;
+
+ /** Returns the count of samples where function was currently executing. */
+  double GetSelfSamplesCount() const;
+
+  /** Returns function entry UID. */
+  unsigned GetCallUid() const;
+
+  /** Returns child nodes count of the node. */
+  int GetChildrenCount() const;
+
+  /** Retrieves a child node by index. */
+  const CpuProfileNode* GetChild(int index) const;
+
+  static const int kNoLineNumberInfo = 0;
+};
+
+
+/**
+ * CpuProfile contains a CPU profile in a form of two call trees:
+ *  - top-down (from main() down to functions that do all the work);
+ *  - bottom-up call graph (in backward direction).
+ */
+class V8EXPORT CpuProfile {
+ public:
+  /** Returns CPU profile UID (assigned by the profiler.) */
+  unsigned GetUid() const;
+
+  /** Returns CPU profile title. */
+  Handle<String> GetTitle() const;
+
+  /** Returns the root node of the bottom up call tree. */
+  const CpuProfileNode* GetBottomUpRoot() const;
+
+  /** Returns the root node of the top down call tree. */
+  const CpuProfileNode* GetTopDownRoot() const;
+};
+
+
+/**
+ * Interface for controlling CPU profiling.
+ */
+class V8EXPORT CpuProfiler {
+ public:
+  /**
+   * Returns the number of profiles collected (doesn't include
+   * profiles that are being collected at the moment of call.)
+   */
+  static int GetProfilesCount();
+
+  /** Returns a profile by index. */
+  static const CpuProfile* GetProfile(int index);
+
+  /** Returns a profile by uid. */
+  static const CpuProfile* FindProfile(unsigned uid);
+
+  /**
+   * Starts collecting CPU profile. Title may be an empty string. It
+   * is allowed to have several profiles being collected at
+   * once. Attempts to start collecting several profiles with the same
+   * title are silently ignored.
+   */
+  static void StartProfiling(Handle<String> title);
+
+  /**
+   * Stops collecting CPU profile with a given title and returns it.
+   * If the title given is empty, finishes the last profile started.
+   */
+  static const CpuProfile* StopProfiling(Handle<String> title);
+};
+
+
+}  // namespace v8
+
+
+#undef V8EXPORT
+
+
+#endif  // V8_V8_PROFILER_H_
=======================================
--- /branches/bleeding_edge/src/api.cc  Thu Mar 25 07:07:17 2010
+++ /branches/bleeding_edge/src/api.cc  Tue Apr  6 07:54:20 2010
@@ -36,6 +36,7 @@
 #include "global-handles.h"
 #include "messages.h"
 #include "platform.h"
+#include "profile-generator-inl.h"
 #include "serialize.h"
 #include "snapshot.h"
 #include "top.h"
@@ -43,6 +44,7 @@
 #include "v8threads.h"
 #include "version.h"

+#include "../include/v8-profiler.h"

 #define LOG_API(expr) LOG(ApiEntryCall(expr))

@@ -3997,6 +3999,131 @@

 #endif  // ENABLE_DEBUGGER_SUPPORT

+
+#ifdef ENABLE_CPP_PROFILES_PROCESSOR
+
+Handle<String> CpuProfileNode::GetFunctionName() const {
+  IsDeadCheck("v8::CpuProfileNode::GetFunctionName");
+ const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
+  const i::CodeEntry* entry = node->entry();
+  if (!entry->has_name_prefix()) {
+    return Handle<String>(ToApi<String>(
+        i::Factory::LookupAsciiSymbol(entry->name())));
+  } else {
+    return Handle<String>(ToApi<String>(i::Factory::NewConsString(
+        i::Factory::LookupAsciiSymbol(entry->name_prefix()),
+        i::Factory::LookupAsciiSymbol(entry->name()))));
+  }
+}
+
+
+Handle<String> CpuProfileNode::GetScriptResourceName() const {
+  IsDeadCheck("v8::CpuProfileNode::GetScriptResourceName");
+ const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
+  return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
+      node->entry()->resource_name())));
+}
+
+
+int CpuProfileNode::GetLineNumber() const {
+  IsDeadCheck("v8::CpuProfileNode::GetLineNumber");
+ return reinterpret_cast<const i::ProfileNode*>(this)->entry()->line_number();
+}
+
+
+double CpuProfileNode::GetTotalSamplesCount() const {
+  IsDeadCheck("v8::CpuProfileNode::GetTotalSamplesCount");
+  return reinterpret_cast<const i::ProfileNode*>(this)->total_ticks();
+}
+
+
+double CpuProfileNode::GetSelfSamplesCount() const {
+  IsDeadCheck("v8::CpuProfileNode::GetSelfSamplesCount");
+  return reinterpret_cast<const i::ProfileNode*>(this)->self_ticks();
+}
+
+
+unsigned CpuProfileNode::GetCallUid() const {
+  IsDeadCheck("v8::CpuProfileNode::GetCallUid");
+ return reinterpret_cast<const i::ProfileNode*>(this)->entry()->call_uid();
+}
+
+
+int CpuProfileNode::GetChildrenCount() const {
+  IsDeadCheck("v8::CpuProfileNode::GetChildrenCount");
+ return reinterpret_cast<const i::ProfileNode*>(this)->children()->length();
+}
+
+
+const CpuProfileNode* CpuProfileNode::GetChild(int index) const {
+  IsDeadCheck("v8::CpuProfileNode::GetChild");
+  const i::ProfileNode* child =
+      reinterpret_cast<const i::ProfileNode*>(this)->children()->at(index);
+  return reinterpret_cast<const CpuProfileNode*>(child);
+}
+
+
+unsigned CpuProfile::GetUid() const {
+  IsDeadCheck("v8::CpuProfile::GetUid");
+  return reinterpret_cast<const i::CpuProfile*>(this)->uid();
+}
+
+
+Handle<String> CpuProfile::GetTitle() const {
+  IsDeadCheck("v8::CpuProfile::GetTitle");
+ const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
+  return Handle<String>(ToApi<String>(i::Factory::LookupAsciiSymbol(
+      profile->title())));
+}
+
+
+const CpuProfileNode* CpuProfile::GetBottomUpRoot() const {
+  IsDeadCheck("v8::CpuProfile::GetBottomUpRoot");
+ const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this); + return reinterpret_cast<const CpuProfileNode*>(profile->bottom_up()->root());
+}
+
+
+const CpuProfileNode* CpuProfile::GetTopDownRoot() const {
+  IsDeadCheck("v8::CpuProfile::GetTopDownRoot");
+ const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this); + return reinterpret_cast<const CpuProfileNode*>(profile->top_down()->root());
+}
+
+
+int CpuProfiler::GetProfilesCount() {
+  IsDeadCheck("v8::CpuProfiler::GetProfilesCount");
+  return i::CpuProfiler::GetProfilesCount();
+}
+
+
+const CpuProfile* CpuProfiler::GetProfile(int index) {
+  IsDeadCheck("v8::CpuProfiler::GetProfile");
+ return reinterpret_cast<const CpuProfile*>(i::CpuProfiler::GetProfile(index));
+}
+
+
+const CpuProfile* CpuProfiler::FindProfile(unsigned uid) {
+  IsDeadCheck("v8::CpuProfiler::FindProfile");
+ return reinterpret_cast<const CpuProfile*>(i::CpuProfiler::FindProfile(uid));
+}
+
+
+void CpuProfiler::StartProfiling(Handle<String> title) {
+  IsDeadCheck("v8::CpuProfiler::StartProfiling");
+  i::CpuProfiler::StartProfiling(*Utils::OpenHandle(*title));
+}
+
+
+const CpuProfile* CpuProfiler::StopProfiling(Handle<String> title) {
+  IsDeadCheck("v8::CpuProfiler::StopProfiling");
+  return reinterpret_cast<const CpuProfile*>(
+      i::CpuProfiler::StopProfiling(*Utils::OpenHandle(*title)));
+}
+
+#endif  // ENABLE_CPP_PROFILES_PROCESSOR
+
+
 namespace internal {


=======================================
--- /branches/bleeding_edge/src/cpu-profiler.cc Tue Apr  6 03:36:38 2010
+++ /branches/bleeding_edge/src/cpu-profiler.cc Tue Apr  6 07:54:20 2010
@@ -33,6 +33,8 @@

 #include "log-inl.h"

+#include "../include/v8-profiler.h"
+
 namespace v8 {
 namespace internal {

@@ -154,6 +156,23 @@
 void ProfilerEventsProcessor::FunctionDeleteEvent(Address from) {
   CodeDeleteEvent(from);
 }
+
+
+void ProfilerEventsProcessor::RegExpCodeCreateEvent(
+    Logger::LogEventsAndTags tag,
+    const char* prefix,
+    String* name,
+    Address start,
+    unsigned size) {
+  CodeEventsContainer evt_rec;
+  CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
+  rec->type = CodeEventRecord::CODE_CREATION;
+  rec->order = ++enqueue_order_;
+  rec->start = start;
+  rec->entry = generator_->NewCodeEntry(tag, prefix, name);
+  rec->size = size;
+  events_buffer_.Enqueue(evt_rec);
+}


 bool ProfilerEventsProcessor::ProcessCodeEvent(unsigned* dequeue_order) {
@@ -287,7 +306,7 @@
       tag,
       name,
       Heap::empty_string(),
-      CodeEntry::kNoLineNumberInfo,
+      v8::CpuProfileNode::kNoLineNumberInfo,
       code->address(),
       code->ExecutableSize());
 }
@@ -349,11 +368,10 @@


 void CpuProfiler::RegExpCodeCreateEvent(Code* code, String* source) {
-  singleton_->processor_->CodeCreateEvent(
+  singleton_->processor_->RegExpCodeCreateEvent(
       Logger::REG_EXP_TAG,
+      "RegExp: ",
       source,
-      Heap::empty_string(),
-      CodeEntry::kNoLineNumberInfo,
       code->address(),
       code->ExecutableSize());
 }
@@ -379,14 +397,14 @@


 void CpuProfiler::StartCollectingProfile(const char* title) {
-  if (profiles_->StartProfiling(title, ++next_profile_uid_)) {
+  if (profiles_->StartProfiling(title, next_profile_uid_++)) {
     StartProcessorIfNotStarted();
   }
 }


 void CpuProfiler::StartCollectingProfile(String* title) {
-  if (profiles_->StartProfiling(title, ++next_profile_uid_)) {
+  if (profiles_->StartProfiling(title, next_profile_uid_++)) {
     StartProcessorIfNotStarted();
   }
 }
=======================================
--- /branches/bleeding_edge/src/cpu-profiler.h  Tue Apr  6 03:36:38 2010
+++ /branches/bleeding_edge/src/cpu-profiler.h  Tue Apr  6 07:54:20 2010
@@ -150,6 +150,9 @@
   void FunctionCreateEvent(Address alias, Address start);
   void FunctionMoveEvent(Address from, Address to);
   void FunctionDeleteEvent(Address from);
+  void RegExpCodeCreateEvent(Logger::LogEventsAndTags tag,
+                             const char* prefix, String* name,
+                             Address start, unsigned size);

   // Tick sample events are filled directly in the buffer of the circular
   // queue (because the structure is of fixed width, but usually not all
=======================================
--- /branches/bleeding_edge/src/flag-definitions.h      Wed Mar 24 03:32:23 2010
+++ /branches/bleeding_edge/src/flag-definitions.h      Tue Apr  6 07:54:20 2010
@@ -391,6 +391,8 @@
 DEFINE_bool(prof_lazy, false,
             "Used with --prof, only does sampling and logging"
             " when profiler is active (implies --noprof_auto).")
+DEFINE_bool(prof_browser_mode, false,
+ "Used with --prof, turns on browser-compatible mode for profiling.")
 DEFINE_bool(log_regexp, false, "Log regular expression execution.")
 DEFINE_bool(sliding_state_window, false,
             "Update sliding state window counters.")
=======================================
--- /branches/bleeding_edge/src/platform-linux.cc       Tue Apr  6 03:36:38 2010
+++ /branches/bleeding_edge/src/platform-linux.cc       Tue Apr  6 07:54:20 2010
@@ -771,13 +771,9 @@
     // Implement this on MIPS.
       UNIMPLEMENTED();
 #endif
-#ifdef ENABLE_CPP_PROFILES_PROCESSOR
-      active_sampler_->SampleStack(sample);
-#else
       if (IsVmThread()) {
         active_sampler_->SampleStack(sample);
       }
-#endif
     }
   }
 #ifndef ENABLE_CPP_PROFILES_PROCESSOR
=======================================
--- /branches/bleeding_edge/src/profile-generator-inl.h Tue Apr 6 03:36:38 2010 +++ /branches/bleeding_edge/src/profile-generator-inl.h Tue Apr 6 07:54:20 2010
@@ -40,7 +40,8 @@
                      const char* name,
                      const char* resource_name,
                      int line_number)
-    : tag_(tag),
+    : call_uid_(next_call_uid_++),
+      tag_(tag),
       name_prefix_(name_prefix),
       name_(name),
       resource_name_(resource_name),
=======================================
--- /branches/bleeding_edge/src/profile-generator.cc Tue Apr 6 03:36:38 2010 +++ /branches/bleeding_edge/src/profile-generator.cc Tue Apr 6 07:54:20 2010
@@ -31,12 +31,14 @@

 #include "profile-generator-inl.h"

+#include "../include/v8-profiler.h"
+
 namespace v8 {
 namespace internal {


 const char* CodeEntry::kEmptyNamePrefix = "";
-const int CodeEntry::kNoLineNumberInfo = -1;
+unsigned CodeEntry::next_call_uid_ = 1;


 ProfileNode* ProfileNode::FindChild(CodeEntry* entry) {
@@ -61,11 +63,14 @@


 void ProfileNode::Print(int indent) {
-  OS::Print("%5u %5u %*c %s%s\n",
+  OS::Print("%5u %5u %*c %s%s",
             total_ticks_, self_ticks_,
             indent, ' ',
-            entry_ != NULL ? entry_->name_prefix() : "",
-            entry_ != NULL ? entry_->name() : "");
+            entry_->name_prefix(),
+            entry_->name());
+  if (entry_->resource_name()[0] != '\0')
+    OS::Print(" %s:%d", entry_->resource_name(), entry_->line_number());
+  OS::Print("\n");
   for (HashMap::Entry* p = children_.Start();
        p != NULL;
        p = children_.Next(p)) {
@@ -86,6 +91,12 @@
 };

 }  // namespace
+
+
+ProfileTree::ProfileTree()
+    : root_entry_(Logger::FUNCTION_TAG, "", "(root)", "", 0),
+      root_(new ProfileNode(&root_entry_)) {
+}


 ProfileTree::~ProfileTree() {
@@ -360,7 +371,7 @@
                                                int line_number) {
   CodeEntry* entry = new CodeEntry(tag,
                                    CodeEntry::kEmptyNamePrefix,
-                                   GetName(name),
+                                   GetFunctionName(name),
                                    GetName(resource_name),
                                    line_number);
   code_entries_.Add(entry);
@@ -374,7 +385,7 @@
                                    CodeEntry::kEmptyNamePrefix,
                                    name,
                                    "",
-                                   CodeEntry::kNoLineNumberInfo);
+                                   v8::CpuProfileNode::kNoLineNumberInfo);
   code_entries_.Add(entry);
   return entry;
 }
@@ -387,7 +398,7 @@
                                    name_prefix,
                                    GetName(name),
                                    "",
-                                   CodeEntry::kNoLineNumberInfo);
+                                   v8::CpuProfileNode::kNoLineNumberInfo);
   code_entries_.Add(entry);
   return entry;
 }
@@ -399,10 +410,17 @@
                                    "args_count: ",
                                    GetName(args_count),
                                    "",
-                                   CodeEntry::kNoLineNumberInfo);
+                                   v8::CpuProfileNode::kNoLineNumberInfo);
   code_entries_.Add(entry);
   return entry;
 }
+
+
+const char* CpuProfilesCollection::GetFunctionName(String* name) {
+  const char* maybe_empty_name = GetName(name);
+  return strlen(maybe_empty_name) > 0 ?
+      maybe_empty_name : "(anonymous function)";
+}


 const char* CpuProfilesCollection::GetName(String* name) {
@@ -453,16 +471,19 @@
   }
   current_profiles_semaphore_->Signal();
 }
+


 ProfileGenerator::ProfileGenerator(CpuProfilesCollection* profiles)
-    : profiles_(profiles) {
+    : profiles_(profiles),
+      program_entry_(
+          profiles->NewCodeEntry(Logger::FUNCTION_TAG, "(program)")) {
 }


 void ProfileGenerator::RecordTickSample(const TickSample& sample) {
-  // Allocate space for stack frames + pc + function.
-  ScopedVector<CodeEntry*> entries(sample.frames_count + 2);
+  // Allocate space for stack frames + pc + function + (program).
+  ScopedVector<CodeEntry*> entries(sample.frames_count + 3);
   CodeEntry** entry = entries.start();
   *entry++ = code_map_.FindEntry(sample.pc);

@@ -486,6 +507,10 @@
        ++stack_pos) {
     *entry++ = code_map_.FindEntry(*stack_pos);
   }
+
+  // WebKit CPU profiles visualization requires "(program)" to be the
+  // topmost entry.
+  *entry++ = FLAG_prof_browser_mode ? program_entry_ : NULL;

   profiles_->AddPathToCurrentProfiles(entries);
 }
=======================================
--- /branches/bleeding_edge/src/profile-generator.h     Tue Apr  6 03:36:38 2010
+++ /branches/bleeding_edge/src/profile-generator.h     Tue Apr  6 07:54:20 2010
@@ -50,17 +50,20 @@
   INLINE(const char* name() const) { return name_; }
   INLINE(const char* resource_name() const) { return resource_name_; }
   INLINE(int line_number() const) { return line_number_; }
+  INLINE(unsigned call_uid() const) { return call_uid_; }

   static const char* kEmptyNamePrefix;
-  static const int kNoLineNumberInfo;

  private:
+  const unsigned call_uid_;
   Logger::LogEventsAndTags tag_;
   const char* name_prefix_;
   const char* name_;
   const char* resource_name_;
   int line_number_;

+  static unsigned next_call_uid_;
+
   DISALLOW_COPY_AND_ASSIGN(CodeEntry);
 };

@@ -103,7 +106,7 @@

 class ProfileTree {
  public:
-  ProfileTree() : root_(new ProfileNode(NULL)) { }
+  ProfileTree();
   ~ProfileTree();

   void AddPathFromEnd(const Vector<CodeEntry*>& path);
@@ -121,6 +124,7 @@
   template <typename Callback>
   void TraverseBreadthFirstPostOrder(Callback* callback);

+  CodeEntry root_entry_;
   ProfileNode* root_;

   DISALLOW_COPY_AND_ASSIGN(ProfileTree);
@@ -219,6 +223,7 @@
   void AddPathToCurrentProfiles(const Vector<CodeEntry*>& path);

  private:
+  const char* GetFunctionName(String* name);
   const char* GetName(String* name);
   const char* GetName(int args_count);

@@ -282,6 +287,7 @@
  private:
   CpuProfilesCollection* profiles_;
   CodeMap code_map_;
+  CodeEntry* program_entry_;

   DISALLOW_COPY_AND_ASSIGN(ProfileGenerator);
 };

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

To unsubscribe, reply using "remove me" as the subject.

Reply via email to