1 // Copyright 2011 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
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.
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.
31 #include "../include/v8-debug.h"
32 #include "allocation.h"
34 #include "atomicops.h"
37 #include "execution.h"
39 #include "global-handles.h"
42 #include "regexp-stack.h"
43 #include "runtime-profiler.h"
53 class CompilationCache;
54 class ContextSlotCache;
55 class ContextSwitcher;
59 class DeoptimizerData;
62 class ExternalReferenceTable;
64 class FunctionInfoListener;
65 class HandleScopeImplementer;
67 class InlineRuntimeFunctionsTable;
68 class NoAllocationStringAllocator;
69 class InnerPointerToCodeCache;
70 class PreallocatedMemoryThread;
74 class StringInputBuffer;
79 class ThreadVisitor; // Defined in v8threads.h
82 // 'void function pointer', used to roundtrip the
83 // ExternalReference::ExternalReferenceRedirector since we can not include
84 // assembler.h, where it is defined, here.
85 typedef void* ExternalReferenceRedirectorPointer();
88 #ifdef ENABLE_DEBUGGER_SUPPORT
94 #if !defined(__arm__) && defined(V8_TARGET_ARCH_ARM) || \
95 !defined(__mips__) && defined(V8_TARGET_ARCH_MIPS)
101 // Static indirection table for handles to constants. If a frame
102 // element represents a constant, the data contains an index into
103 // this table of handles to the actual constants.
104 // Static indirection table for handles to constants. If a Result
105 // represents a constant, the data contains an index into this table
106 // of handles to the actual constants.
107 typedef ZoneList<Handle<Object> > ZoneObjectList;
109 #define RETURN_IF_SCHEDULED_EXCEPTION(isolate) \
110 if (isolate->has_scheduled_exception()) \
111 return isolate->PromoteScheduledException()
113 #define RETURN_IF_EMPTY_HANDLE_VALUE(isolate, call, value) \
114 if (call.is_null()) { \
115 ASSERT(isolate->has_pending_exception()); \
119 #define RETURN_IF_EMPTY_HANDLE(isolate, call) \
120 RETURN_IF_EMPTY_HANDLE_VALUE(isolate, call, Failure::Exception())
122 #define FOR_EACH_ISOLATE_ADDRESS_NAME(C) \
123 C(Handler, handler) \
124 C(CEntryFP, c_entry_fp) \
125 C(Context, context) \
126 C(PendingException, pending_exception) \
127 C(ExternalCaughtException, external_caught_exception) \
128 C(JSEntrySP, js_entry_sp)
131 // Platform-independent, reliable thread identifier.
134 // Creates an invalid ThreadId.
135 ThreadId() : id_(kInvalidId) {}
137 // Returns ThreadId for current thread.
138 static ThreadId Current() { return ThreadId(GetCurrentThreadId()); }
140 // Returns invalid ThreadId (guaranteed not to be equal to any thread).
141 static ThreadId Invalid() { return ThreadId(kInvalidId); }
143 // Compares ThreadIds for equality.
144 INLINE(bool Equals(const ThreadId& other) const) {
145 return id_ == other.id_;
148 // Checks whether this ThreadId refers to any thread.
149 INLINE(bool IsValid() const) {
150 return id_ != kInvalidId;
153 // Converts ThreadId to an integer representation
154 // (required for public API: V8::V8::GetCurrentThreadId).
155 int ToInteger() const { return id_; }
157 // Converts ThreadId to an integer representation
158 // (required for public API: V8::V8::TerminateExecution).
159 static ThreadId FromInteger(int id) { return ThreadId(id); }
162 static const int kInvalidId = -1;
164 explicit ThreadId(int id) : id_(id) {}
166 static int AllocateThreadId();
168 static int GetCurrentThreadId();
172 static Atomic32 highest_thread_id_;
174 friend class Isolate;
178 class ThreadLocalTop BASE_EMBEDDED {
180 // Does early low-level initialization that does not depend on the
181 // isolate being present.
184 // Initialize the thread data.
187 // Get the top C++ try catch handler or NULL if none are registered.
189 // This method is not guarenteed to return an address that can be
190 // used for comparison with addresses into the JS stack. If such an
191 // address is needed, use try_catch_handler_address.
192 v8::TryCatch* TryCatchHandler();
194 // Get the address of the top C++ try catch handler or NULL if
195 // none are registered.
197 // This method always returns an address that can be compared to
198 // pointers into the JavaScript stack. When running on actual
199 // hardware, try_catch_handler_address and TryCatchHandler return
200 // the same pointer. When running on a simulator with a separate JS
201 // stack, try_catch_handler_address returns a JS stack address that
202 // corresponds to the place on the JS stack where the C++ handler
203 // would have been if the stack were not separate.
204 inline Address try_catch_handler_address() {
205 return try_catch_handler_address_;
208 // Set the address of the top C++ try catch handler.
209 inline void set_try_catch_handler_address(Address address) {
210 try_catch_handler_address_ = address;
214 ASSERT(!has_pending_message_);
215 ASSERT(!external_caught_exception_);
216 ASSERT(try_catch_handler_address_ == NULL);
220 // The context where the current execution method is created and for variable
224 MaybeObject* pending_exception_;
225 bool has_pending_message_;
226 Object* pending_message_obj_;
227 Script* pending_message_script_;
228 int pending_message_start_pos_;
229 int pending_message_end_pos_;
230 // Use a separate value for scheduled exceptions to preserve the
231 // invariants that hold about pending_exception. We may want to
233 MaybeObject* scheduled_exception_;
234 bool external_caught_exception_;
235 SaveContext* save_context_;
236 v8::TryCatch* catcher_;
239 Address c_entry_fp_; // the frame pointer of the top c entry frame
240 Address handler_; // try-blocks are chained through the stack
243 #if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_MIPS)
244 Simulator* simulator_;
246 #endif // USE_SIMULATOR
248 Address js_entry_sp_; // the stack pointer of the bottom js entry frame
249 Address external_callback_; // the external callback we're currently in
250 StateTag current_vm_state_;
252 // Generated code scratch locations.
253 int32_t formal_count_;
255 // Call back function to report unsafe JS accesses.
256 v8::FailedAccessCheckCallback failed_access_check_callback_;
258 // Head of the list of live LookupResults.
259 LookupResult* top_lookup_result_;
261 // Call back function for user object comparisons
262 v8::UserObjectComparisonCallback user_object_comparison_callback_;
264 // Whether out of memory exceptions should be ignored.
265 bool ignore_out_of_memory_;
268 void InitializeInternal();
270 Address try_catch_handler_address_;
273 #if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_MIPS)
275 #define ISOLATE_PLATFORM_INIT_LIST(V) \
276 /* VirtualFrame::SpilledScope state */ \
277 V(bool, is_virtual_frame_in_spilled_scope, false) \
278 /* CodeGenerator::EmitNamedStore state */ \
279 V(int, inlined_write_barrier_size, -1)
281 #if !defined(__arm__) && !defined(__mips__)
287 #define ISOLATE_PLATFORM_INIT_LIST(V)
291 #ifdef ENABLE_DEBUGGER_SUPPORT
293 #define ISOLATE_DEBUGGER_INIT_LIST(V) \
294 V(v8::Debug::EventCallback, debug_event_callback, NULL) \
295 V(DebuggerAgent*, debugger_agent_instance, NULL)
298 #define ISOLATE_DEBUGGER_INIT_LIST(V)
304 #define ISOLATE_INIT_DEBUG_ARRAY_LIST(V) \
305 V(CommentStatistic, paged_space_comments_statistics, \
306 CommentStatistic::kMaxComments + 1)
309 #define ISOLATE_INIT_DEBUG_ARRAY_LIST(V)
313 #define ISOLATE_INIT_ARRAY_LIST(V) \
314 /* SerializerDeserializer state. */ \
315 V(Object*, serialize_partial_snapshot_cache, kPartialSnapshotCacheCapacity) \
316 V(int, jsregexp_static_offsets_vector, kJSRegexpStaticOffsetsVectorSize) \
317 V(int, bad_char_shift_table, kUC16AlphabetSize) \
318 V(int, good_suffix_shift_table, (kBMMaxShift + 1)) \
319 V(int, suffix_table, (kBMMaxShift + 1)) \
320 V(uint32_t, private_random_seed, 2) \
321 ISOLATE_INIT_DEBUG_ARRAY_LIST(V)
323 typedef List<HeapObject*, PreallocatedStorage> DebugObjectCache;
325 #define ISOLATE_INIT_LIST(V) \
326 /* AssertNoZoneAllocation state. */ \
327 V(bool, zone_allow_allocation, true) \
328 /* SerializerDeserializer state. */ \
329 V(int, serialize_partial_snapshot_cache_length, 0) \
330 /* Assembler state. */ \
331 /* A previously allocated buffer of kMinimalBufferSize bytes, or NULL. */ \
332 V(byte*, assembler_spare_buffer, NULL) \
333 V(FatalErrorCallback, exception_behavior, NULL) \
334 V(AllowCodeGenerationFromStringsCallback, allow_code_gen_callback, NULL) \
335 V(v8::Debug::MessageHandler, message_handler, NULL) \
336 /* To distinguish the function templates, so that we can find them in the */ \
337 /* function cache of the global context. */ \
338 V(int, next_serial_number, 0) \
339 V(ExternalReferenceRedirectorPointer*, external_reference_redirector, NULL) \
340 V(bool, always_allow_natives_syntax, false) \
341 /* Part of the state of liveedit. */ \
342 V(FunctionInfoListener*, active_function_info_listener, NULL) \
343 /* State for Relocatable. */ \
344 V(Relocatable*, relocatable_top, NULL) \
345 /* State for CodeEntry in profile-generator. */ \
346 V(CodeGenerator*, current_code_generator, NULL) \
347 V(bool, jump_target_compiling_deferred_code, false) \
348 V(DebugObjectCache*, string_stream_debug_object_cache, NULL) \
349 V(Object*, string_stream_current_security_token, NULL) \
350 /* TODO(isolates): Release this on destruction? */ \
351 V(int*, irregexp_interpreter_backtrack_stack_cache, NULL) \
352 /* Serializer state. */ \
353 V(ExternalReferenceTable*, external_reference_table, NULL) \
354 /* AstNode state. */ \
355 V(unsigned, ast_node_id, 0) \
356 V(unsigned, ast_node_count, 0) \
357 /* SafeStackFrameIterator activations count. */ \
358 V(int, safe_stack_iterator_counter, 0) \
359 V(uint64_t, enabled_cpu_features, 0) \
360 V(CpuProfiler*, cpu_profiler, NULL) \
361 V(HeapProfiler*, heap_profiler, NULL) \
362 ISOLATE_PLATFORM_INIT_LIST(V) \
363 ISOLATE_DEBUGGER_INIT_LIST(V)
366 // These forward declarations are required to make the friend declarations in
367 // PerIsolateThreadData work on some older versions of gcc.
368 class ThreadDataTable;
369 class EntryStackItem;
373 // A thread has a PerIsolateThreadData instance for each isolate that it has
374 // entered. That instance is allocated when the isolate is initially entered
375 // and reused on subsequent entries.
376 class PerIsolateThreadData {
378 PerIsolateThreadData(Isolate* isolate, ThreadId thread_id)
380 thread_id_(thread_id),
383 #if !defined(__arm__) && defined(V8_TARGET_ARCH_ARM) || \
384 !defined(__mips__) && defined(V8_TARGET_ARCH_MIPS)
389 Isolate* isolate() const { return isolate_; }
390 ThreadId thread_id() const { return thread_id_; }
391 void set_stack_limit(uintptr_t value) { stack_limit_ = value; }
392 uintptr_t stack_limit() const { return stack_limit_; }
393 ThreadState* thread_state() const { return thread_state_; }
394 void set_thread_state(ThreadState* value) { thread_state_ = value; }
396 #if !defined(__arm__) && defined(V8_TARGET_ARCH_ARM) || \
397 !defined(__mips__) && defined(V8_TARGET_ARCH_MIPS)
398 Simulator* simulator() const { return simulator_; }
399 void set_simulator(Simulator* simulator) {
400 simulator_ = simulator;
404 bool Matches(Isolate* isolate, ThreadId thread_id) const {
405 return isolate_ == isolate && thread_id_.Equals(thread_id);
411 uintptr_t stack_limit_;
412 ThreadState* thread_state_;
414 #if !defined(__arm__) && defined(V8_TARGET_ARCH_ARM) || \
415 !defined(__mips__) && defined(V8_TARGET_ARCH_MIPS)
416 Simulator* simulator_;
419 PerIsolateThreadData* next_;
420 PerIsolateThreadData* prev_;
422 friend class Isolate;
423 friend class ThreadDataTable;
424 friend class EntryStackItem;
426 DISALLOW_COPY_AND_ASSIGN(PerIsolateThreadData);
431 #define DECLARE_ENUM(CamelName, hacker_name) k##CamelName##Address,
432 FOR_EACH_ISOLATE_ADDRESS_NAME(DECLARE_ENUM)
437 // Returns the PerIsolateThreadData for the current thread (or NULL if one is
438 // not currently set).
439 static PerIsolateThreadData* CurrentPerIsolateThreadData() {
440 return reinterpret_cast<PerIsolateThreadData*>(
441 Thread::GetThreadLocal(per_isolate_thread_data_key_));
444 // Returns the isolate inside which the current thread is running.
445 INLINE(static Isolate* Current()) {
446 Isolate* isolate = reinterpret_cast<Isolate*>(
447 Thread::GetExistingThreadLocal(isolate_key_));
448 ASSERT(isolate != NULL);
452 INLINE(static Isolate* UncheckedCurrent()) {
453 return reinterpret_cast<Isolate*>(Thread::GetThreadLocal(isolate_key_));
456 // Usually called by Init(), but can be called early e.g. to allow
457 // testing components that require logging but not the whole
460 // Safe to call more than once.
461 void InitializeLoggingAndCounters();
463 bool Init(Deserializer* des);
465 bool IsInitialized() { return state_ == INITIALIZED; }
467 // True if at least one thread Enter'ed this isolate.
468 bool IsInUse() { return entry_stack_ != NULL; }
470 // Destroys the non-default isolates.
471 // Sets default isolate into "has_been_disposed" state rather then destroying,
472 // for legacy API reasons.
475 bool IsDefaultIsolate() const { return this == default_isolate_; }
477 // Ensures that process-wide resources and the default isolate have been
478 // allocated. It is only necessary to call this method in rare casses, for
479 // example if you are using V8 from within the body of a static initializer.
480 // Safe to call multiple times.
481 static void EnsureDefaultIsolate();
483 // Find the PerThread for this particular (isolate, thread) combination
484 // If one does not yet exist, return null.
485 PerIsolateThreadData* FindPerThreadDataForThisThread();
487 #ifdef ENABLE_DEBUGGER_SUPPORT
488 // Get the debugger from the default isolate. Preinitializes the
489 // default isolate if needed.
490 static Debugger* GetDefaultIsolateDebugger();
493 // Get the stack guard from the default isolate. Preinitializes the
494 // default isolate if needed.
495 static StackGuard* GetDefaultIsolateStackGuard();
497 // Returns the key used to store the pointer to the current isolate.
498 // Used internally for V8 threads that do not execute JavaScript but still
499 // are part of the domain of an isolate (like the context switcher).
500 static Thread::LocalStorageKey isolate_key() {
504 // Returns the key used to store process-wide thread IDs.
505 static Thread::LocalStorageKey thread_id_key() {
506 return thread_id_key_;
509 // If a client attempts to create a Locker without specifying an isolate,
510 // we assume that the client is using legacy behavior. Set up the current
511 // thread to be inside the implicit isolate (or fail a check if we have
512 // switched to non-legacy behavior).
513 static void EnterDefaultIsolate();
515 // Mutex for serializing access to break control structures.
516 Mutex* break_access() { return break_access_; }
518 // Mutex for serializing access to debugger.
519 Mutex* debugger_access() { return debugger_access_; }
521 Address get_address_from_id(AddressId id);
523 // Access to top context (where the current function object was created).
524 Context* context() { return thread_local_top_.context_; }
525 void set_context(Context* context) {
526 ASSERT(context == NULL || context->IsContext());
527 thread_local_top_.context_ = context;
529 Context** context_address() { return &thread_local_top_.context_; }
531 SaveContext* save_context() {return thread_local_top_.save_context_; }
532 void set_save_context(SaveContext* save) {
533 thread_local_top_.save_context_ = save;
536 // Access to current thread id.
537 ThreadId thread_id() { return thread_local_top_.thread_id_; }
538 void set_thread_id(ThreadId id) { thread_local_top_.thread_id_ = id; }
540 // Interface to pending exception.
541 MaybeObject* pending_exception() {
542 ASSERT(has_pending_exception());
543 return thread_local_top_.pending_exception_;
545 bool external_caught_exception() {
546 return thread_local_top_.external_caught_exception_;
548 void set_external_caught_exception(bool value) {
549 thread_local_top_.external_caught_exception_ = value;
551 void set_pending_exception(MaybeObject* exception) {
552 thread_local_top_.pending_exception_ = exception;
554 void clear_pending_exception() {
555 thread_local_top_.pending_exception_ = heap_.the_hole_value();
557 MaybeObject** pending_exception_address() {
558 return &thread_local_top_.pending_exception_;
560 bool has_pending_exception() {
561 return !thread_local_top_.pending_exception_->IsTheHole();
563 void clear_pending_message() {
564 thread_local_top_.has_pending_message_ = false;
565 thread_local_top_.pending_message_obj_ = heap_.the_hole_value();
566 thread_local_top_.pending_message_script_ = NULL;
568 v8::TryCatch* try_catch_handler() {
569 return thread_local_top_.TryCatchHandler();
571 Address try_catch_handler_address() {
572 return thread_local_top_.try_catch_handler_address();
574 bool* external_caught_exception_address() {
575 return &thread_local_top_.external_caught_exception_;
577 v8::TryCatch* catcher() {
578 return thread_local_top_.catcher_;
580 void set_catcher(v8::TryCatch* catcher) {
581 thread_local_top_.catcher_ = catcher;
584 MaybeObject** scheduled_exception_address() {
585 return &thread_local_top_.scheduled_exception_;
587 MaybeObject* scheduled_exception() {
588 ASSERT(has_scheduled_exception());
589 return thread_local_top_.scheduled_exception_;
591 bool has_scheduled_exception() {
592 return thread_local_top_.scheduled_exception_ != heap_.the_hole_value();
594 void clear_scheduled_exception() {
595 thread_local_top_.scheduled_exception_ = heap_.the_hole_value();
598 bool IsExternallyCaught();
600 bool is_catchable_by_javascript(MaybeObject* exception) {
601 return (exception != Failure::OutOfMemoryException()) &&
602 (exception != heap()->termination_exception());
605 // JS execution stack (see frames.h).
606 static Address c_entry_fp(ThreadLocalTop* thread) {
607 return thread->c_entry_fp_;
609 static Address handler(ThreadLocalTop* thread) { return thread->handler_; }
611 inline Address* c_entry_fp_address() {
612 return &thread_local_top_.c_entry_fp_;
614 inline Address* handler_address() { return &thread_local_top_.handler_; }
616 // Bottom JS entry (see StackTracer::Trace in log.cc).
617 static Address js_entry_sp(ThreadLocalTop* thread) {
618 return thread->js_entry_sp_;
620 inline Address* js_entry_sp_address() {
621 return &thread_local_top_.js_entry_sp_;
624 // Generated code scratch locations.
625 void* formal_count_address() { return &thread_local_top_.formal_count_; }
627 // Returns the global object of the current context. It could be
628 // a builtin object, or a js global object.
629 Handle<GlobalObject> global() {
630 return Handle<GlobalObject>(context()->global());
633 // Returns the global proxy object of the current context.
634 Object* global_proxy() {
635 return context()->global_proxy();
638 Handle<JSBuiltinsObject> js_builtins_object() {
639 return Handle<JSBuiltinsObject>(thread_local_top_.context_->builtins());
642 static int ArchiveSpacePerThread() { return sizeof(ThreadLocalTop); }
643 void FreeThreadResources() { thread_local_top_.Free(); }
645 // This method is called by the api after operations that may throw
646 // exceptions. If an exception was thrown and not handled by an external
647 // handler the exception is scheduled to be rethrown when we return to running
648 // JavaScript code. If an exception is scheduled true is returned.
649 bool OptionalRescheduleException(bool is_bottom_call);
651 class ExceptionScope {
653 explicit ExceptionScope(Isolate* isolate) :
654 // Scope currently can only be used for regular exceptions, not
655 // failures like OOM or termination exception.
657 pending_exception_(isolate_->pending_exception()->ToObjectUnchecked()),
658 catcher_(isolate_->catcher())
662 isolate_->set_catcher(catcher_);
663 isolate_->set_pending_exception(*pending_exception_);
668 Handle<Object> pending_exception_;
669 v8::TryCatch* catcher_;
672 void SetCaptureStackTraceForUncaughtExceptions(
675 StackTrace::StackTraceOptions options);
677 // Tells whether the current context has experienced an out of memory
679 bool is_out_of_memory();
680 bool ignore_out_of_memory() {
681 return thread_local_top_.ignore_out_of_memory_;
683 void set_ignore_out_of_memory(bool value) {
684 thread_local_top_.ignore_out_of_memory_ = value;
687 void PrintCurrentStackTrace(FILE* out);
688 void PrintStackTrace(FILE* out, char* thread_data);
689 void PrintStack(StringStream* accumulator);
691 Handle<String> StackTraceString();
692 Handle<JSArray> CaptureCurrentStackTrace(
694 StackTrace::StackTraceOptions options);
696 // Returns if the top context may access the given global object. If
697 // the result is false, the pending exception is guaranteed to be
699 bool MayNamedAccess(JSObject* receiver,
701 v8::AccessType type);
702 bool MayIndexedAccess(JSObject* receiver,
704 v8::AccessType type);
706 void SetFailedAccessCheckCallback(v8::FailedAccessCheckCallback callback);
707 void ReportFailedAccessCheck(JSObject* receiver, v8::AccessType type);
709 void SetUserObjectComparisonCallback(v8::UserObjectComparisonCallback callback);
710 inline v8::UserObjectComparisonCallback UserObjectComparisonCallback() {
711 return thread_local_top()->user_object_comparison_callback_;
714 // Exception throwing support. The caller should use the result
715 // of Throw() as its return value.
716 Failure* Throw(Object* exception, MessageLocation* location = NULL);
717 // Re-throw an exception. This involves no error reporting since
718 // error reporting was handled when the exception was thrown
720 Failure* ReThrow(MaybeObject* exception, MessageLocation* location = NULL);
721 void ScheduleThrow(Object* exception);
722 void ReportPendingMessages();
723 Failure* ThrowIllegalOperation();
725 // Promote a scheduled exception to pending. Asserts has_scheduled_exception.
726 Failure* PromoteScheduledException();
727 void DoThrow(MaybeObject* exception, MessageLocation* location);
728 // Checks if exception should be reported and finds out if it's
729 // caught externally.
730 bool ShouldReportException(bool* can_be_caught_externally,
731 bool catchable_by_javascript);
733 // Attempts to compute the current source location, storing the
734 // result in the target out parameter.
735 void ComputeLocation(MessageLocation* target);
737 // Override command line flag.
738 void TraceException(bool flag);
740 // Out of resource exception helpers.
741 Failure* StackOverflow();
742 Failure* TerminateExecution();
745 void Iterate(ObjectVisitor* v);
746 void Iterate(ObjectVisitor* v, ThreadLocalTop* t);
747 char* Iterate(ObjectVisitor* v, char* t);
748 void IterateThread(ThreadVisitor* v);
749 void IterateThread(ThreadVisitor* v, char* t);
752 // Returns the current global context.
753 Handle<Context> global_context();
755 // Returns the global context of the calling JavaScript code. That
756 // is, the global context of the top-most JavaScript frame.
757 Handle<Context> GetCallingGlobalContext();
759 void RegisterTryCatchHandler(v8::TryCatch* that);
760 void UnregisterTryCatchHandler(v8::TryCatch* that);
762 char* ArchiveThread(char* to);
763 char* RestoreThread(char* from);
765 static const char* const kStackOverflowMessage;
767 static const int kUC16AlphabetSize = 256; // See StringSearchBase.
768 static const int kBMMaxShift = 250; // See StringSearchBase.
771 #define GLOBAL_ACCESSOR(type, name, initialvalue) \
772 inline type name() const { \
773 ASSERT(OFFSET_OF(Isolate, name##_) == name##_debug_offset_); \
776 inline void set_##name(type value) { \
777 ASSERT(OFFSET_OF(Isolate, name##_) == name##_debug_offset_); \
780 ISOLATE_INIT_LIST(GLOBAL_ACCESSOR)
781 #undef GLOBAL_ACCESSOR
783 #define GLOBAL_ARRAY_ACCESSOR(type, name, length) \
784 inline type* name() { \
785 ASSERT(OFFSET_OF(Isolate, name##_) == name##_debug_offset_); \
786 return &(name##_)[0]; \
788 ISOLATE_INIT_ARRAY_LIST(GLOBAL_ARRAY_ACCESSOR)
789 #undef GLOBAL_ARRAY_ACCESSOR
791 #define GLOBAL_CONTEXT_FIELD_ACCESSOR(index, type, name) \
792 Handle<type> name() { \
793 return Handle<type>(context()->global_context()->name()); \
795 GLOBAL_CONTEXT_FIELDS(GLOBAL_CONTEXT_FIELD_ACCESSOR)
796 #undef GLOBAL_CONTEXT_FIELD_ACCESSOR
798 Bootstrapper* bootstrapper() { return bootstrapper_; }
799 Counters* counters() {
800 // Call InitializeLoggingAndCounters() if logging is needed before
801 // the isolate is fully initialized.
802 ASSERT(counters_ != NULL);
805 CodeRange* code_range() { return code_range_; }
806 RuntimeProfiler* runtime_profiler() { return runtime_profiler_; }
807 CompilationCache* compilation_cache() { return compilation_cache_; }
809 // Call InitializeLoggingAndCounters() if logging is needed before
810 // the isolate is fully initialized.
811 ASSERT(logger_ != NULL);
814 StackGuard* stack_guard() { return &stack_guard_; }
815 Heap* heap() { return &heap_; }
816 StatsTable* stats_table();
817 StubCache* stub_cache() { return stub_cache_; }
818 DeoptimizerData* deoptimizer_data() { return deoptimizer_data_; }
819 ThreadLocalTop* thread_local_top() { return &thread_local_top_; }
821 TranscendentalCache* transcendental_cache() const {
822 return transcendental_cache_;
825 MemoryAllocator* memory_allocator() {
826 return memory_allocator_;
829 KeyedLookupCache* keyed_lookup_cache() {
830 return keyed_lookup_cache_;
833 ContextSlotCache* context_slot_cache() {
834 return context_slot_cache_;
837 DescriptorLookupCache* descriptor_lookup_cache() {
838 return descriptor_lookup_cache_;
841 v8::ImplementationUtilities::HandleScopeData* handle_scope_data() {
842 return &handle_scope_data_;
844 HandleScopeImplementer* handle_scope_implementer() {
845 ASSERT(handle_scope_implementer_);
846 return handle_scope_implementer_;
848 Zone* zone() { return &zone_; }
850 UnicodeCache* unicode_cache() {
851 return unicode_cache_;
854 InnerPointerToCodeCache* inner_pointer_to_code_cache() {
855 return inner_pointer_to_code_cache_;
858 StringInputBuffer* write_input_buffer() { return write_input_buffer_; }
860 GlobalHandles* global_handles() { return global_handles_; }
862 ThreadManager* thread_manager() { return thread_manager_; }
864 ContextSwitcher* context_switcher() { return context_switcher_; }
866 void set_context_switcher(ContextSwitcher* switcher) {
867 context_switcher_ = switcher;
870 StringTracker* string_tracker() { return string_tracker_; }
872 unibrow::Mapping<unibrow::Ecma262UnCanonicalize>* jsregexp_uncanonicalize() {
873 return &jsregexp_uncanonicalize_;
876 unibrow::Mapping<unibrow::CanonicalizationRange>* jsregexp_canonrange() {
877 return &jsregexp_canonrange_;
880 StringInputBuffer* objects_string_compare_buffer_a() {
881 return &objects_string_compare_buffer_a_;
884 StringInputBuffer* objects_string_compare_buffer_b() {
885 return &objects_string_compare_buffer_b_;
888 StaticResource<StringInputBuffer>* objects_string_input_buffer() {
889 return &objects_string_input_buffer_;
892 RuntimeState* runtime_state() { return &runtime_state_; }
894 void set_fp_stubs_generated(bool value) {
895 fp_stubs_generated_ = value;
898 bool fp_stubs_generated() { return fp_stubs_generated_; }
900 StaticResource<SafeStringInputBuffer>* compiler_safe_string_input_buffer() {
901 return &compiler_safe_string_input_buffer_;
904 Builtins* builtins() { return &builtins_; }
906 unibrow::Mapping<unibrow::Ecma262Canonicalize>*
907 regexp_macro_assembler_canonicalize() {
908 return ®exp_macro_assembler_canonicalize_;
911 RegExpStack* regexp_stack() { return regexp_stack_; }
913 unibrow::Mapping<unibrow::Ecma262Canonicalize>*
914 interp_canonicalize_mapping() {
915 return &interp_canonicalize_mapping_;
918 void* PreallocatedStorageNew(size_t size);
919 void PreallocatedStorageDelete(void* p);
920 void PreallocatedStorageInit(size_t size);
922 #ifdef ENABLE_DEBUGGER_SUPPORT
923 Debugger* debugger() {
924 if (!NoBarrier_Load(&debugger_initialized_)) InitializeDebugger();
928 if (!NoBarrier_Load(&debugger_initialized_)) InitializeDebugger();
933 inline bool DebuggerHasBreakPoints();
936 HistogramInfo* heap_histograms() { return heap_histograms_; }
938 JSObject::SpillInformation* js_spill_information() {
939 return &js_spill_information_;
942 int* code_kind_statistics() { return code_kind_statistics_; }
945 #if defined(V8_TARGET_ARCH_ARM) && !defined(__arm__) || \
946 defined(V8_TARGET_ARCH_MIPS) && !defined(__mips__)
947 bool simulator_initialized() { return simulator_initialized_; }
948 void set_simulator_initialized(bool initialized) {
949 simulator_initialized_ = initialized;
952 HashMap* simulator_i_cache() { return simulator_i_cache_; }
953 void set_simulator_i_cache(HashMap* hash_map) {
954 simulator_i_cache_ = hash_map;
957 Redirection* simulator_redirection() {
958 return simulator_redirection_;
960 void set_simulator_redirection(Redirection* redirection) {
961 simulator_redirection_ = redirection;
965 Factory* factory() { return reinterpret_cast<Factory*>(this); }
967 // SerializerDeserializer state.
968 static const int kPartialSnapshotCacheCapacity = 1400;
970 static const int kJSRegexpStaticOffsetsVectorSize = 50;
972 Address external_callback() {
973 return thread_local_top_.external_callback_;
975 void set_external_callback(Address callback) {
976 thread_local_top_.external_callback_ = callback;
979 StateTag current_vm_state() {
980 return thread_local_top_.current_vm_state_;
983 void SetCurrentVMState(StateTag state) {
984 if (RuntimeProfiler::IsEnabled()) {
985 // Make sure thread local top is initialized.
986 ASSERT(thread_local_top_.isolate_ == this);
987 StateTag current_state = thread_local_top_.current_vm_state_;
988 if (current_state != JS && state == JS) {
989 // Non-JS -> JS transition.
990 RuntimeProfiler::IsolateEnteredJS(this);
991 } else if (current_state == JS && state != JS) {
992 // JS -> non-JS transition.
993 ASSERT(RuntimeProfiler::IsSomeIsolateInJS());
994 RuntimeProfiler::IsolateExitedJS(this);
996 // Other types of state transitions are not interesting to the
997 // runtime profiler, because they don't affect whether we're
999 ASSERT((current_state == JS) == (state == JS));
1002 thread_local_top_.current_vm_state_ = state;
1005 void SetData(void* data) { embedder_data_ = data; }
1006 void* GetData() { return embedder_data_; }
1008 LookupResult* top_lookup_result() {
1009 return thread_local_top_.top_lookup_result_;
1011 void SetTopLookupResult(LookupResult* top) {
1012 thread_local_top_.top_lookup_result_ = top;
1018 // The per-process lock should be acquired before the ThreadDataTable is
1020 class ThreadDataTable {
1025 PerIsolateThreadData* Lookup(Isolate* isolate, ThreadId thread_id);
1026 void Insert(PerIsolateThreadData* data);
1027 void Remove(Isolate* isolate, ThreadId thread_id);
1028 void Remove(PerIsolateThreadData* data);
1029 void RemoveAllThreads(Isolate* isolate);
1032 PerIsolateThreadData* list_;
1035 // These items form a stack synchronously with threads Enter'ing and Exit'ing
1036 // the Isolate. The top of the stack points to a thread which is currently
1037 // running the Isolate. When the stack is empty, the Isolate is considered
1038 // not entered by any thread and can be Disposed.
1039 // If the same thread enters the Isolate more then once, the entry_count_
1040 // is incremented rather then a new item pushed to the stack.
1041 class EntryStackItem {
1043 EntryStackItem(PerIsolateThreadData* previous_thread_data,
1044 Isolate* previous_isolate,
1045 EntryStackItem* previous_item)
1047 previous_thread_data(previous_thread_data),
1048 previous_isolate(previous_isolate),
1049 previous_item(previous_item) { }
1052 PerIsolateThreadData* previous_thread_data;
1053 Isolate* previous_isolate;
1054 EntryStackItem* previous_item;
1056 DISALLOW_COPY_AND_ASSIGN(EntryStackItem);
1059 // This mutex protects highest_thread_id_, thread_data_table_ and
1060 // default_isolate_.
1061 static Mutex* process_wide_mutex_;
1063 static Thread::LocalStorageKey per_isolate_thread_data_key_;
1064 static Thread::LocalStorageKey isolate_key_;
1065 static Thread::LocalStorageKey thread_id_key_;
1066 static Isolate* default_isolate_;
1067 static ThreadDataTable* thread_data_table_;
1071 static void SetIsolateThreadLocals(Isolate* isolate,
1072 PerIsolateThreadData* data);
1075 UNINITIALIZED, // Some components may not have been allocated.
1076 INITIALIZED // All components are fully initialized.
1080 EntryStackItem* entry_stack_;
1082 // Allocate and insert PerIsolateThreadData into the ThreadDataTable
1083 // (regardless of whether such data already exists).
1084 PerIsolateThreadData* AllocatePerIsolateThreadData(ThreadId thread_id);
1086 // Find the PerThread for this particular (isolate, thread) combination.
1087 // If one does not yet exist, allocate a new one.
1088 PerIsolateThreadData* FindOrAllocatePerThreadDataForThisThread();
1090 // PreInits and returns a default isolate. Needed when a new thread tries
1091 // to create a Locker for the first time (the lock itself is in the isolate).
1092 static Isolate* GetDefaultIsolateForLocking();
1094 // Initializes the current thread to run this Isolate.
1095 // Not thread-safe. Multiple threads should not Enter/Exit the same isolate
1096 // at the same time, this should be prevented using external locking.
1099 // Exits the current thread. The previosuly entered Isolate is restored
1101 // Not thread-safe. Multiple threads should not Enter/Exit the same isolate
1102 // at the same time, this should be prevented using external locking.
1105 void PreallocatedMemoryThreadStart();
1106 void PreallocatedMemoryThreadStop();
1107 void InitializeThreadLocal();
1109 void PrintStackTrace(FILE* out, ThreadLocalTop* thread);
1110 void MarkCompactPrologue(bool is_compacting,
1111 ThreadLocalTop* archived_thread_data);
1112 void MarkCompactEpilogue(bool is_compacting,
1113 ThreadLocalTop* archived_thread_data);
1117 void PropagatePendingExceptionToExternalTryCatch();
1119 void InitializeDebugger();
1121 int stack_trace_nesting_level_;
1122 StringStream* incomplete_message_;
1123 // The preallocated memory thread singleton.
1124 PreallocatedMemoryThread* preallocated_memory_thread_;
1125 Address isolate_addresses_[kIsolateAddressCount + 1]; // NOLINT
1126 NoAllocationStringAllocator* preallocated_message_space_;
1128 Bootstrapper* bootstrapper_;
1129 RuntimeProfiler* runtime_profiler_;
1130 CompilationCache* compilation_cache_;
1131 Counters* counters_;
1132 CodeRange* code_range_;
1133 Mutex* break_access_;
1134 Atomic32 debugger_initialized_;
1135 Mutex* debugger_access_;
1138 StackGuard stack_guard_;
1139 StatsTable* stats_table_;
1140 StubCache* stub_cache_;
1141 DeoptimizerData* deoptimizer_data_;
1142 ThreadLocalTop thread_local_top_;
1143 bool capture_stack_trace_for_uncaught_exceptions_;
1144 int stack_trace_for_uncaught_exceptions_frame_limit_;
1145 StackTrace::StackTraceOptions stack_trace_for_uncaught_exceptions_options_;
1146 TranscendentalCache* transcendental_cache_;
1147 MemoryAllocator* memory_allocator_;
1148 KeyedLookupCache* keyed_lookup_cache_;
1149 ContextSlotCache* context_slot_cache_;
1150 DescriptorLookupCache* descriptor_lookup_cache_;
1151 v8::ImplementationUtilities::HandleScopeData handle_scope_data_;
1152 HandleScopeImplementer* handle_scope_implementer_;
1153 UnicodeCache* unicode_cache_;
1155 PreallocatedStorage in_use_list_;
1156 PreallocatedStorage free_list_;
1157 bool preallocated_storage_preallocated_;
1158 InnerPointerToCodeCache* inner_pointer_to_code_cache_;
1159 StringInputBuffer* write_input_buffer_;
1160 GlobalHandles* global_handles_;
1161 ContextSwitcher* context_switcher_;
1162 ThreadManager* thread_manager_;
1163 RuntimeState runtime_state_;
1164 bool fp_stubs_generated_;
1165 StaticResource<SafeStringInputBuffer> compiler_safe_string_input_buffer_;
1167 StringTracker* string_tracker_;
1168 unibrow::Mapping<unibrow::Ecma262UnCanonicalize> jsregexp_uncanonicalize_;
1169 unibrow::Mapping<unibrow::CanonicalizationRange> jsregexp_canonrange_;
1170 StringInputBuffer objects_string_compare_buffer_a_;
1171 StringInputBuffer objects_string_compare_buffer_b_;
1172 StaticResource<StringInputBuffer> objects_string_input_buffer_;
1173 unibrow::Mapping<unibrow::Ecma262Canonicalize>
1174 regexp_macro_assembler_canonicalize_;
1175 RegExpStack* regexp_stack_;
1176 unibrow::Mapping<unibrow::Ecma262Canonicalize> interp_canonicalize_mapping_;
1177 void* embedder_data_;
1179 #if defined(V8_TARGET_ARCH_ARM) && !defined(__arm__) || \
1180 defined(V8_TARGET_ARCH_MIPS) && !defined(__mips__)
1181 bool simulator_initialized_;
1182 HashMap* simulator_i_cache_;
1183 Redirection* simulator_redirection_;
1187 // A static array of histogram info for each type.
1188 HistogramInfo heap_histograms_[LAST_TYPE + 1];
1189 JSObject::SpillInformation js_spill_information_;
1190 int code_kind_statistics_[Code::NUMBER_OF_KINDS];
1193 #ifdef ENABLE_DEBUGGER_SUPPORT
1194 Debugger* debugger_;
1198 #define GLOBAL_BACKING_STORE(type, name, initialvalue) \
1200 ISOLATE_INIT_LIST(GLOBAL_BACKING_STORE)
1201 #undef GLOBAL_BACKING_STORE
1203 #define GLOBAL_ARRAY_BACKING_STORE(type, name, length) \
1204 type name##_[length];
1205 ISOLATE_INIT_ARRAY_LIST(GLOBAL_ARRAY_BACKING_STORE)
1206 #undef GLOBAL_ARRAY_BACKING_STORE
1209 // This class is huge and has a number of fields controlled by
1210 // preprocessor defines. Make sure the offsets of these fields agree
1211 // between compilation units.
1212 #define ISOLATE_FIELD_OFFSET(type, name, ignored) \
1213 static const intptr_t name##_debug_offset_;
1214 ISOLATE_INIT_LIST(ISOLATE_FIELD_OFFSET)
1215 ISOLATE_INIT_ARRAY_LIST(ISOLATE_FIELD_OFFSET)
1216 #undef ISOLATE_FIELD_OFFSET
1219 friend class ExecutionAccess;
1220 friend class IsolateInitializer;
1221 friend class ThreadManager;
1222 friend class Simulator;
1223 friend class StackGuard;
1224 friend class ThreadId;
1225 friend class TestMemoryAllocatorScope;
1226 friend class v8::Isolate;
1227 friend class v8::Locker;
1228 friend class v8::Unlocker;
1230 DISALLOW_COPY_AND_ASSIGN(Isolate);
1234 // If the GCC version is 4.1.x or 4.2.x an additional field is added to the
1235 // class as a work around for a bug in the generated code found with these
1236 // versions of GCC. See V8 issue 122 for details.
1237 class SaveContext BASE_EMBEDDED {
1239 inline explicit SaveContext(Isolate* isolate);
1242 if (context_.is_null()) {
1243 Isolate* isolate = Isolate::Current();
1244 isolate->set_context(NULL);
1245 isolate->set_save_context(prev_);
1247 Isolate* isolate = context_->GetIsolate();
1248 isolate->set_context(*context_);
1249 isolate->set_save_context(prev_);
1253 Handle<Context> context() { return context_; }
1254 SaveContext* prev() { return prev_; }
1256 // Returns true if this save context is below a given JavaScript frame.
1257 bool IsBelowFrame(JavaScriptFrame* frame) {
1258 return (c_entry_fp_ == 0) || (c_entry_fp_ > frame->sp());
1262 Handle<Context> context_;
1263 #if __GNUC_VERSION__ >= 40100 && __GNUC_VERSION__ < 40300
1264 Handle<Context> dummy_;
1267 Address c_entry_fp_;
1271 class AssertNoContextChange BASE_EMBEDDED {
1274 AssertNoContextChange() :
1275 scope_(Isolate::Current()),
1276 context_(Isolate::Current()->context(), Isolate::Current()) {
1279 ~AssertNoContextChange() {
1280 ASSERT(Isolate::Current()->context() == *context_);
1285 Handle<Context> context_;
1288 AssertNoContextChange() { }
1293 class ExecutionAccess BASE_EMBEDDED {
1295 explicit ExecutionAccess(Isolate* isolate) : isolate_(isolate) {
1298 ~ExecutionAccess() { Unlock(isolate_); }
1300 static void Lock(Isolate* isolate) { isolate->break_access_->Lock(); }
1301 static void Unlock(Isolate* isolate) { isolate->break_access_->Unlock(); }
1303 static bool TryLock(Isolate* isolate) {
1304 return isolate->break_access_->TryLock();
1312 // Support for checking for stack-overflows in C++ code.
1313 class StackLimitCheck BASE_EMBEDDED {
1315 explicit StackLimitCheck(Isolate* isolate) : isolate_(isolate) { }
1317 bool HasOverflowed() const {
1318 StackGuard* stack_guard = isolate_->stack_guard();
1319 // Stack has overflowed in C++ code only if stack pointer exceeds the C++
1320 // stack guard and the limits are not set to interrupt values.
1321 // TODO(214): Stack overflows are ignored if a interrupt is pending. This
1322 // code should probably always use the initial C++ limit.
1323 return (reinterpret_cast<uintptr_t>(this) < stack_guard->climit()) &&
1324 stack_guard->IsStackOverflow();
1331 // Support for temporarily postponing interrupts. When the outermost
1332 // postpone scope is left the interrupts will be re-enabled and any
1333 // interrupts that occurred while in the scope will be taken into
1335 class PostponeInterruptsScope BASE_EMBEDDED {
1337 explicit PostponeInterruptsScope(Isolate* isolate)
1338 : stack_guard_(isolate->stack_guard()) {
1339 stack_guard_->thread_local_.postpone_interrupts_nesting_++;
1340 stack_guard_->DisableInterrupts();
1343 ~PostponeInterruptsScope() {
1344 if (--stack_guard_->thread_local_.postpone_interrupts_nesting_ == 0) {
1345 stack_guard_->EnableInterrupts();
1349 StackGuard* stack_guard_;
1353 // Temporary macros for accessing current isolate and its subobjects.
1354 // They provide better readability, especially when used a lot in the code.
1355 #define HEAP (v8::internal::Isolate::Current()->heap())
1356 #define FACTORY (v8::internal::Isolate::Current()->factory())
1357 #define ISOLATE (v8::internal::Isolate::Current())
1358 #define ZONE (v8::internal::Isolate::Current()->zone())
1359 #define LOGGER (v8::internal::Isolate::Current()->logger())
1362 // Tells whether the global context is marked with out of memory.
1363 inline bool Context::has_out_of_memory() {
1364 return global_context()->out_of_memory()->IsTrue();
1368 // Mark the global context with out of memory.
1369 inline void Context::mark_out_of_memory() {
1370 global_context()->set_out_of_memory(HEAP->true_value());
1374 } } // namespace v8::internal
1376 #endif // V8_ISOLATE_H_