Home | History | Annotate | Download | only in src
      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_API_H_
      6 #define V8_API_H_
      7 
      8 #include "include/v8-testing.h"
      9 #include "src/contexts.h"
     10 #include "src/debug/debug-interface.h"
     11 #include "src/factory.h"
     12 #include "src/isolate.h"
     13 #include "src/list.h"
     14 
     15 namespace v8 {
     16 
     17 // Constants used in the implementation of the API.  The most natural thing
     18 // would usually be to place these with the classes that use them, but
     19 // we want to keep them out of v8.h because it is an externally
     20 // visible file.
     21 class Consts {
     22  public:
     23   enum TemplateType {
     24     FUNCTION_TEMPLATE = 0,
     25     OBJECT_TEMPLATE = 1
     26   };
     27 };
     28 
     29 template <typename T> inline T ToCData(v8::internal::Object* obj) {
     30   STATIC_ASSERT(sizeof(T) == sizeof(v8::internal::Address));
     31   if (obj == v8::internal::Smi::kZero) return nullptr;
     32   return reinterpret_cast<T>(
     33       reinterpret_cast<intptr_t>(
     34           v8::internal::Foreign::cast(obj)->foreign_address()));
     35 }
     36 
     37 
     38 template <typename T>
     39 inline v8::internal::Handle<v8::internal::Object> FromCData(
     40     v8::internal::Isolate* isolate, T obj) {
     41   STATIC_ASSERT(sizeof(T) == sizeof(v8::internal::Address));
     42   if (obj == nullptr) return handle(v8::internal::Smi::kZero, isolate);
     43   return isolate->factory()->NewForeign(
     44       reinterpret_cast<v8::internal::Address>(reinterpret_cast<intptr_t>(obj)));
     45 }
     46 
     47 
     48 class ApiFunction {
     49  public:
     50   explicit ApiFunction(v8::internal::Address addr) : addr_(addr) { }
     51   v8::internal::Address address() { return addr_; }
     52  private:
     53   v8::internal::Address addr_;
     54 };
     55 
     56 
     57 
     58 class RegisteredExtension {
     59  public:
     60   explicit RegisteredExtension(Extension* extension);
     61   static void Register(RegisteredExtension* that);
     62   static void UnregisterAll();
     63   Extension* extension() { return extension_; }
     64   RegisteredExtension* next() { return next_; }
     65   static RegisteredExtension* first_extension() { return first_extension_; }
     66  private:
     67   Extension* extension_;
     68   RegisteredExtension* next_;
     69   static RegisteredExtension* first_extension_;
     70 };
     71 
     72 #define OPEN_HANDLE_LIST(V)                    \
     73   V(Template, TemplateInfo)                    \
     74   V(FunctionTemplate, FunctionTemplateInfo)    \
     75   V(ObjectTemplate, ObjectTemplateInfo)        \
     76   V(Signature, FunctionTemplateInfo)           \
     77   V(AccessorSignature, FunctionTemplateInfo)   \
     78   V(Data, Object)                              \
     79   V(RegExp, JSRegExp)                          \
     80   V(Object, JSReceiver)                        \
     81   V(Array, JSArray)                            \
     82   V(Map, JSMap)                                \
     83   V(Set, JSSet)                                \
     84   V(ArrayBuffer, JSArrayBuffer)                \
     85   V(ArrayBufferView, JSArrayBufferView)        \
     86   V(TypedArray, JSTypedArray)                  \
     87   V(Uint8Array, JSTypedArray)                  \
     88   V(Uint8ClampedArray, JSTypedArray)           \
     89   V(Int8Array, JSTypedArray)                   \
     90   V(Uint16Array, JSTypedArray)                 \
     91   V(Int16Array, JSTypedArray)                  \
     92   V(Uint32Array, JSTypedArray)                 \
     93   V(Int32Array, JSTypedArray)                  \
     94   V(Float32Array, JSTypedArray)                \
     95   V(Float64Array, JSTypedArray)                \
     96   V(DataView, JSDataView)                      \
     97   V(SharedArrayBuffer, JSArrayBuffer)          \
     98   V(Name, Name)                                \
     99   V(String, String)                            \
    100   V(Symbol, Symbol)                            \
    101   V(Script, JSFunction)                        \
    102   V(UnboundScript, SharedFunctionInfo)         \
    103   V(Module, Module)                            \
    104   V(Function, JSReceiver)                      \
    105   V(Message, JSMessageObject)                  \
    106   V(Context, Context)                          \
    107   V(External, Object)                          \
    108   V(StackTrace, JSArray)                       \
    109   V(StackFrame, JSObject)                      \
    110   V(Proxy, JSProxy)                            \
    111   V(NativeWeakMap, JSWeakMap)                  \
    112   V(debug::GeneratorObject, JSGeneratorObject) \
    113   V(debug::Script, Script)                     \
    114   V(Promise, JSPromise)
    115 
    116 class Utils {
    117  public:
    118   static inline bool ApiCheck(bool condition,
    119                               const char* location,
    120                               const char* message) {
    121     if (!condition) Utils::ReportApiFailure(location, message);
    122     return condition;
    123   }
    124   static void ReportOOMFailure(const char* location, bool is_heap_oom);
    125 
    126   static inline Local<Context> ToLocal(
    127       v8::internal::Handle<v8::internal::Context> obj);
    128   static inline Local<Value> ToLocal(
    129       v8::internal::Handle<v8::internal::Object> obj);
    130   static inline Local<Module> ToLocal(
    131       v8::internal::Handle<v8::internal::Module> obj);
    132   static inline Local<Name> ToLocal(
    133       v8::internal::Handle<v8::internal::Name> obj);
    134   static inline Local<String> ToLocal(
    135       v8::internal::Handle<v8::internal::String> obj);
    136   static inline Local<Symbol> ToLocal(
    137       v8::internal::Handle<v8::internal::Symbol> obj);
    138   static inline Local<RegExp> ToLocal(
    139       v8::internal::Handle<v8::internal::JSRegExp> obj);
    140   static inline Local<Object> ToLocal(
    141       v8::internal::Handle<v8::internal::JSReceiver> obj);
    142   static inline Local<Object> ToLocal(
    143       v8::internal::Handle<v8::internal::JSObject> obj);
    144   static inline Local<Function> ToLocal(
    145       v8::internal::Handle<v8::internal::JSFunction> obj);
    146   static inline Local<Array> ToLocal(
    147       v8::internal::Handle<v8::internal::JSArray> obj);
    148   static inline Local<Map> ToLocal(
    149       v8::internal::Handle<v8::internal::JSMap> obj);
    150   static inline Local<Set> ToLocal(
    151       v8::internal::Handle<v8::internal::JSSet> obj);
    152   static inline Local<Proxy> ToLocal(
    153       v8::internal::Handle<v8::internal::JSProxy> obj);
    154   static inline Local<ArrayBuffer> ToLocal(
    155       v8::internal::Handle<v8::internal::JSArrayBuffer> obj);
    156   static inline Local<ArrayBufferView> ToLocal(
    157       v8::internal::Handle<v8::internal::JSArrayBufferView> obj);
    158   static inline Local<DataView> ToLocal(
    159       v8::internal::Handle<v8::internal::JSDataView> obj);
    160   static inline Local<TypedArray> ToLocal(
    161       v8::internal::Handle<v8::internal::JSTypedArray> obj);
    162   static inline Local<Uint8Array> ToLocalUint8Array(
    163       v8::internal::Handle<v8::internal::JSTypedArray> obj);
    164   static inline Local<Uint8ClampedArray> ToLocalUint8ClampedArray(
    165       v8::internal::Handle<v8::internal::JSTypedArray> obj);
    166   static inline Local<Int8Array> ToLocalInt8Array(
    167       v8::internal::Handle<v8::internal::JSTypedArray> obj);
    168   static inline Local<Uint16Array> ToLocalUint16Array(
    169       v8::internal::Handle<v8::internal::JSTypedArray> obj);
    170   static inline Local<Int16Array> ToLocalInt16Array(
    171       v8::internal::Handle<v8::internal::JSTypedArray> obj);
    172   static inline Local<Uint32Array> ToLocalUint32Array(
    173       v8::internal::Handle<v8::internal::JSTypedArray> obj);
    174   static inline Local<Int32Array> ToLocalInt32Array(
    175       v8::internal::Handle<v8::internal::JSTypedArray> obj);
    176   static inline Local<Float32Array> ToLocalFloat32Array(
    177       v8::internal::Handle<v8::internal::JSTypedArray> obj);
    178   static inline Local<Float64Array> ToLocalFloat64Array(
    179       v8::internal::Handle<v8::internal::JSTypedArray> obj);
    180 
    181   static inline Local<SharedArrayBuffer> ToLocalShared(
    182       v8::internal::Handle<v8::internal::JSArrayBuffer> obj);
    183 
    184   static inline Local<Message> MessageToLocal(
    185       v8::internal::Handle<v8::internal::Object> obj);
    186   static inline Local<Promise> PromiseToLocal(
    187       v8::internal::Handle<v8::internal::JSObject> obj);
    188   static inline Local<StackTrace> StackTraceToLocal(
    189       v8::internal::Handle<v8::internal::JSArray> obj);
    190   static inline Local<StackFrame> StackFrameToLocal(
    191       v8::internal::Handle<v8::internal::JSObject> obj);
    192   static inline Local<Number> NumberToLocal(
    193       v8::internal::Handle<v8::internal::Object> obj);
    194   static inline Local<Integer> IntegerToLocal(
    195       v8::internal::Handle<v8::internal::Object> obj);
    196   static inline Local<Uint32> Uint32ToLocal(
    197       v8::internal::Handle<v8::internal::Object> obj);
    198   static inline Local<FunctionTemplate> ToLocal(
    199       v8::internal::Handle<v8::internal::FunctionTemplateInfo> obj);
    200   static inline Local<ObjectTemplate> ToLocal(
    201       v8::internal::Handle<v8::internal::ObjectTemplateInfo> obj);
    202   static inline Local<Signature> SignatureToLocal(
    203       v8::internal::Handle<v8::internal::FunctionTemplateInfo> obj);
    204   static inline Local<AccessorSignature> AccessorSignatureToLocal(
    205       v8::internal::Handle<v8::internal::FunctionTemplateInfo> obj);
    206   static inline Local<External> ExternalToLocal(
    207       v8::internal::Handle<v8::internal::JSObject> obj);
    208   static inline Local<NativeWeakMap> NativeWeakMapToLocal(
    209       v8::internal::Handle<v8::internal::JSWeakMap> obj);
    210   static inline Local<Function> CallableToLocal(
    211       v8::internal::Handle<v8::internal::JSReceiver> obj);
    212 
    213 #define DECLARE_OPEN_HANDLE(From, To) \
    214   static inline v8::internal::Handle<v8::internal::To> \
    215       OpenHandle(const From* that, bool allow_empty_handle = false);
    216 
    217 OPEN_HANDLE_LIST(DECLARE_OPEN_HANDLE)
    218 
    219 #undef DECLARE_OPEN_HANDLE
    220 
    221   template<class From, class To>
    222   static inline Local<To> Convert(v8::internal::Handle<From> obj) {
    223     DCHECK(obj.is_null() ||
    224            (obj->IsSmi() ||
    225             !obj->IsTheHole(i::HeapObject::cast(*obj)->GetIsolate())));
    226     return Local<To>(reinterpret_cast<To*>(obj.location()));
    227   }
    228 
    229   template <class T>
    230   static inline v8::internal::Handle<v8::internal::Object> OpenPersistent(
    231       const v8::Persistent<T>& persistent) {
    232     return v8::internal::Handle<v8::internal::Object>(
    233         reinterpret_cast<v8::internal::Object**>(persistent.val_));
    234   }
    235 
    236   template <class T>
    237   static inline v8::internal::Handle<v8::internal::Object> OpenPersistent(
    238       v8::Persistent<T>* persistent) {
    239     return OpenPersistent(*persistent);
    240   }
    241 
    242   template <class From, class To>
    243   static inline v8::internal::Handle<To> OpenHandle(v8::Local<From> handle) {
    244     return OpenHandle(*handle);
    245   }
    246 
    247  private:
    248   static void ReportApiFailure(const char* location, const char* message);
    249 };
    250 
    251 
    252 template <class T>
    253 inline T* ToApi(v8::internal::Handle<v8::internal::Object> obj) {
    254   return reinterpret_cast<T*>(obj.location());
    255 }
    256 
    257 template <class T>
    258 inline v8::Local<T> ToApiHandle(
    259     v8::internal::Handle<v8::internal::Object> obj) {
    260   return Utils::Convert<v8::internal::Object, T>(obj);
    261 }
    262 
    263 
    264 template <class T>
    265 inline bool ToLocal(v8::internal::MaybeHandle<v8::internal::Object> maybe,
    266                     Local<T>* local) {
    267   v8::internal::Handle<v8::internal::Object> handle;
    268   if (maybe.ToHandle(&handle)) {
    269     *local = Utils::Convert<v8::internal::Object, T>(handle);
    270     return true;
    271   }
    272   return false;
    273 }
    274 
    275 
    276 // Implementations of ToLocal
    277 
    278 #define MAKE_TO_LOCAL(Name, From, To)                                       \
    279   Local<v8::To> Utils::Name(v8::internal::Handle<v8::internal::From> obj) { \
    280     return Convert<v8::internal::From, v8::To>(obj);  \
    281   }
    282 
    283 
    284 #define MAKE_TO_LOCAL_TYPED_ARRAY(Type, typeName, TYPE, ctype, size)  \
    285   Local<v8::Type##Array> Utils::ToLocal##Type##Array(                 \
    286       v8::internal::Handle<v8::internal::JSTypedArray> obj) {         \
    287     DCHECK(obj->type() == v8::internal::kExternal##Type##Array);      \
    288     return Convert<v8::internal::JSTypedArray, v8::Type##Array>(obj); \
    289   }
    290 
    291 
    292 MAKE_TO_LOCAL(ToLocal, Context, Context)
    293 MAKE_TO_LOCAL(ToLocal, Object, Value)
    294 MAKE_TO_LOCAL(ToLocal, Module, Module)
    295 MAKE_TO_LOCAL(ToLocal, Name, Name)
    296 MAKE_TO_LOCAL(ToLocal, String, String)
    297 MAKE_TO_LOCAL(ToLocal, Symbol, Symbol)
    298 MAKE_TO_LOCAL(ToLocal, JSRegExp, RegExp)
    299 MAKE_TO_LOCAL(ToLocal, JSReceiver, Object)
    300 MAKE_TO_LOCAL(ToLocal, JSObject, Object)
    301 MAKE_TO_LOCAL(ToLocal, JSFunction, Function)
    302 MAKE_TO_LOCAL(ToLocal, JSArray, Array)
    303 MAKE_TO_LOCAL(ToLocal, JSMap, Map)
    304 MAKE_TO_LOCAL(ToLocal, JSSet, Set)
    305 MAKE_TO_LOCAL(ToLocal, JSProxy, Proxy)
    306 MAKE_TO_LOCAL(ToLocal, JSArrayBuffer, ArrayBuffer)
    307 MAKE_TO_LOCAL(ToLocal, JSArrayBufferView, ArrayBufferView)
    308 MAKE_TO_LOCAL(ToLocal, JSDataView, DataView)
    309 MAKE_TO_LOCAL(ToLocal, JSTypedArray, TypedArray)
    310 MAKE_TO_LOCAL(ToLocalShared, JSArrayBuffer, SharedArrayBuffer)
    311 
    312 TYPED_ARRAYS(MAKE_TO_LOCAL_TYPED_ARRAY)
    313 
    314 MAKE_TO_LOCAL(ToLocal, FunctionTemplateInfo, FunctionTemplate)
    315 MAKE_TO_LOCAL(ToLocal, ObjectTemplateInfo, ObjectTemplate)
    316 MAKE_TO_LOCAL(SignatureToLocal, FunctionTemplateInfo, Signature)
    317 MAKE_TO_LOCAL(AccessorSignatureToLocal, FunctionTemplateInfo, AccessorSignature)
    318 MAKE_TO_LOCAL(MessageToLocal, Object, Message)
    319 MAKE_TO_LOCAL(PromiseToLocal, JSObject, Promise)
    320 MAKE_TO_LOCAL(StackTraceToLocal, JSArray, StackTrace)
    321 MAKE_TO_LOCAL(StackFrameToLocal, JSObject, StackFrame)
    322 MAKE_TO_LOCAL(NumberToLocal, Object, Number)
    323 MAKE_TO_LOCAL(IntegerToLocal, Object, Integer)
    324 MAKE_TO_LOCAL(Uint32ToLocal, Object, Uint32)
    325 MAKE_TO_LOCAL(ExternalToLocal, JSObject, External)
    326 MAKE_TO_LOCAL(NativeWeakMapToLocal, JSWeakMap, NativeWeakMap)
    327 MAKE_TO_LOCAL(CallableToLocal, JSReceiver, Function)
    328 
    329 #undef MAKE_TO_LOCAL_TYPED_ARRAY
    330 #undef MAKE_TO_LOCAL
    331 
    332 
    333 // Implementations of OpenHandle
    334 
    335 #define MAKE_OPEN_HANDLE(From, To)                                             \
    336   v8::internal::Handle<v8::internal::To> Utils::OpenHandle(                    \
    337       const v8::From* that, bool allow_empty_handle) {                         \
    338     DCHECK(allow_empty_handle || that != NULL);                                \
    339     DCHECK(that == NULL ||                                                     \
    340            (*reinterpret_cast<v8::internal::Object* const*>(that))->Is##To()); \
    341     return v8::internal::Handle<v8::internal::To>(                             \
    342         reinterpret_cast<v8::internal::To**>(const_cast<v8::From*>(that)));    \
    343   }
    344 
    345 OPEN_HANDLE_LIST(MAKE_OPEN_HANDLE)
    346 
    347 #undef MAKE_OPEN_HANDLE
    348 #undef OPEN_HANDLE_LIST
    349 
    350 
    351 namespace internal {
    352 
    353 class V8_EXPORT_PRIVATE DeferredHandles {
    354  public:
    355   ~DeferredHandles();
    356 
    357  private:
    358   DeferredHandles(Object** first_block_limit, Isolate* isolate)
    359       : next_(NULL),
    360         previous_(NULL),
    361         first_block_limit_(first_block_limit),
    362         isolate_(isolate) {
    363     isolate->LinkDeferredHandles(this);
    364   }
    365 
    366   void Iterate(ObjectVisitor* v);
    367 
    368   List<Object**> blocks_;
    369   DeferredHandles* next_;
    370   DeferredHandles* previous_;
    371   Object** first_block_limit_;
    372   Isolate* isolate_;
    373 
    374   friend class HandleScopeImplementer;
    375   friend class Isolate;
    376 };
    377 
    378 
    379 // This class is here in order to be able to declare it a friend of
    380 // HandleScope.  Moving these methods to be members of HandleScope would be
    381 // neat in some ways, but it would expose internal implementation details in
    382 // our public header file, which is undesirable.
    383 //
    384 // An isolate has a single instance of this class to hold the current thread's
    385 // data. In multithreaded V8 programs this data is copied in and out of storage
    386 // so that the currently executing thread always has its own copy of this
    387 // data.
    388 class HandleScopeImplementer {
    389  public:
    390   explicit HandleScopeImplementer(Isolate* isolate)
    391       : isolate_(isolate),
    392         blocks_(0),
    393         entered_contexts_(0),
    394         saved_contexts_(0),
    395         microtask_context_(nullptr),
    396         spare_(NULL),
    397         call_depth_(0),
    398         microtasks_depth_(0),
    399         microtasks_suppressions_(0),
    400         entered_context_count_during_microtasks_(0),
    401 #ifdef DEBUG
    402         debug_microtasks_depth_(0),
    403 #endif
    404         microtasks_policy_(v8::MicrotasksPolicy::kAuto),
    405         last_handle_before_deferred_block_(NULL) { }
    406 
    407   ~HandleScopeImplementer() {
    408     DeleteArray(spare_);
    409   }
    410 
    411   // Threading support for handle data.
    412   static int ArchiveSpacePerThread();
    413   char* RestoreThread(char* from);
    414   char* ArchiveThread(char* to);
    415   void FreeThreadResources();
    416 
    417   // Garbage collection support.
    418   void Iterate(v8::internal::ObjectVisitor* v);
    419   static char* Iterate(v8::internal::ObjectVisitor* v, char* data);
    420 
    421 
    422   inline internal::Object** GetSpareOrNewBlock();
    423   inline void DeleteExtensions(internal::Object** prev_limit);
    424 
    425   // Call depth represents nested v8 api calls.
    426   inline void IncrementCallDepth() {call_depth_++;}
    427   inline void DecrementCallDepth() {call_depth_--;}
    428   inline bool CallDepthIsZero() { return call_depth_ == 0; }
    429 
    430   // Microtasks scope depth represents nested scopes controlling microtasks
    431   // invocation, which happens when depth reaches zero.
    432   inline void IncrementMicrotasksScopeDepth() {microtasks_depth_++;}
    433   inline void DecrementMicrotasksScopeDepth() {microtasks_depth_--;}
    434   inline int GetMicrotasksScopeDepth() { return microtasks_depth_; }
    435 
    436   // Possibly nested microtasks suppression scopes prevent microtasks
    437   // from running.
    438   inline void IncrementMicrotasksSuppressions() {microtasks_suppressions_++;}
    439   inline void DecrementMicrotasksSuppressions() {microtasks_suppressions_--;}
    440   inline bool HasMicrotasksSuppressions() { return !!microtasks_suppressions_; }
    441 
    442 #ifdef DEBUG
    443   // In debug we check that calls not intended to invoke microtasks are
    444   // still correctly wrapped with microtask scopes.
    445   inline void IncrementDebugMicrotasksScopeDepth() {debug_microtasks_depth_++;}
    446   inline void DecrementDebugMicrotasksScopeDepth() {debug_microtasks_depth_--;}
    447   inline bool DebugMicrotasksScopeDepthIsZero() {
    448     return debug_microtasks_depth_ == 0;
    449   }
    450 #endif
    451 
    452   inline void set_microtasks_policy(v8::MicrotasksPolicy policy);
    453   inline v8::MicrotasksPolicy microtasks_policy() const;
    454 
    455   inline void EnterContext(Handle<Context> context);
    456   inline void LeaveContext();
    457   inline bool LastEnteredContextWas(Handle<Context> context);
    458 
    459   // Returns the last entered context or an empty handle if no
    460   // contexts have been entered.
    461   inline Handle<Context> LastEnteredContext();
    462 
    463   inline void EnterMicrotaskContext(Handle<Context> context);
    464   inline void LeaveMicrotaskContext();
    465   inline Handle<Context> MicrotaskContext();
    466   inline bool MicrotaskContextIsLastEnteredContext() const {
    467     return microtask_context_ &&
    468            entered_context_count_during_microtasks_ ==
    469                entered_contexts_.length();
    470   }
    471 
    472   inline void SaveContext(Context* context);
    473   inline Context* RestoreContext();
    474   inline bool HasSavedContexts();
    475 
    476   inline List<internal::Object**>* blocks() { return &blocks_; }
    477   Isolate* isolate() const { return isolate_; }
    478 
    479   void ReturnBlock(Object** block) {
    480     DCHECK(block != NULL);
    481     if (spare_ != NULL) DeleteArray(spare_);
    482     spare_ = block;
    483   }
    484 
    485  private:
    486   void ResetAfterArchive() {
    487     blocks_.Initialize(0);
    488     entered_contexts_.Initialize(0);
    489     saved_contexts_.Initialize(0);
    490     microtask_context_ = nullptr;
    491     entered_context_count_during_microtasks_ = 0;
    492     spare_ = NULL;
    493     last_handle_before_deferred_block_ = NULL;
    494     call_depth_ = 0;
    495   }
    496 
    497   void Free() {
    498     DCHECK(blocks_.length() == 0);
    499     DCHECK(entered_contexts_.length() == 0);
    500     DCHECK(saved_contexts_.length() == 0);
    501     DCHECK(!microtask_context_);
    502     blocks_.Free();
    503     entered_contexts_.Free();
    504     saved_contexts_.Free();
    505     if (spare_ != NULL) {
    506       DeleteArray(spare_);
    507       spare_ = NULL;
    508     }
    509     DCHECK(call_depth_ == 0);
    510   }
    511 
    512   void BeginDeferredScope();
    513   DeferredHandles* Detach(Object** prev_limit);
    514 
    515   Isolate* isolate_;
    516   List<internal::Object**> blocks_;
    517   // Used as a stack to keep track of entered contexts.
    518   List<Context*> entered_contexts_;
    519   // Used as a stack to keep track of saved contexts.
    520   List<Context*> saved_contexts_;
    521   Context* microtask_context_;
    522   Object** spare_;
    523   int call_depth_;
    524   int microtasks_depth_;
    525   int microtasks_suppressions_;
    526   int entered_context_count_during_microtasks_;
    527 #ifdef DEBUG
    528   int debug_microtasks_depth_;
    529 #endif
    530   v8::MicrotasksPolicy microtasks_policy_;
    531   Object** last_handle_before_deferred_block_;
    532   // This is only used for threading support.
    533   HandleScopeData handle_scope_data_;
    534 
    535   void IterateThis(ObjectVisitor* v);
    536   char* RestoreThreadHelper(char* from);
    537   char* ArchiveThreadHelper(char* to);
    538 
    539   friend class DeferredHandles;
    540   friend class DeferredHandleScope;
    541 
    542   DISALLOW_COPY_AND_ASSIGN(HandleScopeImplementer);
    543 };
    544 
    545 
    546 const int kHandleBlockSize = v8::internal::KB - 2;  // fit in one page
    547 
    548 
    549 void HandleScopeImplementer::set_microtasks_policy(
    550     v8::MicrotasksPolicy policy) {
    551   microtasks_policy_ = policy;
    552 }
    553 
    554 
    555 v8::MicrotasksPolicy HandleScopeImplementer::microtasks_policy() const {
    556   return microtasks_policy_;
    557 }
    558 
    559 
    560 void HandleScopeImplementer::SaveContext(Context* context) {
    561   saved_contexts_.Add(context);
    562 }
    563 
    564 
    565 Context* HandleScopeImplementer::RestoreContext() {
    566   return saved_contexts_.RemoveLast();
    567 }
    568 
    569 
    570 bool HandleScopeImplementer::HasSavedContexts() {
    571   return !saved_contexts_.is_empty();
    572 }
    573 
    574 
    575 void HandleScopeImplementer::EnterContext(Handle<Context> context) {
    576   entered_contexts_.Add(*context);
    577 }
    578 
    579 
    580 void HandleScopeImplementer::LeaveContext() {
    581   entered_contexts_.RemoveLast();
    582 }
    583 
    584 
    585 bool HandleScopeImplementer::LastEnteredContextWas(Handle<Context> context) {
    586   return !entered_contexts_.is_empty() && entered_contexts_.last() == *context;
    587 }
    588 
    589 
    590 Handle<Context> HandleScopeImplementer::LastEnteredContext() {
    591   if (entered_contexts_.is_empty()) return Handle<Context>::null();
    592   return Handle<Context>(entered_contexts_.last());
    593 }
    594 
    595 void HandleScopeImplementer::EnterMicrotaskContext(Handle<Context> context) {
    596   DCHECK(!microtask_context_);
    597   microtask_context_ = *context;
    598   entered_context_count_during_microtasks_ = entered_contexts_.length();
    599 }
    600 
    601 void HandleScopeImplementer::LeaveMicrotaskContext() {
    602   DCHECK(microtask_context_);
    603   microtask_context_ = nullptr;
    604   entered_context_count_during_microtasks_ = 0;
    605 }
    606 
    607 Handle<Context> HandleScopeImplementer::MicrotaskContext() {
    608   if (microtask_context_) return Handle<Context>(microtask_context_);
    609   return Handle<Context>::null();
    610 }
    611 
    612 // If there's a spare block, use it for growing the current scope.
    613 internal::Object** HandleScopeImplementer::GetSpareOrNewBlock() {
    614   internal::Object** block = (spare_ != NULL) ?
    615       spare_ :
    616       NewArray<internal::Object*>(kHandleBlockSize);
    617   spare_ = NULL;
    618   return block;
    619 }
    620 
    621 
    622 void HandleScopeImplementer::DeleteExtensions(internal::Object** prev_limit) {
    623   while (!blocks_.is_empty()) {
    624     internal::Object** block_start = blocks_.last();
    625     internal::Object** block_limit = block_start + kHandleBlockSize;
    626 
    627     // SealHandleScope may make the prev_limit to point inside the block.
    628     if (block_start <= prev_limit && prev_limit <= block_limit) {
    629 #ifdef ENABLE_HANDLE_ZAPPING
    630       internal::HandleScope::ZapRange(prev_limit, block_limit);
    631 #endif
    632       break;
    633     }
    634 
    635     blocks_.RemoveLast();
    636 #ifdef ENABLE_HANDLE_ZAPPING
    637     internal::HandleScope::ZapRange(block_start, block_limit);
    638 #endif
    639     if (spare_ != NULL) {
    640       DeleteArray(spare_);
    641     }
    642     spare_ = block_start;
    643   }
    644   DCHECK((blocks_.is_empty() && prev_limit == NULL) ||
    645          (!blocks_.is_empty() && prev_limit != NULL));
    646 }
    647 
    648 
    649 // Interceptor functions called from generated inline caches to notify
    650 // CPU profiler that external callbacks are invoked.
    651 void InvokeAccessorGetterCallback(
    652     v8::Local<v8::Name> property,
    653     const v8::PropertyCallbackInfo<v8::Value>& info,
    654     v8::AccessorNameGetterCallback getter);
    655 
    656 void InvokeFunctionCallback(const v8::FunctionCallbackInfo<v8::Value>& info,
    657                             v8::FunctionCallback callback);
    658 
    659 class Testing {
    660  public:
    661   static v8::Testing::StressType stress_type() { return stress_type_; }
    662   static void set_stress_type(v8::Testing::StressType stress_type) {
    663     stress_type_ = stress_type;
    664   }
    665 
    666  private:
    667   static v8::Testing::StressType stress_type_;
    668 };
    669 
    670 }  // namespace internal
    671 }  // namespace v8
    672 
    673 #endif  // V8_API_H_
    674