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 #ifndef V8_ISOLATE_H_ 29 #define V8_ISOLATE_H_ 30 31 #include "../include/v8-debug.h" 32 #include "allocation.h" 33 #include "apiutils.h" 34 #include "assert-scope.h" 35 #include "atomicops.h" 36 #include "builtins.h" 37 #include "contexts.h" 38 #include "execution.h" 39 #include "frames.h" 40 #include "date.h" 41 #include "global-handles.h" 42 #include "handles.h" 43 #include "hashmap.h" 44 #include "heap.h" 45 #include "optimizing-compiler-thread.h" 46 #include "regexp-stack.h" 47 #include "runtime-profiler.h" 48 #include "runtime.h" 49 #include "zone.h" 50 51 namespace v8 { 52 namespace internal { 53 54 class Bootstrapper; 55 class CodeGenerator; 56 class CodeRange; 57 struct CodeStubInterfaceDescriptor; 58 class CodeTracer; 59 class CompilationCache; 60 class ContextSlotCache; 61 class Counters; 62 class CpuFeatures; 63 class CpuProfiler; 64 class DeoptimizerData; 65 class Deserializer; 66 class EmptyStatement; 67 class ExternalCallbackScope; 68 class ExternalReferenceTable; 69 class Factory; 70 class FunctionInfoListener; 71 class HandleScopeImplementer; 72 class HeapProfiler; 73 class HStatistics; 74 class HTracer; 75 class InlineRuntimeFunctionsTable; 76 class NoAllocationStringAllocator; 77 class InnerPointerToCodeCache; 78 class RandomNumberGenerator; 79 class RegExpStack; 80 class SaveContext; 81 class UnicodeCache; 82 class ConsStringIteratorOp; 83 class StringTracker; 84 class StubCache; 85 class SweeperThread; 86 class ThreadManager; 87 class ThreadState; 88 class ThreadVisitor; // Defined in v8threads.h 89 template <StateTag Tag> class VMState; 90 91 // 'void function pointer', used to roundtrip the 92 // ExternalReference::ExternalReferenceRedirector since we can not include 93 // assembler.h, where it is defined, here. 94 typedef void* ExternalReferenceRedirectorPointer(); 95 96 97 #ifdef ENABLE_DEBUGGER_SUPPORT 98 class Debug; 99 class Debugger; 100 class DebuggerAgent; 101 #endif 102 103 #if !defined(__arm__) && V8_TARGET_ARCH_ARM || \ 104 !defined(__mips__) && V8_TARGET_ARCH_MIPS 105 class Redirection; 106 class Simulator; 107 #endif 108 109 110 // Static indirection table for handles to constants. If a frame 111 // element represents a constant, the data contains an index into 112 // this table of handles to the actual constants. 113 // Static indirection table for handles to constants. If a Result 114 // represents a constant, the data contains an index into this table 115 // of handles to the actual constants. 116 typedef ZoneList<Handle<Object> > ZoneObjectList; 117 118 #define RETURN_IF_SCHEDULED_EXCEPTION(isolate) \ 119 do { \ 120 Isolate* __isolate__ = (isolate); \ 121 if (__isolate__->has_scheduled_exception()) { \ 122 return __isolate__->PromoteScheduledException(); \ 123 } \ 124 } while (false) 125 126 #define RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, T) \ 127 do { \ 128 Isolate* __isolate__ = (isolate); \ 129 if (__isolate__->has_scheduled_exception()) { \ 130 __isolate__->PromoteScheduledException(); \ 131 return Handle<T>::null(); \ 132 } \ 133 } while (false) 134 135 #define RETURN_IF_EMPTY_HANDLE_VALUE(isolate, call, value) \ 136 do { \ 137 if ((call).is_null()) { \ 138 ASSERT((isolate)->has_pending_exception()); \ 139 return (value); \ 140 } \ 141 } while (false) 142 143 #define CHECK_NOT_EMPTY_HANDLE(isolate, call) \ 144 do { \ 145 ASSERT(!(isolate)->has_pending_exception()); \ 146 CHECK(!(call).is_null()); \ 147 CHECK(!(isolate)->has_pending_exception()); \ 148 } while (false) 149 150 #define RETURN_IF_EMPTY_HANDLE(isolate, call) \ 151 RETURN_IF_EMPTY_HANDLE_VALUE(isolate, call, Failure::Exception()) 152 153 #define FOR_EACH_ISOLATE_ADDRESS_NAME(C) \ 154 C(Handler, handler) \ 155 C(CEntryFP, c_entry_fp) \ 156 C(Context, context) \ 157 C(PendingException, pending_exception) \ 158 C(ExternalCaughtException, external_caught_exception) \ 159 C(JSEntrySP, js_entry_sp) 160 161 162 // Platform-independent, reliable thread identifier. 163 class ThreadId { 164 public: 165 // Creates an invalid ThreadId. 166 ThreadId() : id_(kInvalidId) {} 167 168 // Returns ThreadId for current thread. 169 static ThreadId Current() { return ThreadId(GetCurrentThreadId()); } 170 171 // Returns invalid ThreadId (guaranteed not to be equal to any thread). 172 static ThreadId Invalid() { return ThreadId(kInvalidId); } 173 174 // Compares ThreadIds for equality. 175 INLINE(bool Equals(const ThreadId& other) const) { 176 return id_ == other.id_; 177 } 178 179 // Checks whether this ThreadId refers to any thread. 180 INLINE(bool IsValid() const) { 181 return id_ != kInvalidId; 182 } 183 184 // Converts ThreadId to an integer representation 185 // (required for public API: V8::V8::GetCurrentThreadId). 186 int ToInteger() const { return id_; } 187 188 // Converts ThreadId to an integer representation 189 // (required for public API: V8::V8::TerminateExecution). 190 static ThreadId FromInteger(int id) { return ThreadId(id); } 191 192 private: 193 static const int kInvalidId = -1; 194 195 explicit ThreadId(int id) : id_(id) {} 196 197 static int AllocateThreadId(); 198 199 static int GetCurrentThreadId(); 200 201 int id_; 202 203 static Atomic32 highest_thread_id_; 204 205 friend class Isolate; 206 }; 207 208 209 class ThreadLocalTop BASE_EMBEDDED { 210 public: 211 // Does early low-level initialization that does not depend on the 212 // isolate being present. 213 ThreadLocalTop(); 214 215 // Initialize the thread data. 216 void Initialize(); 217 218 // Get the top C++ try catch handler or NULL if none are registered. 219 // 220 // This method is not guarenteed to return an address that can be 221 // used for comparison with addresses into the JS stack. If such an 222 // address is needed, use try_catch_handler_address. 223 v8::TryCatch* TryCatchHandler(); 224 225 // Get the address of the top C++ try catch handler or NULL if 226 // none are registered. 227 // 228 // This method always returns an address that can be compared to 229 // pointers into the JavaScript stack. When running on actual 230 // hardware, try_catch_handler_address and TryCatchHandler return 231 // the same pointer. When running on a simulator with a separate JS 232 // stack, try_catch_handler_address returns a JS stack address that 233 // corresponds to the place on the JS stack where the C++ handler 234 // would have been if the stack were not separate. 235 inline Address try_catch_handler_address() { 236 return try_catch_handler_address_; 237 } 238 239 // Set the address of the top C++ try catch handler. 240 inline void set_try_catch_handler_address(Address address) { 241 try_catch_handler_address_ = address; 242 } 243 244 void Free() { 245 ASSERT(!has_pending_message_); 246 ASSERT(!external_caught_exception_); 247 ASSERT(try_catch_handler_address_ == NULL); 248 } 249 250 Isolate* isolate_; 251 // The context where the current execution method is created and for variable 252 // lookups. 253 Context* context_; 254 ThreadId thread_id_; 255 MaybeObject* pending_exception_; 256 bool has_pending_message_; 257 bool rethrowing_message_; 258 Object* pending_message_obj_; 259 Object* pending_message_script_; 260 int pending_message_start_pos_; 261 int pending_message_end_pos_; 262 // Use a separate value for scheduled exceptions to preserve the 263 // invariants that hold about pending_exception. We may want to 264 // unify them later. 265 MaybeObject* scheduled_exception_; 266 bool external_caught_exception_; 267 SaveContext* save_context_; 268 v8::TryCatch* catcher_; 269 270 // Stack. 271 Address c_entry_fp_; // the frame pointer of the top c entry frame 272 Address handler_; // try-blocks are chained through the stack 273 274 #ifdef USE_SIMULATOR 275 Simulator* simulator_; 276 #endif 277 278 Address js_entry_sp_; // the stack pointer of the bottom JS entry frame 279 // the external callback we're currently in 280 ExternalCallbackScope* external_callback_scope_; 281 StateTag current_vm_state_; 282 283 // Generated code scratch locations. 284 int32_t formal_count_; 285 286 // Call back function to report unsafe JS accesses. 287 v8::FailedAccessCheckCallback failed_access_check_callback_; 288 289 // Head of the list of live LookupResults. 290 LookupResult* top_lookup_result_; 291 292 // Whether out of memory exceptions should be ignored. 293 bool ignore_out_of_memory_; 294 295 private: 296 void InitializeInternal(); 297 298 Address try_catch_handler_address_; 299 }; 300 301 302 #ifdef ENABLE_DEBUGGER_SUPPORT 303 304 #define ISOLATE_DEBUGGER_INIT_LIST(V) \ 305 V(DebuggerAgent*, debugger_agent_instance, NULL) 306 #else 307 308 #define ISOLATE_DEBUGGER_INIT_LIST(V) 309 310 #endif 311 312 #ifdef DEBUG 313 314 #define ISOLATE_INIT_DEBUG_ARRAY_LIST(V) \ 315 V(CommentStatistic, paged_space_comments_statistics, \ 316 CommentStatistic::kMaxComments + 1) 317 #else 318 319 #define ISOLATE_INIT_DEBUG_ARRAY_LIST(V) 320 321 #endif 322 323 #define ISOLATE_INIT_ARRAY_LIST(V) \ 324 /* SerializerDeserializer state. */ \ 325 V(int32_t, jsregexp_static_offsets_vector, kJSRegexpStaticOffsetsVectorSize) \ 326 V(int, bad_char_shift_table, kUC16AlphabetSize) \ 327 V(int, good_suffix_shift_table, (kBMMaxShift + 1)) \ 328 V(int, suffix_table, (kBMMaxShift + 1)) \ 329 V(uint32_t, private_random_seed, 2) \ 330 ISOLATE_INIT_DEBUG_ARRAY_LIST(V) 331 332 typedef List<HeapObject*> DebugObjectCache; 333 334 #define ISOLATE_INIT_LIST(V) \ 335 /* SerializerDeserializer state. */ \ 336 V(int, serialize_partial_snapshot_cache_length, 0) \ 337 V(int, serialize_partial_snapshot_cache_capacity, 0) \ 338 V(Object**, serialize_partial_snapshot_cache, NULL) \ 339 /* Assembler state. */ \ 340 /* A previously allocated buffer of kMinimalBufferSize bytes, or NULL. */ \ 341 V(byte*, assembler_spare_buffer, NULL) \ 342 V(FatalErrorCallback, exception_behavior, NULL) \ 343 V(AllowCodeGenerationFromStringsCallback, allow_code_gen_callback, NULL) \ 344 /* To distinguish the function templates, so that we can find them in the */ \ 345 /* function cache of the native context. */ \ 346 V(int, next_serial_number, 0) \ 347 V(ExternalReferenceRedirectorPointer*, external_reference_redirector, NULL) \ 348 V(bool, always_allow_natives_syntax, false) \ 349 /* Part of the state of liveedit. */ \ 350 V(FunctionInfoListener*, active_function_info_listener, NULL) \ 351 /* State for Relocatable. */ \ 352 V(Relocatable*, relocatable_top, NULL) \ 353 V(DebugObjectCache*, string_stream_debug_object_cache, NULL) \ 354 V(Object*, string_stream_current_security_token, NULL) \ 355 /* TODO(isolates): Release this on destruction? */ \ 356 V(int*, irregexp_interpreter_backtrack_stack_cache, NULL) \ 357 /* Serializer state. */ \ 358 V(ExternalReferenceTable*, external_reference_table, NULL) \ 359 /* AstNode state. */ \ 360 V(int, ast_node_id, 0) \ 361 V(unsigned, ast_node_count, 0) \ 362 V(bool, microtask_pending, false) \ 363 V(HStatistics*, hstatistics, NULL) \ 364 V(HTracer*, htracer, NULL) \ 365 V(CodeTracer*, code_tracer, NULL) \ 366 ISOLATE_DEBUGGER_INIT_LIST(V) 367 368 class Isolate { 369 // These forward declarations are required to make the friend declarations in 370 // PerIsolateThreadData work on some older versions of gcc. 371 class ThreadDataTable; 372 class EntryStackItem; 373 public: 374 ~Isolate(); 375 376 // A thread has a PerIsolateThreadData instance for each isolate that it has 377 // entered. That instance is allocated when the isolate is initially entered 378 // and reused on subsequent entries. 379 class PerIsolateThreadData { 380 public: 381 PerIsolateThreadData(Isolate* isolate, ThreadId thread_id) 382 : isolate_(isolate), 383 thread_id_(thread_id), 384 stack_limit_(0), 385 thread_state_(NULL), 386 #if !defined(__arm__) && V8_TARGET_ARCH_ARM || \ 387 !defined(__mips__) && V8_TARGET_ARCH_MIPS 388 simulator_(NULL), 389 #endif 390 next_(NULL), 391 prev_(NULL) { } 392 Isolate* isolate() const { return isolate_; } 393 ThreadId thread_id() const { return thread_id_; } 394 void set_stack_limit(uintptr_t value) { stack_limit_ = value; } 395 uintptr_t stack_limit() const { return stack_limit_; } 396 ThreadState* thread_state() const { return thread_state_; } 397 void set_thread_state(ThreadState* value) { thread_state_ = value; } 398 399 #if !defined(__arm__) && V8_TARGET_ARCH_ARM || \ 400 !defined(__mips__) && V8_TARGET_ARCH_MIPS 401 Simulator* simulator() const { return simulator_; } 402 void set_simulator(Simulator* simulator) { 403 simulator_ = simulator; 404 } 405 #endif 406 407 bool Matches(Isolate* isolate, ThreadId thread_id) const { 408 return isolate_ == isolate && thread_id_.Equals(thread_id); 409 } 410 411 private: 412 Isolate* isolate_; 413 ThreadId thread_id_; 414 uintptr_t stack_limit_; 415 ThreadState* thread_state_; 416 417 #if !defined(__arm__) && V8_TARGET_ARCH_ARM || \ 418 !defined(__mips__) && V8_TARGET_ARCH_MIPS 419 Simulator* simulator_; 420 #endif 421 422 PerIsolateThreadData* next_; 423 PerIsolateThreadData* prev_; 424 425 friend class Isolate; 426 friend class ThreadDataTable; 427 friend class EntryStackItem; 428 429 DISALLOW_COPY_AND_ASSIGN(PerIsolateThreadData); 430 }; 431 432 433 enum AddressId { 434 #define DECLARE_ENUM(CamelName, hacker_name) k##CamelName##Address, 435 FOR_EACH_ISOLATE_ADDRESS_NAME(DECLARE_ENUM) 436 #undef DECLARE_ENUM 437 kIsolateAddressCount 438 }; 439 440 // Returns the PerIsolateThreadData for the current thread (or NULL if one is 441 // not currently set). 442 static PerIsolateThreadData* CurrentPerIsolateThreadData() { 443 return reinterpret_cast<PerIsolateThreadData*>( 444 Thread::GetThreadLocal(per_isolate_thread_data_key_)); 445 } 446 447 // Returns the isolate inside which the current thread is running. 448 INLINE(static Isolate* Current()) { 449 Isolate* isolate = reinterpret_cast<Isolate*>( 450 Thread::GetExistingThreadLocal(isolate_key_)); 451 ASSERT(isolate != NULL); 452 return isolate; 453 } 454 455 INLINE(static Isolate* UncheckedCurrent()) { 456 return reinterpret_cast<Isolate*>(Thread::GetThreadLocal(isolate_key_)); 457 } 458 459 // Usually called by Init(), but can be called early e.g. to allow 460 // testing components that require logging but not the whole 461 // isolate. 462 // 463 // Safe to call more than once. 464 void InitializeLoggingAndCounters(); 465 466 bool Init(Deserializer* des); 467 468 bool IsInitialized() { return state_ == INITIALIZED; } 469 470 // True if at least one thread Enter'ed this isolate. 471 bool IsInUse() { return entry_stack_ != NULL; } 472 473 // Destroys the non-default isolates. 474 // Sets default isolate into "has_been_disposed" state rather then destroying, 475 // for legacy API reasons. 476 void TearDown(); 477 478 static void GlobalTearDown(); 479 480 bool IsDefaultIsolate() const { return this == default_isolate_; } 481 482 static void SetCrashIfDefaultIsolateInitialized(); 483 // Ensures that process-wide resources and the default isolate have been 484 // allocated. It is only necessary to call this method in rare cases, for 485 // example if you are using V8 from within the body of a static initializer. 486 // Safe to call multiple times. 487 static void EnsureDefaultIsolate(); 488 489 // Find the PerThread for this particular (isolate, thread) combination 490 // If one does not yet exist, return null. 491 PerIsolateThreadData* FindPerThreadDataForThisThread(); 492 493 // Find the PerThread for given (isolate, thread) combination 494 // If one does not yet exist, return null. 495 PerIsolateThreadData* FindPerThreadDataForThread(ThreadId thread_id); 496 497 #ifdef ENABLE_DEBUGGER_SUPPORT 498 // Get the debugger from the default isolate. Preinitializes the 499 // default isolate if needed. 500 static Debugger* GetDefaultIsolateDebugger(); 501 #endif 502 503 // Get the stack guard from the default isolate. Preinitializes the 504 // default isolate if needed. 505 static StackGuard* GetDefaultIsolateStackGuard(); 506 507 // Returns the key used to store the pointer to the current isolate. 508 // Used internally for V8 threads that do not execute JavaScript but still 509 // are part of the domain of an isolate (like the context switcher). 510 static Thread::LocalStorageKey isolate_key() { 511 return isolate_key_; 512 } 513 514 // Returns the key used to store process-wide thread IDs. 515 static Thread::LocalStorageKey thread_id_key() { 516 return thread_id_key_; 517 } 518 519 static Thread::LocalStorageKey per_isolate_thread_data_key(); 520 521 // If a client attempts to create a Locker without specifying an isolate, 522 // we assume that the client is using legacy behavior. Set up the current 523 // thread to be inside the implicit isolate (or fail a check if we have 524 // switched to non-legacy behavior). 525 static void EnterDefaultIsolate(); 526 527 // Mutex for serializing access to break control structures. 528 RecursiveMutex* break_access() { return &break_access_; } 529 530 // Mutex for serializing access to debugger. 531 RecursiveMutex* debugger_access() { return &debugger_access_; } 532 533 Address get_address_from_id(AddressId id); 534 535 // Access to top context (where the current function object was created). 536 Context* context() { return thread_local_top_.context_; } 537 void set_context(Context* context) { 538 ASSERT(context == NULL || context->IsContext()); 539 thread_local_top_.context_ = context; 540 } 541 Context** context_address() { return &thread_local_top_.context_; } 542 543 SaveContext* save_context() { return thread_local_top_.save_context_; } 544 void set_save_context(SaveContext* save) { 545 thread_local_top_.save_context_ = save; 546 } 547 548 // Access to current thread id. 549 ThreadId thread_id() { return thread_local_top_.thread_id_; } 550 void set_thread_id(ThreadId id) { thread_local_top_.thread_id_ = id; } 551 552 // Interface to pending exception. 553 MaybeObject* pending_exception() { 554 ASSERT(has_pending_exception()); 555 return thread_local_top_.pending_exception_; 556 } 557 bool external_caught_exception() { 558 return thread_local_top_.external_caught_exception_; 559 } 560 void set_external_caught_exception(bool value) { 561 thread_local_top_.external_caught_exception_ = value; 562 } 563 void set_pending_exception(MaybeObject* exception) { 564 thread_local_top_.pending_exception_ = exception; 565 } 566 void clear_pending_exception() { 567 thread_local_top_.pending_exception_ = heap_.the_hole_value(); 568 } 569 MaybeObject** pending_exception_address() { 570 return &thread_local_top_.pending_exception_; 571 } 572 bool has_pending_exception() { 573 return !thread_local_top_.pending_exception_->IsTheHole(); 574 } 575 void clear_pending_message() { 576 thread_local_top_.has_pending_message_ = false; 577 thread_local_top_.pending_message_obj_ = heap_.the_hole_value(); 578 thread_local_top_.pending_message_script_ = heap_.the_hole_value(); 579 } 580 v8::TryCatch* try_catch_handler() { 581 return thread_local_top_.TryCatchHandler(); 582 } 583 Address try_catch_handler_address() { 584 return thread_local_top_.try_catch_handler_address(); 585 } 586 bool* external_caught_exception_address() { 587 return &thread_local_top_.external_caught_exception_; 588 } 589 v8::TryCatch* catcher() { 590 return thread_local_top_.catcher_; 591 } 592 void set_catcher(v8::TryCatch* catcher) { 593 thread_local_top_.catcher_ = catcher; 594 } 595 596 MaybeObject** scheduled_exception_address() { 597 return &thread_local_top_.scheduled_exception_; 598 } 599 600 Address pending_message_obj_address() { 601 return reinterpret_cast<Address>(&thread_local_top_.pending_message_obj_); 602 } 603 604 Address has_pending_message_address() { 605 return reinterpret_cast<Address>(&thread_local_top_.has_pending_message_); 606 } 607 608 Address pending_message_script_address() { 609 return reinterpret_cast<Address>( 610 &thread_local_top_.pending_message_script_); 611 } 612 613 MaybeObject* scheduled_exception() { 614 ASSERT(has_scheduled_exception()); 615 return thread_local_top_.scheduled_exception_; 616 } 617 bool has_scheduled_exception() { 618 return thread_local_top_.scheduled_exception_ != heap_.the_hole_value(); 619 } 620 void clear_scheduled_exception() { 621 thread_local_top_.scheduled_exception_ = heap_.the_hole_value(); 622 } 623 624 bool IsExternallyCaught(); 625 626 bool is_catchable_by_javascript(MaybeObject* exception) { 627 return (!exception->IsOutOfMemory()) && 628 (exception != heap()->termination_exception()); 629 } 630 631 // Serializer. 632 void PushToPartialSnapshotCache(Object* obj); 633 634 // JS execution stack (see frames.h). 635 static Address c_entry_fp(ThreadLocalTop* thread) { 636 return thread->c_entry_fp_; 637 } 638 static Address handler(ThreadLocalTop* thread) { return thread->handler_; } 639 640 inline Address* c_entry_fp_address() { 641 return &thread_local_top_.c_entry_fp_; 642 } 643 inline Address* handler_address() { return &thread_local_top_.handler_; } 644 645 // Bottom JS entry. 646 Address js_entry_sp() { 647 return thread_local_top_.js_entry_sp_; 648 } 649 inline Address* js_entry_sp_address() { 650 return &thread_local_top_.js_entry_sp_; 651 } 652 653 // Generated code scratch locations. 654 void* formal_count_address() { return &thread_local_top_.formal_count_; } 655 656 // Returns the global object of the current context. It could be 657 // a builtin object, or a JS global object. 658 Handle<GlobalObject> global_object() { 659 return Handle<GlobalObject>(context()->global_object()); 660 } 661 662 // Returns the global proxy object of the current context. 663 Object* global_proxy() { 664 return context()->global_proxy(); 665 } 666 667 Handle<JSBuiltinsObject> js_builtins_object() { 668 return Handle<JSBuiltinsObject>(thread_local_top_.context_->builtins()); 669 } 670 671 static int ArchiveSpacePerThread() { return sizeof(ThreadLocalTop); } 672 void FreeThreadResources() { thread_local_top_.Free(); } 673 674 // This method is called by the api after operations that may throw 675 // exceptions. If an exception was thrown and not handled by an external 676 // handler the exception is scheduled to be rethrown when we return to running 677 // JavaScript code. If an exception is scheduled true is returned. 678 bool OptionalRescheduleException(bool is_bottom_call); 679 680 class ExceptionScope { 681 public: 682 explicit ExceptionScope(Isolate* isolate) : 683 // Scope currently can only be used for regular exceptions, not 684 // failures like OOM or termination exception. 685 isolate_(isolate), 686 pending_exception_(isolate_->pending_exception()->ToObjectUnchecked(), 687 isolate_), 688 catcher_(isolate_->catcher()) 689 { } 690 691 ~ExceptionScope() { 692 isolate_->set_catcher(catcher_); 693 isolate_->set_pending_exception(*pending_exception_); 694 } 695 696 private: 697 Isolate* isolate_; 698 Handle<Object> pending_exception_; 699 v8::TryCatch* catcher_; 700 }; 701 702 void SetCaptureStackTraceForUncaughtExceptions( 703 bool capture, 704 int frame_limit, 705 StackTrace::StackTraceOptions options); 706 707 // Tells whether the current context has experienced an out of memory 708 // exception. 709 bool is_out_of_memory(); 710 bool ignore_out_of_memory() { 711 return thread_local_top_.ignore_out_of_memory_; 712 } 713 void set_ignore_out_of_memory(bool value) { 714 thread_local_top_.ignore_out_of_memory_ = value; 715 } 716 717 void PrintCurrentStackTrace(FILE* out); 718 void PrintStack(StringStream* accumulator); 719 void PrintStack(FILE* out); 720 Handle<String> StackTraceString(); 721 NO_INLINE(void PushStackTraceAndDie(unsigned int magic, 722 Object* object, 723 Map* map, 724 unsigned int magic2)); 725 Handle<JSArray> CaptureCurrentStackTrace( 726 int frame_limit, 727 StackTrace::StackTraceOptions options); 728 729 Handle<JSArray> CaptureSimpleStackTrace(Handle<JSObject> error_object, 730 Handle<Object> caller, 731 int limit); 732 void CaptureAndSetDetailedStackTrace(Handle<JSObject> error_object); 733 734 // Returns if the top context may access the given global object. If 735 // the result is false, the pending exception is guaranteed to be 736 // set. 737 738 // TODO(yangguo): temporary wrappers 739 bool MayNamedAccessWrapper(Handle<JSObject> receiver, 740 Handle<Object> key, 741 v8::AccessType type) { 742 return MayNamedAccess(*receiver, *key, type); 743 } 744 bool MayIndexedAccessWrapper(Handle<JSObject> receiver, 745 uint32_t index, 746 v8::AccessType type) { 747 return MayIndexedAccess(*receiver, index, type); 748 } 749 750 bool MayNamedAccess(JSObject* receiver, 751 Object* key, 752 v8::AccessType type); 753 bool MayIndexedAccess(JSObject* receiver, 754 uint32_t index, 755 v8::AccessType type); 756 757 void SetFailedAccessCheckCallback(v8::FailedAccessCheckCallback callback); 758 void ReportFailedAccessCheck(JSObject* receiver, v8::AccessType type); 759 760 // Exception throwing support. The caller should use the result 761 // of Throw() as its return value. 762 Failure* Throw(Object* exception, MessageLocation* location = NULL); 763 // Re-throw an exception. This involves no error reporting since 764 // error reporting was handled when the exception was thrown 765 // originally. 766 Failure* ReThrow(MaybeObject* exception); 767 void ScheduleThrow(Object* exception); 768 // Re-set pending message, script and positions reported to the TryCatch 769 // back to the TLS for re-use when rethrowing. 770 void RestorePendingMessageFromTryCatch(v8::TryCatch* handler); 771 void ReportPendingMessages(); 772 // Return pending location if any or unfilled structure. 773 MessageLocation GetMessageLocation(); 774 Failure* ThrowIllegalOperation(); 775 776 // Promote a scheduled exception to pending. Asserts has_scheduled_exception. 777 Failure* PromoteScheduledException(); 778 void DoThrow(Object* exception, MessageLocation* location); 779 // Checks if exception should be reported and finds out if it's 780 // caught externally. 781 bool ShouldReportException(bool* can_be_caught_externally, 782 bool catchable_by_javascript); 783 784 // Attempts to compute the current source location, storing the 785 // result in the target out parameter. 786 void ComputeLocation(MessageLocation* target); 787 788 // Out of resource exception helpers. 789 Failure* StackOverflow(); 790 Failure* TerminateExecution(); 791 void CancelTerminateExecution(); 792 793 // Administration 794 void Iterate(ObjectVisitor* v); 795 void Iterate(ObjectVisitor* v, ThreadLocalTop* t); 796 char* Iterate(ObjectVisitor* v, char* t); 797 void IterateThread(ThreadVisitor* v, char* t); 798 799 800 // Returns the current native and global context. 801 Handle<Context> native_context(); 802 Handle<Context> global_context(); 803 804 // Returns the native context of the calling JavaScript code. That 805 // is, the native context of the top-most JavaScript frame. 806 Handle<Context> GetCallingNativeContext(); 807 808 void RegisterTryCatchHandler(v8::TryCatch* that); 809 void UnregisterTryCatchHandler(v8::TryCatch* that); 810 811 char* ArchiveThread(char* to); 812 char* RestoreThread(char* from); 813 814 static const char* const kStackOverflowMessage; 815 816 static const int kUC16AlphabetSize = 256; // See StringSearchBase. 817 static const int kBMMaxShift = 250; // See StringSearchBase. 818 819 // Accessors. 820 #define GLOBAL_ACCESSOR(type, name, initialvalue) \ 821 inline type name() const { \ 822 ASSERT(OFFSET_OF(Isolate, name##_) == name##_debug_offset_); \ 823 return name##_; \ 824 } \ 825 inline void set_##name(type value) { \ 826 ASSERT(OFFSET_OF(Isolate, name##_) == name##_debug_offset_); \ 827 name##_ = value; \ 828 } 829 ISOLATE_INIT_LIST(GLOBAL_ACCESSOR) 830 #undef GLOBAL_ACCESSOR 831 832 #define GLOBAL_ARRAY_ACCESSOR(type, name, length) \ 833 inline type* name() { \ 834 ASSERT(OFFSET_OF(Isolate, name##_) == name##_debug_offset_); \ 835 return &(name##_)[0]; \ 836 } 837 ISOLATE_INIT_ARRAY_LIST(GLOBAL_ARRAY_ACCESSOR) 838 #undef GLOBAL_ARRAY_ACCESSOR 839 840 #define NATIVE_CONTEXT_FIELD_ACCESSOR(index, type, name) \ 841 Handle<type> name() { \ 842 return Handle<type>(context()->native_context()->name(), this); \ 843 } \ 844 bool is_##name(type* value) { \ 845 return context()->native_context()->is_##name(value); \ 846 } 847 NATIVE_CONTEXT_FIELDS(NATIVE_CONTEXT_FIELD_ACCESSOR) 848 #undef NATIVE_CONTEXT_FIELD_ACCESSOR 849 850 Bootstrapper* bootstrapper() { return bootstrapper_; } 851 Counters* counters() { 852 // Call InitializeLoggingAndCounters() if logging is needed before 853 // the isolate is fully initialized. 854 ASSERT(counters_ != NULL); 855 return counters_; 856 } 857 CodeRange* code_range() { return code_range_; } 858 RuntimeProfiler* runtime_profiler() { return runtime_profiler_; } 859 CompilationCache* compilation_cache() { return compilation_cache_; } 860 Logger* logger() { 861 // Call InitializeLoggingAndCounters() if logging is needed before 862 // the isolate is fully initialized. 863 ASSERT(logger_ != NULL); 864 return logger_; 865 } 866 StackGuard* stack_guard() { return &stack_guard_; } 867 Heap* heap() { return &heap_; } 868 StatsTable* stats_table(); 869 StubCache* stub_cache() { return stub_cache_; } 870 DeoptimizerData* deoptimizer_data() { return deoptimizer_data_; } 871 ThreadLocalTop* thread_local_top() { return &thread_local_top_; } 872 873 TranscendentalCache* transcendental_cache() const { 874 return transcendental_cache_; 875 } 876 877 MemoryAllocator* memory_allocator() { 878 return memory_allocator_; 879 } 880 881 KeyedLookupCache* keyed_lookup_cache() { 882 return keyed_lookup_cache_; 883 } 884 885 ContextSlotCache* context_slot_cache() { 886 return context_slot_cache_; 887 } 888 889 DescriptorLookupCache* descriptor_lookup_cache() { 890 return descriptor_lookup_cache_; 891 } 892 893 v8::ImplementationUtilities::HandleScopeData* handle_scope_data() { 894 return &handle_scope_data_; 895 } 896 HandleScopeImplementer* handle_scope_implementer() { 897 ASSERT(handle_scope_implementer_); 898 return handle_scope_implementer_; 899 } 900 Zone* runtime_zone() { return &runtime_zone_; } 901 902 UnicodeCache* unicode_cache() { 903 return unicode_cache_; 904 } 905 906 InnerPointerToCodeCache* inner_pointer_to_code_cache() { 907 return inner_pointer_to_code_cache_; 908 } 909 910 ConsStringIteratorOp* write_iterator() { return write_iterator_; } 911 912 GlobalHandles* global_handles() { return global_handles_; } 913 914 EternalHandles* eternal_handles() { return eternal_handles_; } 915 916 ThreadManager* thread_manager() { return thread_manager_; } 917 918 StringTracker* string_tracker() { return string_tracker_; } 919 920 unibrow::Mapping<unibrow::Ecma262UnCanonicalize>* jsregexp_uncanonicalize() { 921 return &jsregexp_uncanonicalize_; 922 } 923 924 unibrow::Mapping<unibrow::CanonicalizationRange>* jsregexp_canonrange() { 925 return &jsregexp_canonrange_; 926 } 927 928 ConsStringIteratorOp* objects_string_compare_iterator_a() { 929 return &objects_string_compare_iterator_a_; 930 } 931 932 ConsStringIteratorOp* objects_string_compare_iterator_b() { 933 return &objects_string_compare_iterator_b_; 934 } 935 936 StaticResource<ConsStringIteratorOp>* objects_string_iterator() { 937 return &objects_string_iterator_; 938 } 939 940 RuntimeState* runtime_state() { return &runtime_state_; } 941 942 void set_fp_stubs_generated(bool value) { 943 fp_stubs_generated_ = value; 944 } 945 946 bool fp_stubs_generated() { return fp_stubs_generated_; } 947 948 Builtins* builtins() { return &builtins_; } 949 950 void NotifyExtensionInstalled() { 951 has_installed_extensions_ = true; 952 } 953 954 bool has_installed_extensions() { return has_installed_extensions_; } 955 956 unibrow::Mapping<unibrow::Ecma262Canonicalize>* 957 regexp_macro_assembler_canonicalize() { 958 return ®exp_macro_assembler_canonicalize_; 959 } 960 961 RegExpStack* regexp_stack() { return regexp_stack_; } 962 963 unibrow::Mapping<unibrow::Ecma262Canonicalize>* 964 interp_canonicalize_mapping() { 965 return &interp_canonicalize_mapping_; 966 } 967 968 inline bool IsCodePreAgingActive(); 969 970 #ifdef ENABLE_DEBUGGER_SUPPORT 971 Debugger* debugger() { 972 if (!NoBarrier_Load(&debugger_initialized_)) InitializeDebugger(); 973 return debugger_; 974 } 975 Debug* debug() { 976 if (!NoBarrier_Load(&debugger_initialized_)) InitializeDebugger(); 977 return debug_; 978 } 979 #endif 980 981 inline bool IsDebuggerActive(); 982 inline bool DebuggerHasBreakPoints(); 983 984 CpuProfiler* cpu_profiler() const { return cpu_profiler_; } 985 HeapProfiler* heap_profiler() const { return heap_profiler_; } 986 987 #ifdef DEBUG 988 HistogramInfo* heap_histograms() { return heap_histograms_; } 989 990 JSObject::SpillInformation* js_spill_information() { 991 return &js_spill_information_; 992 } 993 994 int* code_kind_statistics() { return code_kind_statistics_; } 995 #endif 996 997 #if V8_TARGET_ARCH_ARM && !defined(__arm__) || \ 998 V8_TARGET_ARCH_MIPS && !defined(__mips__) 999 bool simulator_initialized() { return simulator_initialized_; } 1000 void set_simulator_initialized(bool initialized) { 1001 simulator_initialized_ = initialized; 1002 } 1003 1004 HashMap* simulator_i_cache() { return simulator_i_cache_; } 1005 void set_simulator_i_cache(HashMap* hash_map) { 1006 simulator_i_cache_ = hash_map; 1007 } 1008 1009 Redirection* simulator_redirection() { 1010 return simulator_redirection_; 1011 } 1012 void set_simulator_redirection(Redirection* redirection) { 1013 simulator_redirection_ = redirection; 1014 } 1015 #endif 1016 1017 Factory* factory() { return reinterpret_cast<Factory*>(this); } 1018 1019 static const int kJSRegexpStaticOffsetsVectorSize = 128; 1020 1021 ExternalCallbackScope* external_callback_scope() { 1022 return thread_local_top_.external_callback_scope_; 1023 } 1024 void set_external_callback_scope(ExternalCallbackScope* scope) { 1025 thread_local_top_.external_callback_scope_ = scope; 1026 } 1027 1028 StateTag current_vm_state() { 1029 return thread_local_top_.current_vm_state_; 1030 } 1031 1032 void set_current_vm_state(StateTag state) { 1033 thread_local_top_.current_vm_state_ = state; 1034 } 1035 1036 void SetData(uint32_t slot, void* data) { 1037 ASSERT(slot < Internals::kNumIsolateDataSlots); 1038 embedder_data_[slot] = data; 1039 } 1040 void* GetData(uint32_t slot) { 1041 ASSERT(slot < Internals::kNumIsolateDataSlots); 1042 return embedder_data_[slot]; 1043 } 1044 1045 LookupResult* top_lookup_result() { 1046 return thread_local_top_.top_lookup_result_; 1047 } 1048 void SetTopLookupResult(LookupResult* top) { 1049 thread_local_top_.top_lookup_result_ = top; 1050 } 1051 1052 bool IsDead() { return has_fatal_error_; } 1053 void SignalFatalError() { has_fatal_error_ = true; } 1054 1055 bool use_crankshaft() const { return use_crankshaft_; } 1056 1057 bool initialized_from_snapshot() { return initialized_from_snapshot_; } 1058 1059 double time_millis_since_init() { 1060 return OS::TimeCurrentMillis() - time_millis_at_init_; 1061 } 1062 1063 DateCache* date_cache() { 1064 return date_cache_; 1065 } 1066 1067 void set_date_cache(DateCache* date_cache) { 1068 if (date_cache != date_cache_) { 1069 delete date_cache_; 1070 } 1071 date_cache_ = date_cache; 1072 } 1073 1074 Map* get_initial_js_array_map(ElementsKind kind); 1075 1076 bool IsFastArrayConstructorPrototypeChainIntact(); 1077 1078 CodeStubInterfaceDescriptor* 1079 code_stub_interface_descriptor(int index); 1080 1081 void IterateDeferredHandles(ObjectVisitor* visitor); 1082 void LinkDeferredHandles(DeferredHandles* deferred_handles); 1083 void UnlinkDeferredHandles(DeferredHandles* deferred_handles); 1084 1085 #ifdef DEBUG 1086 bool IsDeferredHandle(Object** location); 1087 #endif // DEBUG 1088 1089 void set_max_available_threads(int value) { 1090 max_available_threads_ = value; 1091 } 1092 1093 bool concurrent_recompilation_enabled() { 1094 // Thread is only available with flag enabled. 1095 ASSERT(optimizing_compiler_thread_ == NULL || 1096 FLAG_concurrent_recompilation); 1097 return optimizing_compiler_thread_ != NULL; 1098 } 1099 1100 bool concurrent_osr_enabled() const { 1101 // Thread is only available with flag enabled. 1102 ASSERT(optimizing_compiler_thread_ == NULL || 1103 FLAG_concurrent_recompilation); 1104 return optimizing_compiler_thread_ != NULL && FLAG_concurrent_osr; 1105 } 1106 1107 OptimizingCompilerThread* optimizing_compiler_thread() { 1108 return optimizing_compiler_thread_; 1109 } 1110 1111 int num_sweeper_threads() const { 1112 return num_sweeper_threads_; 1113 } 1114 1115 SweeperThread** sweeper_threads() { 1116 return sweeper_thread_; 1117 } 1118 1119 // PreInits and returns a default isolate. Needed when a new thread tries 1120 // to create a Locker for the first time (the lock itself is in the isolate). 1121 // TODO(svenpanne) This method is on death row... 1122 static v8::Isolate* GetDefaultIsolateForLocking(); 1123 1124 int id() const { return static_cast<int>(id_); } 1125 1126 HStatistics* GetHStatistics(); 1127 HTracer* GetHTracer(); 1128 CodeTracer* GetCodeTracer(); 1129 1130 FunctionEntryHook function_entry_hook() { return function_entry_hook_; } 1131 void set_function_entry_hook(FunctionEntryHook function_entry_hook) { 1132 function_entry_hook_ = function_entry_hook; 1133 } 1134 1135 void* stress_deopt_count_address() { return &stress_deopt_count_; } 1136 1137 inline RandomNumberGenerator* random_number_generator(); 1138 1139 // Given an address occupied by a live code object, return that object. 1140 Object* FindCodeObject(Address a); 1141 1142 private: 1143 Isolate(); 1144 1145 friend struct GlobalState; 1146 friend struct InitializeGlobalState; 1147 1148 enum State { 1149 UNINITIALIZED, // Some components may not have been allocated. 1150 INITIALIZED // All components are fully initialized. 1151 }; 1152 1153 // These fields are accessed through the API, offsets must be kept in sync 1154 // with v8::internal::Internals (in include/v8.h) constants. This is also 1155 // verified in Isolate::Init() using runtime checks. 1156 void* embedder_data_[Internals::kNumIsolateDataSlots]; 1157 Heap heap_; 1158 State state_; // Will be padded to kApiPointerSize. 1159 1160 // The per-process lock should be acquired before the ThreadDataTable is 1161 // modified. 1162 class ThreadDataTable { 1163 public: 1164 ThreadDataTable(); 1165 ~ThreadDataTable(); 1166 1167 PerIsolateThreadData* Lookup(Isolate* isolate, ThreadId thread_id); 1168 void Insert(PerIsolateThreadData* data); 1169 void Remove(PerIsolateThreadData* data); 1170 void RemoveAllThreads(Isolate* isolate); 1171 1172 private: 1173 PerIsolateThreadData* list_; 1174 }; 1175 1176 // These items form a stack synchronously with threads Enter'ing and Exit'ing 1177 // the Isolate. The top of the stack points to a thread which is currently 1178 // running the Isolate. When the stack is empty, the Isolate is considered 1179 // not entered by any thread and can be Disposed. 1180 // If the same thread enters the Isolate more then once, the entry_count_ 1181 // is incremented rather then a new item pushed to the stack. 1182 class EntryStackItem { 1183 public: 1184 EntryStackItem(PerIsolateThreadData* previous_thread_data, 1185 Isolate* previous_isolate, 1186 EntryStackItem* previous_item) 1187 : entry_count(1), 1188 previous_thread_data(previous_thread_data), 1189 previous_isolate(previous_isolate), 1190 previous_item(previous_item) { } 1191 1192 int entry_count; 1193 PerIsolateThreadData* previous_thread_data; 1194 Isolate* previous_isolate; 1195 EntryStackItem* previous_item; 1196 1197 private: 1198 DISALLOW_COPY_AND_ASSIGN(EntryStackItem); 1199 }; 1200 1201 // This mutex protects highest_thread_id_, thread_data_table_ and 1202 // default_isolate_. 1203 static Mutex process_wide_mutex_; 1204 1205 static Thread::LocalStorageKey per_isolate_thread_data_key_; 1206 static Thread::LocalStorageKey isolate_key_; 1207 static Thread::LocalStorageKey thread_id_key_; 1208 static Isolate* default_isolate_; 1209 static ThreadDataTable* thread_data_table_; 1210 1211 // A global counter for all generated Isolates, might overflow. 1212 static Atomic32 isolate_counter_; 1213 1214 void Deinit(); 1215 1216 static void SetIsolateThreadLocals(Isolate* isolate, 1217 PerIsolateThreadData* data); 1218 1219 // Find the PerThread for this particular (isolate, thread) combination. 1220 // If one does not yet exist, allocate a new one. 1221 PerIsolateThreadData* FindOrAllocatePerThreadDataForThisThread(); 1222 1223 // Initializes the current thread to run this Isolate. 1224 // Not thread-safe. Multiple threads should not Enter/Exit the same isolate 1225 // at the same time, this should be prevented using external locking. 1226 void Enter(); 1227 1228 // Exits the current thread. The previosuly entered Isolate is restored 1229 // for the thread. 1230 // Not thread-safe. Multiple threads should not Enter/Exit the same isolate 1231 // at the same time, this should be prevented using external locking. 1232 void Exit(); 1233 1234 void InitializeThreadLocal(); 1235 1236 void MarkCompactPrologue(bool is_compacting, 1237 ThreadLocalTop* archived_thread_data); 1238 void MarkCompactEpilogue(bool is_compacting, 1239 ThreadLocalTop* archived_thread_data); 1240 1241 void FillCache(); 1242 1243 void PropagatePendingExceptionToExternalTryCatch(); 1244 1245 void InitializeDebugger(); 1246 1247 // Traverse prototype chain to find out whether the object is derived from 1248 // the Error object. 1249 bool IsErrorObject(Handle<Object> obj); 1250 1251 Atomic32 id_; 1252 EntryStackItem* entry_stack_; 1253 int stack_trace_nesting_level_; 1254 StringStream* incomplete_message_; 1255 Address isolate_addresses_[kIsolateAddressCount + 1]; // NOLINT 1256 Bootstrapper* bootstrapper_; 1257 RuntimeProfiler* runtime_profiler_; 1258 CompilationCache* compilation_cache_; 1259 Counters* counters_; 1260 CodeRange* code_range_; 1261 RecursiveMutex break_access_; 1262 Atomic32 debugger_initialized_; 1263 RecursiveMutex debugger_access_; 1264 Logger* logger_; 1265 StackGuard stack_guard_; 1266 StatsTable* stats_table_; 1267 StubCache* stub_cache_; 1268 DeoptimizerData* deoptimizer_data_; 1269 ThreadLocalTop thread_local_top_; 1270 bool capture_stack_trace_for_uncaught_exceptions_; 1271 int stack_trace_for_uncaught_exceptions_frame_limit_; 1272 StackTrace::StackTraceOptions stack_trace_for_uncaught_exceptions_options_; 1273 TranscendentalCache* transcendental_cache_; 1274 MemoryAllocator* memory_allocator_; 1275 KeyedLookupCache* keyed_lookup_cache_; 1276 ContextSlotCache* context_slot_cache_; 1277 DescriptorLookupCache* descriptor_lookup_cache_; 1278 v8::ImplementationUtilities::HandleScopeData handle_scope_data_; 1279 HandleScopeImplementer* handle_scope_implementer_; 1280 UnicodeCache* unicode_cache_; 1281 Zone runtime_zone_; 1282 InnerPointerToCodeCache* inner_pointer_to_code_cache_; 1283 ConsStringIteratorOp* write_iterator_; 1284 GlobalHandles* global_handles_; 1285 EternalHandles* eternal_handles_; 1286 ThreadManager* thread_manager_; 1287 RuntimeState runtime_state_; 1288 bool fp_stubs_generated_; 1289 Builtins builtins_; 1290 bool has_installed_extensions_; 1291 StringTracker* string_tracker_; 1292 unibrow::Mapping<unibrow::Ecma262UnCanonicalize> jsregexp_uncanonicalize_; 1293 unibrow::Mapping<unibrow::CanonicalizationRange> jsregexp_canonrange_; 1294 ConsStringIteratorOp objects_string_compare_iterator_a_; 1295 ConsStringIteratorOp objects_string_compare_iterator_b_; 1296 StaticResource<ConsStringIteratorOp> objects_string_iterator_; 1297 unibrow::Mapping<unibrow::Ecma262Canonicalize> 1298 regexp_macro_assembler_canonicalize_; 1299 RegExpStack* regexp_stack_; 1300 DateCache* date_cache_; 1301 unibrow::Mapping<unibrow::Ecma262Canonicalize> interp_canonicalize_mapping_; 1302 CodeStubInterfaceDescriptor* code_stub_interface_descriptors_; 1303 RandomNumberGenerator* random_number_generator_; 1304 1305 // True if fatal error has been signaled for this isolate. 1306 bool has_fatal_error_; 1307 1308 // True if we are using the Crankshaft optimizing compiler. 1309 bool use_crankshaft_; 1310 1311 // True if this isolate was initialized from a snapshot. 1312 bool initialized_from_snapshot_; 1313 1314 // Time stamp at initialization. 1315 double time_millis_at_init_; 1316 1317 #if V8_TARGET_ARCH_ARM && !defined(__arm__) || \ 1318 V8_TARGET_ARCH_MIPS && !defined(__mips__) 1319 bool simulator_initialized_; 1320 HashMap* simulator_i_cache_; 1321 Redirection* simulator_redirection_; 1322 #endif 1323 1324 #ifdef DEBUG 1325 // A static array of histogram info for each type. 1326 HistogramInfo heap_histograms_[LAST_TYPE + 1]; 1327 JSObject::SpillInformation js_spill_information_; 1328 int code_kind_statistics_[Code::NUMBER_OF_KINDS]; 1329 #endif 1330 1331 #ifdef ENABLE_DEBUGGER_SUPPORT 1332 Debugger* debugger_; 1333 Debug* debug_; 1334 #endif 1335 CpuProfiler* cpu_profiler_; 1336 HeapProfiler* heap_profiler_; 1337 FunctionEntryHook function_entry_hook_; 1338 1339 #define GLOBAL_BACKING_STORE(type, name, initialvalue) \ 1340 type name##_; 1341 ISOLATE_INIT_LIST(GLOBAL_BACKING_STORE) 1342 #undef GLOBAL_BACKING_STORE 1343 1344 #define GLOBAL_ARRAY_BACKING_STORE(type, name, length) \ 1345 type name##_[length]; 1346 ISOLATE_INIT_ARRAY_LIST(GLOBAL_ARRAY_BACKING_STORE) 1347 #undef GLOBAL_ARRAY_BACKING_STORE 1348 1349 #ifdef DEBUG 1350 // This class is huge and has a number of fields controlled by 1351 // preprocessor defines. Make sure the offsets of these fields agree 1352 // between compilation units. 1353 #define ISOLATE_FIELD_OFFSET(type, name, ignored) \ 1354 static const intptr_t name##_debug_offset_; 1355 ISOLATE_INIT_LIST(ISOLATE_FIELD_OFFSET) 1356 ISOLATE_INIT_ARRAY_LIST(ISOLATE_FIELD_OFFSET) 1357 #undef ISOLATE_FIELD_OFFSET 1358 #endif 1359 1360 DeferredHandles* deferred_handles_head_; 1361 OptimizingCompilerThread* optimizing_compiler_thread_; 1362 SweeperThread** sweeper_thread_; 1363 int num_sweeper_threads_; 1364 1365 // TODO(yangguo): This will become obsolete once ResourceConstraints 1366 // becomes an argument to Isolate constructor. 1367 int max_available_threads_; 1368 1369 // Counts deopt points if deopt_every_n_times is enabled. 1370 unsigned int stress_deopt_count_; 1371 1372 friend class ExecutionAccess; 1373 friend class HandleScopeImplementer; 1374 friend class IsolateInitializer; 1375 friend class OptimizingCompilerThread; 1376 friend class SweeperThread; 1377 friend class ThreadManager; 1378 friend class Simulator; 1379 friend class StackGuard; 1380 friend class ThreadId; 1381 friend class TestMemoryAllocatorScope; 1382 friend class TestCodeRangeScope; 1383 friend class v8::Isolate; 1384 friend class v8::Locker; 1385 friend class v8::Unlocker; 1386 1387 DISALLOW_COPY_AND_ASSIGN(Isolate); 1388 }; 1389 1390 1391 // If the GCC version is 4.1.x or 4.2.x an additional field is added to the 1392 // class as a work around for a bug in the generated code found with these 1393 // versions of GCC. See V8 issue 122 for details. 1394 class SaveContext BASE_EMBEDDED { 1395 public: 1396 inline explicit SaveContext(Isolate* isolate); 1397 1398 ~SaveContext() { 1399 isolate_->set_context(context_.is_null() ? NULL : *context_); 1400 isolate_->set_save_context(prev_); 1401 } 1402 1403 Handle<Context> context() { return context_; } 1404 SaveContext* prev() { return prev_; } 1405 1406 // Returns true if this save context is below a given JavaScript frame. 1407 bool IsBelowFrame(JavaScriptFrame* frame) { 1408 return (c_entry_fp_ == 0) || (c_entry_fp_ > frame->sp()); 1409 } 1410 1411 private: 1412 Isolate* isolate_; 1413 Handle<Context> context_; 1414 SaveContext* prev_; 1415 Address c_entry_fp_; 1416 }; 1417 1418 1419 class AssertNoContextChange BASE_EMBEDDED { 1420 #ifdef DEBUG 1421 public: 1422 explicit AssertNoContextChange(Isolate* isolate) 1423 : isolate_(isolate), 1424 context_(isolate->context(), isolate) { } 1425 ~AssertNoContextChange() { 1426 ASSERT(isolate_->context() == *context_); 1427 } 1428 1429 private: 1430 Isolate* isolate_; 1431 Handle<Context> context_; 1432 #else 1433 public: 1434 explicit AssertNoContextChange(Isolate* isolate) { } 1435 #endif 1436 }; 1437 1438 1439 class ExecutionAccess BASE_EMBEDDED { 1440 public: 1441 explicit ExecutionAccess(Isolate* isolate) : isolate_(isolate) { 1442 Lock(isolate); 1443 } 1444 ~ExecutionAccess() { Unlock(isolate_); } 1445 1446 static void Lock(Isolate* isolate) { isolate->break_access()->Lock(); } 1447 static void Unlock(Isolate* isolate) { isolate->break_access()->Unlock(); } 1448 1449 static bool TryLock(Isolate* isolate) { 1450 return isolate->break_access()->TryLock(); 1451 } 1452 1453 private: 1454 Isolate* isolate_; 1455 }; 1456 1457 1458 // Support for checking for stack-overflows in C++ code. 1459 class StackLimitCheck BASE_EMBEDDED { 1460 public: 1461 explicit StackLimitCheck(Isolate* isolate) : isolate_(isolate) { } 1462 1463 bool HasOverflowed() const { 1464 StackGuard* stack_guard = isolate_->stack_guard(); 1465 return (reinterpret_cast<uintptr_t>(this) < stack_guard->real_climit()); 1466 } 1467 private: 1468 Isolate* isolate_; 1469 }; 1470 1471 1472 // Support for temporarily postponing interrupts. When the outermost 1473 // postpone scope is left the interrupts will be re-enabled and any 1474 // interrupts that occurred while in the scope will be taken into 1475 // account. 1476 class PostponeInterruptsScope BASE_EMBEDDED { 1477 public: 1478 explicit PostponeInterruptsScope(Isolate* isolate) 1479 : stack_guard_(isolate->stack_guard()) { 1480 stack_guard_->thread_local_.postpone_interrupts_nesting_++; 1481 stack_guard_->DisableInterrupts(); 1482 } 1483 1484 ~PostponeInterruptsScope() { 1485 if (--stack_guard_->thread_local_.postpone_interrupts_nesting_ == 0) { 1486 stack_guard_->EnableInterrupts(); 1487 } 1488 } 1489 private: 1490 StackGuard* stack_guard_; 1491 }; 1492 1493 1494 // Tells whether the native context is marked with out of memory. 1495 inline bool Context::has_out_of_memory() { 1496 return native_context()->out_of_memory()->IsTrue(); 1497 } 1498 1499 1500 // Mark the native context with out of memory. 1501 inline void Context::mark_out_of_memory() { 1502 native_context()->set_out_of_memory(GetIsolate()->heap()->true_value()); 1503 } 1504 1505 class CodeTracer V8_FINAL : public Malloced { 1506 public: 1507 explicit CodeTracer(int isolate_id) 1508 : file_(NULL), 1509 scope_depth_(0) { 1510 if (!ShouldRedirect()) { 1511 file_ = stdout; 1512 return; 1513 } 1514 1515 if (FLAG_redirect_code_traces_to == NULL) { 1516 OS::SNPrintF(filename_, 1517 "code-%d-%d.asm", 1518 OS::GetCurrentProcessId(), 1519 isolate_id); 1520 } else { 1521 OS::StrNCpy(filename_, FLAG_redirect_code_traces_to, filename_.length()); 1522 } 1523 1524 WriteChars(filename_.start(), "", 0, false); 1525 } 1526 1527 class Scope { 1528 public: 1529 explicit Scope(CodeTracer* tracer) : tracer_(tracer) { tracer->OpenFile(); } 1530 ~Scope() { tracer_->CloseFile(); } 1531 1532 FILE* file() const { return tracer_->file(); } 1533 1534 private: 1535 CodeTracer* tracer_; 1536 }; 1537 1538 void OpenFile() { 1539 if (!ShouldRedirect()) { 1540 return; 1541 } 1542 1543 if (file_ == NULL) { 1544 file_ = OS::FOpen(filename_.start(), "a"); 1545 } 1546 1547 scope_depth_++; 1548 } 1549 1550 void CloseFile() { 1551 if (!ShouldRedirect()) { 1552 return; 1553 } 1554 1555 if (--scope_depth_ == 0) { 1556 fclose(file_); 1557 file_ = NULL; 1558 } 1559 } 1560 1561 FILE* file() const { return file_; } 1562 1563 private: 1564 static bool ShouldRedirect() { 1565 return FLAG_redirect_code_traces; 1566 } 1567 1568 EmbeddedVector<char, 128> filename_; 1569 FILE* file_; 1570 int scope_depth_; 1571 }; 1572 1573 } } // namespace v8::internal 1574 1575 #endif // V8_ISOLATE_H_ 1576