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