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 #include "src/objects-inl.h"
     15 
     16 namespace v8 {
     17 
     18 // Constants used in the implementation of the API.  The most natural thing
     19 // would usually be to place these with the classes that use them, but
     20 // we want to keep them out of v8.h because it is an externally
     21 // visible file.
     22 class Consts {
     23  public:
     24   enum TemplateType {
     25     FUNCTION_TEMPLATE = 0,
     26     OBJECT_TEMPLATE = 1
     27   };
     28 };
     29 
     30 template <typename T> inline T ToCData(v8::internal::Object* obj) {
     31   STATIC_ASSERT(sizeof(T) == sizeof(v8::internal::Address));
     32   if (obj == v8::internal::Smi::kZero) return nullptr;
     33   return reinterpret_cast<T>(
     34       reinterpret_cast<intptr_t>(
     35           v8::internal::Foreign::cast(obj)->foreign_address()));
     36 }
     37 
     38 
     39 template <typename T>
     40 inline v8::internal::Handle<v8::internal::Object> FromCData(
     41     v8::internal::Isolate* isolate, T obj) {
     42   STATIC_ASSERT(sizeof(T) == sizeof(v8::internal::Address));
     43   if (obj == nullptr) return handle(v8::internal::Smi::kZero, isolate);
     44   return isolate->factory()->NewForeign(
     45       reinterpret_cast<v8::internal::Address>(reinterpret_cast<intptr_t>(obj)));
     46 }
     47 
     48 
     49 class ApiFunction {
     50  public:
     51   explicit ApiFunction(v8::internal::Address addr) : addr_(addr) { }
     52   v8::internal::Address address() { return addr_; }
     53  private:
     54   v8::internal::Address addr_;
     55 };
     56 
     57 
     58 
     59 class RegisteredExtension {
     60  public:
     61   explicit RegisteredExtension(Extension* extension);
     62   static void Register(RegisteredExtension* that);
     63   static void UnregisterAll();
     64   Extension* extension() { return extension_; }
     65   RegisteredExtension* next() { return next_; }
     66   static RegisteredExtension* first_extension() { return first_extension_; }
     67  private:
     68   Extension* extension_;
     69   RegisteredExtension* next_;
     70   static RegisteredExtension* first_extension_;
     71 };
     72 
     73 #define OPEN_HANDLE_LIST(V)                  \
     74   V(Template, TemplateInfo)                  \
     75   V(FunctionTemplate, FunctionTemplateInfo)  \
     76   V(ObjectTemplate, ObjectTemplateInfo)      \
     77   V(Signature, FunctionTemplateInfo)         \
     78   V(AccessorSignature, FunctionTemplateInfo) \
     79   V(Data, Object)                            \
     80   V(RegExp, JSRegExp)                        \
     81   V(Object, JSReceiver)                      \
     82   V(Array, JSArray)                          \
     83   V(Map, JSMap)                              \
     84   V(Set, JSSet)                              \
     85   V(ArrayBuffer, JSArrayBuffer)              \
     86   V(ArrayBufferView, JSArrayBufferView)      \
     87   V(TypedArray, JSTypedArray)                \
     88   V(Uint8Array, JSTypedArray)                \
     89   V(Uint8ClampedArray, JSTypedArray)         \
     90   V(Int8Array, JSTypedArray)                 \
     91   V(Uint16Array, JSTypedArray)               \
     92   V(Int16Array, JSTypedArray)                \
     93   V(Uint32Array, JSTypedArray)               \
     94   V(Int32Array, JSTypedArray)                \
     95   V(Float32Array, JSTypedArray)              \
     96   V(Float64Array, JSTypedArray)              \
     97   V(DataView, JSDataView)                    \
     98   V(SharedArrayBuffer, JSArrayBuffer)        \
     99   V(Name, Name)                              \
    100   V(String, String)                          \
    101   V(Symbol, Symbol)                          \
    102   V(Script, JSFunction)                      \
    103   V(UnboundScript, SharedFunctionInfo)       \
    104   V(Module, Module)                          \
    105   V(Function, JSReceiver)                    \
    106   V(Message, JSMessageObject)                \
    107   V(Context, Context)                        \
    108   V(External, Object)                        \
    109   V(StackTrace, JSArray)                     \
    110   V(StackFrame, JSObject)                    \
    111   V(Proxy, JSProxy)                          \
    112   V(NativeWeakMap, JSWeakMap)                \
    113   V(DebugInterface::Script, Script)
    114 
    115 class Utils {
    116  public:
    117   static inline bool ApiCheck(bool condition,
    118                               const char* location,
    119                               const char* message) {
    120     if (!condition) Utils::ReportApiFailure(location, message);
    121     return condition;
    122   }
    123   static void ReportOOMFailure(const char* location, bool is_heap_oom);
    124 
    125   static inline Local<Context> ToLocal(
    126       v8::internal::Handle<v8::internal::Context> obj);
    127   static inline Local<Value> ToLocal(
    128       v8::internal::Handle<v8::internal::Object> obj);
    129   static inline Local<Module> ToLocal(
    130       v8::internal::Handle<v8::internal::Module> obj);
    131   static inline Local<Name> ToLocal(
    132       v8::internal::Handle<v8::internal::Name> obj);
    133   static inline Local<String> ToLocal(
    134       v8::internal::Handle<v8::internal::String> obj);
    135   static inline Local<Symbol> ToLocal(
    136       v8::internal::Handle<v8::internal::Symbol> obj);
    137   static inline Local<RegExp> ToLocal(
    138       v8::internal::Handle<v8::internal::JSRegExp> obj);
    139   static inline Local<Object> ToLocal(
    140       v8::internal::Handle<v8::internal::JSReceiver> obj);
    141   static inline Local<Object> ToLocal(
    142       v8::internal::Handle<v8::internal::JSObject> obj);
    143   static inline Local<Function> ToLocal(
    144       v8::internal::Handle<v8::internal::JSFunction> obj);
    145   static inline Local<Array> ToLocal(
    146       v8::internal::Handle<v8::internal::JSArray> obj);
    147   static inline Local<Map> ToLocal(
    148       v8::internal::Handle<v8::internal::JSMap> obj);
    149   static inline Local<Set> ToLocal(
    150       v8::internal::Handle<v8::internal::JSSet> obj);
    151   static inline Local<Proxy> ToLocal(
    152       v8::internal::Handle<v8::internal::JSProxy> obj);
    153   static inline Local<ArrayBuffer> ToLocal(
    154       v8::internal::Handle<v8::internal::JSArrayBuffer> obj);
    155   static inline Local<ArrayBufferView> ToLocal(
    156       v8::internal::Handle<v8::internal::JSArrayBufferView> obj);
    157   static inline Local<DataView> ToLocal(
    158       v8::internal::Handle<v8::internal::JSDataView> obj);
    159   static inline Local<TypedArray> ToLocal(
    160       v8::internal::Handle<v8::internal::JSTypedArray> obj);
    161   static inline Local<Uint8Array> ToLocalUint8Array(
    162       v8::internal::Handle<v8::internal::JSTypedArray> obj);
    163   static inline Local<Uint8ClampedArray> ToLocalUint8ClampedArray(
    164       v8::internal::Handle<v8::internal::JSTypedArray> obj);
    165   static inline Local<Int8Array> ToLocalInt8Array(
    166       v8::internal::Handle<v8::internal::JSTypedArray> obj);
    167   static inline Local<Uint16Array> ToLocalUint16Array(
    168       v8::internal::Handle<v8::internal::JSTypedArray> obj);
    169   static inline Local<Int16Array> ToLocalInt16Array(
    170       v8::internal::Handle<v8::internal::JSTypedArray> obj);
    171   static inline Local<Uint32Array> ToLocalUint32Array(
    172       v8::internal::Handle<v8::internal::JSTypedArray> obj);
    173   static inline Local<Int32Array> ToLocalInt32Array(
    174       v8::internal::Handle<v8::internal::JSTypedArray> obj);
    175   static inline Local<Float32Array> ToLocalFloat32Array(
    176       v8::internal::Handle<v8::internal::JSTypedArray> obj);
    177   static inline Local<Float64Array> ToLocalFloat64Array(
    178       v8::internal::Handle<v8::internal::JSTypedArray> obj);
    179 
    180   static inline Local<SharedArrayBuffer> ToLocalShared(
    181       v8::internal::Handle<v8::internal::JSArrayBuffer> obj);
    182 
    183   static inline Local<Message> MessageToLocal(
    184       v8::internal::Handle<v8::internal::Object> obj);
    185   static inline Local<Promise> PromiseToLocal(
    186       v8::internal::Handle<v8::internal::JSObject> obj);
    187   static inline Local<StackTrace> StackTraceToLocal(
    188       v8::internal::Handle<v8::internal::JSArray> obj);
    189   static inline Local<StackFrame> StackFrameToLocal(
    190       v8::internal::Handle<v8::internal::JSObject> obj);
    191   static inline Local<Number> NumberToLocal(
    192       v8::internal::Handle<v8::internal::Object> obj);
    193   static inline Local<Integer> IntegerToLocal(
    194       v8::internal::Handle<v8::internal::Object> obj);
    195   static inline Local<Uint32> Uint32ToLocal(
    196       v8::internal::Handle<v8::internal::Object> obj);
    197   static inline Local<FunctionTemplate> ToLocal(
    198       v8::internal::Handle<v8::internal::FunctionTemplateInfo> obj);
    199   static inline Local<ObjectTemplate> ToLocal(
    200       v8::internal::Handle<v8::internal::ObjectTemplateInfo> obj);
    201   static inline Local<Signature> SignatureToLocal(
    202       v8::internal::Handle<v8::internal::FunctionTemplateInfo> obj);
    203   static inline Local<AccessorSignature> AccessorSignatureToLocal(
    204       v8::internal::Handle<v8::internal::FunctionTemplateInfo> obj);
    205   static inline Local<External> ExternalToLocal(
    206       v8::internal::Handle<v8::internal::JSObject> obj);
    207   static inline Local<NativeWeakMap> NativeWeakMapToLocal(
    208       v8::internal::Handle<v8::internal::JSWeakMap> obj);
    209   static inline Local<Function> CallableToLocal(
    210       v8::internal::Handle<v8::internal::JSReceiver> obj);
    211 
    212 #define DECLARE_OPEN_HANDLE(From, To) \
    213   static inline v8::internal::Handle<v8::internal::To> \
    214       OpenHandle(const From* that, bool allow_empty_handle = false);
    215 
    216 OPEN_HANDLE_LIST(DECLARE_OPEN_HANDLE)
    217 
    218 #undef DECLARE_OPEN_HANDLE
    219 
    220   template<class From, class To>
    221   static inline Local<To> Convert(v8::internal::Handle<From> obj) {
    222     DCHECK(obj.is_null() ||
    223            (obj->IsSmi() ||
    224             !obj->IsTheHole(i::HeapObject::cast(*obj)->GetIsolate())));
    225     return Local<To>(reinterpret_cast<To*>(obj.location()));
    226   }
    227 
    228   template <class T>
    229   static inline v8::internal::Handle<v8::internal::Object> OpenPersistent(
    230       const v8::Persistent<T>& persistent) {
    231     return v8::internal::Handle<v8::internal::Object>(
    232         reinterpret_cast<v8::internal::Object**>(persistent.val_));
    233   }
    234 
    235   template <class T>
    236   static inline v8::internal::Handle<v8::internal::Object> OpenPersistent(
    237       v8::Persistent<T>* persistent) {
    238     return OpenPersistent(*persistent);
    239   }
    240 
    241   template <class From, class To>
    242   static inline v8::internal::Handle<To> OpenHandle(v8::Local<From> handle) {
    243     return OpenHandle(*handle);
    244   }
    245 
    246  private:
    247   static void ReportApiFailure(const char* location, const char* message);
    248 };
    249 
    250 
    251 template <class T>
    252 inline T* ToApi(v8::internal::Handle<v8::internal::Object> obj) {
    253   return reinterpret_cast<T*>(obj.location());
    254 }
    255 
    256 template <class T>
    257 inline v8::Local<T> ToApiHandle(
    258     v8::internal::Handle<v8::internal::Object> obj) {
    259   return Utils::Convert<v8::internal::Object, T>(obj);
    260 }
    261 
    262 
    263 template <class T>
    264 inline bool ToLocal(v8::internal::MaybeHandle<v8::internal::Object> maybe,
    265                     Local<T>* local) {
    266   v8::internal::Handle<v8::internal::Object> handle;
    267   if (maybe.ToHandle(&handle)) {
    268     *local = Utils::Convert<v8::internal::Object, T>(handle);
    269     return true;
    270   }
    271   return false;
    272 }
    273 
    274 
    275 // Implementations of ToLocal
    276 
    277 #define MAKE_TO_LOCAL(Name, From, To)                                       \
    278   Local<v8::To> Utils::Name(v8::internal::Handle<v8::internal::From> obj) { \
    279     return Convert<v8::internal::From, v8::To>(obj);  \
    280   }
    281 
    282 
    283 #define MAKE_TO_LOCAL_TYPED_ARRAY(Type, typeName, TYPE, ctype, size)  \
    284   Local<v8::Type##Array> Utils::ToLocal##Type##Array(                 \
    285       v8::internal::Handle<v8::internal::JSTypedArray> obj) {         \
    286     DCHECK(obj->type() == v8::internal::kExternal##Type##Array);      \
    287     return Convert<v8::internal::JSTypedArray, v8::Type##Array>(obj); \
    288   }
    289 
    290 
    291 MAKE_TO_LOCAL(ToLocal, Context, Context)
    292 MAKE_TO_LOCAL(ToLocal, Object, Value)
    293 MAKE_TO_LOCAL(ToLocal, Module, Module)
    294 MAKE_TO_LOCAL(ToLocal, Name, Name)
    295 MAKE_TO_LOCAL(ToLocal, String, String)
    296 MAKE_TO_LOCAL(ToLocal, Symbol, Symbol)
    297 MAKE_TO_LOCAL(ToLocal, JSRegExp, RegExp)
    298 MAKE_TO_LOCAL(ToLocal, JSReceiver, Object)
    299 MAKE_TO_LOCAL(ToLocal, JSObject, Object)
    300 MAKE_TO_LOCAL(ToLocal, JSFunction, Function)
    301 MAKE_TO_LOCAL(ToLocal, JSArray, Array)
    302 MAKE_TO_LOCAL(ToLocal, JSMap, Map)
    303 MAKE_TO_LOCAL(ToLocal, JSSet, Set)
    304 MAKE_TO_LOCAL(ToLocal, JSProxy, Proxy)
    305 MAKE_TO_LOCAL(ToLocal, JSArrayBuffer, ArrayBuffer)
    306 MAKE_TO_LOCAL(ToLocal, JSArrayBufferView, ArrayBufferView)
    307 MAKE_TO_LOCAL(ToLocal, JSDataView, DataView)
    308 MAKE_TO_LOCAL(ToLocal, JSTypedArray, TypedArray)
    309 MAKE_TO_LOCAL(ToLocalShared, JSArrayBuffer, SharedArrayBuffer)
    310 
    311 TYPED_ARRAYS(MAKE_TO_LOCAL_TYPED_ARRAY)
    312 
    313 MAKE_TO_LOCAL(ToLocal, FunctionTemplateInfo, FunctionTemplate)
    314 MAKE_TO_LOCAL(ToLocal, ObjectTemplateInfo, ObjectTemplate)
    315 MAKE_TO_LOCAL(SignatureToLocal, FunctionTemplateInfo, Signature)
    316 MAKE_TO_LOCAL(AccessorSignatureToLocal, FunctionTemplateInfo, AccessorSignature)
    317 MAKE_TO_LOCAL(MessageToLocal, Object, Message)
    318 MAKE_TO_LOCAL(PromiseToLocal, JSObject, Promise)
    319 MAKE_TO_LOCAL(StackTraceToLocal, JSArray, StackTrace)
    320 MAKE_TO_LOCAL(StackFrameToLocal, JSObject, StackFrame)
    321 MAKE_TO_LOCAL(NumberToLocal, Object, Number)
    322 MAKE_TO_LOCAL(IntegerToLocal, Object, Integer)
    323 MAKE_TO_LOCAL(Uint32ToLocal, Object, Uint32)
    324 MAKE_TO_LOCAL(ExternalToLocal, JSObject, External)
    325 MAKE_TO_LOCAL(NativeWeakMapToLocal, JSWeakMap, NativeWeakMap)
    326 MAKE_TO_LOCAL(CallableToLocal, JSReceiver, Function)
    327 
    328 #undef MAKE_TO_LOCAL_TYPED_ARRAY
    329 #undef MAKE_TO_LOCAL
    330 
    331 
    332 // Implementations of OpenHandle
    333 
    334 #define MAKE_OPEN_HANDLE(From, To)                                             \
    335   v8::internal::Handle<v8::internal::To> Utils::OpenHandle(                    \
    336       const v8::From* that, bool allow_empty_handle) {                         \
    337     DCHECK(allow_empty_handle || that != NULL);                                \
    338     DCHECK(that == NULL ||                                                     \
    339            (*reinterpret_cast<v8::internal::Object* const*>(that))->Is##To()); \
    340     return v8::internal::Handle<v8::internal::To>(                             \
    341         reinterpret_cast<v8::internal::To**>(const_cast<v8::From*>(that)));    \
    342   }
    343 
    344 OPEN_HANDLE_LIST(MAKE_OPEN_HANDLE)
    345 
    346 #undef MAKE_OPEN_HANDLE
    347 #undef OPEN_HANDLE_LIST
    348 
    349 
    350 namespace internal {
    351 
    352 
    353 class 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