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 
ToCData(v8::internal::Object * obj)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>
FromCData(v8::internal::Isolate * isolate,T obj)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:
ApiFunction(v8::internal::Address addr)50   explicit ApiFunction(v8::internal::Address addr) : addr_(addr) { }
address()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();
extension()63   Extension* extension() { return extension_; }
next()64   RegisteredExtension* next() { return next_; }
first_extension()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:
ApiCheck(bool condition,const char * location,const char * message)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 
OPEN_HANDLE_LIST(DECLARE_OPEN_HANDLE)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>
OpenPersistent(const v8::Persistent<T> & persistent)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>
OpenPersistent(v8::Persistent<T> * persistent)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>
OpenHandle(v8::Local<From> handle)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>
ToApi(v8::internal::Handle<v8::internal::Object> obj)253 inline T* ToApi(v8::internal::Handle<v8::internal::Object> obj) {
254   return reinterpret_cast<T*>(obj.location());
255 }
256 
257 template <class T>
ToApiHandle(v8::internal::Handle<v8::internal::Object> obj)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>
ToLocal(v8::internal::MaybeHandle<v8::internal::Object> maybe,Local<T> * local)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 
MAKE_TO_LOCAL(ToLocal,Context,Context)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