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