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