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 "src/isolate.h" 6 7 #include <stdlib.h> 8 9 #include <fstream> // NOLINT(readability/streams) 10 #include <sstream> 11 12 #include "src/ast/context-slot-cache.h" 13 #include "src/base/hashmap.h" 14 #include "src/base/platform/platform.h" 15 #include "src/base/sys-info.h" 16 #include "src/base/utils/random-number-generator.h" 17 #include "src/basic-block-profiler.h" 18 #include "src/bootstrapper.h" 19 #include "src/cancelable-task.h" 20 #include "src/codegen.h" 21 #include "src/compilation-cache.h" 22 #include "src/compilation-statistics.h" 23 #include "src/compiler-dispatcher/compiler-dispatcher-tracer.h" 24 #include "src/compiler-dispatcher/optimizing-compile-dispatcher.h" 25 #include "src/crankshaft/hydrogen.h" 26 #include "src/debug/debug.h" 27 #include "src/deoptimizer.h" 28 #include "src/elements.h" 29 #include "src/external-reference-table.h" 30 #include "src/frames-inl.h" 31 #include "src/ic/access-compiler-data.h" 32 #include "src/ic/stub-cache.h" 33 #include "src/interface-descriptors.h" 34 #include "src/interpreter/interpreter.h" 35 #include "src/isolate-inl.h" 36 #include "src/libsampler/sampler.h" 37 #include "src/log.h" 38 #include "src/messages.h" 39 #include "src/profiler/cpu-profiler.h" 40 #include "src/prototype.h" 41 #include "src/regexp/regexp-stack.h" 42 #include "src/runtime-profiler.h" 43 #include "src/simulator.h" 44 #include "src/snapshot/deserializer.h" 45 #include "src/tracing/tracing-category-observer.h" 46 #include "src/v8.h" 47 #include "src/version.h" 48 #include "src/vm-state-inl.h" 49 #include "src/wasm/wasm-module.h" 50 #include "src/zone/accounting-allocator.h" 51 52 namespace v8 { 53 namespace internal { 54 55 base::Atomic32 ThreadId::highest_thread_id_ = 0; 56 57 int ThreadId::AllocateThreadId() { 58 int new_id = base::NoBarrier_AtomicIncrement(&highest_thread_id_, 1); 59 return new_id; 60 } 61 62 63 int ThreadId::GetCurrentThreadId() { 64 int thread_id = base::Thread::GetThreadLocalInt(Isolate::thread_id_key_); 65 if (thread_id == 0) { 66 thread_id = AllocateThreadId(); 67 base::Thread::SetThreadLocalInt(Isolate::thread_id_key_, thread_id); 68 } 69 return thread_id; 70 } 71 72 73 ThreadLocalTop::ThreadLocalTop() { 74 InitializeInternal(); 75 } 76 77 78 void ThreadLocalTop::InitializeInternal() { 79 c_entry_fp_ = 0; 80 c_function_ = 0; 81 handler_ = 0; 82 #ifdef USE_SIMULATOR 83 simulator_ = NULL; 84 #endif 85 js_entry_sp_ = NULL; 86 external_callback_scope_ = NULL; 87 current_vm_state_ = EXTERNAL; 88 try_catch_handler_ = NULL; 89 context_ = NULL; 90 thread_id_ = ThreadId::Invalid(); 91 external_caught_exception_ = false; 92 failed_access_check_callback_ = NULL; 93 save_context_ = NULL; 94 promise_on_stack_ = NULL; 95 96 // These members are re-initialized later after deserialization 97 // is complete. 98 pending_exception_ = NULL; 99 rethrowing_message_ = false; 100 pending_message_obj_ = NULL; 101 scheduled_exception_ = NULL; 102 } 103 104 105 void ThreadLocalTop::Initialize() { 106 InitializeInternal(); 107 #ifdef USE_SIMULATOR 108 simulator_ = Simulator::current(isolate_); 109 #endif 110 thread_id_ = ThreadId::Current(); 111 } 112 113 114 void ThreadLocalTop::Free() { 115 // Match unmatched PopPromise calls. 116 while (promise_on_stack_) isolate_->PopPromise(); 117 } 118 119 120 base::Thread::LocalStorageKey Isolate::isolate_key_; 121 base::Thread::LocalStorageKey Isolate::thread_id_key_; 122 base::Thread::LocalStorageKey Isolate::per_isolate_thread_data_key_; 123 base::LazyMutex Isolate::thread_data_table_mutex_ = LAZY_MUTEX_INITIALIZER; 124 Isolate::ThreadDataTable* Isolate::thread_data_table_ = NULL; 125 base::Atomic32 Isolate::isolate_counter_ = 0; 126 #if DEBUG 127 base::Atomic32 Isolate::isolate_key_created_ = 0; 128 #endif 129 130 Isolate::PerIsolateThreadData* 131 Isolate::FindOrAllocatePerThreadDataForThisThread() { 132 ThreadId thread_id = ThreadId::Current(); 133 PerIsolateThreadData* per_thread = NULL; 134 { 135 base::LockGuard<base::Mutex> lock_guard(thread_data_table_mutex_.Pointer()); 136 per_thread = thread_data_table_->Lookup(this, thread_id); 137 if (per_thread == NULL) { 138 per_thread = new PerIsolateThreadData(this, thread_id); 139 thread_data_table_->Insert(per_thread); 140 } 141 DCHECK(thread_data_table_->Lookup(this, thread_id) == per_thread); 142 } 143 return per_thread; 144 } 145 146 147 void Isolate::DiscardPerThreadDataForThisThread() { 148 int thread_id_int = base::Thread::GetThreadLocalInt(Isolate::thread_id_key_); 149 if (thread_id_int) { 150 ThreadId thread_id = ThreadId(thread_id_int); 151 DCHECK(!thread_manager_->mutex_owner_.Equals(thread_id)); 152 base::LockGuard<base::Mutex> lock_guard(thread_data_table_mutex_.Pointer()); 153 PerIsolateThreadData* per_thread = 154 thread_data_table_->Lookup(this, thread_id); 155 if (per_thread) { 156 DCHECK(!per_thread->thread_state_); 157 thread_data_table_->Remove(per_thread); 158 } 159 } 160 } 161 162 163 Isolate::PerIsolateThreadData* Isolate::FindPerThreadDataForThisThread() { 164 ThreadId thread_id = ThreadId::Current(); 165 return FindPerThreadDataForThread(thread_id); 166 } 167 168 169 Isolate::PerIsolateThreadData* Isolate::FindPerThreadDataForThread( 170 ThreadId thread_id) { 171 PerIsolateThreadData* per_thread = NULL; 172 { 173 base::LockGuard<base::Mutex> lock_guard(thread_data_table_mutex_.Pointer()); 174 per_thread = thread_data_table_->Lookup(this, thread_id); 175 } 176 return per_thread; 177 } 178 179 180 void Isolate::InitializeOncePerProcess() { 181 base::LockGuard<base::Mutex> lock_guard(thread_data_table_mutex_.Pointer()); 182 CHECK(thread_data_table_ == NULL); 183 isolate_key_ = base::Thread::CreateThreadLocalKey(); 184 #if DEBUG 185 base::NoBarrier_Store(&isolate_key_created_, 1); 186 #endif 187 thread_id_key_ = base::Thread::CreateThreadLocalKey(); 188 per_isolate_thread_data_key_ = base::Thread::CreateThreadLocalKey(); 189 thread_data_table_ = new Isolate::ThreadDataTable(); 190 } 191 192 193 Address Isolate::get_address_from_id(Isolate::AddressId id) { 194 return isolate_addresses_[id]; 195 } 196 197 198 char* Isolate::Iterate(ObjectVisitor* v, char* thread_storage) { 199 ThreadLocalTop* thread = reinterpret_cast<ThreadLocalTop*>(thread_storage); 200 Iterate(v, thread); 201 return thread_storage + sizeof(ThreadLocalTop); 202 } 203 204 205 void Isolate::IterateThread(ThreadVisitor* v, char* t) { 206 ThreadLocalTop* thread = reinterpret_cast<ThreadLocalTop*>(t); 207 v->VisitThread(this, thread); 208 } 209 210 211 void Isolate::Iterate(ObjectVisitor* v, ThreadLocalTop* thread) { 212 // Visit the roots from the top for a given thread. 213 v->VisitPointer(&thread->pending_exception_); 214 v->VisitPointer(&(thread->pending_message_obj_)); 215 v->VisitPointer(bit_cast<Object**>(&(thread->context_))); 216 v->VisitPointer(&thread->scheduled_exception_); 217 218 for (v8::TryCatch* block = thread->try_catch_handler(); 219 block != NULL; 220 block = block->next_) { 221 v->VisitPointer(bit_cast<Object**>(&(block->exception_))); 222 v->VisitPointer(bit_cast<Object**>(&(block->message_obj_))); 223 } 224 225 // Iterate over pointers on native execution stack. 226 for (StackFrameIterator it(this, thread); !it.done(); it.Advance()) { 227 it.frame()->Iterate(v); 228 } 229 } 230 231 232 void Isolate::Iterate(ObjectVisitor* v) { 233 ThreadLocalTop* current_t = thread_local_top(); 234 Iterate(v, current_t); 235 } 236 237 238 void Isolate::IterateDeferredHandles(ObjectVisitor* visitor) { 239 for (DeferredHandles* deferred = deferred_handles_head_; 240 deferred != NULL; 241 deferred = deferred->next_) { 242 deferred->Iterate(visitor); 243 } 244 } 245 246 247 #ifdef DEBUG 248 bool Isolate::IsDeferredHandle(Object** handle) { 249 // Each DeferredHandles instance keeps the handles to one job in the 250 // concurrent recompilation queue, containing a list of blocks. Each block 251 // contains kHandleBlockSize handles except for the first block, which may 252 // not be fully filled. 253 // We iterate through all the blocks to see whether the argument handle 254 // belongs to one of the blocks. If so, it is deferred. 255 for (DeferredHandles* deferred = deferred_handles_head_; 256 deferred != NULL; 257 deferred = deferred->next_) { 258 List<Object**>* blocks = &deferred->blocks_; 259 for (int i = 0; i < blocks->length(); i++) { 260 Object** block_limit = (i == 0) ? deferred->first_block_limit_ 261 : blocks->at(i) + kHandleBlockSize; 262 if (blocks->at(i) <= handle && handle < block_limit) return true; 263 } 264 } 265 return false; 266 } 267 #endif // DEBUG 268 269 270 void Isolate::RegisterTryCatchHandler(v8::TryCatch* that) { 271 thread_local_top()->set_try_catch_handler(that); 272 } 273 274 275 void Isolate::UnregisterTryCatchHandler(v8::TryCatch* that) { 276 DCHECK(thread_local_top()->try_catch_handler() == that); 277 thread_local_top()->set_try_catch_handler(that->next_); 278 } 279 280 281 Handle<String> Isolate::StackTraceString() { 282 if (stack_trace_nesting_level_ == 0) { 283 stack_trace_nesting_level_++; 284 HeapStringAllocator allocator; 285 StringStream::ClearMentionedObjectCache(this); 286 StringStream accumulator(&allocator); 287 incomplete_message_ = &accumulator; 288 PrintStack(&accumulator); 289 Handle<String> stack_trace = accumulator.ToString(this); 290 incomplete_message_ = NULL; 291 stack_trace_nesting_level_ = 0; 292 return stack_trace; 293 } else if (stack_trace_nesting_level_ == 1) { 294 stack_trace_nesting_level_++; 295 base::OS::PrintError( 296 "\n\nAttempt to print stack while printing stack (double fault)\n"); 297 base::OS::PrintError( 298 "If you are lucky you may find a partial stack dump on stdout.\n\n"); 299 incomplete_message_->OutputToStdOut(); 300 return factory()->empty_string(); 301 } else { 302 base::OS::Abort(); 303 // Unreachable 304 return factory()->empty_string(); 305 } 306 } 307 308 309 void Isolate::PushStackTraceAndDie(unsigned int magic, void* ptr1, void* ptr2, 310 unsigned int magic2) { 311 const int kMaxStackTraceSize = 32 * KB; 312 Handle<String> trace = StackTraceString(); 313 uint8_t buffer[kMaxStackTraceSize]; 314 int length = Min(kMaxStackTraceSize - 1, trace->length()); 315 String::WriteToFlat(*trace, buffer, 0, length); 316 buffer[length] = '\0'; 317 // TODO(dcarney): convert buffer to utf8? 318 base::OS::PrintError("Stacktrace (%x-%x) %p %p: %s\n", magic, magic2, ptr1, 319 ptr2, reinterpret_cast<char*>(buffer)); 320 base::OS::Abort(); 321 } 322 323 namespace { 324 325 class StackTraceHelper { 326 public: 327 StackTraceHelper(Isolate* isolate, FrameSkipMode mode, Handle<Object> caller) 328 : isolate_(isolate), 329 mode_(mode), 330 caller_(caller), 331 skip_next_frame_(true) { 332 switch (mode_) { 333 case SKIP_FIRST: 334 skip_next_frame_ = true; 335 break; 336 case SKIP_UNTIL_SEEN: 337 DCHECK(caller_->IsJSFunction()); 338 skip_next_frame_ = true; 339 break; 340 case SKIP_NONE: 341 skip_next_frame_ = false; 342 break; 343 } 344 encountered_strict_function_ = false; 345 } 346 347 // Poison stack frames below the first strict mode frame. 348 // The stack trace API should not expose receivers and function 349 // objects on frames deeper than the top-most one with a strict mode 350 // function. 351 bool IsStrictFrame(JSFunction* fun) { 352 if (!encountered_strict_function_) { 353 encountered_strict_function_ = is_strict(fun->shared()->language_mode()); 354 } 355 return encountered_strict_function_; 356 } 357 358 // Determines whether the given stack frame should be displayed in a stack 359 // trace. 360 bool IsVisibleInStackTrace(JSFunction* fun) { 361 return ShouldIncludeFrame(fun) && IsNotInNativeScript(fun) && 362 IsInSameSecurityContext(fun); 363 } 364 365 private: 366 // This mechanism excludes a number of uninteresting frames from the stack 367 // trace. This can be be the first frame (which will be a builtin-exit frame 368 // for the error constructor builtin) or every frame until encountering a 369 // user-specified function. 370 bool ShouldIncludeFrame(JSFunction* fun) { 371 switch (mode_) { 372 case SKIP_NONE: 373 return true; 374 case SKIP_FIRST: 375 if (!skip_next_frame_) return true; 376 skip_next_frame_ = false; 377 return false; 378 case SKIP_UNTIL_SEEN: 379 if (skip_next_frame_ && (fun == *caller_)) { 380 skip_next_frame_ = false; 381 return false; 382 } 383 return !skip_next_frame_; 384 } 385 UNREACHABLE(); 386 return false; 387 } 388 389 bool IsNotInNativeScript(JSFunction* fun) { 390 // Functions defined in native scripts are not visible unless directly 391 // exposed, in which case the native flag is set. 392 // The --builtins-in-stack-traces command line flag allows including 393 // internal call sites in the stack trace for debugging purposes. 394 if (!FLAG_builtins_in_stack_traces && fun->shared()->IsBuiltin()) { 395 return fun->shared()->native(); 396 } 397 return true; 398 } 399 400 bool IsInSameSecurityContext(JSFunction* fun) { 401 return isolate_->context()->HasSameSecurityTokenAs(fun->context()); 402 } 403 404 Isolate* isolate_; 405 406 const FrameSkipMode mode_; 407 const Handle<Object> caller_; 408 bool skip_next_frame_; 409 410 bool encountered_strict_function_; 411 }; 412 413 // TODO(jgruber): Fix all cases in which frames give us a hole value (e.g. the 414 // receiver in RegExp constructor frames. 415 Handle<Object> TheHoleToUndefined(Isolate* isolate, Handle<Object> in) { 416 return (in->IsTheHole(isolate)) 417 ? Handle<Object>::cast(isolate->factory()->undefined_value()) 418 : in; 419 } 420 421 bool GetStackTraceLimit(Isolate* isolate, int* result) { 422 Handle<JSObject> error = isolate->error_function(); 423 424 Handle<String> key = isolate->factory()->stackTraceLimit_string(); 425 Handle<Object> stack_trace_limit = JSReceiver::GetDataProperty(error, key); 426 if (!stack_trace_limit->IsNumber()) return false; 427 428 // Ensure that limit is not negative. 429 *result = Max(FastD2IChecked(stack_trace_limit->Number()), 0); 430 return true; 431 } 432 433 } // namespace 434 435 Handle<Object> Isolate::CaptureSimpleStackTrace(Handle<JSReceiver> error_object, 436 FrameSkipMode mode, 437 Handle<Object> caller) { 438 DisallowJavascriptExecution no_js(this); 439 440 int limit; 441 if (!GetStackTraceLimit(this, &limit)) return factory()->undefined_value(); 442 443 const int initial_size = Min(limit, 10); 444 Handle<FrameArray> elements = factory()->NewFrameArray(initial_size); 445 446 StackTraceHelper helper(this, mode, caller); 447 448 for (StackFrameIterator iter(this); 449 !iter.done() && elements->FrameCount() < limit; iter.Advance()) { 450 StackFrame* frame = iter.frame(); 451 452 switch (frame->type()) { 453 case StackFrame::JAVA_SCRIPT: 454 case StackFrame::OPTIMIZED: 455 case StackFrame::INTERPRETED: 456 case StackFrame::BUILTIN: { 457 JavaScriptFrame* js_frame = JavaScriptFrame::cast(frame); 458 // Set initial size to the maximum inlining level + 1 for the outermost 459 // function. 460 List<FrameSummary> frames(FLAG_max_inlining_levels + 1); 461 js_frame->Summarize(&frames); 462 for (int i = frames.length() - 1; i >= 0; i--) { 463 Handle<JSFunction> fun = frames[i].function(); 464 465 // Filter out internal frames that we do not want to show. 466 if (!helper.IsVisibleInStackTrace(*fun)) continue; 467 468 Handle<Object> recv = frames[i].receiver(); 469 Handle<AbstractCode> abstract_code = frames[i].abstract_code(); 470 const int offset = frames[i].code_offset(); 471 472 bool force_constructor = false; 473 if (frame->type() == StackFrame::BUILTIN) { 474 // Help CallSite::IsConstructor correctly detect hand-written 475 // construct stubs. 476 if (Code::cast(*abstract_code)->is_construct_stub()) { 477 force_constructor = true; 478 } 479 } 480 481 int flags = 0; 482 if (helper.IsStrictFrame(*fun)) flags |= FrameArray::kIsStrict; 483 if (force_constructor) flags |= FrameArray::kForceConstructor; 484 485 elements = FrameArray::AppendJSFrame( 486 elements, TheHoleToUndefined(this, recv), fun, abstract_code, 487 offset, flags); 488 } 489 } break; 490 491 case StackFrame::BUILTIN_EXIT: { 492 BuiltinExitFrame* exit_frame = BuiltinExitFrame::cast(frame); 493 Handle<JSFunction> fun = handle(exit_frame->function(), this); 494 495 // Filter out internal frames that we do not want to show. 496 if (!helper.IsVisibleInStackTrace(*fun)) continue; 497 498 Handle<Object> recv(exit_frame->receiver(), this); 499 Handle<Code> code(exit_frame->LookupCode(), this); 500 const int offset = 501 static_cast<int>(exit_frame->pc() - code->instruction_start()); 502 503 int flags = 0; 504 if (helper.IsStrictFrame(*fun)) flags |= FrameArray::kIsStrict; 505 if (exit_frame->IsConstructor()) flags |= FrameArray::kForceConstructor; 506 507 elements = FrameArray::AppendJSFrame(elements, recv, fun, 508 Handle<AbstractCode>::cast(code), 509 offset, flags); 510 } break; 511 512 case StackFrame::WASM: { 513 WasmFrame* wasm_frame = WasmFrame::cast(frame); 514 Handle<Object> instance(wasm_frame->wasm_instance(), this); 515 const int wasm_function_index = wasm_frame->function_index(); 516 Code* code = wasm_frame->unchecked_code(); 517 Handle<AbstractCode> abstract_code(AbstractCode::cast(code), this); 518 const int offset = 519 static_cast<int>(wasm_frame->pc() - code->instruction_start()); 520 521 // TODO(wasm): The wasm object returned by the WasmFrame should always 522 // be a wasm object. 523 DCHECK(wasm::IsWasmInstance(*instance) || instance->IsUndefined(this)); 524 525 int flags = wasm::WasmIsAsmJs(*instance, this) 526 ? FrameArray::kIsAsmJsWasmFrame 527 : FrameArray::kIsWasmFrame; 528 529 elements = 530 FrameArray::AppendWasmFrame(elements, instance, wasm_function_index, 531 abstract_code, offset, flags); 532 } break; 533 534 default: 535 break; 536 } 537 } 538 539 elements->ShrinkToFit(); 540 541 // TODO(yangguo): Queue this structured stack trace for preprocessing on GC. 542 return factory()->NewJSArrayWithElements(elements); 543 } 544 545 MaybeHandle<JSReceiver> Isolate::CaptureAndSetDetailedStackTrace( 546 Handle<JSReceiver> error_object) { 547 if (capture_stack_trace_for_uncaught_exceptions_) { 548 // Capture stack trace for a detailed exception message. 549 Handle<Name> key = factory()->detailed_stack_trace_symbol(); 550 Handle<JSArray> stack_trace = CaptureCurrentStackTrace( 551 stack_trace_for_uncaught_exceptions_frame_limit_, 552 stack_trace_for_uncaught_exceptions_options_); 553 RETURN_ON_EXCEPTION( 554 this, JSReceiver::SetProperty(error_object, key, stack_trace, STRICT), 555 JSReceiver); 556 } 557 return error_object; 558 } 559 560 MaybeHandle<JSReceiver> Isolate::CaptureAndSetSimpleStackTrace( 561 Handle<JSReceiver> error_object, FrameSkipMode mode, 562 Handle<Object> caller) { 563 // Capture stack trace for simple stack trace string formatting. 564 Handle<Name> key = factory()->stack_trace_symbol(); 565 Handle<Object> stack_trace = 566 CaptureSimpleStackTrace(error_object, mode, caller); 567 RETURN_ON_EXCEPTION( 568 this, JSReceiver::SetProperty(error_object, key, stack_trace, STRICT), 569 JSReceiver); 570 return error_object; 571 } 572 573 574 Handle<JSArray> Isolate::GetDetailedStackTrace(Handle<JSObject> error_object) { 575 Handle<Name> key_detailed = factory()->detailed_stack_trace_symbol(); 576 Handle<Object> stack_trace = 577 JSReceiver::GetDataProperty(error_object, key_detailed); 578 if (stack_trace->IsJSArray()) return Handle<JSArray>::cast(stack_trace); 579 return Handle<JSArray>(); 580 } 581 582 583 class CaptureStackTraceHelper { 584 public: 585 CaptureStackTraceHelper(Isolate* isolate, 586 StackTrace::StackTraceOptions options) 587 : isolate_(isolate) { 588 if (options & StackTrace::kColumnOffset) { 589 column_key_ = 590 factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("column")); 591 } 592 if (options & StackTrace::kLineNumber) { 593 line_key_ = 594 factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("lineNumber")); 595 } 596 if (options & StackTrace::kScriptId) { 597 script_id_key_ = 598 factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("scriptId")); 599 } 600 if (options & StackTrace::kScriptName) { 601 script_name_key_ = 602 factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("scriptName")); 603 } 604 if (options & StackTrace::kScriptNameOrSourceURL) { 605 script_name_or_source_url_key_ = factory()->InternalizeOneByteString( 606 STATIC_CHAR_VECTOR("scriptNameOrSourceURL")); 607 } 608 if (options & StackTrace::kFunctionName) { 609 function_key_ = factory()->InternalizeOneByteString( 610 STATIC_CHAR_VECTOR("functionName")); 611 } 612 if (options & StackTrace::kIsEval) { 613 eval_key_ = 614 factory()->InternalizeOneByteString(STATIC_CHAR_VECTOR("isEval")); 615 } 616 if (options & StackTrace::kIsConstructor) { 617 constructor_key_ = factory()->InternalizeOneByteString( 618 STATIC_CHAR_VECTOR("isConstructor")); 619 } 620 } 621 622 Handle<JSObject> NewStackFrameObject(FrameSummary& summ) { 623 int position = summ.abstract_code()->SourcePosition(summ.code_offset()); 624 return NewStackFrameObject(summ.function(), position, 625 summ.is_constructor()); 626 } 627 628 Handle<JSObject> NewStackFrameObject(Handle<JSFunction> fun, int position, 629 bool is_constructor) { 630 Handle<JSObject> stack_frame = 631 factory()->NewJSObject(isolate_->object_function()); 632 Handle<Script> script(Script::cast(fun->shared()->script()), isolate_); 633 634 if (!line_key_.is_null()) { 635 Script::PositionInfo info; 636 bool valid_pos = 637 Script::GetPositionInfo(script, position, &info, Script::WITH_OFFSET); 638 639 if (!column_key_.is_null() && valid_pos) { 640 JSObject::AddProperty(stack_frame, column_key_, 641 handle(Smi::FromInt(info.column + 1), isolate_), 642 NONE); 643 } 644 JSObject::AddProperty(stack_frame, line_key_, 645 handle(Smi::FromInt(info.line + 1), isolate_), 646 NONE); 647 } 648 649 if (!script_id_key_.is_null()) { 650 JSObject::AddProperty(stack_frame, script_id_key_, 651 handle(Smi::FromInt(script->id()), isolate_), NONE); 652 } 653 654 if (!script_name_key_.is_null()) { 655 JSObject::AddProperty(stack_frame, script_name_key_, 656 handle(script->name(), isolate_), NONE); 657 } 658 659 if (!script_name_or_source_url_key_.is_null()) { 660 Handle<Object> result = Script::GetNameOrSourceURL(script); 661 JSObject::AddProperty(stack_frame, script_name_or_source_url_key_, result, 662 NONE); 663 } 664 665 if (!eval_key_.is_null()) { 666 Handle<Object> is_eval = factory()->ToBoolean( 667 script->compilation_type() == Script::COMPILATION_TYPE_EVAL); 668 JSObject::AddProperty(stack_frame, eval_key_, is_eval, NONE); 669 } 670 671 if (!function_key_.is_null()) { 672 Handle<Object> fun_name = JSFunction::GetDebugName(fun); 673 JSObject::AddProperty(stack_frame, function_key_, fun_name, NONE); 674 } 675 676 if (!constructor_key_.is_null()) { 677 Handle<Object> is_constructor_obj = factory()->ToBoolean(is_constructor); 678 JSObject::AddProperty(stack_frame, constructor_key_, is_constructor_obj, 679 NONE); 680 } 681 return stack_frame; 682 } 683 684 Handle<JSObject> NewStackFrameObject(BuiltinExitFrame* frame) { 685 Handle<JSObject> stack_frame = 686 factory()->NewJSObject(isolate_->object_function()); 687 Handle<JSFunction> fun = handle(frame->function(), isolate_); 688 if (!function_key_.is_null()) { 689 Handle<Object> fun_name = JSFunction::GetDebugName(fun); 690 JSObject::AddProperty(stack_frame, function_key_, fun_name, NONE); 691 } 692 693 // We don't have a script and hence cannot set line and col positions. 694 DCHECK(!fun->shared()->script()->IsScript()); 695 696 return stack_frame; 697 } 698 699 Handle<JSObject> NewStackFrameObject(WasmFrame* frame) { 700 Handle<JSObject> stack_frame = 701 factory()->NewJSObject(isolate_->object_function()); 702 703 if (!function_key_.is_null()) { 704 Handle<String> name = wasm::GetWasmFunctionName( 705 isolate_, handle(frame->wasm_instance(), isolate_), 706 frame->function_index()); 707 JSObject::AddProperty(stack_frame, function_key_, name, NONE); 708 } 709 // Encode the function index as line number (1-based). 710 if (!line_key_.is_null()) { 711 JSObject::AddProperty( 712 stack_frame, line_key_, 713 isolate_->factory()->NewNumberFromInt(frame->function_index() + 1), 714 NONE); 715 } 716 // Encode the byte offset as column (1-based). 717 if (!column_key_.is_null()) { 718 Code* code = frame->LookupCode(); 719 int offset = static_cast<int>(frame->pc() - code->instruction_start()); 720 int position = AbstractCode::cast(code)->SourcePosition(offset); 721 // Make position 1-based. 722 if (position >= 0) ++position; 723 JSObject::AddProperty(stack_frame, column_key_, 724 isolate_->factory()->NewNumberFromInt(position), 725 NONE); 726 } 727 if (!script_id_key_.is_null()) { 728 int script_id = frame->script()->id(); 729 JSObject::AddProperty(stack_frame, script_id_key_, 730 handle(Smi::FromInt(script_id), isolate_), NONE); 731 } 732 733 return stack_frame; 734 } 735 736 private: 737 inline Factory* factory() { return isolate_->factory(); } 738 739 Isolate* isolate_; 740 Handle<String> column_key_; 741 Handle<String> line_key_; 742 Handle<String> script_id_key_; 743 Handle<String> script_name_key_; 744 Handle<String> script_name_or_source_url_key_; 745 Handle<String> function_key_; 746 Handle<String> eval_key_; 747 Handle<String> constructor_key_; 748 }; 749 750 Handle<JSArray> Isolate::CaptureCurrentStackTrace( 751 int frame_limit, StackTrace::StackTraceOptions options) { 752 DisallowJavascriptExecution no_js(this); 753 CaptureStackTraceHelper helper(this, options); 754 755 // Ensure no negative values. 756 int limit = Max(frame_limit, 0); 757 Handle<JSArray> stack_trace = factory()->NewJSArray(frame_limit); 758 Handle<FixedArray> stack_trace_elems( 759 FixedArray::cast(stack_trace->elements()), this); 760 761 int frames_seen = 0; 762 for (StackTraceFrameIterator it(this); !it.done() && (frames_seen < limit); 763 it.Advance()) { 764 StandardFrame* frame = it.frame(); 765 if (frame->is_java_script()) { 766 // Set initial size to the maximum inlining level + 1 for the outermost 767 // function. 768 List<FrameSummary> frames(FLAG_max_inlining_levels + 1); 769 JavaScriptFrame::cast(frame)->Summarize(&frames); 770 for (int i = frames.length() - 1; i >= 0 && frames_seen < limit; i--) { 771 Handle<JSFunction> fun = frames[i].function(); 772 // Filter frames from other security contexts. 773 if (!(options & StackTrace::kExposeFramesAcrossSecurityOrigins) && 774 !this->context()->HasSameSecurityTokenAs(fun->context())) 775 continue; 776 Handle<JSObject> new_frame_obj = helper.NewStackFrameObject(frames[i]); 777 stack_trace_elems->set(frames_seen, *new_frame_obj); 778 frames_seen++; 779 } 780 } else { 781 DCHECK(frame->is_wasm()); 782 WasmFrame* wasm_frame = WasmFrame::cast(frame); 783 Handle<JSObject> new_frame_obj = helper.NewStackFrameObject(wasm_frame); 784 stack_trace_elems->set(frames_seen, *new_frame_obj); 785 frames_seen++; 786 } 787 } 788 789 stack_trace->set_length(Smi::FromInt(frames_seen)); 790 return stack_trace; 791 } 792 793 794 void Isolate::PrintStack(FILE* out, PrintStackMode mode) { 795 if (stack_trace_nesting_level_ == 0) { 796 stack_trace_nesting_level_++; 797 StringStream::ClearMentionedObjectCache(this); 798 HeapStringAllocator allocator; 799 StringStream accumulator(&allocator); 800 incomplete_message_ = &accumulator; 801 PrintStack(&accumulator, mode); 802 accumulator.OutputToFile(out); 803 InitializeLoggingAndCounters(); 804 accumulator.Log(this); 805 incomplete_message_ = NULL; 806 stack_trace_nesting_level_ = 0; 807 } else if (stack_trace_nesting_level_ == 1) { 808 stack_trace_nesting_level_++; 809 base::OS::PrintError( 810 "\n\nAttempt to print stack while printing stack (double fault)\n"); 811 base::OS::PrintError( 812 "If you are lucky you may find a partial stack dump on stdout.\n\n"); 813 incomplete_message_->OutputToFile(out); 814 } 815 } 816 817 818 static void PrintFrames(Isolate* isolate, 819 StringStream* accumulator, 820 StackFrame::PrintMode mode) { 821 StackFrameIterator it(isolate); 822 for (int i = 0; !it.done(); it.Advance()) { 823 it.frame()->Print(accumulator, mode, i++); 824 } 825 } 826 827 828 void Isolate::PrintStack(StringStream* accumulator, PrintStackMode mode) { 829 // The MentionedObjectCache is not GC-proof at the moment. 830 DisallowHeapAllocation no_gc; 831 HandleScope scope(this); 832 DCHECK(accumulator->IsMentionedObjectCacheClear(this)); 833 834 // Avoid printing anything if there are no frames. 835 if (c_entry_fp(thread_local_top()) == 0) return; 836 837 accumulator->Add( 838 "\n==== JS stack trace =========================================\n\n"); 839 PrintFrames(this, accumulator, StackFrame::OVERVIEW); 840 if (mode == kPrintStackVerbose) { 841 accumulator->Add( 842 "\n==== Details ================================================\n\n"); 843 PrintFrames(this, accumulator, StackFrame::DETAILS); 844 accumulator->PrintMentionedObjectCache(this); 845 } 846 accumulator->Add("=====================\n\n"); 847 } 848 849 850 void Isolate::SetFailedAccessCheckCallback( 851 v8::FailedAccessCheckCallback callback) { 852 thread_local_top()->failed_access_check_callback_ = callback; 853 } 854 855 856 void Isolate::ReportFailedAccessCheck(Handle<JSObject> receiver) { 857 if (!thread_local_top()->failed_access_check_callback_) { 858 return ScheduleThrow(*factory()->NewTypeError(MessageTemplate::kNoAccess)); 859 } 860 861 DCHECK(receiver->IsAccessCheckNeeded()); 862 DCHECK(context()); 863 864 // Get the data object from access check info. 865 HandleScope scope(this); 866 Handle<Object> data; 867 { DisallowHeapAllocation no_gc; 868 AccessCheckInfo* access_check_info = AccessCheckInfo::Get(this, receiver); 869 if (!access_check_info) { 870 AllowHeapAllocation doesnt_matter_anymore; 871 return ScheduleThrow( 872 *factory()->NewTypeError(MessageTemplate::kNoAccess)); 873 } 874 data = handle(access_check_info->data(), this); 875 } 876 877 // Leaving JavaScript. 878 VMState<EXTERNAL> state(this); 879 thread_local_top()->failed_access_check_callback_( 880 v8::Utils::ToLocal(receiver), v8::ACCESS_HAS, v8::Utils::ToLocal(data)); 881 } 882 883 884 bool Isolate::MayAccess(Handle<Context> accessing_context, 885 Handle<JSObject> receiver) { 886 DCHECK(receiver->IsJSGlobalProxy() || receiver->IsAccessCheckNeeded()); 887 888 // Check for compatibility between the security tokens in the 889 // current lexical context and the accessed object. 890 891 // During bootstrapping, callback functions are not enabled yet. 892 if (bootstrapper()->IsActive()) return true; 893 { 894 DisallowHeapAllocation no_gc; 895 896 if (receiver->IsJSGlobalProxy()) { 897 Object* receiver_context = 898 JSGlobalProxy::cast(*receiver)->native_context(); 899 if (!receiver_context->IsContext()) return false; 900 901 // Get the native context of current top context. 902 // avoid using Isolate::native_context() because it uses Handle. 903 Context* native_context = 904 accessing_context->global_object()->native_context(); 905 if (receiver_context == native_context) return true; 906 907 if (Context::cast(receiver_context)->security_token() == 908 native_context->security_token()) 909 return true; 910 } 911 } 912 913 HandleScope scope(this); 914 Handle<Object> data; 915 v8::AccessCheckCallback callback = nullptr; 916 { DisallowHeapAllocation no_gc; 917 AccessCheckInfo* access_check_info = AccessCheckInfo::Get(this, receiver); 918 if (!access_check_info) return false; 919 Object* fun_obj = access_check_info->callback(); 920 callback = v8::ToCData<v8::AccessCheckCallback>(fun_obj); 921 data = handle(access_check_info->data(), this); 922 } 923 924 LOG(this, ApiSecurityCheck()); 925 926 { 927 // Leaving JavaScript. 928 VMState<EXTERNAL> state(this); 929 return callback(v8::Utils::ToLocal(accessing_context), 930 v8::Utils::ToLocal(receiver), v8::Utils::ToLocal(data)); 931 } 932 } 933 934 935 Object* Isolate::StackOverflow() { 936 if (FLAG_abort_on_stack_overflow) { 937 FATAL("Aborting on stack overflow"); 938 } 939 940 DisallowJavascriptExecution no_js(this); 941 HandleScope scope(this); 942 943 Handle<JSFunction> fun = range_error_function(); 944 Handle<Object> msg = factory()->NewStringFromAsciiChecked( 945 MessageTemplate::TemplateString(MessageTemplate::kStackOverflow)); 946 Handle<Object> no_caller; 947 Handle<Object> exception; 948 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 949 this, exception, 950 ErrorUtils::Construct(this, fun, fun, msg, SKIP_NONE, no_caller, true)); 951 952 Throw(*exception, nullptr); 953 954 #ifdef VERIFY_HEAP 955 if (FLAG_verify_heap && FLAG_stress_compaction) { 956 heap()->CollectAllGarbage(Heap::kNoGCFlags, 957 GarbageCollectionReason::kTesting); 958 } 959 #endif // VERIFY_HEAP 960 961 return heap()->exception(); 962 } 963 964 965 Object* Isolate::TerminateExecution() { 966 return Throw(heap_.termination_exception(), nullptr); 967 } 968 969 970 void Isolate::CancelTerminateExecution() { 971 if (try_catch_handler()) { 972 try_catch_handler()->has_terminated_ = false; 973 } 974 if (has_pending_exception() && 975 pending_exception() == heap_.termination_exception()) { 976 thread_local_top()->external_caught_exception_ = false; 977 clear_pending_exception(); 978 } 979 if (has_scheduled_exception() && 980 scheduled_exception() == heap_.termination_exception()) { 981 thread_local_top()->external_caught_exception_ = false; 982 clear_scheduled_exception(); 983 } 984 } 985 986 987 void Isolate::RequestInterrupt(InterruptCallback callback, void* data) { 988 ExecutionAccess access(this); 989 api_interrupts_queue_.push(InterruptEntry(callback, data)); 990 stack_guard()->RequestApiInterrupt(); 991 } 992 993 994 void Isolate::InvokeApiInterruptCallbacks() { 995 RuntimeCallTimerScope runtimeTimer( 996 this, &RuntimeCallStats::InvokeApiInterruptCallbacks); 997 // Note: callback below should be called outside of execution access lock. 998 while (true) { 999 InterruptEntry entry; 1000 { 1001 ExecutionAccess access(this); 1002 if (api_interrupts_queue_.empty()) return; 1003 entry = api_interrupts_queue_.front(); 1004 api_interrupts_queue_.pop(); 1005 } 1006 VMState<EXTERNAL> state(this); 1007 HandleScope handle_scope(this); 1008 entry.first(reinterpret_cast<v8::Isolate*>(this), entry.second); 1009 } 1010 } 1011 1012 1013 void ReportBootstrappingException(Handle<Object> exception, 1014 MessageLocation* location) { 1015 base::OS::PrintError("Exception thrown during bootstrapping\n"); 1016 if (location == NULL || location->script().is_null()) return; 1017 // We are bootstrapping and caught an error where the location is set 1018 // and we have a script for the location. 1019 // In this case we could have an extension (or an internal error 1020 // somewhere) and we print out the line number at which the error occured 1021 // to the console for easier debugging. 1022 int line_number = 1023 location->script()->GetLineNumber(location->start_pos()) + 1; 1024 if (exception->IsString() && location->script()->name()->IsString()) { 1025 base::OS::PrintError( 1026 "Extension or internal compilation error: %s in %s at line %d.\n", 1027 String::cast(*exception)->ToCString().get(), 1028 String::cast(location->script()->name())->ToCString().get(), 1029 line_number); 1030 } else if (location->script()->name()->IsString()) { 1031 base::OS::PrintError( 1032 "Extension or internal compilation error in %s at line %d.\n", 1033 String::cast(location->script()->name())->ToCString().get(), 1034 line_number); 1035 } else if (exception->IsString()) { 1036 base::OS::PrintError("Extension or internal compilation error: %s.\n", 1037 String::cast(*exception)->ToCString().get()); 1038 } else { 1039 base::OS::PrintError("Extension or internal compilation error.\n"); 1040 } 1041 #ifdef OBJECT_PRINT 1042 // Since comments and empty lines have been stripped from the source of 1043 // builtins, print the actual source here so that line numbers match. 1044 if (location->script()->source()->IsString()) { 1045 Handle<String> src(String::cast(location->script()->source())); 1046 PrintF("Failing script:"); 1047 int len = src->length(); 1048 if (len == 0) { 1049 PrintF(" <not available>\n"); 1050 } else { 1051 PrintF("\n"); 1052 int line_number = 1; 1053 PrintF("%5d: ", line_number); 1054 for (int i = 0; i < len; i++) { 1055 uint16_t character = src->Get(i); 1056 PrintF("%c", character); 1057 if (character == '\n' && i < len - 2) { 1058 PrintF("%5d: ", ++line_number); 1059 } 1060 } 1061 PrintF("\n"); 1062 } 1063 } 1064 #endif 1065 } 1066 1067 1068 Object* Isolate::Throw(Object* exception, MessageLocation* location) { 1069 DCHECK(!has_pending_exception()); 1070 1071 HandleScope scope(this); 1072 Handle<Object> exception_handle(exception, this); 1073 1074 if (FLAG_print_all_exceptions) { 1075 printf("=========================================================\n"); 1076 printf("Exception thrown:\n"); 1077 if (location) { 1078 Handle<Script> script = location->script(); 1079 Handle<Object> name = Script::GetNameOrSourceURL(script); 1080 printf("at "); 1081 if (name->IsString() && String::cast(*name)->length() > 0) 1082 String::cast(*name)->PrintOn(stdout); 1083 else 1084 printf("<anonymous>"); 1085 // Script::GetLineNumber and Script::GetColumnNumber can allocate on the heap to 1086 // initialize the line_ends array, so be careful when calling them. 1087 #ifdef DEBUG 1088 if (AllowHeapAllocation::IsAllowed()) { 1089 #else 1090 if (false) { 1091 #endif 1092 printf(", %d:%d - %d:%d\n", 1093 Script::GetLineNumber(script, location->start_pos()) + 1, 1094 Script::GetColumnNumber(script, location->start_pos()), 1095 Script::GetLineNumber(script, location->end_pos()) + 1, 1096 Script::GetColumnNumber(script, location->end_pos())); 1097 } else { 1098 printf(", line %d\n", script->GetLineNumber(location->start_pos()) + 1); 1099 } 1100 } 1101 exception->Print(); 1102 printf("Stack Trace:\n"); 1103 PrintStack(stdout); 1104 printf("=========================================================\n"); 1105 } 1106 1107 // Determine whether a message needs to be created for the given exception 1108 // depending on the following criteria: 1109 // 1) External v8::TryCatch missing: Always create a message because any 1110 // JavaScript handler for a finally-block might re-throw to top-level. 1111 // 2) External v8::TryCatch exists: Only create a message if the handler 1112 // captures messages or is verbose (which reports despite the catch). 1113 // 3) ReThrow from v8::TryCatch: The message from a previous throw still 1114 // exists and we preserve it instead of creating a new message. 1115 bool requires_message = try_catch_handler() == nullptr || 1116 try_catch_handler()->is_verbose_ || 1117 try_catch_handler()->capture_message_; 1118 bool rethrowing_message = thread_local_top()->rethrowing_message_; 1119 1120 thread_local_top()->rethrowing_message_ = false; 1121 1122 // Notify debugger of exception. 1123 if (is_catchable_by_javascript(exception)) { 1124 debug()->OnThrow(exception_handle); 1125 } 1126 1127 // Generate the message if required. 1128 if (requires_message && !rethrowing_message) { 1129 MessageLocation computed_location; 1130 // If no location was specified we try to use a computed one instead. 1131 if (location == NULL && ComputeLocation(&computed_location)) { 1132 location = &computed_location; 1133 } 1134 1135 if (bootstrapper()->IsActive()) { 1136 // It's not safe to try to make message objects or collect stack traces 1137 // while the bootstrapper is active since the infrastructure may not have 1138 // been properly initialized. 1139 ReportBootstrappingException(exception_handle, location); 1140 } else { 1141 Handle<Object> message_obj = CreateMessage(exception_handle, location); 1142 thread_local_top()->pending_message_obj_ = *message_obj; 1143 1144 // For any exception not caught by JavaScript, even when an external 1145 // handler is present: 1146 // If the abort-on-uncaught-exception flag is specified, and if the 1147 // embedder didn't specify a custom uncaught exception callback, 1148 // or if the custom callback determined that V8 should abort, then 1149 // abort. 1150 if (FLAG_abort_on_uncaught_exception) { 1151 CatchType prediction = PredictExceptionCatcher(); 1152 if ((prediction == NOT_CAUGHT || prediction == CAUGHT_BY_EXTERNAL) && 1153 (!abort_on_uncaught_exception_callback_ || 1154 abort_on_uncaught_exception_callback_( 1155 reinterpret_cast<v8::Isolate*>(this)))) { 1156 // Prevent endless recursion. 1157 FLAG_abort_on_uncaught_exception = false; 1158 // This flag is intended for use by JavaScript developers, so 1159 // print a user-friendly stack trace (not an internal one). 1160 PrintF(stderr, "%s\n\nFROM\n", 1161 MessageHandler::GetLocalizedMessage(this, message_obj).get()); 1162 PrintCurrentStackTrace(stderr); 1163 base::OS::Abort(); 1164 } 1165 } 1166 } 1167 } 1168 1169 // Set the exception being thrown. 1170 set_pending_exception(*exception_handle); 1171 return heap()->exception(); 1172 } 1173 1174 1175 Object* Isolate::ReThrow(Object* exception) { 1176 DCHECK(!has_pending_exception()); 1177 1178 // Set the exception being re-thrown. 1179 set_pending_exception(exception); 1180 return heap()->exception(); 1181 } 1182 1183 1184 Object* Isolate::UnwindAndFindHandler() { 1185 Object* exception = pending_exception(); 1186 1187 Code* code = nullptr; 1188 Context* context = nullptr; 1189 intptr_t offset = 0; 1190 Address handler_sp = nullptr; 1191 Address handler_fp = nullptr; 1192 1193 // Special handling of termination exceptions, uncatchable by JavaScript and 1194 // Wasm code, we unwind the handlers until the top ENTRY handler is found. 1195 bool catchable_by_js = is_catchable_by_javascript(exception); 1196 1197 // Compute handler and stack unwinding information by performing a full walk 1198 // over the stack and dispatching according to the frame type. 1199 for (StackFrameIterator iter(this); !iter.done(); iter.Advance()) { 1200 StackFrame* frame = iter.frame(); 1201 1202 // For JSEntryStub frames we always have a handler. 1203 if (frame->is_entry() || frame->is_entry_construct()) { 1204 StackHandler* handler = frame->top_handler(); 1205 1206 // Restore the next handler. 1207 thread_local_top()->handler_ = handler->next()->address(); 1208 1209 // Gather information from the handler. 1210 code = frame->LookupCode(); 1211 handler_sp = handler->address() + StackHandlerConstants::kSize; 1212 offset = Smi::cast(code->handler_table()->get(0))->value(); 1213 break; 1214 } 1215 1216 if (FLAG_wasm_eh_prototype) { 1217 if (frame->is_wasm() && is_catchable_by_wasm(exception)) { 1218 int stack_slots = 0; // Will contain stack slot count of frame. 1219 WasmFrame* wasm_frame = static_cast<WasmFrame*>(frame); 1220 offset = wasm_frame->LookupExceptionHandlerInTable(&stack_slots); 1221 if (offset >= 0) { 1222 // Compute the stack pointer from the frame pointer. This ensures that 1223 // argument slots on the stack are dropped as returning would. 1224 Address return_sp = frame->fp() + 1225 StandardFrameConstants::kFixedFrameSizeAboveFp - 1226 stack_slots * kPointerSize; 1227 1228 // Gather information from the frame. 1229 code = frame->LookupCode(); 1230 1231 handler_sp = return_sp; 1232 handler_fp = frame->fp(); 1233 break; 1234 } 1235 } 1236 } 1237 1238 // For optimized frames we perform a lookup in the handler table. 1239 if (frame->is_optimized() && catchable_by_js) { 1240 OptimizedFrame* js_frame = static_cast<OptimizedFrame*>(frame); 1241 int stack_slots = 0; // Will contain stack slot count of frame. 1242 offset = js_frame->LookupExceptionHandlerInTable(&stack_slots, nullptr); 1243 if (offset >= 0) { 1244 // Compute the stack pointer from the frame pointer. This ensures that 1245 // argument slots on the stack are dropped as returning would. 1246 Address return_sp = frame->fp() + 1247 StandardFrameConstants::kFixedFrameSizeAboveFp - 1248 stack_slots * kPointerSize; 1249 1250 // Gather information from the frame. 1251 code = frame->LookupCode(); 1252 1253 // TODO(bmeurer): Turbofanned BUILTIN frames appear as OPTIMIZED, but 1254 // do not have a code kind of OPTIMIZED_FUNCTION. 1255 if (code->kind() == Code::OPTIMIZED_FUNCTION && 1256 code->marked_for_deoptimization()) { 1257 // If the target code is lazy deoptimized, we jump to the original 1258 // return address, but we make a note that we are throwing, so that 1259 // the deoptimizer can do the right thing. 1260 offset = static_cast<int>(frame->pc() - code->entry()); 1261 set_deoptimizer_lazy_throw(true); 1262 } 1263 handler_sp = return_sp; 1264 handler_fp = frame->fp(); 1265 break; 1266 } 1267 } 1268 1269 // For interpreted frame we perform a range lookup in the handler table. 1270 if (frame->is_interpreted() && catchable_by_js) { 1271 InterpretedFrame* js_frame = static_cast<InterpretedFrame*>(frame); 1272 int register_slots = js_frame->GetBytecodeArray()->register_count(); 1273 int context_reg = 0; // Will contain register index holding context. 1274 offset = js_frame->LookupExceptionHandlerInTable(&context_reg, nullptr); 1275 if (offset >= 0) { 1276 // Compute the stack pointer from the frame pointer. This ensures that 1277 // argument slots on the stack are dropped as returning would. 1278 // Note: This is only needed for interpreted frames that have been 1279 // materialized by the deoptimizer. If there is a handler frame 1280 // in between then {frame->sp()} would already be correct. 1281 Address return_sp = frame->fp() - 1282 InterpreterFrameConstants::kFixedFrameSizeFromFp - 1283 register_slots * kPointerSize; 1284 1285 // Patch the bytecode offset in the interpreted frame to reflect the 1286 // position of the exception handler. The special builtin below will 1287 // take care of continuing to dispatch at that position. Also restore 1288 // the correct context for the handler from the interpreter register. 1289 context = Context::cast(js_frame->ReadInterpreterRegister(context_reg)); 1290 js_frame->PatchBytecodeOffset(static_cast<int>(offset)); 1291 offset = 0; 1292 1293 // Gather information from the frame. 1294 code = *builtins()->InterpreterEnterBytecodeDispatch(); 1295 handler_sp = return_sp; 1296 handler_fp = frame->fp(); 1297 break; 1298 } 1299 } 1300 1301 // For JavaScript frames we perform a range lookup in the handler table. 1302 if (frame->is_java_script() && catchable_by_js) { 1303 JavaScriptFrame* js_frame = static_cast<JavaScriptFrame*>(frame); 1304 int stack_depth = 0; // Will contain operand stack depth of handler. 1305 offset = js_frame->LookupExceptionHandlerInTable(&stack_depth, nullptr); 1306 if (offset >= 0) { 1307 // Compute the stack pointer from the frame pointer. This ensures that 1308 // operand stack slots are dropped for nested statements. Also restore 1309 // correct context for the handler which is pushed within the try-block. 1310 Address return_sp = frame->fp() - 1311 StandardFrameConstants::kFixedFrameSizeFromFp - 1312 stack_depth * kPointerSize; 1313 STATIC_ASSERT(TryBlockConstant::kElementCount == 1); 1314 context = Context::cast(Memory::Object_at(return_sp - kPointerSize)); 1315 1316 // Gather information from the frame. 1317 code = frame->LookupCode(); 1318 handler_sp = return_sp; 1319 handler_fp = frame->fp(); 1320 break; 1321 } 1322 } 1323 1324 RemoveMaterializedObjectsOnUnwind(frame); 1325 } 1326 1327 // Handler must exist. 1328 CHECK(code != nullptr); 1329 1330 // Store information to be consumed by the CEntryStub. 1331 thread_local_top()->pending_handler_context_ = context; 1332 thread_local_top()->pending_handler_code_ = code; 1333 thread_local_top()->pending_handler_offset_ = offset; 1334 thread_local_top()->pending_handler_fp_ = handler_fp; 1335 thread_local_top()->pending_handler_sp_ = handler_sp; 1336 1337 // Return and clear pending exception. 1338 clear_pending_exception(); 1339 return exception; 1340 } 1341 1342 namespace { 1343 HandlerTable::CatchPrediction PredictException(JavaScriptFrame* frame) { 1344 HandlerTable::CatchPrediction prediction; 1345 if (frame->is_optimized()) { 1346 if (frame->LookupExceptionHandlerInTable(nullptr, nullptr) > 0) { 1347 // This optimized frame will catch. It's handler table does not include 1348 // exception prediction, and we need to use the corresponding handler 1349 // tables on the unoptimized code objects. 1350 List<FrameSummary> summaries; 1351 frame->Summarize(&summaries); 1352 for (const FrameSummary& summary : summaries) { 1353 Handle<AbstractCode> code = summary.abstract_code(); 1354 if (code->kind() == AbstractCode::OPTIMIZED_FUNCTION) { 1355 DCHECK(summary.function()->shared()->asm_function()); 1356 DCHECK(!FLAG_turbo_asm_deoptimization); 1357 // asm code cannot contain try-catch. 1358 continue; 1359 } 1360 int code_offset = summary.code_offset(); 1361 int index = 1362 code->LookupRangeInHandlerTable(code_offset, nullptr, &prediction); 1363 if (index <= 0) continue; 1364 if (prediction == HandlerTable::UNCAUGHT) continue; 1365 return prediction; 1366 } 1367 } 1368 } else if (frame->LookupExceptionHandlerInTable(nullptr, &prediction) > 0) { 1369 return prediction; 1370 } 1371 return HandlerTable::UNCAUGHT; 1372 } 1373 } // anonymous namespace 1374 1375 Isolate::CatchType Isolate::PredictExceptionCatcher() { 1376 Address external_handler = thread_local_top()->try_catch_handler_address(); 1377 Address entry_handler = Isolate::handler(thread_local_top()); 1378 if (IsExternalHandlerOnTop(nullptr)) return CAUGHT_BY_EXTERNAL; 1379 1380 // Search for an exception handler by performing a full walk over the stack. 1381 for (StackFrameIterator iter(this); !iter.done(); iter.Advance()) { 1382 StackFrame* frame = iter.frame(); 1383 1384 // For JSEntryStub frames we update the JS_ENTRY handler. 1385 if (frame->is_entry() || frame->is_entry_construct()) { 1386 entry_handler = frame->top_handler()->next()->address(); 1387 } 1388 1389 // For JavaScript frames we perform a lookup in the handler table. 1390 if (frame->is_java_script()) { 1391 JavaScriptFrame* js_frame = static_cast<JavaScriptFrame*>(frame); 1392 HandlerTable::CatchPrediction prediction = PredictException(js_frame); 1393 if (prediction == HandlerTable::DESUGARING) return CAUGHT_BY_DESUGARING; 1394 if (prediction == HandlerTable::ASYNC_AWAIT) return CAUGHT_BY_ASYNC_AWAIT; 1395 if (prediction == HandlerTable::PROMISE) return CAUGHT_BY_PROMISE; 1396 if (prediction != HandlerTable::UNCAUGHT) return CAUGHT_BY_JAVASCRIPT; 1397 } 1398 1399 // The exception has been externally caught if and only if there is an 1400 // external handler which is on top of the top-most JS_ENTRY handler. 1401 if (external_handler != nullptr && !try_catch_handler()->is_verbose_) { 1402 if (entry_handler == nullptr || entry_handler > external_handler) { 1403 return CAUGHT_BY_EXTERNAL; 1404 } 1405 } 1406 } 1407 1408 // Handler not found. 1409 return NOT_CAUGHT; 1410 } 1411 1412 1413 void Isolate::RemoveMaterializedObjectsOnUnwind(StackFrame* frame) { 1414 if (frame->is_optimized()) { 1415 bool removed = materialized_object_store_->Remove(frame->fp()); 1416 USE(removed); 1417 // If there were any materialized objects, the code should be 1418 // marked for deopt. 1419 DCHECK(!removed || frame->LookupCode()->marked_for_deoptimization()); 1420 } 1421 } 1422 1423 1424 Object* Isolate::ThrowIllegalOperation() { 1425 if (FLAG_stack_trace_on_illegal) PrintStack(stdout); 1426 return Throw(heap()->illegal_access_string()); 1427 } 1428 1429 1430 void Isolate::ScheduleThrow(Object* exception) { 1431 // When scheduling a throw we first throw the exception to get the 1432 // error reporting if it is uncaught before rescheduling it. 1433 Throw(exception); 1434 PropagatePendingExceptionToExternalTryCatch(); 1435 if (has_pending_exception()) { 1436 thread_local_top()->scheduled_exception_ = pending_exception(); 1437 thread_local_top()->external_caught_exception_ = false; 1438 clear_pending_exception(); 1439 } 1440 } 1441 1442 1443 void Isolate::RestorePendingMessageFromTryCatch(v8::TryCatch* handler) { 1444 DCHECK(handler == try_catch_handler()); 1445 DCHECK(handler->HasCaught()); 1446 DCHECK(handler->rethrow_); 1447 DCHECK(handler->capture_message_); 1448 Object* message = reinterpret_cast<Object*>(handler->message_obj_); 1449 DCHECK(message->IsJSMessageObject() || message->IsTheHole(this)); 1450 thread_local_top()->pending_message_obj_ = message; 1451 } 1452 1453 1454 void Isolate::CancelScheduledExceptionFromTryCatch(v8::TryCatch* handler) { 1455 DCHECK(has_scheduled_exception()); 1456 if (scheduled_exception() == handler->exception_) { 1457 DCHECK(scheduled_exception() != heap()->termination_exception()); 1458 clear_scheduled_exception(); 1459 } 1460 } 1461 1462 1463 Object* Isolate::PromoteScheduledException() { 1464 Object* thrown = scheduled_exception(); 1465 clear_scheduled_exception(); 1466 // Re-throw the exception to avoid getting repeated error reporting. 1467 return ReThrow(thrown); 1468 } 1469 1470 1471 void Isolate::PrintCurrentStackTrace(FILE* out) { 1472 for (StackTraceFrameIterator it(this); !it.done(); it.Advance()) { 1473 if (!it.is_javascript()) continue; 1474 1475 HandleScope scope(this); 1476 JavaScriptFrame* frame = it.javascript_frame(); 1477 1478 Handle<Object> receiver(frame->receiver(), this); 1479 Handle<JSFunction> function(frame->function(), this); 1480 Handle<AbstractCode> code(AbstractCode::cast(frame->LookupCode()), this); 1481 const int offset = 1482 static_cast<int>(frame->pc() - code->instruction_start()); 1483 1484 JSStackFrame site(this, receiver, function, code, offset); 1485 Handle<String> line = site.ToString().ToHandleChecked(); 1486 if (line->length() > 0) { 1487 line->PrintOn(out); 1488 PrintF(out, "\n"); 1489 } 1490 } 1491 } 1492 1493 bool Isolate::ComputeLocation(MessageLocation* target) { 1494 StackTraceFrameIterator it(this); 1495 if (it.done()) return false; 1496 StandardFrame* frame = it.frame(); 1497 // TODO(clemensh): handle wasm frames 1498 if (!frame->is_java_script()) return false; 1499 JSFunction* fun = JavaScriptFrame::cast(frame)->function(); 1500 Object* script = fun->shared()->script(); 1501 if (!script->IsScript() || 1502 (Script::cast(script)->source()->IsUndefined(this))) { 1503 return false; 1504 } 1505 Handle<Script> casted_script(Script::cast(script), this); 1506 // Compute the location from the function and the relocation info of the 1507 // baseline code. For optimized code this will use the deoptimization 1508 // information to get canonical location information. 1509 List<FrameSummary> frames(FLAG_max_inlining_levels + 1); 1510 JavaScriptFrame::cast(frame)->Summarize(&frames); 1511 FrameSummary& summary = frames.last(); 1512 int pos = summary.abstract_code()->SourcePosition(summary.code_offset()); 1513 *target = MessageLocation(casted_script, pos, pos + 1, handle(fun, this)); 1514 return true; 1515 } 1516 1517 bool Isolate::ComputeLocationFromException(MessageLocation* target, 1518 Handle<Object> exception) { 1519 if (!exception->IsJSObject()) return false; 1520 1521 Handle<Name> start_pos_symbol = factory()->error_start_pos_symbol(); 1522 Handle<Object> start_pos = JSReceiver::GetDataProperty( 1523 Handle<JSObject>::cast(exception), start_pos_symbol); 1524 if (!start_pos->IsSmi()) return false; 1525 int start_pos_value = Handle<Smi>::cast(start_pos)->value(); 1526 1527 Handle<Name> end_pos_symbol = factory()->error_end_pos_symbol(); 1528 Handle<Object> end_pos = JSReceiver::GetDataProperty( 1529 Handle<JSObject>::cast(exception), end_pos_symbol); 1530 if (!end_pos->IsSmi()) return false; 1531 int end_pos_value = Handle<Smi>::cast(end_pos)->value(); 1532 1533 Handle<Name> script_symbol = factory()->error_script_symbol(); 1534 Handle<Object> script = JSReceiver::GetDataProperty( 1535 Handle<JSObject>::cast(exception), script_symbol); 1536 if (!script->IsScript()) return false; 1537 1538 Handle<Script> cast_script(Script::cast(*script)); 1539 *target = MessageLocation(cast_script, start_pos_value, end_pos_value); 1540 return true; 1541 } 1542 1543 1544 bool Isolate::ComputeLocationFromStackTrace(MessageLocation* target, 1545 Handle<Object> exception) { 1546 if (!exception->IsJSObject()) return false; 1547 Handle<Name> key = factory()->stack_trace_symbol(); 1548 Handle<Object> property = 1549 JSReceiver::GetDataProperty(Handle<JSObject>::cast(exception), key); 1550 if (!property->IsJSArray()) return false; 1551 Handle<JSArray> simple_stack_trace = Handle<JSArray>::cast(property); 1552 1553 Handle<FrameArray> elements(FrameArray::cast(simple_stack_trace->elements())); 1554 1555 const int frame_count = elements->FrameCount(); 1556 for (int i = 0; i < frame_count; i++) { 1557 if (elements->IsWasmFrame(i)) { 1558 // TODO(clemensh): handle wasm frames 1559 return false; 1560 } 1561 1562 Handle<JSFunction> fun = handle(elements->Function(i), this); 1563 if (!fun->shared()->IsSubjectToDebugging()) continue; 1564 1565 Object* script = fun->shared()->script(); 1566 if (script->IsScript() && 1567 !(Script::cast(script)->source()->IsUndefined(this))) { 1568 AbstractCode* abstract_code = elements->Code(i); 1569 const int code_offset = elements->Offset(i)->value(); 1570 const int pos = abstract_code->SourcePosition(code_offset); 1571 1572 Handle<Script> casted_script(Script::cast(script)); 1573 *target = MessageLocation(casted_script, pos, pos + 1); 1574 return true; 1575 } 1576 } 1577 return false; 1578 } 1579 1580 1581 Handle<JSMessageObject> Isolate::CreateMessage(Handle<Object> exception, 1582 MessageLocation* location) { 1583 Handle<JSArray> stack_trace_object; 1584 if (capture_stack_trace_for_uncaught_exceptions_) { 1585 if (exception->IsJSError()) { 1586 // We fetch the stack trace that corresponds to this error object. 1587 // If the lookup fails, the exception is probably not a valid Error 1588 // object. In that case, we fall through and capture the stack trace 1589 // at this throw site. 1590 stack_trace_object = 1591 GetDetailedStackTrace(Handle<JSObject>::cast(exception)); 1592 } 1593 if (stack_trace_object.is_null()) { 1594 // Not an error object, we capture stack and location at throw site. 1595 stack_trace_object = CaptureCurrentStackTrace( 1596 stack_trace_for_uncaught_exceptions_frame_limit_, 1597 stack_trace_for_uncaught_exceptions_options_); 1598 } 1599 } 1600 MessageLocation computed_location; 1601 if (location == NULL && 1602 (ComputeLocationFromException(&computed_location, exception) || 1603 ComputeLocationFromStackTrace(&computed_location, exception) || 1604 ComputeLocation(&computed_location))) { 1605 location = &computed_location; 1606 } 1607 1608 return MessageHandler::MakeMessageObject( 1609 this, MessageTemplate::kUncaughtException, location, exception, 1610 stack_trace_object); 1611 } 1612 1613 1614 bool Isolate::IsJavaScriptHandlerOnTop(Object* exception) { 1615 DCHECK_NE(heap()->the_hole_value(), exception); 1616 1617 // For uncatchable exceptions, the JavaScript handler cannot be on top. 1618 if (!is_catchable_by_javascript(exception)) return false; 1619 1620 // Get the top-most JS_ENTRY handler, cannot be on top if it doesn't exist. 1621 Address entry_handler = Isolate::handler(thread_local_top()); 1622 if (entry_handler == nullptr) return false; 1623 1624 // Get the address of the external handler so we can compare the address to 1625 // determine which one is closer to the top of the stack. 1626 Address external_handler = thread_local_top()->try_catch_handler_address(); 1627 if (external_handler == nullptr) return true; 1628 1629 // The exception has been externally caught if and only if there is an 1630 // external handler which is on top of the top-most JS_ENTRY handler. 1631 // 1632 // Note, that finally clauses would re-throw an exception unless it's aborted 1633 // by jumps in control flow (like return, break, etc.) and we'll have another 1634 // chance to set proper v8::TryCatch later. 1635 return (entry_handler < external_handler); 1636 } 1637 1638 1639 bool Isolate::IsExternalHandlerOnTop(Object* exception) { 1640 DCHECK_NE(heap()->the_hole_value(), exception); 1641 1642 // Get the address of the external handler so we can compare the address to 1643 // determine which one is closer to the top of the stack. 1644 Address external_handler = thread_local_top()->try_catch_handler_address(); 1645 if (external_handler == nullptr) return false; 1646 1647 // For uncatchable exceptions, the external handler is always on top. 1648 if (!is_catchable_by_javascript(exception)) return true; 1649 1650 // Get the top-most JS_ENTRY handler, cannot be on top if it doesn't exist. 1651 Address entry_handler = Isolate::handler(thread_local_top()); 1652 if (entry_handler == nullptr) return true; 1653 1654 // The exception has been externally caught if and only if there is an 1655 // external handler which is on top of the top-most JS_ENTRY handler. 1656 // 1657 // Note, that finally clauses would re-throw an exception unless it's aborted 1658 // by jumps in control flow (like return, break, etc.) and we'll have another 1659 // chance to set proper v8::TryCatch later. 1660 return (entry_handler > external_handler); 1661 } 1662 1663 1664 void Isolate::ReportPendingMessages() { 1665 Object* exception = pending_exception(); 1666 1667 // Try to propagate the exception to an external v8::TryCatch handler. If 1668 // propagation was unsuccessful, then we will get another chance at reporting 1669 // the pending message if the exception is re-thrown. 1670 bool has_been_propagated = PropagatePendingExceptionToExternalTryCatch(); 1671 if (!has_been_propagated) return; 1672 1673 // Clear the pending message object early to avoid endless recursion. 1674 Object* message_obj = thread_local_top_.pending_message_obj_; 1675 clear_pending_message(); 1676 1677 // For uncatchable exceptions we do nothing. If needed, the exception and the 1678 // message have already been propagated to v8::TryCatch. 1679 if (!is_catchable_by_javascript(exception)) return; 1680 1681 // Determine whether the message needs to be reported to all message handlers 1682 // depending on whether and external v8::TryCatch or an internal JavaScript 1683 // handler is on top. 1684 bool should_report_exception; 1685 if (IsExternalHandlerOnTop(exception)) { 1686 // Only report the exception if the external handler is verbose. 1687 should_report_exception = try_catch_handler()->is_verbose_; 1688 } else { 1689 // Report the exception if it isn't caught by JavaScript code. 1690 should_report_exception = !IsJavaScriptHandlerOnTop(exception); 1691 } 1692 1693 // Actually report the pending message to all message handlers. 1694 if (!message_obj->IsTheHole(this) && should_report_exception) { 1695 HandleScope scope(this); 1696 Handle<JSMessageObject> message(JSMessageObject::cast(message_obj), this); 1697 Handle<JSValue> script_wrapper(JSValue::cast(message->script()), this); 1698 Handle<Script> script(Script::cast(script_wrapper->value()), this); 1699 int start_pos = message->start_position(); 1700 int end_pos = message->end_position(); 1701 MessageLocation location(script, start_pos, end_pos); 1702 MessageHandler::ReportMessage(this, &location, message); 1703 } 1704 } 1705 1706 1707 MessageLocation Isolate::GetMessageLocation() { 1708 DCHECK(has_pending_exception()); 1709 1710 if (thread_local_top_.pending_exception_ != heap()->termination_exception() && 1711 !thread_local_top_.pending_message_obj_->IsTheHole(this)) { 1712 Handle<JSMessageObject> message_obj( 1713 JSMessageObject::cast(thread_local_top_.pending_message_obj_), this); 1714 Handle<JSValue> script_wrapper(JSValue::cast(message_obj->script()), this); 1715 Handle<Script> script(Script::cast(script_wrapper->value()), this); 1716 int start_pos = message_obj->start_position(); 1717 int end_pos = message_obj->end_position(); 1718 return MessageLocation(script, start_pos, end_pos); 1719 } 1720 1721 return MessageLocation(); 1722 } 1723 1724 1725 bool Isolate::OptionalRescheduleException(bool is_bottom_call) { 1726 DCHECK(has_pending_exception()); 1727 PropagatePendingExceptionToExternalTryCatch(); 1728 1729 bool is_termination_exception = 1730 pending_exception() == heap_.termination_exception(); 1731 1732 // Do not reschedule the exception if this is the bottom call. 1733 bool clear_exception = is_bottom_call; 1734 1735 if (is_termination_exception) { 1736 if (is_bottom_call) { 1737 thread_local_top()->external_caught_exception_ = false; 1738 clear_pending_exception(); 1739 return false; 1740 } 1741 } else if (thread_local_top()->external_caught_exception_) { 1742 // If the exception is externally caught, clear it if there are no 1743 // JavaScript frames on the way to the C++ frame that has the 1744 // external handler. 1745 DCHECK(thread_local_top()->try_catch_handler_address() != NULL); 1746 Address external_handler_address = 1747 thread_local_top()->try_catch_handler_address(); 1748 JavaScriptFrameIterator it(this); 1749 if (it.done() || (it.frame()->sp() > external_handler_address)) { 1750 clear_exception = true; 1751 } 1752 } 1753 1754 // Clear the exception if needed. 1755 if (clear_exception) { 1756 thread_local_top()->external_caught_exception_ = false; 1757 clear_pending_exception(); 1758 return false; 1759 } 1760 1761 // Reschedule the exception. 1762 thread_local_top()->scheduled_exception_ = pending_exception(); 1763 clear_pending_exception(); 1764 return true; 1765 } 1766 1767 void Isolate::PushPromise(Handle<JSObject> promise) { 1768 ThreadLocalTop* tltop = thread_local_top(); 1769 PromiseOnStack* prev = tltop->promise_on_stack_; 1770 Handle<JSObject> global_promise = 1771 Handle<JSObject>::cast(global_handles()->Create(*promise)); 1772 tltop->promise_on_stack_ = new PromiseOnStack(global_promise, prev); 1773 } 1774 1775 1776 void Isolate::PopPromise() { 1777 ThreadLocalTop* tltop = thread_local_top(); 1778 if (tltop->promise_on_stack_ == NULL) return; 1779 PromiseOnStack* prev = tltop->promise_on_stack_->prev(); 1780 Handle<Object> global_promise = tltop->promise_on_stack_->promise(); 1781 delete tltop->promise_on_stack_; 1782 tltop->promise_on_stack_ = prev; 1783 global_handles()->Destroy(global_promise.location()); 1784 } 1785 1786 bool Isolate::PromiseHasUserDefinedRejectHandler(Handle<Object> promise) { 1787 Handle<JSFunction> fun = promise_has_user_defined_reject_handler(); 1788 Handle<Object> has_reject_handler; 1789 // If we are, e.g., overflowing the stack, don't try to call out to JS 1790 if (!AllowJavascriptExecution::IsAllowed(this)) return false; 1791 // Call the registered function to check for a handler 1792 if (Execution::TryCall(this, fun, promise, 0, NULL) 1793 .ToHandle(&has_reject_handler)) { 1794 return has_reject_handler->IsTrue(this); 1795 } 1796 // If an exception is thrown in the course of execution of this built-in 1797 // function, it indicates either a bug, or a synthetic uncatchable 1798 // exception in the shutdown path. In either case, it's OK to predict either 1799 // way in DevTools. 1800 return false; 1801 } 1802 1803 Handle<Object> Isolate::GetPromiseOnStackOnThrow() { 1804 Handle<Object> undefined = factory()->undefined_value(); 1805 ThreadLocalTop* tltop = thread_local_top(); 1806 if (tltop->promise_on_stack_ == NULL) return undefined; 1807 // Find the top-most try-catch or try-finally handler. 1808 CatchType prediction = PredictExceptionCatcher(); 1809 if (prediction == NOT_CAUGHT || prediction == CAUGHT_BY_EXTERNAL) { 1810 return undefined; 1811 } 1812 Handle<Object> retval = undefined; 1813 PromiseOnStack* promise_on_stack = tltop->promise_on_stack_; 1814 for (JavaScriptFrameIterator it(this); !it.done(); it.Advance()) { 1815 switch (PredictException(it.frame())) { 1816 case HandlerTable::UNCAUGHT: 1817 continue; 1818 case HandlerTable::CAUGHT: 1819 case HandlerTable::DESUGARING: 1820 if (retval->IsJSObject()) { 1821 // Caught the result of an inner async/await invocation. 1822 // Mark the inner promise as caught in the "synchronous case" so 1823 // that Debug::OnException will see. In the synchronous case, 1824 // namely in the code in an async function before the first 1825 // await, the function which has this exception event has not yet 1826 // returned, so the generated Promise has not yet been marked 1827 // by AsyncFunctionAwaitCaught with promiseHandledHintSymbol. 1828 Handle<Symbol> key = factory()->promise_handled_hint_symbol(); 1829 JSObject::SetProperty(Handle<JSObject>::cast(retval), key, 1830 factory()->true_value(), STRICT) 1831 .Assert(); 1832 } 1833 return retval; 1834 case HandlerTable::PROMISE: 1835 return promise_on_stack 1836 ? Handle<Object>::cast(promise_on_stack->promise()) 1837 : undefined; 1838 case HandlerTable::ASYNC_AWAIT: { 1839 // If in the initial portion of async/await, continue the loop to pop up 1840 // successive async/await stack frames until an asynchronous one with 1841 // dependents is found, or a non-async stack frame is encountered, in 1842 // order to handle the synchronous async/await catch prediction case: 1843 // assume that async function calls are awaited. 1844 if (!promise_on_stack) return retval; 1845 retval = promise_on_stack->promise(); 1846 if (PromiseHasUserDefinedRejectHandler(retval)) { 1847 return retval; 1848 } 1849 promise_on_stack = promise_on_stack->prev(); 1850 continue; 1851 } 1852 } 1853 } 1854 return retval; 1855 } 1856 1857 1858 void Isolate::SetCaptureStackTraceForUncaughtExceptions( 1859 bool capture, 1860 int frame_limit, 1861 StackTrace::StackTraceOptions options) { 1862 capture_stack_trace_for_uncaught_exceptions_ = capture; 1863 stack_trace_for_uncaught_exceptions_frame_limit_ = frame_limit; 1864 stack_trace_for_uncaught_exceptions_options_ = options; 1865 } 1866 1867 1868 void Isolate::SetAbortOnUncaughtExceptionCallback( 1869 v8::Isolate::AbortOnUncaughtExceptionCallback callback) { 1870 abort_on_uncaught_exception_callback_ = callback; 1871 } 1872 1873 1874 Handle<Context> Isolate::GetCallingNativeContext() { 1875 JavaScriptFrameIterator it(this); 1876 if (debug_->in_debug_scope()) { 1877 while (!it.done()) { 1878 JavaScriptFrame* frame = it.frame(); 1879 Context* context = Context::cast(frame->context()); 1880 if (context->native_context() == *debug_->debug_context()) { 1881 it.Advance(); 1882 } else { 1883 break; 1884 } 1885 } 1886 } 1887 if (it.done()) return Handle<Context>::null(); 1888 JavaScriptFrame* frame = it.frame(); 1889 Context* context = Context::cast(frame->context()); 1890 return Handle<Context>(context->native_context(), this); 1891 } 1892 1893 1894 char* Isolate::ArchiveThread(char* to) { 1895 MemCopy(to, reinterpret_cast<char*>(thread_local_top()), 1896 sizeof(ThreadLocalTop)); 1897 InitializeThreadLocal(); 1898 clear_pending_exception(); 1899 clear_pending_message(); 1900 clear_scheduled_exception(); 1901 return to + sizeof(ThreadLocalTop); 1902 } 1903 1904 1905 char* Isolate::RestoreThread(char* from) { 1906 MemCopy(reinterpret_cast<char*>(thread_local_top()), from, 1907 sizeof(ThreadLocalTop)); 1908 // This might be just paranoia, but it seems to be needed in case a 1909 // thread_local_top_ is restored on a separate OS thread. 1910 #ifdef USE_SIMULATOR 1911 thread_local_top()->simulator_ = Simulator::current(this); 1912 #endif 1913 DCHECK(context() == NULL || context()->IsContext()); 1914 return from + sizeof(ThreadLocalTop); 1915 } 1916 1917 1918 Isolate::ThreadDataTable::ThreadDataTable() 1919 : list_(NULL) { 1920 } 1921 1922 1923 Isolate::ThreadDataTable::~ThreadDataTable() { 1924 // TODO(svenpanne) The assertion below would fire if an embedder does not 1925 // cleanly dispose all Isolates before disposing v8, so we are conservative 1926 // and leave it out for now. 1927 // DCHECK_NULL(list_); 1928 } 1929 1930 1931 Isolate::PerIsolateThreadData::~PerIsolateThreadData() { 1932 #if defined(USE_SIMULATOR) 1933 delete simulator_; 1934 #endif 1935 } 1936 1937 1938 Isolate::PerIsolateThreadData* 1939 Isolate::ThreadDataTable::Lookup(Isolate* isolate, 1940 ThreadId thread_id) { 1941 for (PerIsolateThreadData* data = list_; data != NULL; data = data->next_) { 1942 if (data->Matches(isolate, thread_id)) return data; 1943 } 1944 return NULL; 1945 } 1946 1947 1948 void Isolate::ThreadDataTable::Insert(Isolate::PerIsolateThreadData* data) { 1949 if (list_ != NULL) list_->prev_ = data; 1950 data->next_ = list_; 1951 list_ = data; 1952 } 1953 1954 1955 void Isolate::ThreadDataTable::Remove(PerIsolateThreadData* data) { 1956 if (list_ == data) list_ = data->next_; 1957 if (data->next_ != NULL) data->next_->prev_ = data->prev_; 1958 if (data->prev_ != NULL) data->prev_->next_ = data->next_; 1959 delete data; 1960 } 1961 1962 1963 void Isolate::ThreadDataTable::RemoveAllThreads(Isolate* isolate) { 1964 PerIsolateThreadData* data = list_; 1965 while (data != NULL) { 1966 PerIsolateThreadData* next = data->next_; 1967 if (data->isolate() == isolate) Remove(data); 1968 data = next; 1969 } 1970 } 1971 1972 1973 #ifdef DEBUG 1974 #define TRACE_ISOLATE(tag) \ 1975 do { \ 1976 if (FLAG_trace_isolates) { \ 1977 PrintF("Isolate %p (id %d)" #tag "\n", \ 1978 reinterpret_cast<void*>(this), id()); \ 1979 } \ 1980 } while (false) 1981 #else 1982 #define TRACE_ISOLATE(tag) 1983 #endif 1984 1985 class VerboseAccountingAllocator : public AccountingAllocator { 1986 public: 1987 VerboseAccountingAllocator(Heap* heap, size_t allocation_sample_bytes, 1988 size_t pool_sample_bytes) 1989 : heap_(heap), 1990 last_memory_usage_(0), 1991 last_pool_size_(0), 1992 nesting_deepth_(0), 1993 allocation_sample_bytes_(allocation_sample_bytes), 1994 pool_sample_bytes_(pool_sample_bytes) {} 1995 1996 v8::internal::Segment* GetSegment(size_t size) override { 1997 v8::internal::Segment* memory = AccountingAllocator::GetSegment(size); 1998 if (memory) { 1999 size_t malloced_current = GetCurrentMemoryUsage(); 2000 size_t pooled_current = GetCurrentPoolSize(); 2001 2002 if (last_memory_usage_.Value() + allocation_sample_bytes_ < 2003 malloced_current || 2004 last_pool_size_.Value() + pool_sample_bytes_ < pooled_current) { 2005 PrintMemoryJSON(malloced_current, pooled_current); 2006 last_memory_usage_.SetValue(malloced_current); 2007 last_pool_size_.SetValue(pooled_current); 2008 } 2009 } 2010 return memory; 2011 } 2012 2013 void ReturnSegment(v8::internal::Segment* memory) override { 2014 AccountingAllocator::ReturnSegment(memory); 2015 size_t malloced_current = GetCurrentMemoryUsage(); 2016 size_t pooled_current = GetCurrentPoolSize(); 2017 2018 if (malloced_current + allocation_sample_bytes_ < 2019 last_memory_usage_.Value() || 2020 pooled_current + pool_sample_bytes_ < last_pool_size_.Value()) { 2021 PrintMemoryJSON(malloced_current, pooled_current); 2022 last_memory_usage_.SetValue(malloced_current); 2023 last_pool_size_.SetValue(pooled_current); 2024 } 2025 } 2026 2027 void ZoneCreation(const Zone* zone) override { 2028 double time = heap_->isolate()->time_millis_since_init(); 2029 PrintF( 2030 "{" 2031 "\"type\": \"zonecreation\", " 2032 "\"isolate\": \"%p\", " 2033 "\"time\": %f, " 2034 "\"ptr\": \"%p\", " 2035 "\"name\": \"%s\"," 2036 "\"nesting\": %zu" 2037 "}\n", 2038 reinterpret_cast<void*>(heap_->isolate()), time, 2039 reinterpret_cast<const void*>(zone), zone->name(), 2040 nesting_deepth_.Value()); 2041 nesting_deepth_.Increment(1); 2042 } 2043 2044 void ZoneDestruction(const Zone* zone) override { 2045 nesting_deepth_.Decrement(1); 2046 double time = heap_->isolate()->time_millis_since_init(); 2047 PrintF( 2048 "{" 2049 "\"type\": \"zonedestruction\", " 2050 "\"isolate\": \"%p\", " 2051 "\"time\": %f, " 2052 "\"ptr\": \"%p\", " 2053 "\"name\": \"%s\", " 2054 "\"size\": %zu," 2055 "\"nesting\": %zu" 2056 "}\n", 2057 reinterpret_cast<void*>(heap_->isolate()), time, 2058 reinterpret_cast<const void*>(zone), zone->name(), 2059 zone->allocation_size(), nesting_deepth_.Value()); 2060 } 2061 2062 private: 2063 void PrintMemoryJSON(size_t malloced, size_t pooled) { 2064 // Note: Neither isolate, nor heap is locked, so be careful with accesses 2065 // as the allocator is potentially used on a concurrent thread. 2066 double time = heap_->isolate()->time_millis_since_init(); 2067 PrintF( 2068 "{" 2069 "\"type\": \"zone\", " 2070 "\"isolate\": \"%p\", " 2071 "\"time\": %f, " 2072 "\"allocated\": %zu," 2073 "\"pooled\": %zu" 2074 "}\n", 2075 reinterpret_cast<void*>(heap_->isolate()), time, malloced, pooled); 2076 } 2077 2078 Heap* heap_; 2079 base::AtomicNumber<size_t> last_memory_usage_; 2080 base::AtomicNumber<size_t> last_pool_size_; 2081 base::AtomicNumber<size_t> nesting_deepth_; 2082 size_t allocation_sample_bytes_, pool_sample_bytes_; 2083 }; 2084 2085 Isolate::Isolate(bool enable_serializer) 2086 : embedder_data_(), 2087 entry_stack_(NULL), 2088 stack_trace_nesting_level_(0), 2089 incomplete_message_(NULL), 2090 bootstrapper_(NULL), 2091 runtime_profiler_(NULL), 2092 compilation_cache_(NULL), 2093 counters_(NULL), 2094 logger_(NULL), 2095 stats_table_(NULL), 2096 load_stub_cache_(NULL), 2097 store_stub_cache_(NULL), 2098 code_aging_helper_(NULL), 2099 deoptimizer_data_(NULL), 2100 deoptimizer_lazy_throw_(false), 2101 materialized_object_store_(NULL), 2102 capture_stack_trace_for_uncaught_exceptions_(false), 2103 stack_trace_for_uncaught_exceptions_frame_limit_(0), 2104 stack_trace_for_uncaught_exceptions_options_(StackTrace::kOverview), 2105 context_slot_cache_(NULL), 2106 descriptor_lookup_cache_(NULL), 2107 handle_scope_implementer_(NULL), 2108 unicode_cache_(NULL), 2109 allocator_(FLAG_trace_gc_object_stats ? new VerboseAccountingAllocator( 2110 &heap_, 256 * KB, 128 * KB) 2111 : new AccountingAllocator()), 2112 inner_pointer_to_code_cache_(NULL), 2113 global_handles_(NULL), 2114 eternal_handles_(NULL), 2115 thread_manager_(NULL), 2116 has_installed_extensions_(false), 2117 regexp_stack_(NULL), 2118 date_cache_(NULL), 2119 call_descriptor_data_(NULL), 2120 // TODO(bmeurer) Initialized lazily because it depends on flags; can 2121 // be fixed once the default isolate cleanup is done. 2122 random_number_generator_(NULL), 2123 rail_mode_(PERFORMANCE_ANIMATION), 2124 serializer_enabled_(enable_serializer), 2125 has_fatal_error_(false), 2126 initialized_from_snapshot_(false), 2127 is_tail_call_elimination_enabled_(true), 2128 is_isolate_in_background_(false), 2129 cpu_profiler_(NULL), 2130 heap_profiler_(NULL), 2131 code_event_dispatcher_(new CodeEventDispatcher()), 2132 function_entry_hook_(NULL), 2133 deferred_handles_head_(NULL), 2134 optimizing_compile_dispatcher_(NULL), 2135 stress_deopt_count_(0), 2136 next_optimization_id_(0), 2137 #if TRACE_MAPS 2138 next_unique_sfi_id_(0), 2139 #endif 2140 is_running_microtasks_(false), 2141 use_counter_callback_(NULL), 2142 basic_block_profiler_(NULL), 2143 cancelable_task_manager_(new CancelableTaskManager()), 2144 abort_on_uncaught_exception_callback_(NULL) { 2145 { 2146 base::LockGuard<base::Mutex> lock_guard(thread_data_table_mutex_.Pointer()); 2147 CHECK(thread_data_table_); 2148 } 2149 id_ = base::NoBarrier_AtomicIncrement(&isolate_counter_, 1); 2150 TRACE_ISOLATE(constructor); 2151 2152 memset(isolate_addresses_, 0, 2153 sizeof(isolate_addresses_[0]) * (kIsolateAddressCount + 1)); 2154 2155 heap_.isolate_ = this; 2156 stack_guard_.isolate_ = this; 2157 2158 // ThreadManager is initialized early to support locking an isolate 2159 // before it is entered. 2160 thread_manager_ = new ThreadManager(); 2161 thread_manager_->isolate_ = this; 2162 2163 #ifdef DEBUG 2164 // heap_histograms_ initializes itself. 2165 memset(&js_spill_information_, 0, sizeof(js_spill_information_)); 2166 #endif 2167 2168 handle_scope_data_.Initialize(); 2169 2170 #define ISOLATE_INIT_EXECUTE(type, name, initial_value) \ 2171 name##_ = (initial_value); 2172 ISOLATE_INIT_LIST(ISOLATE_INIT_EXECUTE) 2173 #undef ISOLATE_INIT_EXECUTE 2174 2175 #define ISOLATE_INIT_ARRAY_EXECUTE(type, name, length) \ 2176 memset(name##_, 0, sizeof(type) * length); 2177 ISOLATE_INIT_ARRAY_LIST(ISOLATE_INIT_ARRAY_EXECUTE) 2178 #undef ISOLATE_INIT_ARRAY_EXECUTE 2179 2180 InitializeLoggingAndCounters(); 2181 debug_ = new Debug(this); 2182 2183 init_memcopy_functions(this); 2184 } 2185 2186 2187 void Isolate::TearDown() { 2188 TRACE_ISOLATE(tear_down); 2189 2190 // Temporarily set this isolate as current so that various parts of 2191 // the isolate can access it in their destructors without having a 2192 // direct pointer. We don't use Enter/Exit here to avoid 2193 // initializing the thread data. 2194 PerIsolateThreadData* saved_data = CurrentPerIsolateThreadData(); 2195 DCHECK(base::NoBarrier_Load(&isolate_key_created_) == 1); 2196 Isolate* saved_isolate = 2197 reinterpret_cast<Isolate*>(base::Thread::GetThreadLocal(isolate_key_)); 2198 SetIsolateThreadLocals(this, NULL); 2199 2200 Deinit(); 2201 2202 { 2203 base::LockGuard<base::Mutex> lock_guard(thread_data_table_mutex_.Pointer()); 2204 thread_data_table_->RemoveAllThreads(this); 2205 } 2206 2207 delete this; 2208 2209 // Restore the previous current isolate. 2210 SetIsolateThreadLocals(saved_isolate, saved_data); 2211 } 2212 2213 2214 void Isolate::GlobalTearDown() { 2215 delete thread_data_table_; 2216 thread_data_table_ = NULL; 2217 } 2218 2219 2220 void Isolate::ClearSerializerData() { 2221 delete external_reference_table_; 2222 external_reference_table_ = NULL; 2223 delete external_reference_map_; 2224 external_reference_map_ = NULL; 2225 } 2226 2227 2228 void Isolate::Deinit() { 2229 TRACE_ISOLATE(deinit); 2230 2231 debug()->Unload(); 2232 2233 FreeThreadResources(); 2234 2235 if (concurrent_recompilation_enabled()) { 2236 optimizing_compile_dispatcher_->Stop(); 2237 delete optimizing_compile_dispatcher_; 2238 optimizing_compile_dispatcher_ = NULL; 2239 } 2240 2241 if (heap_.mark_compact_collector()->sweeping_in_progress()) { 2242 heap_.mark_compact_collector()->EnsureSweepingCompleted(); 2243 } 2244 2245 DumpAndResetCompilationStats(); 2246 2247 if (FLAG_print_deopt_stress) { 2248 PrintF(stdout, "=== Stress deopt counter: %u\n", stress_deopt_count_); 2249 } 2250 2251 if (cpu_profiler_) { 2252 cpu_profiler_->DeleteAllProfiles(); 2253 } 2254 2255 // We must stop the logger before we tear down other components. 2256 sampler::Sampler* sampler = logger_->sampler(); 2257 if (sampler && sampler->IsActive()) sampler->Stop(); 2258 2259 delete deoptimizer_data_; 2260 deoptimizer_data_ = NULL; 2261 builtins_.TearDown(); 2262 bootstrapper_->TearDown(); 2263 2264 if (runtime_profiler_ != NULL) { 2265 delete runtime_profiler_; 2266 runtime_profiler_ = NULL; 2267 } 2268 2269 delete basic_block_profiler_; 2270 basic_block_profiler_ = NULL; 2271 2272 delete heap_profiler_; 2273 heap_profiler_ = NULL; 2274 2275 cancelable_task_manager()->CancelAndWait(); 2276 2277 heap_.TearDown(); 2278 logger_->TearDown(); 2279 2280 delete interpreter_; 2281 interpreter_ = NULL; 2282 2283 delete compiler_dispatcher_tracer_; 2284 compiler_dispatcher_tracer_ = nullptr; 2285 2286 delete cpu_profiler_; 2287 cpu_profiler_ = NULL; 2288 2289 code_event_dispatcher_.reset(); 2290 2291 delete root_index_map_; 2292 root_index_map_ = NULL; 2293 2294 ClearSerializerData(); 2295 } 2296 2297 2298 void Isolate::SetIsolateThreadLocals(Isolate* isolate, 2299 PerIsolateThreadData* data) { 2300 base::Thread::SetThreadLocal(isolate_key_, isolate); 2301 base::Thread::SetThreadLocal(per_isolate_thread_data_key_, data); 2302 } 2303 2304 2305 Isolate::~Isolate() { 2306 TRACE_ISOLATE(destructor); 2307 2308 // The entry stack must be empty when we get here. 2309 DCHECK(entry_stack_ == NULL || entry_stack_->previous_item == NULL); 2310 2311 delete entry_stack_; 2312 entry_stack_ = NULL; 2313 2314 delete unicode_cache_; 2315 unicode_cache_ = NULL; 2316 2317 delete date_cache_; 2318 date_cache_ = NULL; 2319 2320 delete[] call_descriptor_data_; 2321 call_descriptor_data_ = NULL; 2322 2323 delete access_compiler_data_; 2324 access_compiler_data_ = NULL; 2325 2326 delete regexp_stack_; 2327 regexp_stack_ = NULL; 2328 2329 delete descriptor_lookup_cache_; 2330 descriptor_lookup_cache_ = NULL; 2331 delete context_slot_cache_; 2332 context_slot_cache_ = NULL; 2333 2334 delete load_stub_cache_; 2335 load_stub_cache_ = NULL; 2336 delete store_stub_cache_; 2337 store_stub_cache_ = NULL; 2338 delete code_aging_helper_; 2339 code_aging_helper_ = NULL; 2340 delete stats_table_; 2341 stats_table_ = NULL; 2342 2343 delete materialized_object_store_; 2344 materialized_object_store_ = NULL; 2345 2346 delete logger_; 2347 logger_ = NULL; 2348 2349 delete counters_; 2350 counters_ = NULL; 2351 2352 delete handle_scope_implementer_; 2353 handle_scope_implementer_ = NULL; 2354 2355 delete code_tracer(); 2356 set_code_tracer(NULL); 2357 2358 delete compilation_cache_; 2359 compilation_cache_ = NULL; 2360 delete bootstrapper_; 2361 bootstrapper_ = NULL; 2362 delete inner_pointer_to_code_cache_; 2363 inner_pointer_to_code_cache_ = NULL; 2364 2365 delete thread_manager_; 2366 thread_manager_ = NULL; 2367 2368 delete global_handles_; 2369 global_handles_ = NULL; 2370 delete eternal_handles_; 2371 eternal_handles_ = NULL; 2372 2373 delete string_stream_debug_object_cache_; 2374 string_stream_debug_object_cache_ = NULL; 2375 2376 delete random_number_generator_; 2377 random_number_generator_ = NULL; 2378 2379 delete debug_; 2380 debug_ = NULL; 2381 2382 delete cancelable_task_manager_; 2383 cancelable_task_manager_ = nullptr; 2384 2385 delete allocator_; 2386 allocator_ = nullptr; 2387 2388 #if USE_SIMULATOR 2389 Simulator::TearDown(simulator_i_cache_, simulator_redirection_); 2390 simulator_i_cache_ = nullptr; 2391 simulator_redirection_ = nullptr; 2392 #endif 2393 } 2394 2395 2396 void Isolate::InitializeThreadLocal() { 2397 thread_local_top_.isolate_ = this; 2398 thread_local_top_.Initialize(); 2399 } 2400 2401 2402 bool Isolate::PropagatePendingExceptionToExternalTryCatch() { 2403 Object* exception = pending_exception(); 2404 2405 if (IsJavaScriptHandlerOnTop(exception)) { 2406 thread_local_top_.external_caught_exception_ = false; 2407 return false; 2408 } 2409 2410 if (!IsExternalHandlerOnTop(exception)) { 2411 thread_local_top_.external_caught_exception_ = false; 2412 return true; 2413 } 2414 2415 thread_local_top_.external_caught_exception_ = true; 2416 if (!is_catchable_by_javascript(exception)) { 2417 try_catch_handler()->can_continue_ = false; 2418 try_catch_handler()->has_terminated_ = true; 2419 try_catch_handler()->exception_ = heap()->null_value(); 2420 } else { 2421 v8::TryCatch* handler = try_catch_handler(); 2422 DCHECK(thread_local_top_.pending_message_obj_->IsJSMessageObject() || 2423 thread_local_top_.pending_message_obj_->IsTheHole(this)); 2424 handler->can_continue_ = true; 2425 handler->has_terminated_ = false; 2426 handler->exception_ = pending_exception(); 2427 // Propagate to the external try-catch only if we got an actual message. 2428 if (thread_local_top_.pending_message_obj_->IsTheHole(this)) return true; 2429 2430 handler->message_obj_ = thread_local_top_.pending_message_obj_; 2431 } 2432 return true; 2433 } 2434 2435 2436 void Isolate::InitializeLoggingAndCounters() { 2437 if (logger_ == NULL) { 2438 logger_ = new Logger(this); 2439 } 2440 if (counters_ == NULL) { 2441 counters_ = new Counters(this); 2442 } 2443 } 2444 2445 2446 bool Isolate::Init(Deserializer* des) { 2447 TRACE_ISOLATE(init); 2448 2449 stress_deopt_count_ = FLAG_deopt_every_n_times; 2450 2451 has_fatal_error_ = false; 2452 2453 if (function_entry_hook() != NULL) { 2454 // When function entry hooking is in effect, we have to create the code 2455 // stubs from scratch to get entry hooks, rather than loading the previously 2456 // generated stubs from disk. 2457 // If this assert fires, the initialization path has regressed. 2458 DCHECK(des == NULL); 2459 } 2460 2461 // The initialization process does not handle memory exhaustion. 2462 AlwaysAllocateScope always_allocate(this); 2463 2464 // Safe after setting Heap::isolate_, and initializing StackGuard 2465 heap_.SetStackLimits(); 2466 2467 #define ASSIGN_ELEMENT(CamelName, hacker_name) \ 2468 isolate_addresses_[Isolate::k##CamelName##Address] = \ 2469 reinterpret_cast<Address>(hacker_name##_address()); 2470 FOR_EACH_ISOLATE_ADDRESS_NAME(ASSIGN_ELEMENT) 2471 #undef ASSIGN_ELEMENT 2472 2473 compilation_cache_ = new CompilationCache(this); 2474 context_slot_cache_ = new ContextSlotCache(); 2475 descriptor_lookup_cache_ = new DescriptorLookupCache(); 2476 unicode_cache_ = new UnicodeCache(); 2477 inner_pointer_to_code_cache_ = new InnerPointerToCodeCache(this); 2478 global_handles_ = new GlobalHandles(this); 2479 eternal_handles_ = new EternalHandles(); 2480 bootstrapper_ = new Bootstrapper(this); 2481 handle_scope_implementer_ = new HandleScopeImplementer(this); 2482 load_stub_cache_ = new StubCache(this, Code::LOAD_IC); 2483 store_stub_cache_ = new StubCache(this, Code::STORE_IC); 2484 materialized_object_store_ = new MaterializedObjectStore(this); 2485 regexp_stack_ = new RegExpStack(); 2486 regexp_stack_->isolate_ = this; 2487 date_cache_ = new DateCache(); 2488 call_descriptor_data_ = 2489 new CallInterfaceDescriptorData[CallDescriptors::NUMBER_OF_DESCRIPTORS]; 2490 access_compiler_data_ = new AccessCompilerData(); 2491 cpu_profiler_ = new CpuProfiler(this); 2492 heap_profiler_ = new HeapProfiler(heap()); 2493 interpreter_ = new interpreter::Interpreter(this); 2494 compiler_dispatcher_tracer_ = new CompilerDispatcherTracer(this); 2495 2496 // Enable logging before setting up the heap 2497 logger_->SetUp(this); 2498 2499 // Initialize other runtime facilities 2500 #if defined(USE_SIMULATOR) 2501 #if V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_MIPS || \ 2502 V8_TARGET_ARCH_MIPS64 || V8_TARGET_ARCH_PPC || V8_TARGET_ARCH_S390 2503 Simulator::Initialize(this); 2504 #endif 2505 #endif 2506 2507 code_aging_helper_ = new CodeAgingHelper(this); 2508 2509 { // NOLINT 2510 // Ensure that the thread has a valid stack guard. The v8::Locker object 2511 // will ensure this too, but we don't have to use lockers if we are only 2512 // using one thread. 2513 ExecutionAccess lock(this); 2514 stack_guard_.InitThread(lock); 2515 } 2516 2517 // SetUp the object heap. 2518 DCHECK(!heap_.HasBeenSetUp()); 2519 if (!heap_.SetUp()) { 2520 V8::FatalProcessOutOfMemory("heap setup"); 2521 return false; 2522 } 2523 2524 // Initialize the interface descriptors ahead of time. 2525 #define INTERFACE_DESCRIPTOR(V) \ 2526 { V##Descriptor(this); } 2527 INTERFACE_DESCRIPTOR_LIST(INTERFACE_DESCRIPTOR) 2528 #undef INTERFACE_DESCRIPTOR 2529 2530 deoptimizer_data_ = new DeoptimizerData(heap()->memory_allocator()); 2531 2532 const bool create_heap_objects = (des == NULL); 2533 if (create_heap_objects && !heap_.CreateHeapObjects()) { 2534 V8::FatalProcessOutOfMemory("heap object creation"); 2535 return false; 2536 } 2537 2538 if (create_heap_objects) { 2539 // Terminate the partial snapshot cache so we can iterate. 2540 partial_snapshot_cache_.Add(heap_.undefined_value()); 2541 } 2542 2543 InitializeThreadLocal(); 2544 2545 bootstrapper_->Initialize(create_heap_objects); 2546 builtins_.SetUp(this, create_heap_objects); 2547 if (create_heap_objects) { 2548 heap_.CreateFixedStubs(); 2549 } 2550 2551 if (FLAG_log_internal_timer_events) { 2552 set_event_logger(Logger::DefaultEventLoggerSentinel); 2553 } 2554 2555 if (FLAG_trace_hydrogen || FLAG_trace_hydrogen_stubs || FLAG_trace_turbo || 2556 FLAG_trace_turbo_graph) { 2557 PrintF("Concurrent recompilation has been disabled for tracing.\n"); 2558 } else if (OptimizingCompileDispatcher::Enabled()) { 2559 optimizing_compile_dispatcher_ = new OptimizingCompileDispatcher(this); 2560 } 2561 2562 // Initialize runtime profiler before deserialization, because collections may 2563 // occur, clearing/updating ICs. 2564 runtime_profiler_ = new RuntimeProfiler(this); 2565 2566 // If we are deserializing, read the state into the now-empty heap. 2567 { 2568 AlwaysAllocateScope always_allocate(this); 2569 2570 if (!create_heap_objects) { 2571 des->Deserialize(this); 2572 } 2573 load_stub_cache_->Initialize(); 2574 store_stub_cache_->Initialize(); 2575 interpreter_->Initialize(); 2576 2577 heap_.NotifyDeserializationComplete(); 2578 } 2579 2580 // Finish initialization of ThreadLocal after deserialization is done. 2581 clear_pending_exception(); 2582 clear_pending_message(); 2583 clear_scheduled_exception(); 2584 2585 // Deserializing may put strange things in the root array's copy of the 2586 // stack guard. 2587 heap_.SetStackLimits(); 2588 2589 // Quiet the heap NaN if needed on target platform. 2590 if (!create_heap_objects) Assembler::QuietNaN(heap_.nan_value()); 2591 2592 if (FLAG_trace_turbo) { 2593 // Create an empty file. 2594 std::ofstream(GetTurboCfgFileName().c_str(), std::ios_base::trunc); 2595 } 2596 2597 CHECK_EQ(static_cast<int>(OFFSET_OF(Isolate, embedder_data_)), 2598 Internals::kIsolateEmbedderDataOffset); 2599 CHECK_EQ(static_cast<int>(OFFSET_OF(Isolate, heap_.roots_)), 2600 Internals::kIsolateRootsOffset); 2601 CHECK_EQ(static_cast<int>(OFFSET_OF(Isolate, heap_.external_memory_)), 2602 Internals::kExternalMemoryOffset); 2603 CHECK_EQ(static_cast<int>(OFFSET_OF(Isolate, heap_.external_memory_limit_)), 2604 Internals::kExternalMemoryLimitOffset); 2605 2606 time_millis_at_init_ = heap_.MonotonicallyIncreasingTimeInMs(); 2607 2608 if (!create_heap_objects) { 2609 // Now that the heap is consistent, it's OK to generate the code for the 2610 // deopt entry table that might have been referred to by optimized code in 2611 // the snapshot. 2612 HandleScope scope(this); 2613 Deoptimizer::EnsureCodeForDeoptimizationEntry( 2614 this, Deoptimizer::LAZY, 2615 ExternalReferenceTable::kDeoptTableSerializeEntryCount - 1); 2616 } 2617 2618 if (!serializer_enabled()) { 2619 // Ensure that all stubs which need to be generated ahead of time, but 2620 // cannot be serialized into the snapshot have been generated. 2621 HandleScope scope(this); 2622 CodeStub::GenerateFPStubs(this); 2623 StoreBufferOverflowStub::GenerateFixedRegStubsAheadOfTime(this); 2624 StubFailureTrampolineStub::GenerateAheadOfTime(this); 2625 } 2626 2627 initialized_from_snapshot_ = (des != NULL); 2628 2629 if (!FLAG_inline_new) heap_.DisableInlineAllocation(); 2630 2631 return true; 2632 } 2633 2634 2635 // Initialized lazily to allow early 2636 // v8::V8::SetAddHistogramSampleFunction calls. 2637 StatsTable* Isolate::stats_table() { 2638 if (stats_table_ == NULL) { 2639 stats_table_ = new StatsTable; 2640 } 2641 return stats_table_; 2642 } 2643 2644 2645 void Isolate::Enter() { 2646 Isolate* current_isolate = NULL; 2647 PerIsolateThreadData* current_data = CurrentPerIsolateThreadData(); 2648 if (current_data != NULL) { 2649 current_isolate = current_data->isolate_; 2650 DCHECK(current_isolate != NULL); 2651 if (current_isolate == this) { 2652 DCHECK(Current() == this); 2653 DCHECK(entry_stack_ != NULL); 2654 DCHECK(entry_stack_->previous_thread_data == NULL || 2655 entry_stack_->previous_thread_data->thread_id().Equals( 2656 ThreadId::Current())); 2657 // Same thread re-enters the isolate, no need to re-init anything. 2658 entry_stack_->entry_count++; 2659 return; 2660 } 2661 } 2662 2663 PerIsolateThreadData* data = FindOrAllocatePerThreadDataForThisThread(); 2664 DCHECK(data != NULL); 2665 DCHECK(data->isolate_ == this); 2666 2667 EntryStackItem* item = new EntryStackItem(current_data, 2668 current_isolate, 2669 entry_stack_); 2670 entry_stack_ = item; 2671 2672 SetIsolateThreadLocals(this, data); 2673 2674 // In case it's the first time some thread enters the isolate. 2675 set_thread_id(data->thread_id()); 2676 } 2677 2678 2679 void Isolate::Exit() { 2680 DCHECK(entry_stack_ != NULL); 2681 DCHECK(entry_stack_->previous_thread_data == NULL || 2682 entry_stack_->previous_thread_data->thread_id().Equals( 2683 ThreadId::Current())); 2684 2685 if (--entry_stack_->entry_count > 0) return; 2686 2687 DCHECK(CurrentPerIsolateThreadData() != NULL); 2688 DCHECK(CurrentPerIsolateThreadData()->isolate_ == this); 2689 2690 // Pop the stack. 2691 EntryStackItem* item = entry_stack_; 2692 entry_stack_ = item->previous_item; 2693 2694 PerIsolateThreadData* previous_thread_data = item->previous_thread_data; 2695 Isolate* previous_isolate = item->previous_isolate; 2696 2697 delete item; 2698 2699 // Reinit the current thread for the isolate it was running before this one. 2700 SetIsolateThreadLocals(previous_isolate, previous_thread_data); 2701 } 2702 2703 2704 void Isolate::LinkDeferredHandles(DeferredHandles* deferred) { 2705 deferred->next_ = deferred_handles_head_; 2706 if (deferred_handles_head_ != NULL) { 2707 deferred_handles_head_->previous_ = deferred; 2708 } 2709 deferred_handles_head_ = deferred; 2710 } 2711 2712 2713 void Isolate::UnlinkDeferredHandles(DeferredHandles* deferred) { 2714 #ifdef DEBUG 2715 // In debug mode assert that the linked list is well-formed. 2716 DeferredHandles* deferred_iterator = deferred; 2717 while (deferred_iterator->previous_ != NULL) { 2718 deferred_iterator = deferred_iterator->previous_; 2719 } 2720 DCHECK(deferred_handles_head_ == deferred_iterator); 2721 #endif 2722 if (deferred_handles_head_ == deferred) { 2723 deferred_handles_head_ = deferred_handles_head_->next_; 2724 } 2725 if (deferred->next_ != NULL) { 2726 deferred->next_->previous_ = deferred->previous_; 2727 } 2728 if (deferred->previous_ != NULL) { 2729 deferred->previous_->next_ = deferred->next_; 2730 } 2731 } 2732 2733 2734 void Isolate::DumpAndResetCompilationStats() { 2735 if (turbo_statistics() != nullptr) { 2736 DCHECK(FLAG_turbo_stats || FLAG_turbo_stats_nvp); 2737 2738 OFStream os(stdout); 2739 if (FLAG_turbo_stats) { 2740 AsPrintableStatistics ps = {*turbo_statistics(), false}; 2741 os << ps << std::endl; 2742 } 2743 if (FLAG_turbo_stats_nvp) { 2744 AsPrintableStatistics ps = {*turbo_statistics(), true}; 2745 os << ps << std::endl; 2746 } 2747 } 2748 if (hstatistics() != nullptr) hstatistics()->Print(); 2749 delete turbo_statistics_; 2750 turbo_statistics_ = nullptr; 2751 delete hstatistics_; 2752 hstatistics_ = nullptr; 2753 if (V8_UNLIKELY(FLAG_runtime_stats == 2754 v8::tracing::TracingCategoryObserver::ENABLED_BY_NATIVE)) { 2755 OFStream os(stdout); 2756 counters()->runtime_call_stats()->Print(os); 2757 counters()->runtime_call_stats()->Reset(); 2758 } 2759 } 2760 2761 2762 HStatistics* Isolate::GetHStatistics() { 2763 if (hstatistics() == NULL) set_hstatistics(new HStatistics()); 2764 return hstatistics(); 2765 } 2766 2767 2768 CompilationStatistics* Isolate::GetTurboStatistics() { 2769 if (turbo_statistics() == NULL) 2770 set_turbo_statistics(new CompilationStatistics()); 2771 return turbo_statistics(); 2772 } 2773 2774 2775 HTracer* Isolate::GetHTracer() { 2776 if (htracer() == NULL) set_htracer(new HTracer(id())); 2777 return htracer(); 2778 } 2779 2780 2781 CodeTracer* Isolate::GetCodeTracer() { 2782 if (code_tracer() == NULL) set_code_tracer(new CodeTracer(id())); 2783 return code_tracer(); 2784 } 2785 2786 Map* Isolate::get_initial_js_array_map(ElementsKind kind) { 2787 if (IsFastElementsKind(kind)) { 2788 DisallowHeapAllocation no_gc; 2789 Object* const initial_js_array_map = 2790 context()->native_context()->get(Context::ArrayMapIndex(kind)); 2791 if (!initial_js_array_map->IsUndefined(this)) { 2792 return Map::cast(initial_js_array_map); 2793 } 2794 } 2795 return nullptr; 2796 } 2797 2798 2799 bool Isolate::use_crankshaft() const { 2800 return FLAG_crankshaft && 2801 !serializer_enabled_ && 2802 CpuFeatures::SupportsCrankshaft(); 2803 } 2804 2805 bool Isolate::IsArrayOrObjectPrototype(Object* object) { 2806 Object* context = heap()->native_contexts_list(); 2807 while (!context->IsUndefined(this)) { 2808 Context* current_context = Context::cast(context); 2809 if (current_context->initial_object_prototype() == object || 2810 current_context->initial_array_prototype() == object) { 2811 return true; 2812 } 2813 context = current_context->next_context_link(); 2814 } 2815 return false; 2816 } 2817 2818 bool Isolate::IsInAnyContext(Object* object, uint32_t index) { 2819 DisallowHeapAllocation no_gc; 2820 Object* context = heap()->native_contexts_list(); 2821 while (!context->IsUndefined(this)) { 2822 Context* current_context = Context::cast(context); 2823 if (current_context->get(index) == object) { 2824 return true; 2825 } 2826 context = current_context->next_context_link(); 2827 } 2828 return false; 2829 } 2830 2831 bool Isolate::IsFastArrayConstructorPrototypeChainIntact() { 2832 PropertyCell* no_elements_cell = heap()->array_protector(); 2833 bool cell_reports_intact = 2834 no_elements_cell->value()->IsSmi() && 2835 Smi::cast(no_elements_cell->value())->value() == kProtectorValid; 2836 2837 #ifdef DEBUG 2838 Map* root_array_map = 2839 get_initial_js_array_map(GetInitialFastElementsKind()); 2840 Context* native_context = context()->native_context(); 2841 JSObject* initial_array_proto = JSObject::cast( 2842 native_context->get(Context::INITIAL_ARRAY_PROTOTYPE_INDEX)); 2843 JSObject* initial_object_proto = JSObject::cast( 2844 native_context->get(Context::INITIAL_OBJECT_PROTOTYPE_INDEX)); 2845 2846 if (root_array_map == NULL || initial_array_proto == initial_object_proto) { 2847 // We are in the bootstrapping process, and the entire check sequence 2848 // shouldn't be performed. 2849 return cell_reports_intact; 2850 } 2851 2852 // Check that the array prototype hasn't been altered WRT empty elements. 2853 if (root_array_map->prototype() != initial_array_proto) { 2854 DCHECK_EQ(false, cell_reports_intact); 2855 return cell_reports_intact; 2856 } 2857 2858 FixedArrayBase* elements = initial_array_proto->elements(); 2859 if (elements != heap()->empty_fixed_array() && 2860 elements != heap()->empty_slow_element_dictionary()) { 2861 DCHECK_EQ(false, cell_reports_intact); 2862 return cell_reports_intact; 2863 } 2864 2865 // Check that the object prototype hasn't been altered WRT empty elements. 2866 PrototypeIterator iter(this, initial_array_proto); 2867 if (iter.IsAtEnd() || iter.GetCurrent() != initial_object_proto) { 2868 DCHECK_EQ(false, cell_reports_intact); 2869 return cell_reports_intact; 2870 } 2871 2872 elements = initial_object_proto->elements(); 2873 if (elements != heap()->empty_fixed_array() && 2874 elements != heap()->empty_slow_element_dictionary()) { 2875 DCHECK_EQ(false, cell_reports_intact); 2876 return cell_reports_intact; 2877 } 2878 2879 iter.Advance(); 2880 if (!iter.IsAtEnd()) { 2881 DCHECK_EQ(false, cell_reports_intact); 2882 return cell_reports_intact; 2883 } 2884 2885 #endif 2886 2887 return cell_reports_intact; 2888 } 2889 2890 bool Isolate::IsIsConcatSpreadableLookupChainIntact() { 2891 Cell* is_concat_spreadable_cell = heap()->is_concat_spreadable_protector(); 2892 bool is_is_concat_spreadable_set = 2893 Smi::cast(is_concat_spreadable_cell->value())->value() == 2894 kProtectorInvalid; 2895 #ifdef DEBUG 2896 Map* root_array_map = get_initial_js_array_map(GetInitialFastElementsKind()); 2897 if (root_array_map == NULL) { 2898 // Ignore the value of is_concat_spreadable during bootstrap. 2899 return !is_is_concat_spreadable_set; 2900 } 2901 Handle<Object> array_prototype(array_function()->prototype(), this); 2902 Handle<Symbol> key = factory()->is_concat_spreadable_symbol(); 2903 Handle<Object> value; 2904 LookupIterator it(array_prototype, key); 2905 if (it.IsFound() && !JSReceiver::GetDataProperty(&it)->IsUndefined(this)) { 2906 // TODO(cbruni): Currently we do not revert if we unset the 2907 // @@isConcatSpreadable property on Array.prototype or Object.prototype 2908 // hence the reverse implication doesn't hold. 2909 DCHECK(is_is_concat_spreadable_set); 2910 return false; 2911 } 2912 #endif // DEBUG 2913 2914 return !is_is_concat_spreadable_set; 2915 } 2916 2917 bool Isolate::IsIsConcatSpreadableLookupChainIntact(JSReceiver* receiver) { 2918 if (!IsIsConcatSpreadableLookupChainIntact()) return false; 2919 return !receiver->HasProxyInPrototype(this); 2920 } 2921 2922 void Isolate::UpdateArrayProtectorOnSetElement(Handle<JSObject> object) { 2923 DisallowHeapAllocation no_gc; 2924 if (!object->map()->is_prototype_map()) return; 2925 if (!IsFastArrayConstructorPrototypeChainIntact()) return; 2926 if (!IsArrayOrObjectPrototype(*object)) return; 2927 PropertyCell::SetValueWithInvalidation( 2928 factory()->array_protector(), 2929 handle(Smi::FromInt(kProtectorInvalid), this)); 2930 } 2931 2932 void Isolate::InvalidateHasInstanceProtector() { 2933 DCHECK(factory()->has_instance_protector()->value()->IsSmi()); 2934 DCHECK(IsHasInstanceLookupChainIntact()); 2935 PropertyCell::SetValueWithInvalidation( 2936 factory()->has_instance_protector(), 2937 handle(Smi::FromInt(kProtectorInvalid), this)); 2938 DCHECK(!IsHasInstanceLookupChainIntact()); 2939 } 2940 2941 void Isolate::InvalidateIsConcatSpreadableProtector() { 2942 DCHECK(factory()->is_concat_spreadable_protector()->value()->IsSmi()); 2943 DCHECK(IsIsConcatSpreadableLookupChainIntact()); 2944 factory()->is_concat_spreadable_protector()->set_value( 2945 Smi::FromInt(kProtectorInvalid)); 2946 DCHECK(!IsIsConcatSpreadableLookupChainIntact()); 2947 } 2948 2949 void Isolate::InvalidateArraySpeciesProtector() { 2950 DCHECK(factory()->species_protector()->value()->IsSmi()); 2951 DCHECK(IsArraySpeciesLookupChainIntact()); 2952 factory()->species_protector()->set_value(Smi::FromInt(kProtectorInvalid)); 2953 DCHECK(!IsArraySpeciesLookupChainIntact()); 2954 } 2955 2956 void Isolate::InvalidateStringLengthOverflowProtector() { 2957 DCHECK(factory()->string_length_protector()->value()->IsSmi()); 2958 DCHECK(IsStringLengthOverflowIntact()); 2959 PropertyCell::SetValueWithInvalidation( 2960 factory()->string_length_protector(), 2961 handle(Smi::FromInt(kProtectorInvalid), this)); 2962 DCHECK(!IsStringLengthOverflowIntact()); 2963 } 2964 2965 void Isolate::InvalidateArrayIteratorProtector() { 2966 DCHECK(factory()->array_iterator_protector()->value()->IsSmi()); 2967 DCHECK(IsArrayIteratorLookupChainIntact()); 2968 factory()->array_iterator_protector()->set_value( 2969 Smi::FromInt(kProtectorInvalid)); 2970 DCHECK(!IsArrayIteratorLookupChainIntact()); 2971 } 2972 2973 bool Isolate::IsAnyInitialArrayPrototype(Handle<JSArray> array) { 2974 DisallowHeapAllocation no_gc; 2975 return IsInAnyContext(*array, Context::INITIAL_ARRAY_PROTOTYPE_INDEX); 2976 } 2977 2978 2979 CallInterfaceDescriptorData* Isolate::call_descriptor_data(int index) { 2980 DCHECK(0 <= index && index < CallDescriptors::NUMBER_OF_DESCRIPTORS); 2981 return &call_descriptor_data_[index]; 2982 } 2983 2984 2985 base::RandomNumberGenerator* Isolate::random_number_generator() { 2986 if (random_number_generator_ == NULL) { 2987 if (FLAG_random_seed != 0) { 2988 random_number_generator_ = 2989 new base::RandomNumberGenerator(FLAG_random_seed); 2990 } else { 2991 random_number_generator_ = new base::RandomNumberGenerator(); 2992 } 2993 } 2994 return random_number_generator_; 2995 } 2996 2997 int Isolate::GenerateIdentityHash(uint32_t mask) { 2998 int hash; 2999 int attempts = 0; 3000 do { 3001 hash = random_number_generator()->NextInt() & mask; 3002 } while (hash == 0 && attempts++ < 30); 3003 return hash != 0 ? hash : 1; 3004 } 3005 3006 Object* Isolate::FindCodeObject(Address a) { 3007 return inner_pointer_to_code_cache()->GcSafeFindCodeForInnerPointer(a); 3008 } 3009 3010 3011 #ifdef DEBUG 3012 #define ISOLATE_FIELD_OFFSET(type, name, ignored) \ 3013 const intptr_t Isolate::name##_debug_offset_ = OFFSET_OF(Isolate, name##_); 3014 ISOLATE_INIT_LIST(ISOLATE_FIELD_OFFSET) 3015 ISOLATE_INIT_ARRAY_LIST(ISOLATE_FIELD_OFFSET) 3016 #undef ISOLATE_FIELD_OFFSET 3017 #endif 3018 3019 3020 Handle<JSObject> Isolate::SetUpSubregistry(Handle<JSObject> registry, 3021 Handle<Map> map, const char* cname) { 3022 Handle<String> name = factory()->InternalizeUtf8String(cname); 3023 Handle<JSObject> obj = factory()->NewJSObjectFromMap(map); 3024 JSObject::NormalizeProperties(obj, CLEAR_INOBJECT_PROPERTIES, 0, 3025 "SetupSymbolRegistry"); 3026 JSObject::AddProperty(registry, name, obj, NONE); 3027 return obj; 3028 } 3029 3030 3031 Handle<JSObject> Isolate::GetSymbolRegistry() { 3032 if (heap()->symbol_registry()->IsSmi()) { 3033 Handle<Map> map = factory()->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize); 3034 Handle<JSObject> registry = factory()->NewJSObjectFromMap(map); 3035 heap()->set_symbol_registry(*registry); 3036 3037 SetUpSubregistry(registry, map, "for"); 3038 SetUpSubregistry(registry, map, "for_api"); 3039 SetUpSubregistry(registry, map, "keyFor"); 3040 SetUpSubregistry(registry, map, "private_api"); 3041 } 3042 return Handle<JSObject>::cast(factory()->symbol_registry()); 3043 } 3044 3045 3046 void Isolate::AddBeforeCallEnteredCallback(BeforeCallEnteredCallback callback) { 3047 for (int i = 0; i < before_call_entered_callbacks_.length(); i++) { 3048 if (callback == before_call_entered_callbacks_.at(i)) return; 3049 } 3050 before_call_entered_callbacks_.Add(callback); 3051 } 3052 3053 3054 void Isolate::RemoveBeforeCallEnteredCallback( 3055 BeforeCallEnteredCallback callback) { 3056 for (int i = 0; i < before_call_entered_callbacks_.length(); i++) { 3057 if (callback == before_call_entered_callbacks_.at(i)) { 3058 before_call_entered_callbacks_.Remove(i); 3059 } 3060 } 3061 } 3062 3063 3064 void Isolate::AddCallCompletedCallback(CallCompletedCallback callback) { 3065 for (int i = 0; i < call_completed_callbacks_.length(); i++) { 3066 if (callback == call_completed_callbacks_.at(i)) return; 3067 } 3068 call_completed_callbacks_.Add(callback); 3069 } 3070 3071 3072 void Isolate::RemoveCallCompletedCallback(CallCompletedCallback callback) { 3073 for (int i = 0; i < call_completed_callbacks_.length(); i++) { 3074 if (callback == call_completed_callbacks_.at(i)) { 3075 call_completed_callbacks_.Remove(i); 3076 } 3077 } 3078 } 3079 3080 3081 void Isolate::FireCallCompletedCallback() { 3082 if (!handle_scope_implementer()->CallDepthIsZero()) return; 3083 3084 bool run_microtasks = 3085 pending_microtask_count() && 3086 !handle_scope_implementer()->HasMicrotasksSuppressions() && 3087 handle_scope_implementer()->microtasks_policy() == 3088 v8::MicrotasksPolicy::kAuto; 3089 3090 if (run_microtasks) RunMicrotasks(); 3091 // Prevent stepping from spilling into the next call made by the embedder. 3092 if (debug()->is_active()) debug()->ClearStepping(); 3093 3094 if (call_completed_callbacks_.is_empty()) return; 3095 // Fire callbacks. Increase call depth to prevent recursive callbacks. 3096 v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(this); 3097 v8::Isolate::SuppressMicrotaskExecutionScope suppress(isolate); 3098 for (int i = 0; i < call_completed_callbacks_.length(); i++) { 3099 call_completed_callbacks_.at(i)(isolate); 3100 } 3101 } 3102 3103 3104 void Isolate::SetPromiseRejectCallback(PromiseRejectCallback callback) { 3105 promise_reject_callback_ = callback; 3106 } 3107 3108 3109 void Isolate::ReportPromiseReject(Handle<JSObject> promise, 3110 Handle<Object> value, 3111 v8::PromiseRejectEvent event) { 3112 if (promise_reject_callback_ == NULL) return; 3113 Handle<JSArray> stack_trace; 3114 if (event == v8::kPromiseRejectWithNoHandler && value->IsJSObject()) { 3115 stack_trace = GetDetailedStackTrace(Handle<JSObject>::cast(value)); 3116 } 3117 promise_reject_callback_(v8::PromiseRejectMessage( 3118 v8::Utils::PromiseToLocal(promise), event, v8::Utils::ToLocal(value), 3119 v8::Utils::StackTraceToLocal(stack_trace))); 3120 } 3121 3122 namespace { 3123 class PromiseDebugEventScope { 3124 public: 3125 PromiseDebugEventScope(Isolate* isolate, Object* id, Object* name) 3126 : isolate_(isolate), 3127 id_(id, isolate_), 3128 name_(name, isolate_), 3129 is_debug_active_(isolate_->debug()->is_active() && id_->IsNumber() && 3130 name_->IsString()) { 3131 if (is_debug_active_) { 3132 isolate_->debug()->OnAsyncTaskEvent( 3133 isolate_->factory()->will_handle_string(), id_, 3134 Handle<String>::cast(name_)); 3135 } 3136 } 3137 3138 ~PromiseDebugEventScope() { 3139 if (is_debug_active_) { 3140 isolate_->debug()->OnAsyncTaskEvent( 3141 isolate_->factory()->did_handle_string(), id_, 3142 Handle<String>::cast(name_)); 3143 } 3144 } 3145 3146 private: 3147 Isolate* isolate_; 3148 Handle<Object> id_; 3149 Handle<Object> name_; 3150 bool is_debug_active_; 3151 }; 3152 } // namespace 3153 3154 void Isolate::PromiseReactionJob(Handle<PromiseReactionJobInfo> info, 3155 MaybeHandle<Object>* result, 3156 MaybeHandle<Object>* maybe_exception) { 3157 PromiseDebugEventScope helper(this, info->debug_id(), info->debug_name()); 3158 3159 Handle<Object> value(info->value(), this); 3160 Handle<Object> tasks(info->tasks(), this); 3161 Handle<JSFunction> promise_handle_fn = promise_handle(); 3162 Handle<Object> undefined = factory()->undefined_value(); 3163 3164 // If tasks is an array we have multiple onFulfilled/onRejected callbacks 3165 // associated with the promise. The deferred object for each callback 3166 // is attached to this array as well. 3167 // Otherwise, there is a single callback and the deferred object is attached 3168 // directly to PromiseReactionJobInfo. 3169 if (tasks->IsJSArray()) { 3170 Handle<JSArray> array = Handle<JSArray>::cast(tasks); 3171 DCHECK(array->length()->IsSmi()); 3172 int length = Smi::cast(array->length())->value(); 3173 ElementsAccessor* accessor = array->GetElementsAccessor(); 3174 DCHECK(length % 2 == 0); 3175 for (int i = 0; i < length; i += 2) { 3176 DCHECK(accessor->HasElement(array, i)); 3177 DCHECK(accessor->HasElement(array, i + 1)); 3178 Handle<Object> argv[] = {value, accessor->Get(array, i), 3179 accessor->Get(array, i + 1)}; 3180 *result = Execution::TryCall(this, promise_handle_fn, undefined, 3181 arraysize(argv), argv, maybe_exception); 3182 // If execution is terminating, just bail out. 3183 if (result->is_null() && maybe_exception->is_null()) { 3184 return; 3185 } 3186 } 3187 } else { 3188 Handle<Object> deferred(info->deferred(), this); 3189 Handle<Object> argv[] = {value, tasks, deferred}; 3190 *result = Execution::TryCall(this, promise_handle_fn, undefined, 3191 arraysize(argv), argv, maybe_exception); 3192 } 3193 } 3194 3195 void Isolate::PromiseResolveThenableJob( 3196 Handle<PromiseResolveThenableJobInfo> info, MaybeHandle<Object>* result, 3197 MaybeHandle<Object>* maybe_exception) { 3198 PromiseDebugEventScope helper(this, info->debug_id(), info->debug_name()); 3199 3200 Handle<JSReceiver> thenable(info->thenable(), this); 3201 Handle<JSFunction> resolve(info->resolve(), this); 3202 Handle<JSFunction> reject(info->reject(), this); 3203 Handle<JSReceiver> then(info->then(), this); 3204 Handle<Object> argv[] = {resolve, reject}; 3205 *result = Execution::TryCall(this, then, thenable, arraysize(argv), argv, 3206 maybe_exception); 3207 3208 Handle<Object> reason; 3209 if (maybe_exception->ToHandle(&reason)) { 3210 DCHECK(result->is_null()); 3211 Handle<Object> reason_arg[] = {reason}; 3212 *result = 3213 Execution::TryCall(this, reject, factory()->undefined_value(), 3214 arraysize(reason_arg), reason_arg, maybe_exception); 3215 } 3216 } 3217 3218 void Isolate::EnqueueMicrotask(Handle<Object> microtask) { 3219 DCHECK(microtask->IsJSFunction() || microtask->IsCallHandlerInfo() || 3220 microtask->IsPromiseResolveThenableJobInfo() || 3221 microtask->IsPromiseReactionJobInfo()); 3222 Handle<FixedArray> queue(heap()->microtask_queue(), this); 3223 int num_tasks = pending_microtask_count(); 3224 DCHECK(num_tasks <= queue->length()); 3225 if (num_tasks == 0) { 3226 queue = factory()->NewFixedArray(8); 3227 heap()->set_microtask_queue(*queue); 3228 } else if (num_tasks == queue->length()) { 3229 queue = factory()->CopyFixedArrayAndGrow(queue, num_tasks); 3230 heap()->set_microtask_queue(*queue); 3231 } 3232 DCHECK(queue->get(num_tasks)->IsUndefined(this)); 3233 queue->set(num_tasks, *microtask); 3234 set_pending_microtask_count(num_tasks + 1); 3235 } 3236 3237 3238 void Isolate::RunMicrotasks() { 3239 // Increase call depth to prevent recursive callbacks. 3240 v8::Isolate::SuppressMicrotaskExecutionScope suppress( 3241 reinterpret_cast<v8::Isolate*>(this)); 3242 is_running_microtasks_ = true; 3243 RunMicrotasksInternal(); 3244 is_running_microtasks_ = false; 3245 FireMicrotasksCompletedCallback(); 3246 } 3247 3248 3249 void Isolate::RunMicrotasksInternal() { 3250 if (!pending_microtask_count()) return; 3251 TRACE_EVENT0("v8.execute", "RunMicrotasks"); 3252 while (pending_microtask_count() > 0) { 3253 HandleScope scope(this); 3254 int num_tasks = pending_microtask_count(); 3255 Handle<FixedArray> queue(heap()->microtask_queue(), this); 3256 DCHECK(num_tasks <= queue->length()); 3257 set_pending_microtask_count(0); 3258 heap()->set_microtask_queue(heap()->empty_fixed_array()); 3259 3260 Isolate* isolate = this; 3261 FOR_WITH_HANDLE_SCOPE(isolate, int, i = 0, i, i < num_tasks, i++, { 3262 Handle<Object> microtask(queue->get(i), this); 3263 3264 if (microtask->IsCallHandlerInfo()) { 3265 Handle<CallHandlerInfo> callback_info = 3266 Handle<CallHandlerInfo>::cast(microtask); 3267 v8::MicrotaskCallback callback = 3268 v8::ToCData<v8::MicrotaskCallback>(callback_info->callback()); 3269 void* data = v8::ToCData<void*>(callback_info->data()); 3270 callback(data); 3271 } else { 3272 SaveContext save(this); 3273 Context* context; 3274 if (microtask->IsJSFunction()) { 3275 context = Handle<JSFunction>::cast(microtask)->context(); 3276 } else if (microtask->IsPromiseResolveThenableJobInfo()) { 3277 context = 3278 Handle<PromiseResolveThenableJobInfo>::cast(microtask)->context(); 3279 } else { 3280 context = Handle<PromiseReactionJobInfo>::cast(microtask)->context(); 3281 } 3282 3283 set_context(context->native_context()); 3284 handle_scope_implementer_->EnterMicrotaskContext( 3285 Handle<Context>(context, this)); 3286 3287 MaybeHandle<Object> result; 3288 MaybeHandle<Object> maybe_exception; 3289 3290 if (microtask->IsJSFunction()) { 3291 Handle<JSFunction> microtask_function = 3292 Handle<JSFunction>::cast(microtask); 3293 result = Execution::TryCall(this, microtask_function, 3294 factory()->undefined_value(), 0, NULL, 3295 &maybe_exception); 3296 } else if (microtask->IsPromiseResolveThenableJobInfo()) { 3297 PromiseResolveThenableJob( 3298 Handle<PromiseResolveThenableJobInfo>::cast(microtask), &result, 3299 &maybe_exception); 3300 } else { 3301 PromiseReactionJob(Handle<PromiseReactionJobInfo>::cast(microtask), 3302 &result, &maybe_exception); 3303 } 3304 3305 handle_scope_implementer_->LeaveMicrotaskContext(); 3306 3307 // If execution is terminating, just bail out. 3308 if (result.is_null() && maybe_exception.is_null()) { 3309 // Clear out any remaining callbacks in the queue. 3310 heap()->set_microtask_queue(heap()->empty_fixed_array()); 3311 set_pending_microtask_count(0); 3312 return; 3313 } 3314 } 3315 }); 3316 } 3317 } 3318 3319 3320 void Isolate::AddMicrotasksCompletedCallback( 3321 MicrotasksCompletedCallback callback) { 3322 for (int i = 0; i < microtasks_completed_callbacks_.length(); i++) { 3323 if (callback == microtasks_completed_callbacks_.at(i)) return; 3324 } 3325 microtasks_completed_callbacks_.Add(callback); 3326 } 3327 3328 3329 void Isolate::RemoveMicrotasksCompletedCallback( 3330 MicrotasksCompletedCallback callback) { 3331 for (int i = 0; i < microtasks_completed_callbacks_.length(); i++) { 3332 if (callback == microtasks_completed_callbacks_.at(i)) { 3333 microtasks_completed_callbacks_.Remove(i); 3334 } 3335 } 3336 } 3337 3338 3339 void Isolate::FireMicrotasksCompletedCallback() { 3340 for (int i = 0; i < microtasks_completed_callbacks_.length(); i++) { 3341 microtasks_completed_callbacks_.at(i)(reinterpret_cast<v8::Isolate*>(this)); 3342 } 3343 } 3344 3345 3346 void Isolate::SetUseCounterCallback(v8::Isolate::UseCounterCallback callback) { 3347 DCHECK(!use_counter_callback_); 3348 use_counter_callback_ = callback; 3349 } 3350 3351 3352 void Isolate::CountUsage(v8::Isolate::UseCounterFeature feature) { 3353 // The counter callback may cause the embedder to call into V8, which is not 3354 // generally possible during GC. 3355 if (heap_.gc_state() == Heap::NOT_IN_GC) { 3356 if (use_counter_callback_) { 3357 HandleScope handle_scope(this); 3358 use_counter_callback_(reinterpret_cast<v8::Isolate*>(this), feature); 3359 } 3360 } else { 3361 heap_.IncrementDeferredCount(feature); 3362 } 3363 } 3364 3365 3366 BasicBlockProfiler* Isolate::GetOrCreateBasicBlockProfiler() { 3367 if (basic_block_profiler_ == NULL) { 3368 basic_block_profiler_ = new BasicBlockProfiler(); 3369 } 3370 return basic_block_profiler_; 3371 } 3372 3373 3374 std::string Isolate::GetTurboCfgFileName() { 3375 if (FLAG_trace_turbo_cfg_file == NULL) { 3376 std::ostringstream os; 3377 os << "turbo-" << base::OS::GetCurrentProcessId() << "-" << id() << ".cfg"; 3378 return os.str(); 3379 } else { 3380 return FLAG_trace_turbo_cfg_file; 3381 } 3382 } 3383 3384 void Isolate::SetTailCallEliminationEnabled(bool enabled) { 3385 if (is_tail_call_elimination_enabled_ == enabled) return; 3386 is_tail_call_elimination_enabled_ = enabled; 3387 // TODO(ishell): Introduce DependencyGroup::kTailCallChangedGroup to 3388 // deoptimize only those functions that are affected by the change of this 3389 // flag. 3390 internal::Deoptimizer::DeoptimizeAll(this); 3391 } 3392 3393 // Heap::detached_contexts tracks detached contexts as pairs 3394 // (number of GC since the context was detached, the context). 3395 void Isolate::AddDetachedContext(Handle<Context> context) { 3396 HandleScope scope(this); 3397 Handle<WeakCell> cell = factory()->NewWeakCell(context); 3398 Handle<FixedArray> detached_contexts = factory()->detached_contexts(); 3399 int length = detached_contexts->length(); 3400 detached_contexts = factory()->CopyFixedArrayAndGrow(detached_contexts, 2); 3401 detached_contexts->set(length, Smi::kZero); 3402 detached_contexts->set(length + 1, *cell); 3403 heap()->set_detached_contexts(*detached_contexts); 3404 } 3405 3406 3407 void Isolate::CheckDetachedContextsAfterGC() { 3408 HandleScope scope(this); 3409 Handle<FixedArray> detached_contexts = factory()->detached_contexts(); 3410 int length = detached_contexts->length(); 3411 if (length == 0) return; 3412 int new_length = 0; 3413 for (int i = 0; i < length; i += 2) { 3414 int mark_sweeps = Smi::cast(detached_contexts->get(i))->value(); 3415 DCHECK(detached_contexts->get(i + 1)->IsWeakCell()); 3416 WeakCell* cell = WeakCell::cast(detached_contexts->get(i + 1)); 3417 if (!cell->cleared()) { 3418 detached_contexts->set(new_length, Smi::FromInt(mark_sweeps + 1)); 3419 detached_contexts->set(new_length + 1, cell); 3420 new_length += 2; 3421 } 3422 counters()->detached_context_age_in_gc()->AddSample(mark_sweeps + 1); 3423 } 3424 if (FLAG_trace_detached_contexts) { 3425 PrintF("%d detached contexts are collected out of %d\n", 3426 length - new_length, length); 3427 for (int i = 0; i < new_length; i += 2) { 3428 int mark_sweeps = Smi::cast(detached_contexts->get(i))->value(); 3429 DCHECK(detached_contexts->get(i + 1)->IsWeakCell()); 3430 WeakCell* cell = WeakCell::cast(detached_contexts->get(i + 1)); 3431 if (mark_sweeps > 3) { 3432 PrintF("detached context %p\n survived %d GCs (leak?)\n", 3433 static_cast<void*>(cell->value()), mark_sweeps); 3434 } 3435 } 3436 } 3437 if (new_length == 0) { 3438 heap()->set_detached_contexts(heap()->empty_fixed_array()); 3439 } else if (new_length < length) { 3440 heap()->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>( 3441 *detached_contexts, length - new_length); 3442 } 3443 } 3444 3445 void Isolate::SetRAILMode(RAILMode rail_mode) { 3446 rail_mode_.SetValue(rail_mode); 3447 if (FLAG_trace_rail) { 3448 PrintIsolate(this, "RAIL mode: %s\n", RAILModeName(rail_mode)); 3449 } 3450 } 3451 3452 void Isolate::IsolateInBackgroundNotification() { 3453 is_isolate_in_background_ = true; 3454 heap()->ActivateMemoryReducerIfNeeded(); 3455 } 3456 3457 void Isolate::IsolateInForegroundNotification() { 3458 is_isolate_in_background_ = false; 3459 } 3460 3461 void Isolate::PrintWithTimestamp(const char* format, ...) { 3462 base::OS::Print("[%d:%p] %8.0f ms: ", base::OS::GetCurrentProcessId(), 3463 static_cast<void*>(this), time_millis_since_init()); 3464 va_list arguments; 3465 va_start(arguments, format); 3466 base::OS::VPrint(format, arguments); 3467 va_end(arguments); 3468 } 3469 3470 bool StackLimitCheck::JsHasOverflowed(uintptr_t gap) const { 3471 StackGuard* stack_guard = isolate_->stack_guard(); 3472 #ifdef USE_SIMULATOR 3473 // The simulator uses a separate JS stack. 3474 Address jssp_address = Simulator::current(isolate_)->get_sp(); 3475 uintptr_t jssp = reinterpret_cast<uintptr_t>(jssp_address); 3476 if (jssp - gap < stack_guard->real_jslimit()) return true; 3477 #endif // USE_SIMULATOR 3478 return GetCurrentStackPosition() - gap < stack_guard->real_climit(); 3479 } 3480 3481 SaveContext::SaveContext(Isolate* isolate) 3482 : isolate_(isolate), prev_(isolate->save_context()) { 3483 if (isolate->context() != NULL) { 3484 context_ = Handle<Context>(isolate->context()); 3485 } 3486 isolate->set_save_context(this); 3487 3488 c_entry_fp_ = isolate->c_entry_fp(isolate->thread_local_top()); 3489 } 3490 3491 SaveContext::~SaveContext() { 3492 isolate_->set_context(context_.is_null() ? NULL : *context_); 3493 isolate_->set_save_context(prev_); 3494 } 3495 3496 #ifdef DEBUG 3497 AssertNoContextChange::AssertNoContextChange(Isolate* isolate) 3498 : isolate_(isolate), context_(isolate->context(), isolate) {} 3499 #endif // DEBUG 3500 3501 3502 bool PostponeInterruptsScope::Intercept(StackGuard::InterruptFlag flag) { 3503 // First check whether the previous scope intercepts. 3504 if (prev_ && prev_->Intercept(flag)) return true; 3505 // Then check whether this scope intercepts. 3506 if ((flag & intercept_mask_)) { 3507 intercepted_flags_ |= flag; 3508 return true; 3509 } 3510 return false; 3511 } 3512 3513 } // namespace internal 3514 } // namespace v8 3515