OLD | NEW |
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
54 | 54 |
55 | 55 |
56 class ScopedLoggerInitializer { | 56 class ScopedLoggerInitializer { |
57 public: | 57 public: |
58 ScopedLoggerInitializer() | 58 ScopedLoggerInitializer() |
59 : saved_log_(i::FLAG_log), | 59 : saved_log_(i::FLAG_log), |
60 saved_prof_(i::FLAG_prof), | 60 saved_prof_(i::FLAG_prof), |
61 temp_file_(NULL), | 61 temp_file_(NULL), |
62 // Need to run this prior to creating the scope. | 62 // Need to run this prior to creating the scope. |
63 trick_to_run_init_flags_(init_flags_()), | 63 trick_to_run_init_flags_(init_flags_()), |
64 scope_(CcTest::isolate()), | 64 isolate_(v8::Isolate::New()), |
65 env_(v8::Context::New(CcTest::isolate())), | 65 isolate_scope_(isolate_), |
66 logger_(CcTest::i_isolate()->logger()) { | 66 scope_(isolate_), |
| 67 env_(v8::Context::New(isolate_)), |
| 68 logger_(reinterpret_cast<i::Isolate*>(isolate_)->logger()) { |
67 env_->Enter(); | 69 env_->Enter(); |
68 } | 70 } |
69 | 71 |
70 ~ScopedLoggerInitializer() { | 72 ~ScopedLoggerInitializer() { |
71 env_->Exit(); | 73 env_->Exit(); |
72 logger_->TearDown(); | 74 logger_->TearDown(); |
73 if (temp_file_ != NULL) fclose(temp_file_); | 75 if (temp_file_ != NULL) fclose(temp_file_); |
74 i::FLAG_prof = saved_prof_; | 76 i::FLAG_prof = saved_prof_; |
75 i::FLAG_log = saved_log_; | 77 i::FLAG_log = saved_log_; |
76 } | 78 } |
77 | 79 |
78 v8::Handle<v8::Context>& env() { return env_; } | 80 v8::Handle<v8::Context>& env() { return env_; } |
79 | 81 |
| 82 v8::Isolate* isolate() { return isolate_; } |
| 83 |
80 Logger* logger() { return logger_; } | 84 Logger* logger() { return logger_; } |
81 | 85 |
82 FILE* StopLoggingGetTempFile() { | 86 FILE* StopLoggingGetTempFile() { |
83 temp_file_ = logger_->TearDown(); | 87 temp_file_ = logger_->TearDown(); |
84 CHECK_NE(NULL, temp_file_); | 88 CHECK_NE(NULL, temp_file_); |
85 fflush(temp_file_); | 89 fflush(temp_file_); |
86 rewind(temp_file_); | 90 rewind(temp_file_); |
87 return temp_file_; | 91 return temp_file_; |
88 } | 92 } |
89 | 93 |
90 private: | 94 private: |
91 static bool init_flags_() { | 95 static bool init_flags_() { |
92 i::FLAG_log = true; | 96 i::FLAG_log = true; |
93 i::FLAG_prof = true; | 97 i::FLAG_prof = true; |
94 i::FLAG_logfile = i::Log::kLogToTemporaryFile; | 98 i::FLAG_logfile = i::Log::kLogToTemporaryFile; |
95 i::FLAG_logfile_per_isolate = false; | 99 i::FLAG_logfile_per_isolate = false; |
96 return false; | 100 return false; |
97 } | 101 } |
98 | 102 |
99 const bool saved_log_; | 103 const bool saved_log_; |
100 const bool saved_prof_; | 104 const bool saved_prof_; |
101 FILE* temp_file_; | 105 FILE* temp_file_; |
102 const bool trick_to_run_init_flags_; | 106 const bool trick_to_run_init_flags_; |
| 107 v8::Isolate* isolate_; |
| 108 v8::Isolate::Scope isolate_scope_; |
103 v8::HandleScope scope_; | 109 v8::HandleScope scope_; |
104 v8::Handle<v8::Context> env_; | 110 v8::Handle<v8::Context> env_; |
105 Logger* logger_; | 111 Logger* logger_; |
106 | 112 |
107 DISALLOW_COPY_AND_ASSIGN(ScopedLoggerInitializer); | 113 DISALLOW_COPY_AND_ASSIGN(ScopedLoggerInitializer); |
108 }; | 114 }; |
109 | 115 |
110 } // namespace | 116 } // namespace |
111 | 117 |
112 | 118 |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
323 // Must not crash. | 329 // Must not crash. |
324 CcTest::i_isolate()->logger()->LogCompiledFunctions(); | 330 CcTest::i_isolate()->logger()->LogCompiledFunctions(); |
325 } | 331 } |
326 | 332 |
327 | 333 |
328 static void ObjMethod1(const v8::FunctionCallbackInfo<v8::Value>& args) { | 334 static void ObjMethod1(const v8::FunctionCallbackInfo<v8::Value>& args) { |
329 } | 335 } |
330 | 336 |
331 | 337 |
332 TEST(LogCallbacks) { | 338 TEST(LogCallbacks) { |
333 v8::Isolate* isolate = CcTest::isolate(); | 339 v8::Isolate* isolate; |
334 ScopedLoggerInitializer initialize_logger; | 340 { |
335 Logger* logger = initialize_logger.logger(); | 341 ScopedLoggerInitializer initialize_logger; |
| 342 isolate = initialize_logger.isolate(); |
| 343 Logger* logger = initialize_logger.logger(); |
336 | 344 |
337 v8::Local<v8::FunctionTemplate> obj = | 345 v8::Local<v8::FunctionTemplate> obj = v8::Local<v8::FunctionTemplate>::New( |
338 v8::Local<v8::FunctionTemplate>::New(isolate, | 346 isolate, v8::FunctionTemplate::New(isolate)); |
339 v8::FunctionTemplate::New(isolate)); | 347 obj->SetClassName(v8_str("Obj")); |
340 obj->SetClassName(v8_str("Obj")); | 348 v8::Handle<v8::ObjectTemplate> proto = obj->PrototypeTemplate(); |
341 v8::Handle<v8::ObjectTemplate> proto = obj->PrototypeTemplate(); | 349 v8::Local<v8::Signature> signature = v8::Signature::New(isolate, obj); |
342 v8::Local<v8::Signature> signature = | 350 proto->Set(v8_str("method1"), |
343 v8::Signature::New(isolate, obj); | 351 v8::FunctionTemplate::New(isolate, ObjMethod1, |
344 proto->Set(v8_str("method1"), | 352 v8::Handle<v8::Value>(), signature), |
345 v8::FunctionTemplate::New(isolate, | 353 static_cast<v8::PropertyAttribute>(v8::DontDelete)); |
346 ObjMethod1, | |
347 v8::Handle<v8::Value>(), | |
348 signature), | |
349 static_cast<v8::PropertyAttribute>(v8::DontDelete)); | |
350 | 354 |
351 initialize_logger.env()->Global()->Set(v8_str("Obj"), obj->GetFunction()); | 355 initialize_logger.env()->Global()->Set(v8_str("Obj"), obj->GetFunction()); |
352 CompileRun("Obj.prototype.method1.toString();"); | 356 CompileRun("Obj.prototype.method1.toString();"); |
353 | 357 |
354 logger->LogCompiledFunctions(); | 358 logger->LogCompiledFunctions(); |
355 | 359 |
356 bool exists = false; | 360 bool exists = false; |
357 i::Vector<const char> log( | 361 i::Vector<const char> log( |
358 i::ReadFile(initialize_logger.StopLoggingGetTempFile(), &exists, true)); | 362 i::ReadFile(initialize_logger.StopLoggingGetTempFile(), &exists, true)); |
359 CHECK(exists); | 363 CHECK(exists); |
360 | 364 |
361 i::EmbeddedVector<char, 100> ref_data; | 365 i::EmbeddedVector<char, 100> ref_data; |
362 i::SNPrintF(ref_data, | 366 i::SNPrintF(ref_data, |
363 "code-creation,Callback,-2,0x%" V8PRIxPTR ",1,\"method1\"", | 367 "code-creation,Callback,-2,0x%" V8PRIxPTR ",1,\"method1\"", |
364 reinterpret_cast<intptr_t>(ObjMethod1)); | 368 reinterpret_cast<intptr_t>(ObjMethod1)); |
365 | 369 |
366 CHECK_NE(NULL, StrNStr(log.start(), ref_data.start(), log.length())); | 370 CHECK_NE(NULL, StrNStr(log.start(), ref_data.start(), log.length())); |
367 log.Dispose(); | 371 log.Dispose(); |
| 372 } |
| 373 isolate->Dispose(); |
368 } | 374 } |
369 | 375 |
370 | 376 |
371 static void Prop1Getter(v8::Local<v8::String> property, | 377 static void Prop1Getter(v8::Local<v8::String> property, |
372 const v8::PropertyCallbackInfo<v8::Value>& info) { | 378 const v8::PropertyCallbackInfo<v8::Value>& info) { |
373 } | 379 } |
374 | 380 |
375 static void Prop1Setter(v8::Local<v8::String> property, | 381 static void Prop1Setter(v8::Local<v8::String> property, |
376 v8::Local<v8::Value> value, | 382 v8::Local<v8::Value> value, |
377 const v8::PropertyCallbackInfo<void>& info) { | 383 const v8::PropertyCallbackInfo<void>& info) { |
378 } | 384 } |
379 | 385 |
380 static void Prop2Getter(v8::Local<v8::String> property, | 386 static void Prop2Getter(v8::Local<v8::String> property, |
381 const v8::PropertyCallbackInfo<v8::Value>& info) { | 387 const v8::PropertyCallbackInfo<v8::Value>& info) { |
382 } | 388 } |
383 | 389 |
384 | 390 |
385 TEST(LogAccessorCallbacks) { | 391 TEST(LogAccessorCallbacks) { |
386 v8::Isolate* isolate = CcTest::isolate(); | 392 v8::Isolate* isolate; |
387 ScopedLoggerInitializer initialize_logger; | 393 { |
388 Logger* logger = initialize_logger.logger(); | 394 ScopedLoggerInitializer initialize_logger; |
| 395 isolate = initialize_logger.isolate(); |
| 396 Logger* logger = initialize_logger.logger(); |
389 | 397 |
390 v8::Local<v8::FunctionTemplate> obj = | 398 v8::Local<v8::FunctionTemplate> obj = v8::Local<v8::FunctionTemplate>::New( |
391 v8::Local<v8::FunctionTemplate>::New(isolate, | 399 isolate, v8::FunctionTemplate::New(isolate)); |
392 v8::FunctionTemplate::New(isolate)); | 400 obj->SetClassName(v8_str("Obj")); |
393 obj->SetClassName(v8_str("Obj")); | 401 v8::Handle<v8::ObjectTemplate> inst = obj->InstanceTemplate(); |
394 v8::Handle<v8::ObjectTemplate> inst = obj->InstanceTemplate(); | 402 inst->SetAccessor(v8_str("prop1"), Prop1Getter, Prop1Setter); |
395 inst->SetAccessor(v8_str("prop1"), Prop1Getter, Prop1Setter); | 403 inst->SetAccessor(v8_str("prop2"), Prop2Getter); |
396 inst->SetAccessor(v8_str("prop2"), Prop2Getter); | |
397 | 404 |
398 logger->LogAccessorCallbacks(); | 405 logger->LogAccessorCallbacks(); |
399 | 406 |
400 bool exists = false; | 407 bool exists = false; |
401 i::Vector<const char> log( | 408 i::Vector<const char> log( |
402 i::ReadFile(initialize_logger.StopLoggingGetTempFile(), &exists, true)); | 409 i::ReadFile(initialize_logger.StopLoggingGetTempFile(), &exists, true)); |
403 CHECK(exists); | 410 CHECK(exists); |
404 | 411 |
405 EmbeddedVector<char, 100> prop1_getter_record; | 412 EmbeddedVector<char, 100> prop1_getter_record; |
406 i::SNPrintF(prop1_getter_record, | 413 i::SNPrintF(prop1_getter_record, |
407 "code-creation,Callback,-2,0x%" V8PRIxPTR ",1,\"get prop1\"", | 414 "code-creation,Callback,-2,0x%" V8PRIxPTR ",1,\"get prop1\"", |
408 reinterpret_cast<intptr_t>(Prop1Getter)); | 415 reinterpret_cast<intptr_t>(Prop1Getter)); |
409 CHECK_NE(NULL, | 416 CHECK_NE(NULL, |
410 StrNStr(log.start(), prop1_getter_record.start(), log.length())); | 417 StrNStr(log.start(), prop1_getter_record.start(), log.length())); |
411 | 418 |
412 EmbeddedVector<char, 100> prop1_setter_record; | 419 EmbeddedVector<char, 100> prop1_setter_record; |
413 i::SNPrintF(prop1_setter_record, | 420 i::SNPrintF(prop1_setter_record, |
414 "code-creation,Callback,-2,0x%" V8PRIxPTR ",1,\"set prop1\"", | 421 "code-creation,Callback,-2,0x%" V8PRIxPTR ",1,\"set prop1\"", |
415 reinterpret_cast<intptr_t>(Prop1Setter)); | 422 reinterpret_cast<intptr_t>(Prop1Setter)); |
416 CHECK_NE(NULL, | 423 CHECK_NE(NULL, |
417 StrNStr(log.start(), prop1_setter_record.start(), log.length())); | 424 StrNStr(log.start(), prop1_setter_record.start(), log.length())); |
418 | 425 |
419 EmbeddedVector<char, 100> prop2_getter_record; | 426 EmbeddedVector<char, 100> prop2_getter_record; |
420 i::SNPrintF(prop2_getter_record, | 427 i::SNPrintF(prop2_getter_record, |
421 "code-creation,Callback,-2,0x%" V8PRIxPTR ",1,\"get prop2\"", | 428 "code-creation,Callback,-2,0x%" V8PRIxPTR ",1,\"get prop2\"", |
422 reinterpret_cast<intptr_t>(Prop2Getter)); | 429 reinterpret_cast<intptr_t>(Prop2Getter)); |
423 CHECK_NE(NULL, | 430 CHECK_NE(NULL, |
424 StrNStr(log.start(), prop2_getter_record.start(), log.length())); | 431 StrNStr(log.start(), prop2_getter_record.start(), log.length())); |
425 log.Dispose(); | 432 log.Dispose(); |
| 433 } |
| 434 isolate->Dispose(); |
426 } | 435 } |
427 | 436 |
428 | 437 |
429 typedef i::NativesCollection<i::TEST> TestSources; | 438 typedef i::NativesCollection<i::TEST> TestSources; |
430 | 439 |
431 | 440 |
432 // Test that logging of code create / move events is equivalent to traversal of | 441 // Test that logging of code create / move events is equivalent to traversal of |
433 // a resulting heap. | 442 // a resulting heap. |
434 TEST(EquivalenceOfLoggingAndTraversal) { | 443 TEST(EquivalenceOfLoggingAndTraversal) { |
435 // This test needs to be run on a "clean" V8 to ensure that snapshot log | 444 // This test needs to be run on a "clean" V8 to ensure that snapshot log |
436 // is loaded. This is always true when running using tools/test.py because | 445 // is loaded. This is always true when running using tools/test.py because |
437 // it launches a new cctest instance for every test. To be sure that launching | 446 // it launches a new cctest instance for every test. To be sure that launching |
438 // cctest manually also works, please be sure that no tests below | 447 // cctest manually also works, please be sure that no tests below |
439 // are using V8. | 448 // are using V8. |
440 | 449 |
441 // Start with profiling to capture all code events from the beginning. | 450 // Start with profiling to capture all code events from the beginning. |
442 ScopedLoggerInitializer initialize_logger; | 451 v8::Isolate* isolate; |
443 Logger* logger = initialize_logger.logger(); | 452 { |
| 453 ScopedLoggerInitializer initialize_logger; |
| 454 isolate = initialize_logger.isolate(); |
| 455 Logger* logger = initialize_logger.logger(); |
444 | 456 |
445 // Compile and run a function that creates other functions. | 457 // Compile and run a function that creates other functions. |
446 CompileRun( | 458 CompileRun( |
447 "(function f(obj) {\n" | 459 "(function f(obj) {\n" |
448 " obj.test =\n" | 460 " obj.test =\n" |
449 " (function a(j) { return function b() { return j; } })(100);\n" | 461 " (function a(j) { return function b() { return j; } })(100);\n" |
450 "})(this);"); | 462 "})(this);"); |
451 logger->StopProfiler(); | 463 logger->StopProfiler(); |
452 CcTest::heap()->CollectAllGarbage(i::Heap::kMakeHeapIterableMask); | 464 reinterpret_cast<i::Isolate*>(isolate)->heap()->CollectAllGarbage( |
453 logger->StringEvent("test-logging-done", ""); | 465 i::Heap::kMakeHeapIterableMask); |
| 466 logger->StringEvent("test-logging-done", ""); |
454 | 467 |
455 // Iterate heap to find compiled functions, will write to log. | 468 // Iterate heap to find compiled functions, will write to log. |
456 logger->LogCompiledFunctions(); | 469 logger->LogCompiledFunctions(); |
457 logger->StringEvent("test-traversal-done", ""); | 470 logger->StringEvent("test-traversal-done", ""); |
458 | 471 |
459 bool exists = false; | 472 bool exists = false; |
460 i::Vector<const char> log( | 473 i::Vector<const char> log( |
461 i::ReadFile(initialize_logger.StopLoggingGetTempFile(), &exists, true)); | 474 i::ReadFile(initialize_logger.StopLoggingGetTempFile(), &exists, true)); |
462 CHECK(exists); | 475 CHECK(exists); |
463 v8::Handle<v8::String> log_str = v8::String::NewFromUtf8( | 476 v8::Handle<v8::String> log_str = v8::String::NewFromUtf8( |
464 CcTest::isolate(), log.start(), v8::String::kNormalString, log.length()); | 477 isolate, log.start(), v8::String::kNormalString, log.length()); |
465 initialize_logger.env()->Global()->Set(v8_str("_log"), log_str); | 478 initialize_logger.env()->Global()->Set(v8_str("_log"), log_str); |
466 | 479 |
467 i::Vector<const unsigned char> source = TestSources::GetScriptsSource(); | 480 i::Vector<const unsigned char> source = TestSources::GetScriptsSource(); |
468 v8::Handle<v8::String> source_str = v8::String::NewFromUtf8( | 481 v8::Handle<v8::String> source_str = v8::String::NewFromUtf8( |
469 CcTest::isolate(), reinterpret_cast<const char*>(source.start()), | 482 isolate, reinterpret_cast<const char*>(source.start()), |
470 v8::String::kNormalString, source.length()); | 483 v8::String::kNormalString, source.length()); |
471 v8::TryCatch try_catch; | 484 v8::TryCatch try_catch; |
472 v8::Handle<v8::Script> script = CompileWithOrigin(source_str, ""); | 485 v8::Handle<v8::Script> script = CompileWithOrigin(source_str, ""); |
473 if (script.IsEmpty()) { | 486 if (script.IsEmpty()) { |
474 v8::String::Utf8Value exception(try_catch.Exception()); | 487 v8::String::Utf8Value exception(try_catch.Exception()); |
475 printf("compile: %s\n", *exception); | 488 printf("compile: %s\n", *exception); |
476 CHECK(false); | 489 CHECK(false); |
| 490 } |
| 491 v8::Handle<v8::Value> result = script->Run(); |
| 492 if (result.IsEmpty()) { |
| 493 v8::String::Utf8Value exception(try_catch.Exception()); |
| 494 printf("run: %s\n", *exception); |
| 495 CHECK(false); |
| 496 } |
| 497 // The result either be a "true" literal or problem description. |
| 498 if (!result->IsTrue()) { |
| 499 v8::Local<v8::String> s = result->ToString(); |
| 500 i::ScopedVector<char> data(s->Utf8Length() + 1); |
| 501 CHECK_NE(NULL, data.start()); |
| 502 s->WriteUtf8(data.start()); |
| 503 printf("%s\n", data.start()); |
| 504 // Make sure that our output is written prior crash due to CHECK failure. |
| 505 fflush(stdout); |
| 506 CHECK(false); |
| 507 } |
477 } | 508 } |
478 v8::Handle<v8::Value> result = script->Run(); | 509 isolate->Dispose(); |
479 if (result.IsEmpty()) { | |
480 v8::String::Utf8Value exception(try_catch.Exception()); | |
481 printf("run: %s\n", *exception); | |
482 CHECK(false); | |
483 } | |
484 // The result either be a "true" literal or problem description. | |
485 if (!result->IsTrue()) { | |
486 v8::Local<v8::String> s = result->ToString(); | |
487 i::ScopedVector<char> data(s->Utf8Length() + 1); | |
488 CHECK_NE(NULL, data.start()); | |
489 s->WriteUtf8(data.start()); | |
490 printf("%s\n", data.start()); | |
491 // Make sure that our output is written prior crash due to CHECK failure. | |
492 fflush(stdout); | |
493 CHECK(false); | |
494 } | |
495 } | 510 } |
OLD | NEW |