isolate.h 49.7 KB
Newer Older
1
// Copyright 2012 the V8 project authors. All rights reserved.
2 3
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
4 5 6 7

#ifndef V8_ISOLATE_H_
#define V8_ISOLATE_H_

8 9 10
#include "include/v8-debug.h"
#include "src/allocation.h"
#include "src/assert-scope.h"
11
#include "src/base/atomicops.h"
12 13
#include "src/builtins.h"
#include "src/contexts.h"
14
#include "src/date.h"
15 16 17 18 19 20 21 22 23
#include "src/execution.h"
#include "src/frames.h"
#include "src/global-handles.h"
#include "src/handles.h"
#include "src/hashmap.h"
#include "src/heap.h"
#include "src/optimizing-compiler-thread.h"
#include "src/regexp-stack.h"
#include "src/runtime.h"
24
#include "src/runtime-profiler.h"
25
#include "src/zone.h"
26 27

namespace v8 {
28 29 30 31 32

namespace base {
class RandomNumberGenerator;
}

33 34 35
namespace internal {

class Bootstrapper;
36
class CallInterfaceDescriptor;
37 38
class CodeGenerator;
class CodeRange;
39
class CodeStubInterfaceDescriptor;
40
class CodeTracer;
41
class CompilationCache;
jarin@chromium.org's avatar
jarin@chromium.org committed
42
class ConsStringIteratorOp;
43 44 45 46 47 48 49
class ContextSlotCache;
class Counters;
class CpuFeatures;
class CpuProfiler;
class DeoptimizerData;
class Deserializer;
class EmptyStatement;
50
class ExternalCallbackScope;
51 52 53 54 55
class ExternalReferenceTable;
class Factory;
class FunctionInfoListener;
class HandleScopeImplementer;
class HeapProfiler;
56
class HStatistics;
57
class HTracer;
58
class InlineRuntimeFunctionsTable;
59
class InnerPointerToCodeCache;
jarin@chromium.org's avatar
jarin@chromium.org committed
60 61
class MaterializedObjectStore;
class NoAllocationStringAllocator;
62
class CodeAgingHelper;
63 64 65 66
class RegExpStack;
class SaveContext;
class StringTracker;
class StubCache;
67
class SweeperThread;
68 69 70
class ThreadManager;
class ThreadState;
class ThreadVisitor;  // Defined in v8threads.h
jarin@chromium.org's avatar
jarin@chromium.org committed
71
class UnicodeCache;
72
template <StateTag Tag> class VMState;
73 74 75 76 77 78 79 80 81 82

// 'void function pointer', used to roundtrip the
// ExternalReference::ExternalReferenceRedirector since we can not include
// assembler.h, where it is defined, here.
typedef void* ExternalReferenceRedirectorPointer();


class Debug;
class Debugger;

83
#if !defined(__arm__) && V8_TARGET_ARCH_ARM || \
84
    !defined(__aarch64__) && V8_TARGET_ARCH_ARM64 || \
85
    !defined(__mips__) && V8_TARGET_ARCH_MIPS
86 87 88 89
class Redirection;
class Simulator;
#endif

90

91 92 93 94 95 96 97 98
// Static indirection table for handles to constants.  If a frame
// element represents a constant, the data contains an index into
// this table of handles to the actual constants.
// Static indirection table for handles to constants.  If a Result
// represents a constant, the data contains an index into this table
// of handles to the actual constants.
typedef ZoneList<Handle<Object> > ZoneObjectList;

99
#define RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate)    \
100 101 102 103 104 105
  do {                                                    \
    Isolate* __isolate__ = (isolate);                     \
    if (__isolate__->has_scheduled_exception()) {         \
      return __isolate__->PromoteScheduledException();    \
    }                                                     \
  } while (false)
106

107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
// Macros for MaybeHandle.

#define RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, T)  \
  do {                                                       \
    Isolate* __isolate__ = (isolate);                        \
    if (__isolate__->has_scheduled_exception()) {            \
      __isolate__->PromoteScheduledException();              \
      return MaybeHandle<T>();                               \
    }                                                        \
  } while (false)

#define ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, dst, call, value)  \
  do {                                                               \
    if (!(call).ToHandle(&dst)) {                                    \
      ASSERT((isolate)->has_pending_exception());                    \
      return value;                                                  \
    }                                                                \
  } while (false)

#define ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, dst, call)  \
127 128
  ASSIGN_RETURN_ON_EXCEPTION_VALUE(                             \
      isolate, dst, call, isolate->heap()->exception())
129 130 131 132

#define ASSIGN_RETURN_ON_EXCEPTION(isolate, dst, call, T)  \
  ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, dst, call, MaybeHandle<T>())

133
#define RETURN_ON_EXCEPTION_VALUE(isolate, call, value)            \
134
  do {                                                             \
135
    if ((call).is_null()) {                                        \
136 137 138 139 140 141
      ASSERT((isolate)->has_pending_exception());                  \
      return value;                                                \
    }                                                              \
  } while (false)

#define RETURN_FAILURE_ON_EXCEPTION(isolate, call)  \
142
  RETURN_ON_EXCEPTION_VALUE(isolate, call, isolate->heap()->exception())
143 144

#define RETURN_ON_EXCEPTION(isolate, call, T)  \
145
  RETURN_ON_EXCEPTION_VALUE(isolate, call, MaybeHandle<T>())
146 147


148 149 150 151 152 153 154
#define FOR_EACH_ISOLATE_ADDRESS_NAME(C)                \
  C(Handler, handler)                                   \
  C(CEntryFP, c_entry_fp)                               \
  C(Context, context)                                   \
  C(PendingException, pending_exception)                \
  C(ExternalCaughtException, external_caught_exception) \
  C(JSEntrySP, js_entry_sp)
155 156


157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
// Platform-independent, reliable thread identifier.
class ThreadId {
 public:
  // Creates an invalid ThreadId.
  ThreadId() : id_(kInvalidId) {}

  // Returns ThreadId for current thread.
  static ThreadId Current() { return ThreadId(GetCurrentThreadId()); }

  // Returns invalid ThreadId (guaranteed not to be equal to any thread).
  static ThreadId Invalid() { return ThreadId(kInvalidId); }

  // Compares ThreadIds for equality.
  INLINE(bool Equals(const ThreadId& other) const) {
    return id_ == other.id_;
  }

  // Checks whether this ThreadId refers to any thread.
  INLINE(bool IsValid() const) {
    return id_ != kInvalidId;
  }

  // Converts ThreadId to an integer representation
  // (required for public API: V8::V8::GetCurrentThreadId).
  int ToInteger() const { return id_; }

  // Converts ThreadId to an integer representation
  // (required for public API: V8::V8::TerminateExecution).
  static ThreadId FromInteger(int id) { return ThreadId(id); }

 private:
  static const int kInvalidId = -1;

  explicit ThreadId(int id) : id_(id) {}

  static int AllocateThreadId();

  static int GetCurrentThreadId();

  int id_;

198
  static base::Atomic32 highest_thread_id_;
199 200 201 202 203

  friend class Isolate;
};


204 205 206 207 208
#define FIELD_ACCESSOR(type, name)                 \
  inline void set_##name(type v) { name##_ = v; }  \
  inline type name() const { return name##_; }


209 210
class ThreadLocalTop BASE_EMBEDDED {
 public:
211 212 213 214
  // Does early low-level initialization that does not depend on the
  // isolate being present.
  ThreadLocalTop();

215 216 217 218 219
  // Initialize the thread data.
  void Initialize();

  // Get the top C++ try catch handler or NULL if none are registered.
  //
220
  // This method is not guaranteed to return an address that can be
221 222
  // used for comparison with addresses into the JS stack.  If such an
  // address is needed, use try_catch_handler_address.
223
  FIELD_ACCESSOR(v8::TryCatch*, try_catch_handler)
224 225 226 227 228 229 230 231 232 233 234

  // Get the address of the top C++ try catch handler or NULL if
  // none are registered.
  //
  // This method always returns an address that can be compared to
  // pointers into the JavaScript stack.  When running on actual
  // hardware, try_catch_handler_address and TryCatchHandler return
  // the same pointer.  When running on a simulator with a separate JS
  // stack, try_catch_handler_address returns a JS stack address that
  // corresponds to the place on the JS stack where the C++ handler
  // would have been if the stack were not separate.
235 236 237 238
  Address try_catch_handler_address() {
    return reinterpret_cast<Address>(
        v8::TryCatch::JSStackComparableAddress(try_catch_handler()));
  }
239 240 241 242

  void Free() {
    ASSERT(!has_pending_message_);
    ASSERT(!external_caught_exception_);
243
    ASSERT(try_catch_handler_ == NULL);
244 245
  }

246
  Isolate* isolate_;
247 248 249
  // The context where the current execution method is created and for variable
  // lookups.
  Context* context_;
250
  ThreadId thread_id_;
251
  Object* pending_exception_;
252
  bool has_pending_message_;
253
  bool rethrowing_message_;
254
  Object* pending_message_obj_;
255
  Object* pending_message_script_;
256 257 258 259 260
  int pending_message_start_pos_;
  int pending_message_end_pos_;
  // Use a separate value for scheduled exceptions to preserve the
  // invariants that hold about pending_exception.  We may want to
  // unify them later.
261
  Object* scheduled_exception_;
262 263 264 265 266 267 268 269 270 271 272 273
  bool external_caught_exception_;
  SaveContext* save_context_;
  v8::TryCatch* catcher_;

  // Stack.
  Address c_entry_fp_;  // the frame pointer of the top c entry frame
  Address handler_;   // try-blocks are chained through the stack

#ifdef USE_SIMULATOR
  Simulator* simulator_;
#endif

274
  Address js_entry_sp_;  // the stack pointer of the bottom JS entry frame
275 276
  // the external callback we're currently in
  ExternalCallbackScope* external_callback_scope_;
277 278 279 280 281 282 283 284
  StateTag current_vm_state_;

  // Generated code scratch locations.
  int32_t formal_count_;

  // Call back function to report unsafe JS accesses.
  v8::FailedAccessCheckCallback failed_access_check_callback_;

285 286 287
  // Head of the list of live LookupResults.
  LookupResult* top_lookup_result_;

288
 private:
289 290
  void InitializeInternal();

291
  v8::TryCatch* try_catch_handler_;
292 293 294
};


295
#if V8_TARGET_ARCH_ARM && !defined(__arm__) || \
296
    V8_TARGET_ARCH_ARM64 && !defined(__aarch64__) || \
297 298 299 300 301 302 303 304 305 306 307 308 309
    V8_TARGET_ARCH_MIPS && !defined(__mips__)

#define ISOLATE_INIT_SIMULATOR_LIST(V)                                         \
  V(bool, simulator_initialized, false)                                        \
  V(HashMap*, simulator_i_cache, NULL)                                         \
  V(Redirection*, simulator_redirection, NULL)
#else

#define ISOLATE_INIT_SIMULATOR_LIST(V)

#endif


310 311 312 313
#ifdef DEBUG

#define ISOLATE_INIT_DEBUG_ARRAY_LIST(V)                                       \
  V(CommentStatistic, paged_space_comments_statistics,                         \
314 315
      CommentStatistic::kMaxComments + 1)                                      \
  V(int, code_kind_statistics, Code::NUMBER_OF_KINDS)
316 317 318 319 320 321 322 323
#else

#define ISOLATE_INIT_DEBUG_ARRAY_LIST(V)

#endif

#define ISOLATE_INIT_ARRAY_LIST(V)                                             \
  /* SerializerDeserializer state. */                                          \
324
  V(int32_t, jsregexp_static_offsets_vector, kJSRegexpStaticOffsetsVectorSize) \
325 326 327
  V(int, bad_char_shift_table, kUC16AlphabetSize)                              \
  V(int, good_suffix_shift_table, (kBMMaxShift + 1))                           \
  V(int, suffix_table, (kBMMaxShift + 1))                                      \
328
  V(uint32_t, private_random_seed, 2)                                          \
329 330
  ISOLATE_INIT_DEBUG_ARRAY_LIST(V)

331
typedef List<HeapObject*> DebugObjectCache;
332 333 334 335

#define ISOLATE_INIT_LIST(V)                                                   \
  /* SerializerDeserializer state. */                                          \
  V(int, serialize_partial_snapshot_cache_length, 0)                           \
336 337
  V(int, serialize_partial_snapshot_cache_capacity, 0)                         \
  V(Object**, serialize_partial_snapshot_cache, NULL)                          \
338 339 340 341
  /* Assembler state. */                                                       \
  /* A previously allocated buffer of kMinimalBufferSize bytes, or NULL. */    \
  V(byte*, assembler_spare_buffer, NULL)                                       \
  V(FatalErrorCallback, exception_behavior, NULL)                              \
342
  V(LogEventCallback, event_logger, NULL)                                      \
343
  V(AllowCodeGenerationFromStringsCallback, allow_code_gen_callback, NULL)     \
344
  /* To distinguish the function templates, so that we can find them in the */ \
345
  /* function cache of the native context. */                                  \
346 347 348 349 350 351 352 353 354 355 356
  V(int, next_serial_number, 0)                                                \
  V(ExternalReferenceRedirectorPointer*, external_reference_redirector, NULL)  \
  /* Part of the state of liveedit. */                                         \
  V(FunctionInfoListener*, active_function_info_listener, NULL)                \
  /* State for Relocatable. */                                                 \
  V(Relocatable*, relocatable_top, NULL)                                       \
  V(DebugObjectCache*, string_stream_debug_object_cache, NULL)                 \
  V(Object*, string_stream_current_security_token, NULL)                       \
  /* Serializer state. */                                                      \
  V(ExternalReferenceTable*, external_reference_table, NULL)                   \
  /* AstNode state. */                                                         \
357
  V(int, ast_node_id, 0)                                                       \
358
  V(unsigned, ast_node_count, 0)                                               \
359
  V(int, pending_microtask_count, 0)                                           \
360
  V(bool, autorun_microtasks, true)                                            \
361
  V(HStatistics*, hstatistics, NULL)                                           \
362
  V(HTracer*, htracer, NULL)                                                   \
363
  V(CodeTracer*, code_tracer, NULL)                                            \
364 365
  V(bool, fp_stubs_generated, false)                                           \
  V(int, max_available_threads, 0)                                             \
366
  V(uint32_t, per_isolate_assert_data, 0xFFFFFFFFu)                            \
367 368
  V(InterruptCallback, api_interrupt_callback, NULL)                           \
  V(void*, api_interrupt_callback_data, NULL)                                  \
369
  ISOLATE_INIT_SIMULATOR_LIST(V)
370

371 372 373 374 375
#define THREAD_LOCAL_TOP_ACCESSOR(type, name)                        \
  inline void set_##name(type v) { thread_local_top_.name##_ = v; }  \
  inline type name() const { return thread_local_top_.name##_; }


376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393
class Isolate {
  // These forward declarations are required to make the friend declarations in
  // PerIsolateThreadData work on some older versions of gcc.
  class ThreadDataTable;
  class EntryStackItem;
 public:
  ~Isolate();

  // A thread has a PerIsolateThreadData instance for each isolate that it has
  // entered. That instance is allocated when the isolate is initially entered
  // and reused on subsequent entries.
  class PerIsolateThreadData {
   public:
    PerIsolateThreadData(Isolate* isolate, ThreadId thread_id)
        : isolate_(isolate),
          thread_id_(thread_id),
          stack_limit_(0),
          thread_state_(NULL),
394
#if !defined(__arm__) && V8_TARGET_ARCH_ARM || \
395
    !defined(__aarch64__) && V8_TARGET_ARCH_ARM64 || \
396
    !defined(__mips__) && V8_TARGET_ARCH_MIPS
397 398 399 400
          simulator_(NULL),
#endif
          next_(NULL),
          prev_(NULL) { }
401
    ~PerIsolateThreadData();
402 403
    Isolate* isolate() const { return isolate_; }
    ThreadId thread_id() const { return thread_id_; }
404 405 406

    FIELD_ACCESSOR(uintptr_t, stack_limit)
    FIELD_ACCESSOR(ThreadState*, thread_state)
407

408
#if !defined(__arm__) && V8_TARGET_ARCH_ARM || \
409
    !defined(__aarch64__) && V8_TARGET_ARCH_ARM64 || \
410
    !defined(__mips__) && V8_TARGET_ARCH_MIPS
411
    FIELD_ACCESSOR(Simulator*, simulator)
412 413 414
#endif

    bool Matches(Isolate* isolate, ThreadId thread_id) const {
415
      return isolate_ == isolate && thread_id_.Equals(thread_id);
416 417 418 419 420 421 422 423
    }

   private:
    Isolate* isolate_;
    ThreadId thread_id_;
    uintptr_t stack_limit_;
    ThreadState* thread_state_;

424
#if !defined(__arm__) && V8_TARGET_ARCH_ARM || \
425
    !defined(__aarch64__) && V8_TARGET_ARCH_ARM64 || \
426
    !defined(__mips__) && V8_TARGET_ARCH_MIPS
427 428 429 430 431 432 433 434 435 436 437 438 439 440 441
    Simulator* simulator_;
#endif

    PerIsolateThreadData* next_;
    PerIsolateThreadData* prev_;

    friend class Isolate;
    friend class ThreadDataTable;
    friend class EntryStackItem;

    DISALLOW_COPY_AND_ASSIGN(PerIsolateThreadData);
  };


  enum AddressId {
442 443
#define DECLARE_ENUM(CamelName, hacker_name) k##CamelName##Address,
    FOR_EACH_ISOLATE_ADDRESS_NAME(DECLARE_ENUM)
444
#undef DECLARE_ENUM
445
    kIsolateAddressCount
446 447 448 449 450 451
  };

  // Returns the PerIsolateThreadData for the current thread (or NULL if one is
  // not currently set).
  static PerIsolateThreadData* CurrentPerIsolateThreadData() {
    return reinterpret_cast<PerIsolateThreadData*>(
452
        base::Thread::GetThreadLocal(per_isolate_thread_data_key_));
453 454 455 456
  }

  // Returns the isolate inside which the current thread is running.
  INLINE(static Isolate* Current()) {
vitalyr@chromium.org's avatar
vitalyr@chromium.org committed
457
    Isolate* isolate = reinterpret_cast<Isolate*>(
458
        base::Thread::GetExistingThreadLocal(isolate_key_));
459 460 461 462 463
    ASSERT(isolate != NULL);
    return isolate;
  }

  INLINE(static Isolate* UncheckedCurrent()) {
464 465
    return reinterpret_cast<Isolate*>(
        base::Thread::GetThreadLocal(isolate_key_));
466 467
  }

468 469 470 471 472 473 474
  // Usually called by Init(), but can be called early e.g. to allow
  // testing components that require logging but not the whole
  // isolate.
  //
  // Safe to call more than once.
  void InitializeLoggingAndCounters();

475 476 477 478 479 480 481 482 483 484 485 486
  bool Init(Deserializer* des);

  bool IsInitialized() { return state_ == INITIALIZED; }

  // True if at least one thread Enter'ed this isolate.
  bool IsInUse() { return entry_stack_ != NULL; }

  // Destroys the non-default isolates.
  // Sets default isolate into "has_been_disposed" state rather then destroying,
  // for legacy API reasons.
  void TearDown();

487 488
  static void GlobalTearDown();

489 490 491 492 493 494 495
  static void SetCrashIfDefaultIsolateInitialized();
  // Ensures that process-wide resources and the default isolate have been
  // allocated. It is only necessary to call this method in rare cases, for
  // example if you are using V8 from within the body of a static initializer.
  // Safe to call multiple times.
  static void EnsureDefaultIsolate();

496 497 498 499
  // Find the PerThread for this particular (isolate, thread) combination
  // If one does not yet exist, return null.
  PerIsolateThreadData* FindPerThreadDataForThisThread();

500 501 502 503
  // Find the PerThread for given (isolate, thread) combination
  // If one does not yet exist, return null.
  PerIsolateThreadData* FindPerThreadDataForThread(ThreadId thread_id);

504 505 506
  // Returns the key used to store the pointer to the current isolate.
  // Used internally for V8 threads that do not execute JavaScript but still
  // are part of the domain of an isolate (like the context switcher).
507
  static base::Thread::LocalStorageKey isolate_key() {
508 509
    return isolate_key_;
  }
510 511

  // Returns the key used to store process-wide thread IDs.
512
  static base::Thread::LocalStorageKey thread_id_key() {
513 514
    return thread_id_key_;
  }
515

516
  static base::Thread::LocalStorageKey per_isolate_thread_data_key();
517 518

  // Mutex for serializing access to break control structures.
519
  base::RecursiveMutex* break_access() { return &break_access_; }
520 521 522 523 524 525

  Address get_address_from_id(AddressId id);

  // Access to top context (where the current function object was created).
  Context* context() { return thread_local_top_.context_; }
  void set_context(Context* context) {
526
    ASSERT(context == NULL || context->IsContext());
527 528 529 530
    thread_local_top_.context_ = context;
  }
  Context** context_address() { return &thread_local_top_.context_; }

531
  THREAD_LOCAL_TOP_ACCESSOR(SaveContext*, save_context)
532 533

  // Access to current thread id.
534
  THREAD_LOCAL_TOP_ACCESSOR(ThreadId, thread_id)
535 536

  // Interface to pending exception.
537
  Object* pending_exception() {
538
    ASSERT(has_pending_exception());
539
    ASSERT(!thread_local_top_.pending_exception_->IsException());
540 541
    return thread_local_top_.pending_exception_;
  }
542

543 544 545
  void set_pending_exception(Object* exception_obj) {
    ASSERT(!exception_obj->IsException());
    thread_local_top_.pending_exception_ = exception_obj;
546
  }
547

548
  void clear_pending_exception() {
549
    ASSERT(!thread_local_top_.pending_exception_->IsException());
550 551
    thread_local_top_.pending_exception_ = heap_.the_hole_value();
  }
552

553
  Object** pending_exception_address() {
554 555
    return &thread_local_top_.pending_exception_;
  }
556

557
  bool has_pending_exception() {
558
    ASSERT(!thread_local_top_.pending_exception_->IsException());
559 560
    return !thread_local_top_.pending_exception_->IsTheHole();
  }
561 562 563

  THREAD_LOCAL_TOP_ACCESSOR(bool, external_caught_exception)

564 565 566
  void clear_pending_message() {
    thread_local_top_.has_pending_message_ = false;
    thread_local_top_.pending_message_obj_ = heap_.the_hole_value();
567
    thread_local_top_.pending_message_script_ = heap_.the_hole_value();
568 569
  }
  v8::TryCatch* try_catch_handler() {
570
    return thread_local_top_.try_catch_handler();
571 572 573 574 575 576 577
  }
  Address try_catch_handler_address() {
    return thread_local_top_.try_catch_handler_address();
  }
  bool* external_caught_exception_address() {
    return &thread_local_top_.external_caught_exception_;
  }
578 579

  THREAD_LOCAL_TOP_ACCESSOR(v8::TryCatch*, catcher)
580

581
  Object** scheduled_exception_address() {
582 583
    return &thread_local_top_.scheduled_exception_;
  }
584 585 586 587 588 589 590 591 592 593 594 595 596 597

  Address pending_message_obj_address() {
    return reinterpret_cast<Address>(&thread_local_top_.pending_message_obj_);
  }

  Address has_pending_message_address() {
    return reinterpret_cast<Address>(&thread_local_top_.has_pending_message_);
  }

  Address pending_message_script_address() {
    return reinterpret_cast<Address>(
        &thread_local_top_.pending_message_script_);
  }

598
  Object* scheduled_exception() {
599
    ASSERT(has_scheduled_exception());
600
    ASSERT(!thread_local_top_.scheduled_exception_->IsException());
601 602 603
    return thread_local_top_.scheduled_exception_;
  }
  bool has_scheduled_exception() {
604
    ASSERT(!thread_local_top_.scheduled_exception_->IsException());
605
    return thread_local_top_.scheduled_exception_ != heap_.the_hole_value();
606 607
  }
  void clear_scheduled_exception() {
608
    ASSERT(!thread_local_top_.scheduled_exception_->IsException());
609 610 611
    thread_local_top_.scheduled_exception_ = heap_.the_hole_value();
  }

612 613
  bool HasExternalTryCatch();
  bool IsFinallyOnTop();
614

615
  bool is_catchable_by_javascript(Object* exception) {
616
    return exception != heap()->termination_exception();
617 618
  }

619 620 621
  // Serializer.
  void PushToPartialSnapshotCache(Object* obj);

622 623 624 625 626 627 628 629 630 631 632
  // JS execution stack (see frames.h).
  static Address c_entry_fp(ThreadLocalTop* thread) {
    return thread->c_entry_fp_;
  }
  static Address handler(ThreadLocalTop* thread) { return thread->handler_; }

  inline Address* c_entry_fp_address() {
    return &thread_local_top_.c_entry_fp_;
  }
  inline Address* handler_address() { return &thread_local_top_.handler_; }

633 634 635
  // Bottom JS entry.
  Address js_entry_sp() {
    return thread_local_top_.js_entry_sp_;
636 637 638 639 640 641 642 643 644
  }
  inline Address* js_entry_sp_address() {
    return &thread_local_top_.js_entry_sp_;
  }

  // Generated code scratch locations.
  void* formal_count_address() { return &thread_local_top_.formal_count_; }

  // Returns the global object of the current context. It could be
645
  // a builtin object, or a JS global object.
646 647
  Handle<GlobalObject> global_object() {
    return Handle<GlobalObject>(context()->global_object());
648 649 650
  }

  // Returns the global proxy object of the current context.
651
  JSObject* global_proxy() {
652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667
    return context()->global_proxy();
  }

  Handle<JSBuiltinsObject> js_builtins_object() {
    return Handle<JSBuiltinsObject>(thread_local_top_.context_->builtins());
  }

  static int ArchiveSpacePerThread() { return sizeof(ThreadLocalTop); }
  void FreeThreadResources() { thread_local_top_.Free(); }

  // This method is called by the api after operations that may throw
  // exceptions.  If an exception was thrown and not handled by an external
  // handler the exception is scheduled to be rethrown when we return to running
  // JavaScript code.  If an exception is scheduled true is returned.
  bool OptionalRescheduleException(bool is_bottom_call);

668 669 670
  class ExceptionScope {
   public:
    explicit ExceptionScope(Isolate* isolate) :
671 672
      // Scope currently can only be used for regular exceptions,
      // not termination exception.
673
      isolate_(isolate),
674
      pending_exception_(isolate_->pending_exception(), isolate_),
675 676 677 678 679 680 681 682 683 684 685 686 687 688
      catcher_(isolate_->catcher())
    { }

    ~ExceptionScope() {
      isolate_->set_catcher(catcher_);
      isolate_->set_pending_exception(*pending_exception_);
    }

   private:
    Isolate* isolate_;
    Handle<Object> pending_exception_;
    v8::TryCatch* catcher_;
  };

689 690 691 692 693 694 695
  void SetCaptureStackTraceForUncaughtExceptions(
      bool capture,
      int frame_limit,
      StackTrace::StackTraceOptions options);

  void PrintCurrentStackTrace(FILE* out);
  void PrintStack(StringStream* accumulator);
696
  void PrintStack(FILE* out);
697
  Handle<String> StackTraceString();
698 699 700 701
  NO_INLINE(void PushStackTraceAndDie(unsigned int magic,
                                      Object* object,
                                      Map* map,
                                      unsigned int magic2));
702 703 704
  Handle<JSArray> CaptureCurrentStackTrace(
      int frame_limit,
      StackTrace::StackTraceOptions options);
705 706 707 708

  Handle<JSArray> CaptureSimpleStackTrace(Handle<JSObject> error_object,
                                          Handle<Object> caller,
                                          int limit);
709
  void CaptureAndSetDetailedStackTrace(Handle<JSObject> error_object);
710

711 712 713
  // Returns if the top context may access the given global object. If
  // the result is false, the pending exception is guaranteed to be
  // set.
714

715 716
  bool MayNamedAccess(Handle<JSObject> receiver,
                      Handle<Object> key,
717
                      v8::AccessType type);
718
  bool MayIndexedAccess(Handle<JSObject> receiver,
719 720 721 722
                        uint32_t index,
                        v8::AccessType type);

  void SetFailedAccessCheckCallback(v8::FailedAccessCheckCallback callback);
723
  void ReportFailedAccessCheck(Handle<JSObject> receiver, v8::AccessType type);
724 725 726

  // Exception throwing support. The caller should use the result
  // of Throw() as its return value.
727
  Object* Throw(Object* exception, MessageLocation* location = NULL);
728 729 730 731 732 733 734 735

  template <typename T>
  MUST_USE_RESULT MaybeHandle<T> Throw(Handle<Object> exception,
                                       MessageLocation* location = NULL) {
    Throw(*exception, location);
    return MaybeHandle<T>();
  }

736 737 738
  // Re-throw an exception.  This involves no error reporting since
  // error reporting was handled when the exception was thrown
  // originally.
739
  Object* ReThrow(Object* exception);
740
  void ScheduleThrow(Object* exception);
741 742 743
  // Re-set pending message, script and positions reported to the TryCatch
  // back to the TLS for re-use when rethrowing.
  void RestorePendingMessageFromTryCatch(v8::TryCatch* handler);
744
  void ReportPendingMessages();
745 746
  // Return pending location if any or unfilled structure.
  MessageLocation GetMessageLocation();
747 748
  Object* ThrowIllegalOperation();
  Object* ThrowInvalidStringLength();
749 750

  // Promote a scheduled exception to pending. Asserts has_scheduled_exception.
751
  Object* PromoteScheduledException();
752
  void DoThrow(Object* exception, MessageLocation* location);
753 754 755 756 757 758 759 760 761 762
  // Checks if exception should be reported and finds out if it's
  // caught externally.
  bool ShouldReportException(bool* can_be_caught_externally,
                             bool catchable_by_javascript);

  // Attempts to compute the current source location, storing the
  // result in the target out parameter.
  void ComputeLocation(MessageLocation* target);

  // Out of resource exception helpers.
763 764
  Object* StackOverflow();
  Object* TerminateExecution();
765
  void CancelTerminateExecution();
766

767 768
  void InvokeApiInterruptCallback();

769 770 771 772 773 774 775
  // Administration
  void Iterate(ObjectVisitor* v);
  void Iterate(ObjectVisitor* v, ThreadLocalTop* t);
  char* Iterate(ObjectVisitor* v, char* t);
  void IterateThread(ThreadVisitor* v, char* t);


776
  // Returns the current native and global context.
777
  Handle<Context> native_context();
778
  Handle<Context> global_context();
779

780 781 782
  // Returns the native context of the calling JavaScript code.  That
  // is, the native context of the top-most JavaScript frame.
  Handle<Context> GetCallingNativeContext();
783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815

  void RegisterTryCatchHandler(v8::TryCatch* that);
  void UnregisterTryCatchHandler(v8::TryCatch* that);

  char* ArchiveThread(char* to);
  char* RestoreThread(char* from);

  static const char* const kStackOverflowMessage;

  static const int kUC16AlphabetSize = 256;  // See StringSearchBase.
  static const int kBMMaxShift = 250;        // See StringSearchBase.

  // Accessors.
#define GLOBAL_ACCESSOR(type, name, initialvalue)                       \
  inline type name() const {                                            \
    ASSERT(OFFSET_OF(Isolate, name##_) == name##_debug_offset_);        \
    return name##_;                                                     \
  }                                                                     \
  inline void set_##name(type value) {                                  \
    ASSERT(OFFSET_OF(Isolate, name##_) == name##_debug_offset_);        \
    name##_ = value;                                                    \
  }
  ISOLATE_INIT_LIST(GLOBAL_ACCESSOR)
#undef GLOBAL_ACCESSOR

#define GLOBAL_ARRAY_ACCESSOR(type, name, length)                       \
  inline type* name() {                                                 \
    ASSERT(OFFSET_OF(Isolate, name##_) == name##_debug_offset_);        \
    return &(name##_)[0];                                               \
  }
  ISOLATE_INIT_ARRAY_LIST(GLOBAL_ARRAY_ACCESSOR)
#undef GLOBAL_ARRAY_ACCESSOR

816 817
#define NATIVE_CONTEXT_FIELD_ACCESSOR(index, type, name)            \
  Handle<type> name() {                                             \
818
    return Handle<type>(native_context()->name(), this);            \
819 820
  }                                                                 \
  bool is_##name(type* value) {                                     \
821
    return native_context()->is_##name(value);                      \
822
  }
823 824
  NATIVE_CONTEXT_FIELDS(NATIVE_CONTEXT_FIELD_ACCESSOR)
#undef NATIVE_CONTEXT_FIELD_ACCESSOR
825 826

  Bootstrapper* bootstrapper() { return bootstrapper_; }
827 828 829 830 831 832
  Counters* counters() {
    // Call InitializeLoggingAndCounters() if logging is needed before
    // the isolate is fully initialized.
    ASSERT(counters_ != NULL);
    return counters_;
  }
833 834 835
  CodeRange* code_range() { return code_range_; }
  RuntimeProfiler* runtime_profiler() { return runtime_profiler_; }
  CompilationCache* compilation_cache() { return compilation_cache_; }
836 837 838 839 840 841
  Logger* logger() {
    // Call InitializeLoggingAndCounters() if logging is needed before
    // the isolate is fully initialized.
    ASSERT(logger_ != NULL);
    return logger_;
  }
842 843
  StackGuard* stack_guard() { return &stack_guard_; }
  Heap* heap() { return &heap_; }
844
  StatsTable* stats_table();
845
  StubCache* stub_cache() { return stub_cache_; }
846
  CodeAgingHelper* code_aging_helper() { return code_aging_helper_; }
847 848
  DeoptimizerData* deoptimizer_data() { return deoptimizer_data_; }
  ThreadLocalTop* thread_local_top() { return &thread_local_top_; }
jarin@chromium.org's avatar
jarin@chromium.org committed
849 850 851
  MaterializedObjectStore* materialized_object_store() {
    return materialized_object_store_;
  }
852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868

  MemoryAllocator* memory_allocator() {
    return memory_allocator_;
  }

  KeyedLookupCache* keyed_lookup_cache() {
    return keyed_lookup_cache_;
  }

  ContextSlotCache* context_slot_cache() {
    return context_slot_cache_;
  }

  DescriptorLookupCache* descriptor_lookup_cache() {
    return descriptor_lookup_cache_;
  }

869 870
  HandleScopeData* handle_scope_data() { return &handle_scope_data_; }

871 872 873 874
  HandleScopeImplementer* handle_scope_implementer() {
    ASSERT(handle_scope_implementer_);
    return handle_scope_implementer_;
  }
875
  Zone* runtime_zone() { return &runtime_zone_; }
876

877 878
  UnicodeCache* unicode_cache() {
    return unicode_cache_;
879 880
  }

881 882 883
  InnerPointerToCodeCache* inner_pointer_to_code_cache() {
    return inner_pointer_to_code_cache_;
  }
884

885
  ConsStringIteratorOp* write_iterator() { return write_iterator_; }
886 887 888

  GlobalHandles* global_handles() { return global_handles_; }

889 890
  EternalHandles* eternal_handles() { return eternal_handles_; }

891 892 893 894 895 896 897 898 899 900 901 902
  ThreadManager* thread_manager() { return thread_manager_; }

  StringTracker* string_tracker() { return string_tracker_; }

  unibrow::Mapping<unibrow::Ecma262UnCanonicalize>* jsregexp_uncanonicalize() {
    return &jsregexp_uncanonicalize_;
  }

  unibrow::Mapping<unibrow::CanonicalizationRange>* jsregexp_canonrange() {
    return &jsregexp_canonrange_;
  }

903 904
  ConsStringIteratorOp* objects_string_compare_iterator_a() {
    return &objects_string_compare_iterator_a_;
905 906
  }

907 908
  ConsStringIteratorOp* objects_string_compare_iterator_b() {
    return &objects_string_compare_iterator_b_;
909 910
  }

911 912
  StaticResource<ConsStringIteratorOp>* objects_string_iterator() {
    return &objects_string_iterator_;
913 914 915 916 917 918
  }

  RuntimeState* runtime_state() { return &runtime_state_; }

  Builtins* builtins() { return &builtins_; }

919 920 921 922 923 924
  void NotifyExtensionInstalled() {
    has_installed_extensions_ = true;
  }

  bool has_installed_extensions() { return has_installed_extensions_; }

925 926 927 928 929 930 931 932 933 934 935 936
  unibrow::Mapping<unibrow::Ecma262Canonicalize>*
      regexp_macro_assembler_canonicalize() {
    return &regexp_macro_assembler_canonicalize_;
  }

  RegExpStack* regexp_stack() { return regexp_stack_; }

  unibrow::Mapping<unibrow::Ecma262Canonicalize>*
      interp_canonicalize_mapping() {
    return &interp_canonicalize_mapping_;
  }

937
  Debug* debug() { return debug_; }
938

939 940
  inline bool DebuggerHasBreakPoints();

941
  CpuProfiler* cpu_profiler() const { return cpu_profiler_; }
942
  HeapProfiler* heap_profiler() const { return heap_profiler_; }
943

944 945 946 947 948 949 950 951 952 953
#ifdef DEBUG
  HistogramInfo* heap_histograms() { return heap_histograms_; }

  JSObject::SpillInformation* js_spill_information() {
    return &js_spill_information_;
  }
#endif

  Factory* factory() { return reinterpret_cast<Factory*>(this); }

954
  static const int kJSRegexpStaticOffsetsVectorSize = 128;
955

956
  THREAD_LOCAL_TOP_ACCESSOR(ExternalCallbackScope*, external_callback_scope)
957

958
  THREAD_LOCAL_TOP_ACCESSOR(StateTag, current_vm_state)
959

960 961 962 963 964 965 966 967
  void SetData(uint32_t slot, void* data) {
    ASSERT(slot < Internals::kNumIsolateDataSlots);
    embedder_data_[slot] = data;
  }
  void* GetData(uint32_t slot) {
    ASSERT(slot < Internals::kNumIsolateDataSlots);
    return embedder_data_[slot];
  }
968

969
  THREAD_LOCAL_TOP_ACCESSOR(LookupResult*, top_lookup_result)
970

971 972 973 974 975 976 977 978
  void enable_serializer() {
    // The serializer can only be enabled before the isolate init.
    ASSERT(state_ != INITIALIZED);
    serializer_enabled_ = true;
  }

  bool serializer_enabled() const { return serializer_enabled_; }

979 980 981
  bool IsDead() { return has_fatal_error_; }
  void SignalFatalError() { has_fatal_error_ = true; }

982
  bool use_crankshaft() const;
983

984 985
  bool initialized_from_snapshot() { return initialized_from_snapshot_; }

986
  double time_millis_since_init() {
987
    return base::OS::TimeCurrentMillis() - time_millis_at_init_;
988 989
  }

990 991 992 993 994 995 996 997 998 999 1000
  DateCache* date_cache() {
    return date_cache_;
  }

  void set_date_cache(DateCache* date_cache) {
    if (date_cache != date_cache_) {
      delete date_cache_;
    }
    date_cache_ = date_cache;
  }

1001 1002 1003 1004
  Map* get_initial_js_array_map(ElementsKind kind);

  bool IsFastArrayConstructorPrototypeChainIntact();

1005 1006 1007
  CodeStubInterfaceDescriptor*
      code_stub_interface_descriptor(int index);

1008 1009 1010
  enum CallDescriptorKey {
    KeyedCall,
    NamedCall,
1011
    CallHandler,
1012
    ArgumentAdaptorCall,
1013
    ApiFunctionCall,
1014 1015 1016 1017 1018
    NUMBER_OF_CALL_DESCRIPTORS
  };

  CallInterfaceDescriptor* call_descriptor(CallDescriptorKey index);

1019 1020 1021 1022
  void IterateDeferredHandles(ObjectVisitor* visitor);
  void LinkDeferredHandles(DeferredHandles* deferred_handles);
  void UnlinkDeferredHandles(DeferredHandles* deferred_handles);

1023 1024 1025 1026
#ifdef DEBUG
  bool IsDeferredHandle(Object** location);
#endif  // DEBUG

1027 1028 1029 1030 1031 1032 1033
  bool concurrent_recompilation_enabled() {
    // Thread is only available with flag enabled.
    ASSERT(optimizing_compiler_thread_ == NULL ||
           FLAG_concurrent_recompilation);
    return optimizing_compiler_thread_ != NULL;
  }

yangguo@chromium.org's avatar
yangguo@chromium.org committed
1034
  bool concurrent_osr_enabled() const {
1035 1036 1037 1038 1039 1040
    // Thread is only available with flag enabled.
    ASSERT(optimizing_compiler_thread_ == NULL ||
           FLAG_concurrent_recompilation);
    return optimizing_compiler_thread_ != NULL && FLAG_concurrent_osr;
  }

1041
  OptimizingCompilerThread* optimizing_compiler_thread() {
1042
    return optimizing_compiler_thread_;
1043 1044
  }

yangguo@chromium.org's avatar
yangguo@chromium.org committed
1045
  int num_sweeper_threads() const {
1046 1047
    return num_sweeper_threads_;
  }
1048

1049 1050 1051 1052
  SweeperThread** sweeper_threads() {
    return sweeper_thread_;
  }

1053 1054
  int id() const { return static_cast<int>(id_); }

1055
  HStatistics* GetHStatistics();
1056
  HTracer* GetHTracer();
1057
  CodeTracer* GetCodeTracer();
1058

1059 1060 1061 1062 1063
  FunctionEntryHook function_entry_hook() { return function_entry_hook_; }
  void set_function_entry_hook(FunctionEntryHook function_entry_hook) {
    function_entry_hook_ = function_entry_hook;
  }

1064 1065
  void* stress_deopt_count_address() { return &stress_deopt_count_; }

1066
  inline base::RandomNumberGenerator* random_number_generator();
1067

1068 1069 1070
  // Given an address occupied by a live code object, return that object.
  Object* FindCodeObject(Address a);

1071 1072 1073 1074 1075 1076 1077 1078
  int NextOptimizationId() {
    int id = next_optimization_id_++;
    if (!Smi::IsValid(next_optimization_id_)) {
      next_optimization_id_ = 0;
    }
    return id;
  }

1079 1080 1081
  // Get (and lazily initialize) the registry for per-isolate symbols.
  Handle<JSObject> GetSymbolRegistry();

1082 1083 1084 1085
  void AddCallCompletedCallback(CallCompletedCallback callback);
  void RemoveCallCompletedCallback(CallCompletedCallback callback);
  void FireCallCompletedCallback();

1086
  void EnqueueMicrotask(Handle<Object> microtask);
1087 1088
  void RunMicrotasks();

1089 1090 1091
  void SetUseCounterCallback(v8::Isolate::UseCounterCallback callback);
  void CountUsage(v8::Isolate::UseCounterFeature feature);

1092
 private:
1093
  Isolate();
1094

1095 1096 1097
  friend struct GlobalState;
  friend struct InitializeGlobalState;

1098 1099 1100 1101 1102 1103 1104 1105
  enum State {
    UNINITIALIZED,    // Some components may not have been allocated.
    INITIALIZED       // All components are fully initialized.
  };

  // These fields are accessed through the API, offsets must be kept in sync
  // with v8::internal::Internals (in include/v8.h) constants. This is also
  // verified in Isolate::Init() using runtime checks.
1106
  void* embedder_data_[Internals::kNumIsolateDataSlots];
1107
  Heap heap_;
1108
  State state_;  // Will be padded to kApiPointerSize.
1109

1110 1111 1112 1113 1114 1115 1116 1117 1118 1119
  // The per-process lock should be acquired before the ThreadDataTable is
  // modified.
  class ThreadDataTable {
   public:
    ThreadDataTable();
    ~ThreadDataTable();

    PerIsolateThreadData* Lookup(Isolate* isolate, ThreadId thread_id);
    void Insert(PerIsolateThreadData* data);
    void Remove(PerIsolateThreadData* data);
1120
    void RemoveAllThreads(Isolate* isolate);
1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146

   private:
    PerIsolateThreadData* list_;
  };

  // These items form a stack synchronously with threads Enter'ing and Exit'ing
  // the Isolate. The top of the stack points to a thread which is currently
  // running the Isolate. When the stack is empty, the Isolate is considered
  // not entered by any thread and can be Disposed.
  // If the same thread enters the Isolate more then once, the entry_count_
  // is incremented rather then a new item pushed to the stack.
  class EntryStackItem {
   public:
    EntryStackItem(PerIsolateThreadData* previous_thread_data,
                   Isolate* previous_isolate,
                   EntryStackItem* previous_item)
        : entry_count(1),
          previous_thread_data(previous_thread_data),
          previous_isolate(previous_isolate),
          previous_item(previous_item) { }

    int entry_count;
    PerIsolateThreadData* previous_thread_data;
    Isolate* previous_isolate;
    EntryStackItem* previous_item;

1147
   private:
1148 1149 1150
    DISALLOW_COPY_AND_ASSIGN(EntryStackItem);
  };

1151
  // This mutex protects highest_thread_id_ and thread_data_table_.
1152
  static base::Mutex process_wide_mutex_;
1153

1154 1155 1156
  static base::Thread::LocalStorageKey per_isolate_thread_data_key_;
  static base::Thread::LocalStorageKey isolate_key_;
  static base::Thread::LocalStorageKey thread_id_key_;
1157 1158
  static ThreadDataTable* thread_data_table_;

1159
  // A global counter for all generated Isolates, might overflow.
1160
  static base::Atomic32 isolate_counter_;
1161

1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190
  void Deinit();

  static void SetIsolateThreadLocals(Isolate* isolate,
                                     PerIsolateThreadData* data);

  // Find the PerThread for this particular (isolate, thread) combination.
  // If one does not yet exist, allocate a new one.
  PerIsolateThreadData* FindOrAllocatePerThreadDataForThisThread();

  // Initializes the current thread to run this Isolate.
  // Not thread-safe. Multiple threads should not Enter/Exit the same isolate
  // at the same time, this should be prevented using external locking.
  void Enter();

  // Exits the current thread. The previosuly entered Isolate is restored
  // for the thread.
  // Not thread-safe. Multiple threads should not Enter/Exit the same isolate
  // at the same time, this should be prevented using external locking.
  void Exit();

  void InitializeThreadLocal();

  void MarkCompactPrologue(bool is_compacting,
                           ThreadLocalTop* archived_thread_data);
  void MarkCompactEpilogue(bool is_compacting,
                           ThreadLocalTop* archived_thread_data);

  void FillCache();

1191 1192 1193 1194
  // Propagate pending exception message to the v8::TryCatch.
  // If there is no external try-catch or message was successfully propagated,
  // then return true.
  bool PropagatePendingExceptionToExternalTryCatch();
1195

1196 1197 1198 1199
  // Traverse prototype chain to find out whether the object is derived from
  // the Error object.
  bool IsErrorObject(Handle<Object> obj);

1200
  base::Atomic32 id_;
1201
  EntryStackItem* entry_stack_;
1202 1203
  int stack_trace_nesting_level_;
  StringStream* incomplete_message_;
1204
  Address isolate_addresses_[kIsolateAddressCount + 1];  // NOLINT
1205 1206 1207 1208 1209
  Bootstrapper* bootstrapper_;
  RuntimeProfiler* runtime_profiler_;
  CompilationCache* compilation_cache_;
  Counters* counters_;
  CodeRange* code_range_;
1210
  base::RecursiveMutex break_access_;
1211
  base::Atomic32 debugger_initialized_;
1212 1213 1214 1215
  Logger* logger_;
  StackGuard stack_guard_;
  StatsTable* stats_table_;
  StubCache* stub_cache_;
1216
  CodeAgingHelper* code_aging_helper_;
1217
  DeoptimizerData* deoptimizer_data_;
jarin@chromium.org's avatar
jarin@chromium.org committed
1218
  MaterializedObjectStore* materialized_object_store_;
1219 1220 1221 1222 1223 1224 1225 1226
  ThreadLocalTop thread_local_top_;
  bool capture_stack_trace_for_uncaught_exceptions_;
  int stack_trace_for_uncaught_exceptions_frame_limit_;
  StackTrace::StackTraceOptions stack_trace_for_uncaught_exceptions_options_;
  MemoryAllocator* memory_allocator_;
  KeyedLookupCache* keyed_lookup_cache_;
  ContextSlotCache* context_slot_cache_;
  DescriptorLookupCache* descriptor_lookup_cache_;
1227
  HandleScopeData handle_scope_data_;
1228
  HandleScopeImplementer* handle_scope_implementer_;
1229
  UnicodeCache* unicode_cache_;
1230
  Zone runtime_zone_;
1231
  InnerPointerToCodeCache* inner_pointer_to_code_cache_;
1232
  ConsStringIteratorOp* write_iterator_;
1233
  GlobalHandles* global_handles_;
1234
  EternalHandles* eternal_handles_;
1235 1236 1237
  ThreadManager* thread_manager_;
  RuntimeState runtime_state_;
  Builtins builtins_;
1238
  bool has_installed_extensions_;
1239 1240 1241
  StringTracker* string_tracker_;
  unibrow::Mapping<unibrow::Ecma262UnCanonicalize> jsregexp_uncanonicalize_;
  unibrow::Mapping<unibrow::CanonicalizationRange> jsregexp_canonrange_;
1242 1243 1244
  ConsStringIteratorOp objects_string_compare_iterator_a_;
  ConsStringIteratorOp objects_string_compare_iterator_b_;
  StaticResource<ConsStringIteratorOp> objects_string_iterator_;
1245 1246 1247
  unibrow::Mapping<unibrow::Ecma262Canonicalize>
      regexp_macro_assembler_canonicalize_;
  RegExpStack* regexp_stack_;
1248
  DateCache* date_cache_;
1249
  unibrow::Mapping<unibrow::Ecma262Canonicalize> interp_canonicalize_mapping_;
1250
  CodeStubInterfaceDescriptor* code_stub_interface_descriptors_;
1251
  CallInterfaceDescriptor* call_descriptors_;
1252
  base::RandomNumberGenerator* random_number_generator_;
1253

1254 1255 1256
  // Whether the isolate has been created for snapshotting.
  bool serializer_enabled_;

1257 1258 1259
  // True if fatal error has been signaled for this isolate.
  bool has_fatal_error_;

1260 1261 1262
  // True if this isolate was initialized from a snapshot.
  bool initialized_from_snapshot_;

1263 1264 1265
  // Time stamp at initialization.
  double time_millis_at_init_;

1266 1267 1268 1269 1270 1271 1272
#ifdef DEBUG
  // A static array of histogram info for each type.
  HistogramInfo heap_histograms_[LAST_TYPE + 1];
  JSObject::SpillInformation js_spill_information_;
#endif

  Debug* debug_;
1273
  CpuProfiler* cpu_profiler_;
1274
  HeapProfiler* heap_profiler_;
1275
  FunctionEntryHook function_entry_hook_;
1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297

#define GLOBAL_BACKING_STORE(type, name, initialvalue)                         \
  type name##_;
  ISOLATE_INIT_LIST(GLOBAL_BACKING_STORE)
#undef GLOBAL_BACKING_STORE

#define GLOBAL_ARRAY_BACKING_STORE(type, name, length)                         \
  type name##_[length];
  ISOLATE_INIT_ARRAY_LIST(GLOBAL_ARRAY_BACKING_STORE)
#undef GLOBAL_ARRAY_BACKING_STORE

#ifdef DEBUG
  // This class is huge and has a number of fields controlled by
  // preprocessor defines. Make sure the offsets of these fields agree
  // between compilation units.
#define ISOLATE_FIELD_OFFSET(type, name, ignored)                              \
  static const intptr_t name##_debug_offset_;
  ISOLATE_INIT_LIST(ISOLATE_FIELD_OFFSET)
  ISOLATE_INIT_ARRAY_LIST(ISOLATE_FIELD_OFFSET)
#undef ISOLATE_FIELD_OFFSET
#endif

1298
  DeferredHandles* deferred_handles_head_;
1299
  OptimizingCompilerThread* optimizing_compiler_thread_;
1300
  SweeperThread** sweeper_thread_;
1301 1302
  int num_sweeper_threads_;

1303 1304 1305
  // Counts deopt points if deopt_every_n_times is enabled.
  unsigned int stress_deopt_count_;

1306 1307
  int next_optimization_id_;

1308 1309 1310
  // List of callbacks when a Call completes.
  List<CallCompletedCallback> call_completed_callbacks_;

1311 1312
  v8::Isolate::UseCounterCallback use_counter_callback_;

1313
  friend class ExecutionAccess;
1314
  friend class HandleScopeImplementer;
1315
  friend class IsolateInitializer;
1316
  friend class OptimizingCompilerThread;
1317
  friend class SweeperThread;
1318 1319 1320
  friend class ThreadManager;
  friend class Simulator;
  friend class StackGuard;
1321
  friend class ThreadId;
1322
  friend class TestMemoryAllocatorScope;
1323
  friend class TestCodeRangeScope;
1324 1325
  friend class v8::Isolate;
  friend class v8::Locker;
1326
  friend class v8::Unlocker;
1327 1328 1329 1330 1331

  DISALLOW_COPY_AND_ASSIGN(Isolate);
};


1332 1333 1334 1335
#undef FIELD_ACCESSOR
#undef THREAD_LOCAL_TOP_ACCESSOR


1336 1337 1338 1339 1340
// If the GCC version is 4.1.x or 4.2.x an additional field is added to the
// class as a work around for a bug in the generated code found with these
// versions of GCC. See V8 issue 122 for details.
class SaveContext BASE_EMBEDDED {
 public:
1341
  inline explicit SaveContext(Isolate* isolate);
1342 1343

  ~SaveContext() {
1344 1345
    isolate_->set_context(context_.is_null() ? NULL : *context_);
    isolate_->set_save_context(prev_);
1346 1347 1348 1349 1350 1351
  }

  Handle<Context> context() { return context_; }
  SaveContext* prev() { return prev_; }

  // Returns true if this save context is below a given JavaScript frame.
1352 1353
  bool IsBelowFrame(JavaScriptFrame* frame) {
    return (c_entry_fp_ == 0) || (c_entry_fp_ > frame->sp());
1354 1355 1356
  }

 private:
1357
  Isolate* isolate_;
1358 1359
  Handle<Context> context_;
  SaveContext* prev_;
1360
  Address c_entry_fp_;
1361 1362 1363 1364 1365 1366
};


class AssertNoContextChange BASE_EMBEDDED {
#ifdef DEBUG
 public:
1367 1368 1369
  explicit AssertNoContextChange(Isolate* isolate)
    : isolate_(isolate),
      context_(isolate->context(), isolate) { }
1370
  ~AssertNoContextChange() {
1371
    ASSERT(isolate_->context() == *context_);
1372 1373 1374
  }

 private:
1375
  Isolate* isolate_;
1376 1377 1378
  Handle<Context> context_;
#else
 public:
1379
  explicit AssertNoContextChange(Isolate* isolate) { }
1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390
#endif
};


class ExecutionAccess BASE_EMBEDDED {
 public:
  explicit ExecutionAccess(Isolate* isolate) : isolate_(isolate) {
    Lock(isolate);
  }
  ~ExecutionAccess() { Unlock(isolate_); }

1391 1392
  static void Lock(Isolate* isolate) { isolate->break_access()->Lock(); }
  static void Unlock(Isolate* isolate) { isolate->break_access()->Unlock(); }
1393 1394

  static bool TryLock(Isolate* isolate) {
1395
    return isolate->break_access()->TryLock();
1396 1397 1398 1399 1400 1401 1402
  }

 private:
  Isolate* isolate_;
};


1403
// Support for checking for stack-overflows.
1404 1405 1406 1407
class StackLimitCheck BASE_EMBEDDED {
 public:
  explicit StackLimitCheck(Isolate* isolate) : isolate_(isolate) { }

1408 1409
  // Use this to check for stack-overflows in C++ code.
  inline bool HasOverflowed() const {
1410
    StackGuard* stack_guard = isolate_->stack_guard();
1411
    return reinterpret_cast<uintptr_t>(this) < stack_guard->real_climit();
1412
  }
1413 1414 1415 1416

  // Use this to check for stack-overflow when entering runtime from JS code.
  bool JsHasOverflowed() const;

1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427
 private:
  Isolate* isolate_;
};


// Support for temporarily postponing interrupts. When the outermost
// postpone scope is left the interrupts will be re-enabled and any
// interrupts that occurred while in the scope will be taken into
// account.
class PostponeInterruptsScope BASE_EMBEDDED {
 public:
1428 1429 1430 1431 1432
  explicit PostponeInterruptsScope(Isolate* isolate)
      : stack_guard_(isolate->stack_guard()), isolate_(isolate) {
    ExecutionAccess access(isolate_);
    stack_guard_->thread_local_.postpone_interrupts_nesting_++;
    stack_guard_->DisableInterrupts();
1433 1434 1435
  }

  ~PostponeInterruptsScope() {
1436 1437 1438 1439
    ExecutionAccess access(isolate_);
    if (--stack_guard_->thread_local_.postpone_interrupts_nesting_ == 0) {
      stack_guard_->EnableInterrupts();
    }
1440 1441 1442
  }
 private:
  StackGuard* stack_guard_;
1443
  Isolate* isolate_;
1444 1445 1446
};


1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457
class CodeTracer V8_FINAL : public Malloced {
 public:
  explicit CodeTracer(int isolate_id)
      : file_(NULL),
        scope_depth_(0) {
    if (!ShouldRedirect()) {
      file_ = stdout;
      return;
    }

    if (FLAG_redirect_code_traces_to == NULL) {
1458 1459
      SNPrintF(filename_,
               "code-%d-%d.asm",
1460
               base::OS::GetCurrentProcessId(),
1461
               isolate_id);
1462
    } else {
1463
      StrNCpy(filename_, FLAG_redirect_code_traces_to, filename_.length());
1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485
    }

    WriteChars(filename_.start(), "", 0, false);
  }

  class Scope {
   public:
    explicit Scope(CodeTracer* tracer) : tracer_(tracer) { tracer->OpenFile(); }
    ~Scope() { tracer_->CloseFile();  }

    FILE* file() const { return tracer_->file(); }

   private:
    CodeTracer* tracer_;
  };

  void OpenFile() {
    if (!ShouldRedirect()) {
      return;
    }

    if (file_ == NULL) {
1486
      file_ = base::OS::FOpen(filename_.start(), "a");
1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513
    }

    scope_depth_++;
  }

  void CloseFile() {
    if (!ShouldRedirect()) {
      return;
    }

    if (--scope_depth_ == 0) {
      fclose(file_);
      file_ = NULL;
    }
  }

  FILE* file() const { return file_; }

 private:
  static bool ShouldRedirect() {
    return FLAG_redirect_code_traces;
  }

  EmbeddedVector<char, 128> filename_;
  FILE* file_;
  int scope_depth_;
};
1514 1515 1516 1517

} }  // namespace v8::internal

#endif  // V8_ISOLATE_H_