Home | History | Annotate | Download | only in src
      1 // Copyright 2006-2008 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_HANDLES_H_
     29 #define V8_HANDLES_H_
     30 
     31 #include "apiutils.h"
     32 
     33 namespace v8 {
     34 namespace internal {
     35 
     36 // ----------------------------------------------------------------------------
     37 // A Handle provides a reference to an object that survives relocation by
     38 // the garbage collector.
     39 // Handles are only valid within a HandleScope.
     40 // When a handle is created for an object a cell is allocated in the heap.
     41 
     42 template<class T>
     43 class Handle {
     44  public:
     45   INLINE(Handle(T** location)) { location_ = location; }
     46   INLINE(explicit Handle(T* obj));
     47 
     48   INLINE(Handle()) : location_(NULL) {}
     49 
     50   // Constructor for handling automatic up casting.
     51   // Ex. Handle<JSFunction> can be passed when Handle<Object> is expected.
     52   template <class S> Handle(Handle<S> handle) {
     53 #ifdef DEBUG
     54     T* a = NULL;
     55     S* b = NULL;
     56     a = b;  // Fake assignment to enforce type checks.
     57     USE(a);
     58 #endif
     59     location_ = reinterpret_cast<T**>(handle.location());
     60   }
     61 
     62   INLINE(T* operator ->() const) { return operator*(); }
     63 
     64   // Check if this handle refers to the exact same object as the other handle.
     65   bool is_identical_to(const Handle<T> other) const {
     66     return operator*() == *other;
     67   }
     68 
     69   // Provides the C++ dereference operator.
     70   INLINE(T* operator*() const);
     71 
     72   // Returns the address to where the raw pointer is stored.
     73   T** location() const {
     74     ASSERT(location_ == NULL ||
     75            reinterpret_cast<Address>(*location_) != kZapValue);
     76     return location_;
     77   }
     78 
     79   template <class S> static Handle<T> cast(Handle<S> that) {
     80     T::cast(*that);
     81     return Handle<T>(reinterpret_cast<T**>(that.location()));
     82   }
     83 
     84   static Handle<T> null() { return Handle<T>(); }
     85   bool is_null() { return location_ == NULL; }
     86 
     87   // Closes the given scope, but lets this handle escape. See
     88   // implementation in api.h.
     89   inline Handle<T> EscapeFrom(v8::HandleScope* scope);
     90 
     91  private:
     92   T** location_;
     93 };
     94 
     95 
     96 // A stack-allocated class that governs a number of local handles.
     97 // After a handle scope has been created, all local handles will be
     98 // allocated within that handle scope until either the handle scope is
     99 // deleted or another handle scope is created.  If there is already a
    100 // handle scope and a new one is created, all allocations will take
    101 // place in the new handle scope until it is deleted.  After that,
    102 // new handles will again be allocated in the original handle scope.
    103 //
    104 // After the handle scope of a local handle has been deleted the
    105 // garbage collector will no longer track the object stored in the
    106 // handle and may deallocate it.  The behavior of accessing a handle
    107 // for which the handle scope has been deleted is undefined.
    108 class HandleScope {
    109  public:
    110   HandleScope() : previous_(current_) {
    111     current_.extensions = 0;
    112   }
    113 
    114   ~HandleScope() {
    115     Leave(&previous_);
    116   }
    117 
    118   // Counts the number of allocated handles.
    119   static int NumberOfHandles();
    120 
    121   // Creates a new handle with the given value.
    122   template <typename T>
    123   static inline T** CreateHandle(T* value) {
    124     internal::Object** cur = current_.next;
    125     if (cur == current_.limit) cur = Extend();
    126     // Update the current next field, set the value in the created
    127     // handle, and return the result.
    128     ASSERT(cur < current_.limit);
    129     current_.next = cur + 1;
    130 
    131     T** result = reinterpret_cast<T**>(cur);
    132     *result = value;
    133     return result;
    134   }
    135 
    136   // Deallocates any extensions used by the current scope.
    137   static void DeleteExtensions();
    138 
    139   static Address current_extensions_address();
    140   static Address current_next_address();
    141   static Address current_limit_address();
    142 
    143  private:
    144   // Prevent heap allocation or illegal handle scopes.
    145   HandleScope(const HandleScope&);
    146   void operator=(const HandleScope&);
    147   void* operator new(size_t size);
    148   void operator delete(void* size_t);
    149 
    150   static v8::ImplementationUtilities::HandleScopeData current_;
    151   const v8::ImplementationUtilities::HandleScopeData previous_;
    152 
    153   // Pushes a fresh handle scope to be used when allocating new handles.
    154   static void Enter(
    155       v8::ImplementationUtilities::HandleScopeData* previous) {
    156     *previous = current_;
    157     current_.extensions = 0;
    158   }
    159 
    160   // Re-establishes the previous scope state. Should be called only
    161   // once, and only for the current scope.
    162   static void Leave(
    163       const v8::ImplementationUtilities::HandleScopeData* previous) {
    164     if (current_.extensions > 0) {
    165       DeleteExtensions();
    166     }
    167     current_ = *previous;
    168 #ifdef DEBUG
    169     ZapRange(current_.next, current_.limit);
    170 #endif
    171   }
    172 
    173   // Extend the handle scope making room for more handles.
    174   static internal::Object** Extend();
    175 
    176   // Zaps the handles in the half-open interval [start, end).
    177   static void ZapRange(internal::Object** start, internal::Object** end);
    178 
    179   friend class v8::HandleScope;
    180   friend class v8::ImplementationUtilities;
    181 };
    182 
    183 
    184 // ----------------------------------------------------------------------------
    185 // Handle operations.
    186 // They might invoke garbage collection. The result is an handle to
    187 // an object of expected type, or the handle is an error if running out
    188 // of space or encountering an internal error.
    189 
    190 void NormalizeProperties(Handle<JSObject> object,
    191                          PropertyNormalizationMode mode,
    192                          int expected_additional_properties);
    193 void NormalizeElements(Handle<JSObject> object);
    194 void TransformToFastProperties(Handle<JSObject> object,
    195                                int unused_property_fields);
    196 void FlattenString(Handle<String> str);
    197 
    198 Handle<Object> SetProperty(Handle<JSObject> object,
    199                            Handle<String> key,
    200                            Handle<Object> value,
    201                            PropertyAttributes attributes);
    202 
    203 Handle<Object> SetProperty(Handle<Object> object,
    204                            Handle<Object> key,
    205                            Handle<Object> value,
    206                            PropertyAttributes attributes);
    207 
    208 Handle<Object> ForceSetProperty(Handle<JSObject> object,
    209                                 Handle<Object> key,
    210                                 Handle<Object> value,
    211                                 PropertyAttributes attributes);
    212 
    213 Handle<Object> SetNormalizedProperty(Handle<JSObject> object,
    214                                      Handle<String> key,
    215                                      Handle<Object> value,
    216                                      PropertyDetails details);
    217 
    218 Handle<Object> ForceDeleteProperty(Handle<JSObject> object,
    219                                    Handle<Object> key);
    220 
    221 Handle<Object> IgnoreAttributesAndSetLocalProperty(Handle<JSObject> object,
    222                                                    Handle<String> key,
    223                                                    Handle<Object> value,
    224     PropertyAttributes attributes);
    225 
    226 Handle<Object> SetPropertyWithInterceptor(Handle<JSObject> object,
    227                                           Handle<String> key,
    228                                           Handle<Object> value,
    229                                           PropertyAttributes attributes);
    230 
    231 Handle<Object> SetElement(Handle<JSObject> object,
    232                           uint32_t index,
    233                           Handle<Object> value);
    234 
    235 Handle<Object> GetProperty(Handle<JSObject> obj,
    236                            const char* name);
    237 
    238 Handle<Object> GetProperty(Handle<Object> obj,
    239                            Handle<Object> key);
    240 
    241 Handle<Object> GetPropertyWithInterceptor(Handle<JSObject> receiver,
    242                                           Handle<JSObject> holder,
    243                                           Handle<String> name,
    244                                           PropertyAttributes* attributes);
    245 
    246 Handle<Object> GetPrototype(Handle<Object> obj);
    247 
    248 Handle<Object> SetPrototype(Handle<JSObject> obj, Handle<Object> value);
    249 
    250 // Return the object's hidden properties object. If the object has no hidden
    251 // properties and create_if_needed is true, then a new hidden property object
    252 // will be allocated. Otherwise the Heap::undefined_value is returned.
    253 Handle<Object> GetHiddenProperties(Handle<JSObject> obj, bool create_if_needed);
    254 
    255 Handle<Object> DeleteElement(Handle<JSObject> obj, uint32_t index);
    256 Handle<Object> DeleteProperty(Handle<JSObject> obj, Handle<String> prop);
    257 
    258 Handle<Object> LookupSingleCharacterStringFromCode(uint32_t index);
    259 
    260 Handle<JSObject> Copy(Handle<JSObject> obj);
    261 
    262 Handle<FixedArray> AddKeysFromJSArray(Handle<FixedArray>,
    263                                       Handle<JSArray> array);
    264 
    265 // Get the JS object corresponding to the given script; create it
    266 // if none exists.
    267 Handle<JSValue> GetScriptWrapper(Handle<Script> script);
    268 
    269 // Script line number computations.
    270 void InitScriptLineEnds(Handle<Script> script);
    271 int GetScriptLineNumber(Handle<Script> script, int code_position);
    272 
    273 // Computes the enumerable keys from interceptors. Used for debug mirrors and
    274 // by GetKeysInFixedArrayFor below.
    275 v8::Handle<v8::Array> GetKeysForNamedInterceptor(Handle<JSObject> receiver,
    276                                                  Handle<JSObject> object);
    277 v8::Handle<v8::Array> GetKeysForIndexedInterceptor(Handle<JSObject> receiver,
    278                                                    Handle<JSObject> object);
    279 
    280 enum KeyCollectionType { LOCAL_ONLY, INCLUDE_PROTOS };
    281 
    282 // Computes the enumerable keys for a JSObject. Used for implementing
    283 // "for (n in object) { }".
    284 Handle<FixedArray> GetKeysInFixedArrayFor(Handle<JSObject> object,
    285                                           KeyCollectionType type);
    286 Handle<JSArray> GetKeysFor(Handle<JSObject> object);
    287 Handle<FixedArray> GetEnumPropertyKeys(Handle<JSObject> object,
    288                                        bool cache_result);
    289 
    290 // Computes the union of keys and return the result.
    291 // Used for implementing "for (n in object) { }"
    292 Handle<FixedArray> UnionOfKeys(Handle<FixedArray> first,
    293                                Handle<FixedArray> second);
    294 
    295 Handle<String> SubString(Handle<String> str, int start, int end);
    296 
    297 
    298 // Sets the expected number of properties for the function's instances.
    299 void SetExpectedNofProperties(Handle<JSFunction> func, int nof);
    300 
    301 // Sets the prototype property for a function instance.
    302 void SetPrototypeProperty(Handle<JSFunction> func, Handle<JSObject> value);
    303 
    304 // Sets the expected number of properties based on estimate from compiler.
    305 void SetExpectedNofPropertiesFromEstimate(Handle<SharedFunctionInfo> shared,
    306                                           int estimate);
    307 void SetExpectedNofPropertiesFromEstimate(Handle<JSFunction> func,
    308                                           int estimate);
    309 
    310 
    311 Handle<JSGlobalProxy> ReinitializeJSGlobalProxy(
    312     Handle<JSFunction> constructor,
    313     Handle<JSGlobalProxy> global);
    314 
    315 Handle<Object> SetPrototype(Handle<JSFunction> function,
    316                             Handle<Object> prototype);
    317 
    318 
    319 // Does lazy compilation of the given function. Returns true on success and
    320 // false if the compilation resulted in a stack overflow.
    321 enum ClearExceptionFlag { KEEP_EXCEPTION, CLEAR_EXCEPTION };
    322 
    323 bool EnsureCompiled(Handle<SharedFunctionInfo> shared,
    324                     ClearExceptionFlag flag);
    325 
    326 bool CompileLazyShared(Handle<SharedFunctionInfo> shared,
    327                        ClearExceptionFlag flag);
    328 
    329 bool CompileLazy(Handle<JSFunction> function,
    330                  Handle<Object> receiver,
    331                  ClearExceptionFlag flag);
    332 
    333 bool CompileLazyInLoop(Handle<JSFunction> function,
    334                        Handle<Object> receiver,
    335                        ClearExceptionFlag flag);
    336 
    337 // Returns the lazy compilation stub for argc arguments.
    338 Handle<Code> ComputeLazyCompile(int argc);
    339 
    340 class NoHandleAllocation BASE_EMBEDDED {
    341  public:
    342 #ifndef DEBUG
    343   NoHandleAllocation() {}
    344   ~NoHandleAllocation() {}
    345 #else
    346   inline NoHandleAllocation();
    347   inline ~NoHandleAllocation();
    348  private:
    349   int extensions_;
    350 #endif
    351 };
    352 
    353 
    354 // ----------------------------------------------------------------------------
    355 
    356 
    357 // Stack allocated wrapper call for optimizing adding multiple
    358 // properties to an object.
    359 class OptimizedObjectForAddingMultipleProperties BASE_EMBEDDED {
    360  public:
    361   OptimizedObjectForAddingMultipleProperties(Handle<JSObject> object,
    362                                              int expected_property_count,
    363                                              bool condition = true);
    364   ~OptimizedObjectForAddingMultipleProperties();
    365  private:
    366   bool has_been_transformed_;  // Tells whether the object has been transformed.
    367   int unused_property_fields_;  // Captures the unused number of field.
    368   Handle<JSObject> object_;    // The object being optimized.
    369 };
    370 
    371 
    372 } }  // namespace v8::internal
    373 
    374 #endif  // V8_HANDLES_H_
    375