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
15namespace 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.
21class Consts {
22 public:
23  enum TemplateType {
24    FUNCTION_TEMPLATE = 0,
25    OBJECT_TEMPLATE = 1
26  };
27};
28
29template <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
38template <typename T>
39inline 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
48class ApiFunction {
49 public:
50  explicit ApiFunction(v8::internal::Address addr) : addr_(addr) { }
51  v8::internal::Address address() { return addr_; }
52 private:
53  v8::internal::Address addr_;
54};
55
56
57
58class 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  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
116class Utils {
117 public:
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
217OPEN_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>
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>
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>
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
252template <class T>
253inline T* ToApi(v8::internal::Handle<v8::internal::Object> obj) {
254  return reinterpret_cast<T*>(obj.location());
255}
256
257template <class T>
258inline v8::Local<T> ToApiHandle(
259    v8::internal::Handle<v8::internal::Object> obj) {
260  return Utils::Convert<v8::internal::Object, T>(obj);
261}
262
263
264template <class T>
265inline 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
292MAKE_TO_LOCAL(ToLocal, Context, Context)
293MAKE_TO_LOCAL(ToLocal, Object, Value)
294MAKE_TO_LOCAL(ToLocal, Module, Module)
295MAKE_TO_LOCAL(ToLocal, Name, Name)
296MAKE_TO_LOCAL(ToLocal, String, String)
297MAKE_TO_LOCAL(ToLocal, Symbol, Symbol)
298MAKE_TO_LOCAL(ToLocal, JSRegExp, RegExp)
299MAKE_TO_LOCAL(ToLocal, JSReceiver, Object)
300MAKE_TO_LOCAL(ToLocal, JSObject, Object)
301MAKE_TO_LOCAL(ToLocal, JSFunction, Function)
302MAKE_TO_LOCAL(ToLocal, JSArray, Array)
303MAKE_TO_LOCAL(ToLocal, JSMap, Map)
304MAKE_TO_LOCAL(ToLocal, JSSet, Set)
305MAKE_TO_LOCAL(ToLocal, JSProxy, Proxy)
306MAKE_TO_LOCAL(ToLocal, JSArrayBuffer, ArrayBuffer)
307MAKE_TO_LOCAL(ToLocal, JSArrayBufferView, ArrayBufferView)
308MAKE_TO_LOCAL(ToLocal, JSDataView, DataView)
309MAKE_TO_LOCAL(ToLocal, JSTypedArray, TypedArray)
310MAKE_TO_LOCAL(ToLocalShared, JSArrayBuffer, SharedArrayBuffer)
311
312TYPED_ARRAYS(MAKE_TO_LOCAL_TYPED_ARRAY)
313
314MAKE_TO_LOCAL(ToLocal, FunctionTemplateInfo, FunctionTemplate)
315MAKE_TO_LOCAL(ToLocal, ObjectTemplateInfo, ObjectTemplate)
316MAKE_TO_LOCAL(SignatureToLocal, FunctionTemplateInfo, Signature)
317MAKE_TO_LOCAL(AccessorSignatureToLocal, FunctionTemplateInfo, AccessorSignature)
318MAKE_TO_LOCAL(MessageToLocal, Object, Message)
319MAKE_TO_LOCAL(PromiseToLocal, JSObject, Promise)
320MAKE_TO_LOCAL(StackTraceToLocal, JSArray, StackTrace)
321MAKE_TO_LOCAL(StackFrameToLocal, JSObject, StackFrame)
322MAKE_TO_LOCAL(NumberToLocal, Object, Number)
323MAKE_TO_LOCAL(IntegerToLocal, Object, Integer)
324MAKE_TO_LOCAL(Uint32ToLocal, Object, Uint32)
325MAKE_TO_LOCAL(ExternalToLocal, JSObject, External)
326MAKE_TO_LOCAL(NativeWeakMapToLocal, JSWeakMap, NativeWeakMap)
327MAKE_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
345OPEN_HANDLE_LIST(MAKE_OPEN_HANDLE)
346
347#undef MAKE_OPEN_HANDLE
348#undef OPEN_HANDLE_LIST
349
350
351namespace internal {
352
353class 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.
388class 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
546const int kHandleBlockSize = v8::internal::KB - 2;  // fit in one page
547
548
549void HandleScopeImplementer::set_microtasks_policy(
550    v8::MicrotasksPolicy policy) {
551  microtasks_policy_ = policy;
552}
553
554
555v8::MicrotasksPolicy HandleScopeImplementer::microtasks_policy() const {
556  return microtasks_policy_;
557}
558
559
560void HandleScopeImplementer::SaveContext(Context* context) {
561  saved_contexts_.Add(context);
562}
563
564
565Context* HandleScopeImplementer::RestoreContext() {
566  return saved_contexts_.RemoveLast();
567}
568
569
570bool HandleScopeImplementer::HasSavedContexts() {
571  return !saved_contexts_.is_empty();
572}
573
574
575void HandleScopeImplementer::EnterContext(Handle<Context> context) {
576  entered_contexts_.Add(*context);
577}
578
579
580void HandleScopeImplementer::LeaveContext() {
581  entered_contexts_.RemoveLast();
582}
583
584
585bool HandleScopeImplementer::LastEnteredContextWas(Handle<Context> context) {
586  return !entered_contexts_.is_empty() && entered_contexts_.last() == *context;
587}
588
589
590Handle<Context> HandleScopeImplementer::LastEnteredContext() {
591  if (entered_contexts_.is_empty()) return Handle<Context>::null();
592  return Handle<Context>(entered_contexts_.last());
593}
594
595void HandleScopeImplementer::EnterMicrotaskContext(Handle<Context> context) {
596  DCHECK(!microtask_context_);
597  microtask_context_ = *context;
598  entered_context_count_during_microtasks_ = entered_contexts_.length();
599}
600
601void HandleScopeImplementer::LeaveMicrotaskContext() {
602  DCHECK(microtask_context_);
603  microtask_context_ = nullptr;
604  entered_context_count_during_microtasks_ = 0;
605}
606
607Handle<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.
613internal::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
622void 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.
651void InvokeAccessorGetterCallback(
652    v8::Local<v8::Name> property,
653    const v8::PropertyCallbackInfo<v8::Value>& info,
654    v8::AccessorNameGetterCallback getter);
655
656void InvokeFunctionCallback(const v8::FunctionCallbackInfo<v8::Value>& info,
657                            v8::FunctionCallback callback);
658
659class 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