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