Home | History | Annotate | Download | only in src
      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 "src/v8.h"
      9 
     10 #include "include/v8-testing.h"
     11 #include "src/contexts.h"
     12 #include "src/factory.h"
     13 #include "src/isolate.h"
     14 #include "src/list-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 
     30 
     31 // Utilities for working with neander-objects, primitive
     32 // env-independent JSObjects used by the api.
     33 class NeanderObject {
     34  public:
     35   explicit NeanderObject(v8::internal::Isolate* isolate, int size);
     36   explicit inline NeanderObject(v8::internal::Handle<v8::internal::Object> obj);
     37   explicit inline NeanderObject(v8::internal::Object* obj);
     38   inline v8::internal::Object* get(int index);
     39   inline void set(int index, v8::internal::Object* value);
     40   inline v8::internal::Handle<v8::internal::JSObject> value() { return value_; }
     41   int size();
     42  private:
     43   v8::internal::Handle<v8::internal::JSObject> value_;
     44 };
     45 
     46 
     47 // Utilities for working with neander-arrays, a simple extensible
     48 // array abstraction built on neander-objects.
     49 class NeanderArray {
     50  public:
     51   explicit NeanderArray(v8::internal::Isolate* isolate);
     52   explicit inline NeanderArray(v8::internal::Handle<v8::internal::Object> obj);
     53   inline v8::internal::Handle<v8::internal::JSObject> value() {
     54     return obj_.value();
     55   }
     56 
     57   void add(v8::internal::Handle<v8::internal::Object> value);
     58 
     59   int length();
     60 
     61   v8::internal::Object* get(int index);
     62   // Change the value at an index to undefined value. If the index is
     63   // out of bounds, the request is ignored. Returns the old value.
     64   void set(int index, v8::internal::Object* value);
     65  private:
     66   NeanderObject obj_;
     67 };
     68 
     69 
     70 NeanderObject::NeanderObject(v8::internal::Handle<v8::internal::Object> obj)
     71     : value_(v8::internal::Handle<v8::internal::JSObject>::cast(obj)) { }
     72 
     73 
     74 NeanderObject::NeanderObject(v8::internal::Object* obj)
     75     : value_(v8::internal::Handle<v8::internal::JSObject>(
     76         v8::internal::JSObject::cast(obj))) { }
     77 
     78 
     79 NeanderArray::NeanderArray(v8::internal::Handle<v8::internal::Object> obj)
     80     : obj_(obj) { }
     81 
     82 
     83 v8::internal::Object* NeanderObject::get(int offset) {
     84   DCHECK(value()->HasFastObjectElements());
     85   return v8::internal::FixedArray::cast(value()->elements())->get(offset);
     86 }
     87 
     88 
     89 void NeanderObject::set(int offset, v8::internal::Object* value) {
     90   DCHECK(value_->HasFastObjectElements());
     91   v8::internal::FixedArray::cast(value_->elements())->set(offset, value);
     92 }
     93 
     94 
     95 template <typename T> inline T ToCData(v8::internal::Object* obj) {
     96   STATIC_ASSERT(sizeof(T) == sizeof(v8::internal::Address));
     97   return reinterpret_cast<T>(
     98       reinterpret_cast<intptr_t>(
     99           v8::internal::Foreign::cast(obj)->foreign_address()));
    100 }
    101 
    102 
    103 template <typename T>
    104 inline v8::internal::Handle<v8::internal::Object> FromCData(
    105     v8::internal::Isolate* isolate, T obj) {
    106   STATIC_ASSERT(sizeof(T) == sizeof(v8::internal::Address));
    107   return isolate->factory()->NewForeign(
    108       reinterpret_cast<v8::internal::Address>(reinterpret_cast<intptr_t>(obj)));
    109 }
    110 
    111 
    112 class ApiFunction {
    113  public:
    114   explicit ApiFunction(v8::internal::Address addr) : addr_(addr) { }
    115   v8::internal::Address address() { return addr_; }
    116  private:
    117   v8::internal::Address addr_;
    118 };
    119 
    120 
    121 
    122 class RegisteredExtension {
    123  public:
    124   explicit RegisteredExtension(Extension* extension);
    125   static void Register(RegisteredExtension* that);
    126   static void UnregisterAll();
    127   Extension* extension() { return extension_; }
    128   RegisteredExtension* next() { return next_; }
    129   static RegisteredExtension* first_extension() { return first_extension_; }
    130  private:
    131   Extension* extension_;
    132   RegisteredExtension* next_;
    133   static RegisteredExtension* first_extension_;
    134 };
    135 
    136 
    137 #define OPEN_HANDLE_LIST(V)                    \
    138   V(Template, TemplateInfo)                    \
    139   V(FunctionTemplate, FunctionTemplateInfo)    \
    140   V(ObjectTemplate, ObjectTemplateInfo)        \
    141   V(Signature, SignatureInfo)                  \
    142   V(AccessorSignature, FunctionTemplateInfo)   \
    143   V(TypeSwitch, TypeSwitchInfo)                \
    144   V(Data, Object)                              \
    145   V(RegExp, JSRegExp)                          \
    146   V(Object, JSObject)                          \
    147   V(Array, JSArray)                            \
    148   V(ArrayBuffer, JSArrayBuffer)                \
    149   V(ArrayBufferView, JSArrayBufferView)        \
    150   V(TypedArray, JSTypedArray)                  \
    151   V(Uint8Array, JSTypedArray)                  \
    152   V(Uint8ClampedArray, JSTypedArray)           \
    153   V(Int8Array, JSTypedArray)                   \
    154   V(Uint16Array, JSTypedArray)                 \
    155   V(Int16Array, JSTypedArray)                  \
    156   V(Uint32Array, JSTypedArray)                 \
    157   V(Int32Array, JSTypedArray)                  \
    158   V(Float32Array, JSTypedArray)                \
    159   V(Float64Array, JSTypedArray)                \
    160   V(DataView, JSDataView)                      \
    161   V(Name, Name)                                \
    162   V(String, String)                            \
    163   V(Symbol, Symbol)                            \
    164   V(Script, JSFunction)                        \
    165   V(UnboundScript, SharedFunctionInfo)         \
    166   V(Function, JSFunction)                      \
    167   V(Message, JSMessageObject)                  \
    168   V(Context, Context)                          \
    169   V(External, Object)                          \
    170   V(StackTrace, JSArray)                       \
    171   V(StackFrame, JSObject)                      \
    172   V(DeclaredAccessorDescriptor, DeclaredAccessorDescriptor)
    173 
    174 
    175 class Utils {
    176  public:
    177   static inline bool ApiCheck(bool condition,
    178                               const char* location,
    179                               const char* message) {
    180     if (!condition) Utils::ReportApiFailure(location, message);
    181     return condition;
    182   }
    183 
    184   static Local<FunctionTemplate> ToFunctionTemplate(NeanderObject obj);
    185   static Local<ObjectTemplate> ToObjectTemplate(NeanderObject obj);
    186 
    187   static inline Local<Context> ToLocal(
    188       v8::internal::Handle<v8::internal::Context> obj);
    189   static inline Local<Value> ToLocal(
    190       v8::internal::Handle<v8::internal::Object> obj);
    191   static inline Local<Function> ToLocal(
    192       v8::internal::Handle<v8::internal::JSFunction> obj);
    193   static inline Local<Name> ToLocal(
    194       v8::internal::Handle<v8::internal::Name> obj);
    195   static inline Local<String> ToLocal(
    196       v8::internal::Handle<v8::internal::String> obj);
    197   static inline Local<Symbol> ToLocal(
    198       v8::internal::Handle<v8::internal::Symbol> obj);
    199   static inline Local<RegExp> ToLocal(
    200       v8::internal::Handle<v8::internal::JSRegExp> obj);
    201   static inline Local<Object> ToLocal(
    202       v8::internal::Handle<v8::internal::JSObject> obj);
    203   static inline Local<Array> ToLocal(
    204       v8::internal::Handle<v8::internal::JSArray> obj);
    205   static inline Local<ArrayBuffer> ToLocal(
    206       v8::internal::Handle<v8::internal::JSArrayBuffer> obj);
    207   static inline Local<ArrayBufferView> ToLocal(
    208       v8::internal::Handle<v8::internal::JSArrayBufferView> obj);
    209   static inline Local<DataView> ToLocal(
    210       v8::internal::Handle<v8::internal::JSDataView> obj);
    211 
    212   static inline Local<TypedArray> ToLocal(
    213       v8::internal::Handle<v8::internal::JSTypedArray> obj);
    214   static inline Local<Uint8Array> ToLocalUint8Array(
    215       v8::internal::Handle<v8::internal::JSTypedArray> obj);
    216   static inline Local<Uint8ClampedArray> ToLocalUint8ClampedArray(
    217       v8::internal::Handle<v8::internal::JSTypedArray> obj);
    218   static inline Local<Int8Array> ToLocalInt8Array(
    219       v8::internal::Handle<v8::internal::JSTypedArray> obj);
    220   static inline Local<Uint16Array> ToLocalUint16Array(
    221       v8::internal::Handle<v8::internal::JSTypedArray> obj);
    222   static inline Local<Int16Array> ToLocalInt16Array(
    223       v8::internal::Handle<v8::internal::JSTypedArray> obj);
    224   static inline Local<Uint32Array> ToLocalUint32Array(
    225       v8::internal::Handle<v8::internal::JSTypedArray> obj);
    226   static inline Local<Int32Array> ToLocalInt32Array(
    227       v8::internal::Handle<v8::internal::JSTypedArray> obj);
    228   static inline Local<Float32Array> ToLocalFloat32Array(
    229       v8::internal::Handle<v8::internal::JSTypedArray> obj);
    230   static inline Local<Float64Array> ToLocalFloat64Array(
    231       v8::internal::Handle<v8::internal::JSTypedArray> obj);
    232 
    233   static inline Local<Message> MessageToLocal(
    234       v8::internal::Handle<v8::internal::Object> obj);
    235   static inline Local<StackTrace> StackTraceToLocal(
    236       v8::internal::Handle<v8::internal::JSArray> obj);
    237   static inline Local<StackFrame> StackFrameToLocal(
    238       v8::internal::Handle<v8::internal::JSObject> obj);
    239   static inline Local<Number> NumberToLocal(
    240       v8::internal::Handle<v8::internal::Object> obj);
    241   static inline Local<Integer> IntegerToLocal(
    242       v8::internal::Handle<v8::internal::Object> obj);
    243   static inline Local<Uint32> Uint32ToLocal(
    244       v8::internal::Handle<v8::internal::Object> obj);
    245   static inline Local<FunctionTemplate> ToLocal(
    246       v8::internal::Handle<v8::internal::FunctionTemplateInfo> obj);
    247   static inline Local<ObjectTemplate> ToLocal(
    248       v8::internal::Handle<v8::internal::ObjectTemplateInfo> obj);
    249   static inline Local<Signature> ToLocal(
    250       v8::internal::Handle<v8::internal::SignatureInfo> obj);
    251   static inline Local<AccessorSignature> AccessorSignatureToLocal(
    252       v8::internal::Handle<v8::internal::FunctionTemplateInfo> obj);
    253   static inline Local<TypeSwitch> ToLocal(
    254       v8::internal::Handle<v8::internal::TypeSwitchInfo> obj);
    255   static inline Local<External> ExternalToLocal(
    256       v8::internal::Handle<v8::internal::JSObject> obj);
    257   static inline Local<DeclaredAccessorDescriptor> ToLocal(
    258       v8::internal::Handle<v8::internal::DeclaredAccessorDescriptor> obj);
    259 
    260 #define DECLARE_OPEN_HANDLE(From, To) \
    261   static inline v8::internal::Handle<v8::internal::To> \
    262       OpenHandle(const From* that, bool allow_empty_handle = false);
    263 
    264 OPEN_HANDLE_LIST(DECLARE_OPEN_HANDLE)
    265 
    266 #undef DECLARE_OPEN_HANDLE
    267 
    268   template<class From, class To>
    269   static inline Local<To> Convert(v8::internal::Handle<From> obj) {
    270     DCHECK(obj.is_null() || !obj->IsTheHole());
    271     return Local<To>(reinterpret_cast<To*>(obj.location()));
    272   }
    273 
    274   template <class T>
    275   static inline v8::internal::Handle<v8::internal::Object> OpenPersistent(
    276       const v8::Persistent<T>& persistent) {
    277     return v8::internal::Handle<v8::internal::Object>(
    278         reinterpret_cast<v8::internal::Object**>(persistent.val_));
    279   }
    280 
    281   template <class T>
    282   static inline v8::internal::Handle<v8::internal::Object> OpenPersistent(
    283       v8::Persistent<T>* persistent) {
    284     return OpenPersistent(*persistent);
    285   }
    286 
    287   template <class From, class To>
    288   static inline v8::internal::Handle<To> OpenHandle(v8::Local<From> handle) {
    289     return OpenHandle(*handle);
    290   }
    291 
    292  private:
    293   static void ReportApiFailure(const char* location, const char* message);
    294 };
    295 
    296 
    297 template <class T>
    298 v8::internal::Handle<T> v8::internal::Handle<T>::EscapeFrom(
    299     v8::EscapableHandleScope* scope) {
    300   v8::internal::Handle<T> handle;
    301   if (!is_null()) {
    302     handle = *this;
    303   }
    304   return Utils::OpenHandle(*scope->Escape(Utils::ToLocal(handle)), true);
    305 }
    306 
    307 
    308 template <class T>
    309 inline T* ToApi(v8::internal::Handle<v8::internal::Object> obj) {
    310   return reinterpret_cast<T*>(obj.location());
    311 }
    312 
    313 template <class T>
    314 inline v8::Local<T> ToApiHandle(
    315     v8::internal::Handle<v8::internal::Object> obj) {
    316   return Utils::Convert<v8::internal::Object, T>(obj);
    317 }
    318 
    319 
    320 // Implementations of ToLocal
    321 
    322 #define MAKE_TO_LOCAL(Name, From, To)                                       \
    323   Local<v8::To> Utils::Name(v8::internal::Handle<v8::internal::From> obj) { \
    324     return Convert<v8::internal::From, v8::To>(obj);  \
    325   }
    326 
    327 
    328 #define MAKE_TO_LOCAL_TYPED_ARRAY(Type, typeName, TYPE, ctype, size)        \
    329   Local<v8::Type##Array> Utils::ToLocal##Type##Array(                       \
    330       v8::internal::Handle<v8::internal::JSTypedArray> obj) {               \
    331     DCHECK(obj->type() == kExternal##Type##Array);                          \
    332     return Convert<v8::internal::JSTypedArray, v8::Type##Array>(obj);       \
    333   }
    334 
    335 
    336 MAKE_TO_LOCAL(ToLocal, Context, Context)
    337 MAKE_TO_LOCAL(ToLocal, Object, Value)
    338 MAKE_TO_LOCAL(ToLocal, JSFunction, Function)
    339 MAKE_TO_LOCAL(ToLocal, Name, Name)
    340 MAKE_TO_LOCAL(ToLocal, String, String)
    341 MAKE_TO_LOCAL(ToLocal, Symbol, Symbol)
    342 MAKE_TO_LOCAL(ToLocal, JSRegExp, RegExp)
    343 MAKE_TO_LOCAL(ToLocal, JSObject, Object)
    344 MAKE_TO_LOCAL(ToLocal, JSArray, Array)
    345 MAKE_TO_LOCAL(ToLocal, JSArrayBuffer, ArrayBuffer)
    346 MAKE_TO_LOCAL(ToLocal, JSArrayBufferView, ArrayBufferView)
    347 MAKE_TO_LOCAL(ToLocal, JSDataView, DataView)
    348 MAKE_TO_LOCAL(ToLocal, JSTypedArray, TypedArray)
    349 
    350 TYPED_ARRAYS(MAKE_TO_LOCAL_TYPED_ARRAY)
    351 
    352 MAKE_TO_LOCAL(ToLocal, FunctionTemplateInfo, FunctionTemplate)
    353 MAKE_TO_LOCAL(ToLocal, ObjectTemplateInfo, ObjectTemplate)
    354 MAKE_TO_LOCAL(ToLocal, SignatureInfo, Signature)
    355 MAKE_TO_LOCAL(AccessorSignatureToLocal, FunctionTemplateInfo, AccessorSignature)
    356 MAKE_TO_LOCAL(ToLocal, TypeSwitchInfo, TypeSwitch)
    357 MAKE_TO_LOCAL(MessageToLocal, Object, Message)
    358 MAKE_TO_LOCAL(StackTraceToLocal, JSArray, StackTrace)
    359 MAKE_TO_LOCAL(StackFrameToLocal, JSObject, StackFrame)
    360 MAKE_TO_LOCAL(NumberToLocal, Object, Number)
    361 MAKE_TO_LOCAL(IntegerToLocal, Object, Integer)
    362 MAKE_TO_LOCAL(Uint32ToLocal, Object, Uint32)
    363 MAKE_TO_LOCAL(ExternalToLocal, JSObject, External)
    364 MAKE_TO_LOCAL(ToLocal, DeclaredAccessorDescriptor, DeclaredAccessorDescriptor)
    365 
    366 #undef MAKE_TO_LOCAL_TYPED_ARRAY
    367 #undef MAKE_TO_LOCAL
    368 
    369 
    370 // Implementations of OpenHandle
    371 
    372 #define MAKE_OPEN_HANDLE(From, To)                                          \
    373   v8::internal::Handle<v8::internal::To> Utils::OpenHandle(                 \
    374     const v8::From* that, bool allow_empty_handle) {                        \
    375     EXTRA_CHECK(allow_empty_handle || that != NULL);                        \
    376     EXTRA_CHECK(that == NULL ||                                             \
    377         (*reinterpret_cast<v8::internal::Object* const*>(that))->Is##To()); \
    378     return v8::internal::Handle<v8::internal::To>(                          \
    379         reinterpret_cast<v8::internal::To**>(const_cast<v8::From*>(that))); \
    380   }
    381 
    382 OPEN_HANDLE_LIST(MAKE_OPEN_HANDLE)
    383 
    384 #undef MAKE_OPEN_HANDLE
    385 #undef OPEN_HANDLE_LIST
    386 
    387 
    388 namespace internal {
    389 
    390 // Tracks string usage to help make better decisions when
    391 // externalizing strings.
    392 //
    393 // Implementation note: internally this class only tracks fresh
    394 // strings and keeps a single use counter for them.
    395 class StringTracker {
    396  public:
    397   // Records that the given string's characters were copied to some
    398   // external buffer. If this happens often we should honor
    399   // externalization requests for the string.
    400   void RecordWrite(Handle<String> string) {
    401     Address address = reinterpret_cast<Address>(*string);
    402     Address top = isolate_->heap()->NewSpaceTop();
    403     if (IsFreshString(address, top)) {
    404       IncrementUseCount(top);
    405     }
    406   }
    407 
    408   // Estimates freshness and use frequency of the given string based
    409   // on how close it is to the new space top and the recorded usage
    410   // history.
    411   inline bool IsFreshUnusedString(Handle<String> string) {
    412     Address address = reinterpret_cast<Address>(*string);
    413     Address top = isolate_->heap()->NewSpaceTop();
    414     return IsFreshString(address, top) && IsUseCountLow(top);
    415   }
    416 
    417  private:
    418   StringTracker() : use_count_(0), last_top_(NULL), isolate_(NULL) { }
    419 
    420   static inline bool IsFreshString(Address string, Address top) {
    421     return top - kFreshnessLimit <= string && string <= top;
    422   }
    423 
    424   inline bool IsUseCountLow(Address top) {
    425     if (last_top_ != top) return true;
    426     return use_count_ < kUseLimit;
    427   }
    428 
    429   inline void IncrementUseCount(Address top) {
    430     if (last_top_ != top) {
    431       use_count_ = 0;
    432       last_top_ = top;
    433     }
    434     ++use_count_;
    435   }
    436 
    437   // Single use counter shared by all fresh strings.
    438   int use_count_;
    439 
    440   // Last new space top when the use count above was valid.
    441   Address last_top_;
    442 
    443   Isolate* isolate_;
    444 
    445   // How close to the new space top a fresh string has to be.
    446   static const int kFreshnessLimit = 1024;
    447 
    448   // The number of uses required to consider a string useful.
    449   static const int kUseLimit = 32;
    450 
    451   friend class Isolate;
    452 
    453   DISALLOW_COPY_AND_ASSIGN(StringTracker);
    454 };
    455 
    456 
    457 class DeferredHandles {
    458  public:
    459   ~DeferredHandles();
    460 
    461  private:
    462   DeferredHandles(Object** first_block_limit, Isolate* isolate)
    463       : next_(NULL),
    464         previous_(NULL),
    465         first_block_limit_(first_block_limit),
    466         isolate_(isolate) {
    467     isolate->LinkDeferredHandles(this);
    468   }
    469 
    470   void Iterate(ObjectVisitor* v);
    471 
    472   List<Object**> blocks_;
    473   DeferredHandles* next_;
    474   DeferredHandles* previous_;
    475   Object** first_block_limit_;
    476   Isolate* isolate_;
    477 
    478   friend class HandleScopeImplementer;
    479   friend class Isolate;
    480 };
    481 
    482 
    483 // This class is here in order to be able to declare it a friend of
    484 // HandleScope.  Moving these methods to be members of HandleScope would be
    485 // neat in some ways, but it would expose internal implementation details in
    486 // our public header file, which is undesirable.
    487 //
    488 // An isolate has a single instance of this class to hold the current thread's
    489 // data. In multithreaded V8 programs this data is copied in and out of storage
    490 // so that the currently executing thread always has its own copy of this
    491 // data.
    492 class HandleScopeImplementer {
    493  public:
    494   explicit HandleScopeImplementer(Isolate* isolate)
    495       : isolate_(isolate),
    496         blocks_(0),
    497         entered_contexts_(0),
    498         saved_contexts_(0),
    499         spare_(NULL),
    500         call_depth_(0),
    501         last_handle_before_deferred_block_(NULL) { }
    502 
    503   ~HandleScopeImplementer() {
    504     DeleteArray(spare_);
    505   }
    506 
    507   // Threading support for handle data.
    508   static int ArchiveSpacePerThread();
    509   char* RestoreThread(char* from);
    510   char* ArchiveThread(char* to);
    511   void FreeThreadResources();
    512 
    513   // Garbage collection support.
    514   void Iterate(v8::internal::ObjectVisitor* v);
    515   static char* Iterate(v8::internal::ObjectVisitor* v, char* data);
    516 
    517 
    518   inline internal::Object** GetSpareOrNewBlock();
    519   inline void DeleteExtensions(internal::Object** prev_limit);
    520 
    521   inline void IncrementCallDepth() {call_depth_++;}
    522   inline void DecrementCallDepth() {call_depth_--;}
    523   inline bool CallDepthIsZero() { return call_depth_ == 0; }
    524 
    525   inline void EnterContext(Handle<Context> context);
    526   inline void LeaveContext();
    527   inline bool LastEnteredContextWas(Handle<Context> context);
    528 
    529   // Returns the last entered context or an empty handle if no
    530   // contexts have been entered.
    531   inline Handle<Context> LastEnteredContext();
    532 
    533   inline void SaveContext(Context* context);
    534   inline Context* RestoreContext();
    535   inline bool HasSavedContexts();
    536 
    537   inline List<internal::Object**>* blocks() { return &blocks_; }
    538   Isolate* isolate() const { return isolate_; }
    539 
    540   void ReturnBlock(Object** block) {
    541     DCHECK(block != NULL);
    542     if (spare_ != NULL) DeleteArray(spare_);
    543     spare_ = block;
    544   }
    545 
    546  private:
    547   void ResetAfterArchive() {
    548     blocks_.Initialize(0);
    549     entered_contexts_.Initialize(0);
    550     saved_contexts_.Initialize(0);
    551     spare_ = NULL;
    552     last_handle_before_deferred_block_ = NULL;
    553     call_depth_ = 0;
    554   }
    555 
    556   void Free() {
    557     DCHECK(blocks_.length() == 0);
    558     DCHECK(entered_contexts_.length() == 0);
    559     DCHECK(saved_contexts_.length() == 0);
    560     blocks_.Free();
    561     entered_contexts_.Free();
    562     saved_contexts_.Free();
    563     if (spare_ != NULL) {
    564       DeleteArray(spare_);
    565       spare_ = NULL;
    566     }
    567     DCHECK(call_depth_ == 0);
    568   }
    569 
    570   void BeginDeferredScope();
    571   DeferredHandles* Detach(Object** prev_limit);
    572 
    573   Isolate* isolate_;
    574   List<internal::Object**> blocks_;
    575   // Used as a stack to keep track of entered contexts.
    576   List<Context*> entered_contexts_;
    577   // Used as a stack to keep track of saved contexts.
    578   List<Context*> saved_contexts_;
    579   Object** spare_;
    580   int call_depth_;
    581   Object** last_handle_before_deferred_block_;
    582   // This is only used for threading support.
    583   HandleScopeData handle_scope_data_;
    584 
    585   void IterateThis(ObjectVisitor* v);
    586   char* RestoreThreadHelper(char* from);
    587   char* ArchiveThreadHelper(char* to);
    588 
    589   friend class DeferredHandles;
    590   friend class DeferredHandleScope;
    591 
    592   DISALLOW_COPY_AND_ASSIGN(HandleScopeImplementer);
    593 };
    594 
    595 
    596 const int kHandleBlockSize = v8::internal::KB - 2;  // fit in one page
    597 
    598 
    599 void HandleScopeImplementer::SaveContext(Context* context) {
    600   saved_contexts_.Add(context);
    601 }
    602 
    603 
    604 Context* HandleScopeImplementer::RestoreContext() {
    605   return saved_contexts_.RemoveLast();
    606 }
    607 
    608 
    609 bool HandleScopeImplementer::HasSavedContexts() {
    610   return !saved_contexts_.is_empty();
    611 }
    612 
    613 
    614 void HandleScopeImplementer::EnterContext(Handle<Context> context) {
    615   entered_contexts_.Add(*context);
    616 }
    617 
    618 
    619 void HandleScopeImplementer::LeaveContext() {
    620   entered_contexts_.RemoveLast();
    621 }
    622 
    623 
    624 bool HandleScopeImplementer::LastEnteredContextWas(Handle<Context> context) {
    625   return !entered_contexts_.is_empty() && entered_contexts_.last() == *context;
    626 }
    627 
    628 
    629 Handle<Context> HandleScopeImplementer::LastEnteredContext() {
    630   if (entered_contexts_.is_empty()) return Handle<Context>::null();
    631   return Handle<Context>(entered_contexts_.last());
    632 }
    633 
    634 
    635 // If there's a spare block, use it for growing the current scope.
    636 internal::Object** HandleScopeImplementer::GetSpareOrNewBlock() {
    637   internal::Object** block = (spare_ != NULL) ?
    638       spare_ :
    639       NewArray<internal::Object*>(kHandleBlockSize);
    640   spare_ = NULL;
    641   return block;
    642 }
    643 
    644 
    645 void HandleScopeImplementer::DeleteExtensions(internal::Object** prev_limit) {
    646   while (!blocks_.is_empty()) {
    647     internal::Object** block_start = blocks_.last();
    648     internal::Object** block_limit = block_start + kHandleBlockSize;
    649 #ifdef DEBUG
    650     // SealHandleScope may make the prev_limit to point inside the block.
    651     if (block_start <= prev_limit && prev_limit <= block_limit) {
    652 #ifdef ENABLE_HANDLE_ZAPPING
    653       internal::HandleScope::ZapRange(prev_limit, block_limit);
    654 #endif
    655       break;
    656     }
    657 #else
    658     if (prev_limit == block_limit) break;
    659 #endif
    660 
    661     blocks_.RemoveLast();
    662 #ifdef ENABLE_HANDLE_ZAPPING
    663     internal::HandleScope::ZapRange(block_start, block_limit);
    664 #endif
    665     if (spare_ != NULL) {
    666       DeleteArray(spare_);
    667     }
    668     spare_ = block_start;
    669   }
    670   DCHECK((blocks_.is_empty() && prev_limit == NULL) ||
    671          (!blocks_.is_empty() && prev_limit != NULL));
    672 }
    673 
    674 
    675 // Interceptor functions called from generated inline caches to notify
    676 // CPU profiler that external callbacks are invoked.
    677 void InvokeAccessorGetterCallback(
    678     v8::Local<v8::Name> property,
    679     const v8::PropertyCallbackInfo<v8::Value>& info,
    680     v8::AccessorNameGetterCallback getter);
    681 
    682 void InvokeFunctionCallback(const v8::FunctionCallbackInfo<v8::Value>& info,
    683                             v8::FunctionCallback callback);
    684 
    685 class Testing {
    686  public:
    687   static v8::Testing::StressType stress_type() { return stress_type_; }
    688   static void set_stress_type(v8::Testing::StressType stress_type) {
    689     stress_type_ = stress_type;
    690   }
    691 
    692  private:
    693   static v8::Testing::StressType stress_type_;
    694 };
    695 
    696 } }  // namespace v8::internal
    697 
    698 #endif  // V8_API_H_
    699