blob: 53ccd3e789135f5f0fa527d4120758455ef16437 [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()),
ager@chromium.org5c838252010-02-19 08:53:10 +000065 env_(v8::Context::New()) {
ager@chromium.org5c838252010-02-19 08:53:10 +000066 env_->Enter();
67 }
68
69 ~ScopedLoggerInitializer() {
70 env_->Exit();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000071 LOGGER->TearDown();
whesse@chromium.org030d38e2011-07-13 13:23:34 +000072 if (temp_file_ != NULL) fclose(temp_file_);
ager@chromium.org5c838252010-02-19 08:53:10 +000073 i::FLAG_prof_lazy = saved_prof_lazy_;
74 i::FLAG_prof = saved_prof_;
75 i::FLAG_prof_auto = saved_prof_auto_;
whesse@chromium.org030d38e2011-07-13 13:23:34 +000076 i::FLAG_log = saved_log_;
ager@chromium.org5c838252010-02-19 08:53:10 +000077 }
78
79 v8::Handle<v8::Context>& env() { return env_; }
80
whesse@chromium.org030d38e2011-07-13 13:23:34 +000081 FILE* StopLoggingGetTempFile() {
82 temp_file_ = LOGGER->TearDown();
83 CHECK_NE(NULL, temp_file_);
84 fflush(temp_file_);
85 rewind(temp_file_);
86 return temp_file_;
87 }
88
ager@chromium.org5c838252010-02-19 08:53:10 +000089 private:
ager@chromium.orgce5e87b2010-03-10 10:24:18 +000090 static bool init_flags_(bool prof_lazy) {
whesse@chromium.org030d38e2011-07-13 13:23:34 +000091 i::FLAG_log = true;
ager@chromium.org5c838252010-02-19 08:53:10 +000092 i::FLAG_prof = true;
93 i::FLAG_prof_lazy = prof_lazy;
94 i::FLAG_prof_auto = false;
whesse@chromium.org030d38e2011-07-13 13:23:34 +000095 i::FLAG_logfile = i::Log::kLogToTemporaryFile;
ager@chromium.org5c838252010-02-19 08:53:10 +000096 return prof_lazy;
97 }
98
whesse@chromium.org030d38e2011-07-13 13:23:34 +000099 const bool saved_log_;
ager@chromium.org5c838252010-02-19 08:53:10 +0000100 const bool saved_prof_lazy_;
101 const bool saved_prof_;
102 const bool saved_prof_auto_;
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000103 FILE* temp_file_;
ager@chromium.org5c838252010-02-19 08:53:10 +0000104 const bool trick_to_run_init_flags_;
ager@chromium.org5c838252010-02-19 08:53:10 +0000105 v8::HandleScope scope_;
106 v8::Handle<v8::Context> env_;
107
108 DISALLOW_COPY_AND_ASSIGN(ScopedLoggerInitializer);
109};
110
ager@chromium.org5c838252010-02-19 08:53:10 +0000111} // namespace
112
113
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000114static const char* StrNStr(const char* s1, const char* s2, int n) {
115 if (s1[n] == '\0') return strstr(s1, s2);
116 i::ScopedVector<char> str(n + 1);
117 i::OS::StrNCpy(str, s1, static_cast<size_t>(n));
118 str[n] = '\0';
119 char* found = strstr(str.start(), s2);
120 return found != NULL ? s1 + (found - str.start()) : NULL;
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000121}
122
123
124TEST(ProfLazyMode) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000125 ScopedLoggerInitializer initialize_logger(true);
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000126
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000127 if (!i::V8::UseCrankshaft()) return;
128
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000129 LOGGER->StringEvent("test-start", "");
130 CompileRun("var a = (function(x) { return x + 1; })(10);");
131 LOGGER->StringEvent("test-profiler-start", "");
132 v8::V8::ResumeProfiler();
133 CompileRun(
134 "var b = (function(x) { return x + 2; })(10);\n"
135 "var c = (function(x) { return x + 3; })(10);\n"
136 "var d = (function(x) { return x + 4; })(10);\n"
137 "var e = (function(x) { return x + 5; })(10);");
138 v8::V8::PauseProfiler();
139 LOGGER->StringEvent("test-profiler-stop", "");
140 CompileRun("var f = (function(x) { return x + 6; })(10);");
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000141 // Check that profiling can be resumed again.
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000142 LOGGER->StringEvent("test-profiler-start-2", "");
143 v8::V8::ResumeProfiler();
144 CompileRun(
145 "var g = (function(x) { return x + 7; })(10);\n"
146 "var h = (function(x) { return x + 8; })(10);\n"
147 "var i = (function(x) { return x + 9; })(10);\n"
148 "var j = (function(x) { return x + 10; })(10);");
149 v8::V8::PauseProfiler();
150 LOGGER->StringEvent("test-profiler-stop-2", "");
151 LOGGER->StringEvent("test-stop", "");
152
153 bool exists = false;
154 i::Vector<const char> log(
155 i::ReadFile(initialize_logger.StopLoggingGetTempFile(), &exists, true));
156 CHECK(exists);
157
158 const char* test_start_position =
159 StrNStr(log.start(), "test-start,", log.length());
160 CHECK_NE(NULL, test_start_position);
161 const char* test_profiler_start_position =
162 StrNStr(log.start(), "test-profiler-start,", log.length());
163 CHECK_NE(NULL, test_profiler_start_position);
164 CHECK_GT(test_profiler_start_position, test_start_position);
165 const char* test_profiler_stop_position =
166 StrNStr(log.start(), "test-profiler-stop,", log.length());
167 CHECK_NE(NULL, test_profiler_stop_position);
168 CHECK_GT(test_profiler_stop_position, test_profiler_start_position);
169 const char* test_profiler_start_2_position =
170 StrNStr(log.start(), "test-profiler-start-2,", log.length());
171 CHECK_NE(NULL, test_profiler_start_2_position);
172 CHECK_GT(test_profiler_start_2_position, test_profiler_stop_position);
173
174 // Nothing must be logged until profiling is resumed.
175 CHECK_EQ(NULL, StrNStr(test_start_position,
176 "code-creation,",
177 static_cast<int>(test_profiler_start_position -
178 test_start_position)));
179 // Nothing must be logged while profiling is suspended.
180 CHECK_EQ(NULL, StrNStr(test_profiler_stop_position,
181 "code-creation,",
182 static_cast<int>(test_profiler_start_2_position -
183 test_profiler_stop_position)));
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000184}
185
186
lrn@chromium.org303ada72010-10-27 09:33:13 +0000187// BUG(913). Need to implement support for profiling multiple VM threads.
188#if 0
ager@chromium.orga1645e22009-09-09 19:27:10 +0000189
190namespace {
191
192class LoopingThread : public v8::internal::Thread {
193 public:
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000194 explicit LoopingThread(v8::internal::Isolate* isolate)
195 : v8::internal::Thread(isolate),
ager@chromium.orga1645e22009-09-09 19:27:10 +0000196 semaphore_(v8::internal::OS::CreateSemaphore(0)),
197 run_(true) {
198 }
199
200 virtual ~LoopingThread() { delete semaphore_; }
201
202 void Run() {
203 self_ = pthread_self();
204 RunLoop();
205 }
206
207 void SendSigProf() { pthread_kill(self_, SIGPROF); }
208
209 void Stop() { run_ = false; }
210
211 bool WaitForRunning() { return semaphore_->Wait(1000000); }
212
213 protected:
214 bool IsRunning() { return run_; }
215
216 virtual void RunLoop() = 0;
217
218 void SetV8ThreadId() {
219 v8_thread_id_ = v8::V8::GetCurrentThreadId();
220 }
221
222 void SignalRunning() { semaphore_->Signal(); }
223
224 private:
225 v8::internal::Semaphore* semaphore_;
226 bool run_;
227 pthread_t self_;
228 int v8_thread_id_;
229};
230
231
232class LoopingJsThread : public LoopingThread {
233 public:
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000234 explicit LoopingJsThread(v8::internal::Isolate* isolate)
235 : LoopingThread(isolate) { }
ager@chromium.orga1645e22009-09-09 19:27:10 +0000236 void RunLoop() {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000237 v8::Locker locker;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000238 CHECK(i::Isolate::Current() != NULL);
239 CHECK_GT(i::Isolate::Current()->thread_manager()->CurrentId(), 0);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000240 SetV8ThreadId();
ager@chromium.orga1645e22009-09-09 19:27:10 +0000241 while (IsRunning()) {
ager@chromium.orga1645e22009-09-09 19:27:10 +0000242 v8::HandleScope scope;
243 v8::Persistent<v8::Context> context = v8::Context::New();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000244 CHECK(!context.IsEmpty());
245 {
246 v8::Context::Scope context_scope(context);
247 SignalRunning();
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000248 CompileRun(
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000249 "var j; for (var i=0; i<10000; ++i) { j = Math.sin(i); }");
250 }
ager@chromium.orga1645e22009-09-09 19:27:10 +0000251 context.Dispose();
252 i::OS::Sleep(1);
253 }
254 }
255};
256
257
258class LoopingNonJsThread : public LoopingThread {
259 public:
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000260 explicit LoopingNonJsThread(v8::internal::Isolate* isolate)
261 : LoopingThread(isolate) { }
ager@chromium.orga1645e22009-09-09 19:27:10 +0000262 void RunLoop() {
263 v8::Locker locker;
264 v8::Unlocker unlocker;
265 // Now thread has V8's id, but will not run VM code.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000266 CHECK(i::Isolate::Current() != NULL);
267 CHECK_GT(i::Isolate::Current()->thread_manager()->CurrentId(), 0);
ager@chromium.orga1645e22009-09-09 19:27:10 +0000268 double i = 10;
269 SignalRunning();
270 while (IsRunning()) {
271 i = sin(i);
272 i::OS::Sleep(1);
273 }
274 }
275};
276
277
278class TestSampler : public v8::internal::Sampler {
279 public:
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000280 explicit TestSampler(v8::internal::Isolate* isolate)
281 : Sampler(isolate, 0, true, true),
ager@chromium.orga1645e22009-09-09 19:27:10 +0000282 semaphore_(v8::internal::OS::CreateSemaphore(0)),
283 was_sample_stack_called_(false) {
284 }
285
286 ~TestSampler() { delete semaphore_; }
287
288 void SampleStack(v8::internal::TickSample*) {
289 was_sample_stack_called_ = true;
290 }
291
292 void Tick(v8::internal::TickSample*) { semaphore_->Signal(); }
293
294 bool WaitForTick() { return semaphore_->Wait(1000000); }
295
296 void Reset() { was_sample_stack_called_ = false; }
297
298 bool WasSampleStackCalled() { return was_sample_stack_called_; }
299
300 private:
301 v8::internal::Semaphore* semaphore_;
302 bool was_sample_stack_called_;
303};
304
305
306} // namespace
307
308TEST(ProfMultipleThreads) {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000309 TestSampler* sampler = NULL;
310 {
311 v8::Locker locker;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000312 sampler = new TestSampler(v8::internal::Isolate::Current());
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000313 sampler->Start();
314 CHECK(sampler->IsActive());
315 }
316
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000317 LoopingJsThread jsThread(v8::internal::Isolate::Current());
ager@chromium.orga1645e22009-09-09 19:27:10 +0000318 jsThread.Start();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000319 LoopingNonJsThread nonJsThread(v8::internal::Isolate::Current());
ager@chromium.orga1645e22009-09-09 19:27:10 +0000320 nonJsThread.Start();
321
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000322 CHECK(!sampler->WasSampleStackCalled());
ager@chromium.orga1645e22009-09-09 19:27:10 +0000323 jsThread.WaitForRunning();
324 jsThread.SendSigProf();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000325 CHECK(sampler->WaitForTick());
326 CHECK(sampler->WasSampleStackCalled());
327 sampler->Reset();
328 CHECK(!sampler->WasSampleStackCalled());
ager@chromium.orga1645e22009-09-09 19:27:10 +0000329 nonJsThread.WaitForRunning();
330 nonJsThread.SendSigProf();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000331 CHECK(!sampler->WaitForTick());
332 CHECK(!sampler->WasSampleStackCalled());
333 sampler->Stop();
ager@chromium.orga1645e22009-09-09 19:27:10 +0000334
335 jsThread.Stop();
336 nonJsThread.Stop();
337 jsThread.Join();
338 nonJsThread.Join();
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000339
340 delete sampler;
ager@chromium.orga1645e22009-09-09 19:27:10 +0000341}
342
343#endif // __linux__
344
345
sgjesse@chromium.org152a0b02009-10-07 13:50:16 +0000346// Test for issue http://crbug.com/23768 in Chromium.
347// Heap can contain scripts with already disposed external sources.
348// We need to verify that LogCompiledFunctions doesn't crash on them.
349namespace {
350
351class SimpleExternalString : public v8::String::ExternalStringResource {
352 public:
353 explicit SimpleExternalString(const char* source)
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000354 : utf_source_(StrLength(source)) {
sgjesse@chromium.org152a0b02009-10-07 13:50:16 +0000355 for (int i = 0; i < utf_source_.length(); ++i)
356 utf_source_[i] = source[i];
357 }
358 virtual ~SimpleExternalString() {}
359 virtual size_t length() const { return utf_source_.length(); }
360 virtual const uint16_t* data() const { return utf_source_.start(); }
361 private:
362 i::ScopedVector<uint16_t> utf_source_;
363};
364
365} // namespace
366
367TEST(Issue23768) {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000368 v8::HandleScope scope(v8::Isolate::GetCurrent());
sgjesse@chromium.org152a0b02009-10-07 13:50:16 +0000369 v8::Handle<v8::Context> env = v8::Context::New();
370 env->Enter();
371
372 SimpleExternalString source_ext_str("(function ext() {})();");
373 v8::Local<v8::String> source = v8::String::NewExternal(&source_ext_str);
374 // Script needs to have a name in order to trigger InitLineEnds execution.
375 v8::Handle<v8::String> origin = v8::String::New("issue-23768-test");
376 v8::Handle<v8::Script> evil_script = v8::Script::Compile(source, origin);
377 CHECK(!evil_script.IsEmpty());
378 CHECK(!evil_script->Run().IsEmpty());
379 i::Handle<i::ExternalTwoByteString> i_source(
380 i::ExternalTwoByteString::cast(*v8::Utils::OpenHandle(*source)));
381 // This situation can happen if source was an external string disposed
382 // by its owner.
383 i_source->set_resource(NULL);
384
385 // Must not crash.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000386 LOGGER->LogCompiledFunctions();
sgjesse@chromium.org152a0b02009-10-07 13:50:16 +0000387}
388
389
ager@chromium.org01beca72009-11-24 14:29:16 +0000390static v8::Handle<v8::Value> ObjMethod1(const v8::Arguments& args) {
391 return v8::Handle<v8::Value>();
392}
393
394TEST(LogCallbacks) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000395 ScopedLoggerInitializer initialize_logger(false);
ager@chromium.org01beca72009-11-24 14:29:16 +0000396
397 v8::Persistent<v8::FunctionTemplate> obj =
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +0000398 v8::Persistent<v8::FunctionTemplate>::New(v8::Isolate::GetCurrent(),
399 v8::FunctionTemplate::New());
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000400 obj->SetClassName(v8_str("Obj"));
ager@chromium.org01beca72009-11-24 14:29:16 +0000401 v8::Handle<v8::ObjectTemplate> proto = obj->PrototypeTemplate();
402 v8::Local<v8::Signature> signature = v8::Signature::New(obj);
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000403 proto->Set(v8_str("method1"),
ager@chromium.org01beca72009-11-24 14:29:16 +0000404 v8::FunctionTemplate::New(ObjMethod1,
405 v8::Handle<v8::Value>(),
406 signature),
407 static_cast<v8::PropertyAttribute>(v8::DontDelete));
408
ager@chromium.org5c838252010-02-19 08:53:10 +0000409 initialize_logger.env()->Global()->Set(v8_str("Obj"), obj->GetFunction());
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000410 CompileRun("Obj.prototype.method1.toString();");
ager@chromium.org01beca72009-11-24 14:29:16 +0000411
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000412 LOGGER->LogCompiledFunctions();
ager@chromium.org01beca72009-11-24 14:29:16 +0000413
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000414 bool exists = false;
415 i::Vector<const char> log(
416 i::ReadFile(initialize_logger.StopLoggingGetTempFile(), &exists, true));
417 CHECK(exists);
418
419 i::EmbeddedVector<char, 100> ref_data;
ager@chromium.org01beca72009-11-24 14:29:16 +0000420 i::OS::SNPrintF(ref_data,
svenpanne@chromium.org83130cf2012-11-30 10:13:25 +0000421 "code-creation,Callback,-3,0x%" V8PRIxPTR ",1,\"method1\"\0",
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000422 ObjMethod1);
423
424 CHECK_NE(NULL, StrNStr(log.start(), ref_data.start(), log.length()));
ager@chromium.org01beca72009-11-24 14:29:16 +0000425
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +0000426 obj.Dispose(v8::Isolate::GetCurrent());
ager@chromium.org01beca72009-11-24 14:29:16 +0000427}
428
429
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000430static v8::Handle<v8::Value> Prop1Getter(v8::Local<v8::String> property,
431 const v8::AccessorInfo& info) {
432 return v8::Handle<v8::Value>();
433}
434
435static void Prop1Setter(v8::Local<v8::String> property,
436 v8::Local<v8::Value> value,
437 const v8::AccessorInfo& info) {
438}
439
440static v8::Handle<v8::Value> Prop2Getter(v8::Local<v8::String> property,
441 const v8::AccessorInfo& info) {
442 return v8::Handle<v8::Value>();
443}
444
445TEST(LogAccessorCallbacks) {
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000446 ScopedLoggerInitializer initialize_logger(false);
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000447
448 v8::Persistent<v8::FunctionTemplate> obj =
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +0000449 v8::Persistent<v8::FunctionTemplate>::New(v8::Isolate::GetCurrent(),
450 v8::FunctionTemplate::New());
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000451 obj->SetClassName(v8_str("Obj"));
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000452 v8::Handle<v8::ObjectTemplate> inst = obj->InstanceTemplate();
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000453 inst->SetAccessor(v8_str("prop1"), Prop1Getter, Prop1Setter);
454 inst->SetAccessor(v8_str("prop2"), Prop2Getter);
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000455
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000456 LOGGER->LogAccessorCallbacks();
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000457
458 bool exists = false;
459 i::Vector<const char> log(
460 i::ReadFile(initialize_logger.StopLoggingGetTempFile(), &exists, true));
461 CHECK(exists);
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000462
463 EmbeddedVector<char, 100> prop1_getter_record;
464 i::OS::SNPrintF(prop1_getter_record,
svenpanne@chromium.org83130cf2012-11-30 10:13:25 +0000465 "code-creation,Callback,-3,0x%" V8PRIxPTR ",1,\"get prop1\"",
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000466 Prop1Getter);
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000467 CHECK_NE(NULL,
468 StrNStr(log.start(), prop1_getter_record.start(), log.length()));
469
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000470 EmbeddedVector<char, 100> prop1_setter_record;
471 i::OS::SNPrintF(prop1_setter_record,
svenpanne@chromium.org83130cf2012-11-30 10:13:25 +0000472 "code-creation,Callback,-3,0x%" V8PRIxPTR ",1,\"set prop1\"",
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000473 Prop1Setter);
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000474 CHECK_NE(NULL,
475 StrNStr(log.start(), prop1_setter_record.start(), log.length()));
476
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000477 EmbeddedVector<char, 100> prop2_getter_record;
478 i::OS::SNPrintF(prop2_getter_record,
svenpanne@chromium.org83130cf2012-11-30 10:13:25 +0000479 "code-creation,Callback,-3,0x%" V8PRIxPTR ",1,\"get prop2\"",
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000480 Prop2Getter);
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000481 CHECK_NE(NULL,
482 StrNStr(log.start(), prop2_getter_record.start(), log.length()));
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000483
mvstanton@chromium.orgd16d8532013-01-25 13:29:10 +0000484 obj.Dispose(v8::Isolate::GetCurrent());
ager@chromium.org5c838252010-02-19 08:53:10 +0000485}
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +0000486
ager@chromium.org5c838252010-02-19 08:53:10 +0000487
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000488TEST(IsLoggingPreserved) {
489 ScopedLoggerInitializer initialize_logger(false);
490
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000491 CHECK(LOGGER->is_logging());
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000492 LOGGER->ResumeProfiler();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000493 CHECK(LOGGER->is_logging());
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000494 LOGGER->PauseProfiler();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000495 CHECK(LOGGER->is_logging());
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000496}
497
498
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +0000499typedef i::NativesCollection<i::TEST> TestSources;
500
lrn@chromium.org34e60782011-09-15 07:25:40 +0000501
502// Test that logging of code create / move events is equivalent to traversal of
503// a resulting heap.
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000504TEST(EquivalenceOfLoggingAndTraversal) {
505 // This test needs to be run on a "clean" V8 to ensure that snapshot log
506 // is loaded. This is always true when running using tools/test.py because
507 // it launches a new cctest instance for every test. To be sure that launching
508 // cctest manually also works, please be sure that no tests below
509 // are using V8.
510 //
511 // P.S. No, V8 can't be re-initialized after disposal, see include/v8.h.
512 CHECK(!i::V8::IsRunning());
513
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000514 // Start with profiling to capture all code events from the beginning.
515 ScopedLoggerInitializer initialize_logger(false);
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000516
517 // Compile and run a function that creates other functions.
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000518 CompileRun(
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000519 "(function f(obj) {\n"
520 " obj.test =\n"
521 " (function a(j) { return function b() { return j; } })(100);\n"
522 "})(this);");
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000523 v8::V8::PauseProfiler();
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000524 HEAP->CollectAllGarbage(i::Heap::kMakeHeapIterableMask);
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000525 LOGGER->StringEvent("test-logging-done", "");
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000526
527 // Iterate heap to find compiled functions, will write to log.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000528 LOGGER->LogCompiledFunctions();
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000529 LOGGER->StringEvent("test-traversal-done", "");
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000530
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000531 bool exists = false;
532 i::Vector<const char> log(
533 i::ReadFile(initialize_logger.StopLoggingGetTempFile(), &exists, true));
534 CHECK(exists);
535 v8::Handle<v8::String> log_str = v8::String::New(log.start(), log.length());
536 initialize_logger.env()->Global()->Set(v8_str("_log"), log_str);
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000537
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +0000538 i::Vector<const unsigned char> source = TestSources::GetScriptsSource();
539 v8::Handle<v8::String> source_str = v8::String::New(
540 reinterpret_cast<const char*>(source.start()), source.length());
541 v8::TryCatch try_catch;
542 v8::Handle<v8::Script> script = v8::Script::Compile(source_str, v8_str(""));
543 if (script.IsEmpty()) {
544 v8::String::Utf8Value exception(try_catch.Exception());
545 printf("compile: %s\n", *exception);
546 CHECK(false);
547 }
548 v8::Handle<v8::Value> result = script->Run();
549 if (result.IsEmpty()) {
550 v8::String::Utf8Value exception(try_catch.Exception());
551 printf("run: %s\n", *exception);
552 CHECK(false);
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000553 }
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000554 // The result either be a "true" literal or problem description.
svenpanne@chromium.org84bcc552011-07-18 09:50:57 +0000555 if (!result->IsTrue()) {
556 v8::Local<v8::String> s = result->ToString();
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000557 i::ScopedVector<char> data(s->Length() + 1);
558 CHECK_NE(NULL, data.start());
559 s->WriteAscii(data.start());
560 printf("%s\n", data.start());
561 // Make sure that our output is written prior crash due to CHECK failure.
562 fflush(stdout);
563 CHECK(false);
564 }
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000565}