blob: 24e5db933805cf02f57ceff510b705faff3346e4 [file] [log] [blame]
ager@chromium.org9085a012009-05-11 19:22:57 +00001// Copyright 2006-2009 the V8 project authors. All rights reserved.
ulan@chromium.org750145a2013-03-07 15:14:13 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
ager@chromium.org9085a012009-05-11 19:22:57 +000027//
28// Tests of logging functions from log.h
29
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000030#ifdef __linux__
ager@chromium.orga1645e22009-09-09 19:27:10 +000031#include <math.h>
32#include <pthread.h>
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000033#include <signal.h>
34#include <unistd.h>
ager@chromium.orga1645e22009-09-09 19:27:10 +000035#endif // __linux__
ager@chromium.org9085a012009-05-11 19:22:57 +000036
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +000037#include "v8.h"
ager@chromium.org9085a012009-05-11 19:22:57 +000038#include "log.h"
lrn@chromium.org25156de2010-04-06 13:10:27 +000039#include "cpu-profiler.h"
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +000040#include "natives.h"
ager@chromium.orga1645e22009-09-09 19:27:10 +000041#include "v8threads.h"
whesse@chromium.org030d38e2011-07-13 13:23:34 +000042#include "v8utils.h"
ager@chromium.org9085a012009-05-11 19:22:57 +000043#include "cctest.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000044#include "vm-state-inl.h"
ager@chromium.org9085a012009-05-11 19:22:57 +000045
kasperl@chromium.org71affb52009-05-26 05:44:31 +000046using v8::internal::Address;
47using v8::internal::EmbeddedVector;
ager@chromium.org9085a012009-05-11 19:22:57 +000048using v8::internal::Logger;
ager@chromium.orgc4c92722009-11-18 14:12:51 +000049using v8::internal::StrLength;
ager@chromium.org9085a012009-05-11 19:22:57 +000050
ager@chromium.org5c838252010-02-19 08:53:10 +000051namespace {
52
lrn@chromium.org34e60782011-09-15 07:25:40 +000053
ager@chromium.org5c838252010-02-19 08:53:10 +000054class ScopedLoggerInitializer {
55 public:
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000056 explicit ScopedLoggerInitializer(bool prof_lazy)
whesse@chromium.org030d38e2011-07-13 13:23:34 +000057 : saved_log_(i::FLAG_log),
58 saved_prof_lazy_(i::FLAG_prof_lazy),
ager@chromium.org5c838252010-02-19 08:53:10 +000059 saved_prof_(i::FLAG_prof),
60 saved_prof_auto_(i::FLAG_prof_auto),
whesse@chromium.org030d38e2011-07-13 13:23:34 +000061 temp_file_(NULL),
62 // Need to run this prior to creating the scope.
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000063 trick_to_run_init_flags_(init_flags_(prof_lazy)),
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000064 scope_(v8::Isolate::GetCurrent()),
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000065 env_(v8::Context::New()),
66 logger_(i::Isolate::Current()->logger()) {
ager@chromium.org5c838252010-02-19 08:53:10 +000067 env_->Enter();
68 }
69
70 ~ScopedLoggerInitializer() {
71 env_->Exit();
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000072 logger_->TearDown();
whesse@chromium.org030d38e2011-07-13 13:23:34 +000073 if (temp_file_ != NULL) fclose(temp_file_);
ager@chromium.org5c838252010-02-19 08:53:10 +000074 i::FLAG_prof_lazy = saved_prof_lazy_;
75 i::FLAG_prof = saved_prof_;
76 i::FLAG_prof_auto = saved_prof_auto_;
whesse@chromium.org030d38e2011-07-13 13:23:34 +000077 i::FLAG_log = saved_log_;
ager@chromium.org5c838252010-02-19 08:53:10 +000078 }
79
80 v8::Handle<v8::Context>& env() { return env_; }
81
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000082 Logger* logger() { return logger_; }
83
whesse@chromium.org030d38e2011-07-13 13:23:34 +000084 FILE* StopLoggingGetTempFile() {
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000085 temp_file_ = logger_->TearDown();
whesse@chromium.org030d38e2011-07-13 13:23:34 +000086 CHECK_NE(NULL, temp_file_);
87 fflush(temp_file_);
88 rewind(temp_file_);
89 return temp_file_;
90 }
91
ager@chromium.org5c838252010-02-19 08:53:10 +000092 private:
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000093 static bool init_flags_(bool prof_lazy) {
whesse@chromium.org030d38e2011-07-13 13:23:34 +000094 i::FLAG_log = true;
ager@chromium.org5c838252010-02-19 08:53:10 +000095 i::FLAG_prof = true;
96 i::FLAG_prof_lazy = prof_lazy;
97 i::FLAG_prof_auto = false;
whesse@chromium.org030d38e2011-07-13 13:23:34 +000098 i::FLAG_logfile = i::Log::kLogToTemporaryFile;
ager@chromium.org5c838252010-02-19 08:53:10 +000099 return prof_lazy;
100 }
101
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000102 const bool saved_log_;
ager@chromium.org5c838252010-02-19 08:53:10 +0000103 const bool saved_prof_lazy_;
104 const bool saved_prof_;
105 const bool saved_prof_auto_;
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000106 FILE* temp_file_;
ager@chromium.org5c838252010-02-19 08:53:10 +0000107 const bool trick_to_run_init_flags_;
ager@chromium.org5c838252010-02-19 08:53:10 +0000108 v8::HandleScope scope_;
109 v8::Handle<v8::Context> env_;
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000110 Logger* logger_;
ager@chromium.org5c838252010-02-19 08:53:10 +0000111
112 DISALLOW_COPY_AND_ASSIGN(ScopedLoggerInitializer);
113};
114
ager@chromium.org5c838252010-02-19 08:53:10 +0000115} // namespace
116
117
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000118static const char* StrNStr(const char* s1, const char* s2, int n) {
119 if (s1[n] == '\0') return strstr(s1, s2);
120 i::ScopedVector<char> str(n + 1);
121 i::OS::StrNCpy(str, s1, static_cast<size_t>(n));
122 str[n] = '\0';
123 char* found = strstr(str.start(), s2);
124 return found != NULL ? s1 + (found - str.start()) : NULL;
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000125}
126
127
128TEST(ProfLazyMode) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000129 ScopedLoggerInitializer initialize_logger(true);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000130 Logger* logger = initialize_logger.logger();
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000131
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000132 if (!i::V8::UseCrankshaft()) return;
133
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000134 logger->StringEvent("test-start", "");
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000135 CompileRun("var a = (function(x) { return x + 1; })(10);");
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000136 logger->StringEvent("test-profiler-start", "");
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000137 v8::V8::ResumeProfiler();
138 CompileRun(
139 "var b = (function(x) { return x + 2; })(10);\n"
140 "var c = (function(x) { return x + 3; })(10);\n"
141 "var d = (function(x) { return x + 4; })(10);\n"
142 "var e = (function(x) { return x + 5; })(10);");
143 v8::V8::PauseProfiler();
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000144 logger->StringEvent("test-profiler-stop", "");
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000145 CompileRun("var f = (function(x) { return x + 6; })(10);");
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000146 // Check that profiling can be resumed again.
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000147 logger->StringEvent("test-profiler-start-2", "");
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000148 v8::V8::ResumeProfiler();
149 CompileRun(
150 "var g = (function(x) { return x + 7; })(10);\n"
151 "var h = (function(x) { return x + 8; })(10);\n"
152 "var i = (function(x) { return x + 9; })(10);\n"
153 "var j = (function(x) { return x + 10; })(10);");
154 v8::V8::PauseProfiler();
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000155 logger->StringEvent("test-profiler-stop-2", "");
156 logger->StringEvent("test-stop", "");
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000157
158 bool exists = false;
159 i::Vector<const char> log(
160 i::ReadFile(initialize_logger.StopLoggingGetTempFile(), &exists, true));
161 CHECK(exists);
162
163 const char* test_start_position =
164 StrNStr(log.start(), "test-start,", log.length());
165 CHECK_NE(NULL, test_start_position);
166 const char* test_profiler_start_position =
167 StrNStr(log.start(), "test-profiler-start,", log.length());
168 CHECK_NE(NULL, test_profiler_start_position);
169 CHECK_GT(test_profiler_start_position, test_start_position);
170 const char* test_profiler_stop_position =
171 StrNStr(log.start(), "test-profiler-stop,", log.length());
172 CHECK_NE(NULL, test_profiler_stop_position);
173 CHECK_GT(test_profiler_stop_position, test_profiler_start_position);
174 const char* test_profiler_start_2_position =
175 StrNStr(log.start(), "test-profiler-start-2,", log.length());
176 CHECK_NE(NULL, test_profiler_start_2_position);
177 CHECK_GT(test_profiler_start_2_position, test_profiler_stop_position);
178
179 // Nothing must be logged until profiling is resumed.
180 CHECK_EQ(NULL, StrNStr(test_start_position,
181 "code-creation,",
182 static_cast<int>(test_profiler_start_position -
183 test_start_position)));
184 // Nothing must be logged while profiling is suspended.
185 CHECK_EQ(NULL, StrNStr(test_profiler_stop_position,
186 "code-creation,",
187 static_cast<int>(test_profiler_start_2_position -
188 test_profiler_stop_position)));
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000189}
190
191
lrn@chromium.org303ada72010-10-27 09:33:13 +0000192// BUG(913). Need to implement support for profiling multiple VM threads.
193#if 0
ager@chromium.orga1645e22009-09-09 19:27:10 +0000194
195namespace {
196
197class LoopingThread : public v8::internal::Thread {
198 public:
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000199 explicit LoopingThread(v8::internal::Isolate* isolate)
200 : v8::internal::Thread(isolate),
ager@chromium.orga1645e22009-09-09 19:27:10 +0000201 semaphore_(v8::internal::OS::CreateSemaphore(0)),
202 run_(true) {
203 }
204
205 virtual ~LoopingThread() { delete semaphore_; }
206
207 void Run() {
208 self_ = pthread_self();
209 RunLoop();
210 }
211
212 void SendSigProf() { pthread_kill(self_, SIGPROF); }
213
214 void Stop() { run_ = false; }
215
216 bool WaitForRunning() { return semaphore_->Wait(1000000); }
217
218 protected:
219 bool IsRunning() { return run_; }
220
221 virtual void RunLoop() = 0;
222
223 void SetV8ThreadId() {
224 v8_thread_id_ = v8::V8::GetCurrentThreadId();
225 }
226
227 void SignalRunning() { semaphore_->Signal(); }
228
229 private:
230 v8::internal::Semaphore* semaphore_;
231 bool run_;
232 pthread_t self_;
233 int v8_thread_id_;
234};
235
236
237class LoopingJsThread : public LoopingThread {
238 public:
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000239 explicit LoopingJsThread(v8::internal::Isolate* isolate)
240 : LoopingThread(isolate) { }
ager@chromium.orga1645e22009-09-09 19:27:10 +0000241 void RunLoop() {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000242 v8::Locker locker;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000243 CHECK(i::Isolate::Current() != NULL);
244 CHECK_GT(i::Isolate::Current()->thread_manager()->CurrentId(), 0);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000245 SetV8ThreadId();
ager@chromium.orga1645e22009-09-09 19:27:10 +0000246 while (IsRunning()) {
ager@chromium.orga1645e22009-09-09 19:27:10 +0000247 v8::HandleScope scope;
248 v8::Persistent<v8::Context> context = v8::Context::New();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000249 CHECK(!context.IsEmpty());
250 {
251 v8::Context::Scope context_scope(context);
252 SignalRunning();
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000253 CompileRun(
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000254 "var j; for (var i=0; i<10000; ++i) { j = Math.sin(i); }");
255 }
ager@chromium.orga1645e22009-09-09 19:27:10 +0000256 context.Dispose();
257 i::OS::Sleep(1);
258 }
259 }
260};
261
262
263class LoopingNonJsThread : public LoopingThread {
264 public:
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000265 explicit LoopingNonJsThread(v8::internal::Isolate* isolate)
266 : LoopingThread(isolate) { }
ager@chromium.orga1645e22009-09-09 19:27:10 +0000267 void RunLoop() {
268 v8::Locker locker;
269 v8::Unlocker unlocker;
270 // Now thread has V8's id, but will not run VM code.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000271 CHECK(i::Isolate::Current() != NULL);
272 CHECK_GT(i::Isolate::Current()->thread_manager()->CurrentId(), 0);
ager@chromium.orga1645e22009-09-09 19:27:10 +0000273 double i = 10;
274 SignalRunning();
275 while (IsRunning()) {
276 i = sin(i);
277 i::OS::Sleep(1);
278 }
279 }
280};
281
282
283class TestSampler : public v8::internal::Sampler {
284 public:
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000285 explicit TestSampler(v8::internal::Isolate* isolate)
286 : Sampler(isolate, 0, true, true),
ager@chromium.orga1645e22009-09-09 19:27:10 +0000287 semaphore_(v8::internal::OS::CreateSemaphore(0)),
288 was_sample_stack_called_(false) {
289 }
290
291 ~TestSampler() { delete semaphore_; }
292
293 void SampleStack(v8::internal::TickSample*) {
294 was_sample_stack_called_ = true;
295 }
296
297 void Tick(v8::internal::TickSample*) { semaphore_->Signal(); }
298
299 bool WaitForTick() { return semaphore_->Wait(1000000); }
300
301 void Reset() { was_sample_stack_called_ = false; }
302
303 bool WasSampleStackCalled() { return was_sample_stack_called_; }
304
305 private:
306 v8::internal::Semaphore* semaphore_;
307 bool was_sample_stack_called_;
308};
309
310
311} // namespace
312
313TEST(ProfMultipleThreads) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000314 TestSampler* sampler = NULL;
315 {
316 v8::Locker locker;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000317 sampler = new TestSampler(v8::internal::Isolate::Current());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000318 sampler->Start();
319 CHECK(sampler->IsActive());
320 }
321
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000322 LoopingJsThread jsThread(v8::internal::Isolate::Current());
ager@chromium.orga1645e22009-09-09 19:27:10 +0000323 jsThread.Start();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000324 LoopingNonJsThread nonJsThread(v8::internal::Isolate::Current());
ager@chromium.orga1645e22009-09-09 19:27:10 +0000325 nonJsThread.Start();
326
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000327 CHECK(!sampler->WasSampleStackCalled());
ager@chromium.orga1645e22009-09-09 19:27:10 +0000328 jsThread.WaitForRunning();
329 jsThread.SendSigProf();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000330 CHECK(sampler->WaitForTick());
331 CHECK(sampler->WasSampleStackCalled());
332 sampler->Reset();
333 CHECK(!sampler->WasSampleStackCalled());
ager@chromium.orga1645e22009-09-09 19:27:10 +0000334 nonJsThread.WaitForRunning();
335 nonJsThread.SendSigProf();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000336 CHECK(!sampler->WaitForTick());
337 CHECK(!sampler->WasSampleStackCalled());
338 sampler->Stop();
ager@chromium.orga1645e22009-09-09 19:27:10 +0000339
340 jsThread.Stop();
341 nonJsThread.Stop();
342 jsThread.Join();
343 nonJsThread.Join();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000344
345 delete sampler;
ager@chromium.orga1645e22009-09-09 19:27:10 +0000346}
347
348#endif // __linux__
349
350
sgjesse@chromium.org152a0b02009-10-07 13:50:16 +0000351// Test for issue http://crbug.com/23768 in Chromium.
352// Heap can contain scripts with already disposed external sources.
353// We need to verify that LogCompiledFunctions doesn't crash on them.
354namespace {
355
356class SimpleExternalString : public v8::String::ExternalStringResource {
357 public:
358 explicit SimpleExternalString(const char* source)
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000359 : utf_source_(StrLength(source)) {
sgjesse@chromium.org152a0b02009-10-07 13:50:16 +0000360 for (int i = 0; i < utf_source_.length(); ++i)
361 utf_source_[i] = source[i];
362 }
363 virtual ~SimpleExternalString() {}
364 virtual size_t length() const { return utf_source_.length(); }
365 virtual const uint16_t* data() const { return utf_source_.start(); }
366 private:
367 i::ScopedVector<uint16_t> utf_source_;
368};
369
370} // namespace
371
372TEST(Issue23768) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000373 v8::HandleScope scope(v8::Isolate::GetCurrent());
sgjesse@chromium.org152a0b02009-10-07 13:50:16 +0000374 v8::Handle<v8::Context> env = v8::Context::New();
375 env->Enter();
376
377 SimpleExternalString source_ext_str("(function ext() {})();");
378 v8::Local<v8::String> source = v8::String::NewExternal(&source_ext_str);
379 // Script needs to have a name in order to trigger InitLineEnds execution.
380 v8::Handle<v8::String> origin = v8::String::New("issue-23768-test");
381 v8::Handle<v8::Script> evil_script = v8::Script::Compile(source, origin);
382 CHECK(!evil_script.IsEmpty());
383 CHECK(!evil_script->Run().IsEmpty());
384 i::Handle<i::ExternalTwoByteString> i_source(
385 i::ExternalTwoByteString::cast(*v8::Utils::OpenHandle(*source)));
386 // This situation can happen if source was an external string disposed
387 // by its owner.
388 i_source->set_resource(NULL);
389
390 // Must not crash.
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000391 i::Isolate::Current()->logger()->LogCompiledFunctions();
sgjesse@chromium.org152a0b02009-10-07 13:50:16 +0000392}
393
394
ager@chromium.org01beca72009-11-24 14:29:16 +0000395static v8::Handle<v8::Value> ObjMethod1(const v8::Arguments& args) {
396 return v8::Handle<v8::Value>();
397}
398
399TEST(LogCallbacks) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000400 ScopedLoggerInitializer initialize_logger(false);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000401 Logger* logger = initialize_logger.logger();
ager@chromium.org01beca72009-11-24 14:29:16 +0000402
403 v8::Persistent<v8::FunctionTemplate> obj =
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +0000404 v8::Persistent<v8::FunctionTemplate>::New(v8::Isolate::GetCurrent(),
405 v8::FunctionTemplate::New());
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000406 obj->SetClassName(v8_str("Obj"));
ager@chromium.org01beca72009-11-24 14:29:16 +0000407 v8::Handle<v8::ObjectTemplate> proto = obj->PrototypeTemplate();
408 v8::Local<v8::Signature> signature = v8::Signature::New(obj);
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000409 proto->Set(v8_str("method1"),
ager@chromium.org01beca72009-11-24 14:29:16 +0000410 v8::FunctionTemplate::New(ObjMethod1,
411 v8::Handle<v8::Value>(),
412 signature),
413 static_cast<v8::PropertyAttribute>(v8::DontDelete));
414
ager@chromium.org5c838252010-02-19 08:53:10 +0000415 initialize_logger.env()->Global()->Set(v8_str("Obj"), obj->GetFunction());
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000416 CompileRun("Obj.prototype.method1.toString();");
ager@chromium.org01beca72009-11-24 14:29:16 +0000417
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000418 logger->LogCompiledFunctions();
ager@chromium.org01beca72009-11-24 14:29:16 +0000419
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000420 bool exists = false;
421 i::Vector<const char> log(
422 i::ReadFile(initialize_logger.StopLoggingGetTempFile(), &exists, true));
423 CHECK(exists);
424
425 i::EmbeddedVector<char, 100> ref_data;
ager@chromium.org01beca72009-11-24 14:29:16 +0000426 i::OS::SNPrintF(ref_data,
svenpanne@chromium.org83130cf2012-11-30 10:13:25 +0000427 "code-creation,Callback,-3,0x%" V8PRIxPTR ",1,\"method1\"\0",
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000428 ObjMethod1);
429
430 CHECK_NE(NULL, StrNStr(log.start(), ref_data.start(), log.length()));
ager@chromium.org01beca72009-11-24 14:29:16 +0000431
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +0000432 obj.Dispose(v8::Isolate::GetCurrent());
ager@chromium.org01beca72009-11-24 14:29:16 +0000433}
434
435
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000436static v8::Handle<v8::Value> Prop1Getter(v8::Local<v8::String> property,
437 const v8::AccessorInfo& info) {
438 return v8::Handle<v8::Value>();
439}
440
441static void Prop1Setter(v8::Local<v8::String> property,
442 v8::Local<v8::Value> value,
443 const v8::AccessorInfo& info) {
444}
445
446static v8::Handle<v8::Value> Prop2Getter(v8::Local<v8::String> property,
447 const v8::AccessorInfo& info) {
448 return v8::Handle<v8::Value>();
449}
450
451TEST(LogAccessorCallbacks) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000452 ScopedLoggerInitializer initialize_logger(false);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000453 Logger* logger = initialize_logger.logger();
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000454
455 v8::Persistent<v8::FunctionTemplate> obj =
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +0000456 v8::Persistent<v8::FunctionTemplate>::New(v8::Isolate::GetCurrent(),
457 v8::FunctionTemplate::New());
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000458 obj->SetClassName(v8_str("Obj"));
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000459 v8::Handle<v8::ObjectTemplate> inst = obj->InstanceTemplate();
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000460 inst->SetAccessor(v8_str("prop1"), Prop1Getter, Prop1Setter);
461 inst->SetAccessor(v8_str("prop2"), Prop2Getter);
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000462
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000463 logger->LogAccessorCallbacks();
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000464
465 bool exists = false;
466 i::Vector<const char> log(
467 i::ReadFile(initialize_logger.StopLoggingGetTempFile(), &exists, true));
468 CHECK(exists);
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000469
470 EmbeddedVector<char, 100> prop1_getter_record;
471 i::OS::SNPrintF(prop1_getter_record,
svenpanne@chromium.org83130cf2012-11-30 10:13:25 +0000472 "code-creation,Callback,-3,0x%" V8PRIxPTR ",1,\"get prop1\"",
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000473 Prop1Getter);
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000474 CHECK_NE(NULL,
475 StrNStr(log.start(), prop1_getter_record.start(), log.length()));
476
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000477 EmbeddedVector<char, 100> prop1_setter_record;
478 i::OS::SNPrintF(prop1_setter_record,
svenpanne@chromium.org83130cf2012-11-30 10:13:25 +0000479 "code-creation,Callback,-3,0x%" V8PRIxPTR ",1,\"set prop1\"",
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000480 Prop1Setter);
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000481 CHECK_NE(NULL,
482 StrNStr(log.start(), prop1_setter_record.start(), log.length()));
483
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000484 EmbeddedVector<char, 100> prop2_getter_record;
485 i::OS::SNPrintF(prop2_getter_record,
svenpanne@chromium.org83130cf2012-11-30 10:13:25 +0000486 "code-creation,Callback,-3,0x%" V8PRIxPTR ",1,\"get prop2\"",
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000487 Prop2Getter);
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000488 CHECK_NE(NULL,
489 StrNStr(log.start(), prop2_getter_record.start(), log.length()));
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000490
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +0000491 obj.Dispose(v8::Isolate::GetCurrent());
ager@chromium.org5c838252010-02-19 08:53:10 +0000492}
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000493
ager@chromium.org5c838252010-02-19 08:53:10 +0000494
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000495TEST(IsLoggingPreserved) {
496 ScopedLoggerInitializer initialize_logger(false);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000497 Logger* logger = initialize_logger.logger();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000498
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000499 CHECK(logger->is_logging());
500 logger->ResumeProfiler();
501 CHECK(logger->is_logging());
502 logger->PauseProfiler();
503 CHECK(logger->is_logging());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000504}
505
506
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +0000507typedef i::NativesCollection<i::TEST> TestSources;
508
lrn@chromium.org34e60782011-09-15 07:25:40 +0000509
510// Test that logging of code create / move events is equivalent to traversal of
511// a resulting heap.
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000512TEST(EquivalenceOfLoggingAndTraversal) {
513 // This test needs to be run on a "clean" V8 to ensure that snapshot log
514 // is loaded. This is always true when running using tools/test.py because
515 // it launches a new cctest instance for every test. To be sure that launching
516 // cctest manually also works, please be sure that no tests below
517 // are using V8.
518 //
519 // P.S. No, V8 can't be re-initialized after disposal, see include/v8.h.
520 CHECK(!i::V8::IsRunning());
521
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000522 // Start with profiling to capture all code events from the beginning.
523 ScopedLoggerInitializer initialize_logger(false);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000524 Logger* logger = initialize_logger.logger();
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000525
526 // Compile and run a function that creates other functions.
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000527 CompileRun(
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000528 "(function f(obj) {\n"
529 " obj.test =\n"
530 " (function a(j) { return function b() { return j; } })(100);\n"
531 "})(this);");
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000532 v8::V8::PauseProfiler();
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000533 HEAP->CollectAllGarbage(i::Heap::kMakeHeapIterableMask);
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000534 logger->StringEvent("test-logging-done", "");
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000535
536 // Iterate heap to find compiled functions, will write to log.
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000537 logger->LogCompiledFunctions();
538 logger->StringEvent("test-traversal-done", "");
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000539
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000540 bool exists = false;
541 i::Vector<const char> log(
542 i::ReadFile(initialize_logger.StopLoggingGetTempFile(), &exists, true));
543 CHECK(exists);
544 v8::Handle<v8::String> log_str = v8::String::New(log.start(), log.length());
545 initialize_logger.env()->Global()->Set(v8_str("_log"), log_str);
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000546
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +0000547 i::Vector<const unsigned char> source = TestSources::GetScriptsSource();
548 v8::Handle<v8::String> source_str = v8::String::New(
549 reinterpret_cast<const char*>(source.start()), source.length());
550 v8::TryCatch try_catch;
551 v8::Handle<v8::Script> script = v8::Script::Compile(source_str, v8_str(""));
552 if (script.IsEmpty()) {
553 v8::String::Utf8Value exception(try_catch.Exception());
554 printf("compile: %s\n", *exception);
555 CHECK(false);
556 }
557 v8::Handle<v8::Value> result = script->Run();
558 if (result.IsEmpty()) {
559 v8::String::Utf8Value exception(try_catch.Exception());
560 printf("run: %s\n", *exception);
561 CHECK(false);
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000562 }
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000563 // The result either be a "true" literal or problem description.
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +0000564 if (!result->IsTrue()) {
565 v8::Local<v8::String> s = result->ToString();
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000566 i::ScopedVector<char> data(s->Length() + 1);
567 CHECK_NE(NULL, data.start());
568 s->WriteAscii(data.start());
569 printf("%s\n", data.start());
570 // Make sure that our output is written prior crash due to CHECK failure.
571 fflush(stdout);
572 CHECK(false);
573 }
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000574}