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