1 // Copyright 2012 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include <stdlib.h> 6 7 #include "src/v8.h" 8 9 #include "src/ast.h" 10 #include "src/base/platform/platform.h" 11 #include "src/base/sys-info.h" 12 #include "src/base/utils/random-number-generator.h" 13 #include "src/bootstrapper.h" 14 #include "src/codegen.h" 15 #include "src/compilation-cache.h" 16 #include "src/cpu-profiler.h" 17 #include "src/debug.h" 18 #include "src/deoptimizer.h" 19 #include "src/heap/spaces.h" 20 #include "src/heap/sweeper-thread.h" 21 #include "src/heap-profiler.h" 22 #include "src/hydrogen.h" 23 #include "src/ic/stub-cache.h" 24 #include "src/isolate-inl.h" 25 #include "src/lithium-allocator.h" 26 #include "src/log.h" 27 #include "src/messages.h" 28 #include "src/prototype.h" 29 #include "src/regexp-stack.h" 30 #include "src/runtime-profiler.h" 31 #include "src/sampler.h" 32 #include "src/scopeinfo.h" 33 #include "src/serialize.h" 34 #include "src/simulator.h" 35 #include "src/version.h" 36 #include "src/vm-state-inl.h" 37 38 39 namespace v8 { 40 namespace internal { 41 42 base::Atomic32 ThreadId::highest_thread_id_ = 0; 43 44 int ThreadId::AllocateThreadId() { 45 int new_id = base::NoBarrier_AtomicIncrement(&highest_thread_id_, 1); 46 return new_id; 47 } 48 49 50 int ThreadId::GetCurrentThreadId() { 51 int thread_id = base::Thread::GetThreadLocalInt(Isolate::thread_id_key_); 52 if (thread_id == 0) { 53 thread_id = AllocateThreadId(); 54 base::Thread::SetThreadLocalInt(Isolate::thread_id_key_, thread_id); 55 } 56 return thread_id; 57 } 58 59 60 ThreadLocalTop::ThreadLocalTop() { 61 InitializeInternal(); 62 } 63 64 65 void ThreadLocalTop::InitializeInternal() { 66 c_entry_fp_ = 0; 67 handler_ = 0; 68 #ifdef USE_SIMULATOR 69 simulator_ = NULL; 70 #endif 71 js_entry_sp_ = NULL; 72 external_callback_scope_ = NULL; 73 current_vm_state_ = EXTERNAL; 74 try_catch_handler_ = NULL; 75 context_ = NULL; 76 thread_id_ = ThreadId::Invalid(); 77 external_caught_exception_ = false; 78 failed_access_check_callback_ = NULL; 79 save_context_ = NULL; 80 catcher_ = NULL; 81 top_lookup_result_ = NULL; 82 promise_on_stack_ = NULL; 83 84 // These members are re-initialized later after deserialization 85 // is complete. 86 pending_exception_ = NULL; 87 has_pending_message_ = false; 88 rethrowing_message_ = false; 89 pending_message_obj_ = NULL; 90 pending_message_script_ = NULL; 91 scheduled_exception_ = NULL; 92 } 93 94 95 void ThreadLocalTop::Initialize() { 96 InitializeInternal(); 97 #ifdef USE_SIMULATOR 98 simulator_ = Simulator::current(isolate_); 99 #endif 100 thread_id_ = ThreadId::Current(); 101 } 102 103 104 void ThreadLocalTop::Free() { 105 // Match unmatched PopPromise calls. 106 while (promise_on_stack_) isolate_->PopPromise(); 107 } 108 109 110 base::Thread::LocalStorageKey Isolate::isolate_key_; 111 base::Thread::LocalStorageKey Isolate::thread_id_key_; 112 base::Thread::LocalStorageKey Isolate::per_isolate_thread_data_key_; 113 #ifdef DEBUG 114 base::Thread::LocalStorageKey PerThreadAssertScopeBase::thread_local_key; 115 #endif // DEBUG 116 base::LazyMutex Isolate::thread_data_table_mutex_ = LAZY_MUTEX_INITIALIZER; 117 Isolate::ThreadDataTable* Isolate::thread_data_table_ = NULL; 118 base::Atomic32 Isolate::isolate_counter_ = 0; 119 120 Isolate::PerIsolateThreadData* 121 Isolate::FindOrAllocatePerThreadDataForThisThread() { 122 ThreadId thread_id = ThreadId::Current(); 123 PerIsolateThreadData* per_thread = NULL; 124 { 125 base::LockGuard<base::Mutex> lock_guard(thread_data_table_mutex_.Pointer()); 126 per_thread = thread_data_table_->Lookup(this, thread_id); 127 if (per_thread == NULL) { 128 per_thread = new PerIsolateThreadData(this, thread_id); 129 thread_data_table_->Insert(per_thread); 130 } 131 DCHECK(thread_data_table_->Lookup(this, thread_id) == per_thread); 132 } 133 return per_thread; 134 } 135 136 137 Isolate::PerIsolateThreadData* Isolate::FindPerThreadDataForThisThread() { 138 ThreadId thread_id = ThreadId::Current(); 139 return FindPerThreadDataForThread(thread_id); 140 } 141 142 143 Isolate::PerIsolateThreadData* Isolate::FindPerThreadDataForThread( 144 ThreadId thread_id) { 145 PerIsolateThreadData* per_thread = NULL; 146 { 147 base::LockGuard<base::Mutex> lock_guard(thread_data_table_mutex_.Pointer()); 148 per_thread = thread_data_table_->Lookup(this, thread_id); 149 } 150 return per_thread; 151 } 152 153 154 void Isolate::InitializeOncePerProcess() { 155 base::LockGuard<base::Mutex> lock_guard(thread_data_table_mutex_.Pointer()); 156 CHECK(thread_data_table_ == NULL); 157 isolate_key_ = base::Thread::CreateThreadLocalKey(); 158 thread_id_key_ = base::Thread::CreateThreadLocalKey(); 159 per_isolate_thread_data_key_ = base::Thread::CreateThreadLocalKey(); 160 #ifdef DEBUG 161 PerThreadAssertScopeBase::thread_local_key = 162 base::Thread::CreateThreadLocalKey(); 163 #endif // DEBUG 164 thread_data_table_ = new Isolate::ThreadDataTable(); 165 } 166 167 168 Address Isolate::get_address_from_id(Isolate::AddressId id) { 169 return isolate_addresses_[id]; 170 } 171 172 173 char* Isolate::Iterate(ObjectVisitor* v, char* thread_storage) { 174 ThreadLocalTop* thread = reinterpret_cast<ThreadLocalTop*>(thread_storage); 175 Iterate(v, thread); 176 return thread_storage + sizeof(ThreadLocalTop); 177 } 178 179 180 void Isolate::IterateThread(ThreadVisitor* v, char* t) { 181 ThreadLocalTop* thread = reinterpret_cast<ThreadLocalTop*>(t); 182 v->VisitThread(this, thread); 183 } 184 185 186 void Isolate::Iterate(ObjectVisitor* v, ThreadLocalTop* thread) { 187 // Visit the roots from the top for a given thread. 188 v->VisitPointer(&thread->pending_exception_); 189 v->VisitPointer(&(thread->pending_message_obj_)); 190 v->VisitPointer(bit_cast<Object**>(&(thread->pending_message_script_))); 191 v->VisitPointer(bit_cast<Object**>(&(thread->context_))); 192 v->VisitPointer(&thread->scheduled_exception_); 193 194 for (v8::TryCatch* block = thread->try_catch_handler(); 195 block != NULL; 196 block = block->next_) { 197 v->VisitPointer(bit_cast<Object**>(&(block->exception_))); 198 v->VisitPointer(bit_cast<Object**>(&(block->message_obj_))); 199 v->VisitPointer(bit_cast<Object**>(&(block->message_script_))); 200 } 201 202 // Iterate over pointers on native execution stack. 203 for (StackFrameIterator it(this, thread); !it.done(); it.Advance()) { 204 it.frame()->Iterate(v); 205 } 206 207 // Iterate pointers in live lookup results. 208 thread->top_lookup_result_->Iterate(v); 209 } 210 211 212 void Isolate::Iterate(ObjectVisitor* v) { 213 ThreadLocalTop* current_t = thread_local_top(); 214 Iterate(v, current_t); 215 } 216 217 218 void Isolate::IterateDeferredHandles(ObjectVisitor* visitor) { 219 for (DeferredHandles* deferred = deferred_handles_head_; 220 deferred != NULL; 221 deferred = deferred->next_) { 222 deferred->Iterate(visitor); 223 } 224 } 225 226 227 #ifdef DEBUG 228 bool Isolate::IsDeferredHandle(Object** handle) { 229 // Each DeferredHandles instance keeps the handles to one job in the 230 // concurrent recompilation queue, containing a list of blocks. Each block 231 // contains kHandleBlockSize handles except for the first block, which may 232 // not be fully filled. 233 // We iterate through all the blocks to see whether the argument handle 234 // belongs to one of the blocks. If so, it is deferred. 235 for (DeferredHandles* deferred = deferred_handles_head_; 236 deferred != NULL; 237 deferred = deferred->next_) { 238 List<Object**>* blocks = &deferred->blocks_; 239 for (int i = 0; i < blocks->length(); i++) { 240 Object** block_limit = (i == 0) ? deferred->first_block_limit_ 241 : blocks->at(i) + kHandleBlockSize; 242 if (blocks->at(i) <= handle && handle < block_limit) return true; 243 } 244 } 245 return false; 246 } 247 #endif // DEBUG 248 249 250 void Isolate::RegisterTryCatchHandler(v8::TryCatch* that) { 251 thread_local_top()->set_try_catch_handler(that); 252 } 253 254 255 void Isolate::UnregisterTryCatchHandler(v8::TryCatch* that) { 256 DCHECK(thread_local_top()->try_catch_handler() == that); 257 thread_local_top()->set_try_catch_handler(that->next_); 258 thread_local_top()->catcher_ = NULL; 259 } 260 261 262 Handle<String> Isolate::StackTraceString() { 263 if (stack_trace_nesting_level_ == 0) { 264 stack_trace_nesting_level_++; 265 HeapStringAllocator allocator; 266 StringStream::ClearMentionedObjectCache(this); 267 StringStream accumulator(&allocator); 268 incomplete_message_ = &accumulator; 269 PrintStack(&accumulator); 270 Handle<String> stack_trace = accumulator.ToString(this); 271 incomplete_message_ = NULL; 272 stack_trace_nesting_level_ = 0; 273 return stack_trace; 274 } else if (stack_trace_nesting_level_ == 1) { 275 stack_trace_nesting_level_++; 276 base::OS::PrintError( 277 "\n\nAttempt to print stack while printing stack (double fault)\n"); 278 base::OS::PrintError( 279 "If you are lucky you may find a partial stack dump on stdout.\n\n"); 280 incomplete_message_->OutputToStdOut(); 281 return factory()->empty_string(); 282 } else { 283 base::OS::Abort(); 284 // Unreachable 285 return factory()->empty_string(); 286 } 287 } 288 289 290 void Isolate::PushStackTraceAndDie(unsigned int magic, 291 Object* object, 292 Map* map, 293 unsigned int magic2) { 294 const int kMaxStackTraceSize = 8192; 295 Handle<String> trace = StackTraceString(); 296 uint8_t buffer[kMaxStackTraceSize]; 297 int length = Min(kMaxStackTraceSize - 1, trace->length()); 298 String::WriteToFlat(*trace, buffer, 0, length); 299 buffer[length] = '\0'; 300 // TODO(dcarney): convert buffer to utf8? 301 base::OS::PrintError("Stacktrace (%x-%x) %p %p: %s\n", magic, magic2, 302 static_cast<void*>(object), static_cast<void*>(map), 303 reinterpret_cast<char*>(buffer)); 304 base::OS::Abort(); 305 } 306 307 308 // Determines whether the given stack frame should be displayed in 309 // a stack trace. The caller is the error constructor that asked 310 // for the stack trace to be collected. The first time a construct 311 // call to this function is encountered it is skipped. The seen_caller 312 // in/out parameter is used to remember if the caller has been seen 313 // yet. 314 static bool IsVisibleInStackTrace(JSFunction* fun, 315 Object* caller, 316 Object* receiver, 317 bool* seen_caller) { 318 if ((fun == caller) && !(*seen_caller)) { 319 *seen_caller = true; 320 return false; 321 } 322 // Skip all frames until we've seen the caller. 323 if (!(*seen_caller)) return false; 324 // Also, skip non-visible built-in functions and any call with the builtins 325 // object as receiver, so as to not reveal either the builtins object or 326 // an internal function. 327 // The --builtins-in-stack-traces command line flag allows including 328 // internal call sites in the stack trace for debugging purposes. 329 if (!FLAG_builtins_in_stack_traces) { 330 if (receiver->IsJSBuiltinsObject()) return false; 331 if (fun->IsBuiltin()) { 332 return fun->shared()->native(); 333 } else if (fun->IsFromNativeScript() || fun->IsFromExtensionScript()) { 334 return false; 335 } 336 } 337 return true; 338 } 339 340 341 Handle<Object> Isolate::CaptureSimpleStackTrace(Handle<JSObject> error_object, 342 Handle<Object> caller) { 343 // Get stack trace limit. 344 Handle<Object> error = Object::GetProperty( 345 this, js_builtins_object(), "$Error").ToHandleChecked(); 346 if (!error->IsJSObject()) return factory()->undefined_value(); 347 348 Handle<String> stackTraceLimit = 349 factory()->InternalizeUtf8String("stackTraceLimit"); 350 DCHECK(!stackTraceLimit.is_null()); 351 Handle<Object> stack_trace_limit = 352 JSObject::GetDataProperty(Handle<JSObject>::cast(error), 353 stackTraceLimit); 354 if (!stack_trace_limit->IsNumber()) return factory()->undefined_value(); 355 int limit = FastD2IChecked(stack_trace_limit->Number()); 356 limit = Max(limit, 0); // Ensure that limit is not negative. 357 358 int initial_size = Min(limit, 10); 359 Handle<FixedArray> elements = 360 factory()->NewFixedArrayWithHoles(initial_size * 4 + 1); 361 362 // If the caller parameter is a function we skip frames until we're 363 // under it before starting to collect. 364 bool seen_caller = !caller->IsJSFunction(); 365 // First element is reserved to store the number of sloppy frames. 366 int cursor = 1; 367 int frames_seen = 0; 368 int sloppy_frames = 0; 369 bool encountered_strict_function = false; 370 for (JavaScriptFrameIterator iter(this); 371 !iter.done() && frames_seen < limit; 372 iter.Advance()) { 373 JavaScriptFrame* frame = iter.frame(); 374 // Set initial size to the maximum inlining level + 1 for the outermost 375 // function. 376 List<FrameSummary> frames(FLAG_max_inlining_levels + 1); 377 frame->Summarize(&frames); 378 for (int i = frames.length() - 1; i >= 0; i--) { 379 Handle<JSFunction> fun = frames[i].function(); 380 Handle<Object> recv = frames[i].receiver(); 381 // Filter out internal frames that we do not want to show. 382 if (!IsVisibleInStackTrace(*fun, *caller, *recv, &seen_caller)) continue; 383 // Filter out frames from other security contexts. 384 if (!this->context()->HasSameSecurityTokenAs(fun->context())) continue; 385 if (cursor + 4 > elements->length()) { 386 int new_capacity = JSObject::NewElementsCapacity(elements->length()); 387 Handle<FixedArray> new_elements = 388 factory()->NewFixedArrayWithHoles(new_capacity); 389 for (int i = 0; i < cursor; i++) { 390 new_elements->set(i, elements->get(i)); 391 } 392 elements = new_elements; 393 } 394 DCHECK(cursor + 4 <= elements->length()); 395 396 397 Handle<Code> code = frames[i].code(); 398 Handle<Smi> offset(Smi::FromInt(frames[i].offset()), this); 399 // The stack trace API should not expose receivers and function 400 // objects on frames deeper than the top-most one with a strict 401 // mode function. The number of sloppy frames is stored as 402 // first element in the result array. 403 if (!encountered_strict_function) { 404 if (fun->shared()->strict_mode() == STRICT) { 405 encountered_strict_function = true; 406 } else { 407 sloppy_frames++; 408 } 409 } 410 elements->set(cursor++, *recv); 411 elements->set(cursor++, *fun); 412 elements->set(cursor++, *code); 413 elements->set(cursor++, *offset); 414 frames_seen++; 415 } 416 } 417 elements->set(0, Smi::FromInt(sloppy_frames)); 418 Handle<JSArray> result = factory()->NewJSArrayWithElements(elements); 419 result->set_length(Smi::FromInt(cursor)); 420 return result; 421 } 422 423 424 void Isolate::CaptureAndSetDetailedStackTrace(Handle<JSObject> error_object) { 425 if (capture_stack_trace_for_uncaught_exceptions_) { 426 // Capture stack trace for a detailed exception message. 427 Handle<Name> key = factory()->detailed_stack_trace_symbol(); 428 Handle<JSArray> stack_trace = CaptureCurrentStackTrace( 429 stack_trace_for_uncaught_exceptions_frame_limit_, 430 stack_trace_for_uncaught_exceptions_options_); 431 JSObject::SetProperty(error_object, key, stack_trace, STRICT).Assert(); 432 } 433 } 434 435 436 void Isolate::CaptureAndSetSimpleStackTrace(Handle<JSObject> error_object, 437 Handle<Object> caller) { 438 // Capture stack trace for simple stack trace string formatting. 439 Handle<Name> key = factory()->stack_trace_symbol(); 440 Handle<Object> stack_trace = CaptureSimpleStackTrace(error_object, caller); 441 JSObject::SetProperty(error_object, key, stack_trace, STRICT).Assert(); 442 } 443 444 445 Handle<JSArray> Isolate::CaptureCurrentStackTrace( 446 int frame_limit, StackTrace::StackTraceOptions options) { 447 // Ensure no negative values. 448 int limit = Max(frame_limit, 0); 449 Handle<JSArray> stack_trace = factory()->NewJSArray(frame_limit); 450 451 Handle<String> column_key = 452 factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("column")); 453 Handle<String> line_key = 454 factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("lineNumber")); 455 Handle<String> script_id_key = 456 factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("scriptId")); 457 Handle<String> script_name_key = 458 factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("scriptName")); 459 Handle<String> script_name_or_source_url_key = 460 factory()->InternalizeOneByteString( 461 STATIC_CHAR_VECTOR("scriptNameOrSourceURL")); 462 Handle<String> function_key = 463 factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("functionName")); 464 Handle<String> eval_key = 465 factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("isEval")); 466 Handle<String> constructor_key = 467 factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("isConstructor")); 468 469 StackTraceFrameIterator it(this); 470 int frames_seen = 0; 471 while (!it.done() && (frames_seen < limit)) { 472 JavaScriptFrame* frame = it.frame(); 473 // Set initial size to the maximum inlining level + 1 for the outermost 474 // function. 475 List<FrameSummary> frames(FLAG_max_inlining_levels + 1); 476 frame->Summarize(&frames); 477 for (int i = frames.length() - 1; i >= 0 && frames_seen < limit; i--) { 478 Handle<JSFunction> fun = frames[i].function(); 479 // Filter frames from other security contexts. 480 if (!(options & StackTrace::kExposeFramesAcrossSecurityOrigins) && 481 !this->context()->HasSameSecurityTokenAs(fun->context())) continue; 482 483 // Create a JSObject to hold the information for the StackFrame. 484 Handle<JSObject> stack_frame = factory()->NewJSObject(object_function()); 485 486 Handle<Script> script(Script::cast(fun->shared()->script())); 487 488 if (options & StackTrace::kLineNumber) { 489 int script_line_offset = script->line_offset()->value(); 490 int position = frames[i].code()->SourcePosition(frames[i].pc()); 491 int line_number = Script::GetLineNumber(script, position); 492 // line_number is already shifted by the script_line_offset. 493 int relative_line_number = line_number - script_line_offset; 494 if (options & StackTrace::kColumnOffset && relative_line_number >= 0) { 495 Handle<FixedArray> line_ends(FixedArray::cast(script->line_ends())); 496 int start = (relative_line_number == 0) ? 0 : 497 Smi::cast(line_ends->get(relative_line_number - 1))->value() + 1; 498 int column_offset = position - start; 499 if (relative_line_number == 0) { 500 // For the case where the code is on the same line as the script 501 // tag. 502 column_offset += script->column_offset()->value(); 503 } 504 JSObject::AddProperty( 505 stack_frame, column_key, 506 handle(Smi::FromInt(column_offset + 1), this), NONE); 507 } 508 JSObject::AddProperty( 509 stack_frame, line_key, 510 handle(Smi::FromInt(line_number + 1), this), NONE); 511 } 512 513 if (options & StackTrace::kScriptId) { 514 JSObject::AddProperty( 515 stack_frame, script_id_key, handle(script->id(), this), NONE); 516 } 517 518 if (options & StackTrace::kScriptName) { 519 JSObject::AddProperty( 520 stack_frame, script_name_key, handle(script->name(), this), NONE); 521 } 522 523 if (options & StackTrace::kScriptNameOrSourceURL) { 524 Handle<Object> result = Script::GetNameOrSourceURL(script); 525 JSObject::AddProperty( 526 stack_frame, script_name_or_source_url_key, result, NONE); 527 } 528 529 if (options & StackTrace::kFunctionName) { 530 Handle<Object> fun_name(fun->shared()->DebugName(), this); 531 JSObject::AddProperty(stack_frame, function_key, fun_name, NONE); 532 } 533 534 if (options & StackTrace::kIsEval) { 535 Handle<Object> is_eval = 536 script->compilation_type() == Script::COMPILATION_TYPE_EVAL ? 537 factory()->true_value() : factory()->false_value(); 538 JSObject::AddProperty(stack_frame, eval_key, is_eval, NONE); 539 } 540 541 if (options & StackTrace::kIsConstructor) { 542 Handle<Object> is_constructor = (frames[i].is_constructor()) ? 543 factory()->true_value() : factory()->false_value(); 544 JSObject::AddProperty( 545 stack_frame, constructor_key, is_constructor, NONE); 546 } 547 548 FixedArray::cast(stack_trace->elements())->set(frames_seen, *stack_frame); 549 frames_seen++; 550 } 551 it.Advance(); 552 } 553 554 stack_trace->set_length(Smi::FromInt(frames_seen)); 555 return stack_trace; 556 } 557 558 559 void Isolate::PrintStack(FILE* out) { 560 if (stack_trace_nesting_level_ == 0) { 561 stack_trace_nesting_level_++; 562 StringStream::ClearMentionedObjectCache(this); 563 HeapStringAllocator allocator; 564 StringStream accumulator(&allocator); 565 incomplete_message_ = &accumulator; 566 PrintStack(&accumulator); 567 accumulator.OutputToFile(out); 568 InitializeLoggingAndCounters(); 569 accumulator.Log(this); 570 incomplete_message_ = NULL; 571 stack_trace_nesting_level_ = 0; 572 } else if (stack_trace_nesting_level_ == 1) { 573 stack_trace_nesting_level_++; 574 base::OS::PrintError( 575 "\n\nAttempt to print stack while printing stack (double fault)\n"); 576 base::OS::PrintError( 577 "If you are lucky you may find a partial stack dump on stdout.\n\n"); 578 incomplete_message_->OutputToFile(out); 579 } 580 } 581 582 583 static void PrintFrames(Isolate* isolate, 584 StringStream* accumulator, 585 StackFrame::PrintMode mode) { 586 StackFrameIterator it(isolate); 587 for (int i = 0; !it.done(); it.Advance()) { 588 it.frame()->Print(accumulator, mode, i++); 589 } 590 } 591 592 593 void Isolate::PrintStack(StringStream* accumulator) { 594 if (!IsInitialized()) { 595 accumulator->Add( 596 "\n==== JS stack trace is not available =======================\n\n"); 597 accumulator->Add( 598 "\n==== Isolate for the thread is not initialized =============\n\n"); 599 return; 600 } 601 // The MentionedObjectCache is not GC-proof at the moment. 602 DisallowHeapAllocation no_gc; 603 DCHECK(StringStream::IsMentionedObjectCacheClear(this)); 604 605 // Avoid printing anything if there are no frames. 606 if (c_entry_fp(thread_local_top()) == 0) return; 607 608 accumulator->Add( 609 "\n==== JS stack trace =========================================\n\n"); 610 PrintFrames(this, accumulator, StackFrame::OVERVIEW); 611 612 accumulator->Add( 613 "\n==== Details ================================================\n\n"); 614 PrintFrames(this, accumulator, StackFrame::DETAILS); 615 616 accumulator->PrintMentionedObjectCache(this); 617 accumulator->Add("=====================\n\n"); 618 } 619 620 621 void Isolate::SetFailedAccessCheckCallback( 622 v8::FailedAccessCheckCallback callback) { 623 thread_local_top()->failed_access_check_callback_ = callback; 624 } 625 626 627 static inline AccessCheckInfo* GetAccessCheckInfo(Isolate* isolate, 628 Handle<JSObject> receiver) { 629 JSFunction* constructor = JSFunction::cast(receiver->map()->constructor()); 630 if (!constructor->shared()->IsApiFunction()) return NULL; 631 632 Object* data_obj = 633 constructor->shared()->get_api_func_data()->access_check_info(); 634 if (data_obj == isolate->heap()->undefined_value()) return NULL; 635 636 return AccessCheckInfo::cast(data_obj); 637 } 638 639 640 void Isolate::ReportFailedAccessCheck(Handle<JSObject> receiver, 641 v8::AccessType type) { 642 if (!thread_local_top()->failed_access_check_callback_) { 643 Handle<String> message = factory()->InternalizeUtf8String("no access"); 644 Handle<Object> error; 645 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 646 this, error, factory()->NewTypeError(message), /* void */); 647 ScheduleThrow(*error); 648 return; 649 } 650 651 DCHECK(receiver->IsAccessCheckNeeded()); 652 DCHECK(context()); 653 654 // Get the data object from access check info. 655 HandleScope scope(this); 656 Handle<Object> data; 657 { DisallowHeapAllocation no_gc; 658 AccessCheckInfo* access_check_info = GetAccessCheckInfo(this, receiver); 659 if (!access_check_info) return; 660 data = handle(access_check_info->data(), this); 661 } 662 663 // Leaving JavaScript. 664 VMState<EXTERNAL> state(this); 665 thread_local_top()->failed_access_check_callback_( 666 v8::Utils::ToLocal(receiver), 667 type, 668 v8::Utils::ToLocal(data)); 669 } 670 671 672 enum MayAccessDecision { 673 YES, NO, UNKNOWN 674 }; 675 676 677 static MayAccessDecision MayAccessPreCheck(Isolate* isolate, 678 Handle<JSObject> receiver, 679 v8::AccessType type) { 680 DisallowHeapAllocation no_gc; 681 // During bootstrapping, callback functions are not enabled yet. 682 if (isolate->bootstrapper()->IsActive()) return YES; 683 684 if (receiver->IsJSGlobalProxy()) { 685 Object* receiver_context = JSGlobalProxy::cast(*receiver)->native_context(); 686 if (!receiver_context->IsContext()) return NO; 687 688 // Get the native context of current top context. 689 // avoid using Isolate::native_context() because it uses Handle. 690 Context* native_context = 691 isolate->context()->global_object()->native_context(); 692 if (receiver_context == native_context) return YES; 693 694 if (Context::cast(receiver_context)->security_token() == 695 native_context->security_token()) 696 return YES; 697 } 698 699 return UNKNOWN; 700 } 701 702 703 bool Isolate::MayNamedAccess(Handle<JSObject> receiver, 704 Handle<Object> key, 705 v8::AccessType type) { 706 DCHECK(receiver->IsJSGlobalProxy() || receiver->IsAccessCheckNeeded()); 707 708 // Skip checks for hidden properties access. Note, we do not 709 // require existence of a context in this case. 710 if (key.is_identical_to(factory()->hidden_string())) return true; 711 712 // Check for compatibility between the security tokens in the 713 // current lexical context and the accessed object. 714 DCHECK(context()); 715 716 MayAccessDecision decision = MayAccessPreCheck(this, receiver, type); 717 if (decision != UNKNOWN) return decision == YES; 718 719 HandleScope scope(this); 720 Handle<Object> data; 721 v8::NamedSecurityCallback callback; 722 { DisallowHeapAllocation no_gc; 723 AccessCheckInfo* access_check_info = GetAccessCheckInfo(this, receiver); 724 if (!access_check_info) return false; 725 Object* fun_obj = access_check_info->named_callback(); 726 callback = v8::ToCData<v8::NamedSecurityCallback>(fun_obj); 727 if (!callback) return false; 728 data = handle(access_check_info->data(), this); 729 } 730 731 LOG(this, ApiNamedSecurityCheck(*key)); 732 733 // Leaving JavaScript. 734 VMState<EXTERNAL> state(this); 735 return callback(v8::Utils::ToLocal(receiver), 736 v8::Utils::ToLocal(key), 737 type, 738 v8::Utils::ToLocal(data)); 739 } 740 741 742 bool Isolate::MayIndexedAccess(Handle<JSObject> receiver, 743 uint32_t index, 744 v8::AccessType type) { 745 DCHECK(receiver->IsJSGlobalProxy() || receiver->IsAccessCheckNeeded()); 746 // Check for compatibility between the security tokens in the 747 // current lexical context and the accessed object. 748 DCHECK(context()); 749 750 MayAccessDecision decision = MayAccessPreCheck(this, receiver, type); 751 if (decision != UNKNOWN) return decision == YES; 752 753 HandleScope scope(this); 754 Handle<Object> data; 755 v8::IndexedSecurityCallback callback; 756 { DisallowHeapAllocation no_gc; 757 // Get named access check callback 758 AccessCheckInfo* access_check_info = GetAccessCheckInfo(this, receiver); 759 if (!access_check_info) return false; 760 Object* fun_obj = access_check_info->indexed_callback(); 761 callback = v8::ToCData<v8::IndexedSecurityCallback>(fun_obj); 762 if (!callback) return false; 763 data = handle(access_check_info->data(), this); 764 } 765 766 LOG(this, ApiIndexedSecurityCheck(index)); 767 768 // Leaving JavaScript. 769 VMState<EXTERNAL> state(this); 770 return callback( 771 v8::Utils::ToLocal(receiver), index, type, v8::Utils::ToLocal(data)); 772 } 773 774 775 const char* const Isolate::kStackOverflowMessage = 776 "Uncaught RangeError: Maximum call stack size exceeded"; 777 778 779 Object* Isolate::StackOverflow() { 780 HandleScope scope(this); 781 // At this point we cannot create an Error object using its javascript 782 // constructor. Instead, we copy the pre-constructed boilerplate and 783 // attach the stack trace as a hidden property. 784 Handle<String> key = factory()->stack_overflow_string(); 785 Handle<JSObject> boilerplate = Handle<JSObject>::cast( 786 Object::GetProperty(js_builtins_object(), key).ToHandleChecked()); 787 Handle<JSObject> exception = factory()->CopyJSObject(boilerplate); 788 DoThrow(*exception, NULL); 789 790 CaptureAndSetSimpleStackTrace(exception, factory()->undefined_value()); 791 return heap()->exception(); 792 } 793 794 795 Object* Isolate::TerminateExecution() { 796 DoThrow(heap_.termination_exception(), NULL); 797 return heap()->exception(); 798 } 799 800 801 void Isolate::CancelTerminateExecution() { 802 if (try_catch_handler()) { 803 try_catch_handler()->has_terminated_ = false; 804 } 805 if (has_pending_exception() && 806 pending_exception() == heap_.termination_exception()) { 807 thread_local_top()->external_caught_exception_ = false; 808 clear_pending_exception(); 809 } 810 if (has_scheduled_exception() && 811 scheduled_exception() == heap_.termination_exception()) { 812 thread_local_top()->external_caught_exception_ = false; 813 clear_scheduled_exception(); 814 } 815 } 816 817 818 void Isolate::InvokeApiInterruptCallback() { 819 // Note: callback below should be called outside of execution access lock. 820 InterruptCallback callback = NULL; 821 void* data = NULL; 822 { 823 ExecutionAccess access(this); 824 callback = api_interrupt_callback_; 825 data = api_interrupt_callback_data_; 826 api_interrupt_callback_ = NULL; 827 api_interrupt_callback_data_ = NULL; 828 } 829 830 if (callback != NULL) { 831 VMState<EXTERNAL> state(this); 832 HandleScope handle_scope(this); 833 callback(reinterpret_cast<v8::Isolate*>(this), data); 834 } 835 } 836 837 838 Object* Isolate::Throw(Object* exception, MessageLocation* location) { 839 DoThrow(exception, location); 840 return heap()->exception(); 841 } 842 843 844 Object* Isolate::ReThrow(Object* exception) { 845 bool can_be_caught_externally = false; 846 bool catchable_by_javascript = is_catchable_by_javascript(exception); 847 ShouldReportException(&can_be_caught_externally, catchable_by_javascript); 848 849 thread_local_top()->catcher_ = can_be_caught_externally ? 850 try_catch_handler() : NULL; 851 852 // Set the exception being re-thrown. 853 set_pending_exception(exception); 854 return heap()->exception(); 855 } 856 857 858 Object* Isolate::ThrowIllegalOperation() { 859 if (FLAG_stack_trace_on_illegal) PrintStack(stdout); 860 return Throw(heap_.illegal_access_string()); 861 } 862 863 864 void Isolate::ScheduleThrow(Object* exception) { 865 // When scheduling a throw we first throw the exception to get the 866 // error reporting if it is uncaught before rescheduling it. 867 Throw(exception); 868 PropagatePendingExceptionToExternalTryCatch(); 869 if (has_pending_exception()) { 870 thread_local_top()->scheduled_exception_ = pending_exception(); 871 thread_local_top()->external_caught_exception_ = false; 872 clear_pending_exception(); 873 } 874 } 875 876 877 void Isolate::RestorePendingMessageFromTryCatch(v8::TryCatch* handler) { 878 DCHECK(handler == try_catch_handler()); 879 DCHECK(handler->HasCaught()); 880 DCHECK(handler->rethrow_); 881 DCHECK(handler->capture_message_); 882 Object* message = reinterpret_cast<Object*>(handler->message_obj_); 883 Object* script = reinterpret_cast<Object*>(handler->message_script_); 884 DCHECK(message->IsJSMessageObject() || message->IsTheHole()); 885 DCHECK(script->IsScript() || script->IsTheHole()); 886 thread_local_top()->pending_message_obj_ = message; 887 thread_local_top()->pending_message_script_ = script; 888 thread_local_top()->pending_message_start_pos_ = handler->message_start_pos_; 889 thread_local_top()->pending_message_end_pos_ = handler->message_end_pos_; 890 } 891 892 893 void Isolate::CancelScheduledExceptionFromTryCatch(v8::TryCatch* handler) { 894 DCHECK(has_scheduled_exception()); 895 if (scheduled_exception() == handler->exception_) { 896 DCHECK(scheduled_exception() != heap()->termination_exception()); 897 clear_scheduled_exception(); 898 } 899 } 900 901 902 Object* Isolate::PromoteScheduledException() { 903 Object* thrown = scheduled_exception(); 904 clear_scheduled_exception(); 905 // Re-throw the exception to avoid getting repeated error reporting. 906 return ReThrow(thrown); 907 } 908 909 910 void Isolate::PrintCurrentStackTrace(FILE* out) { 911 StackTraceFrameIterator it(this); 912 while (!it.done()) { 913 HandleScope scope(this); 914 // Find code position if recorded in relocation info. 915 JavaScriptFrame* frame = it.frame(); 916 int pos = frame->LookupCode()->SourcePosition(frame->pc()); 917 Handle<Object> pos_obj(Smi::FromInt(pos), this); 918 // Fetch function and receiver. 919 Handle<JSFunction> fun(frame->function()); 920 Handle<Object> recv(frame->receiver(), this); 921 // Advance to the next JavaScript frame and determine if the 922 // current frame is the top-level frame. 923 it.Advance(); 924 Handle<Object> is_top_level = it.done() 925 ? factory()->true_value() 926 : factory()->false_value(); 927 // Generate and print stack trace line. 928 Handle<String> line = 929 Execution::GetStackTraceLine(recv, fun, pos_obj, is_top_level); 930 if (line->length() > 0) { 931 line->PrintOn(out); 932 PrintF(out, "\n"); 933 } 934 } 935 } 936 937 938 void Isolate::ComputeLocation(MessageLocation* target) { 939 *target = MessageLocation(Handle<Script>(heap_.empty_script()), -1, -1); 940 StackTraceFrameIterator it(this); 941 if (!it.done()) { 942 JavaScriptFrame* frame = it.frame(); 943 JSFunction* fun = frame->function(); 944 Object* script = fun->shared()->script(); 945 if (script->IsScript() && 946 !(Script::cast(script)->source()->IsUndefined())) { 947 int pos = frame->LookupCode()->SourcePosition(frame->pc()); 948 // Compute the location from the function and the reloc info. 949 Handle<Script> casted_script(Script::cast(script)); 950 *target = MessageLocation(casted_script, pos, pos + 1); 951 } 952 } 953 } 954 955 956 bool Isolate::ShouldReportException(bool* can_be_caught_externally, 957 bool catchable_by_javascript) { 958 // Find the top-most try-catch handler. 959 StackHandler* handler = 960 StackHandler::FromAddress(Isolate::handler(thread_local_top())); 961 while (handler != NULL && !handler->is_catch()) { 962 handler = handler->next(); 963 } 964 965 // Get the address of the external handler so we can compare the address to 966 // determine which one is closer to the top of the stack. 967 Address external_handler_address = 968 thread_local_top()->try_catch_handler_address(); 969 970 // The exception has been externally caught if and only if there is 971 // an external handler which is on top of the top-most try-catch 972 // handler. 973 *can_be_caught_externally = external_handler_address != NULL && 974 (handler == NULL || handler->address() > external_handler_address || 975 !catchable_by_javascript); 976 977 if (*can_be_caught_externally) { 978 // Only report the exception if the external handler is verbose. 979 return try_catch_handler()->is_verbose_; 980 } else { 981 // Report the exception if it isn't caught by JavaScript code. 982 return handler == NULL; 983 } 984 } 985 986 987 bool Isolate::IsErrorObject(Handle<Object> obj) { 988 if (!obj->IsJSObject()) return false; 989 990 Handle<String> error_key = 991 factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("$Error")); 992 Handle<Object> error_constructor = Object::GetProperty( 993 js_builtins_object(), error_key).ToHandleChecked(); 994 995 DisallowHeapAllocation no_gc; 996 for (PrototypeIterator iter(this, *obj, PrototypeIterator::START_AT_RECEIVER); 997 !iter.IsAtEnd(); iter.Advance()) { 998 if (iter.GetCurrent()->IsJSProxy()) return false; 999 if (JSObject::cast(iter.GetCurrent())->map()->constructor() == 1000 *error_constructor) { 1001 return true; 1002 } 1003 } 1004 return false; 1005 } 1006 1007 static int fatal_exception_depth = 0; 1008 1009 void Isolate::DoThrow(Object* exception, MessageLocation* location) { 1010 DCHECK(!has_pending_exception()); 1011 1012 HandleScope scope(this); 1013 Handle<Object> exception_handle(exception, this); 1014 1015 // Determine reporting and whether the exception is caught externally. 1016 bool catchable_by_javascript = is_catchable_by_javascript(exception); 1017 bool can_be_caught_externally = false; 1018 bool should_report_exception = 1019 ShouldReportException(&can_be_caught_externally, catchable_by_javascript); 1020 bool report_exception = catchable_by_javascript && should_report_exception; 1021 bool try_catch_needs_message = 1022 can_be_caught_externally && try_catch_handler()->capture_message_; 1023 bool bootstrapping = bootstrapper()->IsActive(); 1024 bool rethrowing_message = thread_local_top()->rethrowing_message_; 1025 1026 thread_local_top()->rethrowing_message_ = false; 1027 1028 // Notify debugger of exception. 1029 if (catchable_by_javascript) { 1030 debug()->OnThrow(exception_handle, report_exception); 1031 } 1032 1033 // Generate the message if required. 1034 if (!rethrowing_message && (report_exception || try_catch_needs_message)) { 1035 MessageLocation potential_computed_location; 1036 if (location == NULL) { 1037 // If no location was specified we use a computed one instead. 1038 ComputeLocation(&potential_computed_location); 1039 location = &potential_computed_location; 1040 } 1041 // It's not safe to try to make message objects or collect stack traces 1042 // while the bootstrapper is active since the infrastructure may not have 1043 // been properly initialized. 1044 if (!bootstrapping) { 1045 Handle<JSArray> stack_trace_object; 1046 if (capture_stack_trace_for_uncaught_exceptions_) { 1047 if (IsErrorObject(exception_handle)) { 1048 // We fetch the stack trace that corresponds to this error object. 1049 Handle<Name> key = factory()->detailed_stack_trace_symbol(); 1050 // Look up as own property. If the lookup fails, the exception is 1051 // probably not a valid Error object. In that case, we fall through 1052 // and capture the stack trace at this throw site. 1053 LookupIterator lookup(exception_handle, key, 1054 LookupIterator::OWN_SKIP_INTERCEPTOR); 1055 Handle<Object> stack_trace_property; 1056 if (Object::GetProperty(&lookup).ToHandle(&stack_trace_property) && 1057 stack_trace_property->IsJSArray()) { 1058 stack_trace_object = Handle<JSArray>::cast(stack_trace_property); 1059 } 1060 } 1061 if (stack_trace_object.is_null()) { 1062 // Not an error object, we capture at throw site. 1063 stack_trace_object = CaptureCurrentStackTrace( 1064 stack_trace_for_uncaught_exceptions_frame_limit_, 1065 stack_trace_for_uncaught_exceptions_options_); 1066 } 1067 } 1068 1069 Handle<Object> exception_arg = exception_handle; 1070 // If the exception argument is a custom object, turn it into a string 1071 // before throwing as uncaught exception. Note that the pending 1072 // exception object to be set later must not be turned into a string. 1073 if (exception_arg->IsJSObject() && !IsErrorObject(exception_arg)) { 1074 MaybeHandle<Object> maybe_exception = 1075 Execution::ToDetailString(this, exception_arg); 1076 if (!maybe_exception.ToHandle(&exception_arg)) { 1077 exception_arg = factory()->InternalizeOneByteString( 1078 STATIC_CHAR_VECTOR("exception")); 1079 } 1080 } 1081 Handle<Object> message_obj = MessageHandler::MakeMessageObject( 1082 this, 1083 "uncaught_exception", 1084 location, 1085 HandleVector<Object>(&exception_arg, 1), 1086 stack_trace_object); 1087 thread_local_top()->pending_message_obj_ = *message_obj; 1088 if (location != NULL) { 1089 thread_local_top()->pending_message_script_ = *location->script(); 1090 thread_local_top()->pending_message_start_pos_ = location->start_pos(); 1091 thread_local_top()->pending_message_end_pos_ = location->end_pos(); 1092 } 1093 1094 // If the abort-on-uncaught-exception flag is specified, abort on any 1095 // exception not caught by JavaScript, even when an external handler is 1096 // present. This flag is intended for use by JavaScript developers, so 1097 // print a user-friendly stack trace (not an internal one). 1098 if (fatal_exception_depth == 0 && 1099 FLAG_abort_on_uncaught_exception && 1100 (report_exception || can_be_caught_externally)) { 1101 fatal_exception_depth++; 1102 PrintF(stderr, 1103 "%s\n\nFROM\n", 1104 MessageHandler::GetLocalizedMessage(this, message_obj).get()); 1105 PrintCurrentStackTrace(stderr); 1106 base::OS::Abort(); 1107 } 1108 } else if (location != NULL && !location->script().is_null()) { 1109 // We are bootstrapping and caught an error where the location is set 1110 // and we have a script for the location. 1111 // In this case we could have an extension (or an internal error 1112 // somewhere) and we print out the line number at which the error occured 1113 // to the console for easier debugging. 1114 int line_number = 1115 location->script()->GetLineNumber(location->start_pos()) + 1; 1116 if (exception->IsString() && location->script()->name()->IsString()) { 1117 base::OS::PrintError( 1118 "Extension or internal compilation error: %s in %s at line %d.\n", 1119 String::cast(exception)->ToCString().get(), 1120 String::cast(location->script()->name())->ToCString().get(), 1121 line_number); 1122 } else if (location->script()->name()->IsString()) { 1123 base::OS::PrintError( 1124 "Extension or internal compilation error in %s at line %d.\n", 1125 String::cast(location->script()->name())->ToCString().get(), 1126 line_number); 1127 } else { 1128 base::OS::PrintError("Extension or internal compilation error.\n"); 1129 } 1130 #ifdef OBJECT_PRINT 1131 // Since comments and empty lines have been stripped from the source of 1132 // builtins, print the actual source here so that line numbers match. 1133 if (location->script()->source()->IsString()) { 1134 Handle<String> src(String::cast(location->script()->source())); 1135 PrintF("Failing script:\n"); 1136 int len = src->length(); 1137 int line_number = 1; 1138 PrintF("%5d: ", line_number); 1139 for (int i = 0; i < len; i++) { 1140 uint16_t character = src->Get(i); 1141 PrintF("%c", character); 1142 if (character == '\n' && i < len - 2) { 1143 PrintF("%5d: ", ++line_number); 1144 } 1145 } 1146 } 1147 #endif 1148 } 1149 } 1150 1151 // Save the message for reporting if the the exception remains uncaught. 1152 thread_local_top()->has_pending_message_ = report_exception; 1153 1154 // Do not forget to clean catcher_ if currently thrown exception cannot 1155 // be caught. If necessary, ReThrow will update the catcher. 1156 thread_local_top()->catcher_ = can_be_caught_externally ? 1157 try_catch_handler() : NULL; 1158 1159 set_pending_exception(*exception_handle); 1160 } 1161 1162 1163 bool Isolate::HasExternalTryCatch() { 1164 DCHECK(has_pending_exception()); 1165 1166 return (thread_local_top()->catcher_ != NULL) && 1167 (try_catch_handler() == thread_local_top()->catcher_); 1168 } 1169 1170 1171 bool Isolate::IsFinallyOnTop() { 1172 // Get the address of the external handler so we can compare the address to 1173 // determine which one is closer to the top of the stack. 1174 Address external_handler_address = 1175 thread_local_top()->try_catch_handler_address(); 1176 DCHECK(external_handler_address != NULL); 1177 1178 // The exception has been externally caught if and only if there is 1179 // an external handler which is on top of the top-most try-finally 1180 // handler. 1181 // There should be no try-catch blocks as they would prohibit us from 1182 // finding external catcher in the first place (see catcher_ check above). 1183 // 1184 // Note, that finally clause would rethrow an exception unless it's 1185 // aborted by jumps in control flow like return, break, etc. and we'll 1186 // have another chances to set proper v8::TryCatch. 1187 StackHandler* handler = 1188 StackHandler::FromAddress(Isolate::handler(thread_local_top())); 1189 while (handler != NULL && handler->address() < external_handler_address) { 1190 DCHECK(!handler->is_catch()); 1191 if (handler->is_finally()) return true; 1192 1193 handler = handler->next(); 1194 } 1195 1196 return false; 1197 } 1198 1199 1200 void Isolate::ReportPendingMessages() { 1201 DCHECK(has_pending_exception()); 1202 bool can_clear_message = PropagatePendingExceptionToExternalTryCatch(); 1203 1204 HandleScope scope(this); 1205 if (thread_local_top_.pending_exception_ == heap()->termination_exception()) { 1206 // Do nothing: if needed, the exception has been already propagated to 1207 // v8::TryCatch. 1208 } else { 1209 if (thread_local_top_.has_pending_message_) { 1210 thread_local_top_.has_pending_message_ = false; 1211 if (!thread_local_top_.pending_message_obj_->IsTheHole()) { 1212 HandleScope scope(this); 1213 Handle<Object> message_obj(thread_local_top_.pending_message_obj_, 1214 this); 1215 if (!thread_local_top_.pending_message_script_->IsTheHole()) { 1216 Handle<Script> script( 1217 Script::cast(thread_local_top_.pending_message_script_)); 1218 int start_pos = thread_local_top_.pending_message_start_pos_; 1219 int end_pos = thread_local_top_.pending_message_end_pos_; 1220 MessageLocation location(script, start_pos, end_pos); 1221 MessageHandler::ReportMessage(this, &location, message_obj); 1222 } else { 1223 MessageHandler::ReportMessage(this, NULL, message_obj); 1224 } 1225 } 1226 } 1227 } 1228 if (can_clear_message) clear_pending_message(); 1229 } 1230 1231 1232 MessageLocation Isolate::GetMessageLocation() { 1233 DCHECK(has_pending_exception()); 1234 1235 if (thread_local_top_.pending_exception_ != heap()->termination_exception() && 1236 thread_local_top_.has_pending_message_ && 1237 !thread_local_top_.pending_message_obj_->IsTheHole() && 1238 !thread_local_top_.pending_message_obj_->IsTheHole()) { 1239 Handle<Script> script( 1240 Script::cast(thread_local_top_.pending_message_script_)); 1241 int start_pos = thread_local_top_.pending_message_start_pos_; 1242 int end_pos = thread_local_top_.pending_message_end_pos_; 1243 return MessageLocation(script, start_pos, end_pos); 1244 } 1245 1246 return MessageLocation(); 1247 } 1248 1249 1250 bool Isolate::OptionalRescheduleException(bool is_bottom_call) { 1251 DCHECK(has_pending_exception()); 1252 PropagatePendingExceptionToExternalTryCatch(); 1253 1254 bool is_termination_exception = 1255 pending_exception() == heap_.termination_exception(); 1256 1257 // Do not reschedule the exception if this is the bottom call. 1258 bool clear_exception = is_bottom_call; 1259 1260 if (is_termination_exception) { 1261 if (is_bottom_call) { 1262 thread_local_top()->external_caught_exception_ = false; 1263 clear_pending_exception(); 1264 return false; 1265 } 1266 } else if (thread_local_top()->external_caught_exception_) { 1267 // If the exception is externally caught, clear it if there are no 1268 // JavaScript frames on the way to the C++ frame that has the 1269 // external handler. 1270 DCHECK(thread_local_top()->try_catch_handler_address() != NULL); 1271 Address external_handler_address = 1272 thread_local_top()->try_catch_handler_address(); 1273 JavaScriptFrameIterator it(this); 1274 if (it.done() || (it.frame()->sp() > external_handler_address)) { 1275 clear_exception = true; 1276 } 1277 } 1278 1279 // Clear the exception if needed. 1280 if (clear_exception) { 1281 thread_local_top()->external_caught_exception_ = false; 1282 clear_pending_exception(); 1283 return false; 1284 } 1285 1286 // Reschedule the exception. 1287 thread_local_top()->scheduled_exception_ = pending_exception(); 1288 clear_pending_exception(); 1289 return true; 1290 } 1291 1292 1293 void Isolate::PushPromise(Handle<JSObject> promise) { 1294 ThreadLocalTop* tltop = thread_local_top(); 1295 PromiseOnStack* prev = tltop->promise_on_stack_; 1296 StackHandler* handler = StackHandler::FromAddress(Isolate::handler(tltop)); 1297 Handle<JSObject> global_handle = 1298 Handle<JSObject>::cast(global_handles()->Create(*promise)); 1299 tltop->promise_on_stack_ = new PromiseOnStack(handler, global_handle, prev); 1300 } 1301 1302 1303 void Isolate::PopPromise() { 1304 ThreadLocalTop* tltop = thread_local_top(); 1305 if (tltop->promise_on_stack_ == NULL) return; 1306 PromiseOnStack* prev = tltop->promise_on_stack_->prev(); 1307 Handle<Object> global_handle = tltop->promise_on_stack_->promise(); 1308 delete tltop->promise_on_stack_; 1309 tltop->promise_on_stack_ = prev; 1310 global_handles()->Destroy(global_handle.location()); 1311 } 1312 1313 1314 Handle<Object> Isolate::GetPromiseOnStackOnThrow() { 1315 Handle<Object> undefined = factory()->undefined_value(); 1316 ThreadLocalTop* tltop = thread_local_top(); 1317 if (tltop->promise_on_stack_ == NULL) return undefined; 1318 StackHandler* promise_try = tltop->promise_on_stack_->handler(); 1319 // Find the top-most try-catch handler. 1320 StackHandler* handler = StackHandler::FromAddress(Isolate::handler(tltop)); 1321 do { 1322 if (handler == promise_try) { 1323 // Mark the pushed try-catch handler to prevent a later duplicate event 1324 // triggered with the following reject. 1325 return tltop->promise_on_stack_->promise(); 1326 } 1327 handler = handler->next(); 1328 // Throwing inside a Promise can be intercepted by an inner try-catch, so 1329 // we stop at the first try-catch handler. 1330 } while (handler != NULL && !handler->is_catch()); 1331 return undefined; 1332 } 1333 1334 1335 void Isolate::SetCaptureStackTraceForUncaughtExceptions( 1336 bool capture, 1337 int frame_limit, 1338 StackTrace::StackTraceOptions options) { 1339 capture_stack_trace_for_uncaught_exceptions_ = capture; 1340 stack_trace_for_uncaught_exceptions_frame_limit_ = frame_limit; 1341 stack_trace_for_uncaught_exceptions_options_ = options; 1342 } 1343 1344 1345 Handle<Context> Isolate::native_context() { 1346 return handle(context()->native_context()); 1347 } 1348 1349 1350 Handle<Context> Isolate::global_context() { 1351 return handle(context()->global_object()->global_context()); 1352 } 1353 1354 1355 Handle<Context> Isolate::GetCallingNativeContext() { 1356 JavaScriptFrameIterator it(this); 1357 if (debug_->in_debug_scope()) { 1358 while (!it.done()) { 1359 JavaScriptFrame* frame = it.frame(); 1360 Context* context = Context::cast(frame->context()); 1361 if (context->native_context() == *debug_->debug_context()) { 1362 it.Advance(); 1363 } else { 1364 break; 1365 } 1366 } 1367 } 1368 if (it.done()) return Handle<Context>::null(); 1369 JavaScriptFrame* frame = it.frame(); 1370 Context* context = Context::cast(frame->context()); 1371 return Handle<Context>(context->native_context()); 1372 } 1373 1374 1375 char* Isolate::ArchiveThread(char* to) { 1376 MemCopy(to, reinterpret_cast<char*>(thread_local_top()), 1377 sizeof(ThreadLocalTop)); 1378 InitializeThreadLocal(); 1379 clear_pending_exception(); 1380 clear_pending_message(); 1381 clear_scheduled_exception(); 1382 return to + sizeof(ThreadLocalTop); 1383 } 1384 1385 1386 char* Isolate::RestoreThread(char* from) { 1387 MemCopy(reinterpret_cast<char*>(thread_local_top()), from, 1388 sizeof(ThreadLocalTop)); 1389 // This might be just paranoia, but it seems to be needed in case a 1390 // thread_local_top_ is restored on a separate OS thread. 1391 #ifdef USE_SIMULATOR 1392 thread_local_top()->simulator_ = Simulator::current(this); 1393 #endif 1394 DCHECK(context() == NULL || context()->IsContext()); 1395 return from + sizeof(ThreadLocalTop); 1396 } 1397 1398 1399 Isolate::ThreadDataTable::ThreadDataTable() 1400 : list_(NULL) { 1401 } 1402 1403 1404 Isolate::ThreadDataTable::~ThreadDataTable() { 1405 // TODO(svenpanne) The assertion below would fire if an embedder does not 1406 // cleanly dispose all Isolates before disposing v8, so we are conservative 1407 // and leave it out for now. 1408 // DCHECK_EQ(NULL, list_); 1409 } 1410 1411 1412 Isolate::PerIsolateThreadData::~PerIsolateThreadData() { 1413 #if defined(USE_SIMULATOR) 1414 delete simulator_; 1415 #endif 1416 } 1417 1418 1419 Isolate::PerIsolateThreadData* 1420 Isolate::ThreadDataTable::Lookup(Isolate* isolate, 1421 ThreadId thread_id) { 1422 for (PerIsolateThreadData* data = list_; data != NULL; data = data->next_) { 1423 if (data->Matches(isolate, thread_id)) return data; 1424 } 1425 return NULL; 1426 } 1427 1428 1429 void Isolate::ThreadDataTable::Insert(Isolate::PerIsolateThreadData* data) { 1430 if (list_ != NULL) list_->prev_ = data; 1431 data->next_ = list_; 1432 list_ = data; 1433 } 1434 1435 1436 void Isolate::ThreadDataTable::Remove(PerIsolateThreadData* data) { 1437 if (list_ == data) list_ = data->next_; 1438 if (data->next_ != NULL) data->next_->prev_ = data->prev_; 1439 if (data->prev_ != NULL) data->prev_->next_ = data->next_; 1440 delete data; 1441 } 1442 1443 1444 void Isolate::ThreadDataTable::RemoveAllThreads(Isolate* isolate) { 1445 PerIsolateThreadData* data = list_; 1446 while (data != NULL) { 1447 PerIsolateThreadData* next = data->next_; 1448 if (data->isolate() == isolate) Remove(data); 1449 data = next; 1450 } 1451 } 1452 1453 1454 #ifdef DEBUG 1455 #define TRACE_ISOLATE(tag) \ 1456 do { \ 1457 if (FLAG_trace_isolates) { \ 1458 PrintF("Isolate %p (id %d)" #tag "\n", \ 1459 reinterpret_cast<void*>(this), id()); \ 1460 } \ 1461 } while (false) 1462 #else 1463 #define TRACE_ISOLATE(tag) 1464 #endif 1465 1466 1467 Isolate::Isolate() 1468 : embedder_data_(), 1469 state_(UNINITIALIZED), 1470 entry_stack_(NULL), 1471 stack_trace_nesting_level_(0), 1472 incomplete_message_(NULL), 1473 bootstrapper_(NULL), 1474 runtime_profiler_(NULL), 1475 compilation_cache_(NULL), 1476 counters_(NULL), 1477 code_range_(NULL), 1478 logger_(NULL), 1479 stats_table_(NULL), 1480 stub_cache_(NULL), 1481 code_aging_helper_(NULL), 1482 deoptimizer_data_(NULL), 1483 materialized_object_store_(NULL), 1484 capture_stack_trace_for_uncaught_exceptions_(false), 1485 stack_trace_for_uncaught_exceptions_frame_limit_(0), 1486 stack_trace_for_uncaught_exceptions_options_(StackTrace::kOverview), 1487 memory_allocator_(NULL), 1488 keyed_lookup_cache_(NULL), 1489 context_slot_cache_(NULL), 1490 descriptor_lookup_cache_(NULL), 1491 handle_scope_implementer_(NULL), 1492 unicode_cache_(NULL), 1493 runtime_zone_(this), 1494 inner_pointer_to_code_cache_(NULL), 1495 write_iterator_(NULL), 1496 global_handles_(NULL), 1497 eternal_handles_(NULL), 1498 thread_manager_(NULL), 1499 has_installed_extensions_(false), 1500 string_tracker_(NULL), 1501 regexp_stack_(NULL), 1502 date_cache_(NULL), 1503 call_descriptor_data_(NULL), 1504 // TODO(bmeurer) Initialized lazily because it depends on flags; can 1505 // be fixed once the default isolate cleanup is done. 1506 random_number_generator_(NULL), 1507 serializer_enabled_(false), 1508 has_fatal_error_(false), 1509 initialized_from_snapshot_(false), 1510 cpu_profiler_(NULL), 1511 heap_profiler_(NULL), 1512 function_entry_hook_(NULL), 1513 deferred_handles_head_(NULL), 1514 optimizing_compiler_thread_(NULL), 1515 sweeper_thread_(NULL), 1516 num_sweeper_threads_(0), 1517 stress_deopt_count_(0), 1518 next_optimization_id_(0), 1519 use_counter_callback_(NULL) { 1520 { 1521 base::LockGuard<base::Mutex> lock_guard(thread_data_table_mutex_.Pointer()); 1522 CHECK(thread_data_table_); 1523 } 1524 id_ = base::NoBarrier_AtomicIncrement(&isolate_counter_, 1); 1525 TRACE_ISOLATE(constructor); 1526 1527 memset(isolate_addresses_, 0, 1528 sizeof(isolate_addresses_[0]) * (kIsolateAddressCount + 1)); 1529 1530 heap_.isolate_ = this; 1531 stack_guard_.isolate_ = this; 1532 1533 // ThreadManager is initialized early to support locking an isolate 1534 // before it is entered. 1535 thread_manager_ = new ThreadManager(); 1536 thread_manager_->isolate_ = this; 1537 1538 #ifdef DEBUG 1539 // heap_histograms_ initializes itself. 1540 memset(&js_spill_information_, 0, sizeof(js_spill_information_)); 1541 #endif 1542 1543 handle_scope_data_.Initialize(); 1544 1545 #define ISOLATE_INIT_EXECUTE(type, name, initial_value) \ 1546 name##_ = (initial_value); 1547 ISOLATE_INIT_LIST(ISOLATE_INIT_EXECUTE) 1548 #undef ISOLATE_INIT_EXECUTE 1549 1550 #define ISOLATE_INIT_ARRAY_EXECUTE(type, name, length) \ 1551 memset(name##_, 0, sizeof(type) * length); 1552 ISOLATE_INIT_ARRAY_LIST(ISOLATE_INIT_ARRAY_EXECUTE) 1553 #undef ISOLATE_INIT_ARRAY_EXECUTE 1554 1555 InitializeLoggingAndCounters(); 1556 debug_ = new Debug(this); 1557 } 1558 1559 1560 void Isolate::TearDown() { 1561 TRACE_ISOLATE(tear_down); 1562 1563 // Temporarily set this isolate as current so that various parts of 1564 // the isolate can access it in their destructors without having a 1565 // direct pointer. We don't use Enter/Exit here to avoid 1566 // initializing the thread data. 1567 PerIsolateThreadData* saved_data = CurrentPerIsolateThreadData(); 1568 Isolate* saved_isolate = UncheckedCurrent(); 1569 SetIsolateThreadLocals(this, NULL); 1570 1571 Deinit(); 1572 1573 { 1574 base::LockGuard<base::Mutex> lock_guard(thread_data_table_mutex_.Pointer()); 1575 thread_data_table_->RemoveAllThreads(this); 1576 } 1577 1578 if (serialize_partial_snapshot_cache_ != NULL) { 1579 delete[] serialize_partial_snapshot_cache_; 1580 serialize_partial_snapshot_cache_ = NULL; 1581 } 1582 1583 delete this; 1584 1585 // Restore the previous current isolate. 1586 SetIsolateThreadLocals(saved_isolate, saved_data); 1587 } 1588 1589 1590 void Isolate::GlobalTearDown() { 1591 delete thread_data_table_; 1592 thread_data_table_ = NULL; 1593 } 1594 1595 1596 void Isolate::Deinit() { 1597 if (state_ == INITIALIZED) { 1598 TRACE_ISOLATE(deinit); 1599 1600 debug()->Unload(); 1601 1602 FreeThreadResources(); 1603 1604 if (concurrent_recompilation_enabled()) { 1605 optimizing_compiler_thread_->Stop(); 1606 delete optimizing_compiler_thread_; 1607 optimizing_compiler_thread_ = NULL; 1608 } 1609 1610 for (int i = 0; i < num_sweeper_threads_; i++) { 1611 sweeper_thread_[i]->Stop(); 1612 delete sweeper_thread_[i]; 1613 sweeper_thread_[i] = NULL; 1614 } 1615 delete[] sweeper_thread_; 1616 sweeper_thread_ = NULL; 1617 1618 if (FLAG_job_based_sweeping && 1619 heap_.mark_compact_collector()->sweeping_in_progress()) { 1620 heap_.mark_compact_collector()->EnsureSweepingCompleted(); 1621 } 1622 1623 if (FLAG_turbo_stats) GetTStatistics()->Print("TurboFan"); 1624 if (FLAG_hydrogen_stats) GetHStatistics()->Print("Hydrogen"); 1625 1626 if (FLAG_print_deopt_stress) { 1627 PrintF(stdout, "=== Stress deopt counter: %u\n", stress_deopt_count_); 1628 } 1629 1630 // We must stop the logger before we tear down other components. 1631 Sampler* sampler = logger_->sampler(); 1632 if (sampler && sampler->IsActive()) sampler->Stop(); 1633 1634 delete deoptimizer_data_; 1635 deoptimizer_data_ = NULL; 1636 builtins_.TearDown(); 1637 bootstrapper_->TearDown(); 1638 1639 if (runtime_profiler_ != NULL) { 1640 delete runtime_profiler_; 1641 runtime_profiler_ = NULL; 1642 } 1643 heap_.TearDown(); 1644 logger_->TearDown(); 1645 1646 delete heap_profiler_; 1647 heap_profiler_ = NULL; 1648 delete cpu_profiler_; 1649 cpu_profiler_ = NULL; 1650 1651 // The default isolate is re-initializable due to legacy API. 1652 state_ = UNINITIALIZED; 1653 } 1654 } 1655 1656 1657 void Isolate::PushToPartialSnapshotCache(Object* obj) { 1658 int length = serialize_partial_snapshot_cache_length(); 1659 int capacity = serialize_partial_snapshot_cache_capacity(); 1660 1661 if (length >= capacity) { 1662 int new_capacity = static_cast<int>((capacity + 10) * 1.2); 1663 Object** new_array = new Object*[new_capacity]; 1664 for (int i = 0; i < length; i++) { 1665 new_array[i] = serialize_partial_snapshot_cache()[i]; 1666 } 1667 if (capacity != 0) delete[] serialize_partial_snapshot_cache(); 1668 set_serialize_partial_snapshot_cache(new_array); 1669 set_serialize_partial_snapshot_cache_capacity(new_capacity); 1670 } 1671 1672 serialize_partial_snapshot_cache()[length] = obj; 1673 set_serialize_partial_snapshot_cache_length(length + 1); 1674 } 1675 1676 1677 void Isolate::SetIsolateThreadLocals(Isolate* isolate, 1678 PerIsolateThreadData* data) { 1679 base::Thread::SetThreadLocal(isolate_key_, isolate); 1680 base::Thread::SetThreadLocal(per_isolate_thread_data_key_, data); 1681 } 1682 1683 1684 Isolate::~Isolate() { 1685 TRACE_ISOLATE(destructor); 1686 1687 // Has to be called while counters_ are still alive 1688 runtime_zone_.DeleteKeptSegment(); 1689 1690 // The entry stack must be empty when we get here. 1691 DCHECK(entry_stack_ == NULL || entry_stack_->previous_item == NULL); 1692 1693 delete entry_stack_; 1694 entry_stack_ = NULL; 1695 1696 delete unicode_cache_; 1697 unicode_cache_ = NULL; 1698 1699 delete date_cache_; 1700 date_cache_ = NULL; 1701 1702 delete[] call_descriptor_data_; 1703 call_descriptor_data_ = NULL; 1704 1705 delete regexp_stack_; 1706 regexp_stack_ = NULL; 1707 1708 delete descriptor_lookup_cache_; 1709 descriptor_lookup_cache_ = NULL; 1710 delete context_slot_cache_; 1711 context_slot_cache_ = NULL; 1712 delete keyed_lookup_cache_; 1713 keyed_lookup_cache_ = NULL; 1714 1715 delete stub_cache_; 1716 stub_cache_ = NULL; 1717 delete code_aging_helper_; 1718 code_aging_helper_ = NULL; 1719 delete stats_table_; 1720 stats_table_ = NULL; 1721 1722 delete materialized_object_store_; 1723 materialized_object_store_ = NULL; 1724 1725 delete logger_; 1726 logger_ = NULL; 1727 1728 delete counters_; 1729 counters_ = NULL; 1730 1731 delete handle_scope_implementer_; 1732 handle_scope_implementer_ = NULL; 1733 1734 delete compilation_cache_; 1735 compilation_cache_ = NULL; 1736 delete bootstrapper_; 1737 bootstrapper_ = NULL; 1738 delete inner_pointer_to_code_cache_; 1739 inner_pointer_to_code_cache_ = NULL; 1740 delete write_iterator_; 1741 write_iterator_ = NULL; 1742 1743 delete thread_manager_; 1744 thread_manager_ = NULL; 1745 1746 delete string_tracker_; 1747 string_tracker_ = NULL; 1748 1749 delete memory_allocator_; 1750 memory_allocator_ = NULL; 1751 delete code_range_; 1752 code_range_ = NULL; 1753 delete global_handles_; 1754 global_handles_ = NULL; 1755 delete eternal_handles_; 1756 eternal_handles_ = NULL; 1757 1758 delete string_stream_debug_object_cache_; 1759 string_stream_debug_object_cache_ = NULL; 1760 1761 delete external_reference_table_; 1762 external_reference_table_ = NULL; 1763 1764 delete random_number_generator_; 1765 random_number_generator_ = NULL; 1766 1767 delete debug_; 1768 debug_ = NULL; 1769 } 1770 1771 1772 void Isolate::InitializeThreadLocal() { 1773 thread_local_top_.isolate_ = this; 1774 thread_local_top_.Initialize(); 1775 } 1776 1777 1778 bool Isolate::PropagatePendingExceptionToExternalTryCatch() { 1779 DCHECK(has_pending_exception()); 1780 1781 bool has_external_try_catch = HasExternalTryCatch(); 1782 if (!has_external_try_catch) { 1783 thread_local_top_.external_caught_exception_ = false; 1784 return true; 1785 } 1786 1787 bool catchable_by_js = is_catchable_by_javascript(pending_exception()); 1788 if (catchable_by_js && IsFinallyOnTop()) { 1789 thread_local_top_.external_caught_exception_ = false; 1790 return false; 1791 } 1792 1793 thread_local_top_.external_caught_exception_ = true; 1794 if (thread_local_top_.pending_exception_ == heap()->termination_exception()) { 1795 try_catch_handler()->can_continue_ = false; 1796 try_catch_handler()->has_terminated_ = true; 1797 try_catch_handler()->exception_ = heap()->null_value(); 1798 } else { 1799 v8::TryCatch* handler = try_catch_handler(); 1800 DCHECK(thread_local_top_.pending_message_obj_->IsJSMessageObject() || 1801 thread_local_top_.pending_message_obj_->IsTheHole()); 1802 DCHECK(thread_local_top_.pending_message_script_->IsScript() || 1803 thread_local_top_.pending_message_script_->IsTheHole()); 1804 handler->can_continue_ = true; 1805 handler->has_terminated_ = false; 1806 handler->exception_ = pending_exception(); 1807 // Propagate to the external try-catch only if we got an actual message. 1808 if (thread_local_top_.pending_message_obj_->IsTheHole()) return true; 1809 1810 handler->message_obj_ = thread_local_top_.pending_message_obj_; 1811 handler->message_script_ = thread_local_top_.pending_message_script_; 1812 handler->message_start_pos_ = thread_local_top_.pending_message_start_pos_; 1813 handler->message_end_pos_ = thread_local_top_.pending_message_end_pos_; 1814 } 1815 return true; 1816 } 1817 1818 1819 void Isolate::InitializeLoggingAndCounters() { 1820 if (logger_ == NULL) { 1821 logger_ = new Logger(this); 1822 } 1823 if (counters_ == NULL) { 1824 counters_ = new Counters(this); 1825 } 1826 } 1827 1828 1829 bool Isolate::Init(Deserializer* des) { 1830 DCHECK(state_ != INITIALIZED); 1831 TRACE_ISOLATE(init); 1832 1833 stress_deopt_count_ = FLAG_deopt_every_n_times; 1834 1835 has_fatal_error_ = false; 1836 1837 if (function_entry_hook() != NULL) { 1838 // When function entry hooking is in effect, we have to create the code 1839 // stubs from scratch to get entry hooks, rather than loading the previously 1840 // generated stubs from disk. 1841 // If this assert fires, the initialization path has regressed. 1842 DCHECK(des == NULL); 1843 } 1844 1845 // The initialization process does not handle memory exhaustion. 1846 DisallowAllocationFailure disallow_allocation_failure(this); 1847 1848 memory_allocator_ = new MemoryAllocator(this); 1849 code_range_ = new CodeRange(this); 1850 1851 // Safe after setting Heap::isolate_, and initializing StackGuard 1852 heap_.SetStackLimits(); 1853 1854 #define ASSIGN_ELEMENT(CamelName, hacker_name) \ 1855 isolate_addresses_[Isolate::k##CamelName##Address] = \ 1856 reinterpret_cast<Address>(hacker_name##_address()); 1857 FOR_EACH_ISOLATE_ADDRESS_NAME(ASSIGN_ELEMENT) 1858 #undef ASSIGN_ELEMENT 1859 1860 string_tracker_ = new StringTracker(); 1861 string_tracker_->isolate_ = this; 1862 compilation_cache_ = new CompilationCache(this); 1863 keyed_lookup_cache_ = new KeyedLookupCache(); 1864 context_slot_cache_ = new ContextSlotCache(); 1865 descriptor_lookup_cache_ = new DescriptorLookupCache(); 1866 unicode_cache_ = new UnicodeCache(); 1867 inner_pointer_to_code_cache_ = new InnerPointerToCodeCache(this); 1868 write_iterator_ = new ConsStringIteratorOp(); 1869 global_handles_ = new GlobalHandles(this); 1870 eternal_handles_ = new EternalHandles(); 1871 bootstrapper_ = new Bootstrapper(this); 1872 handle_scope_implementer_ = new HandleScopeImplementer(this); 1873 stub_cache_ = new StubCache(this); 1874 materialized_object_store_ = new MaterializedObjectStore(this); 1875 regexp_stack_ = new RegExpStack(); 1876 regexp_stack_->isolate_ = this; 1877 date_cache_ = new DateCache(); 1878 call_descriptor_data_ = 1879 new CallInterfaceDescriptorData[CallDescriptors::NUMBER_OF_DESCRIPTORS]; 1880 cpu_profiler_ = new CpuProfiler(this); 1881 heap_profiler_ = new HeapProfiler(heap()); 1882 1883 // Enable logging before setting up the heap 1884 logger_->SetUp(this); 1885 1886 // Initialize other runtime facilities 1887 #if defined(USE_SIMULATOR) 1888 #if V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_ARM64 || \ 1889 V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64 1890 Simulator::Initialize(this); 1891 #endif 1892 #endif 1893 1894 code_aging_helper_ = new CodeAgingHelper(); 1895 1896 { // NOLINT 1897 // Ensure that the thread has a valid stack guard. The v8::Locker object 1898 // will ensure this too, but we don't have to use lockers if we are only 1899 // using one thread. 1900 ExecutionAccess lock(this); 1901 stack_guard_.InitThread(lock); 1902 } 1903 1904 // SetUp the object heap. 1905 DCHECK(!heap_.HasBeenSetUp()); 1906 if (!heap_.SetUp()) { 1907 V8::FatalProcessOutOfMemory("heap setup"); 1908 return false; 1909 } 1910 1911 deoptimizer_data_ = new DeoptimizerData(memory_allocator_); 1912 1913 const bool create_heap_objects = (des == NULL); 1914 if (create_heap_objects && !heap_.CreateHeapObjects()) { 1915 V8::FatalProcessOutOfMemory("heap object creation"); 1916 return false; 1917 } 1918 1919 if (create_heap_objects) { 1920 // Terminate the cache array with the sentinel so we can iterate. 1921 PushToPartialSnapshotCache(heap_.undefined_value()); 1922 } 1923 1924 InitializeThreadLocal(); 1925 1926 bootstrapper_->Initialize(create_heap_objects); 1927 builtins_.SetUp(this, create_heap_objects); 1928 1929 if (FLAG_log_internal_timer_events) { 1930 set_event_logger(Logger::DefaultTimerEventsLogger); 1931 } else { 1932 set_event_logger(Logger::EmptyTimerEventsLogger); 1933 } 1934 1935 // Set default value if not yet set. 1936 // TODO(yangguo): move this to ResourceConstraints::ConfigureDefaults 1937 // once ResourceConstraints becomes an argument to the Isolate constructor. 1938 if (max_available_threads_ < 1) { 1939 // Choose the default between 1 and 4. 1940 max_available_threads_ = 1941 Max(Min(base::SysInfo::NumberOfProcessors(), 4), 1); 1942 } 1943 1944 if (!FLAG_job_based_sweeping) { 1945 num_sweeper_threads_ = 1946 SweeperThread::NumberOfThreads(max_available_threads_); 1947 } 1948 1949 if (FLAG_trace_hydrogen || FLAG_trace_hydrogen_stubs) { 1950 PrintF("Concurrent recompilation has been disabled for tracing.\n"); 1951 } else if (OptimizingCompilerThread::Enabled(max_available_threads_)) { 1952 optimizing_compiler_thread_ = new OptimizingCompilerThread(this); 1953 optimizing_compiler_thread_->Start(); 1954 } 1955 1956 if (num_sweeper_threads_ > 0) { 1957 sweeper_thread_ = new SweeperThread*[num_sweeper_threads_]; 1958 for (int i = 0; i < num_sweeper_threads_; i++) { 1959 sweeper_thread_[i] = new SweeperThread(this); 1960 sweeper_thread_[i]->Start(); 1961 } 1962 } 1963 1964 // If we are deserializing, read the state into the now-empty heap. 1965 if (!create_heap_objects) { 1966 des->Deserialize(this); 1967 } 1968 stub_cache_->Initialize(); 1969 1970 // Finish initialization of ThreadLocal after deserialization is done. 1971 clear_pending_exception(); 1972 clear_pending_message(); 1973 clear_scheduled_exception(); 1974 1975 // Deserializing may put strange things in the root array's copy of the 1976 // stack guard. 1977 heap_.SetStackLimits(); 1978 1979 // Quiet the heap NaN if needed on target platform. 1980 if (!create_heap_objects) Assembler::QuietNaN(heap_.nan_value()); 1981 1982 runtime_profiler_ = new RuntimeProfiler(this); 1983 1984 // If we are deserializing, log non-function code objects and compiled 1985 // functions found in the snapshot. 1986 if (!create_heap_objects && 1987 (FLAG_log_code || 1988 FLAG_ll_prof || 1989 FLAG_perf_jit_prof || 1990 FLAG_perf_basic_prof || 1991 logger_->is_logging_code_events())) { 1992 HandleScope scope(this); 1993 LOG(this, LogCodeObjects()); 1994 LOG(this, LogCompiledFunctions()); 1995 } 1996 1997 CHECK_EQ(static_cast<int>(OFFSET_OF(Isolate, embedder_data_)), 1998 Internals::kIsolateEmbedderDataOffset); 1999 CHECK_EQ(static_cast<int>(OFFSET_OF(Isolate, heap_.roots_)), 2000 Internals::kIsolateRootsOffset); 2001 CHECK_EQ(static_cast<int>( 2002 OFFSET_OF(Isolate, heap_.amount_of_external_allocated_memory_)), 2003 Internals::kAmountOfExternalAllocatedMemoryOffset); 2004 CHECK_EQ(static_cast<int>(OFFSET_OF( 2005 Isolate, 2006 heap_.amount_of_external_allocated_memory_at_last_global_gc_)), 2007 Internals::kAmountOfExternalAllocatedMemoryAtLastGlobalGCOffset); 2008 2009 state_ = INITIALIZED; 2010 time_millis_at_init_ = base::OS::TimeCurrentMillis(); 2011 2012 if (!create_heap_objects) { 2013 // Now that the heap is consistent, it's OK to generate the code for the 2014 // deopt entry table that might have been referred to by optimized code in 2015 // the snapshot. 2016 HandleScope scope(this); 2017 Deoptimizer::EnsureCodeForDeoptimizationEntry( 2018 this, 2019 Deoptimizer::LAZY, 2020 kDeoptTableSerializeEntryCount - 1); 2021 } 2022 2023 if (!serializer_enabled()) { 2024 // Ensure that all stubs which need to be generated ahead of time, but 2025 // cannot be serialized into the snapshot have been generated. 2026 HandleScope scope(this); 2027 CodeStub::GenerateFPStubs(this); 2028 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(this); 2029 StubFailureTrampolineStub::GenerateAheadOfTime(this); 2030 } 2031 2032 initialized_from_snapshot_ = (des != NULL); 2033 2034 return true; 2035 } 2036 2037 2038 // Initialized lazily to allow early 2039 // v8::V8::SetAddHistogramSampleFunction calls. 2040 StatsTable* Isolate::stats_table() { 2041 if (stats_table_ == NULL) { 2042 stats_table_ = new StatsTable; 2043 } 2044 return stats_table_; 2045 } 2046 2047 2048 void Isolate::Enter() { 2049 Isolate* current_isolate = NULL; 2050 PerIsolateThreadData* current_data = CurrentPerIsolateThreadData(); 2051 if (current_data != NULL) { 2052 current_isolate = current_data->isolate_; 2053 DCHECK(current_isolate != NULL); 2054 if (current_isolate == this) { 2055 DCHECK(Current() == this); 2056 DCHECK(entry_stack_ != NULL); 2057 DCHECK(entry_stack_->previous_thread_data == NULL || 2058 entry_stack_->previous_thread_data->thread_id().Equals( 2059 ThreadId::Current())); 2060 // Same thread re-enters the isolate, no need to re-init anything. 2061 entry_stack_->entry_count++; 2062 return; 2063 } 2064 } 2065 2066 PerIsolateThreadData* data = FindOrAllocatePerThreadDataForThisThread(); 2067 DCHECK(data != NULL); 2068 DCHECK(data->isolate_ == this); 2069 2070 EntryStackItem* item = new EntryStackItem(current_data, 2071 current_isolate, 2072 entry_stack_); 2073 entry_stack_ = item; 2074 2075 SetIsolateThreadLocals(this, data); 2076 2077 // In case it's the first time some thread enters the isolate. 2078 set_thread_id(data->thread_id()); 2079 } 2080 2081 2082 void Isolate::Exit() { 2083 DCHECK(entry_stack_ != NULL); 2084 DCHECK(entry_stack_->previous_thread_data == NULL || 2085 entry_stack_->previous_thread_data->thread_id().Equals( 2086 ThreadId::Current())); 2087 2088 if (--entry_stack_->entry_count > 0) return; 2089 2090 DCHECK(CurrentPerIsolateThreadData() != NULL); 2091 DCHECK(CurrentPerIsolateThreadData()->isolate_ == this); 2092 2093 // Pop the stack. 2094 EntryStackItem* item = entry_stack_; 2095 entry_stack_ = item->previous_item; 2096 2097 PerIsolateThreadData* previous_thread_data = item->previous_thread_data; 2098 Isolate* previous_isolate = item->previous_isolate; 2099 2100 delete item; 2101 2102 // Reinit the current thread for the isolate it was running before this one. 2103 SetIsolateThreadLocals(previous_isolate, previous_thread_data); 2104 } 2105 2106 2107 void Isolate::LinkDeferredHandles(DeferredHandles* deferred) { 2108 deferred->next_ = deferred_handles_head_; 2109 if (deferred_handles_head_ != NULL) { 2110 deferred_handles_head_->previous_ = deferred; 2111 } 2112 deferred_handles_head_ = deferred; 2113 } 2114 2115 2116 void Isolate::UnlinkDeferredHandles(DeferredHandles* deferred) { 2117 #ifdef DEBUG 2118 // In debug mode assert that the linked list is well-formed. 2119 DeferredHandles* deferred_iterator = deferred; 2120 while (deferred_iterator->previous_ != NULL) { 2121 deferred_iterator = deferred_iterator->previous_; 2122 } 2123 DCHECK(deferred_handles_head_ == deferred_iterator); 2124 #endif 2125 if (deferred_handles_head_ == deferred) { 2126 deferred_handles_head_ = deferred_handles_head_->next_; 2127 } 2128 if (deferred->next_ != NULL) { 2129 deferred->next_->previous_ = deferred->previous_; 2130 } 2131 if (deferred->previous_ != NULL) { 2132 deferred->previous_->next_ = deferred->next_; 2133 } 2134 } 2135 2136 2137 HStatistics* Isolate::GetHStatistics() { 2138 if (hstatistics() == NULL) set_hstatistics(new HStatistics()); 2139 return hstatistics(); 2140 } 2141 2142 2143 HStatistics* Isolate::GetTStatistics() { 2144 if (tstatistics() == NULL) set_tstatistics(new HStatistics()); 2145 return tstatistics(); 2146 } 2147 2148 2149 HTracer* Isolate::GetHTracer() { 2150 if (htracer() == NULL) set_htracer(new HTracer(id())); 2151 return htracer(); 2152 } 2153 2154 2155 CodeTracer* Isolate::GetCodeTracer() { 2156 if (code_tracer() == NULL) set_code_tracer(new CodeTracer(id())); 2157 return code_tracer(); 2158 } 2159 2160 2161 Map* Isolate::get_initial_js_array_map(ElementsKind kind) { 2162 Context* native_context = context()->native_context(); 2163 Object* maybe_map_array = native_context->js_array_maps(); 2164 if (!maybe_map_array->IsUndefined()) { 2165 Object* maybe_transitioned_map = 2166 FixedArray::cast(maybe_map_array)->get(kind); 2167 if (!maybe_transitioned_map->IsUndefined()) { 2168 return Map::cast(maybe_transitioned_map); 2169 } 2170 } 2171 return NULL; 2172 } 2173 2174 2175 bool Isolate::use_crankshaft() const { 2176 return FLAG_crankshaft && 2177 !serializer_enabled_ && 2178 CpuFeatures::SupportsCrankshaft(); 2179 } 2180 2181 2182 bool Isolate::IsFastArrayConstructorPrototypeChainIntact() { 2183 Map* root_array_map = 2184 get_initial_js_array_map(GetInitialFastElementsKind()); 2185 DCHECK(root_array_map != NULL); 2186 JSObject* initial_array_proto = JSObject::cast(*initial_array_prototype()); 2187 2188 // Check that the array prototype hasn't been altered WRT empty elements. 2189 if (root_array_map->prototype() != initial_array_proto) return false; 2190 if (initial_array_proto->elements() != heap()->empty_fixed_array()) { 2191 return false; 2192 } 2193 2194 // Check that the object prototype hasn't been altered WRT empty elements. 2195 JSObject* initial_object_proto = JSObject::cast(*initial_object_prototype()); 2196 PrototypeIterator iter(this, initial_array_proto); 2197 if (iter.IsAtEnd() || iter.GetCurrent() != initial_object_proto) { 2198 return false; 2199 } 2200 if (initial_object_proto->elements() != heap()->empty_fixed_array()) { 2201 return false; 2202 } 2203 2204 iter.Advance(); 2205 return iter.IsAtEnd(); 2206 } 2207 2208 2209 CallInterfaceDescriptorData* Isolate::call_descriptor_data(int index) { 2210 DCHECK(0 <= index && index < CallDescriptors::NUMBER_OF_DESCRIPTORS); 2211 return &call_descriptor_data_[index]; 2212 } 2213 2214 2215 Object* Isolate::FindCodeObject(Address a) { 2216 return inner_pointer_to_code_cache()->GcSafeFindCodeForInnerPointer(a); 2217 } 2218 2219 2220 #ifdef DEBUG 2221 #define ISOLATE_FIELD_OFFSET(type, name, ignored) \ 2222 const intptr_t Isolate::name##_debug_offset_ = OFFSET_OF(Isolate, name##_); 2223 ISOLATE_INIT_LIST(ISOLATE_FIELD_OFFSET) 2224 ISOLATE_INIT_ARRAY_LIST(ISOLATE_FIELD_OFFSET) 2225 #undef ISOLATE_FIELD_OFFSET 2226 #endif 2227 2228 2229 Handle<JSObject> Isolate::GetSymbolRegistry() { 2230 if (heap()->symbol_registry()->IsUndefined()) { 2231 Handle<Map> map = factory()->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize); 2232 Handle<JSObject> registry = factory()->NewJSObjectFromMap(map); 2233 heap()->set_symbol_registry(*registry); 2234 2235 static const char* nested[] = { 2236 "for", "for_api", "for_intern", "keyFor", "private_api", "private_intern" 2237 }; 2238 for (unsigned i = 0; i < arraysize(nested); ++i) { 2239 Handle<String> name = factory()->InternalizeUtf8String(nested[i]); 2240 Handle<JSObject> obj = factory()->NewJSObjectFromMap(map); 2241 JSObject::NormalizeProperties(obj, KEEP_INOBJECT_PROPERTIES, 8); 2242 JSObject::SetProperty(registry, name, obj, STRICT).Assert(); 2243 } 2244 } 2245 return Handle<JSObject>::cast(factory()->symbol_registry()); 2246 } 2247 2248 2249 void Isolate::AddCallCompletedCallback(CallCompletedCallback callback) { 2250 for (int i = 0; i < call_completed_callbacks_.length(); i++) { 2251 if (callback == call_completed_callbacks_.at(i)) return; 2252 } 2253 call_completed_callbacks_.Add(callback); 2254 } 2255 2256 2257 void Isolate::RemoveCallCompletedCallback(CallCompletedCallback callback) { 2258 for (int i = 0; i < call_completed_callbacks_.length(); i++) { 2259 if (callback == call_completed_callbacks_.at(i)) { 2260 call_completed_callbacks_.Remove(i); 2261 } 2262 } 2263 } 2264 2265 2266 void Isolate::FireCallCompletedCallback() { 2267 bool has_call_completed_callbacks = !call_completed_callbacks_.is_empty(); 2268 bool run_microtasks = autorun_microtasks() && pending_microtask_count(); 2269 if (!has_call_completed_callbacks && !run_microtasks) return; 2270 2271 if (!handle_scope_implementer()->CallDepthIsZero()) return; 2272 if (run_microtasks) RunMicrotasks(); 2273 // Fire callbacks. Increase call depth to prevent recursive callbacks. 2274 v8::Isolate::SuppressMicrotaskExecutionScope suppress( 2275 reinterpret_cast<v8::Isolate*>(this)); 2276 for (int i = 0; i < call_completed_callbacks_.length(); i++) { 2277 call_completed_callbacks_.at(i)(); 2278 } 2279 } 2280 2281 2282 void Isolate::EnqueueMicrotask(Handle<Object> microtask) { 2283 DCHECK(microtask->IsJSFunction() || microtask->IsCallHandlerInfo()); 2284 Handle<FixedArray> queue(heap()->microtask_queue(), this); 2285 int num_tasks = pending_microtask_count(); 2286 DCHECK(num_tasks <= queue->length()); 2287 if (num_tasks == 0) { 2288 queue = factory()->NewFixedArray(8); 2289 heap()->set_microtask_queue(*queue); 2290 } else if (num_tasks == queue->length()) { 2291 queue = FixedArray::CopySize(queue, num_tasks * 2); 2292 heap()->set_microtask_queue(*queue); 2293 } 2294 DCHECK(queue->get(num_tasks)->IsUndefined()); 2295 queue->set(num_tasks, *microtask); 2296 set_pending_microtask_count(num_tasks + 1); 2297 } 2298 2299 2300 void Isolate::RunMicrotasks() { 2301 // %RunMicrotasks may be called in mjsunit tests, which violates 2302 // this assertion, hence the check for --allow-natives-syntax. 2303 // TODO(adamk): However, this also fails some layout tests. 2304 // 2305 // DCHECK(FLAG_allow_natives_syntax || 2306 // handle_scope_implementer()->CallDepthIsZero()); 2307 2308 // Increase call depth to prevent recursive callbacks. 2309 v8::Isolate::SuppressMicrotaskExecutionScope suppress( 2310 reinterpret_cast<v8::Isolate*>(this)); 2311 2312 while (pending_microtask_count() > 0) { 2313 HandleScope scope(this); 2314 int num_tasks = pending_microtask_count(); 2315 Handle<FixedArray> queue(heap()->microtask_queue(), this); 2316 DCHECK(num_tasks <= queue->length()); 2317 set_pending_microtask_count(0); 2318 heap()->set_microtask_queue(heap()->empty_fixed_array()); 2319 2320 for (int i = 0; i < num_tasks; i++) { 2321 HandleScope scope(this); 2322 Handle<Object> microtask(queue->get(i), this); 2323 if (microtask->IsJSFunction()) { 2324 Handle<JSFunction> microtask_function = 2325 Handle<JSFunction>::cast(microtask); 2326 SaveContext save(this); 2327 set_context(microtask_function->context()->native_context()); 2328 MaybeHandle<Object> maybe_exception; 2329 MaybeHandle<Object> result = 2330 Execution::TryCall(microtask_function, factory()->undefined_value(), 2331 0, NULL, &maybe_exception); 2332 // If execution is terminating, just bail out. 2333 Handle<Object> exception; 2334 if (result.is_null() && maybe_exception.is_null()) { 2335 // Clear out any remaining callbacks in the queue. 2336 heap()->set_microtask_queue(heap()->empty_fixed_array()); 2337 set_pending_microtask_count(0); 2338 return; 2339 } 2340 } else { 2341 Handle<CallHandlerInfo> callback_info = 2342 Handle<CallHandlerInfo>::cast(microtask); 2343 v8::MicrotaskCallback callback = 2344 v8::ToCData<v8::MicrotaskCallback>(callback_info->callback()); 2345 void* data = v8::ToCData<void*>(callback_info->data()); 2346 callback(data); 2347 } 2348 } 2349 } 2350 } 2351 2352 2353 void Isolate::SetUseCounterCallback(v8::Isolate::UseCounterCallback callback) { 2354 DCHECK(!use_counter_callback_); 2355 use_counter_callback_ = callback; 2356 } 2357 2358 2359 void Isolate::CountUsage(v8::Isolate::UseCounterFeature feature) { 2360 if (use_counter_callback_) { 2361 use_counter_callback_(reinterpret_cast<v8::Isolate*>(this), feature); 2362 } 2363 } 2364 2365 2366 bool StackLimitCheck::JsHasOverflowed() const { 2367 StackGuard* stack_guard = isolate_->stack_guard(); 2368 #ifdef USE_SIMULATOR 2369 // The simulator uses a separate JS stack. 2370 Address jssp_address = Simulator::current(isolate_)->get_sp(); 2371 uintptr_t jssp = reinterpret_cast<uintptr_t>(jssp_address); 2372 if (jssp < stack_guard->real_jslimit()) return true; 2373 #endif // USE_SIMULATOR 2374 return GetCurrentStackPosition() < stack_guard->real_climit(); 2375 } 2376 2377 2378 bool PostponeInterruptsScope::Intercept(StackGuard::InterruptFlag flag) { 2379 // First check whether the previous scope intercepts. 2380 if (prev_ && prev_->Intercept(flag)) return true; 2381 // Then check whether this scope intercepts. 2382 if ((flag & intercept_mask_)) { 2383 intercepted_flags_ |= flag; 2384 return true; 2385 } 2386 return false; 2387 } 2388 2389 } } // namespace v8::internal 2390