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