1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright 2006-2009 the V8 project authors. All rights reserved.
2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Redistribution and use in source and binary forms, with or without
3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// modification, are permitted provided that the following conditions are
4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// met:
5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//
6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//     * Redistributions of source code must retain the above copyright
7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//       notice, this list of conditions and the following disclaimer.
8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//     * Redistributions in binary form must reproduce the above
9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//       copyright notice, this list of conditions and the following
10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//       disclaimer in the documentation and/or other materials provided
11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//       with the distribution.
12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//     * Neither the name of Google Inc. nor the names of its
13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//       contributors may be used to endorse or promote products derived
14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//       from this software without specific prior written permission.
15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//
16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Tests of logging functions from log.h
29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef __linux__
31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <pthread.h>
32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <signal.h>
33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <unistd.h>
34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <cmath>
35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif  // __linux__
36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/v8.h"
38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/log.h"
40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/log-utils.h"
41014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/profiler/cpu-profiler.h"
42014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/snapshot/natives.h"
43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/utils.h"
44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/v8threads.h"
45958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/version.h"
46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/vm-state-inl.h"
47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "test/cctest/cctest.h"
48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockusing v8::internal::Address;
50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockusing v8::internal::EmbeddedVector;
51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockusing v8::internal::Logger;
52d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockusing v8::internal::StrLength;
53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
54402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescunamespace {
55402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
56589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
57014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define SETUP_FLAGS()                            \
58014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool saved_log = i::FLAG_log;                  \
59014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool saved_prof = i::FLAG_prof;                \
60014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  i::FLAG_log = true;                            \
61014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  i::FLAG_prof = true;                           \
62014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  i::FLAG_logfile = i::Log::kLogToTemporaryFile; \
63014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  i::FLAG_logfile_per_isolate = false
64014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
65014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
66402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescuclass ScopedLoggerInitializer {
67402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu public:
68014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ScopedLoggerInitializer(bool saved_log, bool saved_prof, v8::Isolate* isolate)
69014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      : saved_log_(saved_log),
70014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        saved_prof_(saved_prof),
713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        temp_file_(NULL),
72014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        isolate_(isolate),
73014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        isolate_scope_(isolate),
74014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        scope_(isolate),
75014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        env_(v8::Context::New(isolate)),
76014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        logger_(reinterpret_cast<i::Isolate*>(isolate)->logger()) {
77402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    env_->Enter();
78402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
79402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
80402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  ~ScopedLoggerInitializer() {
81402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    env_->Exit();
82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    logger_->TearDown();
833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (temp_file_ != NULL) fclose(temp_file_);
84402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu    i::FLAG_prof = saved_prof_;
853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    i::FLAG_log = saved_log_;
86402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  }
87402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
88014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  v8::Local<v8::Context>& env() { return env_; }
89402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate() { return isolate_; }
91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Logger* logger() { return logger_; }
93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  FILE* StopLoggingGetTempFile() {
95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    temp_file_ = logger_->TearDown();
96014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CHECK(temp_file_);
973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    fflush(temp_file_);
983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    rewind(temp_file_);
993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return temp_file_;
1003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
1013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
102402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu private:
1033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const bool saved_log_;
104402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  const bool saved_prof_;
1053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  FILE* temp_file_;
106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate* isolate_;
107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Isolate::Scope isolate_scope_;
108402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  v8::HandleScope scope_;
109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  v8::Local<v8::Context> env_;
110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Logger* logger_;
111402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
112402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu  DISALLOW_COPY_AND_ASSIGN(ScopedLoggerInitializer);
113402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu};
114402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
115402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}  // namespace
116402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
117402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
1183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochstatic const char* StrNStr(const char* s1, const char* s2, int n) {
1193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (s1[n] == '\0') return strstr(s1, s2);
1203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  i::ScopedVector<char> str(n + 1);
121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  i::StrNCpy(str, s1, static_cast<size_t>(n));
1223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  str[n] = '\0';
1233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  char* found = strstr(str.start(), s2);
1243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return found != NULL ? s1 + (found - str.start()) : NULL;
125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1285913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck// BUG(913). Need to implement support for profiling multiple VM threads.
1295913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck#if 0
130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace {
132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass LoopingThread : public v8::internal::Thread {
134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
13544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  explicit LoopingThread(v8::internal::Isolate* isolate)
13644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      : v8::internal::Thread(isolate),
137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        semaphore_(new v8::internal::Semaphore(0)),
138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        run_(true) {
139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual ~LoopingThread() { delete semaphore_; }
142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Run() {
144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    self_ = pthread_self();
145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    RunLoop();
146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void SendSigProf() { pthread_kill(self_, SIGPROF); }
149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Stop() { run_ = false; }
151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool WaitForRunning() { return semaphore_->Wait(1000000); }
153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block protected:
155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool IsRunning() { return run_; }
156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual void RunLoop() = 0;
158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void SetV8ThreadId() {
160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    v8_thread_id_ = v8::V8::GetCurrentThreadId();
161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void SignalRunning() { semaphore_->Signal(); }
164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::internal::Semaphore* semaphore_;
167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool run_;
168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  pthread_t self_;
169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int v8_thread_id_;
170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass LoopingJsThread : public LoopingThread {
174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
17544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  explicit LoopingJsThread(v8::internal::Isolate* isolate)
17644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      : LoopingThread(isolate) { }
177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void RunLoop() {
1786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    v8::Locker locker;
179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(CcTest::i_isolate() != NULL);
180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_GT(CcTest::i_isolate()->thread_manager()->CurrentId(), 0);
1816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    SetV8ThreadId();
182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    while (IsRunning()) {
183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      v8::HandleScope scope;
184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      v8::Persistent<v8::Context> context = v8::Context::New();
1856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      CHECK(!context.IsEmpty());
1866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      {
1876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        v8::Context::Scope context_scope(context);
1886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        SignalRunning();
1893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        CompileRun(
1906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block            "var j; for (var i=0; i<10000; ++i) { j = Math.sin(i); }");
1916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      context.Dispose();
193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      i::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(1));
194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass LoopingNonJsThread : public LoopingThread {
200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
20144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  explicit LoopingNonJsThread(v8::internal::Isolate* isolate)
20244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      : LoopingThread(isolate) { }
203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void RunLoop() {
204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    v8::Locker locker;
205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    v8::Unlocker unlocker;
206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Now thread has V8's id, but will not run VM code.
207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(CcTest::i_isolate() != NULL);
208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_GT(CcTest::i_isolate()->thread_manager()->CurrentId(), 0);
209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    double i = 10;
210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    SignalRunning();
211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    while (IsRunning()) {
212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      i = std::sin(i);
213014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      i::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(1));
214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass TestSampler : public v8::internal::Sampler {
220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
22144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  explicit TestSampler(v8::internal::Isolate* isolate)
22244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      : Sampler(isolate, 0, true, true),
223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        semaphore_(new v8::internal::Semaphore(0)),
224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        was_sample_stack_called_(false) {
225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ~TestSampler() { delete semaphore_; }
228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void SampleStack(v8::internal::TickSample*) {
230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    was_sample_stack_called_ = true;
231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Tick(v8::internal::TickSample*) { semaphore_->Signal(); }
234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool WaitForTick() { return semaphore_->Wait(1000000); }
236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Reset() { was_sample_stack_called_ = false; }
238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool WasSampleStackCalled() { return was_sample_stack_called_; }
240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::internal::Semaphore* semaphore_;
243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool was_sample_stack_called_;
244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}  // namespace
248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(ProfMultipleThreads) {
250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  TestSampler* sampler = NULL;
251b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  {
252b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    v8::Locker locker;
253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    sampler = new TestSampler(CcTest::i_isolate());
254b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    sampler->Start();
255b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    CHECK(sampler->IsActive());
256b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
257b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LoopingJsThread jsThread(CcTest::i_isolate());
259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  jsThread.Start();
260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  LoopingNonJsThread nonJsThread(CcTest::i_isolate());
261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  nonJsThread.Start();
262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
263b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK(!sampler->WasSampleStackCalled());
264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  jsThread.WaitForRunning();
265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  jsThread.SendSigProf();
266b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK(sampler->WaitForTick());
267b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK(sampler->WasSampleStackCalled());
268b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  sampler->Reset();
269b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK(!sampler->WasSampleStackCalled());
270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  nonJsThread.WaitForRunning();
271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  nonJsThread.SendSigProf();
272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK(!sampler->WaitForTick());
273b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CHECK(!sampler->WasSampleStackCalled());
274b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  sampler->Stop();
275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  jsThread.Stop();
277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  nonJsThread.Stop();
278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  jsThread.Join();
279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  nonJsThread.Join();
280b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
281b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  delete sampler;
282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif  // __linux__
285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2873ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// Test for issue http://crbug.com/23768 in Chromium.
2883ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// Heap can contain scripts with already disposed external sources.
2893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// We need to verify that LogCompiledFunctions doesn't crash on them.
2903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blocknamespace {
2913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockclass SimpleExternalString : public v8::String::ExternalStringResource {
2933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block public:
2943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  explicit SimpleExternalString(const char* source)
295d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block      : utf_source_(StrLength(source)) {
2963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block    for (int i = 0; i < utf_source_.length(); ++i)
2973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      utf_source_[i] = source[i];
2983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
2993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  virtual ~SimpleExternalString() {}
3003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  virtual size_t length() const { return utf_source_.length(); }
3013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  virtual const uint16_t* data() const { return utf_source_.start(); }
3023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block private:
3033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  i::ScopedVector<uint16_t> utf_source_;
3043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block};
3053ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3063ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}  // namespace
3073ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3083ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockTEST(Issue23768) {
309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::HandleScope scope(CcTest::isolate());
310014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  v8::Local<v8::Context> env = v8::Context::New(CcTest::isolate());
3113ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  env->Enter();
3123ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3133ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  SimpleExternalString source_ext_str("(function ext() {})();");
314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  v8::Local<v8::String> source =
315014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      v8::String::NewExternalTwoByte(CcTest::isolate(), &source_ext_str)
316014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          .ToLocalChecked();
3173ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Script needs to have a name in order to trigger InitLineEnds execution.
318014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  v8::Local<v8::String> origin =
319014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      v8::String::NewFromUtf8(CcTest::isolate(), "issue-23768-test",
320014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              v8::NewStringType::kNormal)
321014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          .ToLocalChecked();
322014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  v8::Local<v8::Script> evil_script = CompileWithOrigin(source, origin);
3233ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  CHECK(!evil_script.IsEmpty());
324014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CHECK(!evil_script->Run(env).IsEmpty());
3253ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  i::Handle<i::ExternalTwoByteString> i_source(
3263ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block      i::ExternalTwoByteString::cast(*v8::Utils::OpenHandle(*source)));
3273ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // This situation can happen if source was an external string disposed
3283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // by its owner.
3293ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  i_source->set_resource(NULL);
3303ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3313ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  // Must not crash.
332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::i_isolate()->logger()->LogCompiledFunctions();
3333ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block}
3343ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
3353ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void ObjMethod1(const v8::FunctionCallbackInfo<v8::Value>& args) {
337d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
338d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
339d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(LogCallbacks) {
341014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SETUP_FLAGS();
342014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  v8::Isolate::CreateParams create_params;
343014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
344014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  v8::Isolate* isolate = v8::Isolate::New(create_params);
345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
346014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    ScopedLoggerInitializer initialize_logger(saved_log, saved_prof, isolate);
347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Logger* logger = initialize_logger.logger();
348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Local<v8::FunctionTemplate> obj = v8::Local<v8::FunctionTemplate>::New(
350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        isolate, v8::FunctionTemplate::New(isolate));
351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    obj->SetClassName(v8_str("Obj"));
352014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    v8::Local<v8::ObjectTemplate> proto = obj->PrototypeTemplate();
353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Local<v8::Signature> signature = v8::Signature::New(isolate, obj);
354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    proto->Set(v8_str("method1"),
355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               v8::FunctionTemplate::New(isolate, ObjMethod1,
356014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                         v8::Local<v8::Value>(), signature),
357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch               static_cast<v8::PropertyAttribute>(v8::DontDelete));
358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
359014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    initialize_logger.env()
360014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        ->Global()
361014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        ->Set(initialize_logger.env(), v8_str("Obj"),
362014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch              obj->GetFunction(initialize_logger.env()).ToLocalChecked())
363014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        .FromJust();
364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CompileRun("Obj.prototype.method1.toString();");
365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    logger->LogCompiledFunctions();
367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bool exists = false;
369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    i::Vector<const char> log(
370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        i::ReadFile(initialize_logger.StopLoggingGetTempFile(), &exists, true));
371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(exists);
372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    i::EmbeddedVector<char, 100> ref_data;
374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    i::SNPrintF(ref_data,
375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                "code-creation,Callback,-2,0x%" V8PRIxPTR ",1,\"method1\"",
376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                reinterpret_cast<intptr_t>(ObjMethod1));
377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
378014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CHECK(StrNStr(log.start(), ref_data.start(), log.length()));
379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    log.Dispose();
380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate->Dispose();
382d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
383d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
384d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void Prop1Getter(v8::Local<v8::String> property,
386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        const v8::PropertyCallbackInfo<v8::Value>& info) {
387d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
388d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
389d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockstatic void Prop1Setter(v8::Local<v8::String> property,
390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        v8::Local<v8::Value> value,
391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        const v8::PropertyCallbackInfo<void>& info) {
392d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
393d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void Prop2Getter(v8::Local<v8::String> property,
395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                        const v8::PropertyCallbackInfo<v8::Value>& info) {
396402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu}
397d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
398402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu
399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(LogAccessorCallbacks) {
400014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SETUP_FLAGS();
401014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  v8::Isolate::CreateParams create_params;
402014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
403014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  v8::Isolate* isolate = v8::Isolate::New(create_params);
404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
405014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    ScopedLoggerInitializer initialize_logger(saved_log, saved_prof, isolate);
406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Logger* logger = initialize_logger.logger();
407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    v8::Local<v8::FunctionTemplate> obj = v8::Local<v8::FunctionTemplate>::New(
409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        isolate, v8::FunctionTemplate::New(isolate));
410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    obj->SetClassName(v8_str("Obj"));
411014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    v8::Local<v8::ObjectTemplate> inst = obj->InstanceTemplate();
412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    inst->SetAccessor(v8_str("prop1"), Prop1Getter, Prop1Setter);
413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    inst->SetAccessor(v8_str("prop2"), Prop2Getter);
414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    logger->LogAccessorCallbacks();
416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bool exists = false;
418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    i::Vector<const char> log(
419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        i::ReadFile(initialize_logger.StopLoggingGetTempFile(), &exists, true));
420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(exists);
421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EmbeddedVector<char, 100> prop1_getter_record;
423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    i::SNPrintF(prop1_getter_record,
424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                "code-creation,Callback,-2,0x%" V8PRIxPTR ",1,\"get prop1\"",
425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                reinterpret_cast<intptr_t>(Prop1Getter));
426014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CHECK(StrNStr(log.start(), prop1_getter_record.start(), log.length()));
427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EmbeddedVector<char, 100> prop1_setter_record;
429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    i::SNPrintF(prop1_setter_record,
430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                "code-creation,Callback,-2,0x%" V8PRIxPTR ",1,\"set prop1\"",
431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                reinterpret_cast<intptr_t>(Prop1Setter));
432014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CHECK(StrNStr(log.start(), prop1_setter_record.start(), log.length()));
433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EmbeddedVector<char, 100> prop2_getter_record;
435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    i::SNPrintF(prop2_getter_record,
436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                "code-creation,Callback,-2,0x%" V8PRIxPTR ",1,\"get prop2\"",
437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                reinterpret_cast<intptr_t>(Prop2Getter));
438014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CHECK(StrNStr(log.start(), prop2_getter_record.start(), log.length()));
439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    log.Dispose();
440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate->Dispose();
4426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
4436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochtypedef i::NativesCollection<i::TEST> TestSources;
446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
447589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
448589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch// Test that logging of code create / move events is equivalent to traversal of
449589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch// a resulting heap.
450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(EquivalenceOfLoggingAndTraversal) {
451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // This test needs to be run on a "clean" V8 to ensure that snapshot log
452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // is loaded. This is always true when running using tools/test.py because
453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // it launches a new cctest instance for every test. To be sure that launching
454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // cctest manually also works, please be sure that no tests below
455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // are using V8.
456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Start with profiling to capture all code events from the beginning.
458014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SETUP_FLAGS();
459014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  v8::Isolate::CreateParams create_params;
460014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
461014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  v8::Isolate* isolate = v8::Isolate::New(create_params);
462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  {
463014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    ScopedLoggerInitializer initialize_logger(saved_log, saved_prof, isolate);
464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Logger* logger = initialize_logger.logger();
465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Compile and run a function that creates other functions.
467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CompileRun(
468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "(function f(obj) {\n"
469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "  obj.test =\n"
470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "    (function a(j) { return function b() { return j; } })(100);\n"
471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        "})(this);");
472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    logger->StopProfiler();
473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    reinterpret_cast<i::Isolate*>(isolate)->heap()->CollectAllGarbage(
474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        i::Heap::kMakeHeapIterableMask);
475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    logger->StringEvent("test-logging-done", "");
476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Iterate heap to find compiled functions, will write to log.
478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    logger->LogCompiledFunctions();
479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    logger->StringEvent("test-traversal-done", "");
480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bool exists = false;
482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    i::Vector<const char> log(
483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        i::ReadFile(initialize_logger.StopLoggingGetTempFile(), &exists, true));
484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK(exists);
485014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    v8::Local<v8::String> log_str =
486014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        v8::String::NewFromUtf8(isolate, log.start(),
487014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                v8::NewStringType::kNormal, log.length())
488014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            .ToLocalChecked();
489014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    initialize_logger.env()
490014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        ->Global()
491014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        ->Set(initialize_logger.env(), v8_str("_log"), log_str)
492014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        .FromJust();
493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
494958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    i::Vector<const char> source = TestSources::GetScriptsSource();
495014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    v8::Local<v8::String> source_str =
496014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        v8::String::NewFromUtf8(isolate, source.start(),
497014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                v8::NewStringType::kNormal, source.length())
498014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch            .ToLocalChecked();
499014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    v8::TryCatch try_catch(isolate);
500014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    v8::Local<v8::Script> script = CompileWithOrigin(source_str, "");
501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (script.IsEmpty()) {
502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::Utf8Value exception(try_catch.Exception());
503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      printf("compile: %s\n", *exception);
504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CHECK(false);
505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
506014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    v8::Local<v8::Value> result;
507014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (!script->Run(initialize_logger.env()).ToLocal(&result)) {
508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      v8::String::Utf8Value exception(try_catch.Exception());
509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      printf("run: %s\n", *exception);
510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CHECK(false);
511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // The result either be a "true" literal or problem description.
513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!result->IsTrue()) {
514014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      v8::Local<v8::String> s =
515014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          result->ToString(initialize_logger.env()).ToLocalChecked();
516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      i::ScopedVector<char> data(s->Utf8Length() + 1);
517014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      CHECK(data.start());
518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      s->WriteUtf8(data.start());
519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      printf("%s\n", data.start());
520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      // Make sure that our output is written prior crash due to CHECK failure.
521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      fflush(stdout);
522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      CHECK(false);
523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  isolate->Dispose();
526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
527958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
528958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
529958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierTEST(LogVersion) {
530014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SETUP_FLAGS();
531014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  v8::Isolate::CreateParams create_params;
532014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
533014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  v8::Isolate* isolate = v8::Isolate::New(create_params);
534958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  {
535014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    ScopedLoggerInitializer initialize_logger(saved_log, saved_prof, isolate);
536958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    bool exists = false;
537958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    i::Vector<const char> log(
538958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        i::ReadFile(initialize_logger.StopLoggingGetTempFile(), &exists, true));
539958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    CHECK(exists);
540958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    i::EmbeddedVector<char, 100> ref_data;
541958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    i::SNPrintF(ref_data, "v8-version,%d,%d,%d,%d,%d", i::Version::GetMajor(),
542958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                i::Version::GetMinor(), i::Version::GetBuild(),
543958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                i::Version::GetPatch(), i::Version::IsCandidate());
544014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CHECK(StrNStr(log.start(), ref_data.start(), log.length()));
545958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    log.Dispose();
546958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
547958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  isolate->Dispose();
548958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
549014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
550014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
551014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// https://crbug.com/539892
552014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// CodeCreateEvents with really large names should not crash.
553014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochTEST(Issue539892) {
554014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  class : public i::CodeEventLogger {
555014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch   public:
556014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    virtual void CodeMoveEvent(Address from, Address to) {}
557014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    virtual void CodeDeleteEvent(Address from) {}
558014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    virtual void CodeDisableOptEvent(i::Code* code,
559014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                     i::SharedFunctionInfo* shared) {}
560014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
561014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch   private:
562014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    virtual void LogRecordedBuffer(i::Code* code, i::SharedFunctionInfo* shared,
563014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                   const char* name, int length) {}
564014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } code_event_logger;
565014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  SETUP_FLAGS();
566014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  v8::Isolate::CreateParams create_params;
567014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
568014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  v8::Isolate* isolate = v8::Isolate::New(create_params);
569014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
570014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  {
571014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    ScopedLoggerInitializer initialize_logger(saved_log, saved_prof, isolate);
572014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Logger* logger = initialize_logger.logger();
573014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    logger->addCodeEventListener(&code_event_logger);
574014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
575014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Function with a really large name.
576014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    const char* source_text =
577014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        "(function "
578014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        "baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
579014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
580014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
581014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
582014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
583014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
584014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
585014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
586014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
587014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
588014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
589014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
590014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
591014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
592014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
593014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
594014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaac"
595014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        "(){})();";
596014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
597014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CompileRun(source_text);
598014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
599014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Must not crash.
600014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    logger->LogCompiledFunctions();
601014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
602014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  isolate->Dispose();
603014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
604