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