Revision: 16555
Author:   [email protected]
Date:     Thu Sep  5 13:20:51 2013 UTC
Log: Functions may not be optimized and we would like to know in cpu profiler what was the reason.

Current v8 implementation may disable optimization for a particular function or block it with help of dont_optimize flag. The patch propagates the reason of that to the SharedFunctionInfo where cpu profiler can get it.

SharedFunctionInfo is a heap object so I extracted 8 bits from OptsCount for handling bailout reason code.

BUG=none
TEST=test-profile-generator/BailoutReason
[email protected]

Review URL: https://codereview.chromium.org/23817003
http://code.google.com/p/v8/source/detail?r=16555

Modified:
 /branches/bleeding_edge/include/v8-profiler.h
 /branches/bleeding_edge/src/api.cc
 /branches/bleeding_edge/src/ast.cc
 /branches/bleeding_edge/src/ast.h
 /branches/bleeding_edge/src/compiler.cc
 /branches/bleeding_edge/src/cpu-profiler.cc
 /branches/bleeding_edge/src/full-codegen.cc
 /branches/bleeding_edge/src/heap.cc
 /branches/bleeding_edge/src/hydrogen.cc
 /branches/bleeding_edge/src/objects-inl.h
 /branches/bleeding_edge/src/objects.cc
 /branches/bleeding_edge/src/objects.h
 /branches/bleeding_edge/src/parser.cc
 /branches/bleeding_edge/src/profile-generator-inl.h
 /branches/bleeding_edge/src/profile-generator.cc
 /branches/bleeding_edge/src/profile-generator.h
 /branches/bleeding_edge/test/cctest/test-profile-generator.cc

=======================================
--- /branches/bleeding_edge/include/v8-profiler.h Wed Sep 4 11:55:28 2013 UTC +++ /branches/bleeding_edge/include/v8-profiler.h Thu Sep 5 13:20:51 2013 UTC
@@ -57,6 +57,11 @@
    */
   int GetLineNumber() const;

+  /** Returns bailout reason for the function
+    * if the optimization was disabled for it.
+    */
+  const char* GetBailoutReason() const;
+
   /** DEPRECATED. Please use GetHitCount instead.
     * Returns the count of samples where function was currently executing.
     */
=======================================
--- /branches/bleeding_edge/src/api.cc  Thu Sep  5 08:48:34 2013 UTC
+++ /branches/bleeding_edge/src/api.cc  Thu Sep  5 13:20:51 2013 UTC
@@ -7253,6 +7253,12 @@
 int CpuProfileNode::GetLineNumber() const {
return reinterpret_cast<const i::ProfileNode*>(this)->entry()->line_number();
 }
+
+
+const char* CpuProfileNode::GetBailoutReason() const {
+ const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
+  return node->entry()->bailout_reason();
+}


 double CpuProfileNode::GetSelfSamplesCount() const {
=======================================
--- /branches/bleeding_edge/src/ast.cc  Mon Sep  2 09:27:27 2013 UTC
+++ /branches/bleeding_edge/src/ast.cc  Thu Sep  5 13:20:51 2013 UTC
@@ -1085,7 +1085,7 @@
 #define DONT_OPTIMIZE_NODE(NodeType) \
   void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \
     increase_node_count(); \
-    add_flag(kDontOptimize); \
+    set_dont_optimize_reason(k##NodeType); \
     add_flag(kDontInline); \
     add_flag(kDontSelfOptimize); \
   }
@@ -1097,7 +1097,7 @@
 #define DONT_CACHE_NODE(NodeType) \
   void AstConstructionVisitor::Visit##NodeType(NodeType* node) { \
     increase_node_count(); \
-    add_flag(kDontOptimize); \
+    set_dont_optimize_reason(k##NodeType); \
     add_flag(kDontInline); \
     add_flag(kDontSelfOptimize); \
     add_flag(kDontCache); \
=======================================
--- /branches/bleeding_edge/src/ast.h   Tue Sep  3 15:17:51 2013 UTC
+++ /branches/bleeding_edge/src/ast.h   Thu Sep  5 13:20:51 2013 UTC
@@ -171,7 +171,6 @@

 enum AstPropertiesFlag {
   kDontInline,
-  kDontOptimize,
   kDontSelfOptimize,
   kDontSoftInline,
   kDontCache
@@ -2315,6 +2314,12 @@
   void set_ast_properties(AstProperties* ast_properties) {
     ast_properties_ = *ast_properties;
   }
+
+  bool dont_optimize() { return dont_optimize_reason_ != kNoReason; }
+  BailoutReason dont_optimize_reason() { return dont_optimize_reason_; }
+  void set_dont_optimize_reason(BailoutReason reason) {
+    dont_optimize_reason_ = reason;
+  }

  protected:
   FunctionLiteral(Isolate* isolate,
@@ -2335,6 +2340,7 @@
         scope_(scope),
         body_(body),
         inferred_name_(isolate->factory()->empty_string()),
+        dont_optimize_reason_(kNoReason),
         materialized_literal_count_(materialized_literal_count),
         expected_property_count_(expected_property_count),
         handler_count_(handler_count),
@@ -2356,6 +2362,7 @@
   ZoneList<Statement*>* body_;
   Handle<String> inferred_name_;
   AstProperties ast_properties_;
+  BailoutReason dont_optimize_reason_;

   int materialized_literal_count_;
   int expected_property_count_;
@@ -2830,9 +2837,10 @@

 class AstConstructionVisitor BASE_EMBEDDED {
  public:
-  AstConstructionVisitor() { }
+  AstConstructionVisitor() : dont_optimize_reason_(kNoReason) { }

   AstProperties* ast_properties() { return &properties_; }
+  BailoutReason dont_optimize_reason() { return dont_optimize_reason_; }

  private:
   template<class> friend class AstNodeFactory;
@@ -2845,8 +2853,12 @@

   void increase_node_count() { properties_.add_node_count(1); }
   void add_flag(AstPropertiesFlag flag) { properties_.flags()->Add(flag); }
+  void set_dont_optimize_reason(BailoutReason reason) {
+      dont_optimize_reason_ = reason;
+  }

   AstProperties properties_;
+  BailoutReason dont_optimize_reason_;
 };


=======================================
--- /branches/bleeding_edge/src/compiler.cc     Wed Sep  4 13:53:24 2013 UTC
+++ /branches/bleeding_edge/src/compiler.cc     Thu Sep  5 13:20:51 2013 UTC
@@ -230,7 +230,7 @@
   return FLAG_self_optimization &&
       FLAG_crankshaft &&
       !function()->flags()->Contains(kDontSelfOptimize) &&
-      !function()->flags()->Contains(kDontOptimize) &&
+      !function()->dont_optimize() &&
       function()->scope()->AllowsLazyCompilation() &&
       (shared_info().is_null() || !shared_info()->optimization_disabled());
 }
@@ -840,7 +840,7 @@

   // Check the function has compiled code.
   ASSERT(shared->is_compiled());
-  shared->set_dont_optimize(lit->flags()->Contains(kDontOptimize));
+  shared->set_dont_optimize_reason(lit->dont_optimize_reason());
   shared->set_dont_inline(lit->flags()->Contains(kDontInline));
   shared->set_ast_node_count(lit->ast_node_count());

@@ -1360,7 +1360,7 @@
function_info->set_has_duplicate_parameters(lit->has_duplicate_parameters());
   function_info->set_ast_node_count(lit->ast_node_count());
   function_info->set_is_function(lit->is_function());
-  function_info->set_dont_optimize(lit->flags()->Contains(kDontOptimize));
+  function_info->set_dont_optimize_reason(lit->dont_optimize_reason());
   function_info->set_dont_inline(lit->flags()->Contains(kDontInline));
   function_info->set_dont_cache(lit->flags()->Contains(kDontCache));
   function_info->set_is_generator(lit->is_generator());
=======================================
--- /branches/bleeding_edge/src/cpu-profiler.cc Thu Sep  5 12:17:17 2013 UTC
+++ /branches/bleeding_edge/src/cpu-profiler.cc Thu Sep  5 13:20:51 2013 UTC
@@ -243,6 +243,8 @@
     ASSERT(Script::cast(shared->script()));
     Script* script = Script::cast(shared->script());
     rec->entry->set_script_id(script->id()->value());
+    rec->entry->set_bailout_reason(
+        GetBailoutReason(shared->DisableOptimizationReason()));
   }
   rec->size = code->ExecutableSize();
   rec->shared = shared->address();
@@ -273,6 +275,8 @@
   rec->entry->set_script_id(script->id()->value());
   rec->size = code->ExecutableSize();
   rec->shared = shared->address();
+  rec->entry->set_bailout_reason(
+      GetBailoutReason(shared->DisableOptimizationReason()));
   processor_->Enqueue(evt_rec);
 }

=======================================
--- /branches/bleeding_edge/src/full-codegen.cc Mon Sep  2 09:27:27 2013 UTC
+++ /branches/bleeding_edge/src/full-codegen.cc Thu Sep  5 13:20:51 2013 UTC
@@ -333,7 +333,7 @@
   Code::Flags flags = Code::ComputeFlags(Code::FUNCTION);
   Handle<Code> code = CodeGenerator::MakeCodeEpilogue(&masm, flags, info);
   code->set_optimizable(info->IsOptimizable() &&
- !info->function()->flags()->Contains(kDontOptimize) &&
+                        !info->function()->dont_optimize() &&
info->function()->scope()->AllowsLazyCompilation());
   cgen.PopulateDeoptimizationData(code);
   cgen.PopulateTypeFeedbackInfo(code);
=======================================
--- /branches/bleeding_edge/src/heap.cc Thu Sep  5 08:17:57 2013 UTC
+++ /branches/bleeding_edge/src/heap.cc Thu Sep  5 13:20:51 2013 UTC
@@ -3681,7 +3681,7 @@
   share->set_function_token_position(0);
   // All compiler hints default to false or 0.
   share->set_compiler_hints(0);
-  share->set_opt_count(0);
+  share->set_opt_count_and_bailout_reason(0);

   return share;
 }
=======================================
--- /branches/bleeding_edge/src/hydrogen.cc     Thu Sep  5 12:33:14 2013 UTC
+++ /branches/bleeding_edge/src/hydrogen.cc     Thu Sep  5 13:20:51 2013 UTC
@@ -6358,7 +6358,7 @@
     return false;
   }
   AstProperties::Flags* flags(function->flags());
-  if (flags->Contains(kDontInline) || flags->Contains(kDontOptimize)) {
+  if (flags->Contains(kDontInline) || function->dont_optimize()) {
TraceInline(target, caller, "target contains unsupported syntax [late]");
     return false;
   }
=======================================
--- /branches/bleeding_edge/src/objects-inl.h   Thu Sep  5 11:27:22 2013 UTC
+++ /branches/bleeding_edge/src/objects-inl.h   Thu Sep  5 13:20:51 2013 UTC
@@ -4606,7 +4606,8 @@
               kFunctionTokenPositionOffset)
 SMI_ACCESSORS(SharedFunctionInfo, compiler_hints,
               kCompilerHintsOffset)
-SMI_ACCESSORS(SharedFunctionInfo, opt_count, kOptCountOffset)
+SMI_ACCESSORS(SharedFunctionInfo, opt_count_and_bailout_reason,
+              kOptCountAndBailoutReasonOffset)
 SMI_ACCESSORS(SharedFunctionInfo, counters, kCountersOffset)

 #else
@@ -4655,7 +4656,9 @@
                         compiler_hints,
                         kCompilerHintsOffset)

-PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo, opt_count, kOptCountOffset)
+PSEUDO_SMI_ACCESSORS_LO(SharedFunctionInfo,
+                        opt_count_and_bailout_reason,
+                        kOptCountAndBailoutReasonOffset)

 PSEUDO_SMI_ACCESSORS_HI(SharedFunctionInfo, counters, kCountersOffset)

@@ -4900,6 +4903,24 @@
 void SharedFunctionInfo::set_opt_reenable_tries(int tries) {
   set_counters(OptReenableTriesBits::update(counters(), tries));
 }
+
+
+int SharedFunctionInfo::opt_count() {
+  return OptCountBits::decode(opt_count_and_bailout_reason());
+}
+
+
+void SharedFunctionInfo::set_opt_count(int opt_count) {
+  set_opt_count_and_bailout_reason(
+      OptCountBits::update(opt_count_and_bailout_reason(), opt_count));
+}
+
+
+BailoutReason SharedFunctionInfo::DisableOptimizationReason() {
+  BailoutReason reason = static_cast<BailoutReason>(
+ DisabledOptimizationReasonBits::decode(opt_count_and_bailout_reason()));
+  return reason;
+}


 bool SharedFunctionInfo::has_deoptimization_support() {
=======================================
--- /branches/bleeding_edge/src/objects.cc      Thu Sep  5 08:48:34 2013 UTC
+++ /branches/bleeding_edge/src/objects.cc      Thu Sep  5 13:20:51 2013 UTC
@@ -32,6 +32,7 @@
 #include "arguments.h"
 #include "bootstrapper.h"
 #include "codegen.h"
+#include "cpu-profiler.h"
 #include "debug.h"
 #include "deoptimizer.h"
 #include "date.h"
@@ -40,6 +41,7 @@
 #include "full-codegen.h"
 #include "hydrogen.h"
 #include "isolate-inl.h"
+#include "log.h"
 #include "objects-inl.h"
 #include "objects-visiting.h"
 #include "objects-visiting-inl.h"
@@ -9852,12 +9854,16 @@
   // non-optimizable if optimization is disabled for the shared
   // function info.
   set_optimization_disabled(true);
+  set_bailout_reason(reason);
   // Code should be the lazy compilation stub or else unoptimized.  If the
   // latter, disable optimization for the code too.
ASSERT(code()->kind() == Code::FUNCTION || code()->kind() == Code::BUILTIN);
   if (code()->kind() == Code::FUNCTION) {
     code()->set_optimizable(false);
   }
+  PROFILE(Isolate::Current(),
+      LogExistingFunction(Handle<SharedFunctionInfo>(this),
+                          Handle<Code>(code())));
   if (FLAG_trace_opt) {
     PrintF("[disabled optimization for ");
     ShortPrint();
=======================================
--- /branches/bleeding_edge/src/objects.h       Thu Sep  5 11:27:22 2013 UTC
+++ /branches/bleeding_edge/src/objects.h       Thu Sep  5 13:20:51 2013 UTC
@@ -1121,6 +1121,7 @@
"Expected property cell in register rbx") \ V(kExpectingAlignmentForCopyBytes, \ "Expecting alignment for CopyBytes") \ + V(kExportDeclaration, "Export declaration") \ V(kExternalStringExpectedButNotFound, \ "external string expected, but not found") \ V(kFailedBailedOutLastTime, "failed/bailed out last time") \
@@ -1140,6 +1141,7 @@
V(kGlobalFunctionsMustHaveInitialMap, \ "Global functions must have initial map") \ V(kHeapNumberMapRegisterClobbered, "HeapNumberMap register clobbered") \ + V(kImportDeclaration, "Import declaration") \ V(kImproperObjectOnPrototypeChainForStore, \ "improper object on prototype chain for store") \ V(kIndexIsNegative, "Index is negative") \
@@ -1196,6 +1198,12 @@
V(kLookupVariableInCountOperation, \ "lookup variable in count operation") \ V(kMapIsNoLongerInEax, "Map is no longer in eax") \ + V(kModuleDeclaration, "Module declaration") \ + V(kModuleLiteral, "Module literal") \ + V(kModulePath, "Module path") \ + V(kModuleStatement, "Module statement") \ + V(kModuleVariable, "Module variable") \ + V(kModuleUrl, "Module url") \ V(kNoCasesLeft, "no cases left") \ V(kNoEmptyArraysHereInEmitFastAsciiArrayJoin, \ "No empty arrays here in EmitFastAsciiArrayJoin") \
@@ -1237,7 +1245,7 @@
V(kRegisterDidNotMatchExpectedRoot, "Register did not match expected root") \ V(kRegisterWasClobbered, "register was clobbered") \ V(kScopedBlock, "ScopedBlock") \ - V(kSharedFunctionInfoLiteral, "SharedFunctionInfoLiteral") \ + V(kSharedFunctionInfoLiteral, "Shared function info literal") \ V(kSmiAdditionOverflow, "Smi addition overflow") \ V(kSmiSubtractionOverflow, "Smi subtraction overflow") \ V(kStackFrameTypesMustMatch, "stack frame types must match") \
@@ -1323,7 +1331,8 @@
"we should not have an empty lexical context") \ V(kWithStatement, "WithStatement") \ V(kWrongAddressOrValuePassedToRecordWrite, \
-    "Wrong address or value passed to RecordWrite")
+ "Wrong address or value passed to RecordWrite") \
+  V(kYield, "Yield")


 #define ERROR_MESSAGES_CONSTANTS(C, T) C,
@@ -6558,6 +6567,8 @@
   // shared function info.
   void DisableOptimization(BailoutReason reason);

+  inline BailoutReason DisableOptimizationReason();
+
   // Lookup the bailout ID and ASSERT that it exists in the non-optimized
   // code, returns whether it asserted (i.e., always true if assertions are
   // disabled).
@@ -6586,6 +6597,21 @@
   // Stores deopt_count, opt_reenable_tries and ic_age as bit-fields.
   inline void set_counters(int value);
   inline int counters();
+
+  // Stores opt_count and bailout_reason as bit-fields.
+  inline void set_opt_count_and_bailout_reason(int value);
+  inline int opt_count_and_bailout_reason();
+
+  void set_bailout_reason(BailoutReason reason) {
+    set_opt_count_and_bailout_reason(
+ DisabledOptimizationReasonBits::update(opt_count_and_bailout_reason(),
+                                               reason));
+  }
+
+  void set_dont_optimize_reason(BailoutReason reason) {
+    set_bailout_reason(reason);
+    set_dont_optimize(reason != kNoReason);
+  }

   // Source size of this function.
   int SourceSize();
@@ -6653,8 +6679,10 @@
       kEndPositionOffset + kPointerSize;
   static const int kCompilerHintsOffset =
       kFunctionTokenPositionOffset + kPointerSize;
-  static const int kOptCountOffset = kCompilerHintsOffset + kPointerSize;
-  static const int kCountersOffset = kOptCountOffset + kPointerSize;
+  static const int kOptCountAndBailoutReasonOffset =
+      kCompilerHintsOffset + kPointerSize;
+  static const int kCountersOffset =
+      kOptCountAndBailoutReasonOffset + kPointerSize;

   // Total size.
   static const int kSize = kCountersOffset + kPointerSize;
@@ -6688,9 +6716,11 @@
   static const int kCompilerHintsOffset =
       kFunctionTokenPositionOffset + kIntSize;

-  static const int kOptCountOffset = kCompilerHintsOffset + kIntSize;
+  static const int kOptCountAndBailoutReasonOffset =
+      kCompilerHintsOffset + kIntSize;

-  static const int kCountersOffset = kOptCountOffset + kIntSize;
+  static const int kCountersOffset =
+      kOptCountAndBailoutReasonOffset + kIntSize;

   // Total size.
   static const int kSize = kCountersOffset + kIntSize;
@@ -6749,6 +6779,9 @@
   class OptReenableTriesBits: public BitField<int, 4, 18> {};
   class ICAgeBits: public BitField<int, 22, 8> {};

+  class OptCountBits: public BitField<int, 0, 22> {};
+  class DisabledOptimizationReasonBits: public BitField<int, 22, 8> {};
+
  private:
 #if V8_HOST_ARCH_32_BIT
   // On 32 bit platforms, compiler hints is a smi.
=======================================
--- /branches/bleeding_edge/src/parser.cc       Wed Sep  4 07:05:11 2013 UTC
+++ /branches/bleeding_edge/src/parser.cc       Thu Sep  5 13:20:51 2013 UTC
@@ -687,6 +687,8 @@
           FunctionLiteral::kNotParenthesized,
           FunctionLiteral::kNotGenerator);
       result->set_ast_properties(factory()->visitor()->ast_properties());
+      result->set_dont_optimize_reason(
+          factory()->visitor()->dont_optimize_reason());
     } else if (stack_overflow_) {
       isolate()->StackOverflow();
     }
@@ -4334,6 +4336,7 @@
       ? FunctionLiteral::kIsGenerator
       : FunctionLiteral::kNotGenerator;
   AstProperties ast_properties;
+  BailoutReason dont_optimize_reason = kNoReason;
   // Parse function body.
   { FunctionState function_state(this, scope, isolate());
     top_scope_->SetScopeName(function_name);
@@ -4593,6 +4596,7 @@
                         CHECK_OK);
     }
     ast_properties = *factory()->visitor()->ast_properties();
+    dont_optimize_reason = factory()->visitor()->dont_optimize_reason();
   }

   if (is_extended_mode()) {
@@ -4614,6 +4618,7 @@
                                     generator);
   function_literal->set_function_token_position(function_token_position);
   function_literal->set_ast_properties(&ast_properties);
+  function_literal->set_dont_optimize_reason(dont_optimize_reason);

if (fni_ != NULL && should_infer_name) fni_->AddFunction(function_literal);
   return function_literal;
=======================================
--- /branches/bleeding_edge/src/profile-generator-inl.h Tue Aug 27 15:12:04 2013 UTC +++ /branches/bleeding_edge/src/profile-generator-inl.h Thu Sep 5 13:20:51 2013 UTC
@@ -56,8 +56,8 @@
       line_number_(line_number),
       shared_id_(0),
       script_id_(v8::Script::kNoScriptId),
-      no_frame_ranges_(NULL) {
-}
+      no_frame_ranges_(NULL),
+      bailout_reason_(kEmptyBailoutReason) { }


 bool CodeEntry::is_js_function_tag(Logger::LogEventsAndTags tag) {
@@ -75,8 +75,7 @@
       entry_(entry),
       self_ticks_(0),
       children_(CodeEntriesMatch),
-      id_(tree->next_node_id()) {
-}
+      id_(tree->next_node_id()) { }


 CodeEntry* ProfileGenerator::EntryForVMState(StateTag tag) {
=======================================
--- /branches/bleeding_edge/src/profile-generator.cc Mon Sep 2 12:26:06 2013 UTC +++ /branches/bleeding_edge/src/profile-generator.cc Thu Sep 5 13:20:51 2013 UTC
@@ -133,6 +133,7 @@

 const char* const CodeEntry::kEmptyNamePrefix = "";
 const char* const CodeEntry::kEmptyResourceName = "";
+const char* const CodeEntry::kEmptyBailoutReason = "";


 CodeEntry::~CodeEntry() {
@@ -210,13 +211,14 @@


 void ProfileNode::Print(int indent) {
-  OS::Print("%5u %*c %s%s %d #%d",
+  OS::Print("%5u %*c %s%s %d #%d %s",
             self_ticks_,
             indent, ' ',
             entry_->name_prefix(),
             entry_->name(),
             entry_->script_id(),
-            id());
+            id(),
+            entry_->bailout_reason());
   if (entry_->resource_name()[0] != '\0')
     OS::Print(" %s:%d", entry_->resource_name(), entry_->line_number());
   OS::Print("\n");
=======================================
--- /branches/bleeding_edge/src/profile-generator.h Mon Sep 2 12:26:06 2013 UTC +++ /branches/bleeding_edge/src/profile-generator.h Thu Sep 5 13:20:51 2013 UTC
@@ -88,6 +88,10 @@
   INLINE(void set_shared_id(int shared_id)) { shared_id_ = shared_id; }
   INLINE(int script_id() const) { return script_id_; }
   INLINE(void set_script_id(int script_id)) { script_id_ = script_id; }
+  INLINE(void set_bailout_reason(const char* bailout_reason)) {
+    bailout_reason_ = bailout_reason;
+  }
+  INLINE(const char* bailout_reason() const) { return bailout_reason_; }

   INLINE(static bool is_js_function_tag(Logger::LogEventsAndTags tag));

@@ -105,6 +109,7 @@

   static const char* const kEmptyNamePrefix;
   static const char* const kEmptyResourceName;
+  static const char* const kEmptyBailoutReason;

  private:
   Logger::LogEventsAndTags tag_ : 8;
@@ -116,6 +121,7 @@
   int shared_id_;
   int script_id_;
   List<OffsetRange>* no_frame_ranges_;
+  const char* bailout_reason_;

   DISALLOW_COPY_AND_ASSIGN(CodeEntry);
 };
=======================================
--- /branches/bleeding_edge/test/cctest/test-profile-generator.cc Tue Aug 27 15:12:04 2013 UTC +++ /branches/bleeding_edge/test/cctest/test-profile-generator.cc Thu Sep 5 13:20:51 2013 UTC
@@ -782,3 +782,49 @@

   profiler->StopProfiling("LineNumber");
 }
+
+
+
+TEST(BailoutReason) {
+  const char* extensions[] = { "v8/profiler" };
+  v8::ExtensionConfiguration config(1, extensions);
+  LocalContext env(&config);
+  v8::HandleScope hs(env->GetIsolate());
+
+  v8::CpuProfiler* profiler = env->GetIsolate()->GetCpuProfiler();
+  CHECK_EQ(0, profiler->GetProfileCount());
+  v8::Handle<v8::Script> script = v8::Script::Compile(v8::String::New(
+      "function TryCatch() {\n"
+      "  try {\n"
+      "    startProfiling();\n"
+      "  } catch (e) { };\n"
+      "}\n"
+      "function TryFinally() {\n"
+      "  try {\n"
+      "    TryCatch();\n"
+      "  } finally { };\n"
+      "}\n"
+      "TryFinally();\n"
+      "stopProfiling();"));
+  script->Run();
+  CHECK_EQ(1, profiler->GetProfileCount());
+  const v8::CpuProfile* profile = profiler->GetCpuProfile(0);
+  const v8::CpuProfileNode* current = profile->GetTopDownRoot();
+  reinterpret_cast<ProfileNode*>(
+      const_cast<v8::CpuProfileNode*>(current))->Print(0);
+  // The tree should look like this:
+  //  (root)
+  //   (anonymous function)
+  //     kTryFinally
+  //       kTryCatch
+ current = PickChild(current, i::ProfileGenerator::kAnonymousFunctionName);
+  CHECK_NE(NULL, const_cast<v8::CpuProfileNode*>(current));
+
+  current = PickChild(current, "TryFinally");
+  CHECK_NE(NULL, const_cast<v8::CpuProfileNode*>(current));
+  CHECK(!strcmp("TryFinallyStatement", current->GetBailoutReason()));
+
+  current = PickChild(current, "TryCatch");
+  CHECK_NE(NULL, const_cast<v8::CpuProfileNode*>(current));
+  CHECK(!strcmp("TryCatchStatement", current->GetBailoutReason()));
+}

--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to