• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
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 "atomicops.h"
35 #include "builtins.h"
36 #include "contexts.h"
37 #include "execution.h"
38 #include "frames.h"
39 #include "global-handles.h"
40 #include "handles.h"
41 #include "heap.h"
42 #include "regexp-stack.h"
43 #include "runtime-profiler.h"
44 #include "runtime.h"
45 #include "zone.h"
46 
47 namespace v8 {
48 namespace internal {
49 
50 class AstSentinels;
51 class Bootstrapper;
52 class CodeGenerator;
53 class CodeRange;
54 class CompilationCache;
55 class ContextSlotCache;
56 class ContextSwitcher;
57 class Counters;
58 class CpuFeatures;
59 class CpuProfiler;
60 class DeoptimizerData;
61 class Deserializer;
62 class EmptyStatement;
63 class ExternalReferenceTable;
64 class Factory;
65 class FunctionInfoListener;
66 class HandleScopeImplementer;
67 class HeapProfiler;
68 class InlineRuntimeFunctionsTable;
69 class NoAllocationStringAllocator;
70 class PcToCodeCache;
71 class PreallocatedMemoryThread;
72 class ProducerHeapProfile;
73 class RegExpStack;
74 class SaveContext;
75 class UnicodeCache;
76 class StringInputBuffer;
77 class StringTracker;
78 class StubCache;
79 class ThreadManager;
80 class ThreadState;
81 class ThreadVisitor;  // Defined in v8threads.h
82 class VMState;
83 
84 // 'void function pointer', used to roundtrip the
85 // ExternalReference::ExternalReferenceRedirector since we can not include
86 // assembler.h, where it is defined, here.
87 typedef void* ExternalReferenceRedirectorPointer();
88 
89 
90 #ifdef ENABLE_DEBUGGER_SUPPORT
91 class Debug;
92 class Debugger;
93 class DebuggerAgent;
94 #endif
95 
96 #if !defined(__arm__) && defined(V8_TARGET_ARCH_ARM) || \
97     !defined(__mips__) && defined(V8_TARGET_ARCH_MIPS)
98 class Redirection;
99 class Simulator;
100 #endif
101 
102 
103 // Static indirection table for handles to constants.  If a frame
104 // element represents a constant, the data contains an index into
105 // this table of handles to the actual constants.
106 // Static indirection table for handles to constants.  If a Result
107 // represents a constant, the data contains an index into this table
108 // of handles to the actual constants.
109 typedef ZoneList<Handle<Object> > ZoneObjectList;
110 
111 #define RETURN_IF_SCHEDULED_EXCEPTION(isolate)    \
112   if (isolate->has_scheduled_exception())         \
113       return isolate->PromoteScheduledException()
114 
115 #define RETURN_IF_EMPTY_HANDLE_VALUE(isolate, call, value) \
116   if (call.is_null()) {                                    \
117     ASSERT(isolate->has_pending_exception());              \
118     return value;                                          \
119   }
120 
121 #define RETURN_IF_EMPTY_HANDLE(isolate, call)                       \
122   RETURN_IF_EMPTY_HANDLE_VALUE(isolate, call, Failure::Exception())
123 
124 #define ISOLATE_ADDRESS_LIST(C)            \
125   C(handler_address)                       \
126   C(c_entry_fp_address)                    \
127   C(context_address)                       \
128   C(pending_exception_address)             \
129   C(external_caught_exception_address)
130 
131 #ifdef ENABLE_LOGGING_AND_PROFILING
132 #define ISOLATE_ADDRESS_LIST_PROF(C)       \
133   C(js_entry_sp_address)
134 #else
135 #define ISOLATE_ADDRESS_LIST_PROF(C)
136 #endif
137 
138 
139 // Platform-independent, reliable thread identifier.
140 class ThreadId {
141  public:
142   // Creates an invalid ThreadId.
ThreadId()143   ThreadId() : id_(kInvalidId) {}
144 
145   // Returns ThreadId for current thread.
Current()146   static ThreadId Current() { return ThreadId(GetCurrentThreadId()); }
147 
148   // Returns invalid ThreadId (guaranteed not to be equal to any thread).
Invalid()149   static ThreadId Invalid() { return ThreadId(kInvalidId); }
150 
151   // Compares ThreadIds for equality.
INLINE(bool Equals (const ThreadId & other)const)152   INLINE(bool Equals(const ThreadId& other) const) {
153     return id_ == other.id_;
154   }
155 
156   // Checks whether this ThreadId refers to any thread.
INLINE(bool IsValid ()const)157   INLINE(bool IsValid() const) {
158     return id_ != kInvalidId;
159   }
160 
161   // Converts ThreadId to an integer representation
162   // (required for public API: V8::V8::GetCurrentThreadId).
ToInteger()163   int ToInteger() const { return id_; }
164 
165   // Converts ThreadId to an integer representation
166   // (required for public API: V8::V8::TerminateExecution).
FromInteger(int id)167   static ThreadId FromInteger(int id) { return ThreadId(id); }
168 
169  private:
170   static const int kInvalidId = -1;
171 
ThreadId(int id)172   explicit ThreadId(int id) : id_(id) {}
173 
174   static int AllocateThreadId();
175 
176   static int GetCurrentThreadId();
177 
178   int id_;
179 
180   static Atomic32 highest_thread_id_;
181 
182   friend class Isolate;
183 };
184 
185 
186 class ThreadLocalTop BASE_EMBEDDED {
187  public:
188   // Does early low-level initialization that does not depend on the
189   // isolate being present.
190   ThreadLocalTop();
191 
192   // Initialize the thread data.
193   void Initialize();
194 
195   // Get the top C++ try catch handler or NULL if none are registered.
196   //
197   // This method is not guarenteed to return an address that can be
198   // used for comparison with addresses into the JS stack.  If such an
199   // address is needed, use try_catch_handler_address.
200   v8::TryCatch* TryCatchHandler();
201 
202   // Get the address of the top C++ try catch handler or NULL if
203   // none are registered.
204   //
205   // This method always returns an address that can be compared to
206   // pointers into the JavaScript stack.  When running on actual
207   // hardware, try_catch_handler_address and TryCatchHandler return
208   // the same pointer.  When running on a simulator with a separate JS
209   // stack, try_catch_handler_address returns a JS stack address that
210   // corresponds to the place on the JS stack where the C++ handler
211   // would have been if the stack were not separate.
try_catch_handler_address()212   inline Address try_catch_handler_address() {
213     return try_catch_handler_address_;
214   }
215 
216   // Set the address of the top C++ try catch handler.
set_try_catch_handler_address(Address address)217   inline void set_try_catch_handler_address(Address address) {
218     try_catch_handler_address_ = address;
219   }
220 
Free()221   void Free() {
222     ASSERT(!has_pending_message_);
223     ASSERT(!external_caught_exception_);
224     ASSERT(try_catch_handler_address_ == NULL);
225   }
226 
227   // The context where the current execution method is created and for variable
228   // lookups.
229   Context* context_;
230   ThreadId thread_id_;
231   MaybeObject* pending_exception_;
232   bool has_pending_message_;
233   Object* pending_message_obj_;
234   Script* pending_message_script_;
235   int pending_message_start_pos_;
236   int pending_message_end_pos_;
237   // Use a separate value for scheduled exceptions to preserve the
238   // invariants that hold about pending_exception.  We may want to
239   // unify them later.
240   MaybeObject* scheduled_exception_;
241   bool external_caught_exception_;
242   SaveContext* save_context_;
243   v8::TryCatch* catcher_;
244 
245   // Stack.
246   Address c_entry_fp_;  // the frame pointer of the top c entry frame
247   Address handler_;   // try-blocks are chained through the stack
248 
249 #ifdef USE_SIMULATOR
250 #if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_MIPS)
251   Simulator* simulator_;
252 #endif
253 #endif  // USE_SIMULATOR
254 
255 #ifdef ENABLE_LOGGING_AND_PROFILING
256   Address js_entry_sp_;  // the stack pointer of the bottom js entry frame
257   Address external_callback_;  // the external callback we're currently in
258 #endif
259 
260 #ifdef ENABLE_VMSTATE_TRACKING
261   StateTag current_vm_state_;
262 #endif
263 
264   // Generated code scratch locations.
265   int32_t formal_count_;
266 
267   // Call back function to report unsafe JS accesses.
268   v8::FailedAccessCheckCallback failed_access_check_callback_;
269 
270   // Whether out of memory exceptions should be ignored.
271   bool ignore_out_of_memory_;
272 
273  private:
274   void InitializeInternal();
275 
276   Address try_catch_handler_address_;
277 };
278 
279 #if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_MIPS)
280 
281 #define ISOLATE_PLATFORM_INIT_LIST(V)                                          \
282   /* VirtualFrame::SpilledScope state */                                       \
283   V(bool, is_virtual_frame_in_spilled_scope, false)                            \
284   /* CodeGenerator::EmitNamedStore state */                                    \
285   V(int, inlined_write_barrier_size, -1)
286 
287 #if !defined(__arm__) && !defined(__mips__)
288 class HashMap;
289 #endif
290 
291 #else
292 
293 #define ISOLATE_PLATFORM_INIT_LIST(V)
294 
295 #endif
296 
297 #ifdef ENABLE_DEBUGGER_SUPPORT
298 
299 #define ISOLATE_DEBUGGER_INIT_LIST(V)                                          \
300   V(uint64_t, enabled_cpu_features, 0)                                         \
301   V(v8::Debug::EventCallback, debug_event_callback, NULL)                      \
302   V(DebuggerAgent*, debugger_agent_instance, NULL)
303 #else
304 
305 #define ISOLATE_DEBUGGER_INIT_LIST(V)
306 
307 #endif
308 
309 #ifdef DEBUG
310 
311 #define ISOLATE_INIT_DEBUG_ARRAY_LIST(V)                                       \
312   V(CommentStatistic, paged_space_comments_statistics,                         \
313       CommentStatistic::kMaxComments + 1)
314 #else
315 
316 #define ISOLATE_INIT_DEBUG_ARRAY_LIST(V)
317 
318 #endif
319 
320 #ifdef ENABLE_LOGGING_AND_PROFILING
321 
322 #define ISOLATE_LOGGING_INIT_LIST(V)                                           \
323   V(CpuProfiler*, cpu_profiler, NULL)                                          \
324   V(HeapProfiler*, heap_profiler, NULL)
325 
326 #else
327 
328 #define ISOLATE_LOGGING_INIT_LIST(V)
329 
330 #endif
331 
332 #define ISOLATE_INIT_ARRAY_LIST(V)                                             \
333   /* SerializerDeserializer state. */                                          \
334   V(Object*, serialize_partial_snapshot_cache, kPartialSnapshotCacheCapacity)  \
335   V(int, jsregexp_static_offsets_vector, kJSRegexpStaticOffsetsVectorSize)     \
336   V(int, bad_char_shift_table, kUC16AlphabetSize)                              \
337   V(int, good_suffix_shift_table, (kBMMaxShift + 1))                           \
338   V(int, suffix_table, (kBMMaxShift + 1))                                      \
339   ISOLATE_INIT_DEBUG_ARRAY_LIST(V)
340 
341 typedef List<HeapObject*, PreallocatedStorage> DebugObjectCache;
342 
343 #define ISOLATE_INIT_LIST(V)                                                   \
344   /* AssertNoZoneAllocation state. */                                          \
345   V(bool, zone_allow_allocation, true)                                         \
346   /* SerializerDeserializer state. */                                          \
347   V(int, serialize_partial_snapshot_cache_length, 0)                           \
348   /* Assembler state. */                                                       \
349   /* A previously allocated buffer of kMinimalBufferSize bytes, or NULL. */    \
350   V(byte*, assembler_spare_buffer, NULL)                                       \
351   V(FatalErrorCallback, exception_behavior, NULL)                              \
352   V(v8::Debug::MessageHandler, message_handler, NULL)                          \
353   /* To distinguish the function templates, so that we can find them in the */ \
354   /* function cache of the global context. */                                  \
355   V(int, next_serial_number, 0)                                                \
356   V(ExternalReferenceRedirectorPointer*, external_reference_redirector, NULL)  \
357   V(bool, always_allow_natives_syntax, false)                                  \
358   /* Part of the state of liveedit. */                                         \
359   V(FunctionInfoListener*, active_function_info_listener, NULL)                \
360   /* State for Relocatable. */                                                 \
361   V(Relocatable*, relocatable_top, NULL)                                       \
362   /* State for CodeEntry in profile-generator. */                              \
363   V(CodeGenerator*, current_code_generator, NULL)                              \
364   V(bool, jump_target_compiling_deferred_code, false)                          \
365   V(DebugObjectCache*, string_stream_debug_object_cache, NULL)                 \
366   V(Object*, string_stream_current_security_token, NULL)                       \
367   /* TODO(isolates): Release this on destruction? */                           \
368   V(int*, irregexp_interpreter_backtrack_stack_cache, NULL)                    \
369   /* Serializer state. */                                                      \
370   V(ExternalReferenceTable*, external_reference_table, NULL)                   \
371   /* AstNode state. */                                                         \
372   V(unsigned, ast_node_id, 0)                                                  \
373   V(unsigned, ast_node_count, 0)                                               \
374   /* SafeStackFrameIterator activations count. */                              \
375   V(int, safe_stack_iterator_counter, 0)                                       \
376   ISOLATE_PLATFORM_INIT_LIST(V)                                                \
377   ISOLATE_LOGGING_INIT_LIST(V)                                                 \
378   ISOLATE_DEBUGGER_INIT_LIST(V)
379 
380 class Isolate {
381   // These forward declarations are required to make the friend declarations in
382   // PerIsolateThreadData work on some older versions of gcc.
383   class ThreadDataTable;
384   class EntryStackItem;
385  public:
386   ~Isolate();
387 
388   // A thread has a PerIsolateThreadData instance for each isolate that it has
389   // entered. That instance is allocated when the isolate is initially entered
390   // and reused on subsequent entries.
391   class PerIsolateThreadData {
392    public:
PerIsolateThreadData(Isolate * isolate,ThreadId thread_id)393     PerIsolateThreadData(Isolate* isolate, ThreadId thread_id)
394         : isolate_(isolate),
395           thread_id_(thread_id),
396           stack_limit_(0),
397           thread_state_(NULL),
398 #if !defined(__arm__) && defined(V8_TARGET_ARCH_ARM) || \
399     !defined(__mips__) && defined(V8_TARGET_ARCH_MIPS)
400           simulator_(NULL),
401 #endif
402           next_(NULL),
403           prev_(NULL) { }
isolate()404     Isolate* isolate() const { return isolate_; }
thread_id()405     ThreadId thread_id() const { return thread_id_; }
set_stack_limit(uintptr_t value)406     void set_stack_limit(uintptr_t value) { stack_limit_ = value; }
stack_limit()407     uintptr_t stack_limit() const { return stack_limit_; }
thread_state()408     ThreadState* thread_state() const { return thread_state_; }
set_thread_state(ThreadState * value)409     void set_thread_state(ThreadState* value) { thread_state_ = value; }
410 
411 #if !defined(__arm__) && defined(V8_TARGET_ARCH_ARM) || \
412     !defined(__mips__) && defined(V8_TARGET_ARCH_MIPS)
simulator()413     Simulator* simulator() const { return simulator_; }
set_simulator(Simulator * simulator)414     void set_simulator(Simulator* simulator) {
415       simulator_ = simulator;
416     }
417 #endif
418 
Matches(Isolate * isolate,ThreadId thread_id)419     bool Matches(Isolate* isolate, ThreadId thread_id) const {
420       return isolate_ == isolate && thread_id_.Equals(thread_id);
421     }
422 
423    private:
424     Isolate* isolate_;
425     ThreadId thread_id_;
426     uintptr_t stack_limit_;
427     ThreadState* thread_state_;
428 
429 #if !defined(__arm__) && defined(V8_TARGET_ARCH_ARM) || \
430     !defined(__mips__) && defined(V8_TARGET_ARCH_MIPS)
431     Simulator* simulator_;
432 #endif
433 
434     PerIsolateThreadData* next_;
435     PerIsolateThreadData* prev_;
436 
437     friend class Isolate;
438     friend class ThreadDataTable;
439     friend class EntryStackItem;
440 
441     DISALLOW_COPY_AND_ASSIGN(PerIsolateThreadData);
442   };
443 
444 
445   enum AddressId {
446 #define C(name) k_##name,
447     ISOLATE_ADDRESS_LIST(C)
448     ISOLATE_ADDRESS_LIST_PROF(C)
449 #undef C
450     k_isolate_address_count
451   };
452 
453   // Returns the PerIsolateThreadData for the current thread (or NULL if one is
454   // not currently set).
CurrentPerIsolateThreadData()455   static PerIsolateThreadData* CurrentPerIsolateThreadData() {
456     return reinterpret_cast<PerIsolateThreadData*>(
457         Thread::GetThreadLocal(per_isolate_thread_data_key_));
458   }
459 
460   // Returns the isolate inside which the current thread is running.
INLINE(static Isolate * Current ())461   INLINE(static Isolate* Current()) {
462     Isolate* isolate = reinterpret_cast<Isolate*>(
463         Thread::GetExistingThreadLocal(isolate_key_));
464     ASSERT(isolate != NULL);
465     return isolate;
466   }
467 
INLINE(static Isolate * UncheckedCurrent ())468   INLINE(static Isolate* UncheckedCurrent()) {
469     return reinterpret_cast<Isolate*>(Thread::GetThreadLocal(isolate_key_));
470   }
471 
472   // Usually called by Init(), but can be called early e.g. to allow
473   // testing components that require logging but not the whole
474   // isolate.
475   //
476   // Safe to call more than once.
477   void InitializeLoggingAndCounters();
478 
479   bool Init(Deserializer* des);
480 
IsInitialized()481   bool IsInitialized() { return state_ == INITIALIZED; }
482 
483   // True if at least one thread Enter'ed this isolate.
IsInUse()484   bool IsInUse() { return entry_stack_ != NULL; }
485 
486   // Destroys the non-default isolates.
487   // Sets default isolate into "has_been_disposed" state rather then destroying,
488   // for legacy API reasons.
489   void TearDown();
490 
IsDefaultIsolate()491   bool IsDefaultIsolate() const { return this == default_isolate_; }
492 
493   // Ensures that process-wide resources and the default isolate have been
494   // allocated. It is only necessary to call this method in rare casses, for
495   // example if you are using V8 from within the body of a static initializer.
496   // Safe to call multiple times.
497   static void EnsureDefaultIsolate();
498 
499   // Get the debugger from the default isolate. Preinitializes the
500   // default isolate if needed.
501   static Debugger* GetDefaultIsolateDebugger();
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).
isolate_key()510   static Thread::LocalStorageKey isolate_key() {
511     return isolate_key_;
512   }
513 
514   // Returns the key used to store process-wide thread IDs.
thread_id_key()515   static Thread::LocalStorageKey thread_id_key() {
516     return thread_id_key_;
517   }
518 
519   // If a client attempts to create a Locker without specifying an isolate,
520   // we assume that the client is using legacy behavior. Set up the current
521   // thread to be inside the implicit isolate (or fail a check if we have
522   // switched to non-legacy behavior).
523   static void EnterDefaultIsolate();
524 
525   // Mutex for serializing access to break control structures.
break_access()526   Mutex* break_access() { return break_access_; }
527 
528   // Mutex for serializing access to debugger.
debugger_access()529   Mutex* debugger_access() { return debugger_access_; }
530 
531   Address get_address_from_id(AddressId id);
532 
533   // Access to top context (where the current function object was created).
context()534   Context* context() { return thread_local_top_.context_; }
set_context(Context * context)535   void set_context(Context* context) {
536     thread_local_top_.context_ = context;
537   }
context_address()538   Context** context_address() { return &thread_local_top_.context_; }
539 
save_context()540   SaveContext* save_context() {return thread_local_top_.save_context_; }
set_save_context(SaveContext * save)541   void set_save_context(SaveContext* save) {
542     thread_local_top_.save_context_ = save;
543   }
544 
545   // Access to current thread id.
thread_id()546   ThreadId thread_id() { return thread_local_top_.thread_id_; }
set_thread_id(ThreadId id)547   void set_thread_id(ThreadId id) { thread_local_top_.thread_id_ = id; }
548 
549   // Interface to pending exception.
pending_exception()550   MaybeObject* pending_exception() {
551     ASSERT(has_pending_exception());
552     return thread_local_top_.pending_exception_;
553   }
external_caught_exception()554   bool external_caught_exception() {
555     return thread_local_top_.external_caught_exception_;
556   }
set_external_caught_exception(bool value)557   void set_external_caught_exception(bool value) {
558     thread_local_top_.external_caught_exception_ = value;
559   }
set_pending_exception(MaybeObject * exception)560   void set_pending_exception(MaybeObject* exception) {
561     thread_local_top_.pending_exception_ = exception;
562   }
clear_pending_exception()563   void clear_pending_exception() {
564     thread_local_top_.pending_exception_ = heap_.the_hole_value();
565   }
pending_exception_address()566   MaybeObject** pending_exception_address() {
567     return &thread_local_top_.pending_exception_;
568   }
has_pending_exception()569   bool has_pending_exception() {
570     return !thread_local_top_.pending_exception_->IsTheHole();
571   }
clear_pending_message()572   void clear_pending_message() {
573     thread_local_top_.has_pending_message_ = false;
574     thread_local_top_.pending_message_obj_ = heap_.the_hole_value();
575     thread_local_top_.pending_message_script_ = NULL;
576   }
try_catch_handler()577   v8::TryCatch* try_catch_handler() {
578     return thread_local_top_.TryCatchHandler();
579   }
try_catch_handler_address()580   Address try_catch_handler_address() {
581     return thread_local_top_.try_catch_handler_address();
582   }
external_caught_exception_address()583   bool* external_caught_exception_address() {
584     return &thread_local_top_.external_caught_exception_;
585   }
catcher()586   v8::TryCatch* catcher() {
587     return thread_local_top_.catcher_;
588   }
set_catcher(v8::TryCatch * catcher)589   void set_catcher(v8::TryCatch* catcher) {
590     thread_local_top_.catcher_ = catcher;
591   }
592 
scheduled_exception_address()593   MaybeObject** scheduled_exception_address() {
594     return &thread_local_top_.scheduled_exception_;
595   }
scheduled_exception()596   MaybeObject* scheduled_exception() {
597     ASSERT(has_scheduled_exception());
598     return thread_local_top_.scheduled_exception_;
599   }
has_scheduled_exception()600   bool has_scheduled_exception() {
601     return !thread_local_top_.scheduled_exception_->IsTheHole();
602   }
clear_scheduled_exception()603   void clear_scheduled_exception() {
604     thread_local_top_.scheduled_exception_ = heap_.the_hole_value();
605   }
606 
607   bool IsExternallyCaught();
608 
is_catchable_by_javascript(MaybeObject * exception)609   bool is_catchable_by_javascript(MaybeObject* exception) {
610     return (exception != Failure::OutOfMemoryException()) &&
611         (exception != heap()->termination_exception());
612   }
613 
614   // JS execution stack (see frames.h).
c_entry_fp(ThreadLocalTop * thread)615   static Address c_entry_fp(ThreadLocalTop* thread) {
616     return thread->c_entry_fp_;
617   }
handler(ThreadLocalTop * thread)618   static Address handler(ThreadLocalTop* thread) { return thread->handler_; }
619 
c_entry_fp_address()620   inline Address* c_entry_fp_address() {
621     return &thread_local_top_.c_entry_fp_;
622   }
handler_address()623   inline Address* handler_address() { return &thread_local_top_.handler_; }
624 
625 #ifdef ENABLE_LOGGING_AND_PROFILING
626   // Bottom JS entry (see StackTracer::Trace in log.cc).
js_entry_sp(ThreadLocalTop * thread)627   static Address js_entry_sp(ThreadLocalTop* thread) {
628     return thread->js_entry_sp_;
629   }
js_entry_sp_address()630   inline Address* js_entry_sp_address() {
631     return &thread_local_top_.js_entry_sp_;
632   }
633 #endif
634 
635   // Generated code scratch locations.
formal_count_address()636   void* formal_count_address() { return &thread_local_top_.formal_count_; }
637 
638   // Returns the global object of the current context. It could be
639   // a builtin object, or a js global object.
global()640   Handle<GlobalObject> global() {
641     return Handle<GlobalObject>(context()->global());
642   }
643 
644   // Returns the global proxy object of the current context.
global_proxy()645   Object* global_proxy() {
646     return context()->global_proxy();
647   }
648 
js_builtins_object()649   Handle<JSBuiltinsObject> js_builtins_object() {
650     return Handle<JSBuiltinsObject>(thread_local_top_.context_->builtins());
651   }
652 
ArchiveSpacePerThread()653   static int ArchiveSpacePerThread() { return sizeof(ThreadLocalTop); }
FreeThreadResources()654   void FreeThreadResources() { thread_local_top_.Free(); }
655 
656   // This method is called by the api after operations that may throw
657   // exceptions.  If an exception was thrown and not handled by an external
658   // handler the exception is scheduled to be rethrown when we return to running
659   // JavaScript code.  If an exception is scheduled true is returned.
660   bool OptionalRescheduleException(bool is_bottom_call);
661 
662   class ExceptionScope {
663    public:
ExceptionScope(Isolate * isolate)664     explicit ExceptionScope(Isolate* isolate) :
665       // Scope currently can only be used for regular exceptions, not
666       // failures like OOM or termination exception.
667       isolate_(isolate),
668       pending_exception_(isolate_->pending_exception()->ToObjectUnchecked()),
669       catcher_(isolate_->catcher())
670     { }
671 
~ExceptionScope()672     ~ExceptionScope() {
673       isolate_->set_catcher(catcher_);
674       isolate_->set_pending_exception(*pending_exception_);
675     }
676 
677    private:
678     Isolate* isolate_;
679     Handle<Object> pending_exception_;
680     v8::TryCatch* catcher_;
681   };
682 
683   void SetCaptureStackTraceForUncaughtExceptions(
684       bool capture,
685       int frame_limit,
686       StackTrace::StackTraceOptions options);
687 
688   // Tells whether the current context has experienced an out of memory
689   // exception.
690   bool is_out_of_memory();
ignore_out_of_memory()691   bool ignore_out_of_memory() {
692     return thread_local_top_.ignore_out_of_memory_;
693   }
set_ignore_out_of_memory(bool value)694   void set_ignore_out_of_memory(bool value) {
695     thread_local_top_.ignore_out_of_memory_ = value;
696   }
697 
698   void PrintCurrentStackTrace(FILE* out);
699   void PrintStackTrace(FILE* out, char* thread_data);
700   void PrintStack(StringStream* accumulator);
701   void PrintStack();
702   Handle<String> StackTraceString();
703   Handle<JSArray> CaptureCurrentStackTrace(
704       int frame_limit,
705       StackTrace::StackTraceOptions options);
706 
707   // Returns if the top context may access the given global object. If
708   // the result is false, the pending exception is guaranteed to be
709   // set.
710   bool MayNamedAccess(JSObject* receiver,
711                       Object* key,
712                       v8::AccessType type);
713   bool MayIndexedAccess(JSObject* receiver,
714                         uint32_t index,
715                         v8::AccessType type);
716 
717   void SetFailedAccessCheckCallback(v8::FailedAccessCheckCallback callback);
718   void ReportFailedAccessCheck(JSObject* receiver, v8::AccessType type);
719 
720   // Exception throwing support. The caller should use the result
721   // of Throw() as its return value.
722   Failure* Throw(Object* exception, MessageLocation* location = NULL);
723   // Re-throw an exception.  This involves no error reporting since
724   // error reporting was handled when the exception was thrown
725   // originally.
726   Failure* ReThrow(MaybeObject* exception, MessageLocation* location = NULL);
727   void ScheduleThrow(Object* exception);
728   void ReportPendingMessages();
729   Failure* ThrowIllegalOperation();
730 
731   // Promote a scheduled exception to pending. Asserts has_scheduled_exception.
732   Failure* PromoteScheduledException();
733   void DoThrow(MaybeObject* exception, MessageLocation* location);
734   // Checks if exception should be reported and finds out if it's
735   // caught externally.
736   bool ShouldReportException(bool* can_be_caught_externally,
737                              bool catchable_by_javascript);
738 
739   // Attempts to compute the current source location, storing the
740   // result in the target out parameter.
741   void ComputeLocation(MessageLocation* target);
742 
743   // Override command line flag.
744   void TraceException(bool flag);
745 
746   // Out of resource exception helpers.
747   Failure* StackOverflow();
748   Failure* TerminateExecution();
749 
750   // Administration
751   void Iterate(ObjectVisitor* v);
752   void Iterate(ObjectVisitor* v, ThreadLocalTop* t);
753   char* Iterate(ObjectVisitor* v, char* t);
754   void IterateThread(ThreadVisitor* v);
755   void IterateThread(ThreadVisitor* v, char* t);
756 
757 
758   // Returns the current global context.
759   Handle<Context> global_context();
760 
761   // Returns the global context of the calling JavaScript code.  That
762   // is, the global context of the top-most JavaScript frame.
763   Handle<Context> GetCallingGlobalContext();
764 
765   void RegisterTryCatchHandler(v8::TryCatch* that);
766   void UnregisterTryCatchHandler(v8::TryCatch* that);
767 
768   char* ArchiveThread(char* to);
769   char* RestoreThread(char* from);
770 
771   static const char* const kStackOverflowMessage;
772 
773   static const int kUC16AlphabetSize = 256;  // See StringSearchBase.
774   static const int kBMMaxShift = 250;        // See StringSearchBase.
775 
776   // Accessors.
777 #define GLOBAL_ACCESSOR(type, name, initialvalue)                       \
778   inline type name() const {                                            \
779     ASSERT(OFFSET_OF(Isolate, name##_) == name##_debug_offset_);        \
780     return name##_;                                                     \
781   }                                                                     \
782   inline void set_##name(type value) {                                  \
783     ASSERT(OFFSET_OF(Isolate, name##_) == name##_debug_offset_);        \
784     name##_ = value;                                                    \
785   }
786   ISOLATE_INIT_LIST(GLOBAL_ACCESSOR)
787 #undef GLOBAL_ACCESSOR
788 
789 #define GLOBAL_ARRAY_ACCESSOR(type, name, length)                       \
790   inline type* name() {                                                 \
791     ASSERT(OFFSET_OF(Isolate, name##_) == name##_debug_offset_);        \
792     return &(name##_)[0];                                               \
793   }
ISOLATE_INIT_ARRAY_LIST(GLOBAL_ARRAY_ACCESSOR)794   ISOLATE_INIT_ARRAY_LIST(GLOBAL_ARRAY_ACCESSOR)
795 #undef GLOBAL_ARRAY_ACCESSOR
796 
797 #define GLOBAL_CONTEXT_FIELD_ACCESSOR(index, type, name)      \
798   Handle<type> name() {                                       \
799     return Handle<type>(context()->global_context()->name()); \
800   }
801   GLOBAL_CONTEXT_FIELDS(GLOBAL_CONTEXT_FIELD_ACCESSOR)
802 #undef GLOBAL_CONTEXT_FIELD_ACCESSOR
803 
804   Bootstrapper* bootstrapper() { return bootstrapper_; }
counters()805   Counters* counters() {
806     // Call InitializeLoggingAndCounters() if logging is needed before
807     // the isolate is fully initialized.
808     ASSERT(counters_ != NULL);
809     return counters_;
810   }
code_range()811   CodeRange* code_range() { return code_range_; }
runtime_profiler()812   RuntimeProfiler* runtime_profiler() { return runtime_profiler_; }
compilation_cache()813   CompilationCache* compilation_cache() { return compilation_cache_; }
logger()814   Logger* logger() {
815     // Call InitializeLoggingAndCounters() if logging is needed before
816     // the isolate is fully initialized.
817     ASSERT(logger_ != NULL);
818     return logger_;
819   }
stack_guard()820   StackGuard* stack_guard() { return &stack_guard_; }
heap()821   Heap* heap() { return &heap_; }
822   StatsTable* stats_table();
stub_cache()823   StubCache* stub_cache() { return stub_cache_; }
deoptimizer_data()824   DeoptimizerData* deoptimizer_data() { return deoptimizer_data_; }
thread_local_top()825   ThreadLocalTop* thread_local_top() { return &thread_local_top_; }
826 
transcendental_cache()827   TranscendentalCache* transcendental_cache() const {
828     return transcendental_cache_;
829   }
830 
memory_allocator()831   MemoryAllocator* memory_allocator() {
832     return memory_allocator_;
833   }
834 
keyed_lookup_cache()835   KeyedLookupCache* keyed_lookup_cache() {
836     return keyed_lookup_cache_;
837   }
838 
context_slot_cache()839   ContextSlotCache* context_slot_cache() {
840     return context_slot_cache_;
841   }
842 
descriptor_lookup_cache()843   DescriptorLookupCache* descriptor_lookup_cache() {
844     return descriptor_lookup_cache_;
845   }
846 
handle_scope_data()847   v8::ImplementationUtilities::HandleScopeData* handle_scope_data() {
848     return &handle_scope_data_;
849   }
handle_scope_implementer()850   HandleScopeImplementer* handle_scope_implementer() {
851     ASSERT(handle_scope_implementer_);
852     return handle_scope_implementer_;
853   }
zone()854   Zone* zone() { return &zone_; }
855 
unicode_cache()856   UnicodeCache* unicode_cache() {
857     return unicode_cache_;
858   }
859 
pc_to_code_cache()860   PcToCodeCache* pc_to_code_cache() { return pc_to_code_cache_; }
861 
write_input_buffer()862   StringInputBuffer* write_input_buffer() { return write_input_buffer_; }
863 
global_handles()864   GlobalHandles* global_handles() { return global_handles_; }
865 
thread_manager()866   ThreadManager* thread_manager() { return thread_manager_; }
867 
context_switcher()868   ContextSwitcher* context_switcher() { return context_switcher_; }
869 
set_context_switcher(ContextSwitcher * switcher)870   void set_context_switcher(ContextSwitcher* switcher) {
871     context_switcher_ = switcher;
872   }
873 
string_tracker()874   StringTracker* string_tracker() { return string_tracker_; }
875 
jsregexp_uncanonicalize()876   unibrow::Mapping<unibrow::Ecma262UnCanonicalize>* jsregexp_uncanonicalize() {
877     return &jsregexp_uncanonicalize_;
878   }
879 
jsregexp_canonrange()880   unibrow::Mapping<unibrow::CanonicalizationRange>* jsregexp_canonrange() {
881     return &jsregexp_canonrange_;
882   }
883 
objects_string_compare_buffer_a()884   StringInputBuffer* objects_string_compare_buffer_a() {
885     return &objects_string_compare_buffer_a_;
886   }
887 
objects_string_compare_buffer_b()888   StringInputBuffer* objects_string_compare_buffer_b() {
889     return &objects_string_compare_buffer_b_;
890   }
891 
objects_string_input_buffer()892   StaticResource<StringInputBuffer>* objects_string_input_buffer() {
893     return &objects_string_input_buffer_;
894   }
895 
ast_sentinels()896   AstSentinels* ast_sentinels() { return ast_sentinels_; }
897 
runtime_state()898   RuntimeState* runtime_state() { return &runtime_state_; }
899 
liveedit_compare_substrings_buf1()900   StringInputBuffer* liveedit_compare_substrings_buf1() {
901     return &liveedit_compare_substrings_buf1_;
902   }
903 
liveedit_compare_substrings_buf2()904   StringInputBuffer* liveedit_compare_substrings_buf2() {
905     return &liveedit_compare_substrings_buf2_;
906   }
907 
compiler_safe_string_input_buffer()908   StaticResource<SafeStringInputBuffer>* compiler_safe_string_input_buffer() {
909     return &compiler_safe_string_input_buffer_;
910   }
911 
builtins()912   Builtins* builtins() { return &builtins_; }
913 
914   unibrow::Mapping<unibrow::Ecma262Canonicalize>*
regexp_macro_assembler_canonicalize()915       regexp_macro_assembler_canonicalize() {
916     return &regexp_macro_assembler_canonicalize_;
917   }
918 
regexp_stack()919   RegExpStack* regexp_stack() { return regexp_stack_; }
920 
921   unibrow::Mapping<unibrow::Ecma262Canonicalize>*
interp_canonicalize_mapping()922       interp_canonicalize_mapping() {
923     return &interp_canonicalize_mapping_;
924   }
925 
frame_element_constant_list()926   ZoneObjectList* frame_element_constant_list() {
927     return &frame_element_constant_list_;
928   }
929 
result_constant_list()930   ZoneObjectList* result_constant_list() {
931     return &result_constant_list_;
932   }
933 
934   void* PreallocatedStorageNew(size_t size);
935   void PreallocatedStorageDelete(void* p);
936   void PreallocatedStorageInit(size_t size);
937 
938 #ifdef ENABLE_DEBUGGER_SUPPORT
debugger()939   Debugger* debugger() {
940     if (!NoBarrier_Load(&debugger_initialized_)) InitializeDebugger();
941     return debugger_;
942   }
debug()943   Debug* debug() {
944     if (!NoBarrier_Load(&debugger_initialized_)) InitializeDebugger();
945     return debug_;
946   }
947 #endif
948 
949 #ifdef ENABLE_LOGGING_AND_PROFILING
producer_heap_profile()950   ProducerHeapProfile* producer_heap_profile() {
951     return producer_heap_profile_;
952   }
953 #endif
954 
955 #ifdef DEBUG
heap_histograms()956   HistogramInfo* heap_histograms() { return heap_histograms_; }
957 
js_spill_information()958   JSObject::SpillInformation* js_spill_information() {
959     return &js_spill_information_;
960   }
961 
code_kind_statistics()962   int* code_kind_statistics() { return code_kind_statistics_; }
963 #endif
964 
965 #if defined(V8_TARGET_ARCH_ARM) && !defined(__arm__) || \
966     defined(V8_TARGET_ARCH_MIPS) && !defined(__mips__)
simulator_initialized()967   bool simulator_initialized() { return simulator_initialized_; }
set_simulator_initialized(bool initialized)968   void set_simulator_initialized(bool initialized) {
969     simulator_initialized_ = initialized;
970   }
971 
simulator_i_cache()972   HashMap* simulator_i_cache() { return simulator_i_cache_; }
set_simulator_i_cache(HashMap * hash_map)973   void set_simulator_i_cache(HashMap* hash_map) {
974     simulator_i_cache_ = hash_map;
975   }
976 
simulator_redirection()977   Redirection* simulator_redirection() {
978     return simulator_redirection_;
979   }
set_simulator_redirection(Redirection * redirection)980   void set_simulator_redirection(Redirection* redirection) {
981     simulator_redirection_ = redirection;
982   }
983 #endif
984 
factory()985   Factory* factory() { return reinterpret_cast<Factory*>(this); }
986 
987   // SerializerDeserializer state.
988   static const int kPartialSnapshotCacheCapacity = 1400;
989 
990   static const int kJSRegexpStaticOffsetsVectorSize = 50;
991 
992 #ifdef ENABLE_LOGGING_AND_PROFILING
external_callback()993   Address external_callback() {
994     return thread_local_top_.external_callback_;
995   }
set_external_callback(Address callback)996   void set_external_callback(Address callback) {
997     thread_local_top_.external_callback_ = callback;
998   }
999 #endif
1000 
1001 #ifdef ENABLE_VMSTATE_TRACKING
current_vm_state()1002   StateTag current_vm_state() {
1003     return thread_local_top_.current_vm_state_;
1004   }
1005 
SetCurrentVMState(StateTag state)1006   void SetCurrentVMState(StateTag state) {
1007     if (RuntimeProfiler::IsEnabled()) {
1008       StateTag current_state = thread_local_top_.current_vm_state_;
1009       if (current_state != JS && state == JS) {
1010         // Non-JS -> JS transition.
1011         RuntimeProfiler::IsolateEnteredJS(this);
1012       } else if (current_state == JS && state != JS) {
1013         // JS -> non-JS transition.
1014         ASSERT(RuntimeProfiler::IsSomeIsolateInJS());
1015         RuntimeProfiler::IsolateExitedJS(this);
1016       } else {
1017         // Other types of state transitions are not interesting to the
1018         // runtime profiler, because they don't affect whether we're
1019         // in JS or not.
1020         ASSERT((current_state == JS) == (state == JS));
1021       }
1022     }
1023     thread_local_top_.current_vm_state_ = state;
1024   }
1025 #endif
1026 
1027   void ResetEagerOptimizingData();
1028 
1029  private:
1030   Isolate();
1031 
1032   // The per-process lock should be acquired before the ThreadDataTable is
1033   // modified.
1034   class ThreadDataTable {
1035    public:
1036     ThreadDataTable();
1037     ~ThreadDataTable();
1038 
1039     PerIsolateThreadData* Lookup(Isolate* isolate, ThreadId thread_id);
1040     void Insert(PerIsolateThreadData* data);
1041     void Remove(Isolate* isolate, ThreadId thread_id);
1042     void Remove(PerIsolateThreadData* data);
1043 
1044    private:
1045     PerIsolateThreadData* list_;
1046   };
1047 
1048   // These items form a stack synchronously with threads Enter'ing and Exit'ing
1049   // the Isolate. The top of the stack points to a thread which is currently
1050   // running the Isolate. When the stack is empty, the Isolate is considered
1051   // not entered by any thread and can be Disposed.
1052   // If the same thread enters the Isolate more then once, the entry_count_
1053   // is incremented rather then a new item pushed to the stack.
1054   class EntryStackItem {
1055    public:
EntryStackItem(PerIsolateThreadData * previous_thread_data,Isolate * previous_isolate,EntryStackItem * previous_item)1056     EntryStackItem(PerIsolateThreadData* previous_thread_data,
1057                    Isolate* previous_isolate,
1058                    EntryStackItem* previous_item)
1059         : entry_count(1),
1060           previous_thread_data(previous_thread_data),
1061           previous_isolate(previous_isolate),
1062           previous_item(previous_item) { }
1063 
1064     int entry_count;
1065     PerIsolateThreadData* previous_thread_data;
1066     Isolate* previous_isolate;
1067     EntryStackItem* previous_item;
1068 
1069     DISALLOW_COPY_AND_ASSIGN(EntryStackItem);
1070   };
1071 
1072   // This mutex protects highest_thread_id_, thread_data_table_ and
1073   // default_isolate_.
1074   static Mutex* process_wide_mutex_;
1075 
1076   static Thread::LocalStorageKey per_isolate_thread_data_key_;
1077   static Thread::LocalStorageKey isolate_key_;
1078   static Thread::LocalStorageKey thread_id_key_;
1079   static Isolate* default_isolate_;
1080   static ThreadDataTable* thread_data_table_;
1081 
1082   void Deinit();
1083 
1084   static void SetIsolateThreadLocals(Isolate* isolate,
1085                                      PerIsolateThreadData* data);
1086 
1087   enum State {
1088     UNINITIALIZED,    // Some components may not have been allocated.
1089     INITIALIZED       // All components are fully initialized.
1090   };
1091 
1092   State state_;
1093   EntryStackItem* entry_stack_;
1094 
1095   // Allocate and insert PerIsolateThreadData into the ThreadDataTable
1096   // (regardless of whether such data already exists).
1097   PerIsolateThreadData* AllocatePerIsolateThreadData(ThreadId thread_id);
1098 
1099   // Find the PerThread for this particular (isolate, thread) combination.
1100   // If one does not yet exist, allocate a new one.
1101   PerIsolateThreadData* FindOrAllocatePerThreadDataForThisThread();
1102 
1103   // PreInits and returns a default isolate. Needed when a new thread tries
1104   // to create a Locker for the first time (the lock itself is in the isolate).
1105   static Isolate* GetDefaultIsolateForLocking();
1106 
1107   // Initializes the current thread to run this Isolate.
1108   // Not thread-safe. Multiple threads should not Enter/Exit the same isolate
1109   // at the same time, this should be prevented using external locking.
1110   void Enter();
1111 
1112   // Exits the current thread. The previosuly entered Isolate is restored
1113   // for the thread.
1114   // Not thread-safe. Multiple threads should not Enter/Exit the same isolate
1115   // at the same time, this should be prevented using external locking.
1116   void Exit();
1117 
1118   void PreallocatedMemoryThreadStart();
1119   void PreallocatedMemoryThreadStop();
1120   void InitializeThreadLocal();
1121 
1122   void PrintStackTrace(FILE* out, ThreadLocalTop* thread);
1123   void MarkCompactPrologue(bool is_compacting,
1124                            ThreadLocalTop* archived_thread_data);
1125   void MarkCompactEpilogue(bool is_compacting,
1126                            ThreadLocalTop* archived_thread_data);
1127 
1128   void FillCache();
1129 
1130   void PropagatePendingExceptionToExternalTryCatch();
1131 
1132   void InitializeDebugger();
1133 
1134   int stack_trace_nesting_level_;
1135   StringStream* incomplete_message_;
1136   // The preallocated memory thread singleton.
1137   PreallocatedMemoryThread* preallocated_memory_thread_;
1138   Address isolate_addresses_[k_isolate_address_count + 1];  // NOLINT
1139   NoAllocationStringAllocator* preallocated_message_space_;
1140 
1141   Bootstrapper* bootstrapper_;
1142   RuntimeProfiler* runtime_profiler_;
1143   CompilationCache* compilation_cache_;
1144   Counters* counters_;
1145   CodeRange* code_range_;
1146   Mutex* break_access_;
1147   Atomic32 debugger_initialized_;
1148   Mutex* debugger_access_;
1149   Heap heap_;
1150   Logger* logger_;
1151   StackGuard stack_guard_;
1152   StatsTable* stats_table_;
1153   StubCache* stub_cache_;
1154   DeoptimizerData* deoptimizer_data_;
1155   ThreadLocalTop thread_local_top_;
1156   bool capture_stack_trace_for_uncaught_exceptions_;
1157   int stack_trace_for_uncaught_exceptions_frame_limit_;
1158   StackTrace::StackTraceOptions stack_trace_for_uncaught_exceptions_options_;
1159   TranscendentalCache* transcendental_cache_;
1160   MemoryAllocator* memory_allocator_;
1161   KeyedLookupCache* keyed_lookup_cache_;
1162   ContextSlotCache* context_slot_cache_;
1163   DescriptorLookupCache* descriptor_lookup_cache_;
1164   v8::ImplementationUtilities::HandleScopeData handle_scope_data_;
1165   HandleScopeImplementer* handle_scope_implementer_;
1166   UnicodeCache* unicode_cache_;
1167   Zone zone_;
1168   PreallocatedStorage in_use_list_;
1169   PreallocatedStorage free_list_;
1170   bool preallocated_storage_preallocated_;
1171   PcToCodeCache* pc_to_code_cache_;
1172   StringInputBuffer* write_input_buffer_;
1173   GlobalHandles* global_handles_;
1174   ContextSwitcher* context_switcher_;
1175   ThreadManager* thread_manager_;
1176   AstSentinels* ast_sentinels_;
1177   RuntimeState runtime_state_;
1178   StringInputBuffer liveedit_compare_substrings_buf1_;
1179   StringInputBuffer liveedit_compare_substrings_buf2_;
1180   StaticResource<SafeStringInputBuffer> compiler_safe_string_input_buffer_;
1181   Builtins builtins_;
1182   StringTracker* string_tracker_;
1183   unibrow::Mapping<unibrow::Ecma262UnCanonicalize> jsregexp_uncanonicalize_;
1184   unibrow::Mapping<unibrow::CanonicalizationRange> jsregexp_canonrange_;
1185   StringInputBuffer objects_string_compare_buffer_a_;
1186   StringInputBuffer objects_string_compare_buffer_b_;
1187   StaticResource<StringInputBuffer> objects_string_input_buffer_;
1188   unibrow::Mapping<unibrow::Ecma262Canonicalize>
1189       regexp_macro_assembler_canonicalize_;
1190   RegExpStack* regexp_stack_;
1191   unibrow::Mapping<unibrow::Ecma262Canonicalize> interp_canonicalize_mapping_;
1192   ZoneObjectList frame_element_constant_list_;
1193   ZoneObjectList result_constant_list_;
1194 
1195 #if defined(V8_TARGET_ARCH_ARM) && !defined(__arm__) || \
1196     defined(V8_TARGET_ARCH_MIPS) && !defined(__mips__)
1197   bool simulator_initialized_;
1198   HashMap* simulator_i_cache_;
1199   Redirection* simulator_redirection_;
1200 #endif
1201 
1202 #ifdef DEBUG
1203   // A static array of histogram info for each type.
1204   HistogramInfo heap_histograms_[LAST_TYPE + 1];
1205   JSObject::SpillInformation js_spill_information_;
1206   int code_kind_statistics_[Code::NUMBER_OF_KINDS];
1207 #endif
1208 
1209 #ifdef ENABLE_DEBUGGER_SUPPORT
1210   Debugger* debugger_;
1211   Debug* debug_;
1212 #endif
1213 
1214 #ifdef ENABLE_LOGGING_AND_PROFILING
1215   ProducerHeapProfile* producer_heap_profile_;
1216 #endif
1217 
1218 #define GLOBAL_BACKING_STORE(type, name, initialvalue)                         \
1219   type name##_;
1220   ISOLATE_INIT_LIST(GLOBAL_BACKING_STORE)
1221 #undef GLOBAL_BACKING_STORE
1222 
1223 #define GLOBAL_ARRAY_BACKING_STORE(type, name, length)                         \
1224   type name##_[length];
1225   ISOLATE_INIT_ARRAY_LIST(GLOBAL_ARRAY_BACKING_STORE)
1226 #undef GLOBAL_ARRAY_BACKING_STORE
1227 
1228 #ifdef DEBUG
1229   // This class is huge and has a number of fields controlled by
1230   // preprocessor defines. Make sure the offsets of these fields agree
1231   // between compilation units.
1232 #define ISOLATE_FIELD_OFFSET(type, name, ignored)                              \
1233   static const intptr_t name##_debug_offset_;
1234   ISOLATE_INIT_LIST(ISOLATE_FIELD_OFFSET)
1235   ISOLATE_INIT_ARRAY_LIST(ISOLATE_FIELD_OFFSET)
1236 #undef ISOLATE_FIELD_OFFSET
1237 #endif
1238 
1239   friend class ExecutionAccess;
1240   friend class IsolateInitializer;
1241   friend class ThreadId;
1242   friend class TestMemoryAllocatorScope;
1243   friend class v8::Isolate;
1244   friend class v8::Locker;
1245 
1246   DISALLOW_COPY_AND_ASSIGN(Isolate);
1247 };
1248 
1249 
1250 // If the GCC version is 4.1.x or 4.2.x an additional field is added to the
1251 // class as a work around for a bug in the generated code found with these
1252 // versions of GCC. See V8 issue 122 for details.
1253 class SaveContext BASE_EMBEDDED {
1254  public:
SaveContext(Isolate * isolate)1255   explicit SaveContext(Isolate* isolate) : prev_(isolate->save_context()) {
1256     if (isolate->context() != NULL) {
1257       context_ = Handle<Context>(isolate->context());
1258 #if __GNUC_VERSION__ >= 40100 && __GNUC_VERSION__ < 40300
1259       dummy_ = Handle<Context>(isolate->context());
1260 #endif
1261     }
1262     isolate->set_save_context(this);
1263 
1264     // If there is no JS frame under the current C frame, use the value 0.
1265     JavaScriptFrameIterator it(isolate);
1266     js_sp_ = it.done() ? 0 : it.frame()->sp();
1267   }
1268 
~SaveContext()1269   ~SaveContext() {
1270     if (context_.is_null()) {
1271       Isolate* isolate = Isolate::Current();
1272       isolate->set_context(NULL);
1273       isolate->set_save_context(prev_);
1274     } else {
1275       Isolate* isolate = context_->GetIsolate();
1276       isolate->set_context(*context_);
1277       isolate->set_save_context(prev_);
1278     }
1279   }
1280 
context()1281   Handle<Context> context() { return context_; }
prev()1282   SaveContext* prev() { return prev_; }
1283 
1284   // Returns true if this save context is below a given JavaScript frame.
below(JavaScriptFrame * frame)1285   bool below(JavaScriptFrame* frame) {
1286     return (js_sp_ == 0) || (frame->sp() < js_sp_);
1287   }
1288 
1289  private:
1290   Handle<Context> context_;
1291 #if __GNUC_VERSION__ >= 40100 && __GNUC_VERSION__ < 40300
1292   Handle<Context> dummy_;
1293 #endif
1294   SaveContext* prev_;
1295   Address js_sp_;  // The top JS frame's sp when saving context.
1296 };
1297 
1298 
1299 class AssertNoContextChange BASE_EMBEDDED {
1300 #ifdef DEBUG
1301  public:
AssertNoContextChange()1302   AssertNoContextChange() :
1303       scope_(Isolate::Current()),
1304       context_(Isolate::Current()->context(), Isolate::Current()) {
1305   }
1306 
~AssertNoContextChange()1307   ~AssertNoContextChange() {
1308     ASSERT(Isolate::Current()->context() == *context_);
1309   }
1310 
1311  private:
1312   HandleScope scope_;
1313   Handle<Context> context_;
1314 #else
1315  public:
1316   AssertNoContextChange() { }
1317 #endif
1318 };
1319 
1320 
1321 class ExecutionAccess BASE_EMBEDDED {
1322  public:
ExecutionAccess(Isolate * isolate)1323   explicit ExecutionAccess(Isolate* isolate) : isolate_(isolate) {
1324     Lock(isolate);
1325   }
~ExecutionAccess()1326   ~ExecutionAccess() { Unlock(isolate_); }
1327 
Lock(Isolate * isolate)1328   static void Lock(Isolate* isolate) { isolate->break_access_->Lock(); }
Unlock(Isolate * isolate)1329   static void Unlock(Isolate* isolate) { isolate->break_access_->Unlock(); }
1330 
TryLock(Isolate * isolate)1331   static bool TryLock(Isolate* isolate) {
1332     return isolate->break_access_->TryLock();
1333   }
1334 
1335  private:
1336   Isolate* isolate_;
1337 };
1338 
1339 
1340 // Support for checking for stack-overflows in C++ code.
1341 class StackLimitCheck BASE_EMBEDDED {
1342  public:
StackLimitCheck(Isolate * isolate)1343   explicit StackLimitCheck(Isolate* isolate) : isolate_(isolate) { }
1344 
HasOverflowed()1345   bool HasOverflowed() const {
1346     StackGuard* stack_guard = isolate_->stack_guard();
1347     // Stack has overflowed in C++ code only if stack pointer exceeds the C++
1348     // stack guard and the limits are not set to interrupt values.
1349     // TODO(214): Stack overflows are ignored if a interrupt is pending. This
1350     // code should probably always use the initial C++ limit.
1351     return (reinterpret_cast<uintptr_t>(this) < stack_guard->climit()) &&
1352            stack_guard->IsStackOverflow();
1353   }
1354  private:
1355   Isolate* isolate_;
1356 };
1357 
1358 
1359 // Support for temporarily postponing interrupts. When the outermost
1360 // postpone scope is left the interrupts will be re-enabled and any
1361 // interrupts that occurred while in the scope will be taken into
1362 // account.
1363 class PostponeInterruptsScope BASE_EMBEDDED {
1364  public:
PostponeInterruptsScope(Isolate * isolate)1365   explicit PostponeInterruptsScope(Isolate* isolate)
1366       : stack_guard_(isolate->stack_guard()) {
1367     stack_guard_->thread_local_.postpone_interrupts_nesting_++;
1368     stack_guard_->DisableInterrupts();
1369   }
1370 
~PostponeInterruptsScope()1371   ~PostponeInterruptsScope() {
1372     if (--stack_guard_->thread_local_.postpone_interrupts_nesting_ == 0) {
1373       stack_guard_->EnableInterrupts();
1374     }
1375   }
1376  private:
1377   StackGuard* stack_guard_;
1378 };
1379 
1380 
1381 // Temporary macros for accessing current isolate and its subobjects.
1382 // They provide better readability, especially when used a lot in the code.
1383 #define HEAP (v8::internal::Isolate::Current()->heap())
1384 #define FACTORY (v8::internal::Isolate::Current()->factory())
1385 #define ISOLATE (v8::internal::Isolate::Current())
1386 #define ZONE (v8::internal::Isolate::Current()->zone())
1387 #define LOGGER (v8::internal::Isolate::Current()->logger())
1388 
1389 
1390 // Tells whether the global context is marked with out of memory.
has_out_of_memory()1391 inline bool Context::has_out_of_memory() {
1392   return global_context()->out_of_memory()->IsTrue();
1393 }
1394 
1395 
1396 // Mark the global context with out of memory.
mark_out_of_memory()1397 inline void Context::mark_out_of_memory() {
1398   global_context()->set_out_of_memory(HEAP->true_value());
1399 }
1400 
1401 
1402 // Temporary macro to be used to flag definitions that are indeed static
1403 // and not per-isolate. (It would be great to be able to grep for [static]!)
1404 #define RLYSTC static
1405 
1406 
1407 // Temporary macro to be used to flag classes that should be static.
1408 #define STATIC_CLASS class
1409 
1410 
1411 // Temporary macro to be used to flag classes that are completely converted
1412 // to be isolate-friendly. Their mix of static/nonstatic methods/fields is
1413 // correct.
1414 #define ISOLATED_CLASS class
1415 
1416 } }  // namespace v8::internal
1417 
1418 // TODO(isolates): Get rid of these -inl.h includes and place them only where
1419 //                 they're needed.
1420 #include "allocation-inl.h"
1421 #include "zone-inl.h"
1422 #include "frames-inl.h"
1423 
1424 #endif  // V8_ISOLATE_H_
1425