Line data Source code
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/detachable-vector.h"
12 : #include "src/factory.h"
13 : #include "src/isolate.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 :
29 1462529 : template <typename T> inline T ToCData(v8::internal::Object* obj) {
30 : STATIC_ASSERT(sizeof(T) == sizeof(v8::internal::Address));
31 17579135 : if (obj == v8::internal::Smi::kZero) return nullptr;
32 : return reinterpret_cast<T>(
33 : reinterpret_cast<intptr_t>(
34 17252824 : v8::internal::Foreign::cast(obj)->foreign_address()));
35 : }
36 :
37 :
38 : template <typename T>
39 3403504 : 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 3405210 : if (obj == nullptr) return handle(v8::internal::Smi::kZero, isolate);
43 : return isolate->factory()->NewForeign(
44 3401798 : reinterpret_cast<v8::internal::Address>(reinterpret_cast<intptr_t>(obj)));
45 : }
46 :
47 :
48 : class ApiFunction {
49 : public:
50 169757 : explicit ApiFunction(v8::internal::Address addr) : addr_(addr) { }
51 169757 : 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();
63 : Extension* extension() { return extension_; }
64 : RegisteredExtension* next() { return next_; }
65 87030 : 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, FixedArray) \
109 : V(StackFrame, StackFrameInfo) \
110 : V(Proxy, JSProxy) \
111 : V(NativeWeakMap, JSWeakMap) \
112 : V(debug::GeneratorObject, JSGeneratorObject) \
113 : V(debug::Script, Script) \
114 : V(Promise, JSPromise) \
115 : V(Primitive, Object) \
116 : V(PrimitiveArray, FixedArray) \
117 : V(ScriptOrModule, Script)
118 :
119 : class Utils {
120 : public:
121 : static inline bool ApiCheck(bool condition,
122 : const char* location,
123 : const char* message) {
124 697556079 : if (!condition) Utils::ReportApiFailure(location, message);
125 : return condition;
126 : }
127 : static void ReportOOMFailure(const char* location, bool is_heap_oom);
128 :
129 : static inline Local<Context> ToLocal(
130 : v8::internal::Handle<v8::internal::Context> obj);
131 : static inline Local<Value> ToLocal(
132 : v8::internal::Handle<v8::internal::Object> obj);
133 : static inline Local<Module> ToLocal(
134 : v8::internal::Handle<v8::internal::Module> obj);
135 : static inline Local<Name> ToLocal(
136 : v8::internal::Handle<v8::internal::Name> obj);
137 : static inline Local<String> ToLocal(
138 : v8::internal::Handle<v8::internal::String> obj);
139 : static inline Local<Symbol> ToLocal(
140 : v8::internal::Handle<v8::internal::Symbol> obj);
141 : static inline Local<RegExp> ToLocal(
142 : v8::internal::Handle<v8::internal::JSRegExp> obj);
143 : static inline Local<Object> ToLocal(
144 : v8::internal::Handle<v8::internal::JSReceiver> obj);
145 : static inline Local<Object> ToLocal(
146 : v8::internal::Handle<v8::internal::JSObject> obj);
147 : static inline Local<Function> ToLocal(
148 : v8::internal::Handle<v8::internal::JSFunction> obj);
149 : static inline Local<Array> ToLocal(
150 : v8::internal::Handle<v8::internal::JSArray> obj);
151 : static inline Local<Map> ToLocal(
152 : v8::internal::Handle<v8::internal::JSMap> obj);
153 : static inline Local<Set> ToLocal(
154 : v8::internal::Handle<v8::internal::JSSet> obj);
155 : static inline Local<Proxy> ToLocal(
156 : v8::internal::Handle<v8::internal::JSProxy> obj);
157 : static inline Local<ArrayBuffer> ToLocal(
158 : v8::internal::Handle<v8::internal::JSArrayBuffer> obj);
159 : static inline Local<ArrayBufferView> ToLocal(
160 : v8::internal::Handle<v8::internal::JSArrayBufferView> obj);
161 : static inline Local<DataView> ToLocal(
162 : v8::internal::Handle<v8::internal::JSDataView> obj);
163 : static inline Local<TypedArray> ToLocal(
164 : v8::internal::Handle<v8::internal::JSTypedArray> obj);
165 : static inline Local<Uint8Array> ToLocalUint8Array(
166 : v8::internal::Handle<v8::internal::JSTypedArray> obj);
167 : static inline Local<Uint8ClampedArray> ToLocalUint8ClampedArray(
168 : v8::internal::Handle<v8::internal::JSTypedArray> obj);
169 : static inline Local<Int8Array> ToLocalInt8Array(
170 : v8::internal::Handle<v8::internal::JSTypedArray> obj);
171 : static inline Local<Uint16Array> ToLocalUint16Array(
172 : v8::internal::Handle<v8::internal::JSTypedArray> obj);
173 : static inline Local<Int16Array> ToLocalInt16Array(
174 : v8::internal::Handle<v8::internal::JSTypedArray> obj);
175 : static inline Local<Uint32Array> ToLocalUint32Array(
176 : v8::internal::Handle<v8::internal::JSTypedArray> obj);
177 : static inline Local<Int32Array> ToLocalInt32Array(
178 : v8::internal::Handle<v8::internal::JSTypedArray> obj);
179 : static inline Local<Float32Array> ToLocalFloat32Array(
180 : v8::internal::Handle<v8::internal::JSTypedArray> obj);
181 : static inline Local<Float64Array> ToLocalFloat64Array(
182 : v8::internal::Handle<v8::internal::JSTypedArray> obj);
183 :
184 : static inline Local<SharedArrayBuffer> ToLocalShared(
185 : v8::internal::Handle<v8::internal::JSArrayBuffer> obj);
186 :
187 : static inline Local<Message> MessageToLocal(
188 : v8::internal::Handle<v8::internal::Object> obj);
189 : static inline Local<Promise> PromiseToLocal(
190 : v8::internal::Handle<v8::internal::JSObject> obj);
191 : static inline Local<StackTrace> StackTraceToLocal(
192 : v8::internal::Handle<v8::internal::FixedArray> obj);
193 : static inline Local<StackFrame> StackFrameToLocal(
194 : v8::internal::Handle<v8::internal::StackFrameInfo> obj);
195 : static inline Local<Number> NumberToLocal(
196 : v8::internal::Handle<v8::internal::Object> obj);
197 : static inline Local<Integer> IntegerToLocal(
198 : v8::internal::Handle<v8::internal::Object> obj);
199 : static inline Local<Uint32> Uint32ToLocal(
200 : v8::internal::Handle<v8::internal::Object> obj);
201 : static inline Local<FunctionTemplate> ToLocal(
202 : v8::internal::Handle<v8::internal::FunctionTemplateInfo> obj);
203 : static inline Local<ObjectTemplate> ToLocal(
204 : v8::internal::Handle<v8::internal::ObjectTemplateInfo> obj);
205 : static inline Local<Signature> SignatureToLocal(
206 : v8::internal::Handle<v8::internal::FunctionTemplateInfo> obj);
207 : static inline Local<AccessorSignature> AccessorSignatureToLocal(
208 : v8::internal::Handle<v8::internal::FunctionTemplateInfo> obj);
209 : static inline Local<External> ExternalToLocal(
210 : v8::internal::Handle<v8::internal::JSObject> obj);
211 : static inline Local<NativeWeakMap> NativeWeakMapToLocal(
212 : v8::internal::Handle<v8::internal::JSWeakMap> obj);
213 : static inline Local<Function> CallableToLocal(
214 : v8::internal::Handle<v8::internal::JSReceiver> obj);
215 : static inline Local<Primitive> ToLocalPrimitive(
216 : v8::internal::Handle<v8::internal::Object> obj);
217 : static inline Local<PrimitiveArray> ToLocal(
218 : v8::internal::Handle<v8::internal::FixedArray> obj);
219 : static inline Local<ScriptOrModule> ScriptOrModuleToLocal(
220 : v8::internal::Handle<v8::internal::Script> obj);
221 :
222 : #define DECLARE_OPEN_HANDLE(From, To) \
223 : static inline v8::internal::Handle<v8::internal::To> \
224 : OpenHandle(const From* that, bool allow_empty_handle = false);
225 :
226 : OPEN_HANDLE_LIST(DECLARE_OPEN_HANDLE)
227 :
228 : #undef DECLARE_OPEN_HANDLE
229 :
230 : template<class From, class To>
231 : static inline Local<To> Convert(v8::internal::Handle<From> obj) {
232 : DCHECK(obj.is_null() ||
233 : (obj->IsSmi() ||
234 : !obj->IsTheHole(i::HeapObject::cast(*obj)->GetIsolate())));
235 : return Local<To>(reinterpret_cast<To*>(obj.location()));
236 : }
237 :
238 : template <class T>
239 : static inline v8::internal::Handle<v8::internal::Object> OpenPersistent(
240 : const v8::Persistent<T>& persistent) {
241 : return v8::internal::Handle<v8::internal::Object>(
242 15 : reinterpret_cast<v8::internal::Object**>(persistent.val_));
243 : }
244 :
245 : template <class T>
246 : static inline v8::internal::Handle<v8::internal::Object> OpenPersistent(
247 : v8::Persistent<T>* persistent) {
248 : return OpenPersistent(*persistent);
249 : }
250 :
251 : template <class From, class To>
252 : static inline v8::internal::Handle<To> OpenHandle(v8::Local<From> handle) {
253 : return OpenHandle(*handle);
254 : }
255 :
256 : private:
257 : static void ReportApiFailure(const char* location, const char* message);
258 : };
259 :
260 :
261 : template <class T>
262 : inline T* ToApi(v8::internal::Handle<v8::internal::Object> obj) {
263 : return reinterpret_cast<T*>(obj.location());
264 : }
265 :
266 : template <class T>
267 : inline v8::Local<T> ToApiHandle(
268 : v8::internal::Handle<v8::internal::Object> obj) {
269 : return Utils::Convert<v8::internal::Object, T>(obj);
270 : }
271 :
272 :
273 : template <class T>
274 : inline bool ToLocal(v8::internal::MaybeHandle<v8::internal::Object> maybe,
275 : Local<T>* local) {
276 : v8::internal::Handle<v8::internal::Object> handle;
277 1137618 : if (maybe.ToHandle(&handle)) {
278 : *local = Utils::Convert<v8::internal::Object, T>(handle);
279 : return true;
280 : }
281 : return false;
282 : }
283 :
284 :
285 : // Implementations of ToLocal
286 :
287 : #define MAKE_TO_LOCAL(Name, From, To) \
288 : Local<v8::To> Utils::Name(v8::internal::Handle<v8::internal::From> obj) { \
289 : return Convert<v8::internal::From, v8::To>(obj); \
290 : }
291 :
292 :
293 : #define MAKE_TO_LOCAL_TYPED_ARRAY(Type, typeName, TYPE, ctype, size) \
294 : Local<v8::Type##Array> Utils::ToLocal##Type##Array( \
295 : v8::internal::Handle<v8::internal::JSTypedArray> obj) { \
296 : DCHECK(obj->type() == v8::internal::kExternal##Type##Array); \
297 : return Convert<v8::internal::JSTypedArray, v8::Type##Array>(obj); \
298 : }
299 :
300 :
301 : MAKE_TO_LOCAL(ToLocal, Context, Context)
302 : MAKE_TO_LOCAL(ToLocal, Object, Value)
303 : MAKE_TO_LOCAL(ToLocal, Module, Module)
304 : MAKE_TO_LOCAL(ToLocal, Name, Name)
305 961 : MAKE_TO_LOCAL(ToLocal, String, String)
306 : MAKE_TO_LOCAL(ToLocal, Symbol, Symbol)
307 : MAKE_TO_LOCAL(ToLocal, JSRegExp, RegExp)
308 : MAKE_TO_LOCAL(ToLocal, JSReceiver, Object)
309 : MAKE_TO_LOCAL(ToLocal, JSObject, Object)
310 : MAKE_TO_LOCAL(ToLocal, JSFunction, Function)
311 : MAKE_TO_LOCAL(ToLocal, JSArray, Array)
312 : MAKE_TO_LOCAL(ToLocal, JSMap, Map)
313 : MAKE_TO_LOCAL(ToLocal, JSSet, Set)
314 : MAKE_TO_LOCAL(ToLocal, JSProxy, Proxy)
315 : MAKE_TO_LOCAL(ToLocal, JSArrayBuffer, ArrayBuffer)
316 : MAKE_TO_LOCAL(ToLocal, JSArrayBufferView, ArrayBufferView)
317 : MAKE_TO_LOCAL(ToLocal, JSDataView, DataView)
318 : MAKE_TO_LOCAL(ToLocal, JSTypedArray, TypedArray)
319 : MAKE_TO_LOCAL(ToLocalShared, JSArrayBuffer, SharedArrayBuffer)
320 :
321 : TYPED_ARRAYS(MAKE_TO_LOCAL_TYPED_ARRAY)
322 :
323 : MAKE_TO_LOCAL(ToLocal, FunctionTemplateInfo, FunctionTemplate)
324 : MAKE_TO_LOCAL(ToLocal, ObjectTemplateInfo, ObjectTemplate)
325 : MAKE_TO_LOCAL(SignatureToLocal, FunctionTemplateInfo, Signature)
326 : MAKE_TO_LOCAL(AccessorSignatureToLocal, FunctionTemplateInfo, AccessorSignature)
327 : MAKE_TO_LOCAL(MessageToLocal, Object, Message)
328 : MAKE_TO_LOCAL(PromiseToLocal, JSObject, Promise)
329 : MAKE_TO_LOCAL(StackTraceToLocal, FixedArray, StackTrace)
330 : MAKE_TO_LOCAL(StackFrameToLocal, StackFrameInfo, StackFrame)
331 : MAKE_TO_LOCAL(NumberToLocal, Object, Number)
332 : MAKE_TO_LOCAL(IntegerToLocal, Object, Integer)
333 : MAKE_TO_LOCAL(Uint32ToLocal, Object, Uint32)
334 : MAKE_TO_LOCAL(ExternalToLocal, JSObject, External)
335 : MAKE_TO_LOCAL(NativeWeakMapToLocal, JSWeakMap, NativeWeakMap)
336 : MAKE_TO_LOCAL(CallableToLocal, JSReceiver, Function)
337 : MAKE_TO_LOCAL(ToLocalPrimitive, Object, Primitive)
338 : MAKE_TO_LOCAL(ToLocal, FixedArray, PrimitiveArray)
339 : MAKE_TO_LOCAL(ScriptOrModuleToLocal, Script, ScriptOrModule)
340 :
341 : #undef MAKE_TO_LOCAL_TYPED_ARRAY
342 : #undef MAKE_TO_LOCAL
343 :
344 :
345 : // Implementations of OpenHandle
346 :
347 : #define MAKE_OPEN_HANDLE(From, To) \
348 : v8::internal::Handle<v8::internal::To> Utils::OpenHandle( \
349 : const v8::From* that, bool allow_empty_handle) { \
350 : DCHECK(allow_empty_handle || that != nullptr); \
351 : DCHECK(that == nullptr || \
352 : (*reinterpret_cast<v8::internal::Object* const*>(that))->Is##To()); \
353 : return v8::internal::Handle<v8::internal::To>( \
354 : reinterpret_cast<v8::internal::To**>(const_cast<v8::From*>(that))); \
355 : }
356 :
357 140 : OPEN_HANDLE_LIST(MAKE_OPEN_HANDLE)
358 :
359 : #undef MAKE_OPEN_HANDLE
360 : #undef OPEN_HANDLE_LIST
361 :
362 : extern Isolate* IsolateNewImpl(internal::Isolate* isolate,
363 : const Isolate::CreateParams& params);
364 :
365 : namespace internal {
366 :
367 : class V8_EXPORT_PRIVATE DeferredHandles {
368 : public:
369 : ~DeferredHandles();
370 :
371 : private:
372 : DeferredHandles(Object** first_block_limit, Isolate* isolate)
373 : : next_(nullptr),
374 : previous_(nullptr),
375 : first_block_limit_(first_block_limit),
376 9393 : isolate_(isolate) {
377 9393 : isolate->LinkDeferredHandles(this);
378 : }
379 :
380 : void Iterate(RootVisitor* v);
381 :
382 : std::vector<Object**> blocks_;
383 : DeferredHandles* next_;
384 : DeferredHandles* previous_;
385 : Object** first_block_limit_;
386 : Isolate* isolate_;
387 :
388 : friend class HandleScopeImplementer;
389 : friend class Isolate;
390 : };
391 :
392 :
393 : // This class is here in order to be able to declare it a friend of
394 : // HandleScope. Moving these methods to be members of HandleScope would be
395 : // neat in some ways, but it would expose internal implementation details in
396 : // our public header file, which is undesirable.
397 : //
398 : // An isolate has a single instance of this class to hold the current thread's
399 : // data. In multithreaded V8 programs this data is copied in and out of storage
400 : // so that the currently executing thread always has its own copy of this
401 : // data.
402 : class HandleScopeImplementer {
403 : public:
404 : explicit HandleScopeImplementer(Isolate* isolate)
405 : : isolate_(isolate),
406 : microtask_context_(nullptr),
407 : spare_(nullptr),
408 : call_depth_(0),
409 : microtasks_depth_(0),
410 : microtasks_suppressions_(0),
411 : entered_context_count_during_microtasks_(0),
412 : #ifdef DEBUG
413 : debug_microtasks_depth_(0),
414 : #endif
415 : microtasks_policy_(v8::MicrotasksPolicy::kAuto),
416 109998 : last_handle_before_deferred_block_(nullptr) {
417 : }
418 :
419 106730 : ~HandleScopeImplementer() {
420 53365 : DeleteArray(spare_);
421 53365 : }
422 :
423 : // Threading support for handle data.
424 : static int ArchiveSpacePerThread();
425 : char* RestoreThread(char* from);
426 : char* ArchiveThread(char* to);
427 : void FreeThreadResources();
428 :
429 : // Garbage collection support.
430 : void Iterate(v8::internal::RootVisitor* v);
431 : static char* Iterate(v8::internal::RootVisitor* v, char* data);
432 :
433 : inline internal::Object** GetSpareOrNewBlock();
434 : inline void DeleteExtensions(internal::Object** prev_limit);
435 :
436 : // Call depth represents nested v8 api calls.
437 133775838 : inline void IncrementCallDepth() {call_depth_++;}
438 133775879 : inline void DecrementCallDepth() {call_depth_--;}
439 14118 : inline bool CallDepthIsZero() { return call_depth_ == 0; }
440 :
441 : // Microtasks scope depth represents nested scopes controlling microtasks
442 : // invocation, which happens when depth reaches zero.
443 130359 : inline void IncrementMicrotasksScopeDepth() {microtasks_depth_++;}
444 130360 : inline void DecrementMicrotasksScopeDepth() {microtasks_depth_--;}
445 : inline int GetMicrotasksScopeDepth() { return microtasks_depth_; }
446 :
447 : // Possibly nested microtasks suppression scopes prevent microtasks
448 : // from running.
449 98363 : inline void IncrementMicrotasksSuppressions() {microtasks_suppressions_++;}
450 98362 : inline void DecrementMicrotasksSuppressions() {microtasks_suppressions_--;}
451 : inline bool HasMicrotasksSuppressions() { return !!microtasks_suppressions_; }
452 :
453 : #ifdef DEBUG
454 : // In debug we check that calls not intended to invoke microtasks are
455 : // still correctly wrapped with microtask scopes.
456 : inline void IncrementDebugMicrotasksScopeDepth() {debug_microtasks_depth_++;}
457 : inline void DecrementDebugMicrotasksScopeDepth() {debug_microtasks_depth_--;}
458 : inline bool DebugMicrotasksScopeDepthIsZero() {
459 : return debug_microtasks_depth_ == 0;
460 : }
461 : #endif
462 :
463 : inline void set_microtasks_policy(v8::MicrotasksPolicy policy);
464 : inline v8::MicrotasksPolicy microtasks_policy() const;
465 :
466 : inline void EnterContext(Handle<Context> context);
467 : inline void LeaveContext();
468 : inline bool LastEnteredContextWas(Handle<Context> context);
469 :
470 : // Returns the last entered context or an empty handle if no
471 : // contexts have been entered.
472 : inline Handle<Context> LastEnteredContext();
473 :
474 : inline void EnterMicrotaskContext(Handle<Context> context);
475 : inline void LeaveMicrotaskContext();
476 : inline Handle<Context> MicrotaskContext();
477 : inline bool MicrotaskContextIsLastEnteredContext() const {
478 1198467 : return microtask_context_ &&
479 0 : entered_context_count_during_microtasks_ == entered_contexts_.size();
480 : }
481 :
482 : inline void SaveContext(Context* context);
483 : inline Context* RestoreContext();
484 : inline bool HasSavedContexts();
485 :
486 : inline DetachableVector<Object**>* blocks() { return &blocks_; }
487 : Isolate* isolate() const { return isolate_; }
488 :
489 : void ReturnBlock(Object** block) {
490 : DCHECK_NOT_NULL(block);
491 9390 : if (spare_ != nullptr) DeleteArray(spare_);
492 9390 : spare_ = block;
493 : }
494 :
495 : private:
496 : void ResetAfterArchive() {
497 : blocks_.detach();
498 : entered_contexts_.detach();
499 : saved_contexts_.detach();
500 24163 : microtask_context_ = nullptr;
501 24163 : entered_context_count_during_microtasks_ = 0;
502 24163 : spare_ = nullptr;
503 24163 : last_handle_before_deferred_block_ = nullptr;
504 24163 : call_depth_ = 0;
505 : }
506 :
507 5856 : void Free() {
508 : DCHECK(blocks_.empty());
509 : DCHECK(entered_contexts_.empty());
510 : DCHECK(saved_contexts_.empty());
511 : DCHECK(!microtask_context_);
512 :
513 5856 : blocks_.free();
514 5856 : entered_contexts_.free();
515 5856 : saved_contexts_.free();
516 5856 : if (spare_ != nullptr) {
517 : DeleteArray(spare_);
518 5788 : spare_ = nullptr;
519 : }
520 : DCHECK_EQ(call_depth_, 0);
521 5856 : }
522 :
523 : void BeginDeferredScope();
524 : DeferredHandles* Detach(Object** prev_limit);
525 :
526 : Isolate* isolate_;
527 : DetachableVector<Object**> blocks_;
528 : // Used as a stack to keep track of entered contexts.
529 : DetachableVector<Context*> entered_contexts_;
530 : // Used as a stack to keep track of saved contexts.
531 : DetachableVector<Context*> saved_contexts_;
532 : Context* microtask_context_;
533 : Object** spare_;
534 : int call_depth_;
535 : int microtasks_depth_;
536 : int microtasks_suppressions_;
537 : size_t entered_context_count_during_microtasks_;
538 : #ifdef DEBUG
539 : int debug_microtasks_depth_;
540 : #endif
541 : v8::MicrotasksPolicy microtasks_policy_;
542 : Object** last_handle_before_deferred_block_;
543 : // This is only used for threading support.
544 : HandleScopeData handle_scope_data_;
545 :
546 : void IterateThis(RootVisitor* v);
547 : char* RestoreThreadHelper(char* from);
548 : char* ArchiveThreadHelper(char* to);
549 :
550 : friend class DeferredHandles;
551 : friend class DeferredHandleScope;
552 :
553 : DISALLOW_COPY_AND_ASSIGN(HandleScopeImplementer);
554 : };
555 :
556 :
557 : const int kHandleBlockSize = v8::internal::KB - 2; // fit in one page
558 :
559 :
560 : void HandleScopeImplementer::set_microtasks_policy(
561 : v8::MicrotasksPolicy policy) {
562 1657 : microtasks_policy_ = policy;
563 : }
564 :
565 :
566 : v8::MicrotasksPolicy HandleScopeImplementer::microtasks_policy() const {
567 : return microtasks_policy_;
568 : }
569 :
570 :
571 : void HandleScopeImplementer::SaveContext(Context* context) {
572 12765882 : saved_contexts_.push_back(context);
573 : }
574 :
575 :
576 : Context* HandleScopeImplementer::RestoreContext() {
577 12750894 : Context* last_context = saved_contexts_.back();
578 : saved_contexts_.pop_back();
579 : return last_context;
580 : }
581 :
582 :
583 : bool HandleScopeImplementer::HasSavedContexts() {
584 : return !saved_contexts_.empty();
585 : }
586 :
587 :
588 1202125 : void HandleScopeImplementer::EnterContext(Handle<Context> context) {
589 2404308 : entered_contexts_.push_back(*context);
590 1202183 : }
591 :
592 : void HandleScopeImplementer::LeaveContext() { entered_contexts_.pop_back(); }
593 :
594 : bool HandleScopeImplementer::LastEnteredContextWas(Handle<Context> context) {
595 3561575 : return !entered_contexts_.empty() && entered_contexts_.back() == *context;
596 : }
597 :
598 :
599 1244148 : Handle<Context> HandleScopeImplementer::LastEnteredContext() {
600 1244148 : if (entered_contexts_.empty()) return Handle<Context>::null();
601 2488276 : return Handle<Context>(entered_contexts_.back());
602 : }
603 :
604 : void HandleScopeImplementer::EnterMicrotaskContext(Handle<Context> context) {
605 : DCHECK(!microtask_context_);
606 201613 : microtask_context_ = *context;
607 201613 : entered_context_count_during_microtasks_ = entered_contexts_.size();
608 : }
609 :
610 : void HandleScopeImplementer::LeaveMicrotaskContext() {
611 : DCHECK(microtask_context_);
612 201614 : microtask_context_ = nullptr;
613 201614 : entered_context_count_during_microtasks_ = 0;
614 : }
615 :
616 0 : Handle<Context> HandleScopeImplementer::MicrotaskContext() {
617 0 : if (microtask_context_) return Handle<Context>(microtask_context_);
618 : return Handle<Context>::null();
619 : }
620 :
621 : // If there's a spare block, use it for growing the current scope.
622 : internal::Object** HandleScopeImplementer::GetSpareOrNewBlock() {
623 : internal::Object** block =
624 1390809 : (spare_ != nullptr) ? spare_
625 1390809 : : NewArray<internal::Object*>(kHandleBlockSize);
626 1390809 : spare_ = nullptr;
627 : return block;
628 : }
629 :
630 :
631 1161706 : void HandleScopeImplementer::DeleteExtensions(internal::Object** prev_limit) {
632 3704824 : while (!blocks_.empty()) {
633 1826988 : internal::Object** block_start = blocks_.back();
634 1826988 : internal::Object** block_limit = block_start + kHandleBlockSize;
635 :
636 : // SealHandleScope may make the prev_limit to point inside the block.
637 1826988 : if (block_start <= prev_limit && prev_limit <= block_limit) {
638 : #ifdef ENABLE_HANDLE_ZAPPING
639 : internal::HandleScope::ZapRange(prev_limit, block_limit);
640 : #endif
641 : break;
642 : }
643 :
644 : blocks_.pop_back();
645 : #ifdef ENABLE_HANDLE_ZAPPING
646 : internal::HandleScope::ZapRange(block_start, block_limit);
647 : #endif
648 1381411 : if (spare_ != nullptr) {
649 : DeleteArray(spare_);
650 : }
651 1381412 : spare_ = block_start;
652 : }
653 : DCHECK((blocks_.empty() && prev_limit == nullptr) ||
654 : (!blocks_.empty() && prev_limit != nullptr));
655 1161707 : }
656 :
657 : // Interceptor functions called from generated inline caches to notify
658 : // CPU profiler that external callbacks are invoked.
659 : void InvokeAccessorGetterCallback(
660 : v8::Local<v8::Name> property,
661 : const v8::PropertyCallbackInfo<v8::Value>& info,
662 : v8::AccessorNameGetterCallback getter);
663 :
664 : void InvokeFunctionCallback(const v8::FunctionCallbackInfo<v8::Value>& info,
665 : v8::FunctionCallback callback);
666 :
667 : class Testing {
668 : public:
669 22006 : static v8::Testing::StressType stress_type() { return stress_type_; }
670 : static void set_stress_type(v8::Testing::StressType stress_type) {
671 4402 : stress_type_ = stress_type;
672 : }
673 :
674 : private:
675 : static v8::Testing::StressType stress_type_;
676 : };
677 :
678 : } // namespace internal
679 : } // namespace v8
680 :
681 : #endif // V8_API_H_
|