1// Copyright 2006-2009 the V8 project authors. All rights reserved. 2// 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. 27// 28// Tests of logging functions from log.h 29 30#ifdef __linux__ 31#include <pthread.h> 32#include <signal.h> 33#include <unistd.h> 34#include <cmath> 35#endif // __linux__ 36 37#include "src/v8.h" 38 39#include "src/log.h" 40#include "src/log-utils.h" 41#include "src/profiler/cpu-profiler.h" 42#include "src/snapshot/natives.h" 43#include "src/utils.h" 44#include "src/v8threads.h" 45#include "src/version.h" 46#include "src/vm-state-inl.h" 47#include "test/cctest/cctest.h" 48 49using v8::internal::Address; 50using v8::internal::EmbeddedVector; 51using v8::internal::Logger; 52using v8::internal::StrLength; 53 54namespace { 55 56 57#define SETUP_FLAGS() \ 58 bool saved_log = i::FLAG_log; \ 59 bool saved_prof = i::FLAG_prof; \ 60 i::FLAG_log = true; \ 61 i::FLAG_prof = true; \ 62 i::FLAG_logfile = i::Log::kLogToTemporaryFile; \ 63 i::FLAG_logfile_per_isolate = false 64 65 66class ScopedLoggerInitializer { 67 public: 68 ScopedLoggerInitializer(bool saved_log, bool saved_prof, v8::Isolate* isolate) 69 : saved_log_(saved_log), 70 saved_prof_(saved_prof), 71 temp_file_(NULL), 72 isolate_(isolate), 73 isolate_scope_(isolate), 74 scope_(isolate), 75 env_(v8::Context::New(isolate)), 76 logger_(reinterpret_cast<i::Isolate*>(isolate)->logger()) { 77 env_->Enter(); 78 } 79 80 ~ScopedLoggerInitializer() { 81 env_->Exit(); 82 logger_->TearDown(); 83 if (temp_file_ != NULL) fclose(temp_file_); 84 i::FLAG_prof = saved_prof_; 85 i::FLAG_log = saved_log_; 86 } 87 88 v8::Local<v8::Context>& env() { return env_; } 89 90 v8::Isolate* isolate() { return isolate_; } 91 92 Logger* logger() { return logger_; } 93 94 FILE* StopLoggingGetTempFile() { 95 temp_file_ = logger_->TearDown(); 96 CHECK(temp_file_); 97 fflush(temp_file_); 98 rewind(temp_file_); 99 return temp_file_; 100 } 101 102 private: 103 const bool saved_log_; 104 const bool saved_prof_; 105 FILE* temp_file_; 106 v8::Isolate* isolate_; 107 v8::Isolate::Scope isolate_scope_; 108 v8::HandleScope scope_; 109 v8::Local<v8::Context> env_; 110 Logger* logger_; 111 112 DISALLOW_COPY_AND_ASSIGN(ScopedLoggerInitializer); 113}; 114 115} // namespace 116 117 118static 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::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; 125} 126 127 128// BUG(913). Need to implement support for profiling multiple VM threads. 129#if 0 130 131namespace { 132 133class LoopingThread : public v8::internal::Thread { 134 public: 135 explicit LoopingThread(v8::internal::Isolate* isolate) 136 : v8::internal::Thread(isolate), 137 semaphore_(new v8::internal::Semaphore(0)), 138 run_(true) { 139 } 140 141 virtual ~LoopingThread() { delete semaphore_; } 142 143 void Run() { 144 self_ = pthread_self(); 145 RunLoop(); 146 } 147 148 void SendSigProf() { pthread_kill(self_, SIGPROF); } 149 150 void Stop() { run_ = false; } 151 152 bool WaitForRunning() { return semaphore_->Wait(1000000); } 153 154 protected: 155 bool IsRunning() { return run_; } 156 157 virtual void RunLoop() = 0; 158 159 void SetV8ThreadId() { 160 v8_thread_id_ = v8::V8::GetCurrentThreadId(); 161 } 162 163 void SignalRunning() { semaphore_->Signal(); } 164 165 private: 166 v8::internal::Semaphore* semaphore_; 167 bool run_; 168 pthread_t self_; 169 int v8_thread_id_; 170}; 171 172 173class LoopingJsThread : public LoopingThread { 174 public: 175 explicit LoopingJsThread(v8::internal::Isolate* isolate) 176 : LoopingThread(isolate) { } 177 void RunLoop() { 178 v8::Locker locker; 179 CHECK(CcTest::i_isolate() != NULL); 180 CHECK_GT(CcTest::i_isolate()->thread_manager()->CurrentId(), 0); 181 SetV8ThreadId(); 182 while (IsRunning()) { 183 v8::HandleScope scope; 184 v8::Persistent<v8::Context> context = v8::Context::New(); 185 CHECK(!context.IsEmpty()); 186 { 187 v8::Context::Scope context_scope(context); 188 SignalRunning(); 189 CompileRun( 190 "var j; for (var i=0; i<10000; ++i) { j = Math.sin(i); }"); 191 } 192 context.Dispose(); 193 i::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(1)); 194 } 195 } 196}; 197 198 199class LoopingNonJsThread : public LoopingThread { 200 public: 201 explicit LoopingNonJsThread(v8::internal::Isolate* isolate) 202 : LoopingThread(isolate) { } 203 void RunLoop() { 204 v8::Locker locker; 205 v8::Unlocker unlocker; 206 // Now thread has V8's id, but will not run VM code. 207 CHECK(CcTest::i_isolate() != NULL); 208 CHECK_GT(CcTest::i_isolate()->thread_manager()->CurrentId(), 0); 209 double i = 10; 210 SignalRunning(); 211 while (IsRunning()) { 212 i = std::sin(i); 213 i::OS::Sleep(v8::base::TimeDelta::FromMilliseconds(1)); 214 } 215 } 216}; 217 218 219class TestSampler : public v8::internal::Sampler { 220 public: 221 explicit TestSampler(v8::internal::Isolate* isolate) 222 : Sampler(isolate, 0, true, true), 223 semaphore_(new v8::internal::Semaphore(0)), 224 was_sample_stack_called_(false) { 225 } 226 227 ~TestSampler() { delete semaphore_; } 228 229 void SampleStack(v8::internal::TickSample*) { 230 was_sample_stack_called_ = true; 231 } 232 233 void Tick(v8::internal::TickSample*) { semaphore_->Signal(); } 234 235 bool WaitForTick() { return semaphore_->Wait(1000000); } 236 237 void Reset() { was_sample_stack_called_ = false; } 238 239 bool WasSampleStackCalled() { return was_sample_stack_called_; } 240 241 private: 242 v8::internal::Semaphore* semaphore_; 243 bool was_sample_stack_called_; 244}; 245 246 247} // namespace 248 249TEST(ProfMultipleThreads) { 250 TestSampler* sampler = NULL; 251 { 252 v8::Locker locker; 253 sampler = new TestSampler(CcTest::i_isolate()); 254 sampler->Start(); 255 CHECK(sampler->IsActive()); 256 } 257 258 LoopingJsThread jsThread(CcTest::i_isolate()); 259 jsThread.Start(); 260 LoopingNonJsThread nonJsThread(CcTest::i_isolate()); 261 nonJsThread.Start(); 262 263 CHECK(!sampler->WasSampleStackCalled()); 264 jsThread.WaitForRunning(); 265 jsThread.SendSigProf(); 266 CHECK(sampler->WaitForTick()); 267 CHECK(sampler->WasSampleStackCalled()); 268 sampler->Reset(); 269 CHECK(!sampler->WasSampleStackCalled()); 270 nonJsThread.WaitForRunning(); 271 nonJsThread.SendSigProf(); 272 CHECK(!sampler->WaitForTick()); 273 CHECK(!sampler->WasSampleStackCalled()); 274 sampler->Stop(); 275 276 jsThread.Stop(); 277 nonJsThread.Stop(); 278 jsThread.Join(); 279 nonJsThread.Join(); 280 281 delete sampler; 282} 283 284#endif // __linux__ 285 286 287// Test for issue http://crbug.com/23768 in Chromium. 288// Heap can contain scripts with already disposed external sources. 289// We need to verify that LogCompiledFunctions doesn't crash on them. 290namespace { 291 292class SimpleExternalString : public v8::String::ExternalStringResource { 293 public: 294 explicit SimpleExternalString(const char* source) 295 : utf_source_(StrLength(source)) { 296 for (int i = 0; i < utf_source_.length(); ++i) 297 utf_source_[i] = source[i]; 298 } 299 virtual ~SimpleExternalString() {} 300 virtual size_t length() const { return utf_source_.length(); } 301 virtual const uint16_t* data() const { return utf_source_.start(); } 302 private: 303 i::ScopedVector<uint16_t> utf_source_; 304}; 305 306} // namespace 307 308TEST(Issue23768) { 309 v8::HandleScope scope(CcTest::isolate()); 310 v8::Local<v8::Context> env = v8::Context::New(CcTest::isolate()); 311 env->Enter(); 312 313 SimpleExternalString source_ext_str("(function ext() {})();"); 314 v8::Local<v8::String> source = 315 v8::String::NewExternalTwoByte(CcTest::isolate(), &source_ext_str) 316 .ToLocalChecked(); 317 // Script needs to have a name in order to trigger InitLineEnds execution. 318 v8::Local<v8::String> origin = 319 v8::String::NewFromUtf8(CcTest::isolate(), "issue-23768-test", 320 v8::NewStringType::kNormal) 321 .ToLocalChecked(); 322 v8::Local<v8::Script> evil_script = CompileWithOrigin(source, origin); 323 CHECK(!evil_script.IsEmpty()); 324 CHECK(!evil_script->Run(env).IsEmpty()); 325 i::Handle<i::ExternalTwoByteString> i_source( 326 i::ExternalTwoByteString::cast(*v8::Utils::OpenHandle(*source))); 327 // This situation can happen if source was an external string disposed 328 // by its owner. 329 i_source->set_resource(NULL); 330 331 // Must not crash. 332 CcTest::i_isolate()->logger()->LogCompiledFunctions(); 333} 334 335 336static void ObjMethod1(const v8::FunctionCallbackInfo<v8::Value>& args) { 337} 338 339 340TEST(LogCallbacks) { 341 SETUP_FLAGS(); 342 v8::Isolate::CreateParams create_params; 343 create_params.array_buffer_allocator = CcTest::array_buffer_allocator(); 344 v8::Isolate* isolate = v8::Isolate::New(create_params); 345 { 346 ScopedLoggerInitializer initialize_logger(saved_log, saved_prof, isolate); 347 Logger* logger = initialize_logger.logger(); 348 349 v8::Local<v8::FunctionTemplate> obj = v8::Local<v8::FunctionTemplate>::New( 350 isolate, v8::FunctionTemplate::New(isolate)); 351 obj->SetClassName(v8_str("Obj")); 352 v8::Local<v8::ObjectTemplate> proto = obj->PrototypeTemplate(); 353 v8::Local<v8::Signature> signature = v8::Signature::New(isolate, obj); 354 proto->Set(v8_str("method1"), 355 v8::FunctionTemplate::New(isolate, ObjMethod1, 356 v8::Local<v8::Value>(), signature), 357 static_cast<v8::PropertyAttribute>(v8::DontDelete)); 358 359 initialize_logger.env() 360 ->Global() 361 ->Set(initialize_logger.env(), v8_str("Obj"), 362 obj->GetFunction(initialize_logger.env()).ToLocalChecked()) 363 .FromJust(); 364 CompileRun("Obj.prototype.method1.toString();"); 365 366 logger->LogCompiledFunctions(); 367 368 bool exists = false; 369 i::Vector<const char> log( 370 i::ReadFile(initialize_logger.StopLoggingGetTempFile(), &exists, true)); 371 CHECK(exists); 372 373 Address ObjMethod1_entry = reinterpret_cast<Address>(ObjMethod1); 374#if USES_FUNCTION_DESCRIPTORS 375 ObjMethod1_entry = *FUNCTION_ENTRYPOINT_ADDRESS(ObjMethod1_entry); 376#endif 377 i::EmbeddedVector<char, 100> ref_data; 378 i::SNPrintF(ref_data, "code-creation,Callback,-2,%p,1,\"method1\"", 379 static_cast<void*>(ObjMethod1_entry)); 380 381 CHECK(StrNStr(log.start(), ref_data.start(), log.length())); 382 log.Dispose(); 383 } 384 isolate->Dispose(); 385} 386 387 388static void Prop1Getter(v8::Local<v8::String> property, 389 const v8::PropertyCallbackInfo<v8::Value>& info) { 390} 391 392static void Prop1Setter(v8::Local<v8::String> property, 393 v8::Local<v8::Value> value, 394 const v8::PropertyCallbackInfo<void>& info) { 395} 396 397static void Prop2Getter(v8::Local<v8::String> property, 398 const v8::PropertyCallbackInfo<v8::Value>& info) { 399} 400 401 402TEST(LogAccessorCallbacks) { 403 SETUP_FLAGS(); 404 v8::Isolate::CreateParams create_params; 405 create_params.array_buffer_allocator = CcTest::array_buffer_allocator(); 406 v8::Isolate* isolate = v8::Isolate::New(create_params); 407 { 408 ScopedLoggerInitializer initialize_logger(saved_log, saved_prof, isolate); 409 Logger* logger = initialize_logger.logger(); 410 411 v8::Local<v8::FunctionTemplate> obj = v8::Local<v8::FunctionTemplate>::New( 412 isolate, v8::FunctionTemplate::New(isolate)); 413 obj->SetClassName(v8_str("Obj")); 414 v8::Local<v8::ObjectTemplate> inst = obj->InstanceTemplate(); 415 inst->SetAccessor(v8_str("prop1"), Prop1Getter, Prop1Setter); 416 inst->SetAccessor(v8_str("prop2"), Prop2Getter); 417 418 logger->LogAccessorCallbacks(); 419 420 bool exists = false; 421 i::Vector<const char> log( 422 i::ReadFile(initialize_logger.StopLoggingGetTempFile(), &exists, true)); 423 CHECK(exists); 424 425 Address Prop1Getter_entry = reinterpret_cast<Address>(Prop1Getter); 426#if USES_FUNCTION_DESCRIPTORS 427 Prop1Getter_entry = *FUNCTION_ENTRYPOINT_ADDRESS(Prop1Getter_entry); 428#endif 429 EmbeddedVector<char, 100> prop1_getter_record; 430 i::SNPrintF(prop1_getter_record, 431 "code-creation,Callback,-2,%p,1,\"get prop1\"", 432 static_cast<void*>(Prop1Getter_entry)); 433 CHECK(StrNStr(log.start(), prop1_getter_record.start(), log.length())); 434 435 Address Prop1Setter_entry = reinterpret_cast<Address>(Prop1Setter); 436#if USES_FUNCTION_DESCRIPTORS 437 Prop1Setter_entry = *FUNCTION_ENTRYPOINT_ADDRESS(Prop1Setter_entry); 438#endif 439 EmbeddedVector<char, 100> prop1_setter_record; 440 i::SNPrintF(prop1_setter_record, 441 "code-creation,Callback,-2,%p,1,\"set prop1\"", 442 static_cast<void*>(Prop1Setter_entry)); 443 CHECK(StrNStr(log.start(), prop1_setter_record.start(), log.length())); 444 445 Address Prop2Getter_entry = reinterpret_cast<Address>(Prop2Getter); 446#if USES_FUNCTION_DESCRIPTORS 447 Prop2Getter_entry = *FUNCTION_ENTRYPOINT_ADDRESS(Prop2Getter_entry); 448#endif 449 EmbeddedVector<char, 100> prop2_getter_record; 450 i::SNPrintF(prop2_getter_record, 451 "code-creation,Callback,-2,%p,1,\"get prop2\"", 452 static_cast<void*>(Prop2Getter_entry)); 453 CHECK(StrNStr(log.start(), prop2_getter_record.start(), log.length())); 454 log.Dispose(); 455 } 456 isolate->Dispose(); 457} 458 459 460typedef i::NativesCollection<i::TEST> TestSources; 461 462 463// Test that logging of code create / move events is equivalent to traversal of 464// a resulting heap. 465TEST(EquivalenceOfLoggingAndTraversal) { 466 // This test needs to be run on a "clean" V8 to ensure that snapshot log 467 // is loaded. This is always true when running using tools/test.py because 468 // it launches a new cctest instance for every test. To be sure that launching 469 // cctest manually also works, please be sure that no tests below 470 // are using V8. 471 472 // Start with profiling to capture all code events from the beginning. 473 SETUP_FLAGS(); 474 v8::Isolate::CreateParams create_params; 475 create_params.array_buffer_allocator = CcTest::array_buffer_allocator(); 476 v8::Isolate* isolate = v8::Isolate::New(create_params); 477 { 478 ScopedLoggerInitializer initialize_logger(saved_log, saved_prof, isolate); 479 Logger* logger = initialize_logger.logger(); 480 481 // Compile and run a function that creates other functions. 482 CompileRun( 483 "(function f(obj) {\n" 484 " obj.test =\n" 485 " (function a(j) { return function b() { return j; } })(100);\n" 486 "})(this);"); 487 logger->StopProfiler(); 488 reinterpret_cast<i::Isolate*>(isolate)->heap()->CollectAllGarbage( 489 i::Heap::kMakeHeapIterableMask); 490 logger->StringEvent("test-logging-done", ""); 491 492 // Iterate heap to find compiled functions, will write to log. 493 logger->LogCompiledFunctions(); 494 logger->StringEvent("test-traversal-done", ""); 495 496 bool exists = false; 497 i::Vector<const char> log( 498 i::ReadFile(initialize_logger.StopLoggingGetTempFile(), &exists, true)); 499 CHECK(exists); 500 v8::Local<v8::String> log_str = 501 v8::String::NewFromUtf8(isolate, log.start(), 502 v8::NewStringType::kNormal, log.length()) 503 .ToLocalChecked(); 504 initialize_logger.env() 505 ->Global() 506 ->Set(initialize_logger.env(), v8_str("_log"), log_str) 507 .FromJust(); 508 509 i::Vector<const char> source = TestSources::GetScriptsSource(); 510 v8::Local<v8::String> source_str = 511 v8::String::NewFromUtf8(isolate, source.start(), 512 v8::NewStringType::kNormal, source.length()) 513 .ToLocalChecked(); 514 v8::TryCatch try_catch(isolate); 515 v8::Local<v8::Script> script = CompileWithOrigin(source_str, ""); 516 if (script.IsEmpty()) { 517 v8::String::Utf8Value exception(try_catch.Exception()); 518 printf("compile: %s\n", *exception); 519 CHECK(false); 520 } 521 v8::Local<v8::Value> result; 522 if (!script->Run(initialize_logger.env()).ToLocal(&result)) { 523 v8::String::Utf8Value exception(try_catch.Exception()); 524 printf("run: %s\n", *exception); 525 CHECK(false); 526 } 527 // The result either be a "true" literal or problem description. 528 if (!result->IsTrue()) { 529 v8::Local<v8::String> s = 530 result->ToString(initialize_logger.env()).ToLocalChecked(); 531 i::ScopedVector<char> data(s->Utf8Length() + 1); 532 CHECK(data.start()); 533 s->WriteUtf8(data.start()); 534 printf("%s\n", data.start()); 535 // Make sure that our output is written prior crash due to CHECK failure. 536 fflush(stdout); 537 CHECK(false); 538 } 539 } 540 isolate->Dispose(); 541} 542 543 544TEST(LogVersion) { 545 SETUP_FLAGS(); 546 v8::Isolate::CreateParams create_params; 547 create_params.array_buffer_allocator = CcTest::array_buffer_allocator(); 548 v8::Isolate* isolate = v8::Isolate::New(create_params); 549 { 550 ScopedLoggerInitializer initialize_logger(saved_log, saved_prof, isolate); 551 bool exists = false; 552 i::Vector<const char> log( 553 i::ReadFile(initialize_logger.StopLoggingGetTempFile(), &exists, true)); 554 CHECK(exists); 555 i::EmbeddedVector<char, 100> ref_data; 556 i::SNPrintF(ref_data, "v8-version,%d,%d,%d,%d,%d", i::Version::GetMajor(), 557 i::Version::GetMinor(), i::Version::GetBuild(), 558 i::Version::GetPatch(), i::Version::IsCandidate()); 559 CHECK(StrNStr(log.start(), ref_data.start(), log.length())); 560 log.Dispose(); 561 } 562 isolate->Dispose(); 563} 564 565 566// https://crbug.com/539892 567// CodeCreateEvents with really large names should not crash. 568TEST(Issue539892) { 569 class : public i::CodeEventLogger { 570 public: 571 void CodeMoveEvent(i::AbstractCode* from, Address to) override {} 572 void CodeDisableOptEvent(i::AbstractCode* code, 573 i::SharedFunctionInfo* shared) override {} 574 575 private: 576 void LogRecordedBuffer(i::AbstractCode* code, i::SharedFunctionInfo* shared, 577 const char* name, int length) override {} 578 } code_event_logger; 579 SETUP_FLAGS(); 580 v8::Isolate::CreateParams create_params; 581 create_params.array_buffer_allocator = CcTest::array_buffer_allocator(); 582 v8::Isolate* isolate = v8::Isolate::New(create_params); 583 584 { 585 ScopedLoggerInitializer initialize_logger(saved_log, saved_prof, isolate); 586 Logger* logger = initialize_logger.logger(); 587 logger->addCodeEventListener(&code_event_logger); 588 589 // Function with a really large name. 590 const char* source_text = 591 "(function " 592 "baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 593 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 594 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 595 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 596 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 597 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 598 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 599 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 600 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 601 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 602 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 603 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 604 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 605 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 606 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 607 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 608 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaac" 609 "(){})();"; 610 611 CompileRun(source_text); 612 613 // Must not crash. 614 logger->LogCompiledFunctions(); 615 } 616 isolate->Dispose(); 617} 618