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