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