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