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 #include "v8.h"
     29 
     30 #include "api.h"
     31 #include "arguments.h"
     32 #include "bootstrapper.h"
     33 #include "codegen.h"
     34 #include "debug.h"
     35 #include "deoptimizer.h"
     36 #include "date.h"
     37 #include "elements.h"
     38 #include "execution.h"
     39 #include "full-codegen.h"
     40 #include "hydrogen.h"
     41 #include "objects-inl.h"
     42 #include "objects-visiting.h"
     43 #include "objects-visiting-inl.h"
     44 #include "macro-assembler.h"
     45 #include "mark-compact.h"
     46 #include "safepoint-table.h"
     47 #include "string-stream.h"
     48 #include "utils.h"
     49 #include "vm-state-inl.h"
     50 
     51 #ifdef ENABLE_DISASSEMBLER
     52 #include "disasm.h"
     53 #include "disassembler.h"
     54 #endif
     55 
     56 namespace v8 {
     57 namespace internal {
     58 
     59 void PrintElementsKind(FILE* out, ElementsKind kind) {
     60   ElementsAccessor* accessor = ElementsAccessor::ForKind(kind);
     61   PrintF(out, "%s", accessor->name());
     62 }
     63 
     64 
     65 MUST_USE_RESULT static MaybeObject* CreateJSValue(JSFunction* constructor,
     66                                                   Object* value) {
     67   Object* result;
     68   { MaybeObject* maybe_result =
     69         constructor->GetHeap()->AllocateJSObject(constructor);
     70     if (!maybe_result->ToObject(&result)) return maybe_result;
     71   }
     72   JSValue::cast(result)->set_value(value);
     73   return result;
     74 }
     75 
     76 
     77 MaybeObject* Object::ToObject(Context* global_context) {
     78   if (IsNumber()) {
     79     return CreateJSValue(global_context->number_function(), this);
     80   } else if (IsBoolean()) {
     81     return CreateJSValue(global_context->boolean_function(), this);
     82   } else if (IsString()) {
     83     return CreateJSValue(global_context->string_function(), this);
     84   }
     85   ASSERT(IsJSObject());
     86   return this;
     87 }
     88 
     89 
     90 MaybeObject* Object::ToObject() {
     91   if (IsJSReceiver()) {
     92     return this;
     93   } else if (IsNumber()) {
     94     Isolate* isolate = Isolate::Current();
     95     Context* global_context = isolate->context()->global_context();
     96     return CreateJSValue(global_context->number_function(), this);
     97   } else if (IsBoolean()) {
     98     Isolate* isolate = HeapObject::cast(this)->GetIsolate();
     99     Context* global_context = isolate->context()->global_context();
    100     return CreateJSValue(global_context->boolean_function(), this);
    101   } else if (IsString()) {
    102     Isolate* isolate = HeapObject::cast(this)->GetIsolate();
    103     Context* global_context = isolate->context()->global_context();
    104     return CreateJSValue(global_context->string_function(), this);
    105   }
    106 
    107   // Throw a type error.
    108   return Failure::InternalError();
    109 }
    110 
    111 
    112 Object* Object::ToBoolean() {
    113   if (IsTrue()) return this;
    114   if (IsFalse()) return this;
    115   if (IsSmi()) {
    116     return Isolate::Current()->heap()->ToBoolean(Smi::cast(this)->value() != 0);
    117   }
    118   HeapObject* heap_object = HeapObject::cast(this);
    119   if (heap_object->IsUndefined() || heap_object->IsNull()) {
    120     return heap_object->GetHeap()->false_value();
    121   }
    122   // Undetectable object is false
    123   if (heap_object->IsUndetectableObject()) {
    124     return heap_object->GetHeap()->false_value();
    125   }
    126   if (heap_object->IsString()) {
    127     return heap_object->GetHeap()->ToBoolean(
    128         String::cast(this)->length() != 0);
    129   }
    130   if (heap_object->IsHeapNumber()) {
    131     return HeapNumber::cast(this)->HeapNumberToBoolean();
    132   }
    133   return heap_object->GetHeap()->true_value();
    134 }
    135 
    136 
    137 void Object::Lookup(String* name, LookupResult* result) {
    138   Object* holder = NULL;
    139   if (IsJSReceiver()) {
    140     holder = this;
    141   } else {
    142     Context* global_context = Isolate::Current()->context()->global_context();
    143     if (IsNumber()) {
    144       holder = global_context->number_function()->instance_prototype();
    145     } else if (IsString()) {
    146       holder = global_context->string_function()->instance_prototype();
    147     } else if (IsBoolean()) {
    148       holder = global_context->boolean_function()->instance_prototype();
    149     }
    150   }
    151   ASSERT(holder != NULL);  // Cannot handle null or undefined.
    152   JSReceiver::cast(holder)->Lookup(name, result);
    153 }
    154 
    155 
    156 MaybeObject* Object::GetPropertyWithReceiver(Object* receiver,
    157                                              String* name,
    158                                              PropertyAttributes* attributes) {
    159   LookupResult result(name->GetIsolate());
    160   Lookup(name, &result);
    161   MaybeObject* value = GetProperty(receiver, &result, name, attributes);
    162   ASSERT(*attributes <= ABSENT);
    163   return value;
    164 }
    165 
    166 
    167 MaybeObject* JSObject::GetPropertyWithCallback(Object* receiver,
    168                                                Object* structure,
    169                                                String* name) {
    170   Isolate* isolate = name->GetIsolate();
    171   // To accommodate both the old and the new api we switch on the
    172   // data structure used to store the callbacks.  Eventually foreign
    173   // callbacks should be phased out.
    174   if (structure->IsForeign()) {
    175     AccessorDescriptor* callback =
    176         reinterpret_cast<AccessorDescriptor*>(
    177             Foreign::cast(structure)->foreign_address());
    178     MaybeObject* value = (callback->getter)(receiver, callback->data);
    179     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
    180     return value;
    181   }
    182 
    183   // api style callbacks.
    184   if (structure->IsAccessorInfo()) {
    185     AccessorInfo* data = AccessorInfo::cast(structure);
    186     Object* fun_obj = data->getter();
    187     v8::AccessorGetter call_fun = v8::ToCData<v8::AccessorGetter>(fun_obj);
    188     HandleScope scope(isolate);
    189     JSObject* self = JSObject::cast(receiver);
    190     Handle<String> key(name);
    191     LOG(isolate, ApiNamedPropertyAccess("load", self, name));
    192     CustomArguments args(isolate, data->data(), self, this);
    193     v8::AccessorInfo info(args.end());
    194     v8::Handle<v8::Value> result;
    195     {
    196       // Leaving JavaScript.
    197       VMState state(isolate, EXTERNAL);
    198       result = call_fun(v8::Utils::ToLocal(key), info);
    199     }
    200     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
    201     if (result.IsEmpty()) {
    202       return isolate->heap()->undefined_value();
    203     }
    204     return *v8::Utils::OpenHandle(*result);
    205   }
    206 
    207   // __defineGetter__ callback
    208   if (structure->IsAccessorPair()) {
    209     Object* getter = AccessorPair::cast(structure)->getter();
    210     if (getter->IsSpecFunction()) {
    211       // TODO(rossberg): nicer would be to cast to some JSCallable here...
    212       return GetPropertyWithDefinedGetter(receiver, JSReceiver::cast(getter));
    213     }
    214     // Getter is not a function.
    215     return isolate->heap()->undefined_value();
    216   }
    217 
    218   UNREACHABLE();
    219   return NULL;
    220 }
    221 
    222 
    223 MaybeObject* JSProxy::GetPropertyWithHandler(Object* receiver_raw,
    224                                              String* name_raw) {
    225   Isolate* isolate = GetIsolate();
    226   HandleScope scope(isolate);
    227   Handle<Object> receiver(receiver_raw);
    228   Handle<Object> name(name_raw);
    229 
    230   Handle<Object> args[] = { receiver, name };
    231   Handle<Object> result = CallTrap(
    232     "get", isolate->derived_get_trap(), ARRAY_SIZE(args), args);
    233   if (isolate->has_pending_exception()) return Failure::Exception();
    234 
    235   return *result;
    236 }
    237 
    238 
    239 Handle<Object> Object::GetElement(Handle<Object> object, uint32_t index) {
    240   Isolate* isolate = object->IsHeapObject()
    241       ? Handle<HeapObject>::cast(object)->GetIsolate()
    242       : Isolate::Current();
    243   CALL_HEAP_FUNCTION(isolate, object->GetElement(index), Object);
    244 }
    245 
    246 
    247 MaybeObject* JSProxy::GetElementWithHandler(Object* receiver,
    248                                             uint32_t index) {
    249   String* name;
    250   MaybeObject* maybe = GetHeap()->Uint32ToString(index);
    251   if (!maybe->To<String>(&name)) return maybe;
    252   return GetPropertyWithHandler(receiver, name);
    253 }
    254 
    255 
    256 MaybeObject* JSProxy::SetElementWithHandler(uint32_t index,
    257                                             Object* value,
    258                                             StrictModeFlag strict_mode) {
    259   String* name;
    260   MaybeObject* maybe = GetHeap()->Uint32ToString(index);
    261   if (!maybe->To<String>(&name)) return maybe;
    262   return SetPropertyWithHandler(name, value, NONE, strict_mode);
    263 }
    264 
    265 
    266 bool JSProxy::HasElementWithHandler(uint32_t index) {
    267   String* name;
    268   MaybeObject* maybe = GetHeap()->Uint32ToString(index);
    269   if (!maybe->To<String>(&name)) return maybe;
    270   return HasPropertyWithHandler(name);
    271 }
    272 
    273 
    274 MaybeObject* Object::GetPropertyWithDefinedGetter(Object* receiver,
    275                                                   JSReceiver* getter) {
    276   HandleScope scope;
    277   Handle<JSReceiver> fun(getter);
    278   Handle<Object> self(receiver);
    279 #ifdef ENABLE_DEBUGGER_SUPPORT
    280   Debug* debug = fun->GetHeap()->isolate()->debug();
    281   // Handle stepping into a getter if step into is active.
    282   // TODO(rossberg): should this apply to getters that are function proxies?
    283   if (debug->StepInActive() && fun->IsJSFunction()) {
    284     debug->HandleStepIn(
    285         Handle<JSFunction>::cast(fun), Handle<Object>::null(), 0, false);
    286   }
    287 #endif
    288 
    289   bool has_pending_exception;
    290   Handle<Object> result =
    291       Execution::Call(fun, self, 0, NULL, &has_pending_exception, true);
    292   // Check for pending exception and return the result.
    293   if (has_pending_exception) return Failure::Exception();
    294   return *result;
    295 }
    296 
    297 
    298 // Only deal with CALLBACKS and INTERCEPTOR
    299 MaybeObject* JSObject::GetPropertyWithFailedAccessCheck(
    300     Object* receiver,
    301     LookupResult* result,
    302     String* name,
    303     PropertyAttributes* attributes) {
    304   if (result->IsProperty()) {
    305     switch (result->type()) {
    306       case CALLBACKS: {
    307         // Only allow API accessors.
    308         Object* obj = result->GetCallbackObject();
    309         if (obj->IsAccessorInfo()) {
    310           AccessorInfo* info = AccessorInfo::cast(obj);
    311           if (info->all_can_read()) {
    312             *attributes = result->GetAttributes();
    313             return result->holder()->GetPropertyWithCallback(
    314                 receiver, result->GetCallbackObject(), name);
    315           }
    316         }
    317         break;
    318       }
    319       case NORMAL:
    320       case FIELD:
    321       case CONSTANT_FUNCTION: {
    322         // Search ALL_CAN_READ accessors in prototype chain.
    323         LookupResult r(GetIsolate());
    324         result->holder()->LookupRealNamedPropertyInPrototypes(name, &r);
    325         if (r.IsProperty()) {
    326           return GetPropertyWithFailedAccessCheck(receiver,
    327                                                   &r,
    328                                                   name,
    329                                                   attributes);
    330         }
    331         break;
    332       }
    333       case INTERCEPTOR: {
    334         // If the object has an interceptor, try real named properties.
    335         // No access check in GetPropertyAttributeWithInterceptor.
    336         LookupResult r(GetIsolate());
    337         result->holder()->LookupRealNamedProperty(name, &r);
    338         if (r.IsProperty()) {
    339           return GetPropertyWithFailedAccessCheck(receiver,
    340                                                   &r,
    341                                                   name,
    342                                                   attributes);
    343         }
    344         break;
    345       }
    346       default:
    347         UNREACHABLE();
    348     }
    349   }
    350 
    351   // No accessible property found.
    352   *attributes = ABSENT;
    353   Heap* heap = name->GetHeap();
    354   heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_GET);
    355   return heap->undefined_value();
    356 }
    357 
    358 
    359 PropertyAttributes JSObject::GetPropertyAttributeWithFailedAccessCheck(
    360     Object* receiver,
    361     LookupResult* result,
    362     String* name,
    363     bool continue_search) {
    364   if (result->IsProperty()) {
    365     switch (result->type()) {
    366       case CALLBACKS: {
    367         // Only allow API accessors.
    368         Object* obj = result->GetCallbackObject();
    369         if (obj->IsAccessorInfo()) {
    370           AccessorInfo* info = AccessorInfo::cast(obj);
    371           if (info->all_can_read()) {
    372             return result->GetAttributes();
    373           }
    374         }
    375         break;
    376       }
    377 
    378       case NORMAL:
    379       case FIELD:
    380       case CONSTANT_FUNCTION: {
    381         if (!continue_search) break;
    382         // Search ALL_CAN_READ accessors in prototype chain.
    383         LookupResult r(GetIsolate());
    384         result->holder()->LookupRealNamedPropertyInPrototypes(name, &r);
    385         if (r.IsProperty()) {
    386           return GetPropertyAttributeWithFailedAccessCheck(receiver,
    387                                                            &r,
    388                                                            name,
    389                                                            continue_search);
    390         }
    391         break;
    392       }
    393 
    394       case INTERCEPTOR: {
    395         // If the object has an interceptor, try real named properties.
    396         // No access check in GetPropertyAttributeWithInterceptor.
    397         LookupResult r(GetIsolate());
    398         if (continue_search) {
    399           result->holder()->LookupRealNamedProperty(name, &r);
    400         } else {
    401           result->holder()->LocalLookupRealNamedProperty(name, &r);
    402         }
    403         if (r.IsProperty()) {
    404           return GetPropertyAttributeWithFailedAccessCheck(receiver,
    405                                                            &r,
    406                                                            name,
    407                                                            continue_search);
    408         }
    409         break;
    410       }
    411 
    412       default:
    413         UNREACHABLE();
    414     }
    415   }
    416 
    417   GetIsolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
    418   return ABSENT;
    419 }
    420 
    421 
    422 Object* JSObject::GetNormalizedProperty(LookupResult* result) {
    423   ASSERT(!HasFastProperties());
    424   Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry());
    425   if (IsGlobalObject()) {
    426     value = JSGlobalPropertyCell::cast(value)->value();
    427   }
    428   ASSERT(!value->IsJSGlobalPropertyCell());
    429   return value;
    430 }
    431 
    432 
    433 Object* JSObject::SetNormalizedProperty(LookupResult* result, Object* value) {
    434   ASSERT(!HasFastProperties());
    435   if (IsGlobalObject()) {
    436     JSGlobalPropertyCell* cell =
    437         JSGlobalPropertyCell::cast(
    438             property_dictionary()->ValueAt(result->GetDictionaryEntry()));
    439     cell->set_value(value);
    440   } else {
    441     property_dictionary()->ValueAtPut(result->GetDictionaryEntry(), value);
    442   }
    443   return value;
    444 }
    445 
    446 
    447 Handle<Object> JSObject::SetNormalizedProperty(Handle<JSObject> object,
    448                                                Handle<String> key,
    449                                                Handle<Object> value,
    450                                                PropertyDetails details) {
    451   CALL_HEAP_FUNCTION(object->GetIsolate(),
    452                      object->SetNormalizedProperty(*key, *value, details),
    453                      Object);
    454 }
    455 
    456 
    457 MaybeObject* JSObject::SetNormalizedProperty(String* name,
    458                                              Object* value,
    459                                              PropertyDetails details) {
    460   ASSERT(!HasFastProperties());
    461   int entry = property_dictionary()->FindEntry(name);
    462   if (entry == StringDictionary::kNotFound) {
    463     Object* store_value = value;
    464     if (IsGlobalObject()) {
    465       Heap* heap = name->GetHeap();
    466       MaybeObject* maybe_store_value =
    467           heap->AllocateJSGlobalPropertyCell(value);
    468       if (!maybe_store_value->ToObject(&store_value)) return maybe_store_value;
    469     }
    470     Object* dict;
    471     { MaybeObject* maybe_dict =
    472           property_dictionary()->Add(name, store_value, details);
    473       if (!maybe_dict->ToObject(&dict)) return maybe_dict;
    474     }
    475     set_properties(StringDictionary::cast(dict));
    476     return value;
    477   }
    478   // Preserve enumeration index.
    479   details = PropertyDetails(details.attributes(),
    480                             details.type(),
    481                             property_dictionary()->DetailsAt(entry).index());
    482   if (IsGlobalObject()) {
    483     JSGlobalPropertyCell* cell =
    484         JSGlobalPropertyCell::cast(property_dictionary()->ValueAt(entry));
    485     cell->set_value(value);
    486     // Please note we have to update the property details.
    487     property_dictionary()->DetailsAtPut(entry, details);
    488   } else {
    489     property_dictionary()->SetEntry(entry, name, value, details);
    490   }
    491   return value;
    492 }
    493 
    494 
    495 MaybeObject* JSObject::DeleteNormalizedProperty(String* name, DeleteMode mode) {
    496   ASSERT(!HasFastProperties());
    497   StringDictionary* dictionary = property_dictionary();
    498   int entry = dictionary->FindEntry(name);
    499   if (entry != StringDictionary::kNotFound) {
    500     // If we have a global object set the cell to the hole.
    501     if (IsGlobalObject()) {
    502       PropertyDetails details = dictionary->DetailsAt(entry);
    503       if (details.IsDontDelete()) {
    504         if (mode != FORCE_DELETION) return GetHeap()->false_value();
    505         // When forced to delete global properties, we have to make a
    506         // map change to invalidate any ICs that think they can load
    507         // from the DontDelete cell without checking if it contains
    508         // the hole value.
    509         Object* new_map;
    510         { MaybeObject* maybe_new_map = map()->CopyDropDescriptors();
    511           if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
    512         }
    513         set_map(Map::cast(new_map));
    514       }
    515       JSGlobalPropertyCell* cell =
    516           JSGlobalPropertyCell::cast(dictionary->ValueAt(entry));
    517       cell->set_value(cell->GetHeap()->the_hole_value());
    518       dictionary->DetailsAtPut(entry, details.AsDeleted());
    519     } else {
    520       Object* deleted = dictionary->DeleteProperty(entry, mode);
    521       if (deleted == GetHeap()->true_value()) {
    522         FixedArray* new_properties = NULL;
    523         MaybeObject* maybe_properties = dictionary->Shrink(name);
    524         if (!maybe_properties->To(&new_properties)) {
    525           return maybe_properties;
    526         }
    527         set_properties(new_properties);
    528       }
    529       return deleted;
    530     }
    531   }
    532   return GetHeap()->true_value();
    533 }
    534 
    535 
    536 bool JSObject::IsDirty() {
    537   Object* cons_obj = map()->constructor();
    538   if (!cons_obj->IsJSFunction())
    539     return true;
    540   JSFunction* fun = JSFunction::cast(cons_obj);
    541   if (!fun->shared()->IsApiFunction())
    542     return true;
    543   // If the object is fully fast case and has the same map it was
    544   // created with then no changes can have been made to it.
    545   return map() != fun->initial_map()
    546       || !HasFastElements()
    547       || !HasFastProperties();
    548 }
    549 
    550 
    551 Handle<Object> Object::GetProperty(Handle<Object> object,
    552                                    Handle<Object> receiver,
    553                                    LookupResult* result,
    554                                    Handle<String> key,
    555                                    PropertyAttributes* attributes) {
    556   Isolate* isolate = object->IsHeapObject()
    557       ? Handle<HeapObject>::cast(object)->GetIsolate()
    558       : Isolate::Current();
    559   CALL_HEAP_FUNCTION(
    560       isolate,
    561       object->GetProperty(*receiver, result, *key, attributes),
    562       Object);
    563 }
    564 
    565 
    566 MaybeObject* Object::GetProperty(Object* receiver,
    567                                  LookupResult* result,
    568                                  String* name,
    569                                  PropertyAttributes* attributes) {
    570   // Make sure that the top context does not change when doing
    571   // callbacks or interceptor calls.
    572   AssertNoContextChange ncc;
    573   Heap* heap = name->GetHeap();
    574 
    575   // Traverse the prototype chain from the current object (this) to
    576   // the holder and check for access rights. This avoids traversing the
    577   // objects more than once in case of interceptors, because the
    578   // holder will always be the interceptor holder and the search may
    579   // only continue with a current object just after the interceptor
    580   // holder in the prototype chain.
    581   // Proxy handlers do not use the proxy's prototype, so we can skip this.
    582   if (!result->IsHandler()) {
    583     Object* last = result->IsProperty()
    584         ? result->holder()
    585         : Object::cast(heap->null_value());
    586     ASSERT(this != this->GetPrototype());
    587     for (Object* current = this; true; current = current->GetPrototype()) {
    588       if (current->IsAccessCheckNeeded()) {
    589         // Check if we're allowed to read from the current object. Note
    590         // that even though we may not actually end up loading the named
    591         // property from the current object, we still check that we have
    592         // access to it.
    593         JSObject* checked = JSObject::cast(current);
    594         if (!heap->isolate()->MayNamedAccess(checked, name, v8::ACCESS_GET)) {
    595           return checked->GetPropertyWithFailedAccessCheck(receiver,
    596                                                            result,
    597                                                            name,
    598                                                            attributes);
    599         }
    600       }
    601       // Stop traversing the chain once we reach the last object in the
    602       // chain; either the holder of the result or null in case of an
    603       // absent property.
    604       if (current == last) break;
    605     }
    606   }
    607 
    608   if (!result->IsProperty()) {
    609     *attributes = ABSENT;
    610     return heap->undefined_value();
    611   }
    612   *attributes = result->GetAttributes();
    613   Object* value;
    614   switch (result->type()) {
    615     case NORMAL:
    616       value = result->holder()->GetNormalizedProperty(result);
    617       ASSERT(!value->IsTheHole() || result->IsReadOnly());
    618       return value->IsTheHole() ? heap->undefined_value() : value;
    619     case FIELD:
    620       value = result->holder()->FastPropertyAt(result->GetFieldIndex());
    621       ASSERT(!value->IsTheHole() || result->IsReadOnly());
    622       return value->IsTheHole() ? heap->undefined_value() : value;
    623     case CONSTANT_FUNCTION:
    624       return result->GetConstantFunction();
    625     case CALLBACKS:
    626       return result->holder()->GetPropertyWithCallback(
    627           receiver, result->GetCallbackObject(), name);
    628     case HANDLER:
    629       return result->proxy()->GetPropertyWithHandler(receiver, name);
    630     case INTERCEPTOR: {
    631       JSObject* recvr = JSObject::cast(receiver);
    632       return result->holder()->GetPropertyWithInterceptor(
    633           recvr, name, attributes);
    634     }
    635     case MAP_TRANSITION:
    636     case ELEMENTS_TRANSITION:
    637     case CONSTANT_TRANSITION:
    638     case NULL_DESCRIPTOR:
    639       break;
    640   }
    641   UNREACHABLE();
    642   return NULL;
    643 }
    644 
    645 
    646 MaybeObject* Object::GetElementWithReceiver(Object* receiver, uint32_t index) {
    647   Heap* heap = IsSmi()
    648       ? Isolate::Current()->heap()
    649       : HeapObject::cast(this)->GetHeap();
    650   Object* holder = this;
    651 
    652   // Iterate up the prototype chain until an element is found or the null
    653   // prototype is encountered.
    654   for (holder = this;
    655        holder != heap->null_value();
    656        holder = holder->GetPrototype()) {
    657     if (!holder->IsJSObject()) {
    658       Isolate* isolate = heap->isolate();
    659       Context* global_context = isolate->context()->global_context();
    660       if (holder->IsNumber()) {
    661         holder = global_context->number_function()->instance_prototype();
    662       } else if (holder->IsString()) {
    663         holder = global_context->string_function()->instance_prototype();
    664       } else if (holder->IsBoolean()) {
    665         holder = global_context->boolean_function()->instance_prototype();
    666       } else if (holder->IsJSProxy()) {
    667         return JSProxy::cast(holder)->GetElementWithHandler(receiver, index);
    668       } else {
    669         // Undefined and null have no indexed properties.
    670         ASSERT(holder->IsUndefined() || holder->IsNull());
    671         return heap->undefined_value();
    672       }
    673     }
    674 
    675     // Inline the case for JSObjects. Doing so significantly improves the
    676     // performance of fetching elements where checking the prototype chain is
    677     // necessary.
    678     JSObject* js_object = JSObject::cast(holder);
    679 
    680     // Check access rights if needed.
    681     if (js_object->IsAccessCheckNeeded()) {
    682       Isolate* isolate = heap->isolate();
    683       if (!isolate->MayIndexedAccess(js_object, index, v8::ACCESS_GET)) {
    684         isolate->ReportFailedAccessCheck(js_object, v8::ACCESS_GET);
    685         return heap->undefined_value();
    686       }
    687     }
    688 
    689     if (js_object->HasIndexedInterceptor()) {
    690       return js_object->GetElementWithInterceptor(receiver, index);
    691     }
    692 
    693     if (js_object->elements() != heap->empty_fixed_array()) {
    694       MaybeObject* result = js_object->GetElementsAccessor()->Get(
    695           receiver, js_object, index);
    696       if (result != heap->the_hole_value()) return result;
    697     }
    698   }
    699 
    700   return heap->undefined_value();
    701 }
    702 
    703 
    704 Object* Object::GetPrototype() {
    705   if (IsSmi()) {
    706     Heap* heap = Isolate::Current()->heap();
    707     Context* context = heap->isolate()->context()->global_context();
    708     return context->number_function()->instance_prototype();
    709   }
    710 
    711   HeapObject* heap_object = HeapObject::cast(this);
    712 
    713   // The object is either a number, a string, a boolean,
    714   // a real JS object, or a Harmony proxy.
    715   if (heap_object->IsJSReceiver()) {
    716     return heap_object->map()->prototype();
    717   }
    718   Heap* heap = heap_object->GetHeap();
    719   Context* context = heap->isolate()->context()->global_context();
    720 
    721   if (heap_object->IsHeapNumber()) {
    722     return context->number_function()->instance_prototype();
    723   }
    724   if (heap_object->IsString()) {
    725     return context->string_function()->instance_prototype();
    726   }
    727   if (heap_object->IsBoolean()) {
    728     return context->boolean_function()->instance_prototype();
    729   } else {
    730     return heap->null_value();
    731   }
    732 }
    733 
    734 
    735 MaybeObject* Object::GetHash(CreationFlag flag) {
    736   // The object is either a number, a string, an odd-ball,
    737   // a real JS object, or a Harmony proxy.
    738   if (IsNumber()) {
    739     uint32_t hash = ComputeLongHash(double_to_uint64(Number()));
    740     return Smi::FromInt(hash & Smi::kMaxValue);
    741   }
    742   if (IsString()) {
    743     uint32_t hash = String::cast(this)->Hash();
    744     return Smi::FromInt(hash);
    745   }
    746   if (IsOddball()) {
    747     uint32_t hash = Oddball::cast(this)->to_string()->Hash();
    748     return Smi::FromInt(hash);
    749   }
    750   if (IsJSReceiver()) {
    751     return JSReceiver::cast(this)->GetIdentityHash(flag);
    752   }
    753 
    754   UNREACHABLE();
    755   return Smi::FromInt(0);
    756 }
    757 
    758 
    759 bool Object::SameValue(Object* other) {
    760   if (other == this) return true;
    761   if (!IsHeapObject() || !other->IsHeapObject()) return false;
    762 
    763   // The object is either a number, a string, an odd-ball,
    764   // a real JS object, or a Harmony proxy.
    765   if (IsNumber() && other->IsNumber()) {
    766     double this_value = Number();
    767     double other_value = other->Number();
    768     return (this_value == other_value) ||
    769         (isnan(this_value) && isnan(other_value));
    770   }
    771   if (IsString() && other->IsString()) {
    772     return String::cast(this)->Equals(String::cast(other));
    773   }
    774   return false;
    775 }
    776 
    777 
    778 void Object::ShortPrint(FILE* out) {
    779   HeapStringAllocator allocator;
    780   StringStream accumulator(&allocator);
    781   ShortPrint(&accumulator);
    782   accumulator.OutputToFile(out);
    783 }
    784 
    785 
    786 void Object::ShortPrint(StringStream* accumulator) {
    787   if (IsSmi()) {
    788     Smi::cast(this)->SmiPrint(accumulator);
    789   } else if (IsFailure()) {
    790     Failure::cast(this)->FailurePrint(accumulator);
    791   } else {
    792     HeapObject::cast(this)->HeapObjectShortPrint(accumulator);
    793   }
    794 }
    795 
    796 
    797 void Smi::SmiPrint(FILE* out) {
    798   PrintF(out, "%d", value());
    799 }
    800 
    801 
    802 void Smi::SmiPrint(StringStream* accumulator) {
    803   accumulator->Add("%d", value());
    804 }
    805 
    806 
    807 void Failure::FailurePrint(StringStream* accumulator) {
    808   accumulator->Add("Failure(%p)", reinterpret_cast<void*>(value()));
    809 }
    810 
    811 
    812 void Failure::FailurePrint(FILE* out) {
    813   PrintF(out, "Failure(%p)", reinterpret_cast<void*>(value()));
    814 }
    815 
    816 
    817 // Should a word be prefixed by 'a' or 'an' in order to read naturally in
    818 // English?  Returns false for non-ASCII or words that don't start with
    819 // a capital letter.  The a/an rule follows pronunciation in English.
    820 // We don't use the BBC's overcorrect "an historic occasion" though if
    821 // you speak a dialect you may well say "an 'istoric occasion".
    822 static bool AnWord(String* str) {
    823   if (str->length() == 0) return false;  // A nothing.
    824   int c0 = str->Get(0);
    825   int c1 = str->length() > 1 ? str->Get(1) : 0;
    826   if (c0 == 'U') {
    827     if (c1 > 'Z') {
    828       return true;  // An Umpire, but a UTF8String, a U.
    829     }
    830   } else if (c0 == 'A' || c0 == 'E' || c0 == 'I' || c0 == 'O') {
    831     return true;    // An Ape, an ABCBook.
    832   } else if ((c1 == 0 || (c1 >= 'A' && c1 <= 'Z')) &&
    833            (c0 == 'F' || c0 == 'H' || c0 == 'M' || c0 == 'N' || c0 == 'R' ||
    834             c0 == 'S' || c0 == 'X')) {
    835     return true;    // An MP3File, an M.
    836   }
    837   return false;
    838 }
    839 
    840 
    841 MaybeObject* String::SlowTryFlatten(PretenureFlag pretenure) {
    842 #ifdef DEBUG
    843   // Do not attempt to flatten in debug mode when allocation is not
    844   // allowed.  This is to avoid an assertion failure when allocating.
    845   // Flattening strings is the only case where we always allow
    846   // allocation because no GC is performed if the allocation fails.
    847   if (!HEAP->IsAllocationAllowed()) return this;
    848 #endif
    849 
    850   Heap* heap = GetHeap();
    851   switch (StringShape(this).representation_tag()) {
    852     case kConsStringTag: {
    853       ConsString* cs = ConsString::cast(this);
    854       if (cs->second()->length() == 0) {
    855         return cs->first();
    856       }
    857       // There's little point in putting the flat string in new space if the
    858       // cons string is in old space.  It can never get GCed until there is
    859       // an old space GC.
    860       PretenureFlag tenure = heap->InNewSpace(this) ? pretenure : TENURED;
    861       int len = length();
    862       Object* object;
    863       String* result;
    864       if (IsAsciiRepresentation()) {
    865         { MaybeObject* maybe_object = heap->AllocateRawAsciiString(len, tenure);
    866           if (!maybe_object->ToObject(&object)) return maybe_object;
    867         }
    868         result = String::cast(object);
    869         String* first = cs->first();
    870         int first_length = first->length();
    871         char* dest = SeqAsciiString::cast(result)->GetChars();
    872         WriteToFlat(first, dest, 0, first_length);
    873         String* second = cs->second();
    874         WriteToFlat(second,
    875                     dest + first_length,
    876                     0,
    877                     len - first_length);
    878       } else {
    879         { MaybeObject* maybe_object =
    880               heap->AllocateRawTwoByteString(len, tenure);
    881           if (!maybe_object->ToObject(&object)) return maybe_object;
    882         }
    883         result = String::cast(object);
    884         uc16* dest = SeqTwoByteString::cast(result)->GetChars();
    885         String* first = cs->first();
    886         int first_length = first->length();
    887         WriteToFlat(first, dest, 0, first_length);
    888         String* second = cs->second();
    889         WriteToFlat(second,
    890                     dest + first_length,
    891                     0,
    892                     len - first_length);
    893       }
    894       cs->set_first(result);
    895       cs->set_second(heap->empty_string(), SKIP_WRITE_BARRIER);
    896       return result;
    897     }
    898     default:
    899       return this;
    900   }
    901 }
    902 
    903 
    904 bool String::MakeExternal(v8::String::ExternalStringResource* resource) {
    905   // Externalizing twice leaks the external resource, so it's
    906   // prohibited by the API.
    907   ASSERT(!this->IsExternalString());
    908 #ifdef DEBUG
    909   if (FLAG_enable_slow_asserts) {
    910     // Assert that the resource and the string are equivalent.
    911     ASSERT(static_cast<size_t>(this->length()) == resource->length());
    912     ScopedVector<uc16> smart_chars(this->length());
    913     String::WriteToFlat(this, smart_chars.start(), 0, this->length());
    914     ASSERT(memcmp(smart_chars.start(),
    915                   resource->data(),
    916                   resource->length() * sizeof(smart_chars[0])) == 0);
    917   }
    918 #endif  // DEBUG
    919   Heap* heap = GetHeap();
    920   int size = this->Size();  // Byte size of the original string.
    921   if (size < ExternalString::kShortSize) {
    922     return false;
    923   }
    924   bool is_ascii = this->IsAsciiRepresentation();
    925   bool is_symbol = this->IsSymbol();
    926 
    927   // Morph the object to an external string by adjusting the map and
    928   // reinitializing the fields.
    929   if (size >= ExternalString::kSize) {
    930     this->set_map_no_write_barrier(
    931         is_symbol
    932             ? (is_ascii ?  heap->external_symbol_with_ascii_data_map()
    933                         :  heap->external_symbol_map())
    934             : (is_ascii ?  heap->external_string_with_ascii_data_map()
    935                         :  heap->external_string_map()));
    936   } else {
    937     this->set_map_no_write_barrier(
    938         is_symbol
    939             ? (is_ascii ?  heap->short_external_symbol_with_ascii_data_map()
    940                         :  heap->short_external_symbol_map())
    941             : (is_ascii ?  heap->short_external_string_with_ascii_data_map()
    942                         :  heap->short_external_string_map()));
    943   }
    944   ExternalTwoByteString* self = ExternalTwoByteString::cast(this);
    945   self->set_resource(resource);
    946   if (is_symbol) self->Hash();  // Force regeneration of the hash value.
    947 
    948   // Fill the remainder of the string with dead wood.
    949   int new_size = this->Size();  // Byte size of the external String object.
    950   heap->CreateFillerObjectAt(this->address() + new_size, size - new_size);
    951   if (Marking::IsBlack(Marking::MarkBitFrom(this))) {
    952     MemoryChunk::IncrementLiveBytesFromMutator(this->address(),
    953                                                new_size - size);
    954   }
    955   return true;
    956 }
    957 
    958 
    959 bool String::MakeExternal(v8::String::ExternalAsciiStringResource* resource) {
    960 #ifdef DEBUG
    961   if (FLAG_enable_slow_asserts) {
    962     // Assert that the resource and the string are equivalent.
    963     ASSERT(static_cast<size_t>(this->length()) == resource->length());
    964     ScopedVector<char> smart_chars(this->length());
    965     String::WriteToFlat(this, smart_chars.start(), 0, this->length());
    966     ASSERT(memcmp(smart_chars.start(),
    967                   resource->data(),
    968                   resource->length() * sizeof(smart_chars[0])) == 0);
    969   }
    970 #endif  // DEBUG
    971   Heap* heap = GetHeap();
    972   int size = this->Size();  // Byte size of the original string.
    973   if (size < ExternalString::kShortSize) {
    974     return false;
    975   }
    976   bool is_symbol = this->IsSymbol();
    977 
    978   // Morph the object to an external string by adjusting the map and
    979   // reinitializing the fields.  Use short version if space is limited.
    980   if (size >= ExternalString::kSize) {
    981     this->set_map_no_write_barrier(
    982         is_symbol ? heap->external_ascii_symbol_map()
    983                   : heap->external_ascii_string_map());
    984   } else {
    985     this->set_map_no_write_barrier(
    986         is_symbol ? heap->short_external_ascii_symbol_map()
    987                   : heap->short_external_ascii_string_map());
    988   }
    989   ExternalAsciiString* self = ExternalAsciiString::cast(this);
    990   self->set_resource(resource);
    991   if (is_symbol) self->Hash();  // Force regeneration of the hash value.
    992 
    993   // Fill the remainder of the string with dead wood.
    994   int new_size = this->Size();  // Byte size of the external String object.
    995   heap->CreateFillerObjectAt(this->address() + new_size, size - new_size);
    996   if (Marking::IsBlack(Marking::MarkBitFrom(this))) {
    997     MemoryChunk::IncrementLiveBytesFromMutator(this->address(),
    998                                                new_size - size);
    999   }
   1000   return true;
   1001 }
   1002 
   1003 
   1004 void String::StringShortPrint(StringStream* accumulator) {
   1005   int len = length();
   1006   if (len > kMaxShortPrintLength) {
   1007     accumulator->Add("<Very long string[%u]>", len);
   1008     return;
   1009   }
   1010 
   1011   if (!LooksValid()) {
   1012     accumulator->Add("<Invalid String>");
   1013     return;
   1014   }
   1015 
   1016   StringInputBuffer buf(this);
   1017 
   1018   bool truncated = false;
   1019   if (len > kMaxShortPrintLength) {
   1020     len = kMaxShortPrintLength;
   1021     truncated = true;
   1022   }
   1023   bool ascii = true;
   1024   for (int i = 0; i < len; i++) {
   1025     int c = buf.GetNext();
   1026 
   1027     if (c < 32 || c >= 127) {
   1028       ascii = false;
   1029     }
   1030   }
   1031   buf.Reset(this);
   1032   if (ascii) {
   1033     accumulator->Add("<String[%u]: ", length());
   1034     for (int i = 0; i < len; i++) {
   1035       accumulator->Put(buf.GetNext());
   1036     }
   1037     accumulator->Put('>');
   1038   } else {
   1039     // Backslash indicates that the string contains control
   1040     // characters and that backslashes are therefore escaped.
   1041     accumulator->Add("<String[%u]\\: ", length());
   1042     for (int i = 0; i < len; i++) {
   1043       int c = buf.GetNext();
   1044       if (c == '\n') {
   1045         accumulator->Add("\\n");
   1046       } else if (c == '\r') {
   1047         accumulator->Add("\\r");
   1048       } else if (c == '\\') {
   1049         accumulator->Add("\\\\");
   1050       } else if (c < 32 || c > 126) {
   1051         accumulator->Add("\\x%02x", c);
   1052       } else {
   1053         accumulator->Put(c);
   1054       }
   1055     }
   1056     if (truncated) {
   1057       accumulator->Put('.');
   1058       accumulator->Put('.');
   1059       accumulator->Put('.');
   1060     }
   1061     accumulator->Put('>');
   1062   }
   1063   return;
   1064 }
   1065 
   1066 
   1067 void JSObject::JSObjectShortPrint(StringStream* accumulator) {
   1068   switch (map()->instance_type()) {
   1069     case JS_ARRAY_TYPE: {
   1070       double length = JSArray::cast(this)->length()->Number();
   1071       accumulator->Add("<JS Array[%u]>", static_cast<uint32_t>(length));
   1072       break;
   1073     }
   1074     case JS_WEAK_MAP_TYPE: {
   1075       accumulator->Add("<JS WeakMap>");
   1076       break;
   1077     }
   1078     case JS_REGEXP_TYPE: {
   1079       accumulator->Add("<JS RegExp>");
   1080       break;
   1081     }
   1082     case JS_FUNCTION_TYPE: {
   1083       Object* fun_name = JSFunction::cast(this)->shared()->name();
   1084       bool printed = false;
   1085       if (fun_name->IsString()) {
   1086         String* str = String::cast(fun_name);
   1087         if (str->length() > 0) {
   1088           accumulator->Add("<JS Function ");
   1089           accumulator->Put(str);
   1090           accumulator->Put('>');
   1091           printed = true;
   1092         }
   1093       }
   1094       if (!printed) {
   1095         accumulator->Add("<JS Function>");
   1096       }
   1097       break;
   1098     }
   1099     // All other JSObjects are rather similar to each other (JSObject,
   1100     // JSGlobalProxy, JSGlobalObject, JSUndetectableObject, JSValue).
   1101     default: {
   1102       Map* map_of_this = map();
   1103       Heap* heap = GetHeap();
   1104       Object* constructor = map_of_this->constructor();
   1105       bool printed = false;
   1106       if (constructor->IsHeapObject() &&
   1107           !heap->Contains(HeapObject::cast(constructor))) {
   1108         accumulator->Add("!!!INVALID CONSTRUCTOR!!!");
   1109       } else {
   1110         bool global_object = IsJSGlobalProxy();
   1111         if (constructor->IsJSFunction()) {
   1112           if (!heap->Contains(JSFunction::cast(constructor)->shared())) {
   1113             accumulator->Add("!!!INVALID SHARED ON CONSTRUCTOR!!!");
   1114           } else {
   1115             Object* constructor_name =
   1116                 JSFunction::cast(constructor)->shared()->name();
   1117             if (constructor_name->IsString()) {
   1118               String* str = String::cast(constructor_name);
   1119               if (str->length() > 0) {
   1120                 bool vowel = AnWord(str);
   1121                 accumulator->Add("<%sa%s ",
   1122                        global_object ? "Global Object: " : "",
   1123                        vowel ? "n" : "");
   1124                 accumulator->Put(str);
   1125                 printed = true;
   1126               }
   1127             }
   1128           }
   1129         }
   1130         if (!printed) {
   1131           accumulator->Add("<JS %sObject", global_object ? "Global " : "");
   1132         }
   1133       }
   1134       if (IsJSValue()) {
   1135         accumulator->Add(" value = ");
   1136         JSValue::cast(this)->value()->ShortPrint(accumulator);
   1137       }
   1138       accumulator->Put('>');
   1139       break;
   1140     }
   1141   }
   1142 }
   1143 
   1144 
   1145 void JSObject::PrintElementsTransition(
   1146     FILE* file, ElementsKind from_kind, FixedArrayBase* from_elements,
   1147     ElementsKind to_kind, FixedArrayBase* to_elements) {
   1148   if (from_kind != to_kind) {
   1149     PrintF(file, "elements transition [");
   1150     PrintElementsKind(file, from_kind);
   1151     PrintF(file, " -> ");
   1152     PrintElementsKind(file, to_kind);
   1153     PrintF(file, "] in ");
   1154     JavaScriptFrame::PrintTop(file, false, true);
   1155     PrintF(file, " for ");
   1156     ShortPrint(file);
   1157     PrintF(file, " from ");
   1158     from_elements->ShortPrint(file);
   1159     PrintF(file, " to ");
   1160     to_elements->ShortPrint(file);
   1161     PrintF(file, "\n");
   1162   }
   1163 }
   1164 
   1165 
   1166 void HeapObject::HeapObjectShortPrint(StringStream* accumulator) {
   1167   Heap* heap = GetHeap();
   1168   if (!heap->Contains(this)) {
   1169     accumulator->Add("!!!INVALID POINTER!!!");
   1170     return;
   1171   }
   1172   if (!heap->Contains(map())) {
   1173     accumulator->Add("!!!INVALID MAP!!!");
   1174     return;
   1175   }
   1176 
   1177   accumulator->Add("%p ", this);
   1178 
   1179   if (IsString()) {
   1180     String::cast(this)->StringShortPrint(accumulator);
   1181     return;
   1182   }
   1183   if (IsJSObject()) {
   1184     JSObject::cast(this)->JSObjectShortPrint(accumulator);
   1185     return;
   1186   }
   1187   switch (map()->instance_type()) {
   1188     case MAP_TYPE:
   1189       accumulator->Add("<Map(elements=%u)>", Map::cast(this)->elements_kind());
   1190       break;
   1191     case FIXED_ARRAY_TYPE:
   1192       accumulator->Add("<FixedArray[%u]>", FixedArray::cast(this)->length());
   1193       break;
   1194     case FIXED_DOUBLE_ARRAY_TYPE:
   1195       accumulator->Add("<FixedDoubleArray[%u]>",
   1196                        FixedDoubleArray::cast(this)->length());
   1197       break;
   1198     case BYTE_ARRAY_TYPE:
   1199       accumulator->Add("<ByteArray[%u]>", ByteArray::cast(this)->length());
   1200       break;
   1201     case FREE_SPACE_TYPE:
   1202       accumulator->Add("<FreeSpace[%u]>", FreeSpace::cast(this)->Size());
   1203       break;
   1204     case EXTERNAL_PIXEL_ARRAY_TYPE:
   1205       accumulator->Add("<ExternalPixelArray[%u]>",
   1206                        ExternalPixelArray::cast(this)->length());
   1207       break;
   1208     case EXTERNAL_BYTE_ARRAY_TYPE:
   1209       accumulator->Add("<ExternalByteArray[%u]>",
   1210                        ExternalByteArray::cast(this)->length());
   1211       break;
   1212     case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
   1213       accumulator->Add("<ExternalUnsignedByteArray[%u]>",
   1214                        ExternalUnsignedByteArray::cast(this)->length());
   1215       break;
   1216     case EXTERNAL_SHORT_ARRAY_TYPE:
   1217       accumulator->Add("<ExternalShortArray[%u]>",
   1218                        ExternalShortArray::cast(this)->length());
   1219       break;
   1220     case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
   1221       accumulator->Add("<ExternalUnsignedShortArray[%u]>",
   1222                        ExternalUnsignedShortArray::cast(this)->length());
   1223       break;
   1224     case EXTERNAL_INT_ARRAY_TYPE:
   1225       accumulator->Add("<ExternalIntArray[%u]>",
   1226                        ExternalIntArray::cast(this)->length());
   1227       break;
   1228     case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
   1229       accumulator->Add("<ExternalUnsignedIntArray[%u]>",
   1230                        ExternalUnsignedIntArray::cast(this)->length());
   1231       break;
   1232     case EXTERNAL_FLOAT_ARRAY_TYPE:
   1233       accumulator->Add("<ExternalFloatArray[%u]>",
   1234                        ExternalFloatArray::cast(this)->length());
   1235       break;
   1236     case EXTERNAL_DOUBLE_ARRAY_TYPE:
   1237       accumulator->Add("<ExternalDoubleArray[%u]>",
   1238                        ExternalDoubleArray::cast(this)->length());
   1239       break;
   1240     case SHARED_FUNCTION_INFO_TYPE:
   1241       accumulator->Add("<SharedFunctionInfo>");
   1242       break;
   1243     case JS_MESSAGE_OBJECT_TYPE:
   1244       accumulator->Add("<JSMessageObject>");
   1245       break;
   1246 #define MAKE_STRUCT_CASE(NAME, Name, name) \
   1247   case NAME##_TYPE:                        \
   1248     accumulator->Put('<');                 \
   1249     accumulator->Add(#Name);               \
   1250     accumulator->Put('>');                 \
   1251     break;
   1252   STRUCT_LIST(MAKE_STRUCT_CASE)
   1253 #undef MAKE_STRUCT_CASE
   1254     case CODE_TYPE:
   1255       accumulator->Add("<Code>");
   1256       break;
   1257     case ODDBALL_TYPE: {
   1258       if (IsUndefined())
   1259         accumulator->Add("<undefined>");
   1260       else if (IsTheHole())
   1261         accumulator->Add("<the hole>");
   1262       else if (IsNull())
   1263         accumulator->Add("<null>");
   1264       else if (IsTrue())
   1265         accumulator->Add("<true>");
   1266       else if (IsFalse())
   1267         accumulator->Add("<false>");
   1268       else
   1269         accumulator->Add("<Odd Oddball>");
   1270       break;
   1271     }
   1272     case HEAP_NUMBER_TYPE:
   1273       accumulator->Add("<Number: ");
   1274       HeapNumber::cast(this)->HeapNumberPrint(accumulator);
   1275       accumulator->Put('>');
   1276       break;
   1277     case JS_PROXY_TYPE:
   1278       accumulator->Add("<JSProxy>");
   1279       break;
   1280     case JS_FUNCTION_PROXY_TYPE:
   1281       accumulator->Add("<JSFunctionProxy>");
   1282       break;
   1283     case FOREIGN_TYPE:
   1284       accumulator->Add("<Foreign>");
   1285       break;
   1286     case JS_GLOBAL_PROPERTY_CELL_TYPE:
   1287       accumulator->Add("Cell for ");
   1288       JSGlobalPropertyCell::cast(this)->value()->ShortPrint(accumulator);
   1289       break;
   1290     default:
   1291       accumulator->Add("<Other heap object (%d)>", map()->instance_type());
   1292       break;
   1293   }
   1294 }
   1295 
   1296 
   1297 void HeapObject::Iterate(ObjectVisitor* v) {
   1298   // Handle header
   1299   IteratePointer(v, kMapOffset);
   1300   // Handle object body
   1301   Map* m = map();
   1302   IterateBody(m->instance_type(), SizeFromMap(m), v);
   1303 }
   1304 
   1305 
   1306 void HeapObject::IterateBody(InstanceType type, int object_size,
   1307                              ObjectVisitor* v) {
   1308   // Avoiding <Type>::cast(this) because it accesses the map pointer field.
   1309   // During GC, the map pointer field is encoded.
   1310   if (type < FIRST_NONSTRING_TYPE) {
   1311     switch (type & kStringRepresentationMask) {
   1312       case kSeqStringTag:
   1313         break;
   1314       case kConsStringTag:
   1315         ConsString::BodyDescriptor::IterateBody(this, v);
   1316         break;
   1317       case kSlicedStringTag:
   1318         SlicedString::BodyDescriptor::IterateBody(this, v);
   1319         break;
   1320       case kExternalStringTag:
   1321         if ((type & kStringEncodingMask) == kAsciiStringTag) {
   1322           reinterpret_cast<ExternalAsciiString*>(this)->
   1323               ExternalAsciiStringIterateBody(v);
   1324         } else {
   1325           reinterpret_cast<ExternalTwoByteString*>(this)->
   1326               ExternalTwoByteStringIterateBody(v);
   1327         }
   1328         break;
   1329     }
   1330     return;
   1331   }
   1332 
   1333   switch (type) {
   1334     case FIXED_ARRAY_TYPE:
   1335       FixedArray::BodyDescriptor::IterateBody(this, object_size, v);
   1336       break;
   1337     case FIXED_DOUBLE_ARRAY_TYPE:
   1338       break;
   1339     case JS_OBJECT_TYPE:
   1340     case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
   1341     case JS_VALUE_TYPE:
   1342     case JS_DATE_TYPE:
   1343     case JS_ARRAY_TYPE:
   1344     case JS_SET_TYPE:
   1345     case JS_MAP_TYPE:
   1346     case JS_WEAK_MAP_TYPE:
   1347     case JS_REGEXP_TYPE:
   1348     case JS_GLOBAL_PROXY_TYPE:
   1349     case JS_GLOBAL_OBJECT_TYPE:
   1350     case JS_BUILTINS_OBJECT_TYPE:
   1351     case JS_MESSAGE_OBJECT_TYPE:
   1352       JSObject::BodyDescriptor::IterateBody(this, object_size, v);
   1353       break;
   1354     case JS_FUNCTION_TYPE:
   1355       reinterpret_cast<JSFunction*>(this)
   1356           ->JSFunctionIterateBody(object_size, v);
   1357       break;
   1358     case ODDBALL_TYPE:
   1359       Oddball::BodyDescriptor::IterateBody(this, v);
   1360       break;
   1361     case JS_PROXY_TYPE:
   1362       JSProxy::BodyDescriptor::IterateBody(this, v);
   1363       break;
   1364     case JS_FUNCTION_PROXY_TYPE:
   1365       JSFunctionProxy::BodyDescriptor::IterateBody(this, v);
   1366       break;
   1367     case FOREIGN_TYPE:
   1368       reinterpret_cast<Foreign*>(this)->ForeignIterateBody(v);
   1369       break;
   1370     case MAP_TYPE:
   1371       Map::BodyDescriptor::IterateBody(this, v);
   1372       break;
   1373     case CODE_TYPE:
   1374       reinterpret_cast<Code*>(this)->CodeIterateBody(v);
   1375       break;
   1376     case JS_GLOBAL_PROPERTY_CELL_TYPE:
   1377       JSGlobalPropertyCell::BodyDescriptor::IterateBody(this, v);
   1378       break;
   1379     case HEAP_NUMBER_TYPE:
   1380     case FILLER_TYPE:
   1381     case BYTE_ARRAY_TYPE:
   1382     case FREE_SPACE_TYPE:
   1383     case EXTERNAL_PIXEL_ARRAY_TYPE:
   1384     case EXTERNAL_BYTE_ARRAY_TYPE:
   1385     case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
   1386     case EXTERNAL_SHORT_ARRAY_TYPE:
   1387     case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
   1388     case EXTERNAL_INT_ARRAY_TYPE:
   1389     case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
   1390     case EXTERNAL_FLOAT_ARRAY_TYPE:
   1391     case EXTERNAL_DOUBLE_ARRAY_TYPE:
   1392       break;
   1393     case SHARED_FUNCTION_INFO_TYPE: {
   1394       SharedFunctionInfo* shared = reinterpret_cast<SharedFunctionInfo*>(this);
   1395       shared->SharedFunctionInfoIterateBody(v);
   1396       break;
   1397     }
   1398 
   1399 #define MAKE_STRUCT_CASE(NAME, Name, name) \
   1400         case NAME##_TYPE:
   1401       STRUCT_LIST(MAKE_STRUCT_CASE)
   1402 #undef MAKE_STRUCT_CASE
   1403       StructBodyDescriptor::IterateBody(this, object_size, v);
   1404       break;
   1405     default:
   1406       PrintF("Unknown type: %d\n", type);
   1407       UNREACHABLE();
   1408   }
   1409 }
   1410 
   1411 
   1412 Object* HeapNumber::HeapNumberToBoolean() {
   1413   // NaN, +0, and -0 should return the false object
   1414 #if __BYTE_ORDER == __LITTLE_ENDIAN
   1415   union IeeeDoubleLittleEndianArchType u;
   1416 #elif __BYTE_ORDER == __BIG_ENDIAN
   1417   union IeeeDoubleBigEndianArchType u;
   1418 #endif
   1419   u.d = value();
   1420   if (u.bits.exp == 2047) {
   1421     // Detect NaN for IEEE double precision floating point.
   1422     if ((u.bits.man_low | u.bits.man_high) != 0)
   1423       return GetHeap()->false_value();
   1424   }
   1425   if (u.bits.exp == 0) {
   1426     // Detect +0, and -0 for IEEE double precision floating point.
   1427     if ((u.bits.man_low | u.bits.man_high) == 0)
   1428       return GetHeap()->false_value();
   1429   }
   1430   return GetHeap()->true_value();
   1431 }
   1432 
   1433 
   1434 void HeapNumber::HeapNumberPrint(FILE* out) {
   1435   PrintF(out, "%.16g", Number());
   1436 }
   1437 
   1438 
   1439 void HeapNumber::HeapNumberPrint(StringStream* accumulator) {
   1440   // The Windows version of vsnprintf can allocate when printing a %g string
   1441   // into a buffer that may not be big enough.  We don't want random memory
   1442   // allocation when producing post-crash stack traces, so we print into a
   1443   // buffer that is plenty big enough for any floating point number, then
   1444   // print that using vsnprintf (which may truncate but never allocate if
   1445   // there is no more space in the buffer).
   1446   EmbeddedVector<char, 100> buffer;
   1447   OS::SNPrintF(buffer, "%.16g", Number());
   1448   accumulator->Add("%s", buffer.start());
   1449 }
   1450 
   1451 
   1452 String* JSReceiver::class_name() {
   1453   if (IsJSFunction() && IsJSFunctionProxy()) {
   1454     return GetHeap()->function_class_symbol();
   1455   }
   1456   if (map()->constructor()->IsJSFunction()) {
   1457     JSFunction* constructor = JSFunction::cast(map()->constructor());
   1458     return String::cast(constructor->shared()->instance_class_name());
   1459   }
   1460   // If the constructor is not present, return "Object".
   1461   return GetHeap()->Object_symbol();
   1462 }
   1463 
   1464 
   1465 String* JSReceiver::constructor_name() {
   1466   if (map()->constructor()->IsJSFunction()) {
   1467     JSFunction* constructor = JSFunction::cast(map()->constructor());
   1468     String* name = String::cast(constructor->shared()->name());
   1469     if (name->length() > 0) return name;
   1470     String* inferred_name = constructor->shared()->inferred_name();
   1471     if (inferred_name->length() > 0) return inferred_name;
   1472     Object* proto = GetPrototype();
   1473     if (proto->IsJSObject()) return JSObject::cast(proto)->constructor_name();
   1474   }
   1475   // TODO(rossberg): what about proxies?
   1476   // If the constructor is not present, return "Object".
   1477   return GetHeap()->Object_symbol();
   1478 }
   1479 
   1480 
   1481 MaybeObject* JSObject::AddFastPropertyUsingMap(Map* new_map,
   1482                                                String* name,
   1483                                                Object* value) {
   1484   int index = new_map->PropertyIndexFor(name);
   1485   if (map()->unused_property_fields() == 0) {
   1486     ASSERT(map()->unused_property_fields() == 0);
   1487     int new_unused = new_map->unused_property_fields();
   1488     Object* values;
   1489     { MaybeObject* maybe_values =
   1490           properties()->CopySize(properties()->length() + new_unused + 1);
   1491       if (!maybe_values->ToObject(&values)) return maybe_values;
   1492     }
   1493     set_properties(FixedArray::cast(values));
   1494   }
   1495   set_map(new_map);
   1496   return FastPropertyAtPut(index, value);
   1497 }
   1498 
   1499 
   1500 static bool IsIdentifier(UnicodeCache* cache,
   1501                          unibrow::CharacterStream* buffer) {
   1502   // Checks whether the buffer contains an identifier (no escape).
   1503   if (!buffer->has_more()) return false;
   1504   if (!cache->IsIdentifierStart(buffer->GetNext())) {
   1505     return false;
   1506   }
   1507   while (buffer->has_more()) {
   1508     if (!cache->IsIdentifierPart(buffer->GetNext())) {
   1509       return false;
   1510     }
   1511   }
   1512   return true;
   1513 }
   1514 
   1515 
   1516 MaybeObject* JSObject::AddFastProperty(String* name,
   1517                                        Object* value,
   1518                                        PropertyAttributes attributes) {
   1519   ASSERT(!IsJSGlobalProxy());
   1520 
   1521   // Normalize the object if the name is an actual string (not the
   1522   // hidden symbols) and is not a real identifier.
   1523   Isolate* isolate = GetHeap()->isolate();
   1524   StringInputBuffer buffer(name);
   1525   if (!IsIdentifier(isolate->unicode_cache(), &buffer)
   1526       && name != isolate->heap()->hidden_symbol()) {
   1527     Object* obj;
   1528     { MaybeObject* maybe_obj =
   1529           NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
   1530       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   1531     }
   1532     return AddSlowProperty(name, value, attributes);
   1533   }
   1534 
   1535   DescriptorArray* old_descriptors = map()->instance_descriptors();
   1536   // Compute the new index for new field.
   1537   int index = map()->NextFreePropertyIndex();
   1538 
   1539   // Allocate new instance descriptors with (name, index) added
   1540   FieldDescriptor new_field(name, index, attributes);
   1541   Object* new_descriptors;
   1542   { MaybeObject* maybe_new_descriptors =
   1543         old_descriptors->CopyInsert(&new_field, REMOVE_TRANSITIONS);
   1544     if (!maybe_new_descriptors->ToObject(&new_descriptors)) {
   1545       return maybe_new_descriptors;
   1546     }
   1547   }
   1548 
   1549   // Only allow map transition if the object isn't the global object and there
   1550   // is not a transition for the name, or there's a transition for the name but
   1551   // it's unrelated to properties.
   1552   int descriptor_index = old_descriptors->Search(name);
   1553 
   1554   // Element transitions are stored in the descriptor for property "", which is
   1555   // not a identifier and should have forced a switch to slow properties above.
   1556   ASSERT(descriptor_index == DescriptorArray::kNotFound ||
   1557       old_descriptors->GetType(descriptor_index) != ELEMENTS_TRANSITION);
   1558   bool can_insert_transition = descriptor_index == DescriptorArray::kNotFound ||
   1559       old_descriptors->GetType(descriptor_index) == ELEMENTS_TRANSITION;
   1560   bool allow_map_transition =
   1561       can_insert_transition &&
   1562       (isolate->context()->global_context()->object_function()->map() != map());
   1563 
   1564   ASSERT(index < map()->inobject_properties() ||
   1565          (index - map()->inobject_properties()) < properties()->length() ||
   1566          map()->unused_property_fields() == 0);
   1567   // Allocate a new map for the object.
   1568   Object* r;
   1569   { MaybeObject* maybe_r = map()->CopyDropDescriptors();
   1570     if (!maybe_r->ToObject(&r)) return maybe_r;
   1571   }
   1572   Map* new_map = Map::cast(r);
   1573   if (allow_map_transition) {
   1574     // Allocate new instance descriptors for the old map with map transition.
   1575     MapTransitionDescriptor d(name, Map::cast(new_map), attributes);
   1576     Object* r;
   1577     { MaybeObject* maybe_r = old_descriptors->CopyInsert(&d, KEEP_TRANSITIONS);
   1578       if (!maybe_r->ToObject(&r)) return maybe_r;
   1579     }
   1580     old_descriptors = DescriptorArray::cast(r);
   1581   }
   1582 
   1583   if (map()->unused_property_fields() == 0) {
   1584     if (properties()->length() > MaxFastProperties()) {
   1585       Object* obj;
   1586       { MaybeObject* maybe_obj =
   1587             NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
   1588         if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   1589       }
   1590       return AddSlowProperty(name, value, attributes);
   1591     }
   1592     // Make room for the new value
   1593     Object* values;
   1594     { MaybeObject* maybe_values =
   1595           properties()->CopySize(properties()->length() + kFieldsAdded);
   1596       if (!maybe_values->ToObject(&values)) return maybe_values;
   1597     }
   1598     set_properties(FixedArray::cast(values));
   1599     new_map->set_unused_property_fields(kFieldsAdded - 1);
   1600   } else {
   1601     new_map->set_unused_property_fields(map()->unused_property_fields() - 1);
   1602   }
   1603   // We have now allocated all the necessary objects.
   1604   // All the changes can be applied at once, so they are atomic.
   1605   map()->set_instance_descriptors(old_descriptors);
   1606   new_map->set_instance_descriptors(DescriptorArray::cast(new_descriptors));
   1607   set_map(new_map);
   1608   return FastPropertyAtPut(index, value);
   1609 }
   1610 
   1611 
   1612 MaybeObject* JSObject::AddConstantFunctionProperty(
   1613     String* name,
   1614     JSFunction* function,
   1615     PropertyAttributes attributes) {
   1616   // Allocate new instance descriptors with (name, function) added
   1617   ConstantFunctionDescriptor d(name, function, attributes);
   1618   Object* new_descriptors;
   1619   { MaybeObject* maybe_new_descriptors =
   1620         map()->instance_descriptors()->CopyInsert(&d, REMOVE_TRANSITIONS);
   1621     if (!maybe_new_descriptors->ToObject(&new_descriptors)) {
   1622       return maybe_new_descriptors;
   1623     }
   1624   }
   1625 
   1626   // Allocate a new map for the object.
   1627   Object* new_map;
   1628   { MaybeObject* maybe_new_map = map()->CopyDropDescriptors();
   1629     if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
   1630   }
   1631 
   1632   DescriptorArray* descriptors = DescriptorArray::cast(new_descriptors);
   1633   Map::cast(new_map)->set_instance_descriptors(descriptors);
   1634   Map* old_map = map();
   1635   set_map(Map::cast(new_map));
   1636 
   1637   // If the old map is the global object map (from new Object()),
   1638   // then transitions are not added to it, so we are done.
   1639   Heap* heap = GetHeap();
   1640   if (old_map == heap->isolate()->context()->global_context()->
   1641       object_function()->map()) {
   1642     return function;
   1643   }
   1644 
   1645   // Do not add CONSTANT_TRANSITIONS to global objects
   1646   if (IsGlobalObject()) {
   1647     return function;
   1648   }
   1649 
   1650   // Add a CONSTANT_TRANSITION descriptor to the old map,
   1651   // so future assignments to this property on other objects
   1652   // of the same type will create a normal field, not a constant function.
   1653   // Don't do this for special properties, with non-trival attributes.
   1654   if (attributes != NONE) {
   1655     return function;
   1656   }
   1657   ConstTransitionDescriptor mark(name, Map::cast(new_map));
   1658   { MaybeObject* maybe_new_descriptors =
   1659         old_map->instance_descriptors()->CopyInsert(&mark, KEEP_TRANSITIONS);
   1660     if (!maybe_new_descriptors->ToObject(&new_descriptors)) {
   1661       // We have accomplished the main goal, so return success.
   1662       return function;
   1663     }
   1664   }
   1665   old_map->set_instance_descriptors(DescriptorArray::cast(new_descriptors));
   1666 
   1667   return function;
   1668 }
   1669 
   1670 
   1671 // Add property in slow mode
   1672 MaybeObject* JSObject::AddSlowProperty(String* name,
   1673                                        Object* value,
   1674                                        PropertyAttributes attributes) {
   1675   ASSERT(!HasFastProperties());
   1676   StringDictionary* dict = property_dictionary();
   1677   Object* store_value = value;
   1678   if (IsGlobalObject()) {
   1679     // In case name is an orphaned property reuse the cell.
   1680     int entry = dict->FindEntry(name);
   1681     if (entry != StringDictionary::kNotFound) {
   1682       store_value = dict->ValueAt(entry);
   1683       JSGlobalPropertyCell::cast(store_value)->set_value(value);
   1684       // Assign an enumeration index to the property and update
   1685       // SetNextEnumerationIndex.
   1686       int index = dict->NextEnumerationIndex();
   1687       PropertyDetails details = PropertyDetails(attributes, NORMAL, index);
   1688       dict->SetNextEnumerationIndex(index + 1);
   1689       dict->SetEntry(entry, name, store_value, details);
   1690       return value;
   1691     }
   1692     Heap* heap = GetHeap();
   1693     { MaybeObject* maybe_store_value =
   1694           heap->AllocateJSGlobalPropertyCell(value);
   1695       if (!maybe_store_value->ToObject(&store_value)) return maybe_store_value;
   1696     }
   1697     JSGlobalPropertyCell::cast(store_value)->set_value(value);
   1698   }
   1699   PropertyDetails details = PropertyDetails(attributes, NORMAL);
   1700   Object* result;
   1701   { MaybeObject* maybe_result = dict->Add(name, store_value, details);
   1702     if (!maybe_result->ToObject(&result)) return maybe_result;
   1703   }
   1704   if (dict != result) set_properties(StringDictionary::cast(result));
   1705   return value;
   1706 }
   1707 
   1708 
   1709 MaybeObject* JSObject::AddProperty(String* name,
   1710                                    Object* value,
   1711                                    PropertyAttributes attributes,
   1712                                    StrictModeFlag strict_mode) {
   1713   ASSERT(!IsJSGlobalProxy());
   1714   Map* map_of_this = map();
   1715   Heap* heap = GetHeap();
   1716   if (!map_of_this->is_extensible()) {
   1717     if (strict_mode == kNonStrictMode) {
   1718       return value;
   1719     } else {
   1720       Handle<Object> args[1] = {Handle<String>(name)};
   1721       return heap->isolate()->Throw(
   1722           *FACTORY->NewTypeError("object_not_extensible",
   1723                                  HandleVector(args, 1)));
   1724     }
   1725   }
   1726   if (HasFastProperties()) {
   1727     // Ensure the descriptor array does not get too big.
   1728     if (map_of_this->instance_descriptors()->number_of_descriptors() <
   1729         DescriptorArray::kMaxNumberOfDescriptors) {
   1730       if (value->IsJSFunction()) {
   1731         return AddConstantFunctionProperty(name,
   1732                                            JSFunction::cast(value),
   1733                                            attributes);
   1734       } else {
   1735         return AddFastProperty(name, value, attributes);
   1736       }
   1737     } else {
   1738       // Normalize the object to prevent very large instance descriptors.
   1739       // This eliminates unwanted N^2 allocation and lookup behavior.
   1740       Object* obj;
   1741       { MaybeObject* maybe_obj =
   1742             NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
   1743         if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   1744       }
   1745     }
   1746   }
   1747   return AddSlowProperty(name, value, attributes);
   1748 }
   1749 
   1750 
   1751 MaybeObject* JSObject::SetPropertyPostInterceptor(
   1752     String* name,
   1753     Object* value,
   1754     PropertyAttributes attributes,
   1755     StrictModeFlag strict_mode) {
   1756   // Check local property, ignore interceptor.
   1757   LookupResult result(GetIsolate());
   1758   LocalLookupRealNamedProperty(name, &result);
   1759   if (result.IsFound()) {
   1760     // An existing property, a map transition or a null descriptor was
   1761     // found.  Use set property to handle all these cases.
   1762     return SetProperty(&result, name, value, attributes, strict_mode);
   1763   }
   1764   bool found = false;
   1765   MaybeObject* result_object;
   1766   result_object = SetPropertyWithCallbackSetterInPrototypes(name,
   1767                                                             value,
   1768                                                             attributes,
   1769                                                             &found,
   1770                                                             strict_mode);
   1771   if (found) return result_object;
   1772   // Add a new real property.
   1773   return AddProperty(name, value, attributes, strict_mode);
   1774 }
   1775 
   1776 
   1777 MaybeObject* JSObject::ReplaceSlowProperty(String* name,
   1778                                            Object* value,
   1779                                            PropertyAttributes attributes) {
   1780   StringDictionary* dictionary = property_dictionary();
   1781   int old_index = dictionary->FindEntry(name);
   1782   int new_enumeration_index = 0;  // 0 means "Use the next available index."
   1783   if (old_index != -1) {
   1784     // All calls to ReplaceSlowProperty have had all transitions removed.
   1785     ASSERT(!dictionary->ContainsTransition(old_index));
   1786     new_enumeration_index = dictionary->DetailsAt(old_index).index();
   1787   }
   1788 
   1789   PropertyDetails new_details(attributes, NORMAL, new_enumeration_index);
   1790   return SetNormalizedProperty(name, value, new_details);
   1791 }
   1792 
   1793 
   1794 MaybeObject* JSObject::ConvertDescriptorToFieldAndMapTransition(
   1795     String* name,
   1796     Object* new_value,
   1797     PropertyAttributes attributes) {
   1798   Map* old_map = map();
   1799   Object* result;
   1800   { MaybeObject* maybe_result =
   1801         ConvertDescriptorToField(name, new_value, attributes);
   1802     if (!maybe_result->ToObject(&result)) return maybe_result;
   1803   }
   1804   // If we get to this point we have succeeded - do not return failure
   1805   // after this point.  Later stuff is optional.
   1806   if (!HasFastProperties()) {
   1807     return result;
   1808   }
   1809   // Do not add transitions to the map of "new Object()".
   1810   if (map() == GetIsolate()->context()->global_context()->
   1811       object_function()->map()) {
   1812     return result;
   1813   }
   1814 
   1815   MapTransitionDescriptor transition(name,
   1816                                      map(),
   1817                                      attributes);
   1818   Object* new_descriptors;
   1819   { MaybeObject* maybe_new_descriptors = old_map->instance_descriptors()->
   1820         CopyInsert(&transition, KEEP_TRANSITIONS);
   1821     if (!maybe_new_descriptors->ToObject(&new_descriptors)) {
   1822       return result;  // Yes, return _result_.
   1823     }
   1824   }
   1825   old_map->set_instance_descriptors(DescriptorArray::cast(new_descriptors));
   1826   return result;
   1827 }
   1828 
   1829 
   1830 MaybeObject* JSObject::ConvertDescriptorToField(String* name,
   1831                                                 Object* new_value,
   1832                                                 PropertyAttributes attributes) {
   1833   if (map()->unused_property_fields() == 0 &&
   1834       properties()->length() > MaxFastProperties()) {
   1835     Object* obj;
   1836     { MaybeObject* maybe_obj =
   1837           NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
   1838       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   1839     }
   1840     return ReplaceSlowProperty(name, new_value, attributes);
   1841   }
   1842 
   1843   int index = map()->NextFreePropertyIndex();
   1844   FieldDescriptor new_field(name, index, attributes);
   1845   // Make a new DescriptorArray replacing an entry with FieldDescriptor.
   1846   Object* descriptors_unchecked;
   1847   { MaybeObject* maybe_descriptors_unchecked = map()->instance_descriptors()->
   1848                                   CopyInsert(&new_field, REMOVE_TRANSITIONS);
   1849     if (!maybe_descriptors_unchecked->ToObject(&descriptors_unchecked)) {
   1850       return maybe_descriptors_unchecked;
   1851     }
   1852   }
   1853   DescriptorArray* new_descriptors =
   1854       DescriptorArray::cast(descriptors_unchecked);
   1855 
   1856   // Make a new map for the object.
   1857   Object* new_map_unchecked;
   1858   { MaybeObject* maybe_new_map_unchecked = map()->CopyDropDescriptors();
   1859     if (!maybe_new_map_unchecked->ToObject(&new_map_unchecked)) {
   1860       return maybe_new_map_unchecked;
   1861     }
   1862   }
   1863   Map* new_map = Map::cast(new_map_unchecked);
   1864   new_map->set_instance_descriptors(new_descriptors);
   1865 
   1866   // Make new properties array if necessary.
   1867   FixedArray* new_properties = 0;  // Will always be NULL or a valid pointer.
   1868   int new_unused_property_fields = map()->unused_property_fields() - 1;
   1869   if (map()->unused_property_fields() == 0) {
   1870     new_unused_property_fields = kFieldsAdded - 1;
   1871     Object* new_properties_object;
   1872     { MaybeObject* maybe_new_properties_object =
   1873           properties()->CopySize(properties()->length() + kFieldsAdded);
   1874       if (!maybe_new_properties_object->ToObject(&new_properties_object)) {
   1875         return maybe_new_properties_object;
   1876       }
   1877     }
   1878     new_properties = FixedArray::cast(new_properties_object);
   1879   }
   1880 
   1881   // Update pointers to commit changes.
   1882   // Object points to the new map.
   1883   new_map->set_unused_property_fields(new_unused_property_fields);
   1884   set_map(new_map);
   1885   if (new_properties) {
   1886     set_properties(FixedArray::cast(new_properties));
   1887   }
   1888   return FastPropertyAtPut(index, new_value);
   1889 }
   1890 
   1891 
   1892 
   1893 MaybeObject* JSObject::SetPropertyWithInterceptor(
   1894     String* name,
   1895     Object* value,
   1896     PropertyAttributes attributes,
   1897     StrictModeFlag strict_mode) {
   1898   Isolate* isolate = GetIsolate();
   1899   HandleScope scope(isolate);
   1900   Handle<JSObject> this_handle(this);
   1901   Handle<String> name_handle(name);
   1902   Handle<Object> value_handle(value, isolate);
   1903   Handle<InterceptorInfo> interceptor(GetNamedInterceptor());
   1904   if (!interceptor->setter()->IsUndefined()) {
   1905     LOG(isolate, ApiNamedPropertyAccess("interceptor-named-set", this, name));
   1906     CustomArguments args(isolate, interceptor->data(), this, this);
   1907     v8::AccessorInfo info(args.end());
   1908     v8::NamedPropertySetter setter =
   1909         v8::ToCData<v8::NamedPropertySetter>(interceptor->setter());
   1910     v8::Handle<v8::Value> result;
   1911     {
   1912       // Leaving JavaScript.
   1913       VMState state(isolate, EXTERNAL);
   1914       Handle<Object> value_unhole(value->IsTheHole() ?
   1915                                   isolate->heap()->undefined_value() :
   1916                                   value,
   1917                                   isolate);
   1918       result = setter(v8::Utils::ToLocal(name_handle),
   1919                       v8::Utils::ToLocal(value_unhole),
   1920                       info);
   1921     }
   1922     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   1923     if (!result.IsEmpty()) return *value_handle;
   1924   }
   1925   MaybeObject* raw_result =
   1926       this_handle->SetPropertyPostInterceptor(*name_handle,
   1927                                               *value_handle,
   1928                                               attributes,
   1929                                               strict_mode);
   1930   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   1931   return raw_result;
   1932 }
   1933 
   1934 
   1935 Handle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object,
   1936                                        Handle<String> key,
   1937                                        Handle<Object> value,
   1938                                        PropertyAttributes attributes,
   1939                                        StrictModeFlag strict_mode) {
   1940   CALL_HEAP_FUNCTION(object->GetIsolate(),
   1941                      object->SetProperty(*key, *value, attributes, strict_mode),
   1942                      Object);
   1943 }
   1944 
   1945 
   1946 MaybeObject* JSReceiver::SetProperty(String* name,
   1947                                      Object* value,
   1948                                      PropertyAttributes attributes,
   1949                                      StrictModeFlag strict_mode) {
   1950   LookupResult result(GetIsolate());
   1951   LocalLookup(name, &result);
   1952   return SetProperty(&result, name, value, attributes, strict_mode);
   1953 }
   1954 
   1955 
   1956 MaybeObject* JSObject::SetPropertyWithCallback(Object* structure,
   1957                                                String* name,
   1958                                                Object* value,
   1959                                                JSObject* holder,
   1960                                                StrictModeFlag strict_mode) {
   1961   Isolate* isolate = GetIsolate();
   1962   HandleScope scope(isolate);
   1963 
   1964   // We should never get here to initialize a const with the hole
   1965   // value since a const declaration would conflict with the setter.
   1966   ASSERT(!value->IsTheHole());
   1967   Handle<Object> value_handle(value, isolate);
   1968 
   1969   // To accommodate both the old and the new api we switch on the
   1970   // data structure used to store the callbacks.  Eventually foreign
   1971   // callbacks should be phased out.
   1972   if (structure->IsForeign()) {
   1973     AccessorDescriptor* callback =
   1974         reinterpret_cast<AccessorDescriptor*>(
   1975             Foreign::cast(structure)->foreign_address());
   1976     MaybeObject* obj = (callback->setter)(this,  value, callback->data);
   1977     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   1978     if (obj->IsFailure()) return obj;
   1979     return *value_handle;
   1980   }
   1981 
   1982   if (structure->IsAccessorInfo()) {
   1983     // api style callbacks
   1984     AccessorInfo* data = AccessorInfo::cast(structure);
   1985     Object* call_obj = data->setter();
   1986     v8::AccessorSetter call_fun = v8::ToCData<v8::AccessorSetter>(call_obj);
   1987     if (call_fun == NULL) return value;
   1988     Handle<String> key(name);
   1989     LOG(isolate, ApiNamedPropertyAccess("store", this, name));
   1990     CustomArguments args(isolate, data->data(), this, JSObject::cast(holder));
   1991     v8::AccessorInfo info(args.end());
   1992     {
   1993       // Leaving JavaScript.
   1994       VMState state(isolate, EXTERNAL);
   1995       call_fun(v8::Utils::ToLocal(key),
   1996                v8::Utils::ToLocal(value_handle),
   1997                info);
   1998     }
   1999     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   2000     return *value_handle;
   2001   }
   2002 
   2003   if (structure->IsAccessorPair()) {
   2004     Object* setter = AccessorPair::cast(structure)->setter();
   2005     if (setter->IsSpecFunction()) {
   2006       // TODO(rossberg): nicer would be to cast to some JSCallable here...
   2007      return SetPropertyWithDefinedSetter(JSReceiver::cast(setter), value);
   2008     } else {
   2009       if (strict_mode == kNonStrictMode) {
   2010         return value;
   2011       }
   2012       Handle<String> key(name);
   2013       Handle<Object> holder_handle(holder, isolate);
   2014       Handle<Object> args[2] = { key, holder_handle };
   2015       return isolate->Throw(
   2016           *isolate->factory()->NewTypeError("no_setter_in_callback",
   2017                                             HandleVector(args, 2)));
   2018     }
   2019   }
   2020 
   2021   UNREACHABLE();
   2022   return NULL;
   2023 }
   2024 
   2025 
   2026 MaybeObject* JSReceiver::SetPropertyWithDefinedSetter(JSReceiver* setter,
   2027                                                       Object* value) {
   2028   Isolate* isolate = GetIsolate();
   2029   Handle<Object> value_handle(value, isolate);
   2030   Handle<JSReceiver> fun(setter, isolate);
   2031   Handle<JSReceiver> self(this, isolate);
   2032 #ifdef ENABLE_DEBUGGER_SUPPORT
   2033   Debug* debug = isolate->debug();
   2034   // Handle stepping into a setter if step into is active.
   2035   // TODO(rossberg): should this apply to getters that are function proxies?
   2036   if (debug->StepInActive() && fun->IsJSFunction()) {
   2037     debug->HandleStepIn(
   2038         Handle<JSFunction>::cast(fun), Handle<Object>::null(), 0, false);
   2039   }
   2040 #endif
   2041   bool has_pending_exception;
   2042   Handle<Object> argv[] = { value_handle };
   2043   Execution::Call(fun, self, ARRAY_SIZE(argv), argv, &has_pending_exception);
   2044   // Check for pending exception and return the result.
   2045   if (has_pending_exception) return Failure::Exception();
   2046   return *value_handle;
   2047 }
   2048 
   2049 
   2050 void JSObject::LookupCallbackSetterInPrototypes(String* name,
   2051                                                 LookupResult* result) {
   2052   Heap* heap = GetHeap();
   2053   for (Object* pt = GetPrototype();
   2054        pt != heap->null_value();
   2055        pt = pt->GetPrototype()) {
   2056     if (pt->IsJSProxy()) {
   2057       return result->HandlerResult(JSProxy::cast(pt));
   2058     }
   2059     JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result);
   2060     if (result->IsProperty()) {
   2061       if (result->type() == CALLBACKS && !result->IsReadOnly()) return;
   2062       // Found non-callback or read-only callback, stop looking.
   2063       break;
   2064     }
   2065   }
   2066   result->NotFound();
   2067 }
   2068 
   2069 
   2070 MaybeObject* JSObject::SetElementWithCallbackSetterInPrototypes(
   2071     uint32_t index,
   2072     Object* value,
   2073     bool* found,
   2074     StrictModeFlag strict_mode) {
   2075   Heap* heap = GetHeap();
   2076   for (Object* pt = GetPrototype();
   2077        pt != heap->null_value();
   2078        pt = pt->GetPrototype()) {
   2079     if (pt->IsJSProxy()) {
   2080       String* name;
   2081       MaybeObject* maybe = GetHeap()->Uint32ToString(index);
   2082       if (!maybe->To<String>(&name)) {
   2083         *found = true;  // Force abort
   2084         return maybe;
   2085       }
   2086       return JSProxy::cast(pt)->SetPropertyWithHandlerIfDefiningSetter(
   2087           name, value, NONE, strict_mode, found);
   2088     }
   2089     if (!JSObject::cast(pt)->HasDictionaryElements()) {
   2090       continue;
   2091     }
   2092     SeededNumberDictionary* dictionary =
   2093         JSObject::cast(pt)->element_dictionary();
   2094     int entry = dictionary->FindEntry(index);
   2095     if (entry != SeededNumberDictionary::kNotFound) {
   2096       PropertyDetails details = dictionary->DetailsAt(entry);
   2097       if (details.type() == CALLBACKS) {
   2098         *found = true;
   2099         return SetElementWithCallback(dictionary->ValueAt(entry),
   2100                                       index,
   2101                                       value,
   2102                                       JSObject::cast(pt),
   2103                                       strict_mode);
   2104       }
   2105     }
   2106   }
   2107   *found = false;
   2108   return heap->the_hole_value();
   2109 }
   2110 
   2111 MaybeObject* JSObject::SetPropertyWithCallbackSetterInPrototypes(
   2112     String* name,
   2113     Object* value,
   2114     PropertyAttributes attributes,
   2115     bool* found,
   2116     StrictModeFlag strict_mode) {
   2117   Heap* heap = GetHeap();
   2118   // We could not find a local property so let's check whether there is an
   2119   // accessor that wants to handle the property.
   2120   LookupResult accessor_result(heap->isolate());
   2121   LookupCallbackSetterInPrototypes(name, &accessor_result);
   2122   if (accessor_result.IsFound()) {
   2123     *found = true;
   2124     if (accessor_result.type() == CALLBACKS) {
   2125       return SetPropertyWithCallback(accessor_result.GetCallbackObject(),
   2126                                      name,
   2127                                      value,
   2128                                      accessor_result.holder(),
   2129                                      strict_mode);
   2130     } else if (accessor_result.type() == HANDLER) {
   2131       // There is a proxy in the prototype chain. Invoke its
   2132       // getPropertyDescriptor trap.
   2133       bool found = false;
   2134       // SetPropertyWithHandlerIfDefiningSetter can cause GC,
   2135       // make sure to use the handlified references after calling
   2136       // the function.
   2137       Handle<JSObject> self(this);
   2138       Handle<String> hname(name);
   2139       Handle<Object> hvalue(value);
   2140       MaybeObject* result =
   2141           accessor_result.proxy()->SetPropertyWithHandlerIfDefiningSetter(
   2142               name, value, attributes, strict_mode, &found);
   2143       if (found) return result;
   2144       // The proxy does not define the property as an accessor.
   2145       // Consequently, it has no effect on setting the receiver.
   2146       return self->AddProperty(*hname, *hvalue, attributes, strict_mode);
   2147     }
   2148   }
   2149   *found = false;
   2150   return heap->the_hole_value();
   2151 }
   2152 
   2153 
   2154 void JSObject::LookupInDescriptor(String* name, LookupResult* result) {
   2155   DescriptorArray* descriptors = map()->instance_descriptors();
   2156   int number = descriptors->SearchWithCache(name);
   2157   if (number != DescriptorArray::kNotFound) {
   2158     result->DescriptorResult(this, descriptors->GetDetails(number), number);
   2159   } else {
   2160     result->NotFound();
   2161   }
   2162 }
   2163 
   2164 
   2165 void Map::LookupInDescriptors(JSObject* holder,
   2166                               String* name,
   2167                               LookupResult* result) {
   2168   DescriptorArray* descriptors = instance_descriptors();
   2169   DescriptorLookupCache* cache =
   2170       GetHeap()->isolate()->descriptor_lookup_cache();
   2171   int number = cache->Lookup(descriptors, name);
   2172   if (number == DescriptorLookupCache::kAbsent) {
   2173     number = descriptors->Search(name);
   2174     cache->Update(descriptors, name, number);
   2175   }
   2176   if (number != DescriptorArray::kNotFound) {
   2177     result->DescriptorResult(holder, descriptors->GetDetails(number), number);
   2178   } else {
   2179     result->NotFound();
   2180   }
   2181 }
   2182 
   2183 
   2184 static bool ContainsMap(MapHandleList* maps, Handle<Map> map) {
   2185   ASSERT(!map.is_null());
   2186   for (int i = 0; i < maps->length(); ++i) {
   2187     if (!maps->at(i).is_null() && maps->at(i).is_identical_to(map)) return true;
   2188   }
   2189   return false;
   2190 }
   2191 
   2192 
   2193 template <class T>
   2194 static Handle<T> MaybeNull(T* p) {
   2195   if (p == NULL) return Handle<T>::null();
   2196   return Handle<T>(p);
   2197 }
   2198 
   2199 
   2200 Handle<Map> Map::FindTransitionedMap(MapHandleList* candidates) {
   2201   ElementsKind elms_kind = elements_kind();
   2202   if (elms_kind == FAST_DOUBLE_ELEMENTS) {
   2203     bool dummy = true;
   2204     Handle<Map> fast_map =
   2205         MaybeNull(LookupElementsTransitionMap(FAST_ELEMENTS, &dummy));
   2206     if (!fast_map.is_null() && ContainsMap(candidates, fast_map)) {
   2207       return fast_map;
   2208     }
   2209     return Handle<Map>::null();
   2210   }
   2211   if (elms_kind == FAST_SMI_ONLY_ELEMENTS) {
   2212     bool dummy = true;
   2213     Handle<Map> double_map =
   2214         MaybeNull(LookupElementsTransitionMap(FAST_DOUBLE_ELEMENTS, &dummy));
   2215     // In the current implementation, if the DOUBLE map doesn't exist, the
   2216     // FAST map can't exist either.
   2217     if (double_map.is_null()) return Handle<Map>::null();
   2218     Handle<Map> fast_map =
   2219         MaybeNull(double_map->LookupElementsTransitionMap(FAST_ELEMENTS,
   2220                                                           &dummy));
   2221     if (!fast_map.is_null() && ContainsMap(candidates, fast_map)) {
   2222       return fast_map;
   2223     }
   2224     if (ContainsMap(candidates, double_map)) return double_map;
   2225   }
   2226   return Handle<Map>::null();
   2227 }
   2228 
   2229 static Map* GetElementsTransitionMapFromDescriptor(Object* descriptor_contents,
   2230                                                    ElementsKind elements_kind) {
   2231   if (descriptor_contents->IsMap()) {
   2232     Map* map = Map::cast(descriptor_contents);
   2233     if (map->elements_kind() == elements_kind) {
   2234       return map;
   2235     }
   2236     return NULL;
   2237   }
   2238 
   2239   FixedArray* map_array = FixedArray::cast(descriptor_contents);
   2240   for (int i = 0; i < map_array->length(); ++i) {
   2241     Object* current = map_array->get(i);
   2242     // Skip undefined slots, they are sentinels for reclaimed maps.
   2243     if (!current->IsUndefined()) {
   2244       Map* current_map = Map::cast(map_array->get(i));
   2245       if (current_map->elements_kind() == elements_kind) {
   2246         return current_map;
   2247       }
   2248     }
   2249   }
   2250 
   2251   return NULL;
   2252 }
   2253 
   2254 
   2255 static MaybeObject* AddElementsTransitionMapToDescriptor(
   2256     Object* descriptor_contents,
   2257     Map* new_map) {
   2258   // Nothing was in the descriptor for an ELEMENTS_TRANSITION,
   2259   // simply add the map.
   2260   if (descriptor_contents == NULL) {
   2261     return new_map;
   2262   }
   2263 
   2264   // There was already a map in the descriptor, create a 2-element FixedArray
   2265   // to contain the existing map plus the new one.
   2266   FixedArray* new_array;
   2267   Heap* heap = new_map->GetHeap();
   2268   if (descriptor_contents->IsMap()) {
   2269     // Must tenure, DescriptorArray expects no new-space objects.
   2270     MaybeObject* maybe_new_array = heap->AllocateFixedArray(2, TENURED);
   2271     if (!maybe_new_array->To<FixedArray>(&new_array)) {
   2272       return maybe_new_array;
   2273     }
   2274     new_array->set(0, descriptor_contents);
   2275     new_array->set(1, new_map);
   2276     return new_array;
   2277   }
   2278 
   2279   // The descriptor already contained a list of maps for different ElementKinds
   2280   // of ELEMENTS_TRANSITION, first check the existing array for an undefined
   2281   // slot, and if that's not available, create a FixedArray to hold the existing
   2282   // maps plus the new one and fill it in.
   2283   FixedArray* array = FixedArray::cast(descriptor_contents);
   2284   for (int i = 0; i < array->length(); ++i) {
   2285     if (array->get(i)->IsUndefined()) {
   2286       array->set(i, new_map);
   2287       return array;
   2288     }
   2289   }
   2290 
   2291   // Must tenure, DescriptorArray expects no new-space objects.
   2292   MaybeObject* maybe_new_array =
   2293       heap->AllocateFixedArray(array->length() + 1, TENURED);
   2294   if (!maybe_new_array->To<FixedArray>(&new_array)) {
   2295     return maybe_new_array;
   2296   }
   2297   int i = 0;
   2298   while (i < array->length()) {
   2299     new_array->set(i, array->get(i));
   2300     ++i;
   2301   }
   2302   new_array->set(i, new_map);
   2303   return new_array;
   2304 }
   2305 
   2306 
   2307 String* Map::elements_transition_sentinel_name() {
   2308   return GetHeap()->empty_symbol();
   2309 }
   2310 
   2311 
   2312 Object* Map::GetDescriptorContents(String* sentinel_name,
   2313                                    bool* safe_to_add_transition) {
   2314   // Get the cached index for the descriptors lookup, or find and cache it.
   2315   DescriptorArray* descriptors = instance_descriptors();
   2316   DescriptorLookupCache* cache = GetIsolate()->descriptor_lookup_cache();
   2317   int index = cache->Lookup(descriptors, sentinel_name);
   2318   if (index == DescriptorLookupCache::kAbsent) {
   2319     index = descriptors->Search(sentinel_name);
   2320     cache->Update(descriptors, sentinel_name, index);
   2321   }
   2322   // If the transition already exists, return its descriptor.
   2323   if (index != DescriptorArray::kNotFound) {
   2324     PropertyDetails details(descriptors->GetDetails(index));
   2325     if (details.type() == ELEMENTS_TRANSITION) {
   2326       return descriptors->GetValue(index);
   2327     } else {
   2328       if (safe_to_add_transition != NULL) {
   2329         *safe_to_add_transition = false;
   2330       }
   2331     }
   2332   }
   2333   return NULL;
   2334 }
   2335 
   2336 
   2337 Map* Map::LookupElementsTransitionMap(ElementsKind elements_kind,
   2338                                       bool* safe_to_add_transition) {
   2339   // Special case: indirect SMI->FAST transition (cf. comment in
   2340   // AddElementsTransition()).
   2341   if (this->elements_kind() == FAST_SMI_ONLY_ELEMENTS &&
   2342       elements_kind == FAST_ELEMENTS) {
   2343     Map* double_map = this->LookupElementsTransitionMap(FAST_DOUBLE_ELEMENTS,
   2344                                                         safe_to_add_transition);
   2345     if (double_map == NULL) return double_map;
   2346     return double_map->LookupElementsTransitionMap(FAST_ELEMENTS,
   2347                                                    safe_to_add_transition);
   2348   }
   2349   Object* descriptor_contents = GetDescriptorContents(
   2350       elements_transition_sentinel_name(), safe_to_add_transition);
   2351   if (descriptor_contents != NULL) {
   2352     Map* maybe_transition_map =
   2353         GetElementsTransitionMapFromDescriptor(descriptor_contents,
   2354                                                elements_kind);
   2355     ASSERT(maybe_transition_map == NULL || maybe_transition_map->IsMap());
   2356     return maybe_transition_map;
   2357   }
   2358   return NULL;
   2359 }
   2360 
   2361 
   2362 MaybeObject* Map::AddElementsTransition(ElementsKind elements_kind,
   2363                                         Map* transitioned_map) {
   2364   // The map transition graph should be a tree, therefore the transition
   2365   // from SMI to FAST elements is not done directly, but by going through
   2366   // DOUBLE elements first.
   2367   if (this->elements_kind() == FAST_SMI_ONLY_ELEMENTS &&
   2368       elements_kind == FAST_ELEMENTS) {
   2369     bool safe_to_add = true;
   2370     Map* double_map = this->LookupElementsTransitionMap(
   2371         FAST_DOUBLE_ELEMENTS, &safe_to_add);
   2372     // This method is only called when safe_to_add_transition has been found
   2373     // to be true earlier.
   2374     ASSERT(safe_to_add);
   2375 
   2376     if (double_map == NULL) {
   2377       MaybeObject* maybe_map = this->CopyDropTransitions();
   2378       if (!maybe_map->To(&double_map)) return maybe_map;
   2379       double_map->set_elements_kind(FAST_DOUBLE_ELEMENTS);
   2380       MaybeObject* maybe_double_transition = this->AddElementsTransition(
   2381           FAST_DOUBLE_ELEMENTS, double_map);
   2382       if (maybe_double_transition->IsFailure()) return maybe_double_transition;
   2383     }
   2384     return double_map->AddElementsTransition(FAST_ELEMENTS, transitioned_map);
   2385   }
   2386 
   2387   bool safe_to_add_transition = true;
   2388   Object* descriptor_contents = GetDescriptorContents(
   2389       elements_transition_sentinel_name(), &safe_to_add_transition);
   2390   // This method is only called when safe_to_add_transition has been found
   2391   // to be true earlier.
   2392   ASSERT(safe_to_add_transition);
   2393   MaybeObject* maybe_new_contents =
   2394       AddElementsTransitionMapToDescriptor(descriptor_contents,
   2395                                            transitioned_map);
   2396   Object* new_contents;
   2397   if (!maybe_new_contents->ToObject(&new_contents)) {
   2398     return maybe_new_contents;
   2399   }
   2400 
   2401   ElementsTransitionDescriptor desc(elements_transition_sentinel_name(),
   2402                                     new_contents);
   2403   Object* new_descriptors;
   2404   MaybeObject* maybe_new_descriptors =
   2405       instance_descriptors()->CopyInsert(&desc, KEEP_TRANSITIONS);
   2406   if (!maybe_new_descriptors->ToObject(&new_descriptors)) {
   2407     return maybe_new_descriptors;
   2408   }
   2409   set_instance_descriptors(DescriptorArray::cast(new_descriptors));
   2410   return this;
   2411 }
   2412 
   2413 
   2414 Handle<Map> JSObject::GetElementsTransitionMap(Handle<JSObject> object,
   2415                                                ElementsKind to_kind) {
   2416   Isolate* isolate = object->GetIsolate();
   2417   CALL_HEAP_FUNCTION(isolate,
   2418                      object->GetElementsTransitionMap(isolate, to_kind),
   2419                      Map);
   2420 }
   2421 
   2422 
   2423 MaybeObject* JSObject::GetElementsTransitionMapSlow(ElementsKind to_kind) {
   2424   Map* current_map = map();
   2425   ElementsKind from_kind = current_map->elements_kind();
   2426 
   2427   if (from_kind == to_kind) return current_map;
   2428 
   2429   // Only objects with FastProperties can have DescriptorArrays and can track
   2430   // element-related maps. Also don't add descriptors to maps that are shared.
   2431   bool safe_to_add_transition = HasFastProperties() &&
   2432       !current_map->IsUndefined() &&
   2433       !current_map->is_shared();
   2434 
   2435   // Prevent long chains of DICTIONARY -> FAST_ELEMENTS maps caused by objects
   2436   // with elements that switch back and forth between dictionary and fast
   2437   // element mode.
   2438   if (from_kind == DICTIONARY_ELEMENTS && to_kind == FAST_ELEMENTS) {
   2439     safe_to_add_transition = false;
   2440   }
   2441 
   2442   if (safe_to_add_transition) {
   2443     // It's only safe to manipulate the descriptor array if it would be
   2444     // safe to add a transition.
   2445     Map* maybe_transition_map = current_map->LookupElementsTransitionMap(
   2446         to_kind, &safe_to_add_transition);
   2447     if (maybe_transition_map != NULL) {
   2448       return maybe_transition_map;
   2449     }
   2450   }
   2451 
   2452   Map* new_map = NULL;
   2453 
   2454   // No transition to an existing map for the given ElementsKind. Make a new
   2455   // one.
   2456   { MaybeObject* maybe_map = current_map->CopyDropTransitions();
   2457     if (!maybe_map->To(&new_map)) return maybe_map;
   2458   }
   2459 
   2460   new_map->set_elements_kind(to_kind);
   2461 
   2462   // Only remember the map transition if the object's map is NOT equal to the
   2463   // global object_function's map and there is not an already existing
   2464   // non-matching element transition.
   2465   Context* global_context = GetIsolate()->context()->global_context();
   2466   bool allow_map_transition = safe_to_add_transition &&
   2467       (global_context->object_function()->map() != map());
   2468   if (allow_map_transition) {
   2469     MaybeObject* maybe_transition =
   2470         current_map->AddElementsTransition(to_kind, new_map);
   2471     if (maybe_transition->IsFailure()) return maybe_transition;
   2472   }
   2473   return new_map;
   2474 }
   2475 
   2476 
   2477 void JSObject::LocalLookupRealNamedProperty(String* name,
   2478                                             LookupResult* result) {
   2479   if (IsJSGlobalProxy()) {
   2480     Object* proto = GetPrototype();
   2481     if (proto->IsNull()) return result->NotFound();
   2482     ASSERT(proto->IsJSGlobalObject());
   2483     // A GlobalProxy's prototype should always be a proper JSObject.
   2484     return JSObject::cast(proto)->LocalLookupRealNamedProperty(name, result);
   2485   }
   2486 
   2487   if (HasFastProperties()) {
   2488     LookupInDescriptor(name, result);
   2489     if (result->IsFound()) {
   2490       // A property, a map transition or a null descriptor was found.
   2491       // We return all of these result types because
   2492       // LocalLookupRealNamedProperty is used when setting properties
   2493       // where map transitions and null descriptors are handled.
   2494       ASSERT(result->holder() == this && result->type() != NORMAL);
   2495       // Disallow caching for uninitialized constants. These can only
   2496       // occur as fields.
   2497       if (result->IsReadOnly() && result->type() == FIELD &&
   2498           FastPropertyAt(result->GetFieldIndex())->IsTheHole()) {
   2499         result->DisallowCaching();
   2500       }
   2501       return;
   2502     }
   2503   } else {
   2504     int entry = property_dictionary()->FindEntry(name);
   2505     if (entry != StringDictionary::kNotFound) {
   2506       Object* value = property_dictionary()->ValueAt(entry);
   2507       if (IsGlobalObject()) {
   2508         PropertyDetails d = property_dictionary()->DetailsAt(entry);
   2509         if (d.IsDeleted()) {
   2510           result->NotFound();
   2511           return;
   2512         }
   2513         value = JSGlobalPropertyCell::cast(value)->value();
   2514       }
   2515       // Make sure to disallow caching for uninitialized constants
   2516       // found in the dictionary-mode objects.
   2517       if (value->IsTheHole()) result->DisallowCaching();
   2518       result->DictionaryResult(this, entry);
   2519       return;
   2520     }
   2521   }
   2522   result->NotFound();
   2523 }
   2524 
   2525 
   2526 void JSObject::LookupRealNamedProperty(String* name, LookupResult* result) {
   2527   LocalLookupRealNamedProperty(name, result);
   2528   if (result->IsProperty()) return;
   2529 
   2530   LookupRealNamedPropertyInPrototypes(name, result);
   2531 }
   2532 
   2533 
   2534 void JSObject::LookupRealNamedPropertyInPrototypes(String* name,
   2535                                                    LookupResult* result) {
   2536   Heap* heap = GetHeap();
   2537   for (Object* pt = GetPrototype();
   2538        pt != heap->null_value();
   2539        pt = JSObject::cast(pt)->GetPrototype()) {
   2540     JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result);
   2541     if (result->IsProperty() && (result->type() != INTERCEPTOR)) return;
   2542   }
   2543   result->NotFound();
   2544 }
   2545 
   2546 
   2547 // We only need to deal with CALLBACKS and INTERCEPTORS
   2548 MaybeObject* JSObject::SetPropertyWithFailedAccessCheck(
   2549     LookupResult* result,
   2550     String* name,
   2551     Object* value,
   2552     bool check_prototype,
   2553     StrictModeFlag strict_mode) {
   2554   if (check_prototype && !result->IsProperty()) {
   2555     LookupCallbackSetterInPrototypes(name, result);
   2556   }
   2557 
   2558   if (result->IsProperty()) {
   2559     if (!result->IsReadOnly()) {
   2560       switch (result->type()) {
   2561         case CALLBACKS: {
   2562           Object* obj = result->GetCallbackObject();
   2563           if (obj->IsAccessorInfo()) {
   2564             AccessorInfo* info = AccessorInfo::cast(obj);
   2565             if (info->all_can_write()) {
   2566               return SetPropertyWithCallback(result->GetCallbackObject(),
   2567                                              name,
   2568                                              value,
   2569                                              result->holder(),
   2570                                              strict_mode);
   2571             }
   2572           }
   2573           break;
   2574         }
   2575         case INTERCEPTOR: {
   2576           // Try lookup real named properties. Note that only property can be
   2577           // set is callbacks marked as ALL_CAN_WRITE on the prototype chain.
   2578           LookupResult r(GetIsolate());
   2579           LookupRealNamedProperty(name, &r);
   2580           if (r.IsProperty()) {
   2581             return SetPropertyWithFailedAccessCheck(&r,
   2582                                                     name,
   2583                                                     value,
   2584                                                     check_prototype,
   2585                                                     strict_mode);
   2586           }
   2587           break;
   2588         }
   2589         default: {
   2590           break;
   2591         }
   2592       }
   2593     }
   2594   }
   2595 
   2596   Isolate* isolate = GetIsolate();
   2597   HandleScope scope(isolate);
   2598   Handle<Object> value_handle(value);
   2599   isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET);
   2600   return *value_handle;
   2601 }
   2602 
   2603 
   2604 MaybeObject* JSReceiver::SetProperty(LookupResult* result,
   2605                                      String* key,
   2606                                      Object* value,
   2607                                      PropertyAttributes attributes,
   2608                                      StrictModeFlag strict_mode) {
   2609   if (result->IsFound() && result->type() == HANDLER) {
   2610     return result->proxy()->SetPropertyWithHandler(
   2611         key, value, attributes, strict_mode);
   2612   } else {
   2613     return JSObject::cast(this)->SetPropertyForResult(
   2614         result, key, value, attributes, strict_mode);
   2615   }
   2616 }
   2617 
   2618 
   2619 bool JSProxy::HasPropertyWithHandler(String* name_raw) {
   2620   Isolate* isolate = GetIsolate();
   2621   HandleScope scope(isolate);
   2622   Handle<Object> receiver(this);
   2623   Handle<Object> name(name_raw);
   2624 
   2625   Handle<Object> args[] = { name };
   2626   Handle<Object> result = CallTrap(
   2627     "has", isolate->derived_has_trap(), ARRAY_SIZE(args), args);
   2628   if (isolate->has_pending_exception()) return Failure::Exception();
   2629 
   2630   return result->ToBoolean()->IsTrue();
   2631 }
   2632 
   2633 
   2634 MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyWithHandler(
   2635     String* name_raw,
   2636     Object* value_raw,
   2637     PropertyAttributes attributes,
   2638     StrictModeFlag strict_mode) {
   2639   Isolate* isolate = GetIsolate();
   2640   HandleScope scope(isolate);
   2641   Handle<Object> receiver(this);
   2642   Handle<Object> name(name_raw);
   2643   Handle<Object> value(value_raw);
   2644 
   2645   Handle<Object> args[] = { receiver, name, value };
   2646   CallTrap("set", isolate->derived_set_trap(), ARRAY_SIZE(args), args);
   2647   if (isolate->has_pending_exception()) return Failure::Exception();
   2648 
   2649   return *value;
   2650 }
   2651 
   2652 
   2653 MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyWithHandlerIfDefiningSetter(
   2654     String* name_raw,
   2655     Object* value_raw,
   2656     PropertyAttributes attributes,
   2657     StrictModeFlag strict_mode,
   2658     bool* found) {
   2659   *found = true;  // except where defined otherwise...
   2660   Isolate* isolate = GetHeap()->isolate();
   2661   Handle<JSProxy> proxy(this);
   2662   Handle<Object> handler(this->handler());  // Trap might morph proxy.
   2663   Handle<String> name(name_raw);
   2664   Handle<Object> value(value_raw);
   2665   Handle<Object> args[] = { name };
   2666   Handle<Object> result = proxy->CallTrap(
   2667       "getPropertyDescriptor", Handle<Object>(), ARRAY_SIZE(args), args);
   2668   if (isolate->has_pending_exception()) return Failure::Exception();
   2669 
   2670   if (!result->IsUndefined()) {
   2671     // The proxy handler cares about this property.
   2672     // Check whether it is virtualized as an accessor.
   2673     // Emulate [[GetProperty]] semantics for proxies.
   2674     bool has_pending_exception;
   2675     Handle<Object> argv[] = { result };
   2676     Handle<Object> desc =
   2677         Execution::Call(isolate->to_complete_property_descriptor(), result,
   2678                         ARRAY_SIZE(argv), argv, &has_pending_exception);
   2679     if (has_pending_exception) return Failure::Exception();
   2680 
   2681     Handle<String> conf_name =
   2682         isolate->factory()->LookupAsciiSymbol("configurable_");
   2683     Handle<Object> configurable(v8::internal::GetProperty(desc, conf_name));
   2684     ASSERT(!isolate->has_pending_exception());
   2685     if (configurable->IsFalse()) {
   2686       Handle<String> trap =
   2687           isolate->factory()->LookupAsciiSymbol("getPropertyDescriptor");
   2688       Handle<Object> args[] = { handler, trap, name };
   2689       Handle<Object> error = isolate->factory()->NewTypeError(
   2690           "proxy_prop_not_configurable", HandleVector(args, ARRAY_SIZE(args)));
   2691       return isolate->Throw(*error);
   2692     }
   2693     ASSERT(configurable->IsTrue());
   2694 
   2695     // Check for AccessorDescriptor.
   2696     Handle<String> set_name = isolate->factory()->LookupAsciiSymbol("set_");
   2697     Handle<Object> setter(v8::internal::GetProperty(desc, set_name));
   2698     ASSERT(!isolate->has_pending_exception());
   2699     if (!setter->IsUndefined()) {
   2700       // We have a setter -- invoke it.
   2701       // TODO(rossberg): nicer would be to cast to some JSCallable here...
   2702       return proxy->SetPropertyWithDefinedSetter(
   2703           JSReceiver::cast(*setter), *value);
   2704     } else {
   2705       Handle<String> get_name = isolate->factory()->LookupAsciiSymbol("get_");
   2706       Handle<Object> getter(v8::internal::GetProperty(desc, get_name));
   2707       ASSERT(!isolate->has_pending_exception());
   2708       if (!getter->IsUndefined()) {
   2709         // We have a getter but no setter -- the property may not be
   2710         // written. In strict mode, throw an error.
   2711         if (strict_mode == kNonStrictMode) return *value;
   2712         Handle<Object> args[] = { name, proxy };
   2713         Handle<Object> error = isolate->factory()->NewTypeError(
   2714             "no_setter_in_callback", HandleVector(args, ARRAY_SIZE(args)));
   2715         return isolate->Throw(*error);
   2716       }
   2717     }
   2718     // Fall-through.
   2719   }
   2720 
   2721   // The proxy does not define the property as an accessor.
   2722   *found = false;
   2723   return *value;
   2724 }
   2725 
   2726 
   2727 MUST_USE_RESULT MaybeObject* JSProxy::DeletePropertyWithHandler(
   2728     String* name_raw, DeleteMode mode) {
   2729   Isolate* isolate = GetIsolate();
   2730   HandleScope scope(isolate);
   2731   Handle<Object> receiver(this);
   2732   Handle<Object> name(name_raw);
   2733 
   2734   Handle<Object> args[] = { name };
   2735   Handle<Object> result = CallTrap(
   2736     "delete", Handle<Object>(), ARRAY_SIZE(args), args);
   2737   if (isolate->has_pending_exception()) return Failure::Exception();
   2738 
   2739   Object* bool_result = result->ToBoolean();
   2740   if (mode == STRICT_DELETION && bool_result == GetHeap()->false_value()) {
   2741     Handle<String> trap_name = isolate->factory()->LookupAsciiSymbol("delete");
   2742     Handle<Object> args[] = { Handle<Object>(handler()), trap_name };
   2743     Handle<Object> error = isolate->factory()->NewTypeError(
   2744         "handler_failed", HandleVector(args, ARRAY_SIZE(args)));
   2745     isolate->Throw(*error);
   2746     return Failure::Exception();
   2747   }
   2748   return bool_result;
   2749 }
   2750 
   2751 
   2752 MUST_USE_RESULT MaybeObject* JSProxy::DeleteElementWithHandler(
   2753     uint32_t index,
   2754     DeleteMode mode) {
   2755   Isolate* isolate = GetIsolate();
   2756   HandleScope scope(isolate);
   2757   Handle<String> name = isolate->factory()->Uint32ToString(index);
   2758   return JSProxy::DeletePropertyWithHandler(*name, mode);
   2759 }
   2760 
   2761 
   2762 MUST_USE_RESULT PropertyAttributes JSProxy::GetPropertyAttributeWithHandler(
   2763     JSReceiver* receiver_raw,
   2764     String* name_raw) {
   2765   Isolate* isolate = GetIsolate();
   2766   HandleScope scope(isolate);
   2767   Handle<JSProxy> proxy(this);
   2768   Handle<Object> handler(this->handler());  // Trap might morph proxy.
   2769   Handle<JSReceiver> receiver(receiver_raw);
   2770   Handle<Object> name(name_raw);
   2771 
   2772   Handle<Object> args[] = { name };
   2773   Handle<Object> result = CallTrap(
   2774     "getPropertyDescriptor", Handle<Object>(), ARRAY_SIZE(args), args);
   2775   if (isolate->has_pending_exception()) return NONE;
   2776 
   2777   if (result->IsUndefined()) return ABSENT;
   2778 
   2779   bool has_pending_exception;
   2780   Handle<Object> argv[] = { result };
   2781   Handle<Object> desc =
   2782       Execution::Call(isolate->to_complete_property_descriptor(), result,
   2783                       ARRAY_SIZE(argv), argv, &has_pending_exception);
   2784   if (has_pending_exception) return NONE;
   2785 
   2786   // Convert result to PropertyAttributes.
   2787   Handle<String> enum_n = isolate->factory()->LookupAsciiSymbol("enumerable");
   2788   Handle<Object> enumerable(v8::internal::GetProperty(desc, enum_n));
   2789   if (isolate->has_pending_exception()) return NONE;
   2790   Handle<String> conf_n = isolate->factory()->LookupAsciiSymbol("configurable");
   2791   Handle<Object> configurable(v8::internal::GetProperty(desc, conf_n));
   2792   if (isolate->has_pending_exception()) return NONE;
   2793   Handle<String> writ_n = isolate->factory()->LookupAsciiSymbol("writable");
   2794   Handle<Object> writable(v8::internal::GetProperty(desc, writ_n));
   2795   if (isolate->has_pending_exception()) return NONE;
   2796 
   2797   if (configurable->IsFalse()) {
   2798     Handle<String> trap =
   2799         isolate->factory()->LookupAsciiSymbol("getPropertyDescriptor");
   2800     Handle<Object> args[] = { handler, trap, name };
   2801     Handle<Object> error = isolate->factory()->NewTypeError(
   2802         "proxy_prop_not_configurable", HandleVector(args, ARRAY_SIZE(args)));
   2803     isolate->Throw(*error);
   2804     return NONE;
   2805   }
   2806 
   2807   int attributes = NONE;
   2808   if (enumerable->ToBoolean()->IsFalse()) attributes |= DONT_ENUM;
   2809   if (configurable->ToBoolean()->IsFalse()) attributes |= DONT_DELETE;
   2810   if (writable->ToBoolean()->IsFalse()) attributes |= READ_ONLY;
   2811   return static_cast<PropertyAttributes>(attributes);
   2812 }
   2813 
   2814 
   2815 MUST_USE_RESULT PropertyAttributes JSProxy::GetElementAttributeWithHandler(
   2816     JSReceiver* receiver,
   2817     uint32_t index) {
   2818   Isolate* isolate = GetIsolate();
   2819   HandleScope scope(isolate);
   2820   Handle<String> name = isolate->factory()->Uint32ToString(index);
   2821   return GetPropertyAttributeWithHandler(receiver, *name);
   2822 }
   2823 
   2824 
   2825 void JSProxy::Fix() {
   2826   Isolate* isolate = GetIsolate();
   2827   HandleScope scope(isolate);
   2828   Handle<JSProxy> self(this);
   2829 
   2830   // Save identity hash.
   2831   MaybeObject* maybe_hash = GetIdentityHash(OMIT_CREATION);
   2832 
   2833   if (IsJSFunctionProxy()) {
   2834     isolate->factory()->BecomeJSFunction(self);
   2835     // Code will be set on the JavaScript side.
   2836   } else {
   2837     isolate->factory()->BecomeJSObject(self);
   2838   }
   2839   ASSERT(self->IsJSObject());
   2840 
   2841   // Inherit identity, if it was present.
   2842   Object* hash;
   2843   if (maybe_hash->To<Object>(&hash) && hash->IsSmi()) {
   2844     Handle<JSObject> new_self(JSObject::cast(*self));
   2845     isolate->factory()->SetIdentityHash(new_self, hash);
   2846   }
   2847 }
   2848 
   2849 
   2850 MUST_USE_RESULT Handle<Object> JSProxy::CallTrap(const char* name,
   2851                                                  Handle<Object> derived,
   2852                                                  int argc,
   2853                                                  Handle<Object> argv[]) {
   2854   Isolate* isolate = GetIsolate();
   2855   Handle<Object> handler(this->handler());
   2856 
   2857   Handle<String> trap_name = isolate->factory()->LookupAsciiSymbol(name);
   2858   Handle<Object> trap(v8::internal::GetProperty(handler, trap_name));
   2859   if (isolate->has_pending_exception()) return trap;
   2860 
   2861   if (trap->IsUndefined()) {
   2862     if (derived.is_null()) {
   2863       Handle<Object> args[] = { handler, trap_name };
   2864       Handle<Object> error = isolate->factory()->NewTypeError(
   2865         "handler_trap_missing", HandleVector(args, ARRAY_SIZE(args)));
   2866       isolate->Throw(*error);
   2867       return Handle<Object>();
   2868     }
   2869     trap = Handle<Object>(derived);
   2870   }
   2871 
   2872   bool threw;
   2873   return Execution::Call(trap, handler, argc, argv, &threw);
   2874 }
   2875 
   2876 
   2877 MaybeObject* JSObject::SetPropertyForResult(LookupResult* result,
   2878                                             String* name,
   2879                                             Object* value,
   2880                                             PropertyAttributes attributes,
   2881                                             StrictModeFlag strict_mode) {
   2882   Heap* heap = GetHeap();
   2883   // Make sure that the top context does not change when doing callbacks or
   2884   // interceptor calls.
   2885   AssertNoContextChange ncc;
   2886 
   2887   // Optimization for 2-byte strings often used as keys in a decompression
   2888   // dictionary.  We make these short keys into symbols to avoid constantly
   2889   // reallocating them.
   2890   if (!name->IsSymbol() && name->length() <= 2) {
   2891     Object* symbol_version;
   2892     { MaybeObject* maybe_symbol_version = heap->LookupSymbol(name);
   2893       if (maybe_symbol_version->ToObject(&symbol_version)) {
   2894         name = String::cast(symbol_version);
   2895       }
   2896     }
   2897   }
   2898 
   2899   // Check access rights if needed.
   2900   if (IsAccessCheckNeeded()) {
   2901     if (!heap->isolate()->MayNamedAccess(this, name, v8::ACCESS_SET)) {
   2902       return SetPropertyWithFailedAccessCheck(
   2903           result, name, value, true, strict_mode);
   2904     }
   2905   }
   2906 
   2907   if (IsJSGlobalProxy()) {
   2908     Object* proto = GetPrototype();
   2909     if (proto->IsNull()) return value;
   2910     ASSERT(proto->IsJSGlobalObject());
   2911     return JSObject::cast(proto)->SetPropertyForResult(
   2912         result, name, value, attributes, strict_mode);
   2913   }
   2914 
   2915   if (!result->IsProperty() && !IsJSContextExtensionObject()) {
   2916     bool found = false;
   2917     MaybeObject* result_object;
   2918     result_object = SetPropertyWithCallbackSetterInPrototypes(name,
   2919                                                               value,
   2920                                                               attributes,
   2921                                                               &found,
   2922                                                               strict_mode);
   2923     if (found) return result_object;
   2924   }
   2925 
   2926   // At this point, no GC should have happened, as this would invalidate
   2927   // 'result', which we cannot handlify!
   2928 
   2929   if (!result->IsFound()) {
   2930     // Neither properties nor transitions found.
   2931     return AddProperty(name, value, attributes, strict_mode);
   2932   }
   2933   if (result->IsReadOnly() && result->IsProperty()) {
   2934     if (strict_mode == kStrictMode) {
   2935       Handle<JSObject> self(this);
   2936       Handle<String> hname(name);
   2937       Handle<Object> args[] = { hname, self };
   2938       return heap->isolate()->Throw(*heap->isolate()->factory()->NewTypeError(
   2939           "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args))));
   2940     } else {
   2941       return value;
   2942     }
   2943   }
   2944   // This is a real property that is not read-only, or it is a
   2945   // transition or null descriptor and there are no setters in the prototypes.
   2946   switch (result->type()) {
   2947     case NORMAL:
   2948       return SetNormalizedProperty(result, value);
   2949     case FIELD:
   2950       return FastPropertyAtPut(result->GetFieldIndex(), value);
   2951     case MAP_TRANSITION:
   2952       if (attributes == result->GetAttributes()) {
   2953         // Only use map transition if the attributes match.
   2954         return AddFastPropertyUsingMap(result->GetTransitionMap(),
   2955                                        name,
   2956                                        value);
   2957       }
   2958       return ConvertDescriptorToField(name, value, attributes);
   2959     case CONSTANT_FUNCTION:
   2960       // Only replace the function if necessary.
   2961       if (value == result->GetConstantFunction()) return value;
   2962       // Preserve the attributes of this existing property.
   2963       attributes = result->GetAttributes();
   2964       return ConvertDescriptorToField(name, value, attributes);
   2965     case CALLBACKS:
   2966       return SetPropertyWithCallback(result->GetCallbackObject(),
   2967                                      name,
   2968                                      value,
   2969                                      result->holder(),
   2970                                      strict_mode);
   2971     case INTERCEPTOR:
   2972       return SetPropertyWithInterceptor(name, value, attributes, strict_mode);
   2973     case CONSTANT_TRANSITION: {
   2974       // If the same constant function is being added we can simply
   2975       // transition to the target map.
   2976       Map* target_map = result->GetTransitionMap();
   2977       DescriptorArray* target_descriptors = target_map->instance_descriptors();
   2978       int number = target_descriptors->SearchWithCache(name);
   2979       ASSERT(number != DescriptorArray::kNotFound);
   2980       ASSERT(target_descriptors->GetType(number) == CONSTANT_FUNCTION);
   2981       JSFunction* function =
   2982           JSFunction::cast(target_descriptors->GetValue(number));
   2983       if (value == function) {
   2984         set_map(target_map);
   2985         return value;
   2986       }
   2987       // Otherwise, replace with a MAP_TRANSITION to a new map with a
   2988       // FIELD, even if the value is a constant function.
   2989       return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
   2990     }
   2991     case NULL_DESCRIPTOR:
   2992     case ELEMENTS_TRANSITION:
   2993       return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
   2994     case HANDLER:
   2995       UNREACHABLE();
   2996       return value;
   2997   }
   2998   UNREACHABLE();  // keep the compiler happy
   2999   return value;
   3000 }
   3001 
   3002 
   3003 // Set a real local property, even if it is READ_ONLY.  If the property is not
   3004 // present, add it with attributes NONE.  This code is an exact clone of
   3005 // SetProperty, with the check for IsReadOnly and the check for a
   3006 // callback setter removed.  The two lines looking up the LookupResult
   3007 // result are also added.  If one of the functions is changed, the other
   3008 // should be.
   3009 // Note that this method cannot be used to set the prototype of a function
   3010 // because ConvertDescriptorToField() which is called in "case CALLBACKS:"
   3011 // doesn't handle function prototypes correctly.
   3012 Handle<Object> JSObject::SetLocalPropertyIgnoreAttributes(
   3013     Handle<JSObject> object,
   3014     Handle<String> key,
   3015     Handle<Object> value,
   3016     PropertyAttributes attributes) {
   3017   CALL_HEAP_FUNCTION(
   3018     object->GetIsolate(),
   3019     object->SetLocalPropertyIgnoreAttributes(*key, *value, attributes),
   3020     Object);
   3021 }
   3022 
   3023 
   3024 MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes(
   3025     String* name,
   3026     Object* value,
   3027     PropertyAttributes attributes) {
   3028 
   3029   // Make sure that the top context does not change when doing callbacks or
   3030   // interceptor calls.
   3031   AssertNoContextChange ncc;
   3032   Isolate* isolate = GetIsolate();
   3033   LookupResult result(isolate);
   3034   LocalLookup(name, &result);
   3035   // Check access rights if needed.
   3036   if (IsAccessCheckNeeded()) {
   3037     if (!isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) {
   3038       return SetPropertyWithFailedAccessCheck(&result,
   3039                                               name,
   3040                                               value,
   3041                                               false,
   3042                                               kNonStrictMode);
   3043     }
   3044   }
   3045 
   3046   if (IsJSGlobalProxy()) {
   3047     Object* proto = GetPrototype();
   3048     if (proto->IsNull()) return value;
   3049     ASSERT(proto->IsJSGlobalObject());
   3050     return JSObject::cast(proto)->SetLocalPropertyIgnoreAttributes(
   3051         name,
   3052         value,
   3053         attributes);
   3054   }
   3055 
   3056   // Check for accessor in prototype chain removed here in clone.
   3057   if (!result.IsFound()) {
   3058     // Neither properties nor transitions found.
   3059     return AddProperty(name, value, attributes, kNonStrictMode);
   3060   }
   3061 
   3062   PropertyDetails details = PropertyDetails(attributes, NORMAL);
   3063 
   3064   // Check of IsReadOnly removed from here in clone.
   3065   switch (result.type()) {
   3066     case NORMAL:
   3067       return SetNormalizedProperty(name, value, details);
   3068     case FIELD:
   3069       return FastPropertyAtPut(result.GetFieldIndex(), value);
   3070     case MAP_TRANSITION:
   3071       if (attributes == result.GetAttributes()) {
   3072         // Only use map transition if the attributes match.
   3073         return AddFastPropertyUsingMap(result.GetTransitionMap(),
   3074                                        name,
   3075                                        value);
   3076       }
   3077       return ConvertDescriptorToField(name, value, attributes);
   3078     case CONSTANT_FUNCTION:
   3079       // Only replace the function if necessary.
   3080       if (value == result.GetConstantFunction()) return value;
   3081       // Preserve the attributes of this existing property.
   3082       attributes = result.GetAttributes();
   3083       return ConvertDescriptorToField(name, value, attributes);
   3084     case CALLBACKS:
   3085     case INTERCEPTOR:
   3086       // Override callback in clone
   3087       return ConvertDescriptorToField(name, value, attributes);
   3088     case CONSTANT_TRANSITION:
   3089       // Replace with a MAP_TRANSITION to a new map with a FIELD, even
   3090       // if the value is a function.
   3091       return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
   3092     case NULL_DESCRIPTOR:
   3093     case ELEMENTS_TRANSITION:
   3094       return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
   3095     case HANDLER:
   3096       UNREACHABLE();
   3097       return value;
   3098   }
   3099   UNREACHABLE();  // keep the compiler happy
   3100   return value;
   3101 }
   3102 
   3103 
   3104 PropertyAttributes JSObject::GetPropertyAttributePostInterceptor(
   3105       JSObject* receiver,
   3106       String* name,
   3107       bool continue_search) {
   3108   // Check local property, ignore interceptor.
   3109   LookupResult result(GetIsolate());
   3110   LocalLookupRealNamedProperty(name, &result);
   3111   if (result.IsProperty()) return result.GetAttributes();
   3112 
   3113   if (continue_search) {
   3114     // Continue searching via the prototype chain.
   3115     Object* pt = GetPrototype();
   3116     if (!pt->IsNull()) {
   3117       return JSObject::cast(pt)->
   3118         GetPropertyAttributeWithReceiver(receiver, name);
   3119     }
   3120   }
   3121   return ABSENT;
   3122 }
   3123 
   3124 
   3125 PropertyAttributes JSObject::GetPropertyAttributeWithInterceptor(
   3126       JSObject* receiver,
   3127       String* name,
   3128       bool continue_search) {
   3129   Isolate* isolate = GetIsolate();
   3130 
   3131   // Make sure that the top context does not change when doing
   3132   // callbacks or interceptor calls.
   3133   AssertNoContextChange ncc;
   3134 
   3135   HandleScope scope(isolate);
   3136   Handle<InterceptorInfo> interceptor(GetNamedInterceptor());
   3137   Handle<JSObject> receiver_handle(receiver);
   3138   Handle<JSObject> holder_handle(this);
   3139   Handle<String> name_handle(name);
   3140   CustomArguments args(isolate, interceptor->data(), receiver, this);
   3141   v8::AccessorInfo info(args.end());
   3142   if (!interceptor->query()->IsUndefined()) {
   3143     v8::NamedPropertyQuery query =
   3144         v8::ToCData<v8::NamedPropertyQuery>(interceptor->query());
   3145     LOG(isolate,
   3146         ApiNamedPropertyAccess("interceptor-named-has", *holder_handle, name));
   3147     v8::Handle<v8::Integer> result;
   3148     {
   3149       // Leaving JavaScript.
   3150       VMState state(isolate, EXTERNAL);
   3151       result = query(v8::Utils::ToLocal(name_handle), info);
   3152     }
   3153     if (!result.IsEmpty()) {
   3154       ASSERT(result->IsInt32());
   3155       return static_cast<PropertyAttributes>(result->Int32Value());
   3156     }
   3157   } else if (!interceptor->getter()->IsUndefined()) {
   3158     v8::NamedPropertyGetter getter =
   3159         v8::ToCData<v8::NamedPropertyGetter>(interceptor->getter());
   3160     LOG(isolate,
   3161         ApiNamedPropertyAccess("interceptor-named-get-has", this, name));
   3162     v8::Handle<v8::Value> result;
   3163     {
   3164       // Leaving JavaScript.
   3165       VMState state(isolate, EXTERNAL);
   3166       result = getter(v8::Utils::ToLocal(name_handle), info);
   3167     }
   3168     if (!result.IsEmpty()) return DONT_ENUM;
   3169   }
   3170   return holder_handle->GetPropertyAttributePostInterceptor(*receiver_handle,
   3171                                                             *name_handle,
   3172                                                             continue_search);
   3173 }
   3174 
   3175 
   3176 PropertyAttributes JSReceiver::GetPropertyAttributeWithReceiver(
   3177       JSReceiver* receiver,
   3178       String* key) {
   3179   uint32_t index = 0;
   3180   if (IsJSObject() && key->AsArrayIndex(&index)) {
   3181     return JSObject::cast(this)->HasElementWithReceiver(receiver, index)
   3182         ? NONE : ABSENT;
   3183   }
   3184   // Named property.
   3185   LookupResult result(GetIsolate());
   3186   Lookup(key, &result);
   3187   return GetPropertyAttribute(receiver, &result, key, true);
   3188 }
   3189 
   3190 
   3191 PropertyAttributes JSReceiver::GetPropertyAttribute(JSReceiver* receiver,
   3192                                                     LookupResult* result,
   3193                                                     String* name,
   3194                                                     bool continue_search) {
   3195   // Check access rights if needed.
   3196   if (IsAccessCheckNeeded()) {
   3197     JSObject* this_obj = JSObject::cast(this);
   3198     Heap* heap = GetHeap();
   3199     if (!heap->isolate()->MayNamedAccess(this_obj, name, v8::ACCESS_HAS)) {
   3200       return this_obj->GetPropertyAttributeWithFailedAccessCheck(
   3201           receiver, result, name, continue_search);
   3202     }
   3203   }
   3204   if (result->IsProperty()) {
   3205     switch (result->type()) {
   3206       case NORMAL:  // fall through
   3207       case FIELD:
   3208       case CONSTANT_FUNCTION:
   3209       case CALLBACKS:
   3210         return result->GetAttributes();
   3211       case HANDLER: {
   3212         return JSProxy::cast(result->proxy())->GetPropertyAttributeWithHandler(
   3213             receiver, name);
   3214       }
   3215       case INTERCEPTOR:
   3216         return result->holder()->GetPropertyAttributeWithInterceptor(
   3217             JSObject::cast(receiver), name, continue_search);
   3218       default:
   3219         UNREACHABLE();
   3220     }
   3221   }
   3222   return ABSENT;
   3223 }
   3224 
   3225 
   3226 PropertyAttributes JSReceiver::GetLocalPropertyAttribute(String* name) {
   3227   // Check whether the name is an array index.
   3228   uint32_t index = 0;
   3229   if (IsJSObject() && name->AsArrayIndex(&index)) {
   3230     if (JSObject::cast(this)->HasLocalElement(index)) return NONE;
   3231     return ABSENT;
   3232   }
   3233   // Named property.
   3234   LookupResult result(GetIsolate());
   3235   LocalLookup(name, &result);
   3236   return GetPropertyAttribute(this, &result, name, false);
   3237 }
   3238 
   3239 
   3240 MaybeObject* NormalizedMapCache::Get(JSObject* obj,
   3241                                      PropertyNormalizationMode mode) {
   3242   Isolate* isolate = obj->GetIsolate();
   3243   Map* fast = obj->map();
   3244   int index = fast->Hash() % kEntries;
   3245   Object* result = get(index);
   3246   if (result->IsMap() &&
   3247       Map::cast(result)->EquivalentToForNormalization(fast, mode)) {
   3248 #ifdef DEBUG
   3249     if (FLAG_verify_heap) {
   3250       Map::cast(result)->SharedMapVerify();
   3251     }
   3252     if (FLAG_enable_slow_asserts) {
   3253       // The cached map should match newly created normalized map bit-by-bit.
   3254       Object* fresh;
   3255       { MaybeObject* maybe_fresh =
   3256             fast->CopyNormalized(mode, SHARED_NORMALIZED_MAP);
   3257         if (maybe_fresh->ToObject(&fresh)) {
   3258           ASSERT(memcmp(Map::cast(fresh)->address(),
   3259                         Map::cast(result)->address(),
   3260                         Map::kSize) == 0);
   3261         }
   3262       }
   3263     }
   3264 #endif
   3265     return result;
   3266   }
   3267 
   3268   { MaybeObject* maybe_result =
   3269         fast->CopyNormalized(mode, SHARED_NORMALIZED_MAP);
   3270     if (!maybe_result->ToObject(&result)) return maybe_result;
   3271   }
   3272   set(index, result);
   3273   isolate->counters()->normalized_maps()->Increment();
   3274 
   3275   return result;
   3276 }
   3277 
   3278 
   3279 void NormalizedMapCache::Clear() {
   3280   int entries = length();
   3281   for (int i = 0; i != entries; i++) {
   3282     set_undefined(i);
   3283   }
   3284 }
   3285 
   3286 
   3287 void JSObject::UpdateMapCodeCache(Handle<JSObject> object,
   3288                                   Handle<String> name,
   3289                                   Handle<Code> code) {
   3290   Isolate* isolate = object->GetIsolate();
   3291   CALL_HEAP_FUNCTION_VOID(isolate,
   3292                           object->UpdateMapCodeCache(*name, *code));
   3293 }
   3294 
   3295 
   3296 MaybeObject* JSObject::UpdateMapCodeCache(String* name, Code* code) {
   3297   if (map()->is_shared()) {
   3298     // Fast case maps are never marked as shared.
   3299     ASSERT(!HasFastProperties());
   3300     // Replace the map with an identical copy that can be safely modified.
   3301     Object* obj;
   3302     { MaybeObject* maybe_obj = map()->CopyNormalized(KEEP_INOBJECT_PROPERTIES,
   3303                                                      UNIQUE_NORMALIZED_MAP);
   3304       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   3305     }
   3306     GetIsolate()->counters()->normalized_maps()->Increment();
   3307 
   3308     set_map(Map::cast(obj));
   3309   }
   3310   return map()->UpdateCodeCache(name, code);
   3311 }
   3312 
   3313 
   3314 void JSObject::NormalizeProperties(Handle<JSObject> object,
   3315                                    PropertyNormalizationMode mode,
   3316                                    int expected_additional_properties) {
   3317   CALL_HEAP_FUNCTION_VOID(object->GetIsolate(),
   3318                           object->NormalizeProperties(
   3319                               mode, expected_additional_properties));
   3320 }
   3321 
   3322 
   3323 MaybeObject* JSObject::NormalizeProperties(PropertyNormalizationMode mode,
   3324                                            int expected_additional_properties) {
   3325   if (!HasFastProperties()) return this;
   3326 
   3327   // The global object is always normalized.
   3328   ASSERT(!IsGlobalObject());
   3329   // JSGlobalProxy must never be normalized
   3330   ASSERT(!IsJSGlobalProxy());
   3331 
   3332   Map* map_of_this = map();
   3333 
   3334   // Allocate new content.
   3335   int property_count = map_of_this->NumberOfDescribedProperties();
   3336   if (expected_additional_properties > 0) {
   3337     property_count += expected_additional_properties;
   3338   } else {
   3339     property_count += 2;  // Make space for two more properties.
   3340   }
   3341   StringDictionary* dictionary;
   3342   { MaybeObject* maybe_dictionary = StringDictionary::Allocate(property_count);
   3343     if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
   3344   }
   3345 
   3346   DescriptorArray* descs = map_of_this->instance_descriptors();
   3347   for (int i = 0; i < descs->number_of_descriptors(); i++) {
   3348     PropertyDetails details(descs->GetDetails(i));
   3349     switch (details.type()) {
   3350       case CONSTANT_FUNCTION: {
   3351         PropertyDetails d =
   3352             PropertyDetails(details.attributes(), NORMAL, details.index());
   3353         Object* value = descs->GetConstantFunction(i);
   3354         MaybeObject* maybe_dictionary =
   3355             dictionary->Add(descs->GetKey(i), value, d);
   3356         if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
   3357         break;
   3358       }
   3359       case FIELD: {
   3360         PropertyDetails d =
   3361             PropertyDetails(details.attributes(), NORMAL, details.index());
   3362         Object* value = FastPropertyAt(descs->GetFieldIndex(i));
   3363         MaybeObject* maybe_dictionary =
   3364             dictionary->Add(descs->GetKey(i), value, d);
   3365         if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
   3366         break;
   3367       }
   3368       case CALLBACKS: {
   3369         if (!descs->IsProperty(i)) break;
   3370         Object* value = descs->GetCallbacksObject(i);
   3371         if (value->IsAccessorPair()) {
   3372           MaybeObject* maybe_copy =
   3373               AccessorPair::cast(value)->CopyWithoutTransitions();
   3374           if (!maybe_copy->To(&value)) return maybe_copy;
   3375         }
   3376         MaybeObject* maybe_dictionary =
   3377             dictionary->Add(descs->GetKey(i), value, details);
   3378         if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
   3379         break;
   3380       }
   3381       case MAP_TRANSITION:
   3382       case CONSTANT_TRANSITION:
   3383       case NULL_DESCRIPTOR:
   3384       case INTERCEPTOR:
   3385       case ELEMENTS_TRANSITION:
   3386         break;
   3387       case HANDLER:
   3388       case NORMAL:
   3389         UNREACHABLE();
   3390         break;
   3391     }
   3392   }
   3393 
   3394   Heap* current_heap = GetHeap();
   3395 
   3396   // Copy the next enumeration index from instance descriptor.
   3397   int index = map_of_this->instance_descriptors()->NextEnumerationIndex();
   3398   dictionary->SetNextEnumerationIndex(index);
   3399 
   3400   Map* new_map;
   3401   { MaybeObject* maybe_map =
   3402         current_heap->isolate()->context()->global_context()->
   3403         normalized_map_cache()->Get(this, mode);
   3404     if (!maybe_map->To(&new_map)) return maybe_map;
   3405   }
   3406 
   3407   // We have now successfully allocated all the necessary objects.
   3408   // Changes can now be made with the guarantee that all of them take effect.
   3409 
   3410   // Resize the object in the heap if necessary.
   3411   int new_instance_size = new_map->instance_size();
   3412   int instance_size_delta = map_of_this->instance_size() - new_instance_size;
   3413   ASSERT(instance_size_delta >= 0);
   3414   current_heap->CreateFillerObjectAt(this->address() + new_instance_size,
   3415                                      instance_size_delta);
   3416   if (Marking::IsBlack(Marking::MarkBitFrom(this))) {
   3417     MemoryChunk::IncrementLiveBytesFromMutator(this->address(),
   3418                                                -instance_size_delta);
   3419   }
   3420 
   3421 
   3422   set_map(new_map);
   3423   new_map->clear_instance_descriptors();
   3424 
   3425   set_properties(dictionary);
   3426 
   3427   current_heap->isolate()->counters()->props_to_dictionary()->Increment();
   3428 
   3429 #ifdef DEBUG
   3430   if (FLAG_trace_normalization) {
   3431     PrintF("Object properties have been normalized:\n");
   3432     Print();
   3433   }
   3434 #endif
   3435   return this;
   3436 }
   3437 
   3438 
   3439 void JSObject::TransformToFastProperties(Handle<JSObject> object,
   3440                                          int unused_property_fields) {
   3441   CALL_HEAP_FUNCTION_VOID(
   3442       object->GetIsolate(),
   3443       object->TransformToFastProperties(unused_property_fields));
   3444 }
   3445 
   3446 
   3447 MaybeObject* JSObject::TransformToFastProperties(int unused_property_fields) {
   3448   if (HasFastProperties()) return this;
   3449   ASSERT(!IsGlobalObject());
   3450   return property_dictionary()->
   3451       TransformPropertiesToFastFor(this, unused_property_fields);
   3452 }
   3453 
   3454 
   3455 Handle<SeededNumberDictionary> JSObject::NormalizeElements(
   3456     Handle<JSObject> object) {
   3457   CALL_HEAP_FUNCTION(object->GetIsolate(),
   3458                      object->NormalizeElements(),
   3459                      SeededNumberDictionary);
   3460 }
   3461 
   3462 
   3463 MaybeObject* JSObject::NormalizeElements() {
   3464   ASSERT(!HasExternalArrayElements());
   3465 
   3466   // Find the backing store.
   3467   FixedArrayBase* array = FixedArrayBase::cast(elements());
   3468   Map* old_map = array->map();
   3469   bool is_arguments =
   3470       (old_map == old_map->GetHeap()->non_strict_arguments_elements_map());
   3471   if (is_arguments) {
   3472     array = FixedArrayBase::cast(FixedArray::cast(array)->get(1));
   3473   }
   3474   if (array->IsDictionary()) return array;
   3475 
   3476   ASSERT(HasFastElements() ||
   3477          HasFastSmiOnlyElements() ||
   3478          HasFastDoubleElements() ||
   3479          HasFastArgumentsElements());
   3480   // Compute the effective length and allocate a new backing store.
   3481   int length = IsJSArray()
   3482       ? Smi::cast(JSArray::cast(this)->length())->value()
   3483       : array->length();
   3484   int old_capacity = 0;
   3485   int used_elements = 0;
   3486   GetElementsCapacityAndUsage(&old_capacity, &used_elements);
   3487   SeededNumberDictionary* dictionary = NULL;
   3488   { Object* object;
   3489     MaybeObject* maybe = SeededNumberDictionary::Allocate(used_elements);
   3490     if (!maybe->ToObject(&object)) return maybe;
   3491     dictionary = SeededNumberDictionary::cast(object);
   3492   }
   3493 
   3494   // Copy the elements to the new backing store.
   3495   bool has_double_elements = array->IsFixedDoubleArray();
   3496   for (int i = 0; i < length; i++) {
   3497     Object* value = NULL;
   3498     if (has_double_elements) {
   3499       FixedDoubleArray* double_array = FixedDoubleArray::cast(array);
   3500       if (double_array->is_the_hole(i)) {
   3501         value = GetIsolate()->heap()->the_hole_value();
   3502       } else {
   3503         // Objects must be allocated in the old object space, since the
   3504         // overall number of HeapNumbers needed for the conversion might
   3505         // exceed the capacity of new space, and we would fail repeatedly
   3506         // trying to convert the FixedDoubleArray.
   3507         MaybeObject* maybe_value_object =
   3508             GetHeap()->AllocateHeapNumber(double_array->get_scalar(i), TENURED);
   3509         if (!maybe_value_object->ToObject(&value)) return maybe_value_object;
   3510       }
   3511     } else {
   3512       ASSERT(old_map->has_fast_elements() ||
   3513              old_map->has_fast_smi_only_elements());
   3514       value = FixedArray::cast(array)->get(i);
   3515     }
   3516     PropertyDetails details = PropertyDetails(NONE, NORMAL);
   3517     if (!value->IsTheHole()) {
   3518       Object* result;
   3519       MaybeObject* maybe_result =
   3520           dictionary->AddNumberEntry(i, value, details);
   3521       if (!maybe_result->ToObject(&result)) return maybe_result;
   3522       dictionary = SeededNumberDictionary::cast(result);
   3523     }
   3524   }
   3525 
   3526   // Switch to using the dictionary as the backing storage for elements.
   3527   if (is_arguments) {
   3528     FixedArray::cast(elements())->set(1, dictionary);
   3529   } else {
   3530     // Set the new map first to satify the elements type assert in
   3531     // set_elements().
   3532     Object* new_map;
   3533     MaybeObject* maybe = GetElementsTransitionMap(GetIsolate(),
   3534                                                   DICTIONARY_ELEMENTS);
   3535     if (!maybe->ToObject(&new_map)) return maybe;
   3536     set_map(Map::cast(new_map));
   3537     set_elements(dictionary);
   3538   }
   3539 
   3540   old_map->GetHeap()->isolate()->counters()->elements_to_dictionary()->
   3541       Increment();
   3542 
   3543 #ifdef DEBUG
   3544   if (FLAG_trace_normalization) {
   3545     PrintF("Object elements have been normalized:\n");
   3546     Print();
   3547   }
   3548 #endif
   3549 
   3550   ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements());
   3551   return dictionary;
   3552 }
   3553 
   3554 
   3555 Smi* JSReceiver::GenerateIdentityHash() {
   3556   Isolate* isolate = GetIsolate();
   3557 
   3558   int hash_value;
   3559   int attempts = 0;
   3560   do {
   3561     // Generate a random 32-bit hash value but limit range to fit
   3562     // within a smi.
   3563     hash_value = V8::RandomPrivate(isolate) & Smi::kMaxValue;
   3564     attempts++;
   3565   } while (hash_value == 0 && attempts < 30);
   3566   hash_value = hash_value != 0 ? hash_value : 1;  // never return 0
   3567 
   3568   return Smi::FromInt(hash_value);
   3569 }
   3570 
   3571 
   3572 MaybeObject* JSObject::SetIdentityHash(Object* hash, CreationFlag flag) {
   3573   MaybeObject* maybe = SetHiddenProperty(GetHeap()->identity_hash_symbol(),
   3574                                          hash);
   3575   if (maybe->IsFailure()) return maybe;
   3576   return this;
   3577 }
   3578 
   3579 
   3580 int JSObject::GetIdentityHash(Handle<JSObject> obj) {
   3581   CALL_AND_RETRY(obj->GetIsolate(),
   3582                  obj->GetIdentityHash(ALLOW_CREATION),
   3583                  return Smi::cast(__object__)->value(),
   3584                  return 0);
   3585 }
   3586 
   3587 
   3588 MaybeObject* JSObject::GetIdentityHash(CreationFlag flag) {
   3589   Object* stored_value = GetHiddenProperty(GetHeap()->identity_hash_symbol());
   3590   if (stored_value->IsSmi()) return stored_value;
   3591 
   3592   // Do not generate permanent identity hash code if not requested.
   3593   if (flag == OMIT_CREATION) return GetHeap()->undefined_value();
   3594 
   3595   Smi* hash = GenerateIdentityHash();
   3596   MaybeObject* result = SetHiddenProperty(GetHeap()->identity_hash_symbol(),
   3597                                           hash);
   3598   if (result->IsFailure()) return result;
   3599   if (result->ToObjectUnchecked()->IsUndefined()) {
   3600     // Trying to get hash of detached proxy.
   3601     return Smi::FromInt(0);
   3602   }
   3603   return hash;
   3604 }
   3605 
   3606 
   3607 MaybeObject* JSProxy::GetIdentityHash(CreationFlag flag) {
   3608   Object* hash = this->hash();
   3609   if (!hash->IsSmi() && flag == ALLOW_CREATION) {
   3610     hash = GenerateIdentityHash();
   3611     set_hash(hash);
   3612   }
   3613   return hash;
   3614 }
   3615 
   3616 
   3617 Object* JSObject::GetHiddenProperty(String* key) {
   3618   if (IsJSGlobalProxy()) {
   3619     // For a proxy, use the prototype as target object.
   3620     Object* proxy_parent = GetPrototype();
   3621     // If the proxy is detached, return undefined.
   3622     if (proxy_parent->IsNull()) return GetHeap()->undefined_value();
   3623     ASSERT(proxy_parent->IsJSGlobalObject());
   3624     return JSObject::cast(proxy_parent)->GetHiddenProperty(key);
   3625   }
   3626   ASSERT(!IsJSGlobalProxy());
   3627   MaybeObject* hidden_lookup = GetHiddenPropertiesDictionary(false);
   3628   ASSERT(!hidden_lookup->IsFailure());  // No failure when passing false as arg.
   3629   if (hidden_lookup->ToObjectUnchecked()->IsUndefined()) {
   3630     return GetHeap()->undefined_value();
   3631   }
   3632   StringDictionary* dictionary =
   3633       StringDictionary::cast(hidden_lookup->ToObjectUnchecked());
   3634   int entry = dictionary->FindEntry(key);
   3635   if (entry == StringDictionary::kNotFound) return GetHeap()->undefined_value();
   3636   return dictionary->ValueAt(entry);
   3637 }
   3638 
   3639 
   3640 Handle<Object> JSObject::SetHiddenProperty(Handle<JSObject> obj,
   3641                                  Handle<String> key,
   3642                                  Handle<Object> value) {
   3643   CALL_HEAP_FUNCTION(obj->GetIsolate(),
   3644                      obj->SetHiddenProperty(*key, *value),
   3645                      Object);
   3646 }
   3647 
   3648 
   3649 MaybeObject* JSObject::SetHiddenProperty(String* key, Object* value) {
   3650   if (IsJSGlobalProxy()) {
   3651     // For a proxy, use the prototype as target object.
   3652     Object* proxy_parent = GetPrototype();
   3653     // If the proxy is detached, return undefined.
   3654     if (proxy_parent->IsNull()) return GetHeap()->undefined_value();
   3655     ASSERT(proxy_parent->IsJSGlobalObject());
   3656     return JSObject::cast(proxy_parent)->SetHiddenProperty(key, value);
   3657   }
   3658   ASSERT(!IsJSGlobalProxy());
   3659   MaybeObject* hidden_lookup = GetHiddenPropertiesDictionary(true);
   3660   StringDictionary* dictionary;
   3661   if (!hidden_lookup->To<StringDictionary>(&dictionary)) return hidden_lookup;
   3662 
   3663   // If it was found, check if the key is already in the dictionary.
   3664   int entry = dictionary->FindEntry(key);
   3665   if (entry != StringDictionary::kNotFound) {
   3666     // If key was found, just update the value.
   3667     dictionary->ValueAtPut(entry, value);
   3668     return this;
   3669   }
   3670   // Key was not already in the dictionary, so add the entry.
   3671   MaybeObject* insert_result = dictionary->Add(key,
   3672                                                value,
   3673                                                PropertyDetails(NONE, NORMAL));
   3674   StringDictionary* new_dict;
   3675   if (!insert_result->To<StringDictionary>(&new_dict)) return insert_result;
   3676   if (new_dict != dictionary) {
   3677     // If adding the key expanded the dictionary (i.e., Add returned a new
   3678     // dictionary), store it back to the object.
   3679     MaybeObject* store_result = SetHiddenPropertiesDictionary(new_dict);
   3680     if (store_result->IsFailure()) return store_result;
   3681   }
   3682   // Return this to mark success.
   3683   return this;
   3684 }
   3685 
   3686 
   3687 void JSObject::DeleteHiddenProperty(String* key) {
   3688   if (IsJSGlobalProxy()) {
   3689     // For a proxy, use the prototype as target object.
   3690     Object* proxy_parent = GetPrototype();
   3691     // If the proxy is detached, return immediately.
   3692     if (proxy_parent->IsNull()) return;
   3693     ASSERT(proxy_parent->IsJSGlobalObject());
   3694     JSObject::cast(proxy_parent)->DeleteHiddenProperty(key);
   3695     return;
   3696   }
   3697   MaybeObject* hidden_lookup = GetHiddenPropertiesDictionary(false);
   3698   ASSERT(!hidden_lookup->IsFailure());  // No failure when passing false as arg.
   3699   if (hidden_lookup->ToObjectUnchecked()->IsUndefined()) return;
   3700   StringDictionary* dictionary =
   3701       StringDictionary::cast(hidden_lookup->ToObjectUnchecked());
   3702   int entry = dictionary->FindEntry(key);
   3703   if (entry == StringDictionary::kNotFound) {
   3704     // Key wasn't in dictionary. Deletion is a success.
   3705     return;
   3706   }
   3707   // Key was in the dictionary. Remove it.
   3708   dictionary->DeleteProperty(entry, JSReceiver::FORCE_DELETION);
   3709 }
   3710 
   3711 
   3712 bool JSObject::HasHiddenProperties() {
   3713   return GetPropertyAttributePostInterceptor(this,
   3714                                              GetHeap()->hidden_symbol(),
   3715                                              false) != ABSENT;
   3716 }
   3717 
   3718 
   3719 MaybeObject* JSObject::GetHiddenPropertiesDictionary(bool create_if_absent) {
   3720   ASSERT(!IsJSGlobalProxy());
   3721   if (HasFastProperties()) {
   3722     // If the object has fast properties, check whether the first slot
   3723     // in the descriptor array matches the hidden symbol. Since the
   3724     // hidden symbols hash code is zero (and no other string has hash
   3725     // code zero) it will always occupy the first entry if present.
   3726     DescriptorArray* descriptors = this->map()->instance_descriptors();
   3727     if ((descriptors->number_of_descriptors() > 0) &&
   3728         (descriptors->GetKey(0) == GetHeap()->hidden_symbol())) {
   3729       if (descriptors->GetType(0) == FIELD) {
   3730         Object* hidden_store =
   3731             this->FastPropertyAt(descriptors->GetFieldIndex(0));
   3732         return StringDictionary::cast(hidden_store);
   3733       } else {
   3734         ASSERT(descriptors->GetType(0) == NULL_DESCRIPTOR ||
   3735                descriptors->GetType(0) == MAP_TRANSITION);
   3736       }
   3737     }
   3738   } else {
   3739     PropertyAttributes attributes;
   3740     // You can't install a getter on a property indexed by the hidden symbol,
   3741     // so we can be sure that GetLocalPropertyPostInterceptor returns a real
   3742     // object.
   3743     Object* lookup =
   3744         GetLocalPropertyPostInterceptor(this,
   3745                                         GetHeap()->hidden_symbol(),
   3746                                         &attributes)->ToObjectUnchecked();
   3747     if (!lookup->IsUndefined()) {
   3748       return StringDictionary::cast(lookup);
   3749     }
   3750   }
   3751   if (!create_if_absent) return GetHeap()->undefined_value();
   3752   const int kInitialSize = 5;
   3753   MaybeObject* dict_alloc = StringDictionary::Allocate(kInitialSize);
   3754   StringDictionary* dictionary;
   3755   if (!dict_alloc->To<StringDictionary>(&dictionary)) return dict_alloc;
   3756   MaybeObject* store_result =
   3757       SetPropertyPostInterceptor(GetHeap()->hidden_symbol(),
   3758                                  dictionary,
   3759                                  DONT_ENUM,
   3760                                  kNonStrictMode);
   3761   if (store_result->IsFailure()) return store_result;
   3762   return dictionary;
   3763 }
   3764 
   3765 
   3766 MaybeObject* JSObject::SetHiddenPropertiesDictionary(
   3767     StringDictionary* dictionary) {
   3768   ASSERT(!IsJSGlobalProxy());
   3769   ASSERT(HasHiddenProperties());
   3770   if (HasFastProperties()) {
   3771     // If the object has fast properties, check whether the first slot
   3772     // in the descriptor array matches the hidden symbol. Since the
   3773     // hidden symbols hash code is zero (and no other string has hash
   3774     // code zero) it will always occupy the first entry if present.
   3775     DescriptorArray* descriptors = this->map()->instance_descriptors();
   3776     if ((descriptors->number_of_descriptors() > 0) &&
   3777         (descriptors->GetKey(0) == GetHeap()->hidden_symbol())) {
   3778       if (descriptors->GetType(0) == FIELD) {
   3779         this->FastPropertyAtPut(descriptors->GetFieldIndex(0), dictionary);
   3780         return this;
   3781       } else {
   3782         ASSERT(descriptors->GetType(0) == NULL_DESCRIPTOR ||
   3783                descriptors->GetType(0) == MAP_TRANSITION);
   3784       }
   3785     }
   3786   }
   3787   MaybeObject* store_result =
   3788       SetPropertyPostInterceptor(GetHeap()->hidden_symbol(),
   3789                                  dictionary,
   3790                                  DONT_ENUM,
   3791                                  kNonStrictMode);
   3792   if (store_result->IsFailure()) return store_result;
   3793   return this;
   3794 }
   3795 
   3796 
   3797 MaybeObject* JSObject::DeletePropertyPostInterceptor(String* name,
   3798                                                      DeleteMode mode) {
   3799   // Check local property, ignore interceptor.
   3800   LookupResult result(GetIsolate());
   3801   LocalLookupRealNamedProperty(name, &result);
   3802   if (!result.IsProperty()) return GetHeap()->true_value();
   3803 
   3804   // Normalize object if needed.
   3805   Object* obj;
   3806   { MaybeObject* maybe_obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
   3807     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   3808   }
   3809 
   3810   return DeleteNormalizedProperty(name, mode);
   3811 }
   3812 
   3813 
   3814 MaybeObject* JSObject::DeletePropertyWithInterceptor(String* name) {
   3815   Isolate* isolate = GetIsolate();
   3816   HandleScope scope(isolate);
   3817   Handle<InterceptorInfo> interceptor(GetNamedInterceptor());
   3818   Handle<String> name_handle(name);
   3819   Handle<JSObject> this_handle(this);
   3820   if (!interceptor->deleter()->IsUndefined()) {
   3821     v8::NamedPropertyDeleter deleter =
   3822         v8::ToCData<v8::NamedPropertyDeleter>(interceptor->deleter());
   3823     LOG(isolate,
   3824         ApiNamedPropertyAccess("interceptor-named-delete", *this_handle, name));
   3825     CustomArguments args(isolate, interceptor->data(), this, this);
   3826     v8::AccessorInfo info(args.end());
   3827     v8::Handle<v8::Boolean> result;
   3828     {
   3829       // Leaving JavaScript.
   3830       VMState state(isolate, EXTERNAL);
   3831       result = deleter(v8::Utils::ToLocal(name_handle), info);
   3832     }
   3833     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   3834     if (!result.IsEmpty()) {
   3835       ASSERT(result->IsBoolean());
   3836       return *v8::Utils::OpenHandle(*result);
   3837     }
   3838   }
   3839   MaybeObject* raw_result =
   3840       this_handle->DeletePropertyPostInterceptor(*name_handle, NORMAL_DELETION);
   3841   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   3842   return raw_result;
   3843 }
   3844 
   3845 
   3846 MaybeObject* JSObject::DeleteElementWithInterceptor(uint32_t index) {
   3847   Isolate* isolate = GetIsolate();
   3848   Heap* heap = isolate->heap();
   3849   // Make sure that the top context does not change when doing
   3850   // callbacks or interceptor calls.
   3851   AssertNoContextChange ncc;
   3852   HandleScope scope(isolate);
   3853   Handle<InterceptorInfo> interceptor(GetIndexedInterceptor());
   3854   if (interceptor->deleter()->IsUndefined()) return heap->false_value();
   3855   v8::IndexedPropertyDeleter deleter =
   3856       v8::ToCData<v8::IndexedPropertyDeleter>(interceptor->deleter());
   3857   Handle<JSObject> this_handle(this);
   3858   LOG(isolate,
   3859       ApiIndexedPropertyAccess("interceptor-indexed-delete", this, index));
   3860   CustomArguments args(isolate, interceptor->data(), this, this);
   3861   v8::AccessorInfo info(args.end());
   3862   v8::Handle<v8::Boolean> result;
   3863   {
   3864     // Leaving JavaScript.
   3865     VMState state(isolate, EXTERNAL);
   3866     result = deleter(index, info);
   3867   }
   3868   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   3869   if (!result.IsEmpty()) {
   3870     ASSERT(result->IsBoolean());
   3871     return *v8::Utils::OpenHandle(*result);
   3872   }
   3873   MaybeObject* raw_result = this_handle->GetElementsAccessor()->Delete(
   3874       *this_handle,
   3875       index,
   3876       NORMAL_DELETION);
   3877   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   3878   return raw_result;
   3879 }
   3880 
   3881 
   3882 Handle<Object> JSObject::DeleteElement(Handle<JSObject> obj,
   3883                                        uint32_t index) {
   3884   CALL_HEAP_FUNCTION(obj->GetIsolate(),
   3885                      obj->DeleteElement(index, JSObject::NORMAL_DELETION),
   3886                      Object);
   3887 }
   3888 
   3889 
   3890 MaybeObject* JSObject::DeleteElement(uint32_t index, DeleteMode mode) {
   3891   Isolate* isolate = GetIsolate();
   3892   // Check access rights if needed.
   3893   if (IsAccessCheckNeeded() &&
   3894       !isolate->MayIndexedAccess(this, index, v8::ACCESS_DELETE)) {
   3895     isolate->ReportFailedAccessCheck(this, v8::ACCESS_DELETE);
   3896     return isolate->heap()->false_value();
   3897   }
   3898 
   3899   if (IsJSGlobalProxy()) {
   3900     Object* proto = GetPrototype();
   3901     if (proto->IsNull()) return isolate->heap()->false_value();
   3902     ASSERT(proto->IsJSGlobalObject());
   3903     return JSGlobalObject::cast(proto)->DeleteElement(index, mode);
   3904   }
   3905 
   3906   if (HasIndexedInterceptor()) {
   3907     // Skip interceptor if forcing deletion.
   3908     if (mode != FORCE_DELETION) {
   3909       return DeleteElementWithInterceptor(index);
   3910     }
   3911     mode = JSReceiver::FORCE_DELETION;
   3912   }
   3913 
   3914   return GetElementsAccessor()->Delete(this, index, mode);
   3915 }
   3916 
   3917 
   3918 Handle<Object> JSObject::DeleteProperty(Handle<JSObject> obj,
   3919                               Handle<String> prop) {
   3920   CALL_HEAP_FUNCTION(obj->GetIsolate(),
   3921                      obj->DeleteProperty(*prop, JSObject::NORMAL_DELETION),
   3922                      Object);
   3923 }
   3924 
   3925 
   3926 MaybeObject* JSObject::DeleteProperty(String* name, DeleteMode mode) {
   3927   Isolate* isolate = GetIsolate();
   3928   // ECMA-262, 3rd, 8.6.2.5
   3929   ASSERT(name->IsString());
   3930 
   3931   // Check access rights if needed.
   3932   if (IsAccessCheckNeeded() &&
   3933       !isolate->MayNamedAccess(this, name, v8::ACCESS_DELETE)) {
   3934     isolate->ReportFailedAccessCheck(this, v8::ACCESS_DELETE);
   3935     return isolate->heap()->false_value();
   3936   }
   3937 
   3938   if (IsJSGlobalProxy()) {
   3939     Object* proto = GetPrototype();
   3940     if (proto->IsNull()) return isolate->heap()->false_value();
   3941     ASSERT(proto->IsJSGlobalObject());
   3942     return JSGlobalObject::cast(proto)->DeleteProperty(name, mode);
   3943   }
   3944 
   3945   uint32_t index = 0;
   3946   if (name->AsArrayIndex(&index)) {
   3947     return DeleteElement(index, mode);
   3948   } else {
   3949     LookupResult result(isolate);
   3950     LocalLookup(name, &result);
   3951     if (!result.IsProperty()) return isolate->heap()->true_value();
   3952     // Ignore attributes if forcing a deletion.
   3953     if (result.IsDontDelete() && mode != FORCE_DELETION) {
   3954       if (mode == STRICT_DELETION) {
   3955         // Deleting a non-configurable property in strict mode.
   3956         HandleScope scope(isolate);
   3957         Handle<Object> args[2] = { Handle<Object>(name), Handle<Object>(this) };
   3958         return isolate->Throw(*isolate->factory()->NewTypeError(
   3959             "strict_delete_property", HandleVector(args, 2)));
   3960       }
   3961       return isolate->heap()->false_value();
   3962     }
   3963     // Check for interceptor.
   3964     if (result.type() == INTERCEPTOR) {
   3965       // Skip interceptor if forcing a deletion.
   3966       if (mode == FORCE_DELETION) {
   3967         return DeletePropertyPostInterceptor(name, mode);
   3968       }
   3969       return DeletePropertyWithInterceptor(name);
   3970     }
   3971     // Normalize object if needed.
   3972     Object* obj;
   3973     { MaybeObject* maybe_obj =
   3974           NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
   3975       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   3976     }
   3977     // Make sure the properties are normalized before removing the entry.
   3978     return DeleteNormalizedProperty(name, mode);
   3979   }
   3980 }
   3981 
   3982 
   3983 MaybeObject* JSReceiver::DeleteElement(uint32_t index, DeleteMode mode) {
   3984   if (IsJSProxy()) {
   3985     return JSProxy::cast(this)->DeleteElementWithHandler(index, mode);
   3986   }
   3987   return JSObject::cast(this)->DeleteElement(index, mode);
   3988 }
   3989 
   3990 
   3991 MaybeObject* JSReceiver::DeleteProperty(String* name, DeleteMode mode) {
   3992   if (IsJSProxy()) {
   3993     return JSProxy::cast(this)->DeletePropertyWithHandler(name, mode);
   3994   }
   3995   return JSObject::cast(this)->DeleteProperty(name, mode);
   3996 }
   3997 
   3998 
   3999 bool JSObject::ReferencesObjectFromElements(FixedArray* elements,
   4000                                             ElementsKind kind,
   4001                                             Object* object) {
   4002   ASSERT(kind == FAST_ELEMENTS ||
   4003          kind == DICTIONARY_ELEMENTS);
   4004   if (kind == FAST_ELEMENTS) {
   4005     int length = IsJSArray()
   4006         ? Smi::cast(JSArray::cast(this)->length())->value()
   4007         : elements->length();
   4008     for (int i = 0; i < length; ++i) {
   4009       Object* element = elements->get(i);
   4010       if (!element->IsTheHole() && element == object) return true;
   4011     }
   4012   } else {
   4013     Object* key =
   4014         SeededNumberDictionary::cast(elements)->SlowReverseLookup(object);
   4015     if (!key->IsUndefined()) return true;
   4016   }
   4017   return false;
   4018 }
   4019 
   4020 
   4021 // Check whether this object references another object.
   4022 bool JSObject::ReferencesObject(Object* obj) {
   4023   Map* map_of_this = map();
   4024   Heap* heap = GetHeap();
   4025   AssertNoAllocation no_alloc;
   4026 
   4027   // Is the object the constructor for this object?
   4028   if (map_of_this->constructor() == obj) {
   4029     return true;
   4030   }
   4031 
   4032   // Is the object the prototype for this object?
   4033   if (map_of_this->prototype() == obj) {
   4034     return true;
   4035   }
   4036 
   4037   // Check if the object is among the named properties.
   4038   Object* key = SlowReverseLookup(obj);
   4039   if (!key->IsUndefined()) {
   4040     return true;
   4041   }
   4042 
   4043   // Check if the object is among the indexed properties.
   4044   ElementsKind kind = GetElementsKind();
   4045   switch (kind) {
   4046     case EXTERNAL_PIXEL_ELEMENTS:
   4047     case EXTERNAL_BYTE_ELEMENTS:
   4048     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
   4049     case EXTERNAL_SHORT_ELEMENTS:
   4050     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
   4051     case EXTERNAL_INT_ELEMENTS:
   4052     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
   4053     case EXTERNAL_FLOAT_ELEMENTS:
   4054     case EXTERNAL_DOUBLE_ELEMENTS:
   4055     case FAST_DOUBLE_ELEMENTS:
   4056       // Raw pixels and external arrays do not reference other
   4057       // objects.
   4058       break;
   4059     case FAST_SMI_ONLY_ELEMENTS:
   4060       break;
   4061     case FAST_ELEMENTS:
   4062     case DICTIONARY_ELEMENTS: {
   4063       FixedArray* elements = FixedArray::cast(this->elements());
   4064       if (ReferencesObjectFromElements(elements, kind, obj)) return true;
   4065       break;
   4066     }
   4067     case NON_STRICT_ARGUMENTS_ELEMENTS: {
   4068       FixedArray* parameter_map = FixedArray::cast(elements());
   4069       // Check the mapped parameters.
   4070       int length = parameter_map->length();
   4071       for (int i = 2; i < length; ++i) {
   4072         Object* value = parameter_map->get(i);
   4073         if (!value->IsTheHole() && value == obj) return true;
   4074       }
   4075       // Check the arguments.
   4076       FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
   4077       kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS : FAST_ELEMENTS;
   4078       if (ReferencesObjectFromElements(arguments, kind, obj)) return true;
   4079       break;
   4080     }
   4081   }
   4082 
   4083   // For functions check the context.
   4084   if (IsJSFunction()) {
   4085     // Get the constructor function for arguments array.
   4086     JSObject* arguments_boilerplate =
   4087         heap->isolate()->context()->global_context()->
   4088             arguments_boilerplate();
   4089     JSFunction* arguments_function =
   4090         JSFunction::cast(arguments_boilerplate->map()->constructor());
   4091 
   4092     // Get the context and don't check if it is the global context.
   4093     JSFunction* f = JSFunction::cast(this);
   4094     Context* context = f->context();
   4095     if (context->IsGlobalContext()) {
   4096       return false;
   4097     }
   4098 
   4099     // Check the non-special context slots.
   4100     for (int i = Context::MIN_CONTEXT_SLOTS; i < context->length(); i++) {
   4101       // Only check JS objects.
   4102       if (context->get(i)->IsJSObject()) {
   4103         JSObject* ctxobj = JSObject::cast(context->get(i));
   4104         // If it is an arguments array check the content.
   4105         if (ctxobj->map()->constructor() == arguments_function) {
   4106           if (ctxobj->ReferencesObject(obj)) {
   4107             return true;
   4108           }
   4109         } else if (ctxobj == obj) {
   4110           return true;
   4111         }
   4112       }
   4113     }
   4114 
   4115     // Check the context extension (if any) if it can have references.
   4116     if (context->has_extension() && !context->IsCatchContext()) {
   4117       return JSObject::cast(context->extension())->ReferencesObject(obj);
   4118     }
   4119   }
   4120 
   4121   // No references to object.
   4122   return false;
   4123 }
   4124 
   4125 
   4126 Handle<Object> JSObject::PreventExtensions(Handle<JSObject> object) {
   4127   CALL_HEAP_FUNCTION(object->GetIsolate(), object->PreventExtensions(), Object);
   4128 }
   4129 
   4130 
   4131 MaybeObject* JSObject::PreventExtensions() {
   4132   Isolate* isolate = GetIsolate();
   4133   if (IsAccessCheckNeeded() &&
   4134       !isolate->MayNamedAccess(this,
   4135                                isolate->heap()->undefined_value(),
   4136                                v8::ACCESS_KEYS)) {
   4137     isolate->ReportFailedAccessCheck(this, v8::ACCESS_KEYS);
   4138     return isolate->heap()->false_value();
   4139   }
   4140 
   4141   if (IsJSGlobalProxy()) {
   4142     Object* proto = GetPrototype();
   4143     if (proto->IsNull()) return this;
   4144     ASSERT(proto->IsJSGlobalObject());
   4145     return JSObject::cast(proto)->PreventExtensions();
   4146   }
   4147 
   4148   // It's not possible to seal objects with external array elements
   4149   if (HasExternalArrayElements()) {
   4150     HandleScope scope(isolate);
   4151     Handle<Object> object(this);
   4152     Handle<Object> error  =
   4153         isolate->factory()->NewTypeError(
   4154             "cant_prevent_ext_external_array_elements",
   4155             HandleVector(&object, 1));
   4156     return isolate->Throw(*error);
   4157   }
   4158 
   4159   // If there are fast elements we normalize.
   4160   SeededNumberDictionary* dictionary = NULL;
   4161   { MaybeObject* maybe = NormalizeElements();
   4162     if (!maybe->To<SeededNumberDictionary>(&dictionary)) return maybe;
   4163   }
   4164   ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements());
   4165   // Make sure that we never go back to fast case.
   4166   dictionary->set_requires_slow_elements();
   4167 
   4168   // Do a map transition, other objects with this map may still
   4169   // be extensible.
   4170   Map* new_map;
   4171   { MaybeObject* maybe = map()->CopyDropTransitions();
   4172     if (!maybe->To<Map>(&new_map)) return maybe;
   4173   }
   4174   new_map->set_is_extensible(false);
   4175   set_map(new_map);
   4176   ASSERT(!map()->is_extensible());
   4177   return new_map;
   4178 }
   4179 
   4180 
   4181 // Tests for the fast common case for property enumeration:
   4182 // - This object and all prototypes has an enum cache (which means that
   4183 //   it is no proxy, has no interceptors and needs no access checks).
   4184 // - This object has no elements.
   4185 // - No prototype has enumerable properties/elements.
   4186 bool JSReceiver::IsSimpleEnum() {
   4187   Heap* heap = GetHeap();
   4188   for (Object* o = this;
   4189        o != heap->null_value();
   4190        o = JSObject::cast(o)->GetPrototype()) {
   4191     if (!o->IsJSObject()) return false;
   4192     JSObject* curr = JSObject::cast(o);
   4193     if (!curr->map()->instance_descriptors()->HasEnumCache()) return false;
   4194     ASSERT(!curr->HasNamedInterceptor());
   4195     ASSERT(!curr->HasIndexedInterceptor());
   4196     ASSERT(!curr->IsAccessCheckNeeded());
   4197     if (curr->NumberOfEnumElements() > 0) return false;
   4198     if (curr != this) {
   4199       FixedArray* curr_fixed_array =
   4200           FixedArray::cast(curr->map()->instance_descriptors()->GetEnumCache());
   4201       if (curr_fixed_array->length() > 0) return false;
   4202     }
   4203   }
   4204   return true;
   4205 }
   4206 
   4207 
   4208 int Map::NumberOfDescribedProperties(PropertyAttributes filter) {
   4209   int result = 0;
   4210   DescriptorArray* descs = instance_descriptors();
   4211   for (int i = 0; i < descs->number_of_descriptors(); i++) {
   4212     PropertyDetails details(descs->GetDetails(i));
   4213     if (descs->IsProperty(i) && (details.attributes() & filter) == 0) {
   4214       result++;
   4215     }
   4216   }
   4217   return result;
   4218 }
   4219 
   4220 
   4221 int Map::PropertyIndexFor(String* name) {
   4222   DescriptorArray* descs = instance_descriptors();
   4223   for (int i = 0; i < descs->number_of_descriptors(); i++) {
   4224     if (name->Equals(descs->GetKey(i)) && !descs->IsNullDescriptor(i)) {
   4225       return descs->GetFieldIndex(i);
   4226     }
   4227   }
   4228   return -1;
   4229 }
   4230 
   4231 
   4232 int Map::NextFreePropertyIndex() {
   4233   int max_index = -1;
   4234   DescriptorArray* descs = instance_descriptors();
   4235   for (int i = 0; i < descs->number_of_descriptors(); i++) {
   4236     if (descs->GetType(i) == FIELD) {
   4237       int current_index = descs->GetFieldIndex(i);
   4238       if (current_index > max_index) max_index = current_index;
   4239     }
   4240   }
   4241   return max_index + 1;
   4242 }
   4243 
   4244 
   4245 AccessorDescriptor* Map::FindAccessor(String* name) {
   4246   DescriptorArray* descs = instance_descriptors();
   4247   for (int i = 0; i < descs->number_of_descriptors(); i++) {
   4248     if (name->Equals(descs->GetKey(i)) && descs->GetType(i) == CALLBACKS) {
   4249       return descs->GetCallbacks(i);
   4250     }
   4251   }
   4252   return NULL;
   4253 }
   4254 
   4255 
   4256 void JSReceiver::LocalLookup(String* name, LookupResult* result) {
   4257   ASSERT(name->IsString());
   4258 
   4259   Heap* heap = GetHeap();
   4260 
   4261   if (IsJSGlobalProxy()) {
   4262     Object* proto = GetPrototype();
   4263     if (proto->IsNull()) return result->NotFound();
   4264     ASSERT(proto->IsJSGlobalObject());
   4265     return JSReceiver::cast(proto)->LocalLookup(name, result);
   4266   }
   4267 
   4268   if (IsJSProxy()) {
   4269     result->HandlerResult(JSProxy::cast(this));
   4270     return;
   4271   }
   4272 
   4273   // Do not use inline caching if the object is a non-global object
   4274   // that requires access checks.
   4275   if (IsAccessCheckNeeded()) {
   4276     result->DisallowCaching();
   4277   }
   4278 
   4279   JSObject* js_object = JSObject::cast(this);
   4280 
   4281   // Check __proto__ before interceptor.
   4282   if (name->Equals(heap->Proto_symbol()) && !IsJSContextExtensionObject()) {
   4283     result->ConstantResult(js_object);
   4284     return;
   4285   }
   4286 
   4287   // Check for lookup interceptor except when bootstrapping.
   4288   if (js_object->HasNamedInterceptor() &&
   4289       !heap->isolate()->bootstrapper()->IsActive()) {
   4290     result->InterceptorResult(js_object);
   4291     return;
   4292   }
   4293 
   4294   js_object->LocalLookupRealNamedProperty(name, result);
   4295 }
   4296 
   4297 
   4298 void JSReceiver::Lookup(String* name, LookupResult* result) {
   4299   // Ecma-262 3rd 8.6.2.4
   4300   Heap* heap = GetHeap();
   4301   for (Object* current = this;
   4302        current != heap->null_value();
   4303        current = JSObject::cast(current)->GetPrototype()) {
   4304     JSReceiver::cast(current)->LocalLookup(name, result);
   4305     if (result->IsProperty()) return;
   4306   }
   4307   result->NotFound();
   4308 }
   4309 
   4310 
   4311 // Search object and it's prototype chain for callback properties.
   4312 void JSObject::LookupCallback(String* name, LookupResult* result) {
   4313   Heap* heap = GetHeap();
   4314   for (Object* current = this;
   4315        current != heap->null_value() && current->IsJSObject();
   4316        current = JSObject::cast(current)->GetPrototype()) {
   4317     JSObject::cast(current)->LocalLookupRealNamedProperty(name, result);
   4318     if (result->IsFound() && result->type() == CALLBACKS) return;
   4319   }
   4320   result->NotFound();
   4321 }
   4322 
   4323 
   4324 // Try to update an accessor in an elements dictionary. Return true if the
   4325 // update succeeded, and false otherwise.
   4326 static bool UpdateGetterSetterInDictionary(
   4327     SeededNumberDictionary* dictionary,
   4328     uint32_t index,
   4329     Object* getter,
   4330     Object* setter,
   4331     PropertyAttributes attributes) {
   4332   int entry = dictionary->FindEntry(index);
   4333   if (entry != SeededNumberDictionary::kNotFound) {
   4334     Object* result = dictionary->ValueAt(entry);
   4335     PropertyDetails details = dictionary->DetailsAt(entry);
   4336     if (details.type() == CALLBACKS && result->IsAccessorPair()) {
   4337       ASSERT(!details.IsDontDelete());
   4338       if (details.attributes() != attributes) {
   4339         dictionary->DetailsAtPut(entry,
   4340                                  PropertyDetails(attributes, CALLBACKS, index));
   4341       }
   4342       AccessorPair::cast(result)->SetComponents(getter, setter);
   4343       return true;
   4344     }
   4345   }
   4346   return false;
   4347 }
   4348 
   4349 
   4350 MaybeObject* JSObject::DefineElementAccessor(uint32_t index,
   4351                                              Object* getter,
   4352                                              Object* setter,
   4353                                              PropertyAttributes attributes) {
   4354   switch (GetElementsKind()) {
   4355     case FAST_SMI_ONLY_ELEMENTS:
   4356     case FAST_ELEMENTS:
   4357     case FAST_DOUBLE_ELEMENTS:
   4358       break;
   4359     case EXTERNAL_PIXEL_ELEMENTS:
   4360     case EXTERNAL_BYTE_ELEMENTS:
   4361     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
   4362     case EXTERNAL_SHORT_ELEMENTS:
   4363     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
   4364     case EXTERNAL_INT_ELEMENTS:
   4365     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
   4366     case EXTERNAL_FLOAT_ELEMENTS:
   4367     case EXTERNAL_DOUBLE_ELEMENTS:
   4368       // Ignore getters and setters on pixel and external array elements.
   4369       return GetHeap()->undefined_value();
   4370     case DICTIONARY_ELEMENTS:
   4371       if (UpdateGetterSetterInDictionary(element_dictionary(),
   4372                                          index,
   4373                                          getter,
   4374                                          setter,
   4375                                          attributes)) {
   4376         return GetHeap()->undefined_value();
   4377       }
   4378       break;
   4379     case NON_STRICT_ARGUMENTS_ELEMENTS: {
   4380       // Ascertain whether we have read-only properties or an existing
   4381       // getter/setter pair in an arguments elements dictionary backing
   4382       // store.
   4383       FixedArray* parameter_map = FixedArray::cast(elements());
   4384       uint32_t length = parameter_map->length();
   4385       Object* probe =
   4386           index < (length - 2) ? parameter_map->get(index + 2) : NULL;
   4387       if (probe == NULL || probe->IsTheHole()) {
   4388         FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
   4389         if (arguments->IsDictionary()) {
   4390           SeededNumberDictionary* dictionary =
   4391               SeededNumberDictionary::cast(arguments);
   4392           if (UpdateGetterSetterInDictionary(dictionary,
   4393                                              index,
   4394                                              getter,
   4395                                              setter,
   4396                                              attributes)) {
   4397             return GetHeap()->undefined_value();
   4398           }
   4399         }
   4400       }
   4401       break;
   4402     }
   4403   }
   4404 
   4405   AccessorPair* accessors;
   4406   { MaybeObject* maybe_accessors = GetHeap()->AllocateAccessorPair();
   4407     if (!maybe_accessors->To(&accessors)) return maybe_accessors;
   4408   }
   4409   accessors->SetComponents(getter, setter);
   4410 
   4411   return SetElementCallback(index, accessors, attributes);
   4412 }
   4413 
   4414 
   4415 MaybeObject* JSObject::DefinePropertyAccessor(String* name,
   4416                                               Object* getter,
   4417                                               Object* setter,
   4418                                               PropertyAttributes attributes) {
   4419   // Lookup the name.
   4420   LookupResult result(GetHeap()->isolate());
   4421   LocalLookupRealNamedProperty(name, &result);
   4422   if (result.IsFound()) {
   4423     if (result.type() == CALLBACKS) {
   4424       ASSERT(!result.IsDontDelete());
   4425       Object* obj = result.GetCallbackObject();
   4426       // Need to preserve old getters/setters.
   4427       if (obj->IsAccessorPair()) {
   4428         AccessorPair* copy;
   4429         { MaybeObject* maybe_copy =
   4430               AccessorPair::cast(obj)->CopyWithoutTransitions();
   4431           if (!maybe_copy->To(&copy)) return maybe_copy;
   4432         }
   4433         copy->SetComponents(getter, setter);
   4434         // Use set to update attributes.
   4435         return SetPropertyCallback(name, copy, attributes);
   4436       }
   4437     }
   4438   }
   4439 
   4440   AccessorPair* accessors;
   4441   { MaybeObject* maybe_accessors = GetHeap()->AllocateAccessorPair();
   4442     if (!maybe_accessors->To(&accessors)) return maybe_accessors;
   4443   }
   4444   accessors->SetComponents(getter, setter);
   4445 
   4446   return SetPropertyCallback(name, accessors, attributes);
   4447 }
   4448 
   4449 
   4450 bool JSObject::CanSetCallback(String* name) {
   4451   ASSERT(!IsAccessCheckNeeded() ||
   4452          GetIsolate()->MayNamedAccess(this, name, v8::ACCESS_SET));
   4453 
   4454   // Check if there is an API defined callback object which prohibits
   4455   // callback overwriting in this object or it's prototype chain.
   4456   // This mechanism is needed for instance in a browser setting, where
   4457   // certain accessors such as window.location should not be allowed
   4458   // to be overwritten because allowing overwriting could potentially
   4459   // cause security problems.
   4460   LookupResult callback_result(GetIsolate());
   4461   LookupCallback(name, &callback_result);
   4462   if (callback_result.IsProperty()) {
   4463     Object* obj = callback_result.GetCallbackObject();
   4464     if (obj->IsAccessorInfo() &&
   4465         AccessorInfo::cast(obj)->prohibits_overwriting()) {
   4466       return false;
   4467     }
   4468   }
   4469 
   4470   return true;
   4471 }
   4472 
   4473 
   4474 MaybeObject* JSObject::SetElementCallback(uint32_t index,
   4475                                           Object* structure,
   4476                                           PropertyAttributes attributes) {
   4477   PropertyDetails details = PropertyDetails(attributes, CALLBACKS);
   4478 
   4479   // Normalize elements to make this operation simple.
   4480   SeededNumberDictionary* dictionary;
   4481   { MaybeObject* maybe_dictionary = NormalizeElements();
   4482     if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
   4483   }
   4484   ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements());
   4485 
   4486   // Update the dictionary with the new CALLBACKS property.
   4487   { MaybeObject* maybe_dictionary = dictionary->Set(index, structure, details);
   4488     if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
   4489   }
   4490 
   4491   dictionary->set_requires_slow_elements();
   4492   // Update the dictionary backing store on the object.
   4493   if (elements()->map() == GetHeap()->non_strict_arguments_elements_map()) {
   4494     // Also delete any parameter alias.
   4495     //
   4496     // TODO(kmillikin): when deleting the last parameter alias we could
   4497     // switch to a direct backing store without the parameter map.  This
   4498     // would allow GC of the context.
   4499     FixedArray* parameter_map = FixedArray::cast(elements());
   4500     if (index < static_cast<uint32_t>(parameter_map->length()) - 2) {
   4501       parameter_map->set(index + 2, GetHeap()->the_hole_value());
   4502     }
   4503     parameter_map->set(1, dictionary);
   4504   } else {
   4505     set_elements(dictionary);
   4506   }
   4507 
   4508   return GetHeap()->undefined_value();
   4509 }
   4510 
   4511 
   4512 MaybeObject* JSObject::SetPropertyCallback(String* name,
   4513                                            Object* structure,
   4514                                            PropertyAttributes attributes) {
   4515   // Normalize object to make this operation simple.
   4516   { MaybeObject* maybe_ok = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
   4517     if (maybe_ok->IsFailure()) return maybe_ok;
   4518   }
   4519 
   4520   // For the global object allocate a new map to invalidate the global inline
   4521   // caches which have a global property cell reference directly in the code.
   4522   if (IsGlobalObject()) {
   4523     Map* new_map;
   4524     { MaybeObject* maybe_new_map = map()->CopyDropDescriptors();
   4525       if (!maybe_new_map->To(&new_map)) return maybe_new_map;
   4526     }
   4527     set_map(new_map);
   4528     // When running crankshaft, changing the map is not enough. We
   4529     // need to deoptimize all functions that rely on this global
   4530     // object.
   4531     Deoptimizer::DeoptimizeGlobalObject(this);
   4532   }
   4533 
   4534   // Update the dictionary with the new CALLBACKS property.
   4535   PropertyDetails details = PropertyDetails(attributes, CALLBACKS);
   4536   { MaybeObject* maybe_ok = SetNormalizedProperty(name, structure, details);
   4537     if (maybe_ok->IsFailure()) return maybe_ok;
   4538   }
   4539 
   4540   return GetHeap()->undefined_value();
   4541 }
   4542 
   4543 
   4544 void JSObject::DefineAccessor(Handle<JSObject> object,
   4545                               Handle<String> name,
   4546                               Handle<Object> getter,
   4547                               Handle<Object> setter,
   4548                               PropertyAttributes attributes) {
   4549   CALL_HEAP_FUNCTION_VOID(
   4550       object->GetIsolate(),
   4551       object->DefineAccessor(*name, *getter, *setter, attributes));
   4552 }
   4553 
   4554 MaybeObject* JSObject::DefineAccessor(String* name,
   4555                                       Object* getter,
   4556                                       Object* setter,
   4557                                       PropertyAttributes attributes) {
   4558   Isolate* isolate = GetIsolate();
   4559   // Check access rights if needed.
   4560   if (IsAccessCheckNeeded() &&
   4561       !isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) {
   4562     isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET);
   4563     return isolate->heap()->undefined_value();
   4564   }
   4565 
   4566   if (IsJSGlobalProxy()) {
   4567     Object* proto = GetPrototype();
   4568     if (proto->IsNull()) return this;
   4569     ASSERT(proto->IsJSGlobalObject());
   4570     return JSObject::cast(proto)->DefineAccessor(
   4571         name, getter, setter, attributes);
   4572   }
   4573 
   4574   // Make sure that the top context does not change when doing callbacks or
   4575   // interceptor calls.
   4576   AssertNoContextChange ncc;
   4577 
   4578   // Try to flatten before operating on the string.
   4579   name->TryFlatten();
   4580 
   4581   if (!CanSetCallback(name)) return isolate->heap()->undefined_value();
   4582 
   4583   uint32_t index = 0;
   4584   return name->AsArrayIndex(&index) ?
   4585       DefineElementAccessor(index, getter, setter, attributes) :
   4586       DefinePropertyAccessor(name, getter, setter, attributes);
   4587 }
   4588 
   4589 
   4590 MaybeObject* JSObject::DefineAccessor(AccessorInfo* info) {
   4591   Isolate* isolate = GetIsolate();
   4592   String* name = String::cast(info->name());
   4593   // Check access rights if needed.
   4594   if (IsAccessCheckNeeded() &&
   4595       !isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) {
   4596     isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET);
   4597     return isolate->heap()->undefined_value();
   4598   }
   4599 
   4600   if (IsJSGlobalProxy()) {
   4601     Object* proto = GetPrototype();
   4602     if (proto->IsNull()) return this;
   4603     ASSERT(proto->IsJSGlobalObject());
   4604     return JSObject::cast(proto)->DefineAccessor(info);
   4605   }
   4606 
   4607   // Make sure that the top context does not change when doing callbacks or
   4608   // interceptor calls.
   4609   AssertNoContextChange ncc;
   4610 
   4611   // Try to flatten before operating on the string.
   4612   name->TryFlatten();
   4613 
   4614   if (!CanSetCallback(name)) {
   4615     return isolate->heap()->undefined_value();
   4616   }
   4617 
   4618   uint32_t index = 0;
   4619   bool is_element = name->AsArrayIndex(&index);
   4620 
   4621   if (is_element) {
   4622     if (IsJSArray()) return isolate->heap()->undefined_value();
   4623 
   4624     // Accessors overwrite previous callbacks (cf. with getters/setters).
   4625     switch (GetElementsKind()) {
   4626       case FAST_SMI_ONLY_ELEMENTS:
   4627       case FAST_ELEMENTS:
   4628       case FAST_DOUBLE_ELEMENTS:
   4629         break;
   4630       case EXTERNAL_PIXEL_ELEMENTS:
   4631       case EXTERNAL_BYTE_ELEMENTS:
   4632       case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
   4633       case EXTERNAL_SHORT_ELEMENTS:
   4634       case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
   4635       case EXTERNAL_INT_ELEMENTS:
   4636       case EXTERNAL_UNSIGNED_INT_ELEMENTS:
   4637       case EXTERNAL_FLOAT_ELEMENTS:
   4638       case EXTERNAL_DOUBLE_ELEMENTS:
   4639         // Ignore getters and setters on pixel and external array
   4640         // elements.
   4641         return isolate->heap()->undefined_value();
   4642       case DICTIONARY_ELEMENTS:
   4643         break;
   4644       case NON_STRICT_ARGUMENTS_ELEMENTS:
   4645         UNIMPLEMENTED();
   4646         break;
   4647     }
   4648 
   4649     { MaybeObject* maybe_ok =
   4650           SetElementCallback(index, info, info->property_attributes());
   4651       if (maybe_ok->IsFailure()) return maybe_ok;
   4652     }
   4653   } else {
   4654     // Lookup the name.
   4655     LookupResult result(isolate);
   4656     LocalLookup(name, &result);
   4657     // ES5 forbids turning a property into an accessor if it's not
   4658     // configurable (that is IsDontDelete in ES3 and v8), see 8.6.1 (Table 5).
   4659     if (result.IsProperty() && (result.IsReadOnly() || result.IsDontDelete())) {
   4660       return isolate->heap()->undefined_value();
   4661     }
   4662     { MaybeObject* maybe_ok =
   4663           SetPropertyCallback(name, info, info->property_attributes());
   4664       if (maybe_ok->IsFailure()) return maybe_ok;
   4665     }
   4666   }
   4667 
   4668   return this;
   4669 }
   4670 
   4671 
   4672 Object* JSObject::LookupAccessor(String* name, AccessorComponent component) {
   4673   Heap* heap = GetHeap();
   4674 
   4675   // Make sure that the top context does not change when doing callbacks or
   4676   // interceptor calls.
   4677   AssertNoContextChange ncc;
   4678 
   4679   // Check access rights if needed.
   4680   if (IsAccessCheckNeeded() &&
   4681       !heap->isolate()->MayNamedAccess(this, name, v8::ACCESS_HAS)) {
   4682     heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
   4683     return heap->undefined_value();
   4684   }
   4685 
   4686   // Make the lookup and include prototypes.
   4687   uint32_t index = 0;
   4688   if (name->AsArrayIndex(&index)) {
   4689     for (Object* obj = this;
   4690          obj != heap->null_value();
   4691          obj = JSObject::cast(obj)->GetPrototype()) {
   4692       JSObject* js_object = JSObject::cast(obj);
   4693       if (js_object->HasDictionaryElements()) {
   4694         SeededNumberDictionary* dictionary = js_object->element_dictionary();
   4695         int entry = dictionary->FindEntry(index);
   4696         if (entry != SeededNumberDictionary::kNotFound) {
   4697           Object* element = dictionary->ValueAt(entry);
   4698           if (dictionary->DetailsAt(entry).type() == CALLBACKS &&
   4699               element->IsAccessorPair()) {
   4700             return AccessorPair::cast(element)->GetComponent(component);
   4701           }
   4702         }
   4703       }
   4704     }
   4705   } else {
   4706     for (Object* obj = this;
   4707          obj != heap->null_value();
   4708          obj = JSObject::cast(obj)->GetPrototype()) {
   4709       LookupResult result(heap->isolate());
   4710       JSObject::cast(obj)->LocalLookup(name, &result);
   4711       if (result.IsProperty()) {
   4712         if (result.IsReadOnly()) return heap->undefined_value();
   4713         if (result.type() == CALLBACKS) {
   4714           Object* obj = result.GetCallbackObject();
   4715           if (obj->IsAccessorPair()) {
   4716             return AccessorPair::cast(obj)->GetComponent(component);
   4717           }
   4718         }
   4719       }
   4720     }
   4721   }
   4722   return heap->undefined_value();
   4723 }
   4724 
   4725 
   4726 Object* JSObject::SlowReverseLookup(Object* value) {
   4727   if (HasFastProperties()) {
   4728     DescriptorArray* descs = map()->instance_descriptors();
   4729     for (int i = 0; i < descs->number_of_descriptors(); i++) {
   4730       if (descs->GetType(i) == FIELD) {
   4731         if (FastPropertyAt(descs->GetFieldIndex(i)) == value) {
   4732           return descs->GetKey(i);
   4733         }
   4734       } else if (descs->GetType(i) == CONSTANT_FUNCTION) {
   4735         if (descs->GetConstantFunction(i) == value) {
   4736           return descs->GetKey(i);
   4737         }
   4738       }
   4739     }
   4740     return GetHeap()->undefined_value();
   4741   } else {
   4742     return property_dictionary()->SlowReverseLookup(value);
   4743   }
   4744 }
   4745 
   4746 
   4747 MaybeObject* Map::CopyDropDescriptors() {
   4748   Heap* heap = GetHeap();
   4749   Object* result;
   4750   { MaybeObject* maybe_result =
   4751         heap->AllocateMap(instance_type(), instance_size());
   4752     if (!maybe_result->ToObject(&result)) return maybe_result;
   4753   }
   4754   Map::cast(result)->set_prototype(prototype());
   4755   Map::cast(result)->set_constructor(constructor());
   4756   // Don't copy descriptors, so map transitions always remain a forest.
   4757   // If we retained the same descriptors we would have two maps
   4758   // pointing to the same transition which is bad because the garbage
   4759   // collector relies on being able to reverse pointers from transitions
   4760   // to maps.  If properties need to be retained use CopyDropTransitions.
   4761   Map::cast(result)->clear_instance_descriptors();
   4762   // Please note instance_type and instance_size are set when allocated.
   4763   Map::cast(result)->set_inobject_properties(inobject_properties());
   4764   Map::cast(result)->set_unused_property_fields(unused_property_fields());
   4765 
   4766   // If the map has pre-allocated properties always start out with a descriptor
   4767   // array describing these properties.
   4768   if (pre_allocated_property_fields() > 0) {
   4769     ASSERT(constructor()->IsJSFunction());
   4770     JSFunction* ctor = JSFunction::cast(constructor());
   4771     Object* descriptors;
   4772     { MaybeObject* maybe_descriptors =
   4773           ctor->initial_map()->instance_descriptors()->RemoveTransitions();
   4774       if (!maybe_descriptors->ToObject(&descriptors)) return maybe_descriptors;
   4775     }
   4776     Map::cast(result)->set_instance_descriptors(
   4777         DescriptorArray::cast(descriptors));
   4778     Map::cast(result)->set_pre_allocated_property_fields(
   4779         pre_allocated_property_fields());
   4780   }
   4781   Map::cast(result)->set_bit_field(bit_field());
   4782   Map::cast(result)->set_bit_field2(bit_field2());
   4783   Map::cast(result)->set_bit_field3(bit_field3());
   4784   Map::cast(result)->set_is_shared(false);
   4785   Map::cast(result)->ClearCodeCache(heap);
   4786   return result;
   4787 }
   4788 
   4789 
   4790 MaybeObject* Map::CopyNormalized(PropertyNormalizationMode mode,
   4791                                  NormalizedMapSharingMode sharing) {
   4792   int new_instance_size = instance_size();
   4793   if (mode == CLEAR_INOBJECT_PROPERTIES) {
   4794     new_instance_size -= inobject_properties() * kPointerSize;
   4795   }
   4796 
   4797   Object* result;
   4798   { MaybeObject* maybe_result =
   4799         GetHeap()->AllocateMap(instance_type(), new_instance_size);
   4800     if (!maybe_result->ToObject(&result)) return maybe_result;
   4801   }
   4802 
   4803   if (mode != CLEAR_INOBJECT_PROPERTIES) {
   4804     Map::cast(result)->set_inobject_properties(inobject_properties());
   4805   }
   4806 
   4807   Map::cast(result)->set_prototype(prototype());
   4808   Map::cast(result)->set_constructor(constructor());
   4809 
   4810   Map::cast(result)->set_bit_field(bit_field());
   4811   Map::cast(result)->set_bit_field2(bit_field2());
   4812   Map::cast(result)->set_bit_field3(bit_field3());
   4813 
   4814   Map::cast(result)->set_is_shared(sharing == SHARED_NORMALIZED_MAP);
   4815 
   4816 #ifdef DEBUG
   4817   if (FLAG_verify_heap && Map::cast(result)->is_shared()) {
   4818     Map::cast(result)->SharedMapVerify();
   4819   }
   4820 #endif
   4821 
   4822   return result;
   4823 }
   4824 
   4825 
   4826 MaybeObject* Map::CopyDropTransitions() {
   4827   Object* new_map;
   4828   { MaybeObject* maybe_new_map = CopyDropDescriptors();
   4829     if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
   4830   }
   4831   Object* descriptors;
   4832   { MaybeObject* maybe_descriptors =
   4833         instance_descriptors()->RemoveTransitions();
   4834     if (!maybe_descriptors->ToObject(&descriptors)) return maybe_descriptors;
   4835   }
   4836   cast(new_map)->set_instance_descriptors(DescriptorArray::cast(descriptors));
   4837   return new_map;
   4838 }
   4839 
   4840 void Map::UpdateCodeCache(Handle<Map> map,
   4841                           Handle<String> name,
   4842                           Handle<Code> code) {
   4843   Isolate* isolate = map->GetIsolate();
   4844   CALL_HEAP_FUNCTION_VOID(isolate,
   4845                           map->UpdateCodeCache(*name, *code));
   4846 }
   4847 
   4848 MaybeObject* Map::UpdateCodeCache(String* name, Code* code) {
   4849   // Allocate the code cache if not present.
   4850   if (code_cache()->IsFixedArray()) {
   4851     Object* result;
   4852     { MaybeObject* maybe_result = GetHeap()->AllocateCodeCache();
   4853       if (!maybe_result->ToObject(&result)) return maybe_result;
   4854     }
   4855     set_code_cache(result);
   4856   }
   4857 
   4858   // Update the code cache.
   4859   return CodeCache::cast(code_cache())->Update(name, code);
   4860 }
   4861 
   4862 
   4863 Object* Map::FindInCodeCache(String* name, Code::Flags flags) {
   4864   // Do a lookup if a code cache exists.
   4865   if (!code_cache()->IsFixedArray()) {
   4866     return CodeCache::cast(code_cache())->Lookup(name, flags);
   4867   } else {
   4868     return GetHeap()->undefined_value();
   4869   }
   4870 }
   4871 
   4872 
   4873 int Map::IndexInCodeCache(Object* name, Code* code) {
   4874   // Get the internal index if a code cache exists.
   4875   if (!code_cache()->IsFixedArray()) {
   4876     return CodeCache::cast(code_cache())->GetIndex(name, code);
   4877   }
   4878   return -1;
   4879 }
   4880 
   4881 
   4882 void Map::RemoveFromCodeCache(String* name, Code* code, int index) {
   4883   // No GC is supposed to happen between a call to IndexInCodeCache and
   4884   // RemoveFromCodeCache so the code cache must be there.
   4885   ASSERT(!code_cache()->IsFixedArray());
   4886   CodeCache::cast(code_cache())->RemoveByIndex(name, code, index);
   4887 }
   4888 
   4889 
   4890 // An iterator over all map transitions in an descriptor array, reusing the map
   4891 // field of the contens array while it is running.
   4892 class IntrusiveMapTransitionIterator {
   4893  public:
   4894   explicit IntrusiveMapTransitionIterator(DescriptorArray* descriptor_array)
   4895       : descriptor_array_(descriptor_array) { }
   4896 
   4897   void Start() {
   4898     ASSERT(!IsIterating());
   4899     if (HasContentArray()) *ContentHeader() = Smi::FromInt(0);
   4900   }
   4901 
   4902   bool IsIterating() {
   4903     return HasContentArray() && (*ContentHeader())->IsSmi();
   4904   }
   4905 
   4906   Map* Next() {
   4907     ASSERT(IsIterating());
   4908     FixedArray* contents = ContentArray();
   4909     // Attention, tricky index manipulation ahead: Every entry in the contents
   4910     // array consists of a value/details pair, so the index is typically even.
   4911     // An exception is made for CALLBACKS entries: An even index means we look
   4912     // at its getter, and an odd index means we look at its setter.
   4913     int index = Smi::cast(*ContentHeader())->value();
   4914     while (index < contents->length()) {
   4915       PropertyDetails details(Smi::cast(contents->get(index | 1)));
   4916       switch (details.type()) {
   4917         case MAP_TRANSITION:
   4918         case CONSTANT_TRANSITION:
   4919         case ELEMENTS_TRANSITION:
   4920           // We definitely have a map transition.
   4921           *ContentHeader() = Smi::FromInt(index + 2);
   4922           return static_cast<Map*>(contents->get(index));
   4923         case CALLBACKS: {
   4924           // We might have a map transition in a getter or in a setter.
   4925           AccessorPair* accessors =
   4926               static_cast<AccessorPair*>(contents->get(index & ~1));
   4927           Object* accessor =
   4928               ((index & 1) == 0) ? accessors->getter() : accessors->setter();
   4929           index++;
   4930           if (accessor->IsMap()) {
   4931             *ContentHeader() = Smi::FromInt(index);
   4932             return static_cast<Map*>(accessor);
   4933           }
   4934           break;
   4935         }
   4936         case NORMAL:
   4937         case FIELD:
   4938         case CONSTANT_FUNCTION:
   4939         case HANDLER:
   4940         case INTERCEPTOR:
   4941         case NULL_DESCRIPTOR:
   4942           // We definitely have no map transition.
   4943           index += 2;
   4944           break;
   4945       }
   4946     }
   4947     *ContentHeader() = descriptor_array_->GetHeap()->fixed_array_map();
   4948     return NULL;
   4949   }
   4950 
   4951  private:
   4952   bool HasContentArray() {
   4953     return descriptor_array_-> length() > DescriptorArray::kContentArrayIndex;
   4954   }
   4955 
   4956   FixedArray* ContentArray() {
   4957     Object* array = descriptor_array_->get(DescriptorArray::kContentArrayIndex);
   4958     return static_cast<FixedArray*>(array);
   4959   }
   4960 
   4961   Object** ContentHeader() {
   4962     return HeapObject::RawField(ContentArray(), DescriptorArray::kMapOffset);
   4963   }
   4964 
   4965   DescriptorArray* descriptor_array_;
   4966 };
   4967 
   4968 
   4969 // An iterator over all prototype transitions, reusing the map field of the
   4970 // underlying array while it is running.
   4971 class IntrusivePrototypeTransitionIterator {
   4972  public:
   4973   explicit IntrusivePrototypeTransitionIterator(FixedArray* proto_trans)
   4974       : proto_trans_(proto_trans) { }
   4975 
   4976   void Start() {
   4977     ASSERT(!IsIterating());
   4978     if (HasTransitions()) *Header() = Smi::FromInt(0);
   4979   }
   4980 
   4981   bool IsIterating() {
   4982     return HasTransitions() && (*Header())->IsSmi();
   4983   }
   4984 
   4985   Map* Next() {
   4986     ASSERT(IsIterating());
   4987     int transitionNumber = Smi::cast(*Header())->value();
   4988     if (transitionNumber < NumberOfTransitions()) {
   4989       *Header() = Smi::FromInt(transitionNumber + 1);
   4990       return GetTransition(transitionNumber);
   4991     }
   4992     *Header() = proto_trans_->GetHeap()->fixed_array_map();
   4993     return NULL;
   4994   }
   4995 
   4996  private:
   4997   bool HasTransitions() {
   4998     return proto_trans_->length() >= Map::kProtoTransitionHeaderSize;
   4999   }
   5000 
   5001   Object** Header() {
   5002     return HeapObject::RawField(proto_trans_, FixedArray::kMapOffset);
   5003   }
   5004 
   5005   int NumberOfTransitions() {
   5006     Object* num = proto_trans_->get(Map::kProtoTransitionNumberOfEntriesOffset);
   5007     return Smi::cast(num)->value();
   5008   }
   5009 
   5010   Map* GetTransition(int transitionNumber) {
   5011     return Map::cast(proto_trans_->get(IndexFor(transitionNumber)));
   5012   }
   5013 
   5014   int IndexFor(int transitionNumber) {
   5015     return Map::kProtoTransitionHeaderSize +
   5016         Map::kProtoTransitionMapOffset +
   5017         transitionNumber * Map::kProtoTransitionElementsPerEntry;
   5018   }
   5019 
   5020   FixedArray* proto_trans_;
   5021 };
   5022 
   5023 
   5024 // To traverse the transition tree iteratively, we have to store two kinds of
   5025 // information in a map: The parent map in the traversal and which children of a
   5026 // node have already been visited. To do this without additional memory, we
   5027 // temporarily reuse two maps with known values:
   5028 //
   5029 //  (1) The map of the map temporarily holds the parent, and is restored to the
   5030 //      meta map afterwards.
   5031 //
   5032 //  (2) The info which children have already been visited depends on which part
   5033 //      of the map we currently iterate:
   5034 //
   5035 //    (a) If we currently follow normal map transitions, we temporarily store
   5036 //        the current index in the map of the FixedArray of the desciptor
   5037 //        array's contents, and restore it to the fixed array map afterwards.
   5038 //        Note that a single descriptor can have 0, 1, or 2 transitions.
   5039 //
   5040 //    (b) If we currently follow prototype transitions, we temporarily store
   5041 //        the current index in the map of the FixedArray holding the prototype
   5042 //        transitions, and restore it to the fixed array map afterwards.
   5043 //
   5044 // Note that the child iterator is just a concatenation of two iterators: One
   5045 // iterating over map transitions and one iterating over prototype transisitons.
   5046 class TraversableMap : public Map {
   5047  public:
   5048   // Record the parent in the traversal within this map. Note that this destroys
   5049   // this map's map!
   5050   void SetParent(TraversableMap* parent) { set_map_no_write_barrier(parent); }
   5051 
   5052   // Reset the current map's map, returning the parent previously stored in it.
   5053   TraversableMap* GetAndResetParent() {
   5054     TraversableMap* old_parent = static_cast<TraversableMap*>(map());
   5055     set_map_no_write_barrier(GetHeap()->meta_map());
   5056     return old_parent;
   5057   }
   5058 
   5059   // Start iterating over this map's children, possibly destroying a FixedArray
   5060   // map (see explanation above).
   5061   void ChildIteratorStart() {
   5062     IntrusiveMapTransitionIterator(instance_descriptors()).Start();
   5063     IntrusivePrototypeTransitionIterator(
   5064         unchecked_prototype_transitions()).Start();
   5065   }
   5066 
   5067   // If we have an unvisited child map, return that one and advance. If we have
   5068   // none, return NULL and reset any destroyed FixedArray maps.
   5069   TraversableMap* ChildIteratorNext() {
   5070     IntrusiveMapTransitionIterator descriptor_iterator(instance_descriptors());
   5071     if (descriptor_iterator.IsIterating()) {
   5072       Map* next = descriptor_iterator.Next();
   5073       if (next != NULL) return static_cast<TraversableMap*>(next);
   5074     }
   5075     IntrusivePrototypeTransitionIterator
   5076         proto_iterator(unchecked_prototype_transitions());
   5077     if (proto_iterator.IsIterating()) {
   5078       Map* next = proto_iterator.Next();
   5079       if (next != NULL) return static_cast<TraversableMap*>(next);
   5080     }
   5081     return NULL;
   5082   }
   5083 };
   5084 
   5085 
   5086 // Traverse the transition tree in postorder without using the C++ stack by
   5087 // doing pointer reversal.
   5088 void Map::TraverseTransitionTree(TraverseCallback callback, void* data) {
   5089   TraversableMap* current = static_cast<TraversableMap*>(this);
   5090   current->ChildIteratorStart();
   5091   while (true) {
   5092     TraversableMap* child = current->ChildIteratorNext();
   5093     if (child != NULL) {
   5094       child->ChildIteratorStart();
   5095       child->SetParent(current);
   5096       current = child;
   5097     } else {
   5098       TraversableMap* parent = current->GetAndResetParent();
   5099       callback(current, data);
   5100       if (current == this) break;
   5101       current = parent;
   5102     }
   5103   }
   5104 }
   5105 
   5106 
   5107 MaybeObject* CodeCache::Update(String* name, Code* code) {
   5108   // The number of monomorphic stubs for normal load/store/call IC's can grow to
   5109   // a large number and therefore they need to go into a hash table. They are
   5110   // used to load global properties from cells.
   5111   if (code->type() == NORMAL) {
   5112     // Make sure that a hash table is allocated for the normal load code cache.
   5113     if (normal_type_cache()->IsUndefined()) {
   5114       Object* result;
   5115       { MaybeObject* maybe_result =
   5116             CodeCacheHashTable::Allocate(CodeCacheHashTable::kInitialSize);
   5117         if (!maybe_result->ToObject(&result)) return maybe_result;
   5118       }
   5119       set_normal_type_cache(result);
   5120     }
   5121     return UpdateNormalTypeCache(name, code);
   5122   } else {
   5123     ASSERT(default_cache()->IsFixedArray());
   5124     return UpdateDefaultCache(name, code);
   5125   }
   5126 }
   5127 
   5128 
   5129 MaybeObject* CodeCache::UpdateDefaultCache(String* name, Code* code) {
   5130   // When updating the default code cache we disregard the type encoded in the
   5131   // flags. This allows call constant stubs to overwrite call field
   5132   // stubs, etc.
   5133   Code::Flags flags = Code::RemoveTypeFromFlags(code->flags());
   5134 
   5135   // First check whether we can update existing code cache without
   5136   // extending it.
   5137   FixedArray* cache = default_cache();
   5138   int length = cache->length();
   5139   int deleted_index = -1;
   5140   for (int i = 0; i < length; i += kCodeCacheEntrySize) {
   5141     Object* key = cache->get(i);
   5142     if (key->IsNull()) {
   5143       if (deleted_index < 0) deleted_index = i;
   5144       continue;
   5145     }
   5146     if (key->IsUndefined()) {
   5147       if (deleted_index >= 0) i = deleted_index;
   5148       cache->set(i + kCodeCacheEntryNameOffset, name);
   5149       cache->set(i + kCodeCacheEntryCodeOffset, code);
   5150       return this;
   5151     }
   5152     if (name->Equals(String::cast(key))) {
   5153       Code::Flags found =
   5154           Code::cast(cache->get(i + kCodeCacheEntryCodeOffset))->flags();
   5155       if (Code::RemoveTypeFromFlags(found) == flags) {
   5156         cache->set(i + kCodeCacheEntryCodeOffset, code);
   5157         return this;
   5158       }
   5159     }
   5160   }
   5161 
   5162   // Reached the end of the code cache.  If there were deleted
   5163   // elements, reuse the space for the first of them.
   5164   if (deleted_index >= 0) {
   5165     cache->set(deleted_index + kCodeCacheEntryNameOffset, name);
   5166     cache->set(deleted_index + kCodeCacheEntryCodeOffset, code);
   5167     return this;
   5168   }
   5169 
   5170   // Extend the code cache with some new entries (at least one). Must be a
   5171   // multiple of the entry size.
   5172   int new_length = length + ((length >> 1)) + kCodeCacheEntrySize;
   5173   new_length = new_length - new_length % kCodeCacheEntrySize;
   5174   ASSERT((new_length % kCodeCacheEntrySize) == 0);
   5175   Object* result;
   5176   { MaybeObject* maybe_result = cache->CopySize(new_length);
   5177     if (!maybe_result->ToObject(&result)) return maybe_result;
   5178   }
   5179 
   5180   // Add the (name, code) pair to the new cache.
   5181   cache = FixedArray::cast(result);
   5182   cache->set(length + kCodeCacheEntryNameOffset, name);
   5183   cache->set(length + kCodeCacheEntryCodeOffset, code);
   5184   set_default_cache(cache);
   5185   return this;
   5186 }
   5187 
   5188 
   5189 MaybeObject* CodeCache::UpdateNormalTypeCache(String* name, Code* code) {
   5190   // Adding a new entry can cause a new cache to be allocated.
   5191   CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
   5192   Object* new_cache;
   5193   { MaybeObject* maybe_new_cache = cache->Put(name, code);
   5194     if (!maybe_new_cache->ToObject(&new_cache)) return maybe_new_cache;
   5195   }
   5196   set_normal_type_cache(new_cache);
   5197   return this;
   5198 }
   5199 
   5200 
   5201 Object* CodeCache::Lookup(String* name, Code::Flags flags) {
   5202   if (Code::ExtractTypeFromFlags(flags) == NORMAL) {
   5203     return LookupNormalTypeCache(name, flags);
   5204   } else {
   5205     return LookupDefaultCache(name, flags);
   5206   }
   5207 }
   5208 
   5209 
   5210 Object* CodeCache::LookupDefaultCache(String* name, Code::Flags flags) {
   5211   FixedArray* cache = default_cache();
   5212   int length = cache->length();
   5213   for (int i = 0; i < length; i += kCodeCacheEntrySize) {
   5214     Object* key = cache->get(i + kCodeCacheEntryNameOffset);
   5215     // Skip deleted elements.
   5216     if (key->IsNull()) continue;
   5217     if (key->IsUndefined()) return key;
   5218     if (name->Equals(String::cast(key))) {
   5219       Code* code = Code::cast(cache->get(i + kCodeCacheEntryCodeOffset));
   5220       if (code->flags() == flags) {
   5221         return code;
   5222       }
   5223     }
   5224   }
   5225   return GetHeap()->undefined_value();
   5226 }
   5227 
   5228 
   5229 Object* CodeCache::LookupNormalTypeCache(String* name, Code::Flags flags) {
   5230   if (!normal_type_cache()->IsUndefined()) {
   5231     CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
   5232     return cache->Lookup(name, flags);
   5233   } else {
   5234     return GetHeap()->undefined_value();
   5235   }
   5236 }
   5237 
   5238 
   5239 int CodeCache::GetIndex(Object* name, Code* code) {
   5240   if (code->type() == NORMAL) {
   5241     if (normal_type_cache()->IsUndefined()) return -1;
   5242     CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
   5243     return cache->GetIndex(String::cast(name), code->flags());
   5244   }
   5245 
   5246   FixedArray* array = default_cache();
   5247   int len = array->length();
   5248   for (int i = 0; i < len; i += kCodeCacheEntrySize) {
   5249     if (array->get(i + kCodeCacheEntryCodeOffset) == code) return i + 1;
   5250   }
   5251   return -1;
   5252 }
   5253 
   5254 
   5255 void CodeCache::RemoveByIndex(Object* name, Code* code, int index) {
   5256   if (code->type() == NORMAL) {
   5257     ASSERT(!normal_type_cache()->IsUndefined());
   5258     CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
   5259     ASSERT(cache->GetIndex(String::cast(name), code->flags()) == index);
   5260     cache->RemoveByIndex(index);
   5261   } else {
   5262     FixedArray* array = default_cache();
   5263     ASSERT(array->length() >= index && array->get(index)->IsCode());
   5264     // Use null instead of undefined for deleted elements to distinguish
   5265     // deleted elements from unused elements.  This distinction is used
   5266     // when looking up in the cache and when updating the cache.
   5267     ASSERT_EQ(1, kCodeCacheEntryCodeOffset - kCodeCacheEntryNameOffset);
   5268     array->set_null(index - 1);  // Name.
   5269     array->set_null(index);  // Code.
   5270   }
   5271 }
   5272 
   5273 
   5274 // The key in the code cache hash table consists of the property name and the
   5275 // code object. The actual match is on the name and the code flags. If a key
   5276 // is created using the flags and not a code object it can only be used for
   5277 // lookup not to create a new entry.
   5278 class CodeCacheHashTableKey : public HashTableKey {
   5279  public:
   5280   CodeCacheHashTableKey(String* name, Code::Flags flags)
   5281       : name_(name), flags_(flags), code_(NULL) { }
   5282 
   5283   CodeCacheHashTableKey(String* name, Code* code)
   5284       : name_(name),
   5285         flags_(code->flags()),
   5286         code_(code) { }
   5287 
   5288 
   5289   bool IsMatch(Object* other) {
   5290     if (!other->IsFixedArray()) return false;
   5291     FixedArray* pair = FixedArray::cast(other);
   5292     String* name = String::cast(pair->get(0));
   5293     Code::Flags flags = Code::cast(pair->get(1))->flags();
   5294     if (flags != flags_) {
   5295       return false;
   5296     }
   5297     return name_->Equals(name);
   5298   }
   5299 
   5300   static uint32_t NameFlagsHashHelper(String* name, Code::Flags flags) {
   5301     return name->Hash() ^ flags;
   5302   }
   5303 
   5304   uint32_t Hash() { return NameFlagsHashHelper(name_, flags_); }
   5305 
   5306   uint32_t HashForObject(Object* obj) {
   5307     FixedArray* pair = FixedArray::cast(obj);
   5308     String* name = String::cast(pair->get(0));
   5309     Code* code = Code::cast(pair->get(1));
   5310     return NameFlagsHashHelper(name, code->flags());
   5311   }
   5312 
   5313   MUST_USE_RESULT MaybeObject* AsObject() {
   5314     ASSERT(code_ != NULL);
   5315     Object* obj;
   5316     { MaybeObject* maybe_obj = code_->GetHeap()->AllocateFixedArray(2);
   5317       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   5318     }
   5319     FixedArray* pair = FixedArray::cast(obj);
   5320     pair->set(0, name_);
   5321     pair->set(1, code_);
   5322     return pair;
   5323   }
   5324 
   5325  private:
   5326   String* name_;
   5327   Code::Flags flags_;
   5328   // TODO(jkummerow): We should be able to get by without this.
   5329   Code* code_;
   5330 };
   5331 
   5332 
   5333 Object* CodeCacheHashTable::Lookup(String* name, Code::Flags flags) {
   5334   CodeCacheHashTableKey key(name, flags);
   5335   int entry = FindEntry(&key);
   5336   if (entry == kNotFound) return GetHeap()->undefined_value();
   5337   return get(EntryToIndex(entry) + 1);
   5338 }
   5339 
   5340 
   5341 MaybeObject* CodeCacheHashTable::Put(String* name, Code* code) {
   5342   CodeCacheHashTableKey key(name, code);
   5343   Object* obj;
   5344   { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
   5345     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   5346   }
   5347 
   5348   // Don't use |this|, as the table might have grown.
   5349   CodeCacheHashTable* cache = reinterpret_cast<CodeCacheHashTable*>(obj);
   5350 
   5351   int entry = cache->FindInsertionEntry(key.Hash());
   5352   Object* k;
   5353   { MaybeObject* maybe_k = key.AsObject();
   5354     if (!maybe_k->ToObject(&k)) return maybe_k;
   5355   }
   5356 
   5357   cache->set(EntryToIndex(entry), k);
   5358   cache->set(EntryToIndex(entry) + 1, code);
   5359   cache->ElementAdded();
   5360   return cache;
   5361 }
   5362 
   5363 
   5364 int CodeCacheHashTable::GetIndex(String* name, Code::Flags flags) {
   5365   CodeCacheHashTableKey key(name, flags);
   5366   int entry = FindEntry(&key);
   5367   return (entry == kNotFound) ? -1 : entry;
   5368 }
   5369 
   5370 
   5371 void CodeCacheHashTable::RemoveByIndex(int index) {
   5372   ASSERT(index >= 0);
   5373   Heap* heap = GetHeap();
   5374   set(EntryToIndex(index), heap->the_hole_value());
   5375   set(EntryToIndex(index) + 1, heap->the_hole_value());
   5376   ElementRemoved();
   5377 }
   5378 
   5379 
   5380 void PolymorphicCodeCache::Update(Handle<PolymorphicCodeCache> cache,
   5381                                   MapHandleList* maps,
   5382                                   Code::Flags flags,
   5383                                   Handle<Code> code) {
   5384   Isolate* isolate = cache->GetIsolate();
   5385   CALL_HEAP_FUNCTION_VOID(isolate, cache->Update(maps, flags, *code));
   5386 }
   5387 
   5388 
   5389 MaybeObject* PolymorphicCodeCache::Update(MapHandleList* maps,
   5390                                           Code::Flags flags,
   5391                                           Code* code) {
   5392   // Initialize cache if necessary.
   5393   if (cache()->IsUndefined()) {
   5394     Object* result;
   5395     { MaybeObject* maybe_result =
   5396           PolymorphicCodeCacheHashTable::Allocate(
   5397               PolymorphicCodeCacheHashTable::kInitialSize);
   5398       if (!maybe_result->ToObject(&result)) return maybe_result;
   5399     }
   5400     set_cache(result);
   5401   } else {
   5402     // This entry shouldn't be contained in the cache yet.
   5403     ASSERT(PolymorphicCodeCacheHashTable::cast(cache())
   5404                ->Lookup(maps, flags)->IsUndefined());
   5405   }
   5406   PolymorphicCodeCacheHashTable* hash_table =
   5407       PolymorphicCodeCacheHashTable::cast(cache());
   5408   Object* new_cache;
   5409   { MaybeObject* maybe_new_cache = hash_table->Put(maps, flags, code);
   5410     if (!maybe_new_cache->ToObject(&new_cache)) return maybe_new_cache;
   5411   }
   5412   set_cache(new_cache);
   5413   return this;
   5414 }
   5415 
   5416 
   5417 Handle<Object> PolymorphicCodeCache::Lookup(MapHandleList* maps,
   5418                                             Code::Flags flags) {
   5419   if (!cache()->IsUndefined()) {
   5420     PolymorphicCodeCacheHashTable* hash_table =
   5421         PolymorphicCodeCacheHashTable::cast(cache());
   5422     return Handle<Object>(hash_table->Lookup(maps, flags));
   5423   } else {
   5424     return GetIsolate()->factory()->undefined_value();
   5425   }
   5426 }
   5427 
   5428 
   5429 // Despite their name, object of this class are not stored in the actual
   5430 // hash table; instead they're temporarily used for lookups. It is therefore
   5431 // safe to have a weak (non-owning) pointer to a MapList as a member field.
   5432 class PolymorphicCodeCacheHashTableKey : public HashTableKey {
   5433  public:
   5434   // Callers must ensure that |maps| outlives the newly constructed object.
   5435   PolymorphicCodeCacheHashTableKey(MapHandleList* maps, int code_flags)
   5436       : maps_(maps),
   5437         code_flags_(code_flags) {}
   5438 
   5439   bool IsMatch(Object* other) {
   5440     MapHandleList other_maps(kDefaultListAllocationSize);
   5441     int other_flags;
   5442     FromObject(other, &other_flags, &other_maps);
   5443     if (code_flags_ != other_flags) return false;
   5444     if (maps_->length() != other_maps.length()) return false;
   5445     // Compare just the hashes first because it's faster.
   5446     int this_hash = MapsHashHelper(maps_, code_flags_);
   5447     int other_hash = MapsHashHelper(&other_maps, other_flags);
   5448     if (this_hash != other_hash) return false;
   5449 
   5450     // Full comparison: for each map in maps_, look for an equivalent map in
   5451     // other_maps. This implementation is slow, but probably good enough for
   5452     // now because the lists are short (<= 4 elements currently).
   5453     for (int i = 0; i < maps_->length(); ++i) {
   5454       bool match_found = false;
   5455       for (int j = 0; j < other_maps.length(); ++j) {
   5456         if (*(maps_->at(i)) == *(other_maps.at(j))) {
   5457           match_found = true;
   5458           break;
   5459         }
   5460       }
   5461       if (!match_found) return false;
   5462     }
   5463     return true;
   5464   }
   5465 
   5466   static uint32_t MapsHashHelper(MapHandleList* maps, int code_flags) {
   5467     uint32_t hash = code_flags;
   5468     for (int i = 0; i < maps->length(); ++i) {
   5469       hash ^= maps->at(i)->Hash();
   5470     }
   5471     return hash;
   5472   }
   5473 
   5474   uint32_t Hash() {
   5475     return MapsHashHelper(maps_, code_flags_);
   5476   }
   5477 
   5478   uint32_t HashForObject(Object* obj) {
   5479     MapHandleList other_maps(kDefaultListAllocationSize);
   5480     int other_flags;
   5481     FromObject(obj, &other_flags, &other_maps);
   5482     return MapsHashHelper(&other_maps, other_flags);
   5483   }
   5484 
   5485   MUST_USE_RESULT MaybeObject* AsObject() {
   5486     Object* obj;
   5487     // The maps in |maps_| must be copied to a newly allocated FixedArray,
   5488     // both because the referenced MapList is short-lived, and because C++
   5489     // objects can't be stored in the heap anyway.
   5490     { MaybeObject* maybe_obj =
   5491         HEAP->AllocateUninitializedFixedArray(maps_->length() + 1);
   5492       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   5493     }
   5494     FixedArray* list = FixedArray::cast(obj);
   5495     list->set(0, Smi::FromInt(code_flags_));
   5496     for (int i = 0; i < maps_->length(); ++i) {
   5497       list->set(i + 1, *maps_->at(i));
   5498     }
   5499     return list;
   5500   }
   5501 
   5502  private:
   5503   static MapHandleList* FromObject(Object* obj,
   5504                                    int* code_flags,
   5505                                    MapHandleList* maps) {
   5506     FixedArray* list = FixedArray::cast(obj);
   5507     maps->Rewind(0);
   5508     *code_flags = Smi::cast(list->get(0))->value();
   5509     for (int i = 1; i < list->length(); ++i) {
   5510       maps->Add(Handle<Map>(Map::cast(list->get(i))));
   5511     }
   5512     return maps;
   5513   }
   5514 
   5515   MapHandleList* maps_;  // weak.
   5516   int code_flags_;
   5517   static const int kDefaultListAllocationSize = kMaxKeyedPolymorphism + 1;
   5518 };
   5519 
   5520 
   5521 Object* PolymorphicCodeCacheHashTable::Lookup(MapHandleList* maps,
   5522                                               int code_flags) {
   5523   PolymorphicCodeCacheHashTableKey key(maps, code_flags);
   5524   int entry = FindEntry(&key);
   5525   if (entry == kNotFound) return GetHeap()->undefined_value();
   5526   return get(EntryToIndex(entry) + 1);
   5527 }
   5528 
   5529 
   5530 MaybeObject* PolymorphicCodeCacheHashTable::Put(MapHandleList* maps,
   5531                                                 int code_flags,
   5532                                                 Code* code) {
   5533   PolymorphicCodeCacheHashTableKey key(maps, code_flags);
   5534   Object* obj;
   5535   { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
   5536     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   5537   }
   5538   PolymorphicCodeCacheHashTable* cache =
   5539       reinterpret_cast<PolymorphicCodeCacheHashTable*>(obj);
   5540   int entry = cache->FindInsertionEntry(key.Hash());
   5541   { MaybeObject* maybe_obj = key.AsObject();
   5542     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   5543   }
   5544   cache->set(EntryToIndex(entry), obj);
   5545   cache->set(EntryToIndex(entry) + 1, code);
   5546   cache->ElementAdded();
   5547   return cache;
   5548 }
   5549 
   5550 
   5551 MaybeObject* FixedArray::AddKeysFromJSArray(JSArray* array) {
   5552   ElementsAccessor* accessor = array->GetElementsAccessor();
   5553   MaybeObject* maybe_result =
   5554       accessor->AddElementsToFixedArray(array, array, this);
   5555   FixedArray* result;
   5556   if (!maybe_result->To<FixedArray>(&result)) return maybe_result;
   5557 #ifdef DEBUG
   5558   if (FLAG_enable_slow_asserts) {
   5559     for (int i = 0; i < result->length(); i++) {
   5560       Object* current = result->get(i);
   5561       ASSERT(current->IsNumber() || current->IsString());
   5562     }
   5563   }
   5564 #endif
   5565   return result;
   5566 }
   5567 
   5568 
   5569 MaybeObject* FixedArray::UnionOfKeys(FixedArray* other) {
   5570   ElementsAccessor* accessor = ElementsAccessor::ForArray(other);
   5571   MaybeObject* maybe_result =
   5572       accessor->AddElementsToFixedArray(NULL, NULL, this, other);
   5573   FixedArray* result;
   5574   if (!maybe_result->To<FixedArray>(&result)) return maybe_result;
   5575 #ifdef DEBUG
   5576   if (FLAG_enable_slow_asserts) {
   5577     for (int i = 0; i < result->length(); i++) {
   5578       Object* current = result->get(i);
   5579       ASSERT(current->IsNumber() || current->IsString());
   5580     }
   5581   }
   5582 #endif
   5583   return result;
   5584 }
   5585 
   5586 
   5587 MaybeObject* FixedArray::CopySize(int new_length) {
   5588   Heap* heap = GetHeap();
   5589   if (new_length == 0) return heap->empty_fixed_array();
   5590   Object* obj;
   5591   { MaybeObject* maybe_obj = heap->AllocateFixedArray(new_length);
   5592     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   5593   }
   5594   FixedArray* result = FixedArray::cast(obj);
   5595   // Copy the content
   5596   AssertNoAllocation no_gc;
   5597   int len = length();
   5598   if (new_length < len) len = new_length;
   5599   // We are taking the map from the old fixed array so the map is sure to
   5600   // be an immortal immutable object.
   5601   result->set_map_no_write_barrier(map());
   5602   WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
   5603   for (int i = 0; i < len; i++) {
   5604     result->set(i, get(i), mode);
   5605   }
   5606   return result;
   5607 }
   5608 
   5609 
   5610 void FixedArray::CopyTo(int pos, FixedArray* dest, int dest_pos, int len) {
   5611   AssertNoAllocation no_gc;
   5612   WriteBarrierMode mode = dest->GetWriteBarrierMode(no_gc);
   5613   for (int index = 0; index < len; index++) {
   5614     dest->set(dest_pos+index, get(pos+index), mode);
   5615   }
   5616 }
   5617 
   5618 
   5619 #ifdef DEBUG
   5620 bool FixedArray::IsEqualTo(FixedArray* other) {
   5621   if (length() != other->length()) return false;
   5622   for (int i = 0 ; i < length(); ++i) {
   5623     if (get(i) != other->get(i)) return false;
   5624   }
   5625   return true;
   5626 }
   5627 #endif
   5628 
   5629 
   5630 MaybeObject* DescriptorArray::Allocate(int number_of_descriptors) {
   5631   Heap* heap = Isolate::Current()->heap();
   5632   if (number_of_descriptors == 0) {
   5633     return heap->empty_descriptor_array();
   5634   }
   5635   // Allocate the array of keys.
   5636   Object* array;
   5637   { MaybeObject* maybe_array =
   5638         heap->AllocateFixedArray(ToKeyIndex(number_of_descriptors));
   5639     if (!maybe_array->ToObject(&array)) return maybe_array;
   5640   }
   5641   // Do not use DescriptorArray::cast on incomplete object.
   5642   FixedArray* result = FixedArray::cast(array);
   5643 
   5644   // Allocate the content array and set it in the descriptor array.
   5645   { MaybeObject* maybe_array =
   5646         heap->AllocateFixedArray(number_of_descriptors << 1);
   5647     if (!maybe_array->ToObject(&array)) return maybe_array;
   5648   }
   5649   result->set(kBitField3StorageIndex, Smi::FromInt(0));
   5650   result->set(kContentArrayIndex, array);
   5651   result->set(kEnumerationIndexIndex,
   5652               Smi::FromInt(PropertyDetails::kInitialIndex));
   5653   return result;
   5654 }
   5655 
   5656 
   5657 void DescriptorArray::SetEnumCache(FixedArray* bridge_storage,
   5658                                    FixedArray* new_cache,
   5659                                    Object* new_index_cache) {
   5660   ASSERT(bridge_storage->length() >= kEnumCacheBridgeLength);
   5661   ASSERT(new_index_cache->IsSmi() || new_index_cache->IsFixedArray());
   5662   if (HasEnumCache()) {
   5663     FixedArray::cast(get(kEnumerationIndexIndex))->
   5664       set(kEnumCacheBridgeCacheIndex, new_cache);
   5665     FixedArray::cast(get(kEnumerationIndexIndex))->
   5666       set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache);
   5667   } else {
   5668     if (IsEmpty()) return;  // Do nothing for empty descriptor array.
   5669     FixedArray::cast(bridge_storage)->
   5670       set(kEnumCacheBridgeCacheIndex, new_cache);
   5671     FixedArray::cast(bridge_storage)->
   5672       set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache);
   5673     NoWriteBarrierSet(FixedArray::cast(bridge_storage),
   5674                       kEnumCacheBridgeEnumIndex,
   5675                       get(kEnumerationIndexIndex));
   5676     set(kEnumerationIndexIndex, bridge_storage);
   5677   }
   5678 }
   5679 
   5680 
   5681 static bool InsertionPointFound(String* key1, String* key2) {
   5682   return key1->Hash() > key2->Hash() || key1 == key2;
   5683 }
   5684 
   5685 
   5686 void DescriptorArray::CopyFrom(Handle<DescriptorArray> dst,
   5687                                int dst_index,
   5688                                Handle<DescriptorArray> src,
   5689                                int src_index,
   5690                                const WhitenessWitness& witness) {
   5691   CALL_HEAP_FUNCTION_VOID(dst->GetIsolate(),
   5692                           dst->CopyFrom(dst_index, *src, src_index, witness));
   5693 }
   5694 
   5695 
   5696 MaybeObject* DescriptorArray::CopyFrom(int dst_index,
   5697                                        DescriptorArray* src,
   5698                                        int src_index,
   5699                                        const WhitenessWitness& witness) {
   5700   Object* value = src->GetValue(src_index);
   5701   PropertyDetails details(src->GetDetails(src_index));
   5702   if (details.type() == CALLBACKS && value->IsAccessorPair()) {
   5703     MaybeObject* maybe_copy =
   5704         AccessorPair::cast(value)->CopyWithoutTransitions();
   5705     if (!maybe_copy->To(&value)) return maybe_copy;
   5706   }
   5707   Descriptor desc(src->GetKey(src_index), value, details);
   5708   Set(dst_index, &desc, witness);
   5709   return this;
   5710 }
   5711 
   5712 
   5713 MaybeObject* DescriptorArray::CopyInsert(Descriptor* descriptor,
   5714                                          TransitionFlag transition_flag) {
   5715   // Transitions are only kept when inserting another transition.
   5716   // This precondition is not required by this function's implementation, but
   5717   // is currently required by the semantics of maps, so we check it.
   5718   // Conversely, we filter after replacing, so replacing a transition and
   5719   // removing all other transitions is not supported.
   5720   bool remove_transitions = transition_flag == REMOVE_TRANSITIONS;
   5721   ASSERT(remove_transitions == !descriptor->ContainsTransition());
   5722   ASSERT(descriptor->GetDetails().type() != NULL_DESCRIPTOR);
   5723 
   5724   // Ensure the key is a symbol.
   5725   { MaybeObject* maybe_result = descriptor->KeyToSymbol();
   5726     if (maybe_result->IsFailure()) return maybe_result;
   5727   }
   5728 
   5729   int new_size = 0;
   5730   for (int i = 0; i < number_of_descriptors(); i++) {
   5731     if (IsNullDescriptor(i)) continue;
   5732     if (remove_transitions && IsTransitionOnly(i)) continue;
   5733     new_size++;
   5734   }
   5735 
   5736   // If key is in descriptor, we replace it in-place when filtering.
   5737   // Count a null descriptor for key as inserted, not replaced.
   5738   int index = Search(descriptor->GetKey());
   5739   const bool replacing = (index != kNotFound);
   5740   bool keep_enumeration_index = false;
   5741   if (replacing) {
   5742     // We are replacing an existing descriptor.  We keep the enumeration
   5743     // index of a visible property.
   5744     PropertyType t = PropertyDetails(GetDetails(index)).type();
   5745     if (t == CONSTANT_FUNCTION ||
   5746         t == FIELD ||
   5747         t == CALLBACKS ||
   5748         t == INTERCEPTOR) {
   5749       keep_enumeration_index = true;
   5750     } else if (remove_transitions) {
   5751      // Replaced descriptor has been counted as removed if it is
   5752      // a transition that will be replaced.  Adjust count in this case.
   5753       ++new_size;
   5754     }
   5755   } else {
   5756     ++new_size;
   5757   }
   5758 
   5759   DescriptorArray* new_descriptors;
   5760   { MaybeObject* maybe_result = Allocate(new_size);
   5761     if (!maybe_result->To(&new_descriptors)) return maybe_result;
   5762   }
   5763 
   5764   DescriptorArray::WhitenessWitness witness(new_descriptors);
   5765 
   5766   // Set the enumeration index in the descriptors and set the enumeration index
   5767   // in the result.
   5768   int enumeration_index = NextEnumerationIndex();
   5769   if (!descriptor->ContainsTransition()) {
   5770     if (keep_enumeration_index) {
   5771       descriptor->SetEnumerationIndex(
   5772           PropertyDetails(GetDetails(index)).index());
   5773     } else {
   5774       descriptor->SetEnumerationIndex(enumeration_index);
   5775       ++enumeration_index;
   5776     }
   5777   }
   5778   new_descriptors->SetNextEnumerationIndex(enumeration_index);
   5779 
   5780   // Copy the descriptors, filtering out transitions and null descriptors,
   5781   // and inserting or replacing a descriptor.
   5782   int to_index = 0;
   5783   int insertion_index = -1;
   5784   int from_index = 0;
   5785   while (from_index < number_of_descriptors()) {
   5786     if (insertion_index < 0 &&
   5787         InsertionPointFound(GetKey(from_index), descriptor->GetKey())) {
   5788       insertion_index = to_index++;
   5789       if (replacing) from_index++;
   5790     } else {
   5791       if (!(IsNullDescriptor(from_index) ||
   5792             (remove_transitions && IsTransitionOnly(from_index)))) {
   5793         MaybeObject* copy_result =
   5794             new_descriptors->CopyFrom(to_index++, this, from_index, witness);
   5795         if (copy_result->IsFailure()) return copy_result;
   5796       }
   5797       from_index++;
   5798     }
   5799   }
   5800   if (insertion_index < 0) insertion_index = to_index++;
   5801   new_descriptors->Set(insertion_index, descriptor, witness);
   5802 
   5803   ASSERT(to_index == new_descriptors->number_of_descriptors());
   5804   SLOW_ASSERT(new_descriptors->IsSortedNoDuplicates());
   5805 
   5806   return new_descriptors;
   5807 }
   5808 
   5809 
   5810 MaybeObject* DescriptorArray::RemoveTransitions() {
   5811   // Allocate the new descriptor array.
   5812   int new_number_of_descriptors = 0;
   5813   for (int i = 0; i < number_of_descriptors(); i++) {
   5814     if (IsProperty(i)) new_number_of_descriptors++;
   5815   }
   5816   DescriptorArray* new_descriptors;
   5817   { MaybeObject* maybe_result = Allocate(new_number_of_descriptors);
   5818     if (!maybe_result->To(&new_descriptors)) return maybe_result;
   5819   }
   5820 
   5821   // Copy the content.
   5822   DescriptorArray::WhitenessWitness witness(new_descriptors);
   5823   int next_descriptor = 0;
   5824   for (int i = 0; i < number_of_descriptors(); i++) {
   5825     if (IsProperty(i)) {
   5826       MaybeObject* copy_result =
   5827           new_descriptors->CopyFrom(next_descriptor++, this, i, witness);
   5828       if (copy_result->IsFailure()) return copy_result;
   5829     }
   5830   }
   5831   ASSERT(next_descriptor == new_descriptors->number_of_descriptors());
   5832 
   5833   return new_descriptors;
   5834 }
   5835 
   5836 
   5837 void DescriptorArray::SortUnchecked(const WhitenessWitness& witness) {
   5838   // In-place heap sort.
   5839   int len = number_of_descriptors();
   5840 
   5841   // Bottom-up max-heap construction.
   5842   // Index of the last node with children
   5843   const int max_parent_index = (len / 2) - 1;
   5844   for (int i = max_parent_index; i >= 0; --i) {
   5845     int parent_index = i;
   5846     const uint32_t parent_hash = GetKey(i)->Hash();
   5847     while (parent_index <= max_parent_index) {
   5848       int child_index = 2 * parent_index + 1;
   5849       uint32_t child_hash = GetKey(child_index)->Hash();
   5850       if (child_index + 1 < len) {
   5851         uint32_t right_child_hash = GetKey(child_index + 1)->Hash();
   5852         if (right_child_hash > child_hash) {
   5853           child_index++;
   5854           child_hash = right_child_hash;
   5855         }
   5856       }
   5857       if (child_hash <= parent_hash) break;
   5858       NoIncrementalWriteBarrierSwapDescriptors(parent_index, child_index);
   5859       // Now element at child_index could be < its children.
   5860       parent_index = child_index;  // parent_hash remains correct.
   5861     }
   5862   }
   5863 
   5864   // Extract elements and create sorted array.
   5865   for (int i = len - 1; i > 0; --i) {
   5866     // Put max element at the back of the array.
   5867     NoIncrementalWriteBarrierSwapDescriptors(0, i);
   5868     // Shift down the new top element.
   5869     int parent_index = 0;
   5870     const uint32_t parent_hash = GetKey(parent_index)->Hash();
   5871     const int max_parent_index = (i / 2) - 1;
   5872     while (parent_index <= max_parent_index) {
   5873       int child_index = parent_index * 2 + 1;
   5874       uint32_t child_hash = GetKey(child_index)->Hash();
   5875       if (child_index + 1 < i) {
   5876         uint32_t right_child_hash = GetKey(child_index + 1)->Hash();
   5877         if (right_child_hash > child_hash) {
   5878           child_index++;
   5879           child_hash = right_child_hash;
   5880         }
   5881       }
   5882       if (child_hash <= parent_hash) break;
   5883       NoIncrementalWriteBarrierSwapDescriptors(parent_index, child_index);
   5884       parent_index = child_index;
   5885     }
   5886   }
   5887 }
   5888 
   5889 
   5890 void DescriptorArray::Sort(const WhitenessWitness& witness) {
   5891   SortUnchecked(witness);
   5892   SLOW_ASSERT(IsSortedNoDuplicates());
   5893 }
   5894 
   5895 
   5896 int DescriptorArray::BinarySearch(String* name, int low, int high) {
   5897   uint32_t hash = name->Hash();
   5898 
   5899   while (low <= high) {
   5900     int mid = (low + high) / 2;
   5901     String* mid_name = GetKey(mid);
   5902     uint32_t mid_hash = mid_name->Hash();
   5903 
   5904     if (mid_hash > hash) {
   5905       high = mid - 1;
   5906       continue;
   5907     }
   5908     if (mid_hash < hash) {
   5909       low = mid + 1;
   5910       continue;
   5911     }
   5912     // Found an element with the same hash-code.
   5913     ASSERT(hash == mid_hash);
   5914     // There might be more, so we find the first one and
   5915     // check them all to see if we have a match.
   5916     if (name == mid_name  && !is_null_descriptor(mid)) return mid;
   5917     while ((mid > low) && (GetKey(mid - 1)->Hash() == hash)) mid--;
   5918     for (; (mid <= high) && (GetKey(mid)->Hash() == hash); mid++) {
   5919       if (GetKey(mid)->Equals(name) && !is_null_descriptor(mid)) return mid;
   5920     }
   5921     break;
   5922   }
   5923   return kNotFound;
   5924 }
   5925 
   5926 
   5927 int DescriptorArray::LinearSearch(String* name, int len) {
   5928   uint32_t hash = name->Hash();
   5929   for (int number = 0; number < len; number++) {
   5930     String* entry = GetKey(number);
   5931     if ((entry->Hash() == hash) &&
   5932         name->Equals(entry) &&
   5933         !is_null_descriptor(number)) {
   5934       return number;
   5935     }
   5936   }
   5937   return kNotFound;
   5938 }
   5939 
   5940 
   5941 MaybeObject* AccessorPair::CopyWithoutTransitions() {
   5942   Heap* heap = GetHeap();
   5943   AccessorPair* copy;
   5944   { MaybeObject* maybe_copy = heap->AllocateAccessorPair();
   5945     if (!maybe_copy->To(&copy)) return maybe_copy;
   5946   }
   5947   copy->set_getter(getter()->IsMap() ? heap->the_hole_value() : getter());
   5948   copy->set_setter(setter()->IsMap() ? heap->the_hole_value() : setter());
   5949   return copy;
   5950 }
   5951 
   5952 
   5953 Object* AccessorPair::GetComponent(AccessorComponent component) {
   5954     Object* accessor = (component == ACCESSOR_GETTER) ? getter() : setter();
   5955     return accessor->IsTheHole() ? GetHeap()->undefined_value() : accessor;
   5956 }
   5957 
   5958 
   5959 MaybeObject* DeoptimizationInputData::Allocate(int deopt_entry_count,
   5960                                                PretenureFlag pretenure) {
   5961   ASSERT(deopt_entry_count > 0);
   5962   return HEAP->AllocateFixedArray(LengthFor(deopt_entry_count),
   5963                                   pretenure);
   5964 }
   5965 
   5966 
   5967 MaybeObject* DeoptimizationOutputData::Allocate(int number_of_deopt_points,
   5968                                                 PretenureFlag pretenure) {
   5969   if (number_of_deopt_points == 0) return HEAP->empty_fixed_array();
   5970   return HEAP->AllocateFixedArray(LengthOfFixedArray(number_of_deopt_points),
   5971                                   pretenure);
   5972 }
   5973 
   5974 
   5975 #ifdef DEBUG
   5976 bool DescriptorArray::IsEqualTo(DescriptorArray* other) {
   5977   if (IsEmpty()) return other->IsEmpty();
   5978   if (other->IsEmpty()) return false;
   5979   if (length() != other->length()) return false;
   5980   for (int i = 0; i < length(); ++i) {
   5981     if (get(i) != other->get(i) && i != kContentArrayIndex) return false;
   5982   }
   5983   return GetContentArray()->IsEqualTo(other->GetContentArray());
   5984 }
   5985 #endif
   5986 
   5987 
   5988 bool String::LooksValid() {
   5989   if (!Isolate::Current()->heap()->Contains(this)) return false;
   5990   return true;
   5991 }
   5992 
   5993 
   5994 String::FlatContent String::GetFlatContent() {
   5995   int length = this->length();
   5996   StringShape shape(this);
   5997   String* string = this;
   5998   int offset = 0;
   5999   if (shape.representation_tag() == kConsStringTag) {
   6000     ConsString* cons = ConsString::cast(string);
   6001     if (cons->second()->length() != 0) {
   6002       return FlatContent();
   6003     }
   6004     string = cons->first();
   6005     shape = StringShape(string);
   6006   }
   6007   if (shape.representation_tag() == kSlicedStringTag) {
   6008     SlicedString* slice = SlicedString::cast(string);
   6009     offset = slice->offset();
   6010     string = slice->parent();
   6011     shape = StringShape(string);
   6012     ASSERT(shape.representation_tag() != kConsStringTag &&
   6013            shape.representation_tag() != kSlicedStringTag);
   6014   }
   6015   if (shape.encoding_tag() == kAsciiStringTag) {
   6016     const char* start;
   6017     if (shape.representation_tag() == kSeqStringTag) {
   6018       start = SeqAsciiString::cast(string)->GetChars();
   6019     } else {
   6020       start = ExternalAsciiString::cast(string)->GetChars();
   6021     }
   6022     return FlatContent(Vector<const char>(start + offset, length));
   6023   } else {
   6024     ASSERT(shape.encoding_tag() == kTwoByteStringTag);
   6025     const uc16* start;
   6026     if (shape.representation_tag() == kSeqStringTag) {
   6027       start = SeqTwoByteString::cast(string)->GetChars();
   6028     } else {
   6029       start = ExternalTwoByteString::cast(string)->GetChars();
   6030     }
   6031     return FlatContent(Vector<const uc16>(start + offset, length));
   6032   }
   6033 }
   6034 
   6035 
   6036 SmartArrayPointer<char> String::ToCString(AllowNullsFlag allow_nulls,
   6037                                           RobustnessFlag robust_flag,
   6038                                           int offset,
   6039                                           int length,
   6040                                           int* length_return) {
   6041   if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) {
   6042     return SmartArrayPointer<char>(NULL);
   6043   }
   6044   Heap* heap = GetHeap();
   6045 
   6046   // Negative length means the to the end of the string.
   6047   if (length < 0) length = kMaxInt - offset;
   6048 
   6049   // Compute the size of the UTF-8 string. Start at the specified offset.
   6050   Access<StringInputBuffer> buffer(
   6051       heap->isolate()->objects_string_input_buffer());
   6052   buffer->Reset(offset, this);
   6053   int character_position = offset;
   6054   int utf8_bytes = 0;
   6055   int last = unibrow::Utf16::kNoPreviousCharacter;
   6056   while (buffer->has_more() && character_position++ < offset + length) {
   6057     uint16_t character = buffer->GetNext();
   6058     utf8_bytes += unibrow::Utf8::Length(character, last);
   6059     last = character;
   6060   }
   6061 
   6062   if (length_return) {
   6063     *length_return = utf8_bytes;
   6064   }
   6065 
   6066   char* result = NewArray<char>(utf8_bytes + 1);
   6067 
   6068   // Convert the UTF-16 string to a UTF-8 buffer. Start at the specified offset.
   6069   buffer->Rewind();
   6070   buffer->Seek(offset);
   6071   character_position = offset;
   6072   int utf8_byte_position = 0;
   6073   last = unibrow::Utf16::kNoPreviousCharacter;
   6074   while (buffer->has_more() && character_position++ < offset + length) {
   6075     uint16_t character = buffer->GetNext();
   6076     if (allow_nulls == DISALLOW_NULLS && character == 0) {
   6077       character = ' ';
   6078     }
   6079     utf8_byte_position +=
   6080         unibrow::Utf8::Encode(result + utf8_byte_position, character, last);
   6081     last = character;
   6082   }
   6083   result[utf8_byte_position] = 0;
   6084   return SmartArrayPointer<char>(result);
   6085 }
   6086 
   6087 
   6088 SmartArrayPointer<char> String::ToCString(AllowNullsFlag allow_nulls,
   6089                                           RobustnessFlag robust_flag,
   6090                                           int* length_return) {
   6091   return ToCString(allow_nulls, robust_flag, 0, -1, length_return);
   6092 }
   6093 
   6094 
   6095 const uc16* String::GetTwoByteData() {
   6096   return GetTwoByteData(0);
   6097 }
   6098 
   6099 
   6100 const uc16* String::GetTwoByteData(unsigned start) {
   6101   ASSERT(!IsAsciiRepresentationUnderneath());
   6102   switch (StringShape(this).representation_tag()) {
   6103     case kSeqStringTag:
   6104       return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start);
   6105     case kExternalStringTag:
   6106       return ExternalTwoByteString::cast(this)->
   6107         ExternalTwoByteStringGetData(start);
   6108     case kSlicedStringTag: {
   6109       SlicedString* slice = SlicedString::cast(this);
   6110       return slice->parent()->GetTwoByteData(start + slice->offset());
   6111     }
   6112     case kConsStringTag:
   6113       UNREACHABLE();
   6114       return NULL;
   6115   }
   6116   UNREACHABLE();
   6117   return NULL;
   6118 }
   6119 
   6120 
   6121 SmartArrayPointer<uc16> String::ToWideCString(RobustnessFlag robust_flag) {
   6122   if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) {
   6123     return SmartArrayPointer<uc16>();
   6124   }
   6125   Heap* heap = GetHeap();
   6126 
   6127   Access<StringInputBuffer> buffer(
   6128       heap->isolate()->objects_string_input_buffer());
   6129   buffer->Reset(this);
   6130 
   6131   uc16* result = NewArray<uc16>(length() + 1);
   6132 
   6133   int i = 0;
   6134   while (buffer->has_more()) {
   6135     uint16_t character = buffer->GetNext();
   6136     result[i++] = character;
   6137   }
   6138   result[i] = 0;
   6139   return SmartArrayPointer<uc16>(result);
   6140 }
   6141 
   6142 
   6143 const uc16* SeqTwoByteString::SeqTwoByteStringGetData(unsigned start) {
   6144   return reinterpret_cast<uc16*>(
   6145       reinterpret_cast<char*>(this) - kHeapObjectTag + kHeaderSize) + start;
   6146 }
   6147 
   6148 
   6149 void SeqTwoByteString::SeqTwoByteStringReadBlockIntoBuffer(ReadBlockBuffer* rbb,
   6150                                                            unsigned* offset_ptr,
   6151                                                            unsigned max_chars) {
   6152   unsigned chars_read = 0;
   6153   unsigned offset = *offset_ptr;
   6154   while (chars_read < max_chars) {
   6155     uint16_t c = *reinterpret_cast<uint16_t*>(
   6156         reinterpret_cast<char*>(this) -
   6157             kHeapObjectTag + kHeaderSize + offset * kShortSize);
   6158     if (c <= kMaxAsciiCharCode) {
   6159       // Fast case for ASCII characters.   Cursor is an input output argument.
   6160       if (!unibrow::CharacterStream::EncodeAsciiCharacter(c,
   6161                                                           rbb->util_buffer,
   6162                                                           rbb->capacity,
   6163                                                           rbb->cursor)) {
   6164         break;
   6165       }
   6166     } else {
   6167       if (!unibrow::CharacterStream::EncodeNonAsciiCharacter(c,
   6168                                                              rbb->util_buffer,
   6169                                                              rbb->capacity,
   6170                                                              rbb->cursor)) {
   6171         break;
   6172       }
   6173     }
   6174     offset++;
   6175     chars_read++;
   6176   }
   6177   *offset_ptr = offset;
   6178   rbb->remaining += chars_read;
   6179 }
   6180 
   6181 
   6182 const unibrow::byte* SeqAsciiString::SeqAsciiStringReadBlock(
   6183     unsigned* remaining,
   6184     unsigned* offset_ptr,
   6185     unsigned max_chars) {
   6186   const unibrow::byte* b = reinterpret_cast<unibrow::byte*>(this) -
   6187       kHeapObjectTag + kHeaderSize + *offset_ptr * kCharSize;
   6188   *remaining = max_chars;
   6189   *offset_ptr += max_chars;
   6190   return b;
   6191 }
   6192 
   6193 
   6194 // This will iterate unless the block of string data spans two 'halves' of
   6195 // a ConsString, in which case it will recurse.  Since the block of string
   6196 // data to be read has a maximum size this limits the maximum recursion
   6197 // depth to something sane.  Since C++ does not have tail call recursion
   6198 // elimination, the iteration must be explicit. Since this is not an
   6199 // -IntoBuffer method it can delegate to one of the efficient
   6200 // *AsciiStringReadBlock routines.
   6201 const unibrow::byte* ConsString::ConsStringReadBlock(ReadBlockBuffer* rbb,
   6202                                                      unsigned* offset_ptr,
   6203                                                      unsigned max_chars) {
   6204   ConsString* current = this;
   6205   unsigned offset = *offset_ptr;
   6206   int offset_correction = 0;
   6207 
   6208   while (true) {
   6209     String* left = current->first();
   6210     unsigned left_length = (unsigned)left->length();
   6211     if (left_length > offset &&
   6212         (max_chars <= left_length - offset ||
   6213          (rbb->capacity <= left_length - offset &&
   6214           (max_chars = left_length - offset, true)))) {  // comma operator!
   6215       // Left hand side only - iterate unless we have reached the bottom of
   6216       // the cons tree.  The assignment on the left of the comma operator is
   6217       // in order to make use of the fact that the -IntoBuffer routines can
   6218       // produce at most 'capacity' characters.  This enables us to postpone
   6219       // the point where we switch to the -IntoBuffer routines (below) in order
   6220       // to maximize the chances of delegating a big chunk of work to the
   6221       // efficient *AsciiStringReadBlock routines.
   6222       if (StringShape(left).IsCons()) {
   6223         current = ConsString::cast(left);
   6224         continue;
   6225       } else {
   6226         const unibrow::byte* answer =
   6227             String::ReadBlock(left, rbb, &offset, max_chars);
   6228         *offset_ptr = offset + offset_correction;
   6229         return answer;
   6230       }
   6231     } else if (left_length <= offset) {
   6232       // Right hand side only - iterate unless we have reached the bottom of
   6233       // the cons tree.
   6234       String* right = current->second();
   6235       offset -= left_length;
   6236       offset_correction += left_length;
   6237       if (StringShape(right).IsCons()) {
   6238         current = ConsString::cast(right);
   6239         continue;
   6240       } else {
   6241         const unibrow::byte* answer =
   6242             String::ReadBlock(right, rbb, &offset, max_chars);
   6243         *offset_ptr = offset + offset_correction;
   6244         return answer;
   6245       }
   6246     } else {
   6247       // The block to be read spans two sides of the ConsString, so we call the
   6248       // -IntoBuffer version, which will recurse.  The -IntoBuffer methods
   6249       // are able to assemble data from several part strings because they use
   6250       // the util_buffer to store their data and never return direct pointers
   6251       // to their storage.  We don't try to read more than the buffer capacity
   6252       // here or we can get too much recursion.
   6253       ASSERT(rbb->remaining == 0);
   6254       ASSERT(rbb->cursor == 0);
   6255       current->ConsStringReadBlockIntoBuffer(
   6256           rbb,
   6257           &offset,
   6258           max_chars > rbb->capacity ? rbb->capacity : max_chars);
   6259       *offset_ptr = offset + offset_correction;
   6260       return rbb->util_buffer;
   6261     }
   6262   }
   6263 }
   6264 
   6265 
   6266 const unibrow::byte* ExternalAsciiString::ExternalAsciiStringReadBlock(
   6267       unsigned* remaining,
   6268       unsigned* offset_ptr,
   6269       unsigned max_chars) {
   6270   // Cast const char* to unibrow::byte* (signedness difference).
   6271   const unibrow::byte* b =
   6272       reinterpret_cast<const unibrow::byte*>(GetChars()) + *offset_ptr;
   6273   *remaining = max_chars;
   6274   *offset_ptr += max_chars;
   6275   return b;
   6276 }
   6277 
   6278 
   6279 void ExternalTwoByteString::ExternalTwoByteStringReadBlockIntoBuffer(
   6280       ReadBlockBuffer* rbb,
   6281       unsigned* offset_ptr,
   6282       unsigned max_chars) {
   6283   unsigned chars_read = 0;
   6284   unsigned offset = *offset_ptr;
   6285   const uint16_t* data = GetChars();
   6286   while (chars_read < max_chars) {
   6287     uint16_t c = data[offset];
   6288     if (c <= kMaxAsciiCharCode) {
   6289       // Fast case for ASCII characters. Cursor is an input output argument.
   6290       if (!unibrow::CharacterStream::EncodeAsciiCharacter(c,
   6291                                                           rbb->util_buffer,
   6292                                                           rbb->capacity,
   6293                                                           rbb->cursor))
   6294         break;
   6295     } else {
   6296       if (!unibrow::CharacterStream::EncodeNonAsciiCharacter(c,
   6297                                                              rbb->util_buffer,
   6298                                                              rbb->capacity,
   6299                                                              rbb->cursor))
   6300         break;
   6301     }
   6302     offset++;
   6303     chars_read++;
   6304   }
   6305   *offset_ptr = offset;
   6306   rbb->remaining += chars_read;
   6307 }
   6308 
   6309 
   6310 void SeqAsciiString::SeqAsciiStringReadBlockIntoBuffer(ReadBlockBuffer* rbb,
   6311                                                  unsigned* offset_ptr,
   6312                                                  unsigned max_chars) {
   6313   unsigned capacity = rbb->capacity - rbb->cursor;
   6314   if (max_chars > capacity) max_chars = capacity;
   6315   memcpy(rbb->util_buffer + rbb->cursor,
   6316          reinterpret_cast<char*>(this) - kHeapObjectTag + kHeaderSize +
   6317              *offset_ptr * kCharSize,
   6318          max_chars);
   6319   rbb->remaining += max_chars;
   6320   *offset_ptr += max_chars;
   6321   rbb->cursor += max_chars;
   6322 }
   6323 
   6324 
   6325 void ExternalAsciiString::ExternalAsciiStringReadBlockIntoBuffer(
   6326       ReadBlockBuffer* rbb,
   6327       unsigned* offset_ptr,
   6328       unsigned max_chars) {
   6329   unsigned capacity = rbb->capacity - rbb->cursor;
   6330   if (max_chars > capacity) max_chars = capacity;
   6331   memcpy(rbb->util_buffer + rbb->cursor, GetChars() + *offset_ptr, max_chars);
   6332   rbb->remaining += max_chars;
   6333   *offset_ptr += max_chars;
   6334   rbb->cursor += max_chars;
   6335 }
   6336 
   6337 
   6338 // This method determines the type of string involved and then copies
   6339 // a whole chunk of characters into a buffer, or returns a pointer to a buffer
   6340 // where they can be found.  The pointer is not necessarily valid across a GC
   6341 // (see AsciiStringReadBlock).
   6342 const unibrow::byte* String::ReadBlock(String* input,
   6343                                        ReadBlockBuffer* rbb,
   6344                                        unsigned* offset_ptr,
   6345                                        unsigned max_chars) {
   6346   ASSERT(*offset_ptr <= static_cast<unsigned>(input->length()));
   6347   if (max_chars == 0) {
   6348     rbb->remaining = 0;
   6349     return NULL;
   6350   }
   6351   switch (StringShape(input).representation_tag()) {
   6352     case kSeqStringTag:
   6353       if (input->IsAsciiRepresentation()) {
   6354         SeqAsciiString* str = SeqAsciiString::cast(input);
   6355         return str->SeqAsciiStringReadBlock(&rbb->remaining,
   6356                                             offset_ptr,
   6357                                             max_chars);
   6358       } else {
   6359         SeqTwoByteString* str = SeqTwoByteString::cast(input);
   6360         str->SeqTwoByteStringReadBlockIntoBuffer(rbb,
   6361                                                  offset_ptr,
   6362                                                  max_chars);
   6363         return rbb->util_buffer;
   6364       }
   6365     case kConsStringTag:
   6366       return ConsString::cast(input)->ConsStringReadBlock(rbb,
   6367                                                           offset_ptr,
   6368                                                           max_chars);
   6369     case kExternalStringTag:
   6370       if (input->IsAsciiRepresentation()) {
   6371         return ExternalAsciiString::cast(input)->ExternalAsciiStringReadBlock(
   6372             &rbb->remaining,
   6373             offset_ptr,
   6374             max_chars);
   6375       } else {
   6376         ExternalTwoByteString::cast(input)->
   6377             ExternalTwoByteStringReadBlockIntoBuffer(rbb,
   6378                                                      offset_ptr,
   6379                                                      max_chars);
   6380         return rbb->util_buffer;
   6381       }
   6382     case kSlicedStringTag:
   6383       return SlicedString::cast(input)->SlicedStringReadBlock(rbb,
   6384                                                               offset_ptr,
   6385                                                               max_chars);
   6386     default:
   6387       break;
   6388   }
   6389 
   6390   UNREACHABLE();
   6391   return 0;
   6392 }
   6393 
   6394 
   6395 void Relocatable::PostGarbageCollectionProcessing() {
   6396   Isolate* isolate = Isolate::Current();
   6397   Relocatable* current = isolate->relocatable_top();
   6398   while (current != NULL) {
   6399     current->PostGarbageCollection();
   6400     current = current->prev_;
   6401   }
   6402 }
   6403 
   6404 
   6405 // Reserve space for statics needing saving and restoring.
   6406 int Relocatable::ArchiveSpacePerThread() {
   6407   return sizeof(Isolate::Current()->relocatable_top());
   6408 }
   6409 
   6410 
   6411 // Archive statics that are thread local.
   6412 char* Relocatable::ArchiveState(Isolate* isolate, char* to) {
   6413   *reinterpret_cast<Relocatable**>(to) = isolate->relocatable_top();
   6414   isolate->set_relocatable_top(NULL);
   6415   return to + ArchiveSpacePerThread();
   6416 }
   6417 
   6418 
   6419 // Restore statics that are thread local.
   6420 char* Relocatable::RestoreState(Isolate* isolate, char* from) {
   6421   isolate->set_relocatable_top(*reinterpret_cast<Relocatable**>(from));
   6422   return from + ArchiveSpacePerThread();
   6423 }
   6424 
   6425 
   6426 char* Relocatable::Iterate(ObjectVisitor* v, char* thread_storage) {
   6427   Relocatable* top = *reinterpret_cast<Relocatable**>(thread_storage);
   6428   Iterate(v, top);
   6429   return thread_storage + ArchiveSpacePerThread();
   6430 }
   6431 
   6432 
   6433 void Relocatable::Iterate(ObjectVisitor* v) {
   6434   Isolate* isolate = Isolate::Current();
   6435   Iterate(v, isolate->relocatable_top());
   6436 }
   6437 
   6438 
   6439 void Relocatable::Iterate(ObjectVisitor* v, Relocatable* top) {
   6440   Relocatable* current = top;
   6441   while (current != NULL) {
   6442     current->IterateInstance(v);
   6443     current = current->prev_;
   6444   }
   6445 }
   6446 
   6447 
   6448 FlatStringReader::FlatStringReader(Isolate* isolate, Handle<String> str)
   6449     : Relocatable(isolate),
   6450       str_(str.location()),
   6451       length_(str->length()) {
   6452   PostGarbageCollection();
   6453 }
   6454 
   6455 
   6456 FlatStringReader::FlatStringReader(Isolate* isolate, Vector<const char> input)
   6457     : Relocatable(isolate),
   6458       str_(0),
   6459       is_ascii_(true),
   6460       length_(input.length()),
   6461       start_(input.start()) { }
   6462 
   6463 
   6464 void FlatStringReader::PostGarbageCollection() {
   6465   if (str_ == NULL) return;
   6466   Handle<String> str(str_);
   6467   ASSERT(str->IsFlat());
   6468   String::FlatContent content = str->GetFlatContent();
   6469   ASSERT(content.IsFlat());
   6470   is_ascii_ = content.IsAscii();
   6471   if (is_ascii_) {
   6472     start_ = content.ToAsciiVector().start();
   6473   } else {
   6474     start_ = content.ToUC16Vector().start();
   6475   }
   6476 }
   6477 
   6478 
   6479 void StringInputBuffer::Seek(unsigned pos) {
   6480   Reset(pos, input_);
   6481 }
   6482 
   6483 
   6484 void SafeStringInputBuffer::Seek(unsigned pos) {
   6485   Reset(pos, input_);
   6486 }
   6487 
   6488 
   6489 // This method determines the type of string involved and then copies
   6490 // a whole chunk of characters into a buffer.  It can be used with strings
   6491 // that have been glued together to form a ConsString and which must cooperate
   6492 // to fill up a buffer.
   6493 void String::ReadBlockIntoBuffer(String* input,
   6494                                  ReadBlockBuffer* rbb,
   6495                                  unsigned* offset_ptr,
   6496                                  unsigned max_chars) {
   6497   ASSERT(*offset_ptr <= (unsigned)input->length());
   6498   if (max_chars == 0) return;
   6499 
   6500   switch (StringShape(input).representation_tag()) {
   6501     case kSeqStringTag:
   6502       if (input->IsAsciiRepresentation()) {
   6503         SeqAsciiString::cast(input)->SeqAsciiStringReadBlockIntoBuffer(rbb,
   6504                                                                  offset_ptr,
   6505                                                                  max_chars);
   6506         return;
   6507       } else {
   6508         SeqTwoByteString::cast(input)->SeqTwoByteStringReadBlockIntoBuffer(rbb,
   6509                                                                      offset_ptr,
   6510                                                                      max_chars);
   6511         return;
   6512       }
   6513     case kConsStringTag:
   6514       ConsString::cast(input)->ConsStringReadBlockIntoBuffer(rbb,
   6515                                                              offset_ptr,
   6516                                                              max_chars);
   6517       return;
   6518     case kExternalStringTag:
   6519       if (input->IsAsciiRepresentation()) {
   6520         ExternalAsciiString::cast(input)->
   6521             ExternalAsciiStringReadBlockIntoBuffer(rbb, offset_ptr, max_chars);
   6522       } else {
   6523         ExternalTwoByteString::cast(input)->
   6524             ExternalTwoByteStringReadBlockIntoBuffer(rbb,
   6525                                                      offset_ptr,
   6526                                                      max_chars);
   6527        }
   6528        return;
   6529     case kSlicedStringTag:
   6530       SlicedString::cast(input)->SlicedStringReadBlockIntoBuffer(rbb,
   6531                                                                  offset_ptr,
   6532                                                                  max_chars);
   6533       return;
   6534     default:
   6535       break;
   6536   }
   6537 
   6538   UNREACHABLE();
   6539   return;
   6540 }
   6541 
   6542 
   6543 const unibrow::byte* String::ReadBlock(String* input,
   6544                                        unibrow::byte* util_buffer,
   6545                                        unsigned capacity,
   6546                                        unsigned* remaining,
   6547                                        unsigned* offset_ptr) {
   6548   ASSERT(*offset_ptr <= (unsigned)input->length());
   6549   unsigned chars = input->length() - *offset_ptr;
   6550   ReadBlockBuffer rbb(util_buffer, 0, capacity, 0);
   6551   const unibrow::byte* answer = ReadBlock(input, &rbb, offset_ptr, chars);
   6552   ASSERT(rbb.remaining <= static_cast<unsigned>(input->length()));
   6553   *remaining = rbb.remaining;
   6554   return answer;
   6555 }
   6556 
   6557 
   6558 const unibrow::byte* String::ReadBlock(String** raw_input,
   6559                                        unibrow::byte* util_buffer,
   6560                                        unsigned capacity,
   6561                                        unsigned* remaining,
   6562                                        unsigned* offset_ptr) {
   6563   Handle<String> input(raw_input);
   6564   ASSERT(*offset_ptr <= (unsigned)input->length());
   6565   unsigned chars = input->length() - *offset_ptr;
   6566   if (chars > capacity) chars = capacity;
   6567   ReadBlockBuffer rbb(util_buffer, 0, capacity, 0);
   6568   ReadBlockIntoBuffer(*input, &rbb, offset_ptr, chars);
   6569   ASSERT(rbb.remaining <= static_cast<unsigned>(input->length()));
   6570   *remaining = rbb.remaining;
   6571   return rbb.util_buffer;
   6572 }
   6573 
   6574 
   6575 // This will iterate unless the block of string data spans two 'halves' of
   6576 // a ConsString, in which case it will recurse.  Since the block of string
   6577 // data to be read has a maximum size this limits the maximum recursion
   6578 // depth to something sane.  Since C++ does not have tail call recursion
   6579 // elimination, the iteration must be explicit.
   6580 void ConsString::ConsStringReadBlockIntoBuffer(ReadBlockBuffer* rbb,
   6581                                                unsigned* offset_ptr,
   6582                                                unsigned max_chars) {
   6583   ConsString* current = this;
   6584   unsigned offset = *offset_ptr;
   6585   int offset_correction = 0;
   6586 
   6587   while (true) {
   6588     String* left = current->first();
   6589     unsigned left_length = (unsigned)left->length();
   6590     if (left_length > offset &&
   6591       max_chars <= left_length - offset) {
   6592       // Left hand side only - iterate unless we have reached the bottom of
   6593       // the cons tree.
   6594       if (StringShape(left).IsCons()) {
   6595         current = ConsString::cast(left);
   6596         continue;
   6597       } else {
   6598         String::ReadBlockIntoBuffer(left, rbb, &offset, max_chars);
   6599         *offset_ptr = offset + offset_correction;
   6600         return;
   6601       }
   6602     } else if (left_length <= offset) {
   6603       // Right hand side only - iterate unless we have reached the bottom of
   6604       // the cons tree.
   6605       offset -= left_length;
   6606       offset_correction += left_length;
   6607       String* right = current->second();
   6608       if (StringShape(right).IsCons()) {
   6609         current = ConsString::cast(right);
   6610         continue;
   6611       } else {
   6612         String::ReadBlockIntoBuffer(right, rbb, &offset, max_chars);
   6613         *offset_ptr = offset + offset_correction;
   6614         return;
   6615       }
   6616     } else {
   6617       // The block to be read spans two sides of the ConsString, so we recurse.
   6618       // First recurse on the left.
   6619       max_chars -= left_length - offset;
   6620       String::ReadBlockIntoBuffer(left, rbb, &offset, left_length - offset);
   6621       // We may have reached the max or there may not have been enough space
   6622       // in the buffer for the characters in the left hand side.
   6623       if (offset == left_length) {
   6624         // Recurse on the right.
   6625         String* right = String::cast(current->second());
   6626         offset -= left_length;
   6627         offset_correction += left_length;
   6628         String::ReadBlockIntoBuffer(right, rbb, &offset, max_chars);
   6629       }
   6630       *offset_ptr = offset + offset_correction;
   6631       return;
   6632     }
   6633   }
   6634 }
   6635 
   6636 
   6637 uint16_t ConsString::ConsStringGet(int index) {
   6638   ASSERT(index >= 0 && index < this->length());
   6639 
   6640   // Check for a flattened cons string
   6641   if (second()->length() == 0) {
   6642     String* left = first();
   6643     return left->Get(index);
   6644   }
   6645 
   6646   String* string = String::cast(this);
   6647 
   6648   while (true) {
   6649     if (StringShape(string).IsCons()) {
   6650       ConsString* cons_string = ConsString::cast(string);
   6651       String* left = cons_string->first();
   6652       if (left->length() > index) {
   6653         string = left;
   6654       } else {
   6655         index -= left->length();
   6656         string = cons_string->second();
   6657       }
   6658     } else {
   6659       return string->Get(index);
   6660     }
   6661   }
   6662 
   6663   UNREACHABLE();
   6664   return 0;
   6665 }
   6666 
   6667 
   6668 uint16_t SlicedString::SlicedStringGet(int index) {
   6669   return parent()->Get(offset() + index);
   6670 }
   6671 
   6672 
   6673 const unibrow::byte* SlicedString::SlicedStringReadBlock(
   6674     ReadBlockBuffer* buffer, unsigned* offset_ptr, unsigned chars) {
   6675   unsigned offset = this->offset();
   6676   *offset_ptr += offset;
   6677   const unibrow::byte* answer = String::ReadBlock(String::cast(parent()),
   6678                                                   buffer, offset_ptr, chars);
   6679   *offset_ptr -= offset;
   6680   return answer;
   6681 }
   6682 
   6683 
   6684 void SlicedString::SlicedStringReadBlockIntoBuffer(
   6685     ReadBlockBuffer* buffer, unsigned* offset_ptr, unsigned chars) {
   6686   unsigned offset = this->offset();
   6687   *offset_ptr += offset;
   6688   String::ReadBlockIntoBuffer(String::cast(parent()),
   6689                               buffer, offset_ptr, chars);
   6690   *offset_ptr -= offset;
   6691 }
   6692 
   6693 template <typename sinkchar>
   6694 void String::WriteToFlat(String* src,
   6695                          sinkchar* sink,
   6696                          int f,
   6697                          int t) {
   6698   String* source = src;
   6699   int from = f;
   6700   int to = t;
   6701   while (true) {
   6702     ASSERT(0 <= from && from <= to && to <= source->length());
   6703     switch (StringShape(source).full_representation_tag()) {
   6704       case kAsciiStringTag | kExternalStringTag: {
   6705         CopyChars(sink,
   6706                   ExternalAsciiString::cast(source)->GetChars() + from,
   6707                   to - from);
   6708         return;
   6709       }
   6710       case kTwoByteStringTag | kExternalStringTag: {
   6711         const uc16* data =
   6712             ExternalTwoByteString::cast(source)->GetChars();
   6713         CopyChars(sink,
   6714                   data + from,
   6715                   to - from);
   6716         return;
   6717       }
   6718       case kAsciiStringTag | kSeqStringTag: {
   6719         CopyChars(sink,
   6720                   SeqAsciiString::cast(source)->GetChars() + from,
   6721                   to - from);
   6722         return;
   6723       }
   6724       case kTwoByteStringTag | kSeqStringTag: {
   6725         CopyChars(sink,
   6726                   SeqTwoByteString::cast(source)->GetChars() + from,
   6727                   to - from);
   6728         return;
   6729       }
   6730       case kAsciiStringTag | kConsStringTag:
   6731       case kTwoByteStringTag | kConsStringTag: {
   6732         ConsString* cons_string = ConsString::cast(source);
   6733         String* first = cons_string->first();
   6734         int boundary = first->length();
   6735         if (to - boundary >= boundary - from) {
   6736           // Right hand side is longer.  Recurse over left.
   6737           if (from < boundary) {
   6738             WriteToFlat(first, sink, from, boundary);
   6739             sink += boundary - from;
   6740             from = 0;
   6741           } else {
   6742             from -= boundary;
   6743           }
   6744           to -= boundary;
   6745           source = cons_string->second();
   6746         } else {
   6747           // Left hand side is longer.  Recurse over right.
   6748           if (to > boundary) {
   6749             String* second = cons_string->second();
   6750             // When repeatedly appending to a string, we get a cons string that
   6751             // is unbalanced to the left, a list, essentially.  We inline the
   6752             // common case of sequential ascii right child.
   6753             if (to - boundary == 1) {
   6754               sink[boundary - from] = static_cast<sinkchar>(second->Get(0));
   6755             } else if (second->IsSeqAsciiString()) {
   6756               CopyChars(sink + boundary - from,
   6757                         SeqAsciiString::cast(second)->GetChars(),
   6758                         to - boundary);
   6759             } else {
   6760               WriteToFlat(second,
   6761                           sink + boundary - from,
   6762                           0,
   6763                           to - boundary);
   6764             }
   6765             to = boundary;
   6766           }
   6767           source = first;
   6768         }
   6769         break;
   6770       }
   6771       case kAsciiStringTag | kSlicedStringTag:
   6772       case kTwoByteStringTag | kSlicedStringTag: {
   6773         SlicedString* slice = SlicedString::cast(source);
   6774         unsigned offset = slice->offset();
   6775         WriteToFlat(slice->parent(), sink, from + offset, to + offset);
   6776         return;
   6777       }
   6778     }
   6779   }
   6780 }
   6781 
   6782 
   6783 template <typename IteratorA, typename IteratorB>
   6784 static inline bool CompareStringContents(IteratorA* ia, IteratorB* ib) {
   6785   // General slow case check.  We know that the ia and ib iterators
   6786   // have the same length.
   6787   while (ia->has_more()) {
   6788     uint32_t ca = ia->GetNext();
   6789     uint32_t cb = ib->GetNext();
   6790     ASSERT(ca <= unibrow::Utf16::kMaxNonSurrogateCharCode);
   6791     ASSERT(cb <= unibrow::Utf16::kMaxNonSurrogateCharCode);
   6792     if (ca != cb)
   6793       return false;
   6794   }
   6795   return true;
   6796 }
   6797 
   6798 
   6799 // Compares the contents of two strings by reading and comparing
   6800 // int-sized blocks of characters.
   6801 template <typename Char>
   6802 static inline bool CompareRawStringContents(Vector<Char> a, Vector<Char> b) {
   6803   int length = a.length();
   6804   ASSERT_EQ(length, b.length());
   6805   const Char* pa = a.start();
   6806   const Char* pb = b.start();
   6807   int i = 0;
   6808 #ifndef V8_HOST_CAN_READ_UNALIGNED
   6809   // If this architecture isn't comfortable reading unaligned ints
   6810   // then we have to check that the strings are aligned before
   6811   // comparing them blockwise.
   6812   const int kAlignmentMask = sizeof(uint32_t) - 1;  // NOLINT
   6813   uint32_t pa_addr = reinterpret_cast<uint32_t>(pa);
   6814   uint32_t pb_addr = reinterpret_cast<uint32_t>(pb);
   6815   if (((pa_addr & kAlignmentMask) | (pb_addr & kAlignmentMask)) == 0) {
   6816 #endif
   6817     const int kStepSize = sizeof(int) / sizeof(Char);  // NOLINT
   6818     int endpoint = length - kStepSize;
   6819     // Compare blocks until we reach near the end of the string.
   6820     for (; i <= endpoint; i += kStepSize) {
   6821       uint32_t wa = *reinterpret_cast<const uint32_t*>(pa + i);
   6822       uint32_t wb = *reinterpret_cast<const uint32_t*>(pb + i);
   6823       if (wa != wb) {
   6824         return false;
   6825       }
   6826     }
   6827 #ifndef V8_HOST_CAN_READ_UNALIGNED
   6828   }
   6829 #endif
   6830   // Compare the remaining characters that didn't fit into a block.
   6831   for (; i < length; i++) {
   6832     if (a[i] != b[i]) {
   6833       return false;
   6834     }
   6835   }
   6836   return true;
   6837 }
   6838 
   6839 
   6840 template <typename IteratorA>
   6841 static inline bool CompareStringContentsPartial(Isolate* isolate,
   6842                                                 IteratorA* ia,
   6843                                                 String* b) {
   6844   String::FlatContent content = b->GetFlatContent();
   6845   if (content.IsFlat()) {
   6846     if (content.IsAscii()) {
   6847       VectorIterator<char> ib(content.ToAsciiVector());
   6848       return CompareStringContents(ia, &ib);
   6849     } else {
   6850       VectorIterator<uc16> ib(content.ToUC16Vector());
   6851       return CompareStringContents(ia, &ib);
   6852     }
   6853   } else {
   6854     isolate->objects_string_compare_buffer_b()->Reset(0, b);
   6855     return CompareStringContents(ia,
   6856                                  isolate->objects_string_compare_buffer_b());
   6857   }
   6858 }
   6859 
   6860 
   6861 bool String::SlowEquals(String* other) {
   6862   // Fast check: negative check with lengths.
   6863   int len = length();
   6864   if (len != other->length()) return false;
   6865   if (len == 0) return true;
   6866 
   6867   // Fast check: if hash code is computed for both strings
   6868   // a fast negative check can be performed.
   6869   if (HasHashCode() && other->HasHashCode()) {
   6870 #ifdef DEBUG
   6871     if (FLAG_enable_slow_asserts) {
   6872       if (Hash() != other->Hash()) {
   6873         bool found_difference = false;
   6874         for (int i = 0; i < len; i++) {
   6875           if (Get(i) != other->Get(i)) {
   6876             found_difference = true;
   6877             break;
   6878           }
   6879         }
   6880         ASSERT(found_difference);
   6881       }
   6882     }
   6883 #endif
   6884     if (Hash() != other->Hash()) return false;
   6885   }
   6886 
   6887   // We know the strings are both non-empty. Compare the first chars
   6888   // before we try to flatten the strings.
   6889   if (this->Get(0) != other->Get(0)) return false;
   6890 
   6891   String* lhs = this->TryFlattenGetString();
   6892   String* rhs = other->TryFlattenGetString();
   6893 
   6894   if (StringShape(lhs).IsSequentialAscii() &&
   6895       StringShape(rhs).IsSequentialAscii()) {
   6896     const char* str1 = SeqAsciiString::cast(lhs)->GetChars();
   6897     const char* str2 = SeqAsciiString::cast(rhs)->GetChars();
   6898     return CompareRawStringContents(Vector<const char>(str1, len),
   6899                                     Vector<const char>(str2, len));
   6900   }
   6901 
   6902   Isolate* isolate = GetIsolate();
   6903   String::FlatContent lhs_content = lhs->GetFlatContent();
   6904   String::FlatContent rhs_content = rhs->GetFlatContent();
   6905   if (lhs_content.IsFlat()) {
   6906     if (lhs_content.IsAscii()) {
   6907       Vector<const char> vec1 = lhs_content.ToAsciiVector();
   6908       if (rhs_content.IsFlat()) {
   6909         if (rhs_content.IsAscii()) {
   6910           Vector<const char> vec2 = rhs_content.ToAsciiVector();
   6911           return CompareRawStringContents(vec1, vec2);
   6912         } else {
   6913           VectorIterator<char> buf1(vec1);
   6914           VectorIterator<uc16> ib(rhs_content.ToUC16Vector());
   6915           return CompareStringContents(&buf1, &ib);
   6916         }
   6917       } else {
   6918         VectorIterator<char> buf1(vec1);
   6919         isolate->objects_string_compare_buffer_b()->Reset(0, rhs);
   6920         return CompareStringContents(&buf1,
   6921             isolate->objects_string_compare_buffer_b());
   6922       }
   6923     } else {
   6924       Vector<const uc16> vec1 = lhs_content.ToUC16Vector();
   6925       if (rhs_content.IsFlat()) {
   6926         if (rhs_content.IsAscii()) {
   6927           VectorIterator<uc16> buf1(vec1);
   6928           VectorIterator<char> ib(rhs_content.ToAsciiVector());
   6929           return CompareStringContents(&buf1, &ib);
   6930         } else {
   6931           Vector<const uc16> vec2(rhs_content.ToUC16Vector());
   6932           return CompareRawStringContents(vec1, vec2);
   6933         }
   6934       } else {
   6935         VectorIterator<uc16> buf1(vec1);
   6936         isolate->objects_string_compare_buffer_b()->Reset(0, rhs);
   6937         return CompareStringContents(&buf1,
   6938             isolate->objects_string_compare_buffer_b());
   6939       }
   6940     }
   6941   } else {
   6942     isolate->objects_string_compare_buffer_a()->Reset(0, lhs);
   6943     return CompareStringContentsPartial(isolate,
   6944         isolate->objects_string_compare_buffer_a(), rhs);
   6945   }
   6946 }
   6947 
   6948 
   6949 bool String::MarkAsUndetectable() {
   6950   if (StringShape(this).IsSymbol()) return false;
   6951 
   6952   Map* map = this->map();
   6953   Heap* heap = GetHeap();
   6954   if (map == heap->string_map()) {
   6955     this->set_map(heap->undetectable_string_map());
   6956     return true;
   6957   } else if (map == heap->ascii_string_map()) {
   6958     this->set_map(heap->undetectable_ascii_string_map());
   6959     return true;
   6960   }
   6961   // Rest cannot be marked as undetectable
   6962   return false;
   6963 }
   6964 
   6965 
   6966 bool String::IsEqualTo(Vector<const char> str) {
   6967   Isolate* isolate = GetIsolate();
   6968   int slen = length();
   6969   Access<UnicodeCache::Utf8Decoder>
   6970       decoder(isolate->unicode_cache()->utf8_decoder());
   6971   decoder->Reset(str.start(), str.length());
   6972   int i;
   6973   for (i = 0; i < slen && decoder->has_more(); i++) {
   6974     uint32_t r = decoder->GetNext();
   6975     if (r > unibrow::Utf16::kMaxNonSurrogateCharCode) {
   6976       if (i > slen - 1) return false;
   6977       if (Get(i++) != unibrow::Utf16::LeadSurrogate(r)) return false;
   6978       if (Get(i) != unibrow::Utf16::TrailSurrogate(r)) return false;
   6979     } else {
   6980       if (Get(i) != r) return false;
   6981     }
   6982   }
   6983   return i == slen && !decoder->has_more();
   6984 }
   6985 
   6986 
   6987 bool String::IsAsciiEqualTo(Vector<const char> str) {
   6988   int slen = length();
   6989   if (str.length() != slen) return false;
   6990   FlatContent content = GetFlatContent();
   6991   if (content.IsAscii()) {
   6992     return CompareChars(content.ToAsciiVector().start(),
   6993                         str.start(), slen) == 0;
   6994   }
   6995   for (int i = 0; i < slen; i++) {
   6996     if (Get(i) != static_cast<uint16_t>(str[i])) return false;
   6997   }
   6998   return true;
   6999 }
   7000 
   7001 
   7002 bool String::IsTwoByteEqualTo(Vector<const uc16> str) {
   7003   int slen = length();
   7004   if (str.length() != slen) return false;
   7005   FlatContent content = GetFlatContent();
   7006   if (content.IsTwoByte()) {
   7007     return CompareChars(content.ToUC16Vector().start(), str.start(), slen) == 0;
   7008   }
   7009   for (int i = 0; i < slen; i++) {
   7010     if (Get(i) != str[i]) return false;
   7011   }
   7012   return true;
   7013 }
   7014 
   7015 
   7016 uint32_t String::ComputeAndSetHash() {
   7017   // Should only be called if hash code has not yet been computed.
   7018   ASSERT(!HasHashCode());
   7019 
   7020   const int len = length();
   7021 
   7022   // Compute the hash code.
   7023   uint32_t field = 0;
   7024   if (StringShape(this).IsSequentialAscii()) {
   7025     field = HashSequentialString(SeqAsciiString::cast(this)->GetChars(),
   7026                                  len,
   7027                                  GetHeap()->HashSeed());
   7028   } else if (StringShape(this).IsSequentialTwoByte()) {
   7029     field = HashSequentialString(SeqTwoByteString::cast(this)->GetChars(),
   7030                                  len,
   7031                                  GetHeap()->HashSeed());
   7032   } else {
   7033     StringInputBuffer buffer(this);
   7034     field = ComputeHashField(&buffer, len, GetHeap()->HashSeed());
   7035   }
   7036 
   7037   // Store the hash code in the object.
   7038   set_hash_field(field);
   7039 
   7040   // Check the hash code is there.
   7041   ASSERT(HasHashCode());
   7042   uint32_t result = field >> kHashShift;
   7043   ASSERT(result != 0);  // Ensure that the hash value of 0 is never computed.
   7044   return result;
   7045 }
   7046 
   7047 
   7048 bool String::ComputeArrayIndex(unibrow::CharacterStream* buffer,
   7049                                uint32_t* index,
   7050                                int length) {
   7051   if (length == 0 || length > kMaxArrayIndexSize) return false;
   7052   uc32 ch = buffer->GetNext();
   7053 
   7054   // If the string begins with a '0' character, it must only consist
   7055   // of it to be a legal array index.
   7056   if (ch == '0') {
   7057     *index = 0;
   7058     return length == 1;
   7059   }
   7060 
   7061   // Convert string to uint32 array index; character by character.
   7062   int d = ch - '0';
   7063   if (d < 0 || d > 9) return false;
   7064   uint32_t result = d;
   7065   while (buffer->has_more()) {
   7066     d = buffer->GetNext() - '0';
   7067     if (d < 0 || d > 9) return false;
   7068     // Check that the new result is below the 32 bit limit.
   7069     if (result > 429496729U - ((d > 5) ? 1 : 0)) return false;
   7070     result = (result * 10) + d;
   7071   }
   7072 
   7073   *index = result;
   7074   return true;
   7075 }
   7076 
   7077 
   7078 bool String::SlowAsArrayIndex(uint32_t* index) {
   7079   if (length() <= kMaxCachedArrayIndexLength) {
   7080     Hash();  // force computation of hash code
   7081     uint32_t field = hash_field();
   7082     if ((field & kIsNotArrayIndexMask) != 0) return false;
   7083     // Isolate the array index form the full hash field.
   7084     *index = (kArrayIndexHashMask & field) >> kHashShift;
   7085     return true;
   7086   } else {
   7087     StringInputBuffer buffer(this);
   7088     return ComputeArrayIndex(&buffer, index, length());
   7089   }
   7090 }
   7091 
   7092 
   7093 uint32_t StringHasher::MakeArrayIndexHash(uint32_t value, int length) {
   7094   // For array indexes mix the length into the hash as an array index could
   7095   // be zero.
   7096   ASSERT(length > 0);
   7097   ASSERT(length <= String::kMaxArrayIndexSize);
   7098   ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) <
   7099          (1 << String::kArrayIndexValueBits));
   7100 
   7101   value <<= String::kHashShift;
   7102   value |= length << String::kArrayIndexHashLengthShift;
   7103 
   7104   ASSERT((value & String::kIsNotArrayIndexMask) == 0);
   7105   ASSERT((length > String::kMaxCachedArrayIndexLength) ||
   7106          (value & String::kContainsCachedArrayIndexMask) == 0);
   7107   return value;
   7108 }
   7109 
   7110 
   7111 void StringHasher::AddSurrogatePair(uc32 c) {
   7112   uint16_t lead = unibrow::Utf16::LeadSurrogate(c);
   7113   AddCharacter(lead);
   7114   uint16_t trail = unibrow::Utf16::TrailSurrogate(c);
   7115   AddCharacter(trail);
   7116 }
   7117 
   7118 
   7119 void StringHasher::AddSurrogatePairNoIndex(uc32 c) {
   7120   uint16_t lead = unibrow::Utf16::LeadSurrogate(c);
   7121   AddCharacterNoIndex(lead);
   7122   uint16_t trail = unibrow::Utf16::TrailSurrogate(c);
   7123   AddCharacterNoIndex(trail);
   7124 }
   7125 
   7126 
   7127 uint32_t StringHasher::GetHashField() {
   7128   ASSERT(is_valid());
   7129   if (length_ <= String::kMaxHashCalcLength) {
   7130     if (is_array_index()) {
   7131       return MakeArrayIndexHash(array_index(), length_);
   7132     }
   7133     return (GetHash() << String::kHashShift) | String::kIsNotArrayIndexMask;
   7134   } else {
   7135     return (length_ << String::kHashShift) | String::kIsNotArrayIndexMask;
   7136   }
   7137 }
   7138 
   7139 
   7140 uint32_t String::ComputeHashField(unibrow::CharacterStream* buffer,
   7141                                   int length,
   7142                                   uint32_t seed) {
   7143   StringHasher hasher(length, seed);
   7144 
   7145   // Very long strings have a trivial hash that doesn't inspect the
   7146   // string contents.
   7147   if (hasher.has_trivial_hash()) {
   7148     return hasher.GetHashField();
   7149   }
   7150 
   7151   // Do the iterative array index computation as long as there is a
   7152   // chance this is an array index.
   7153   while (buffer->has_more() && hasher.is_array_index()) {
   7154     hasher.AddCharacter(buffer->GetNext());
   7155   }
   7156 
   7157   // Process the remaining characters without updating the array
   7158   // index.
   7159   while (buffer->has_more()) {
   7160     hasher.AddCharacterNoIndex(buffer->GetNext());
   7161   }
   7162 
   7163   return hasher.GetHashField();
   7164 }
   7165 
   7166 
   7167 MaybeObject* String::SubString(int start, int end, PretenureFlag pretenure) {
   7168   Heap* heap = GetHeap();
   7169   if (start == 0 && end == length()) return this;
   7170   MaybeObject* result = heap->AllocateSubString(this, start, end, pretenure);
   7171   return result;
   7172 }
   7173 
   7174 
   7175 void String::PrintOn(FILE* file) {
   7176   int length = this->length();
   7177   for (int i = 0; i < length; i++) {
   7178     fprintf(file, "%c", Get(i));
   7179   }
   7180 }
   7181 
   7182 
   7183 void Map::CreateOneBackPointer(Object* transition_target) {
   7184   if (!transition_target->IsMap()) return;
   7185   Map* target = Map::cast(transition_target);
   7186 #ifdef DEBUG
   7187   // Verify target.
   7188   Object* source_prototype = prototype();
   7189   Object* target_prototype = target->prototype();
   7190   ASSERT(source_prototype->IsJSReceiver() ||
   7191          source_prototype->IsMap() ||
   7192          source_prototype->IsNull());
   7193   ASSERT(target_prototype->IsJSReceiver() ||
   7194          target_prototype->IsNull());
   7195   ASSERT(source_prototype->IsMap() ||
   7196          source_prototype == target_prototype);
   7197 #endif
   7198   // Point target back to source.  set_prototype() will not let us set
   7199   // the prototype to a map, as we do here.
   7200   *RawField(target, kPrototypeOffset) = this;
   7201 }
   7202 
   7203 
   7204 void Map::CreateBackPointers() {
   7205   DescriptorArray* descriptors = instance_descriptors();
   7206   for (int i = 0; i < descriptors->number_of_descriptors(); i++) {
   7207     switch (descriptors->GetType(i)) {
   7208       case MAP_TRANSITION:
   7209       case CONSTANT_TRANSITION:
   7210         CreateOneBackPointer(descriptors->GetValue(i));
   7211         break;
   7212       case ELEMENTS_TRANSITION: {
   7213         Object* object = descriptors->GetValue(i);
   7214         if (object->IsMap()) {
   7215           CreateOneBackPointer(object);
   7216         } else {
   7217           FixedArray* array = FixedArray::cast(object);
   7218           for (int i = 0; i < array->length(); ++i) {
   7219             CreateOneBackPointer(array->get(i));
   7220           }
   7221         }
   7222         break;
   7223       }
   7224       case CALLBACKS: {
   7225         Object* object = descriptors->GetValue(i);
   7226         if (object->IsAccessorPair()) {
   7227           AccessorPair* accessors = AccessorPair::cast(object);
   7228           CreateOneBackPointer(accessors->getter());
   7229           CreateOneBackPointer(accessors->setter());
   7230         }
   7231         break;
   7232       }
   7233       case NORMAL:
   7234       case FIELD:
   7235       case CONSTANT_FUNCTION:
   7236       case HANDLER:
   7237       case INTERCEPTOR:
   7238       case NULL_DESCRIPTOR:
   7239         break;
   7240     }
   7241   }
   7242 }
   7243 
   7244 
   7245 bool Map::RestoreOneBackPointer(Object* object,
   7246                                 Object* real_prototype,
   7247                                 bool* keep_entry) {
   7248   if (!object->IsMap()) return false;
   7249   Map* map = Map::cast(object);
   7250   if (Marking::MarkBitFrom(map).Get()) {
   7251     *keep_entry = true;
   7252     return false;
   7253   }
   7254   ASSERT(map->prototype() == this || map->prototype() == real_prototype);
   7255   // Getter prototype() is read-only, set_prototype() has side effects.
   7256   *RawField(map, Map::kPrototypeOffset) = real_prototype;
   7257   return true;
   7258 }
   7259 
   7260 
   7261 void Map::ClearNonLiveTransitions(Heap* heap, Object* real_prototype) {
   7262   DescriptorArray* d = DescriptorArray::cast(
   7263       *RawField(this, Map::kInstanceDescriptorsOrBitField3Offset));
   7264   if (d->IsEmpty()) return;
   7265   Smi* NullDescriptorDetails =
   7266     PropertyDetails(NONE, NULL_DESCRIPTOR).AsSmi();
   7267   FixedArray* contents = FixedArray::cast(
   7268       d->get(DescriptorArray::kContentArrayIndex));
   7269   ASSERT(contents->length() >= 2);
   7270   for (int i = 0; i < contents->length(); i += 2) {
   7271     // If the pair (value, details) is a map transition, check if the target is
   7272     // live. If not, null the descriptor. Also drop the back pointer for that
   7273     // map transition, so that this map is not reached again by following a back
   7274     // pointer from a non-live object.
   7275     bool keep_entry = false;
   7276     PropertyDetails details(Smi::cast(contents->get(i + 1)));
   7277     switch (details.type()) {
   7278       case MAP_TRANSITION:
   7279       case CONSTANT_TRANSITION:
   7280         RestoreOneBackPointer(contents->get(i), real_prototype, &keep_entry);
   7281         break;
   7282       case ELEMENTS_TRANSITION: {
   7283         Object* object = contents->get(i);
   7284         if (object->IsMap()) {
   7285           RestoreOneBackPointer(object, real_prototype, &keep_entry);
   7286         } else {
   7287           FixedArray* array = FixedArray::cast(object);
   7288           for (int j = 0; j < array->length(); ++j) {
   7289             if (RestoreOneBackPointer(array->get(j),
   7290                                       real_prototype,
   7291                                       &keep_entry)) {
   7292               array->set_undefined(j);
   7293             }
   7294           }
   7295         }
   7296         break;
   7297       }
   7298       case CALLBACKS: {
   7299         Object* object = contents->get(i);
   7300         if (object->IsAccessorPair()) {
   7301           AccessorPair* accessors = AccessorPair::cast(object);
   7302           if (RestoreOneBackPointer(accessors->getter(),
   7303                                     real_prototype,
   7304                                     &keep_entry)) {
   7305             accessors->set_getter(heap->the_hole_value());
   7306           }
   7307           if (RestoreOneBackPointer(accessors->setter(),
   7308                                     real_prototype,
   7309                                     &keep_entry)) {
   7310             accessors->set_setter(heap->the_hole_value());
   7311           }
   7312         } else {
   7313           keep_entry = true;
   7314         }
   7315         break;
   7316       }
   7317       case NORMAL:
   7318       case FIELD:
   7319       case CONSTANT_FUNCTION:
   7320       case HANDLER:
   7321       case INTERCEPTOR:
   7322       case NULL_DESCRIPTOR:
   7323         keep_entry = true;
   7324         break;
   7325     }
   7326     // Make sure that an entry containing only dead transitions gets collected.
   7327     // What we *really* want to do here is removing this entry completely, but
   7328     // for technical reasons we can't do this, so we zero it out instead.
   7329     if (!keep_entry) {
   7330       contents->set_unchecked(i + 1, NullDescriptorDetails);
   7331       contents->set_null_unchecked(heap, i);
   7332     }
   7333   }
   7334 }
   7335 
   7336 
   7337 int Map::Hash() {
   7338   // For performance reasons we only hash the 3 most variable fields of a map:
   7339   // constructor, prototype and bit_field2.
   7340 
   7341   // Shift away the tag.
   7342   int hash = (static_cast<uint32_t>(
   7343         reinterpret_cast<uintptr_t>(constructor())) >> 2);
   7344 
   7345   // XOR-ing the prototype and constructor directly yields too many zero bits
   7346   // when the two pointers are close (which is fairly common).
   7347   // To avoid this we shift the prototype 4 bits relatively to the constructor.
   7348   hash ^= (static_cast<uint32_t>(
   7349         reinterpret_cast<uintptr_t>(prototype())) << 2);
   7350 
   7351   return hash ^ (hash >> 16) ^ bit_field2();
   7352 }
   7353 
   7354 
   7355 bool Map::EquivalentToForNormalization(Map* other,
   7356                                        PropertyNormalizationMode mode) {
   7357   return
   7358     constructor() == other->constructor() &&
   7359     prototype() == other->prototype() &&
   7360     inobject_properties() == ((mode == CLEAR_INOBJECT_PROPERTIES) ?
   7361                               0 :
   7362                               other->inobject_properties()) &&
   7363     instance_type() == other->instance_type() &&
   7364     bit_field() == other->bit_field() &&
   7365     bit_field2() == other->bit_field2() &&
   7366     (bit_field3() & ~(1<<Map::kIsShared)) ==
   7367         (other->bit_field3() & ~(1<<Map::kIsShared));
   7368 }
   7369 
   7370 
   7371 void JSFunction::JSFunctionIterateBody(int object_size, ObjectVisitor* v) {
   7372   // Iterate over all fields in the body but take care in dealing with
   7373   // the code entry.
   7374   IteratePointers(v, kPropertiesOffset, kCodeEntryOffset);
   7375   v->VisitCodeEntry(this->address() + kCodeEntryOffset);
   7376   IteratePointers(v, kCodeEntryOffset + kPointerSize, object_size);
   7377 }
   7378 
   7379 
   7380 void JSFunction::MarkForLazyRecompilation() {
   7381   ASSERT(is_compiled() && !IsOptimized());
   7382   ASSERT(shared()->allows_lazy_compilation() ||
   7383          code()->optimizable());
   7384   Builtins* builtins = GetIsolate()->builtins();
   7385   ReplaceCode(builtins->builtin(Builtins::kLazyRecompile));
   7386 }
   7387 
   7388 
   7389 bool SharedFunctionInfo::EnsureCompiled(Handle<SharedFunctionInfo> shared,
   7390                                         ClearExceptionFlag flag) {
   7391   return shared->is_compiled() || CompileLazy(shared, flag);
   7392 }
   7393 
   7394 
   7395 static bool CompileLazyHelper(CompilationInfo* info,
   7396                               ClearExceptionFlag flag) {
   7397   // Compile the source information to a code object.
   7398   ASSERT(info->IsOptimizing() || !info->shared_info()->is_compiled());
   7399   ASSERT(!info->isolate()->has_pending_exception());
   7400   bool result = Compiler::CompileLazy(info);
   7401   ASSERT(result != Isolate::Current()->has_pending_exception());
   7402   if (!result && flag == CLEAR_EXCEPTION) {
   7403     info->isolate()->clear_pending_exception();
   7404   }
   7405   return result;
   7406 }
   7407 
   7408 
   7409 bool SharedFunctionInfo::CompileLazy(Handle<SharedFunctionInfo> shared,
   7410                                      ClearExceptionFlag flag) {
   7411   CompilationInfo info(shared);
   7412   return CompileLazyHelper(&info, flag);
   7413 }
   7414 
   7415 
   7416 bool JSFunction::CompileLazy(Handle<JSFunction> function,
   7417                              ClearExceptionFlag flag) {
   7418   bool result = true;
   7419   if (function->shared()->is_compiled()) {
   7420     function->ReplaceCode(function->shared()->code());
   7421     function->shared()->set_code_age(0);
   7422   } else {
   7423     CompilationInfo info(function);
   7424     result = CompileLazyHelper(&info, flag);
   7425     ASSERT(!result || function->is_compiled());
   7426   }
   7427   return result;
   7428 }
   7429 
   7430 
   7431 bool JSFunction::CompileOptimized(Handle<JSFunction> function,
   7432                                   int osr_ast_id,
   7433                                   ClearExceptionFlag flag) {
   7434   CompilationInfo info(function);
   7435   info.SetOptimizing(osr_ast_id);
   7436   return CompileLazyHelper(&info, flag);
   7437 }
   7438 
   7439 
   7440 bool JSFunction::IsInlineable() {
   7441   if (IsBuiltin()) return false;
   7442   SharedFunctionInfo* shared_info = shared();
   7443   // Check that the function has a script associated with it.
   7444   if (!shared_info->script()->IsScript()) return false;
   7445   if (shared_info->optimization_disabled()) return false;
   7446   Code* code = shared_info->code();
   7447   if (code->kind() == Code::OPTIMIZED_FUNCTION) return true;
   7448   // If we never ran this (unlikely) then lets try to optimize it.
   7449   if (code->kind() != Code::FUNCTION) return true;
   7450   return code->optimizable();
   7451 }
   7452 
   7453 
   7454 MaybeObject* JSFunction::SetInstancePrototype(Object* value) {
   7455   ASSERT(value->IsJSReceiver());
   7456   Heap* heap = GetHeap();
   7457   if (has_initial_map()) {
   7458     // If the function has allocated the initial map
   7459     // replace it with a copy containing the new prototype.
   7460     Map* new_map;
   7461     MaybeObject* maybe_new_map = initial_map()->CopyDropTransitions();
   7462     if (!maybe_new_map->To(&new_map)) return maybe_new_map;
   7463     new_map->set_prototype(value);
   7464     MaybeObject* maybe_object =
   7465         set_initial_map_and_cache_transitions(new_map);
   7466     if (maybe_object->IsFailure()) return maybe_object;
   7467   } else {
   7468     // Put the value in the initial map field until an initial map is
   7469     // needed.  At that point, a new initial map is created and the
   7470     // prototype is put into the initial map where it belongs.
   7471     set_prototype_or_initial_map(value);
   7472   }
   7473   heap->ClearInstanceofCache();
   7474   return value;
   7475 }
   7476 
   7477 
   7478 MaybeObject* JSFunction::SetPrototype(Object* value) {
   7479   ASSERT(should_have_prototype());
   7480   Object* construct_prototype = value;
   7481 
   7482   // If the value is not a JSReceiver, store the value in the map's
   7483   // constructor field so it can be accessed.  Also, set the prototype
   7484   // used for constructing objects to the original object prototype.
   7485   // See ECMA-262 13.2.2.
   7486   if (!value->IsJSReceiver()) {
   7487     // Copy the map so this does not affect unrelated functions.
   7488     // Remove map transitions because they point to maps with a
   7489     // different prototype.
   7490     Map* new_map;
   7491     { MaybeObject* maybe_new_map = map()->CopyDropTransitions();
   7492       if (!maybe_new_map->To(&new_map)) return maybe_new_map;
   7493     }
   7494     Heap* heap = new_map->GetHeap();
   7495     set_map(new_map);
   7496     new_map->set_constructor(value);
   7497     new_map->set_non_instance_prototype(true);
   7498     construct_prototype =
   7499         heap->isolate()->context()->global_context()->
   7500             initial_object_prototype();
   7501   } else {
   7502     map()->set_non_instance_prototype(false);
   7503   }
   7504 
   7505   return SetInstancePrototype(construct_prototype);
   7506 }
   7507 
   7508 
   7509 Object* JSFunction::RemovePrototype() {
   7510   Context* global_context = context()->global_context();
   7511   Map* no_prototype_map = shared()->is_classic_mode()
   7512       ? global_context->function_without_prototype_map()
   7513       : global_context->strict_mode_function_without_prototype_map();
   7514 
   7515   if (map() == no_prototype_map) {
   7516     // Be idempotent.
   7517     return this;
   7518   }
   7519 
   7520   ASSERT(map() == (shared()->is_classic_mode()
   7521                    ? global_context->function_map()
   7522                    : global_context->strict_mode_function_map()));
   7523 
   7524   set_map(no_prototype_map);
   7525   set_prototype_or_initial_map(no_prototype_map->GetHeap()->the_hole_value());
   7526   return this;
   7527 }
   7528 
   7529 
   7530 Object* JSFunction::SetInstanceClassName(String* name) {
   7531   shared()->set_instance_class_name(name);
   7532   return this;
   7533 }
   7534 
   7535 
   7536 void JSFunction::PrintName(FILE* out) {
   7537   SmartArrayPointer<char> name = shared()->DebugName()->ToCString();
   7538   PrintF(out, "%s", *name);
   7539 }
   7540 
   7541 
   7542 Context* JSFunction::GlobalContextFromLiterals(FixedArray* literals) {
   7543   return Context::cast(literals->get(JSFunction::kLiteralGlobalContextIndex));
   7544 }
   7545 
   7546 
   7547 MaybeObject* Oddball::Initialize(const char* to_string,
   7548                                  Object* to_number,
   7549                                  byte kind) {
   7550   String* symbol;
   7551   { MaybeObject* maybe_symbol =
   7552         Isolate::Current()->heap()->LookupAsciiSymbol(to_string);
   7553     if (!maybe_symbol->To(&symbol)) return maybe_symbol;
   7554   }
   7555   set_to_string(symbol);
   7556   set_to_number(to_number);
   7557   set_kind(kind);
   7558   return this;
   7559 }
   7560 
   7561 
   7562 String* SharedFunctionInfo::DebugName() {
   7563   Object* n = name();
   7564   if (!n->IsString() || String::cast(n)->length() == 0) return inferred_name();
   7565   return String::cast(n);
   7566 }
   7567 
   7568 
   7569 bool SharedFunctionInfo::HasSourceCode() {
   7570   return !script()->IsUndefined() &&
   7571          !reinterpret_cast<Script*>(script())->source()->IsUndefined();
   7572 }
   7573 
   7574 
   7575 Handle<Object> SharedFunctionInfo::GetSourceCode() {
   7576   if (!HasSourceCode()) return GetIsolate()->factory()->undefined_value();
   7577   Handle<String> source(String::cast(Script::cast(script())->source()));
   7578   return SubString(source, start_position(), end_position());
   7579 }
   7580 
   7581 
   7582 int SharedFunctionInfo::SourceSize() {
   7583   return end_position() - start_position();
   7584 }
   7585 
   7586 
   7587 int SharedFunctionInfo::CalculateInstanceSize() {
   7588   int instance_size =
   7589       JSObject::kHeaderSize +
   7590       expected_nof_properties() * kPointerSize;
   7591   if (instance_size > JSObject::kMaxInstanceSize) {
   7592     instance_size = JSObject::kMaxInstanceSize;
   7593   }
   7594   return instance_size;
   7595 }
   7596 
   7597 
   7598 int SharedFunctionInfo::CalculateInObjectProperties() {
   7599   return (CalculateInstanceSize() - JSObject::kHeaderSize) / kPointerSize;
   7600 }
   7601 
   7602 
   7603 bool SharedFunctionInfo::CanGenerateInlineConstructor(Object* prototype) {
   7604   // Check the basic conditions for generating inline constructor code.
   7605   if (!FLAG_inline_new
   7606       || !has_only_simple_this_property_assignments()
   7607       || this_property_assignments_count() == 0) {
   7608     return false;
   7609   }
   7610 
   7611   // If the prototype is null inline constructors cause no problems.
   7612   if (!prototype->IsJSObject()) {
   7613     ASSERT(prototype->IsNull());
   7614     return true;
   7615   }
   7616 
   7617   Heap* heap = GetHeap();
   7618 
   7619   // Traverse the proposed prototype chain looking for setters for properties of
   7620   // the same names as are set by the inline constructor.
   7621   for (Object* obj = prototype;
   7622        obj != heap->null_value();
   7623        obj = obj->GetPrototype()) {
   7624     JSObject* js_object = JSObject::cast(obj);
   7625     for (int i = 0; i < this_property_assignments_count(); i++) {
   7626       LookupResult result(heap->isolate());
   7627       String* name = GetThisPropertyAssignmentName(i);
   7628       js_object->LocalLookupRealNamedProperty(name, &result);
   7629       if (result.IsFound() && result.type() == CALLBACKS) {
   7630         return false;
   7631       }
   7632     }
   7633   }
   7634 
   7635   return true;
   7636 }
   7637 
   7638 
   7639 void SharedFunctionInfo::ForbidInlineConstructor() {
   7640   set_compiler_hints(BooleanBit::set(compiler_hints(),
   7641                                      kHasOnlySimpleThisPropertyAssignments,
   7642                                      false));
   7643 }
   7644 
   7645 
   7646 void SharedFunctionInfo::SetThisPropertyAssignmentsInfo(
   7647     bool only_simple_this_property_assignments,
   7648     FixedArray* assignments) {
   7649   set_compiler_hints(BooleanBit::set(compiler_hints(),
   7650                                      kHasOnlySimpleThisPropertyAssignments,
   7651                                      only_simple_this_property_assignments));
   7652   set_this_property_assignments(assignments);
   7653   set_this_property_assignments_count(assignments->length() / 3);
   7654 }
   7655 
   7656 
   7657 void SharedFunctionInfo::ClearThisPropertyAssignmentsInfo() {
   7658   Heap* heap = GetHeap();
   7659   set_compiler_hints(BooleanBit::set(compiler_hints(),
   7660                                      kHasOnlySimpleThisPropertyAssignments,
   7661                                      false));
   7662   set_this_property_assignments(heap->undefined_value());
   7663   set_this_property_assignments_count(0);
   7664 }
   7665 
   7666 
   7667 String* SharedFunctionInfo::GetThisPropertyAssignmentName(int index) {
   7668   Object* obj = this_property_assignments();
   7669   ASSERT(obj->IsFixedArray());
   7670   ASSERT(index < this_property_assignments_count());
   7671   obj = FixedArray::cast(obj)->get(index * 3);
   7672   ASSERT(obj->IsString());
   7673   return String::cast(obj);
   7674 }
   7675 
   7676 
   7677 bool SharedFunctionInfo::IsThisPropertyAssignmentArgument(int index) {
   7678   Object* obj = this_property_assignments();
   7679   ASSERT(obj->IsFixedArray());
   7680   ASSERT(index < this_property_assignments_count());
   7681   obj = FixedArray::cast(obj)->get(index * 3 + 1);
   7682   return Smi::cast(obj)->value() != -1;
   7683 }
   7684 
   7685 
   7686 int SharedFunctionInfo::GetThisPropertyAssignmentArgument(int index) {
   7687   ASSERT(IsThisPropertyAssignmentArgument(index));
   7688   Object* obj =
   7689       FixedArray::cast(this_property_assignments())->get(index * 3 + 1);
   7690   return Smi::cast(obj)->value();
   7691 }
   7692 
   7693 
   7694 Object* SharedFunctionInfo::GetThisPropertyAssignmentConstant(int index) {
   7695   ASSERT(!IsThisPropertyAssignmentArgument(index));
   7696   Object* obj =
   7697       FixedArray::cast(this_property_assignments())->get(index * 3 + 2);
   7698   return obj;
   7699 }
   7700 
   7701 
   7702 // Support function for printing the source code to a StringStream
   7703 // without any allocation in the heap.
   7704 void SharedFunctionInfo::SourceCodePrint(StringStream* accumulator,
   7705                                          int max_length) {
   7706   // For some native functions there is no source.
   7707   if (!HasSourceCode()) {
   7708     accumulator->Add("<No Source>");
   7709     return;
   7710   }
   7711 
   7712   // Get the source for the script which this function came from.
   7713   // Don't use String::cast because we don't want more assertion errors while
   7714   // we are already creating a stack dump.
   7715   String* script_source =
   7716       reinterpret_cast<String*>(Script::cast(script())->source());
   7717 
   7718   if (!script_source->LooksValid()) {
   7719     accumulator->Add("<Invalid Source>");
   7720     return;
   7721   }
   7722 
   7723   if (!is_toplevel()) {
   7724     accumulator->Add("function ");
   7725     Object* name = this->name();
   7726     if (name->IsString() && String::cast(name)->length() > 0) {
   7727       accumulator->PrintName(name);
   7728     }
   7729   }
   7730 
   7731   int len = end_position() - start_position();
   7732   if (len <= max_length || max_length < 0) {
   7733     accumulator->Put(script_source, start_position(), end_position());
   7734   } else {
   7735     accumulator->Put(script_source,
   7736                      start_position(),
   7737                      start_position() + max_length);
   7738     accumulator->Add("...\n");
   7739   }
   7740 }
   7741 
   7742 
   7743 static bool IsCodeEquivalent(Code* code, Code* recompiled) {
   7744   if (code->instruction_size() != recompiled->instruction_size()) return false;
   7745   ByteArray* code_relocation = code->relocation_info();
   7746   ByteArray* recompiled_relocation = recompiled->relocation_info();
   7747   int length = code_relocation->length();
   7748   if (length != recompiled_relocation->length()) return false;
   7749   int compare = memcmp(code_relocation->GetDataStartAddress(),
   7750                        recompiled_relocation->GetDataStartAddress(),
   7751                        length);
   7752   return compare == 0;
   7753 }
   7754 
   7755 
   7756 void SharedFunctionInfo::EnableDeoptimizationSupport(Code* recompiled) {
   7757   ASSERT(!has_deoptimization_support());
   7758   AssertNoAllocation no_allocation;
   7759   Code* code = this->code();
   7760   if (IsCodeEquivalent(code, recompiled)) {
   7761     // Copy the deoptimization data from the recompiled code.
   7762     code->set_deoptimization_data(recompiled->deoptimization_data());
   7763     code->set_has_deoptimization_support(true);
   7764   } else {
   7765     // TODO(3025757): In case the recompiled isn't equivalent to the
   7766     // old code, we have to replace it. We should try to avoid this
   7767     // altogether because it flushes valuable type feedback by
   7768     // effectively resetting all IC state.
   7769     set_code(recompiled);
   7770   }
   7771   ASSERT(has_deoptimization_support());
   7772 }
   7773 
   7774 
   7775 void SharedFunctionInfo::DisableOptimization() {
   7776   // Disable optimization for the shared function info and mark the
   7777   // code as non-optimizable. The marker on the shared function info
   7778   // is there because we flush non-optimized code thereby loosing the
   7779   // non-optimizable information for the code. When the code is
   7780   // regenerated and set on the shared function info it is marked as
   7781   // non-optimizable if optimization is disabled for the shared
   7782   // function info.
   7783   set_optimization_disabled(true);
   7784   // Code should be the lazy compilation stub or else unoptimized.  If the
   7785   // latter, disable optimization for the code too.
   7786   ASSERT(code()->kind() == Code::FUNCTION || code()->kind() == Code::BUILTIN);
   7787   if (code()->kind() == Code::FUNCTION) {
   7788     code()->set_optimizable(false);
   7789   }
   7790   if (FLAG_trace_opt) {
   7791     PrintF("[disabled optimization for %s]\n", *DebugName()->ToCString());
   7792   }
   7793 }
   7794 
   7795 
   7796 bool SharedFunctionInfo::VerifyBailoutId(int id) {
   7797   ASSERT(id != AstNode::kNoNumber);
   7798   Code* unoptimized = code();
   7799   DeoptimizationOutputData* data =
   7800       DeoptimizationOutputData::cast(unoptimized->deoptimization_data());
   7801   unsigned ignore = Deoptimizer::GetOutputInfo(data, id, this);
   7802   USE(ignore);
   7803   return true;  // Return true if there was no ASSERT.
   7804 }
   7805 
   7806 
   7807 void SharedFunctionInfo::StartInobjectSlackTracking(Map* map) {
   7808   ASSERT(!IsInobjectSlackTrackingInProgress());
   7809 
   7810   if (!FLAG_clever_optimizations) return;
   7811 
   7812   // Only initiate the tracking the first time.
   7813   if (live_objects_may_exist()) return;
   7814   set_live_objects_may_exist(true);
   7815 
   7816   // No tracking during the snapshot construction phase.
   7817   if (Serializer::enabled()) return;
   7818 
   7819   if (map->unused_property_fields() == 0) return;
   7820 
   7821   // Nonzero counter is a leftover from the previous attempt interrupted
   7822   // by GC, keep it.
   7823   if (construction_count() == 0) {
   7824     set_construction_count(kGenerousAllocationCount);
   7825   }
   7826   set_initial_map(map);
   7827   Builtins* builtins = map->GetHeap()->isolate()->builtins();
   7828   ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubGeneric),
   7829             construct_stub());
   7830   set_construct_stub(builtins->builtin(Builtins::kJSConstructStubCountdown));
   7831 }
   7832 
   7833 
   7834 // Called from GC, hence reinterpret_cast and unchecked accessors.
   7835 void SharedFunctionInfo::DetachInitialMap() {
   7836   Map* map = reinterpret_cast<Map*>(initial_map());
   7837 
   7838   // Make the map remember to restore the link if it survives the GC.
   7839   map->set_bit_field2(
   7840       map->bit_field2() | (1 << Map::kAttachedToSharedFunctionInfo));
   7841 
   7842   // Undo state changes made by StartInobjectTracking (except the
   7843   // construction_count). This way if the initial map does not survive the GC
   7844   // then StartInobjectTracking will be called again the next time the
   7845   // constructor is called. The countdown will continue and (possibly after
   7846   // several more GCs) CompleteInobjectSlackTracking will eventually be called.
   7847   Heap* heap = map->GetHeap();
   7848   set_initial_map(heap->raw_unchecked_undefined_value());
   7849   Builtins* builtins = heap->isolate()->builtins();
   7850   ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubCountdown),
   7851             *RawField(this, kConstructStubOffset));
   7852   set_construct_stub(builtins->builtin(Builtins::kJSConstructStubGeneric));
   7853   // It is safe to clear the flag: it will be set again if the map is live.
   7854   set_live_objects_may_exist(false);
   7855 }
   7856 
   7857 
   7858 // Called from GC, hence reinterpret_cast and unchecked accessors.
   7859 void SharedFunctionInfo::AttachInitialMap(Map* map) {
   7860   map->set_bit_field2(
   7861       map->bit_field2() & ~(1 << Map::kAttachedToSharedFunctionInfo));
   7862 
   7863   // Resume inobject slack tracking.
   7864   set_initial_map(map);
   7865   Builtins* builtins = map->GetHeap()->isolate()->builtins();
   7866   ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubGeneric),
   7867             *RawField(this, kConstructStubOffset));
   7868   set_construct_stub(builtins->builtin(Builtins::kJSConstructStubCountdown));
   7869   // The map survived the gc, so there may be objects referencing it.
   7870   set_live_objects_may_exist(true);
   7871 }
   7872 
   7873 
   7874 void SharedFunctionInfo::ResetForNewContext(int new_ic_age) {
   7875   code()->ClearInlineCaches();
   7876   set_ic_age(new_ic_age);
   7877   if (code()->kind() == Code::FUNCTION) {
   7878     code()->set_profiler_ticks(0);
   7879     if (optimization_disabled() &&
   7880         opt_count() >= Compiler::kDefaultMaxOptCount) {
   7881       // Re-enable optimizations if they were disabled due to opt_count limit.
   7882       set_optimization_disabled(false);
   7883       code()->set_optimizable(true);
   7884     }
   7885     set_opt_count(0);
   7886   }
   7887 }
   7888 
   7889 
   7890 static void GetMinInobjectSlack(Map* map, void* data) {
   7891   int slack = map->unused_property_fields();
   7892   if (*reinterpret_cast<int*>(data) > slack) {
   7893     *reinterpret_cast<int*>(data) = slack;
   7894   }
   7895 }
   7896 
   7897 
   7898 static void ShrinkInstanceSize(Map* map, void* data) {
   7899   int slack = *reinterpret_cast<int*>(data);
   7900   map->set_inobject_properties(map->inobject_properties() - slack);
   7901   map->set_unused_property_fields(map->unused_property_fields() - slack);
   7902   map->set_instance_size(map->instance_size() - slack * kPointerSize);
   7903 
   7904   // Visitor id might depend on the instance size, recalculate it.
   7905   map->set_visitor_id(StaticVisitorBase::GetVisitorId(map));
   7906 }
   7907 
   7908 
   7909 void SharedFunctionInfo::CompleteInobjectSlackTracking() {
   7910   ASSERT(live_objects_may_exist() && IsInobjectSlackTrackingInProgress());
   7911   Map* map = Map::cast(initial_map());
   7912 
   7913   Heap* heap = map->GetHeap();
   7914   set_initial_map(heap->undefined_value());
   7915   Builtins* builtins = heap->isolate()->builtins();
   7916   ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubCountdown),
   7917             construct_stub());
   7918   set_construct_stub(builtins->builtin(Builtins::kJSConstructStubGeneric));
   7919 
   7920   int slack = map->unused_property_fields();
   7921   map->TraverseTransitionTree(&GetMinInobjectSlack, &slack);
   7922   if (slack != 0) {
   7923     // Resize the initial map and all maps in its transition tree.
   7924     map->TraverseTransitionTree(&ShrinkInstanceSize, &slack);
   7925 
   7926     // Give the correct expected_nof_properties to initial maps created later.
   7927     ASSERT(expected_nof_properties() >= slack);
   7928     set_expected_nof_properties(expected_nof_properties() - slack);
   7929   }
   7930 }
   7931 
   7932 
   7933 void SharedFunctionInfo::SharedFunctionInfoIterateBody(ObjectVisitor* v) {
   7934   v->VisitSharedFunctionInfo(this);
   7935   SharedFunctionInfo::BodyDescriptor::IterateBody(this, v);
   7936 }
   7937 
   7938 
   7939 #define DECLARE_TAG(ignore1, name, ignore2) name,
   7940 const char* const VisitorSynchronization::kTags[
   7941     VisitorSynchronization::kNumberOfSyncTags] = {
   7942   VISITOR_SYNCHRONIZATION_TAGS_LIST(DECLARE_TAG)
   7943 };
   7944 #undef DECLARE_TAG
   7945 
   7946 
   7947 #define DECLARE_TAG(ignore1, ignore2, name) name,
   7948 const char* const VisitorSynchronization::kTagNames[
   7949     VisitorSynchronization::kNumberOfSyncTags] = {
   7950   VISITOR_SYNCHRONIZATION_TAGS_LIST(DECLARE_TAG)
   7951 };
   7952 #undef DECLARE_TAG
   7953 
   7954 
   7955 void ObjectVisitor::VisitCodeTarget(RelocInfo* rinfo) {
   7956   ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode()));
   7957   Object* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
   7958   Object* old_target = target;
   7959   VisitPointer(&target);
   7960   CHECK_EQ(target, old_target);  // VisitPointer doesn't change Code* *target.
   7961 }
   7962 
   7963 
   7964 void ObjectVisitor::VisitCodeEntry(Address entry_address) {
   7965   Object* code = Code::GetObjectFromEntryAddress(entry_address);
   7966   Object* old_code = code;
   7967   VisitPointer(&code);
   7968   if (code != old_code) {
   7969     Memory::Address_at(entry_address) = reinterpret_cast<Code*>(code)->entry();
   7970   }
   7971 }
   7972 
   7973 
   7974 void ObjectVisitor::VisitGlobalPropertyCell(RelocInfo* rinfo) {
   7975   ASSERT(rinfo->rmode() == RelocInfo::GLOBAL_PROPERTY_CELL);
   7976   Object* cell = rinfo->target_cell();
   7977   Object* old_cell = cell;
   7978   VisitPointer(&cell);
   7979   if (cell != old_cell) {
   7980     rinfo->set_target_cell(reinterpret_cast<JSGlobalPropertyCell*>(cell));
   7981   }
   7982 }
   7983 
   7984 
   7985 void ObjectVisitor::VisitDebugTarget(RelocInfo* rinfo) {
   7986   ASSERT((RelocInfo::IsJSReturn(rinfo->rmode()) &&
   7987           rinfo->IsPatchedReturnSequence()) ||
   7988          (RelocInfo::IsDebugBreakSlot(rinfo->rmode()) &&
   7989           rinfo->IsPatchedDebugBreakSlotSequence()));
   7990   Object* target = Code::GetCodeFromTargetAddress(rinfo->call_address());
   7991   Object* old_target = target;
   7992   VisitPointer(&target);
   7993   CHECK_EQ(target, old_target);  // VisitPointer doesn't change Code* *target.
   7994 }
   7995 
   7996 void ObjectVisitor::VisitEmbeddedPointer(RelocInfo* rinfo) {
   7997   ASSERT(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT);
   7998   VisitPointer(rinfo->target_object_address());
   7999 }
   8000 
   8001 void ObjectVisitor::VisitExternalReference(RelocInfo* rinfo) {
   8002   Address* p = rinfo->target_reference_address();
   8003   VisitExternalReferences(p, p + 1);
   8004 }
   8005 
   8006 void Code::InvalidateRelocation() {
   8007   set_relocation_info(GetHeap()->empty_byte_array());
   8008 }
   8009 
   8010 
   8011 void Code::Relocate(intptr_t delta) {
   8012   for (RelocIterator it(this, RelocInfo::kApplyMask); !it.done(); it.next()) {
   8013     it.rinfo()->apply(delta);
   8014   }
   8015   CPU::FlushICache(instruction_start(), instruction_size());
   8016 }
   8017 
   8018 
   8019 void Code::CopyFrom(const CodeDesc& desc) {
   8020   ASSERT(Marking::Color(this) == Marking::WHITE_OBJECT);
   8021 
   8022   // copy code
   8023   memmove(instruction_start(), desc.buffer, desc.instr_size);
   8024 
   8025   // copy reloc info
   8026   memmove(relocation_start(),
   8027           desc.buffer + desc.buffer_size - desc.reloc_size,
   8028           desc.reloc_size);
   8029 
   8030   // unbox handles and relocate
   8031   intptr_t delta = instruction_start() - desc.buffer;
   8032   int mode_mask = RelocInfo::kCodeTargetMask |
   8033                   RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
   8034                   RelocInfo::ModeMask(RelocInfo::GLOBAL_PROPERTY_CELL) |
   8035                   RelocInfo::kApplyMask;
   8036   Assembler* origin = desc.origin;  // Needed to find target_object on X64.
   8037   for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
   8038     RelocInfo::Mode mode = it.rinfo()->rmode();
   8039     if (mode == RelocInfo::EMBEDDED_OBJECT) {
   8040       Handle<Object> p = it.rinfo()->target_object_handle(origin);
   8041       it.rinfo()->set_target_object(*p, SKIP_WRITE_BARRIER);
   8042     } else if (mode == RelocInfo::GLOBAL_PROPERTY_CELL) {
   8043       Handle<JSGlobalPropertyCell> cell  = it.rinfo()->target_cell_handle();
   8044       it.rinfo()->set_target_cell(*cell, SKIP_WRITE_BARRIER);
   8045     } else if (RelocInfo::IsCodeTarget(mode)) {
   8046       // rewrite code handles in inline cache targets to direct
   8047       // pointers to the first instruction in the code object
   8048       Handle<Object> p = it.rinfo()->target_object_handle(origin);
   8049       Code* code = Code::cast(*p);
   8050       it.rinfo()->set_target_address(code->instruction_start(),
   8051                                      SKIP_WRITE_BARRIER);
   8052     } else {
   8053       it.rinfo()->apply(delta);
   8054     }
   8055   }
   8056   CPU::FlushICache(instruction_start(), instruction_size());
   8057 }
   8058 
   8059 
   8060 // Locate the source position which is closest to the address in the code. This
   8061 // is using the source position information embedded in the relocation info.
   8062 // The position returned is relative to the beginning of the script where the
   8063 // source for this function is found.
   8064 int Code::SourcePosition(Address pc) {
   8065   int distance = kMaxInt;
   8066   int position = RelocInfo::kNoPosition;  // Initially no position found.
   8067   // Run through all the relocation info to find the best matching source
   8068   // position. All the code needs to be considered as the sequence of the
   8069   // instructions in the code does not necessarily follow the same order as the
   8070   // source.
   8071   RelocIterator it(this, RelocInfo::kPositionMask);
   8072   while (!it.done()) {
   8073     // Only look at positions after the current pc.
   8074     if (it.rinfo()->pc() < pc) {
   8075       // Get position and distance.
   8076 
   8077       int dist = static_cast<int>(pc - it.rinfo()->pc());
   8078       int pos = static_cast<int>(it.rinfo()->data());
   8079       // If this position is closer than the current candidate or if it has the
   8080       // same distance as the current candidate and the position is higher then
   8081       // this position is the new candidate.
   8082       if ((dist < distance) ||
   8083           (dist == distance && pos > position)) {
   8084         position = pos;
   8085         distance = dist;
   8086       }
   8087     }
   8088     it.next();
   8089   }
   8090   return position;
   8091 }
   8092 
   8093 
   8094 // Same as Code::SourcePosition above except it only looks for statement
   8095 // positions.
   8096 int Code::SourceStatementPosition(Address pc) {
   8097   // First find the position as close as possible using all position
   8098   // information.
   8099   int position = SourcePosition(pc);
   8100   // Now find the closest statement position before the position.
   8101   int statement_position = 0;
   8102   RelocIterator it(this, RelocInfo::kPositionMask);
   8103   while (!it.done()) {
   8104     if (RelocInfo::IsStatementPosition(it.rinfo()->rmode())) {
   8105       int p = static_cast<int>(it.rinfo()->data());
   8106       if (statement_position < p && p <= position) {
   8107         statement_position = p;
   8108       }
   8109     }
   8110     it.next();
   8111   }
   8112   return statement_position;
   8113 }
   8114 
   8115 
   8116 SafepointEntry Code::GetSafepointEntry(Address pc) {
   8117   SafepointTable table(this);
   8118   return table.FindEntry(pc);
   8119 }
   8120 
   8121 
   8122 void Code::SetNoStackCheckTable() {
   8123   // Indicate the absence of a stack-check table by a table start after the
   8124   // end of the instructions.  Table start must be aligned, so round up.
   8125   set_stack_check_table_offset(RoundUp(instruction_size(), kIntSize));
   8126 }
   8127 
   8128 
   8129 Map* Code::FindFirstMap() {
   8130   ASSERT(is_inline_cache_stub());
   8131   AssertNoAllocation no_allocation;
   8132   int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
   8133   for (RelocIterator it(this, mask); !it.done(); it.next()) {
   8134     RelocInfo* info = it.rinfo();
   8135     Object* object = info->target_object();
   8136     if (object->IsMap()) return Map::cast(object);
   8137   }
   8138   return NULL;
   8139 }
   8140 
   8141 
   8142 void Code::ClearInlineCaches() {
   8143   int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
   8144              RelocInfo::ModeMask(RelocInfo::CONSTRUCT_CALL) |
   8145              RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID) |
   8146              RelocInfo::ModeMask(RelocInfo::CODE_TARGET_CONTEXT);
   8147   for (RelocIterator it(this, mask); !it.done(); it.next()) {
   8148     RelocInfo* info = it.rinfo();
   8149     Code* target(Code::GetCodeFromTargetAddress(info->target_address()));
   8150     if (target->is_inline_cache_stub()) {
   8151       IC::Clear(info->pc());
   8152     }
   8153   }
   8154 }
   8155 
   8156 
   8157 #ifdef ENABLE_DISASSEMBLER
   8158 
   8159 void DeoptimizationInputData::DeoptimizationInputDataPrint(FILE* out) {
   8160   disasm::NameConverter converter;
   8161   int deopt_count = DeoptCount();
   8162   PrintF(out, "Deoptimization Input Data (deopt points = %d)\n", deopt_count);
   8163   if (0 == deopt_count) return;
   8164 
   8165   PrintF(out, "%6s  %6s  %6s %6s %12s\n", "index", "ast id", "argc", "pc",
   8166          FLAG_print_code_verbose ? "commands" : "");
   8167   for (int i = 0; i < deopt_count; i++) {
   8168     PrintF(out, "%6d  %6d  %6d %6d",
   8169            i,
   8170            AstId(i)->value(),
   8171            ArgumentsStackHeight(i)->value(),
   8172            Pc(i)->value());
   8173 
   8174     if (!FLAG_print_code_verbose) {
   8175       PrintF(out, "\n");
   8176       continue;
   8177     }
   8178     // Print details of the frame translation.
   8179     int translation_index = TranslationIndex(i)->value();
   8180     TranslationIterator iterator(TranslationByteArray(), translation_index);
   8181     Translation::Opcode opcode =
   8182         static_cast<Translation::Opcode>(iterator.Next());
   8183     ASSERT(Translation::BEGIN == opcode);
   8184     int frame_count = iterator.Next();
   8185     int jsframe_count = iterator.Next();
   8186     PrintF(out, "  %s {frame count=%d, js frame count=%d}\n",
   8187            Translation::StringFor(opcode),
   8188            frame_count,
   8189            jsframe_count);
   8190 
   8191     while (iterator.HasNext() &&
   8192            Translation::BEGIN !=
   8193            (opcode = static_cast<Translation::Opcode>(iterator.Next()))) {
   8194       PrintF(out, "%24s    %s ", "", Translation::StringFor(opcode));
   8195 
   8196       switch (opcode) {
   8197         case Translation::BEGIN:
   8198           UNREACHABLE();
   8199           break;
   8200 
   8201         case Translation::JS_FRAME: {
   8202           int ast_id = iterator.Next();
   8203           int function_id = iterator.Next();
   8204           JSFunction* function =
   8205               JSFunction::cast(LiteralArray()->get(function_id));
   8206           unsigned height = iterator.Next();
   8207           PrintF(out, "{ast_id=%d, function=", ast_id);
   8208           function->PrintName(out);
   8209           PrintF(out, ", height=%u}", height);
   8210           break;
   8211         }
   8212 
   8213         case Translation::ARGUMENTS_ADAPTOR_FRAME:
   8214         case Translation::CONSTRUCT_STUB_FRAME: {
   8215           int function_id = iterator.Next();
   8216           JSFunction* function =
   8217               JSFunction::cast(LiteralArray()->get(function_id));
   8218           unsigned height = iterator.Next();
   8219           PrintF(out, "{function=");
   8220           function->PrintName(out);
   8221           PrintF(out, ", height=%u}", height);
   8222           break;
   8223         }
   8224 
   8225         case Translation::DUPLICATE:
   8226           break;
   8227 
   8228         case Translation::REGISTER: {
   8229           int reg_code = iterator.Next();
   8230             PrintF(out, "{input=%s}", converter.NameOfCPURegister(reg_code));
   8231           break;
   8232         }
   8233 
   8234         case Translation::INT32_REGISTER: {
   8235           int reg_code = iterator.Next();
   8236           PrintF(out, "{input=%s}", converter.NameOfCPURegister(reg_code));
   8237           break;
   8238         }
   8239 
   8240         case Translation::DOUBLE_REGISTER: {
   8241           int reg_code = iterator.Next();
   8242           PrintF(out, "{input=%s}",
   8243                  DoubleRegister::AllocationIndexToString(reg_code));
   8244           break;
   8245         }
   8246 
   8247         case Translation::STACK_SLOT: {
   8248           int input_slot_index = iterator.Next();
   8249           PrintF(out, "{input=%d}", input_slot_index);
   8250           break;
   8251         }
   8252 
   8253         case Translation::INT32_STACK_SLOT: {
   8254           int input_slot_index = iterator.Next();
   8255           PrintF(out, "{input=%d}", input_slot_index);
   8256           break;
   8257         }
   8258 
   8259         case Translation::DOUBLE_STACK_SLOT: {
   8260           int input_slot_index = iterator.Next();
   8261           PrintF(out, "{input=%d}", input_slot_index);
   8262           break;
   8263         }
   8264 
   8265         case Translation::LITERAL: {
   8266           unsigned literal_index = iterator.Next();
   8267           PrintF(out, "{literal_id=%u}", literal_index);
   8268           break;
   8269         }
   8270 
   8271         case Translation::ARGUMENTS_OBJECT:
   8272           break;
   8273       }
   8274       PrintF(out, "\n");
   8275     }
   8276   }
   8277 }
   8278 
   8279 
   8280 void DeoptimizationOutputData::DeoptimizationOutputDataPrint(FILE* out) {
   8281   PrintF(out, "Deoptimization Output Data (deopt points = %d)\n",
   8282          this->DeoptPoints());
   8283   if (this->DeoptPoints() == 0) return;
   8284 
   8285   PrintF("%6s  %8s  %s\n", "ast id", "pc", "state");
   8286   for (int i = 0; i < this->DeoptPoints(); i++) {
   8287     int pc_and_state = this->PcAndState(i)->value();
   8288     PrintF("%6d  %8d  %s\n",
   8289            this->AstId(i)->value(),
   8290            FullCodeGenerator::PcField::decode(pc_and_state),
   8291            FullCodeGenerator::State2String(
   8292                FullCodeGenerator::StateField::decode(pc_and_state)));
   8293   }
   8294 }
   8295 
   8296 
   8297 // Identify kind of code.
   8298 const char* Code::Kind2String(Kind kind) {
   8299   switch (kind) {
   8300     case FUNCTION: return "FUNCTION";
   8301     case OPTIMIZED_FUNCTION: return "OPTIMIZED_FUNCTION";
   8302     case STUB: return "STUB";
   8303     case BUILTIN: return "BUILTIN";
   8304     case LOAD_IC: return "LOAD_IC";
   8305     case KEYED_LOAD_IC: return "KEYED_LOAD_IC";
   8306     case STORE_IC: return "STORE_IC";
   8307     case KEYED_STORE_IC: return "KEYED_STORE_IC";
   8308     case CALL_IC: return "CALL_IC";
   8309     case KEYED_CALL_IC: return "KEYED_CALL_IC";
   8310     case UNARY_OP_IC: return "UNARY_OP_IC";
   8311     case BINARY_OP_IC: return "BINARY_OP_IC";
   8312     case COMPARE_IC: return "COMPARE_IC";
   8313     case TO_BOOLEAN_IC: return "TO_BOOLEAN_IC";
   8314   }
   8315   UNREACHABLE();
   8316   return NULL;
   8317 }
   8318 
   8319 
   8320 const char* Code::ICState2String(InlineCacheState state) {
   8321   switch (state) {
   8322     case UNINITIALIZED: return "UNINITIALIZED";
   8323     case PREMONOMORPHIC: return "PREMONOMORPHIC";
   8324     case MONOMORPHIC: return "MONOMORPHIC";
   8325     case MONOMORPHIC_PROTOTYPE_FAILURE: return "MONOMORPHIC_PROTOTYPE_FAILURE";
   8326     case MEGAMORPHIC: return "MEGAMORPHIC";
   8327     case DEBUG_BREAK: return "DEBUG_BREAK";
   8328     case DEBUG_PREPARE_STEP_IN: return "DEBUG_PREPARE_STEP_IN";
   8329   }
   8330   UNREACHABLE();
   8331   return NULL;
   8332 }
   8333 
   8334 
   8335 const char* Code::PropertyType2String(PropertyType type) {
   8336   switch (type) {
   8337     case NORMAL: return "NORMAL";
   8338     case FIELD: return "FIELD";
   8339     case CONSTANT_FUNCTION: return "CONSTANT_FUNCTION";
   8340     case CALLBACKS: return "CALLBACKS";
   8341     case HANDLER: return "HANDLER";
   8342     case INTERCEPTOR: return "INTERCEPTOR";
   8343     case MAP_TRANSITION: return "MAP_TRANSITION";
   8344     case ELEMENTS_TRANSITION: return "ELEMENTS_TRANSITION";
   8345     case CONSTANT_TRANSITION: return "CONSTANT_TRANSITION";
   8346     case NULL_DESCRIPTOR: return "NULL_DESCRIPTOR";
   8347   }
   8348   UNREACHABLE();  // keep the compiler happy
   8349   return NULL;
   8350 }
   8351 
   8352 
   8353 void Code::PrintExtraICState(FILE* out, Kind kind, ExtraICState extra) {
   8354   const char* name = NULL;
   8355   switch (kind) {
   8356     case CALL_IC:
   8357       if (extra == STRING_INDEX_OUT_OF_BOUNDS) {
   8358         name = "STRING_INDEX_OUT_OF_BOUNDS";
   8359       }
   8360       break;
   8361     case STORE_IC:
   8362     case KEYED_STORE_IC:
   8363       if (extra == kStrictMode) {
   8364         name = "STRICT";
   8365       }
   8366       break;
   8367     default:
   8368       break;
   8369   }
   8370   if (name != NULL) {
   8371     PrintF(out, "extra_ic_state = %s\n", name);
   8372   } else {
   8373     PrintF(out, "extra_ic_state = %d\n", extra);
   8374   }
   8375 }
   8376 
   8377 
   8378 void Code::Disassemble(const char* name, FILE* out) {
   8379   PrintF(out, "kind = %s\n", Kind2String(kind()));
   8380   if (is_inline_cache_stub()) {
   8381     PrintF(out, "ic_state = %s\n", ICState2String(ic_state()));
   8382     PrintExtraICState(out, kind(), extra_ic_state());
   8383     if (ic_state() == MONOMORPHIC) {
   8384       PrintF(out, "type = %s\n", PropertyType2String(type()));
   8385     }
   8386     if (is_call_stub() || is_keyed_call_stub()) {
   8387       PrintF(out, "argc = %d\n", arguments_count());
   8388     }
   8389   }
   8390   if ((name != NULL) && (name[0] != '\0')) {
   8391     PrintF(out, "name = %s\n", name);
   8392   }
   8393   if (kind() == OPTIMIZED_FUNCTION) {
   8394     PrintF(out, "stack_slots = %d\n", stack_slots());
   8395   }
   8396 
   8397   PrintF(out, "Instructions (size = %d)\n", instruction_size());
   8398   Disassembler::Decode(out, this);
   8399   PrintF(out, "\n");
   8400 
   8401   if (kind() == FUNCTION) {
   8402     DeoptimizationOutputData* data =
   8403         DeoptimizationOutputData::cast(this->deoptimization_data());
   8404     data->DeoptimizationOutputDataPrint(out);
   8405   } else if (kind() == OPTIMIZED_FUNCTION) {
   8406     DeoptimizationInputData* data =
   8407         DeoptimizationInputData::cast(this->deoptimization_data());
   8408     data->DeoptimizationInputDataPrint(out);
   8409   }
   8410   PrintF("\n");
   8411 
   8412   if (kind() == OPTIMIZED_FUNCTION) {
   8413     SafepointTable table(this);
   8414     PrintF(out, "Safepoints (size = %u)\n", table.size());
   8415     for (unsigned i = 0; i < table.length(); i++) {
   8416       unsigned pc_offset = table.GetPcOffset(i);
   8417       PrintF(out, "%p  %4d  ", (instruction_start() + pc_offset), pc_offset);
   8418       table.PrintEntry(i);
   8419       PrintF(out, " (sp -> fp)");
   8420       SafepointEntry entry = table.GetEntry(i);
   8421       if (entry.deoptimization_index() != Safepoint::kNoDeoptimizationIndex) {
   8422         PrintF(out, "  %6d", entry.deoptimization_index());
   8423       } else {
   8424         PrintF(out, "  <none>");
   8425       }
   8426       if (entry.argument_count() > 0) {
   8427         PrintF(out, " argc: %d", entry.argument_count());
   8428       }
   8429       PrintF(out, "\n");
   8430     }
   8431     PrintF(out, "\n");
   8432   } else if (kind() == FUNCTION) {
   8433     unsigned offset = stack_check_table_offset();
   8434     // If there is no stack check table, the "table start" will at or after
   8435     // (due to alignment) the end of the instruction stream.
   8436     if (static_cast<int>(offset) < instruction_size()) {
   8437       unsigned* address =
   8438           reinterpret_cast<unsigned*>(instruction_start() + offset);
   8439       unsigned length = address[0];
   8440       PrintF(out, "Stack checks (size = %u)\n", length);
   8441       PrintF(out, "ast_id  pc_offset\n");
   8442       for (unsigned i = 0; i < length; ++i) {
   8443         unsigned index = (2 * i) + 1;
   8444         PrintF(out, "%6u  %9u\n", address[index], address[index + 1]);
   8445       }
   8446       PrintF(out, "\n");
   8447     }
   8448   }
   8449 
   8450   PrintF("RelocInfo (size = %d)\n", relocation_size());
   8451   for (RelocIterator it(this); !it.done(); it.next()) it.rinfo()->Print(out);
   8452   PrintF(out, "\n");
   8453 }
   8454 #endif  // ENABLE_DISASSEMBLER
   8455 
   8456 
   8457 MaybeObject* JSObject::SetFastElementsCapacityAndLength(
   8458     int capacity,
   8459     int length,
   8460     SetFastElementsCapacityMode set_capacity_mode) {
   8461   Heap* heap = GetHeap();
   8462   // We should never end in here with a pixel or external array.
   8463   ASSERT(!HasExternalArrayElements());
   8464 
   8465   // Allocate a new fast elements backing store.
   8466   FixedArray* new_elements;
   8467   { MaybeObject* maybe = heap->AllocateFixedArrayWithHoles(capacity);
   8468     if (!maybe->To(&new_elements)) return maybe;
   8469   }
   8470 
   8471   // Find the new map to use for this object if there is a map change.
   8472   Map* new_map = NULL;
   8473   if (elements()->map() != heap->non_strict_arguments_elements_map()) {
   8474     // The resized array has FAST_SMI_ONLY_ELEMENTS if the capacity mode forces
   8475     // it, or if it's allowed and the old elements array contained only SMIs.
   8476     bool has_fast_smi_only_elements =
   8477         (set_capacity_mode == kForceSmiOnlyElements) ||
   8478         ((set_capacity_mode == kAllowSmiOnlyElements) &&
   8479          (elements()->map()->has_fast_smi_only_elements() ||
   8480           elements() == heap->empty_fixed_array()));
   8481     ElementsKind elements_kind = has_fast_smi_only_elements
   8482         ? FAST_SMI_ONLY_ELEMENTS
   8483         : FAST_ELEMENTS;
   8484     MaybeObject* maybe = GetElementsTransitionMap(GetIsolate(), elements_kind);
   8485     if (!maybe->To(&new_map)) return maybe;
   8486   }
   8487 
   8488   FixedArrayBase* old_elements = elements();
   8489   ElementsKind elements_kind = GetElementsKind();
   8490   ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind);
   8491   ElementsKind to_kind = (elements_kind == FAST_SMI_ONLY_ELEMENTS)
   8492       ? FAST_SMI_ONLY_ELEMENTS
   8493       : FAST_ELEMENTS;
   8494   //  int copy_size = Min(old_elements_raw->length(), new_elements->length());
   8495   accessor->CopyElements(this, new_elements, to_kind);
   8496   if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) {
   8497     set_map_and_elements(new_map, new_elements);
   8498   } else {
   8499     FixedArray* parameter_map = FixedArray::cast(old_elements);
   8500     parameter_map->set(1, new_elements);
   8501   }
   8502 
   8503   if (FLAG_trace_elements_transitions) {
   8504     PrintElementsTransition(stdout, elements_kind, old_elements,
   8505                             GetElementsKind(), new_elements);
   8506   }
   8507 
   8508   // Update the length if necessary.
   8509   if (IsJSArray()) {
   8510     JSArray::cast(this)->set_length(Smi::FromInt(length));
   8511   }
   8512 
   8513   return new_elements;
   8514 }
   8515 
   8516 
   8517 MaybeObject* JSObject::SetFastDoubleElementsCapacityAndLength(
   8518     int capacity,
   8519     int length) {
   8520   Heap* heap = GetHeap();
   8521   // We should never end in here with a pixel or external array.
   8522   ASSERT(!HasExternalArrayElements());
   8523 
   8524   FixedArrayBase* elems;
   8525   { MaybeObject* maybe_obj =
   8526         heap->AllocateUninitializedFixedDoubleArray(capacity);
   8527     if (!maybe_obj->To(&elems)) return maybe_obj;
   8528   }
   8529 
   8530   Map* new_map;
   8531   { MaybeObject* maybe_obj =
   8532         GetElementsTransitionMap(heap->isolate(), FAST_DOUBLE_ELEMENTS);
   8533     if (!maybe_obj->To(&new_map)) return maybe_obj;
   8534   }
   8535 
   8536   FixedArrayBase* old_elements = elements();
   8537   ElementsKind elements_kind = GetElementsKind();
   8538   ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind);
   8539   accessor->CopyElements(this, elems, FAST_DOUBLE_ELEMENTS);
   8540   if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) {
   8541     set_map_and_elements(new_map, elems);
   8542   } else {
   8543     FixedArray* parameter_map = FixedArray::cast(old_elements);
   8544     parameter_map->set(1, elems);
   8545   }
   8546 
   8547   if (FLAG_trace_elements_transitions) {
   8548     PrintElementsTransition(stdout, elements_kind, old_elements,
   8549                             FAST_DOUBLE_ELEMENTS, elems);
   8550   }
   8551 
   8552   if (IsJSArray()) {
   8553     JSArray::cast(this)->set_length(Smi::FromInt(length));
   8554   }
   8555 
   8556   return this;
   8557 }
   8558 
   8559 
   8560 MaybeObject* JSArray::Initialize(int capacity) {
   8561   Heap* heap = GetHeap();
   8562   ASSERT(capacity >= 0);
   8563   set_length(Smi::FromInt(0));
   8564   FixedArray* new_elements;
   8565   if (capacity == 0) {
   8566     new_elements = heap->empty_fixed_array();
   8567   } else {
   8568     MaybeObject* maybe_obj = heap->AllocateFixedArrayWithHoles(capacity);
   8569     if (!maybe_obj->To(&new_elements)) return maybe_obj;
   8570   }
   8571   set_elements(new_elements);
   8572   return this;
   8573 }
   8574 
   8575 
   8576 void JSArray::Expand(int required_size) {
   8577   GetIsolate()->factory()->SetElementsCapacityAndLength(
   8578       Handle<JSArray>(this), required_size, required_size);
   8579 }
   8580 
   8581 
   8582 MaybeObject* JSArray::SetElementsLength(Object* len) {
   8583   // We should never end in here with a pixel or external array.
   8584   ASSERT(AllowsSetElementsLength());
   8585   return GetElementsAccessor()->SetLength(this, len);
   8586 }
   8587 
   8588 
   8589 Object* Map::GetPrototypeTransition(Object* prototype) {
   8590   FixedArray* cache = prototype_transitions();
   8591   int number_of_transitions = NumberOfProtoTransitions();
   8592   const int proto_offset =
   8593       kProtoTransitionHeaderSize + kProtoTransitionPrototypeOffset;
   8594   const int map_offset = kProtoTransitionHeaderSize + kProtoTransitionMapOffset;
   8595   const int step = kProtoTransitionElementsPerEntry;
   8596   for (int i = 0; i < number_of_transitions; i++) {
   8597     if (cache->get(proto_offset + i * step) == prototype) {
   8598       Object* map = cache->get(map_offset + i * step);
   8599       ASSERT(map->IsMap());
   8600       return map;
   8601     }
   8602   }
   8603   return NULL;
   8604 }
   8605 
   8606 
   8607 MaybeObject* Map::PutPrototypeTransition(Object* prototype, Map* map) {
   8608   ASSERT(map->IsMap());
   8609   ASSERT(HeapObject::cast(prototype)->map()->IsMap());
   8610   // Don't cache prototype transition if this map is shared.
   8611   if (is_shared() || !FLAG_cache_prototype_transitions) return this;
   8612 
   8613   FixedArray* cache = prototype_transitions();
   8614 
   8615   const int step = kProtoTransitionElementsPerEntry;
   8616   const int header = kProtoTransitionHeaderSize;
   8617 
   8618   int capacity = (cache->length() - header) / step;
   8619 
   8620   int transitions = NumberOfProtoTransitions() + 1;
   8621 
   8622   if (transitions > capacity) {
   8623     if (capacity > kMaxCachedPrototypeTransitions) return this;
   8624 
   8625     FixedArray* new_cache;
   8626     // Grow array by factor 2 over and above what we need.
   8627     { MaybeObject* maybe_cache =
   8628           GetHeap()->AllocateFixedArray(transitions * 2 * step + header);
   8629       if (!maybe_cache->To(&new_cache)) return maybe_cache;
   8630     }
   8631 
   8632     for (int i = 0; i < capacity * step; i++) {
   8633       new_cache->set(i + header, cache->get(i + header));
   8634     }
   8635     cache = new_cache;
   8636     set_prototype_transitions(cache);
   8637   }
   8638 
   8639   int last = transitions - 1;
   8640 
   8641   cache->set(header + last * step + kProtoTransitionPrototypeOffset, prototype);
   8642   cache->set(header + last * step + kProtoTransitionMapOffset, map);
   8643   SetNumberOfProtoTransitions(transitions);
   8644 
   8645   return cache;
   8646 }
   8647 
   8648 
   8649 MaybeObject* JSReceiver::SetPrototype(Object* value,
   8650                                       bool skip_hidden_prototypes) {
   8651 #ifdef DEBUG
   8652   int size = Size();
   8653 #endif
   8654 
   8655   Heap* heap = GetHeap();
   8656   // Silently ignore the change if value is not a JSObject or null.
   8657   // SpiderMonkey behaves this way.
   8658   if (!value->IsJSReceiver() && !value->IsNull()) return value;
   8659 
   8660   // From 8.6.2 Object Internal Methods
   8661   // ...
   8662   // In addition, if [[Extensible]] is false the value of the [[Class]] and
   8663   // [[Prototype]] internal properties of the object may not be modified.
   8664   // ...
   8665   // Implementation specific extensions that modify [[Class]], [[Prototype]]
   8666   // or [[Extensible]] must not violate the invariants defined in the preceding
   8667   // paragraph.
   8668   if (!this->map()->is_extensible()) {
   8669     HandleScope scope(heap->isolate());
   8670     Handle<Object> handle(this, heap->isolate());
   8671     return heap->isolate()->Throw(
   8672         *FACTORY->NewTypeError("non_extensible_proto",
   8673                                HandleVector<Object>(&handle, 1)));
   8674   }
   8675 
   8676   // Before we can set the prototype we need to be sure
   8677   // prototype cycles are prevented.
   8678   // It is sufficient to validate that the receiver is not in the new prototype
   8679   // chain.
   8680   for (Object* pt = value; pt != heap->null_value(); pt = pt->GetPrototype()) {
   8681     if (JSReceiver::cast(pt) == this) {
   8682       // Cycle detected.
   8683       HandleScope scope(heap->isolate());
   8684       return heap->isolate()->Throw(
   8685           *FACTORY->NewError("cyclic_proto", HandleVector<Object>(NULL, 0)));
   8686     }
   8687   }
   8688 
   8689   JSReceiver* real_receiver = this;
   8690 
   8691   if (skip_hidden_prototypes) {
   8692     // Find the first object in the chain whose prototype object is not
   8693     // hidden and set the new prototype on that object.
   8694     Object* current_proto = real_receiver->GetPrototype();
   8695     while (current_proto->IsJSObject() &&
   8696           JSReceiver::cast(current_proto)->map()->is_hidden_prototype()) {
   8697       real_receiver = JSReceiver::cast(current_proto);
   8698       current_proto = current_proto->GetPrototype();
   8699     }
   8700   }
   8701 
   8702   // Set the new prototype of the object.
   8703   Map* map = real_receiver->map();
   8704 
   8705   // Nothing to do if prototype is already set.
   8706   if (map->prototype() == value) return value;
   8707 
   8708   Object* new_map = map->GetPrototypeTransition(value);
   8709   if (new_map == NULL) {
   8710     { MaybeObject* maybe_new_map = map->CopyDropTransitions();
   8711       if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
   8712     }
   8713 
   8714     { MaybeObject* maybe_new_cache =
   8715           map->PutPrototypeTransition(value, Map::cast(new_map));
   8716       if (maybe_new_cache->IsFailure()) return maybe_new_cache;
   8717     }
   8718 
   8719     Map::cast(new_map)->set_prototype(value);
   8720   }
   8721   ASSERT(Map::cast(new_map)->prototype() == value);
   8722   real_receiver->set_map(Map::cast(new_map));
   8723 
   8724   heap->ClearInstanceofCache();
   8725   ASSERT(size == Size());
   8726   return value;
   8727 }
   8728 
   8729 
   8730 MaybeObject* JSObject::EnsureCanContainElements(Arguments* args,
   8731                                                 uint32_t first_arg,
   8732                                                 uint32_t arg_count,
   8733                                                 EnsureElementsMode mode) {
   8734   // Elements in |Arguments| are ordered backwards (because they're on the
   8735   // stack), but the method that's called here iterates over them in forward
   8736   // direction.
   8737   return EnsureCanContainElements(
   8738       args->arguments() - first_arg - (arg_count - 1),
   8739       arg_count, mode);
   8740 }
   8741 
   8742 
   8743 bool JSObject::HasElementWithInterceptor(JSReceiver* receiver, uint32_t index) {
   8744   Isolate* isolate = GetIsolate();
   8745   // Make sure that the top context does not change when doing
   8746   // callbacks or interceptor calls.
   8747   AssertNoContextChange ncc;
   8748   HandleScope scope(isolate);
   8749   Handle<InterceptorInfo> interceptor(GetIndexedInterceptor());
   8750   Handle<JSReceiver> receiver_handle(receiver);
   8751   Handle<JSObject> holder_handle(this);
   8752   CustomArguments args(isolate, interceptor->data(), receiver, this);
   8753   v8::AccessorInfo info(args.end());
   8754   if (!interceptor->query()->IsUndefined()) {
   8755     v8::IndexedPropertyQuery query =
   8756         v8::ToCData<v8::IndexedPropertyQuery>(interceptor->query());
   8757     LOG(isolate,
   8758         ApiIndexedPropertyAccess("interceptor-indexed-has", this, index));
   8759     v8::Handle<v8::Integer> result;
   8760     {
   8761       // Leaving JavaScript.
   8762       VMState state(isolate, EXTERNAL);
   8763       result = query(index, info);
   8764     }
   8765     if (!result.IsEmpty()) {
   8766       ASSERT(result->IsInt32());
   8767       return true;  // absence of property is signaled by empty handle.
   8768     }
   8769   } else if (!interceptor->getter()->IsUndefined()) {
   8770     v8::IndexedPropertyGetter getter =
   8771         v8::ToCData<v8::IndexedPropertyGetter>(interceptor->getter());
   8772     LOG(isolate,
   8773         ApiIndexedPropertyAccess("interceptor-indexed-has-get", this, index));
   8774     v8::Handle<v8::Value> result;
   8775     {
   8776       // Leaving JavaScript.
   8777       VMState state(isolate, EXTERNAL);
   8778       result = getter(index, info);
   8779     }
   8780     if (!result.IsEmpty()) return true;
   8781   }
   8782 
   8783   if (holder_handle->GetElementsAccessor()->HasElement(
   8784           *receiver_handle, *holder_handle, index)) {
   8785     return true;
   8786   }
   8787 
   8788   if (holder_handle->IsStringObjectWithCharacterAt(index)) return true;
   8789   Object* pt = holder_handle->GetPrototype();
   8790   if (pt->IsJSProxy()) {
   8791     // We need to follow the spec and simulate a call to [[GetOwnProperty]].
   8792     return JSProxy::cast(pt)->GetElementAttributeWithHandler(
   8793         receiver, index) != ABSENT;
   8794   }
   8795   if (pt->IsNull()) return false;
   8796   return JSObject::cast(pt)->HasElementWithReceiver(*receiver_handle, index);
   8797 }
   8798 
   8799 
   8800 JSObject::LocalElementType JSObject::HasLocalElement(uint32_t index) {
   8801   // Check access rights if needed.
   8802   if (IsAccessCheckNeeded()) {
   8803     Heap* heap = GetHeap();
   8804     if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) {
   8805       heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
   8806       return UNDEFINED_ELEMENT;
   8807     }
   8808   }
   8809 
   8810   if (IsJSGlobalProxy()) {
   8811     Object* proto = GetPrototype();
   8812     if (proto->IsNull()) return UNDEFINED_ELEMENT;
   8813     ASSERT(proto->IsJSGlobalObject());
   8814     return JSObject::cast(proto)->HasLocalElement(index);
   8815   }
   8816 
   8817   // Check for lookup interceptor
   8818   if (HasIndexedInterceptor()) {
   8819     return HasElementWithInterceptor(this, index) ? INTERCEPTED_ELEMENT
   8820                                                   : UNDEFINED_ELEMENT;
   8821   }
   8822 
   8823   // Handle [] on String objects.
   8824   if (this->IsStringObjectWithCharacterAt(index)) {
   8825     return STRING_CHARACTER_ELEMENT;
   8826   }
   8827 
   8828   switch (GetElementsKind()) {
   8829     case FAST_SMI_ONLY_ELEMENTS:
   8830     case FAST_ELEMENTS: {
   8831       uint32_t length = IsJSArray() ?
   8832           static_cast<uint32_t>
   8833               (Smi::cast(JSArray::cast(this)->length())->value()) :
   8834           static_cast<uint32_t>(FixedArray::cast(elements())->length());
   8835       if ((index < length) &&
   8836           !FixedArray::cast(elements())->get(index)->IsTheHole()) {
   8837         return FAST_ELEMENT;
   8838       }
   8839       break;
   8840     }
   8841     case FAST_DOUBLE_ELEMENTS: {
   8842       uint32_t length = IsJSArray() ?
   8843           static_cast<uint32_t>
   8844               (Smi::cast(JSArray::cast(this)->length())->value()) :
   8845           static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length());
   8846       if ((index < length) &&
   8847           !FixedDoubleArray::cast(elements())->is_the_hole(index)) {
   8848         return FAST_ELEMENT;
   8849       }
   8850       break;
   8851     }
   8852     case EXTERNAL_PIXEL_ELEMENTS: {
   8853       ExternalPixelArray* pixels = ExternalPixelArray::cast(elements());
   8854       if (index < static_cast<uint32_t>(pixels->length())) return FAST_ELEMENT;
   8855       break;
   8856     }
   8857     case EXTERNAL_BYTE_ELEMENTS:
   8858     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
   8859     case EXTERNAL_SHORT_ELEMENTS:
   8860     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
   8861     case EXTERNAL_INT_ELEMENTS:
   8862     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
   8863     case EXTERNAL_FLOAT_ELEMENTS:
   8864     case EXTERNAL_DOUBLE_ELEMENTS: {
   8865       ExternalArray* array = ExternalArray::cast(elements());
   8866       if (index < static_cast<uint32_t>(array->length())) return FAST_ELEMENT;
   8867       break;
   8868     }
   8869     case DICTIONARY_ELEMENTS: {
   8870       if (element_dictionary()->FindEntry(index) !=
   8871           SeededNumberDictionary::kNotFound) {
   8872         return DICTIONARY_ELEMENT;
   8873       }
   8874       break;
   8875     }
   8876     case NON_STRICT_ARGUMENTS_ELEMENTS: {
   8877       // Aliased parameters and non-aliased elements in a fast backing store
   8878       // behave as FAST_ELEMENT.  Non-aliased elements in a dictionary
   8879       // backing store behave as DICTIONARY_ELEMENT.
   8880       FixedArray* parameter_map = FixedArray::cast(elements());
   8881       uint32_t length = parameter_map->length();
   8882       Object* probe =
   8883           index < (length - 2) ? parameter_map->get(index + 2) : NULL;
   8884       if (probe != NULL && !probe->IsTheHole()) return FAST_ELEMENT;
   8885       // If not aliased, check the arguments.
   8886       FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
   8887       if (arguments->IsDictionary()) {
   8888         SeededNumberDictionary* dictionary =
   8889             SeededNumberDictionary::cast(arguments);
   8890         if (dictionary->FindEntry(index) != SeededNumberDictionary::kNotFound) {
   8891           return DICTIONARY_ELEMENT;
   8892         }
   8893       } else {
   8894         length = arguments->length();
   8895         probe = (index < length) ? arguments->get(index) : NULL;
   8896         if (probe != NULL && !probe->IsTheHole()) return FAST_ELEMENT;
   8897       }
   8898       break;
   8899     }
   8900   }
   8901 
   8902   return UNDEFINED_ELEMENT;
   8903 }
   8904 
   8905 
   8906 bool JSObject::HasElementWithReceiver(JSReceiver* receiver, uint32_t index) {
   8907   // Check access rights if needed.
   8908   if (IsAccessCheckNeeded()) {
   8909     Heap* heap = GetHeap();
   8910     if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) {
   8911       heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
   8912       return false;
   8913     }
   8914   }
   8915 
   8916   // Check for lookup interceptor
   8917   if (HasIndexedInterceptor()) {
   8918     return HasElementWithInterceptor(receiver, index);
   8919   }
   8920 
   8921   ElementsAccessor* accessor = GetElementsAccessor();
   8922   if (accessor->HasElement(receiver, this, index)) {
   8923     return true;
   8924   }
   8925 
   8926   // Handle [] on String objects.
   8927   if (this->IsStringObjectWithCharacterAt(index)) return true;
   8928 
   8929   Object* pt = GetPrototype();
   8930   if (pt->IsNull()) return false;
   8931   if (pt->IsJSProxy()) {
   8932     // We need to follow the spec and simulate a call to [[GetOwnProperty]].
   8933     return JSProxy::cast(pt)->GetElementAttributeWithHandler(
   8934         receiver, index) != ABSENT;
   8935   }
   8936   return JSObject::cast(pt)->HasElementWithReceiver(receiver, index);
   8937 }
   8938 
   8939 
   8940 MaybeObject* JSObject::SetElementWithInterceptor(uint32_t index,
   8941                                                  Object* value,
   8942                                                  PropertyAttributes attributes,
   8943                                                  StrictModeFlag strict_mode,
   8944                                                  bool check_prototype,
   8945                                                  SetPropertyMode set_mode) {
   8946   Isolate* isolate = GetIsolate();
   8947   // Make sure that the top context does not change when doing
   8948   // callbacks or interceptor calls.
   8949   AssertNoContextChange ncc;
   8950   HandleScope scope(isolate);
   8951   Handle<InterceptorInfo> interceptor(GetIndexedInterceptor());
   8952   Handle<JSObject> this_handle(this);
   8953   Handle<Object> value_handle(value, isolate);
   8954   if (!interceptor->setter()->IsUndefined()) {
   8955     v8::IndexedPropertySetter setter =
   8956         v8::ToCData<v8::IndexedPropertySetter>(interceptor->setter());
   8957     LOG(isolate,
   8958         ApiIndexedPropertyAccess("interceptor-indexed-set", this, index));
   8959     CustomArguments args(isolate, interceptor->data(), this, this);
   8960     v8::AccessorInfo info(args.end());
   8961     v8::Handle<v8::Value> result;
   8962     {
   8963       // Leaving JavaScript.
   8964       VMState state(isolate, EXTERNAL);
   8965       result = setter(index, v8::Utils::ToLocal(value_handle), info);
   8966     }
   8967     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   8968     if (!result.IsEmpty()) return *value_handle;
   8969   }
   8970   MaybeObject* raw_result =
   8971       this_handle->SetElementWithoutInterceptor(index,
   8972                                                 *value_handle,
   8973                                                 attributes,
   8974                                                 strict_mode,
   8975                                                 check_prototype,
   8976                                                 set_mode);
   8977   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   8978   return raw_result;
   8979 }
   8980 
   8981 
   8982 MaybeObject* JSObject::GetElementWithCallback(Object* receiver,
   8983                                               Object* structure,
   8984                                               uint32_t index,
   8985                                               Object* holder) {
   8986   Isolate* isolate = GetIsolate();
   8987   ASSERT(!structure->IsForeign());
   8988 
   8989   // api style callbacks.
   8990   if (structure->IsAccessorInfo()) {
   8991     Handle<AccessorInfo> data(AccessorInfo::cast(structure));
   8992     Object* fun_obj = data->getter();
   8993     v8::AccessorGetter call_fun = v8::ToCData<v8::AccessorGetter>(fun_obj);
   8994     HandleScope scope(isolate);
   8995     Handle<JSObject> self(JSObject::cast(receiver));
   8996     Handle<JSObject> holder_handle(JSObject::cast(holder));
   8997     Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
   8998     Handle<String> key = isolate->factory()->NumberToString(number);
   8999     LOG(isolate, ApiNamedPropertyAccess("load", *self, *key));
   9000     CustomArguments args(isolate, data->data(), *self, *holder_handle);
   9001     v8::AccessorInfo info(args.end());
   9002     v8::Handle<v8::Value> result;
   9003     {
   9004       // Leaving JavaScript.
   9005       VMState state(isolate, EXTERNAL);
   9006       result = call_fun(v8::Utils::ToLocal(key), info);
   9007     }
   9008     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   9009     if (result.IsEmpty()) return isolate->heap()->undefined_value();
   9010     return *v8::Utils::OpenHandle(*result);
   9011   }
   9012 
   9013   // __defineGetter__ callback
   9014   if (structure->IsAccessorPair()) {
   9015     Object* getter = AccessorPair::cast(structure)->getter();
   9016     if (getter->IsSpecFunction()) {
   9017       // TODO(rossberg): nicer would be to cast to some JSCallable here...
   9018       return GetPropertyWithDefinedGetter(receiver, JSReceiver::cast(getter));
   9019     }
   9020     // Getter is not a function.
   9021     return isolate->heap()->undefined_value();
   9022   }
   9023 
   9024   UNREACHABLE();
   9025   return NULL;
   9026 }
   9027 
   9028 
   9029 MaybeObject* JSObject::SetElementWithCallback(Object* structure,
   9030                                               uint32_t index,
   9031                                               Object* value,
   9032                                               JSObject* holder,
   9033                                               StrictModeFlag strict_mode) {
   9034   Isolate* isolate = GetIsolate();
   9035   HandleScope scope(isolate);
   9036 
   9037   // We should never get here to initialize a const with the hole
   9038   // value since a const declaration would conflict with the setter.
   9039   ASSERT(!value->IsTheHole());
   9040   Handle<Object> value_handle(value, isolate);
   9041 
   9042   // To accommodate both the old and the new api we switch on the
   9043   // data structure used to store the callbacks.  Eventually foreign
   9044   // callbacks should be phased out.
   9045   ASSERT(!structure->IsForeign());
   9046 
   9047   if (structure->IsAccessorInfo()) {
   9048     // api style callbacks
   9049     Handle<JSObject> self(this);
   9050     Handle<JSObject> holder_handle(JSObject::cast(holder));
   9051     Handle<AccessorInfo> data(AccessorInfo::cast(structure));
   9052     Object* call_obj = data->setter();
   9053     v8::AccessorSetter call_fun = v8::ToCData<v8::AccessorSetter>(call_obj);
   9054     if (call_fun == NULL) return value;
   9055     Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
   9056     Handle<String> key(isolate->factory()->NumberToString(number));
   9057     LOG(isolate, ApiNamedPropertyAccess("store", *self, *key));
   9058     CustomArguments args(isolate, data->data(), *self, *holder_handle);
   9059     v8::AccessorInfo info(args.end());
   9060     {
   9061       // Leaving JavaScript.
   9062       VMState state(isolate, EXTERNAL);
   9063       call_fun(v8::Utils::ToLocal(key),
   9064                v8::Utils::ToLocal(value_handle),
   9065                info);
   9066     }
   9067     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   9068     return *value_handle;
   9069   }
   9070 
   9071   if (structure->IsAccessorPair()) {
   9072     Handle<Object> setter(AccessorPair::cast(structure)->setter());
   9073     if (setter->IsSpecFunction()) {
   9074       // TODO(rossberg): nicer would be to cast to some JSCallable here...
   9075       return SetPropertyWithDefinedSetter(JSReceiver::cast(*setter), value);
   9076     } else {
   9077       if (strict_mode == kNonStrictMode) {
   9078         return value;
   9079       }
   9080       Handle<Object> holder_handle(holder, isolate);
   9081       Handle<Object> key(isolate->factory()->NewNumberFromUint(index));
   9082       Handle<Object> args[2] = { key, holder_handle };
   9083       return isolate->Throw(
   9084           *isolate->factory()->NewTypeError("no_setter_in_callback",
   9085                                             HandleVector(args, 2)));
   9086     }
   9087   }
   9088 
   9089   UNREACHABLE();
   9090   return NULL;
   9091 }
   9092 
   9093 
   9094 bool JSObject::HasFastArgumentsElements() {
   9095   Heap* heap = GetHeap();
   9096   if (!elements()->IsFixedArray()) return false;
   9097   FixedArray* elements = FixedArray::cast(this->elements());
   9098   if (elements->map() != heap->non_strict_arguments_elements_map()) {
   9099     return false;
   9100   }
   9101   FixedArray* arguments = FixedArray::cast(elements->get(1));
   9102   return !arguments->IsDictionary();
   9103 }
   9104 
   9105 
   9106 bool JSObject::HasDictionaryArgumentsElements() {
   9107   Heap* heap = GetHeap();
   9108   if (!elements()->IsFixedArray()) return false;
   9109   FixedArray* elements = FixedArray::cast(this->elements());
   9110   if (elements->map() != heap->non_strict_arguments_elements_map()) {
   9111     return false;
   9112   }
   9113   FixedArray* arguments = FixedArray::cast(elements->get(1));
   9114   return arguments->IsDictionary();
   9115 }
   9116 
   9117 
   9118 // Adding n elements in fast case is O(n*n).
   9119 // Note: revisit design to have dual undefined values to capture absent
   9120 // elements.
   9121 MaybeObject* JSObject::SetFastElement(uint32_t index,
   9122                                       Object* value,
   9123                                       StrictModeFlag strict_mode,
   9124                                       bool check_prototype) {
   9125   ASSERT(HasFastTypeElements() ||
   9126          HasFastArgumentsElements());
   9127 
   9128   FixedArray* backing_store = FixedArray::cast(elements());
   9129   if (backing_store->map() == GetHeap()->non_strict_arguments_elements_map()) {
   9130     backing_store = FixedArray::cast(backing_store->get(1));
   9131   } else {
   9132     MaybeObject* maybe = EnsureWritableFastElements();
   9133     if (!maybe->To(&backing_store)) return maybe;
   9134   }
   9135   uint32_t capacity = static_cast<uint32_t>(backing_store->length());
   9136 
   9137   if (check_prototype &&
   9138       (index >= capacity || backing_store->get(index)->IsTheHole())) {
   9139     bool found;
   9140     MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index,
   9141                                                                    value,
   9142                                                                    &found,
   9143                                                                    strict_mode);
   9144     if (found) return result;
   9145   }
   9146 
   9147   uint32_t new_capacity = capacity;
   9148   // Check if the length property of this object needs to be updated.
   9149   uint32_t array_length = 0;
   9150   bool must_update_array_length = false;
   9151   if (IsJSArray()) {
   9152     CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length));
   9153     if (index >= array_length) {
   9154       must_update_array_length = true;
   9155       array_length = index + 1;
   9156     }
   9157   }
   9158   // Check if the capacity of the backing store needs to be increased, or if
   9159   // a transition to slow elements is necessary.
   9160   if (index >= capacity) {
   9161     bool convert_to_slow = true;
   9162     if ((index - capacity) < kMaxGap) {
   9163       new_capacity = NewElementsCapacity(index + 1);
   9164       ASSERT(new_capacity > index);
   9165       if (!ShouldConvertToSlowElements(new_capacity)) {
   9166         convert_to_slow = false;
   9167       }
   9168     }
   9169     if (convert_to_slow) {
   9170       MaybeObject* result = NormalizeElements();
   9171       if (result->IsFailure()) return result;
   9172       return SetDictionaryElement(index, value, NONE, strict_mode,
   9173                                   check_prototype);
   9174     }
   9175   }
   9176   // Convert to fast double elements if appropriate.
   9177   if (HasFastSmiOnlyElements() && !value->IsSmi() && value->IsNumber()) {
   9178     MaybeObject* maybe =
   9179         SetFastDoubleElementsCapacityAndLength(new_capacity, array_length);
   9180     if (maybe->IsFailure()) return maybe;
   9181     FixedDoubleArray::cast(elements())->set(index, value->Number());
   9182     return value;
   9183   }
   9184   // Change elements kind from SMI_ONLY to generic FAST if necessary.
   9185   if (HasFastSmiOnlyElements() && !value->IsSmi()) {
   9186     Map* new_map;
   9187     { MaybeObject* maybe_new_map = GetElementsTransitionMap(GetIsolate(),
   9188                                                             FAST_ELEMENTS);
   9189       if (!maybe_new_map->To(&new_map)) return maybe_new_map;
   9190     }
   9191     set_map(new_map);
   9192     if (FLAG_trace_elements_transitions) {
   9193       PrintElementsTransition(stdout, FAST_SMI_ONLY_ELEMENTS, elements(),
   9194                               FAST_ELEMENTS, elements());
   9195     }
   9196   }
   9197   // Increase backing store capacity if that's been decided previously.
   9198   if (new_capacity != capacity) {
   9199     FixedArray* new_elements;
   9200     SetFastElementsCapacityMode set_capacity_mode =
   9201         value->IsSmi() && HasFastSmiOnlyElements()
   9202             ? kAllowSmiOnlyElements
   9203             : kDontAllowSmiOnlyElements;
   9204     { MaybeObject* maybe =
   9205           SetFastElementsCapacityAndLength(new_capacity,
   9206                                            array_length,
   9207                                            set_capacity_mode);
   9208       if (!maybe->To(&new_elements)) return maybe;
   9209     }
   9210     new_elements->set(index, value);
   9211     return value;
   9212   }
   9213   // Finally, set the new element and length.
   9214   ASSERT(elements()->IsFixedArray());
   9215   backing_store->set(index, value);
   9216   if (must_update_array_length) {
   9217     JSArray::cast(this)->set_length(Smi::FromInt(array_length));
   9218   }
   9219   return value;
   9220 }
   9221 
   9222 
   9223 MaybeObject* JSObject::SetDictionaryElement(uint32_t index,
   9224                                             Object* value,
   9225                                             PropertyAttributes attributes,
   9226                                             StrictModeFlag strict_mode,
   9227                                             bool check_prototype,
   9228                                             SetPropertyMode set_mode) {
   9229   ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements());
   9230   Isolate* isolate = GetIsolate();
   9231   Heap* heap = isolate->heap();
   9232 
   9233   // Insert element in the dictionary.
   9234   FixedArray* elements = FixedArray::cast(this->elements());
   9235   bool is_arguments =
   9236       (elements->map() == heap->non_strict_arguments_elements_map());
   9237   SeededNumberDictionary* dictionary = NULL;
   9238   if (is_arguments) {
   9239     dictionary = SeededNumberDictionary::cast(elements->get(1));
   9240   } else {
   9241     dictionary = SeededNumberDictionary::cast(elements);
   9242   }
   9243 
   9244   int entry = dictionary->FindEntry(index);
   9245   if (entry != SeededNumberDictionary::kNotFound) {
   9246     Object* element = dictionary->ValueAt(entry);
   9247     PropertyDetails details = dictionary->DetailsAt(entry);
   9248     if (details.type() == CALLBACKS && set_mode == SET_PROPERTY) {
   9249       return SetElementWithCallback(element, index, value, this, strict_mode);
   9250     } else {
   9251       dictionary->UpdateMaxNumberKey(index);
   9252       // If a value has not been initialized we allow writing to it even if it
   9253       // is read-only (a declared const that has not been initialized).  If a
   9254       // value is being defined we skip attribute checks completely.
   9255       if (set_mode == DEFINE_PROPERTY) {
   9256         details = PropertyDetails(attributes, NORMAL, details.index());
   9257         dictionary->DetailsAtPut(entry, details);
   9258       } else if (details.IsReadOnly() && !element->IsTheHole()) {
   9259         if (strict_mode == kNonStrictMode) {
   9260           return isolate->heap()->undefined_value();
   9261         } else {
   9262           Handle<Object> holder(this);
   9263           Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
   9264           Handle<Object> args[2] = { number, holder };
   9265           Handle<Object> error =
   9266               isolate->factory()->NewTypeError("strict_read_only_property",
   9267                                                HandleVector(args, 2));
   9268           return isolate->Throw(*error);
   9269         }
   9270       }
   9271       // Elements of the arguments object in slow mode might be slow aliases.
   9272       if (is_arguments && element->IsAliasedArgumentsEntry()) {
   9273         AliasedArgumentsEntry* entry = AliasedArgumentsEntry::cast(element);
   9274         Context* context = Context::cast(elements->get(0));
   9275         int context_index = entry->aliased_context_slot();
   9276         ASSERT(!context->get(context_index)->IsTheHole());
   9277         context->set(context_index, value);
   9278         // For elements that are still writable we keep slow aliasing.
   9279         if (!details.IsReadOnly()) value = element;
   9280       }
   9281       dictionary->ValueAtPut(entry, value);
   9282     }
   9283   } else {
   9284     // Index not already used. Look for an accessor in the prototype chain.
   9285     if (check_prototype) {
   9286       bool found;
   9287       MaybeObject* result =
   9288           SetElementWithCallbackSetterInPrototypes(
   9289               index, value, &found, strict_mode);
   9290       if (found) return result;
   9291     }
   9292     // When we set the is_extensible flag to false we always force the
   9293     // element into dictionary mode (and force them to stay there).
   9294     if (!map()->is_extensible()) {
   9295       if (strict_mode == kNonStrictMode) {
   9296         return isolate->heap()->undefined_value();
   9297       } else {
   9298         Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
   9299         Handle<String> name = isolate->factory()->NumberToString(number);
   9300         Handle<Object> args[1] = { name };
   9301         Handle<Object> error =
   9302             isolate->factory()->NewTypeError("object_not_extensible",
   9303                                              HandleVector(args, 1));
   9304         return isolate->Throw(*error);
   9305       }
   9306     }
   9307     FixedArrayBase* new_dictionary;
   9308     PropertyDetails details = PropertyDetails(attributes, NORMAL);
   9309     MaybeObject* maybe = dictionary->AddNumberEntry(index, value, details);
   9310     if (!maybe->To(&new_dictionary)) return maybe;
   9311     if (dictionary != SeededNumberDictionary::cast(new_dictionary)) {
   9312       if (is_arguments) {
   9313         elements->set(1, new_dictionary);
   9314       } else {
   9315         set_elements(new_dictionary);
   9316       }
   9317       dictionary = SeededNumberDictionary::cast(new_dictionary);
   9318     }
   9319   }
   9320 
   9321   // Update the array length if this JSObject is an array.
   9322   if (IsJSArray()) {
   9323     MaybeObject* result =
   9324         JSArray::cast(this)->JSArrayUpdateLengthFromIndex(index, value);
   9325     if (result->IsFailure()) return result;
   9326   }
   9327 
   9328   // Attempt to put this object back in fast case.
   9329   if (ShouldConvertToFastElements()) {
   9330     uint32_t new_length = 0;
   9331     if (IsJSArray()) {
   9332       CHECK(JSArray::cast(this)->length()->ToArrayIndex(&new_length));
   9333     } else {
   9334       new_length = dictionary->max_number_key() + 1;
   9335     }
   9336     SetFastElementsCapacityMode set_capacity_mode = FLAG_smi_only_arrays
   9337         ? kAllowSmiOnlyElements
   9338         : kDontAllowSmiOnlyElements;
   9339     bool has_smi_only_elements = false;
   9340     bool should_convert_to_fast_double_elements =
   9341         ShouldConvertToFastDoubleElements(&has_smi_only_elements);
   9342     if (has_smi_only_elements) {
   9343       set_capacity_mode = kForceSmiOnlyElements;
   9344     }
   9345     MaybeObject* result = should_convert_to_fast_double_elements
   9346         ? SetFastDoubleElementsCapacityAndLength(new_length, new_length)
   9347         : SetFastElementsCapacityAndLength(new_length,
   9348                                            new_length,
   9349                                            set_capacity_mode);
   9350     if (result->IsFailure()) return result;
   9351 #ifdef DEBUG
   9352     if (FLAG_trace_normalization) {
   9353       PrintF("Object elements are fast case again:\n");
   9354       Print();
   9355     }
   9356 #endif
   9357   }
   9358   return value;
   9359 }
   9360 
   9361 
   9362 MUST_USE_RESULT MaybeObject* JSObject::SetFastDoubleElement(
   9363     uint32_t index,
   9364     Object* value,
   9365     StrictModeFlag strict_mode,
   9366     bool check_prototype) {
   9367   ASSERT(HasFastDoubleElements());
   9368 
   9369   FixedArrayBase* base_elms = FixedArrayBase::cast(elements());
   9370   uint32_t elms_length = static_cast<uint32_t>(base_elms->length());
   9371 
   9372   // If storing to an element that isn't in the array, pass the store request
   9373   // up the prototype chain before storing in the receiver's elements.
   9374   if (check_prototype &&
   9375       (index >= elms_length ||
   9376        FixedDoubleArray::cast(base_elms)->is_the_hole(index))) {
   9377     bool found;
   9378     MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index,
   9379                                                                    value,
   9380                                                                    &found,
   9381                                                                    strict_mode);
   9382     if (found) return result;
   9383   }
   9384 
   9385   // If the value object is not a heap number, switch to fast elements and try
   9386   // again.
   9387   bool value_is_smi = value->IsSmi();
   9388   if (!value->IsNumber()) {
   9389     Object* obj;
   9390     uint32_t length = elms_length;
   9391     if (IsJSArray()) {
   9392       CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length));
   9393     }
   9394     MaybeObject* maybe_obj = SetFastElementsCapacityAndLength(
   9395         elms_length,
   9396         length,
   9397         kDontAllowSmiOnlyElements);
   9398     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   9399     return SetFastElement(index,
   9400                           value,
   9401                           strict_mode,
   9402                           check_prototype);
   9403   }
   9404 
   9405   double double_value = value_is_smi
   9406       ? static_cast<double>(Smi::cast(value)->value())
   9407       : HeapNumber::cast(value)->value();
   9408 
   9409   // Check whether there is extra space in the fixed array.
   9410   if (index < elms_length) {
   9411     FixedDoubleArray* elms = FixedDoubleArray::cast(elements());
   9412     elms->set(index, double_value);
   9413     if (IsJSArray()) {
   9414       // Update the length of the array if needed.
   9415       uint32_t array_length = 0;
   9416       CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length));
   9417       if (index >= array_length) {
   9418         JSArray::cast(this)->set_length(Smi::FromInt(index + 1));
   9419       }
   9420     }
   9421     return value;
   9422   }
   9423 
   9424   // Allow gap in fast case.
   9425   if ((index - elms_length) < kMaxGap) {
   9426     // Try allocating extra space.
   9427     int new_capacity = NewElementsCapacity(index+1);
   9428     if (!ShouldConvertToSlowElements(new_capacity)) {
   9429       ASSERT(static_cast<uint32_t>(new_capacity) > index);
   9430       Object* obj;
   9431       { MaybeObject* maybe_obj =
   9432             SetFastDoubleElementsCapacityAndLength(new_capacity,
   9433                                                    index + 1);
   9434         if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   9435       }
   9436       FixedDoubleArray::cast(elements())->set(index, double_value);
   9437       return value;
   9438     }
   9439   }
   9440 
   9441   // Otherwise default to slow case.
   9442   ASSERT(HasFastDoubleElements());
   9443   ASSERT(map()->has_fast_double_elements());
   9444   ASSERT(elements()->IsFixedDoubleArray());
   9445   Object* obj;
   9446   { MaybeObject* maybe_obj = NormalizeElements();
   9447     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   9448   }
   9449   ASSERT(HasDictionaryElements());
   9450   return SetElement(index, value, NONE, strict_mode, check_prototype);
   9451 }
   9452 
   9453 
   9454 MaybeObject* JSReceiver::SetElement(uint32_t index,
   9455                                     Object* value,
   9456                                     PropertyAttributes attributes,
   9457                                     StrictModeFlag strict_mode,
   9458                                     bool check_proto) {
   9459   if (IsJSProxy()) {
   9460     return JSProxy::cast(this)->SetElementWithHandler(
   9461         index, value, strict_mode);
   9462   } else {
   9463     return JSObject::cast(this)->SetElement(
   9464         index, value, attributes, strict_mode, check_proto);
   9465   }
   9466 }
   9467 
   9468 
   9469 Handle<Object> JSObject::SetOwnElement(Handle<JSObject> object,
   9470                                        uint32_t index,
   9471                                        Handle<Object> value,
   9472                                        StrictModeFlag strict_mode) {
   9473   ASSERT(!object->HasExternalArrayElements());
   9474   CALL_HEAP_FUNCTION(
   9475       object->GetIsolate(),
   9476       object->SetElement(index, *value, NONE, strict_mode, false),
   9477       Object);
   9478 }
   9479 
   9480 
   9481 Handle<Object> JSObject::SetElement(Handle<JSObject> object,
   9482                                     uint32_t index,
   9483                                     Handle<Object> value,
   9484                                     PropertyAttributes attr,
   9485                                     StrictModeFlag strict_mode,
   9486                                     SetPropertyMode set_mode) {
   9487   if (object->HasExternalArrayElements()) {
   9488     if (!value->IsSmi() && !value->IsHeapNumber() && !value->IsUndefined()) {
   9489       bool has_exception;
   9490       Handle<Object> number = Execution::ToNumber(value, &has_exception);
   9491       if (has_exception) return Handle<Object>();
   9492       value = number;
   9493     }
   9494   }
   9495   CALL_HEAP_FUNCTION(
   9496       object->GetIsolate(),
   9497       object->SetElement(index, *value, attr, strict_mode, true, set_mode),
   9498       Object);
   9499 }
   9500 
   9501 
   9502 MaybeObject* JSObject::SetElement(uint32_t index,
   9503                                   Object* value,
   9504                                   PropertyAttributes attributes,
   9505                                   StrictModeFlag strict_mode,
   9506                                   bool check_prototype,
   9507                                   SetPropertyMode set_mode) {
   9508   // Check access rights if needed.
   9509   if (IsAccessCheckNeeded()) {
   9510     Heap* heap = GetHeap();
   9511     if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_SET)) {
   9512       HandleScope scope(heap->isolate());
   9513       Handle<Object> value_handle(value);
   9514       heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_SET);
   9515       return *value_handle;
   9516     }
   9517   }
   9518 
   9519   if (IsJSGlobalProxy()) {
   9520     Object* proto = GetPrototype();
   9521     if (proto->IsNull()) return value;
   9522     ASSERT(proto->IsJSGlobalObject());
   9523     return JSObject::cast(proto)->SetElement(index,
   9524                                              value,
   9525                                              attributes,
   9526                                              strict_mode,
   9527                                              check_prototype,
   9528                                              set_mode);
   9529   }
   9530 
   9531   // Don't allow element properties to be redefined for external arrays.
   9532   if (HasExternalArrayElements() && set_mode == DEFINE_PROPERTY) {
   9533     Isolate* isolate = GetHeap()->isolate();
   9534     Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
   9535     Handle<Object> args[] = { Handle<Object>(this), number };
   9536     Handle<Object> error = isolate->factory()->NewTypeError(
   9537         "redef_external_array_element", HandleVector(args, ARRAY_SIZE(args)));
   9538     return isolate->Throw(*error);
   9539   }
   9540 
   9541   // Normalize the elements to enable attributes on the property.
   9542   if ((attributes & (DONT_DELETE | DONT_ENUM | READ_ONLY)) != 0) {
   9543     SeededNumberDictionary* dictionary;
   9544     MaybeObject* maybe_object = NormalizeElements();
   9545     if (!maybe_object->To(&dictionary)) return maybe_object;
   9546     // Make sure that we never go back to fast case.
   9547     dictionary->set_requires_slow_elements();
   9548   }
   9549 
   9550   // Check for lookup interceptor
   9551   if (HasIndexedInterceptor()) {
   9552     return SetElementWithInterceptor(index,
   9553                                      value,
   9554                                      attributes,
   9555                                      strict_mode,
   9556                                      check_prototype,
   9557                                      set_mode);
   9558   }
   9559 
   9560   return SetElementWithoutInterceptor(index,
   9561                                       value,
   9562                                       attributes,
   9563                                       strict_mode,
   9564                                       check_prototype,
   9565                                       set_mode);
   9566 }
   9567 
   9568 
   9569 MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index,
   9570                                                     Object* value,
   9571                                                     PropertyAttributes attr,
   9572                                                     StrictModeFlag strict_mode,
   9573                                                     bool check_prototype,
   9574                                                     SetPropertyMode set_mode) {
   9575   ASSERT(HasDictionaryElements() ||
   9576          HasDictionaryArgumentsElements() ||
   9577          (attr & (DONT_DELETE | DONT_ENUM | READ_ONLY)) == 0);
   9578   Isolate* isolate = GetIsolate();
   9579   switch (GetElementsKind()) {
   9580     case FAST_SMI_ONLY_ELEMENTS:
   9581     case FAST_ELEMENTS:
   9582       return SetFastElement(index, value, strict_mode, check_prototype);
   9583     case FAST_DOUBLE_ELEMENTS:
   9584       return SetFastDoubleElement(index, value, strict_mode, check_prototype);
   9585     case EXTERNAL_PIXEL_ELEMENTS: {
   9586       ExternalPixelArray* pixels = ExternalPixelArray::cast(elements());
   9587       return pixels->SetValue(index, value);
   9588     }
   9589     case EXTERNAL_BYTE_ELEMENTS: {
   9590       ExternalByteArray* array = ExternalByteArray::cast(elements());
   9591       return array->SetValue(index, value);
   9592     }
   9593     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: {
   9594       ExternalUnsignedByteArray* array =
   9595           ExternalUnsignedByteArray::cast(elements());
   9596       return array->SetValue(index, value);
   9597     }
   9598     case EXTERNAL_SHORT_ELEMENTS: {
   9599       ExternalShortArray* array = ExternalShortArray::cast(elements());
   9600       return array->SetValue(index, value);
   9601     }
   9602     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: {
   9603       ExternalUnsignedShortArray* array =
   9604           ExternalUnsignedShortArray::cast(elements());
   9605       return array->SetValue(index, value);
   9606     }
   9607     case EXTERNAL_INT_ELEMENTS: {
   9608       ExternalIntArray* array = ExternalIntArray::cast(elements());
   9609       return array->SetValue(index, value);
   9610     }
   9611     case EXTERNAL_UNSIGNED_INT_ELEMENTS: {
   9612       ExternalUnsignedIntArray* array =
   9613           ExternalUnsignedIntArray::cast(elements());
   9614       return array->SetValue(index, value);
   9615     }
   9616     case EXTERNAL_FLOAT_ELEMENTS: {
   9617       ExternalFloatArray* array = ExternalFloatArray::cast(elements());
   9618       return array->SetValue(index, value);
   9619     }
   9620     case EXTERNAL_DOUBLE_ELEMENTS: {
   9621       ExternalDoubleArray* array = ExternalDoubleArray::cast(elements());
   9622       return array->SetValue(index, value);
   9623     }
   9624     case DICTIONARY_ELEMENTS:
   9625       return SetDictionaryElement(index, value, attr, strict_mode,
   9626                                   check_prototype, set_mode);
   9627     case NON_STRICT_ARGUMENTS_ELEMENTS: {
   9628       FixedArray* parameter_map = FixedArray::cast(elements());
   9629       uint32_t length = parameter_map->length();
   9630       Object* probe =
   9631           (index < length - 2) ? parameter_map->get(index + 2) : NULL;
   9632       if (probe != NULL && !probe->IsTheHole()) {
   9633         Context* context = Context::cast(parameter_map->get(0));
   9634         int context_index = Smi::cast(probe)->value();
   9635         ASSERT(!context->get(context_index)->IsTheHole());
   9636         context->set(context_index, value);
   9637         // Redefining attributes of an aliased element destroys fast aliasing.
   9638         if (set_mode == SET_PROPERTY || attr == NONE) return value;
   9639         parameter_map->set_the_hole(index + 2);
   9640         // For elements that are still writable we re-establish slow aliasing.
   9641         if ((attr & READ_ONLY) == 0) {
   9642           MaybeObject* maybe_entry =
   9643               isolate->heap()->AllocateAliasedArgumentsEntry(context_index);
   9644           if (!maybe_entry->ToObject(&value)) return maybe_entry;
   9645         }
   9646       }
   9647       FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
   9648       if (arguments->IsDictionary()) {
   9649         return SetDictionaryElement(index, value, attr, strict_mode,
   9650                                     check_prototype, set_mode);
   9651       } else {
   9652         return SetFastElement(index, value, strict_mode, check_prototype);
   9653       }
   9654     }
   9655   }
   9656   // All possible cases have been handled above. Add a return to avoid the
   9657   // complaints from the compiler.
   9658   UNREACHABLE();
   9659   return isolate->heap()->null_value();
   9660 }
   9661 
   9662 
   9663 Handle<Object> JSObject::TransitionElementsKind(Handle<JSObject> object,
   9664                                                 ElementsKind to_kind) {
   9665   CALL_HEAP_FUNCTION(object->GetIsolate(),
   9666                      object->TransitionElementsKind(to_kind),
   9667                      Object);
   9668 }
   9669 
   9670 
   9671 MaybeObject* JSObject::TransitionElementsKind(ElementsKind to_kind) {
   9672   ElementsKind from_kind = map()->elements_kind();
   9673 
   9674   Isolate* isolate = GetIsolate();
   9675   if ((from_kind == FAST_SMI_ONLY_ELEMENTS ||
   9676       elements() == isolate->heap()->empty_fixed_array()) &&
   9677       to_kind == FAST_ELEMENTS) {
   9678     ASSERT(from_kind != FAST_ELEMENTS);
   9679     MaybeObject* maybe_new_map = GetElementsTransitionMap(isolate, to_kind);
   9680     Map* new_map;
   9681     if (!maybe_new_map->To(&new_map)) return maybe_new_map;
   9682     set_map(new_map);
   9683     if (FLAG_trace_elements_transitions) {
   9684       FixedArrayBase* elms = FixedArrayBase::cast(elements());
   9685       PrintElementsTransition(stdout, from_kind, elms, to_kind, elms);
   9686     }
   9687     return this;
   9688   }
   9689 
   9690   FixedArrayBase* elms = FixedArrayBase::cast(elements());
   9691   uint32_t capacity = static_cast<uint32_t>(elms->length());
   9692   uint32_t length = capacity;
   9693 
   9694   if (IsJSArray()) {
   9695     Object* raw_length = JSArray::cast(this)->length();
   9696     if (raw_length->IsUndefined()) {
   9697       // If length is undefined, then JSArray is being initialized and has no
   9698       // elements, assume a length of zero.
   9699       length = 0;
   9700     } else {
   9701       CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length));
   9702     }
   9703   }
   9704 
   9705   if (from_kind == FAST_SMI_ONLY_ELEMENTS &&
   9706       to_kind == FAST_DOUBLE_ELEMENTS) {
   9707     MaybeObject* maybe_result =
   9708         SetFastDoubleElementsCapacityAndLength(capacity, length);
   9709     if (maybe_result->IsFailure()) return maybe_result;
   9710     return this;
   9711   }
   9712 
   9713   if (from_kind == FAST_DOUBLE_ELEMENTS && to_kind == FAST_ELEMENTS) {
   9714     MaybeObject* maybe_result = SetFastElementsCapacityAndLength(
   9715         capacity, length, kDontAllowSmiOnlyElements);
   9716     if (maybe_result->IsFailure()) return maybe_result;
   9717     return this;
   9718   }
   9719 
   9720   // This method should never be called for any other case than the ones
   9721   // handled above.
   9722   UNREACHABLE();
   9723   return GetIsolate()->heap()->null_value();
   9724 }
   9725 
   9726 
   9727 // static
   9728 bool Map::IsValidElementsTransition(ElementsKind from_kind,
   9729                                     ElementsKind to_kind) {
   9730   return
   9731       (from_kind == FAST_SMI_ONLY_ELEMENTS &&
   9732           (to_kind == FAST_DOUBLE_ELEMENTS || to_kind == FAST_ELEMENTS)) ||
   9733       (from_kind == FAST_DOUBLE_ELEMENTS && to_kind == FAST_ELEMENTS);
   9734 }
   9735 
   9736 
   9737 MaybeObject* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index,
   9738                                                    Object* value) {
   9739   uint32_t old_len = 0;
   9740   CHECK(length()->ToArrayIndex(&old_len));
   9741   // Check to see if we need to update the length. For now, we make
   9742   // sure that the length stays within 32-bits (unsigned).
   9743   if (index >= old_len && index != 0xffffffff) {
   9744     Object* len;
   9745     { MaybeObject* maybe_len =
   9746           GetHeap()->NumberFromDouble(static_cast<double>(index) + 1);
   9747       if (!maybe_len->ToObject(&len)) return maybe_len;
   9748     }
   9749     set_length(len);
   9750   }
   9751   return value;
   9752 }
   9753 
   9754 
   9755 MaybeObject* JSObject::GetElementWithInterceptor(Object* receiver,
   9756                                                  uint32_t index) {
   9757   Isolate* isolate = GetIsolate();
   9758   // Make sure that the top context does not change when doing
   9759   // callbacks or interceptor calls.
   9760   AssertNoContextChange ncc;
   9761   HandleScope scope(isolate);
   9762   Handle<InterceptorInfo> interceptor(GetIndexedInterceptor(), isolate);
   9763   Handle<Object> this_handle(receiver, isolate);
   9764   Handle<JSObject> holder_handle(this, isolate);
   9765   if (!interceptor->getter()->IsUndefined()) {
   9766     v8::IndexedPropertyGetter getter =
   9767         v8::ToCData<v8::IndexedPropertyGetter>(interceptor->getter());
   9768     LOG(isolate,
   9769         ApiIndexedPropertyAccess("interceptor-indexed-get", this, index));
   9770     CustomArguments args(isolate, interceptor->data(), receiver, this);
   9771     v8::AccessorInfo info(args.end());
   9772     v8::Handle<v8::Value> result;
   9773     {
   9774       // Leaving JavaScript.
   9775       VMState state(isolate, EXTERNAL);
   9776       result = getter(index, info);
   9777     }
   9778     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   9779     if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
   9780   }
   9781 
   9782   Heap* heap = holder_handle->GetHeap();
   9783   ElementsAccessor* handler = holder_handle->GetElementsAccessor();
   9784   MaybeObject* raw_result = handler->Get(*this_handle,
   9785                                          *holder_handle,
   9786                                          index);
   9787   if (raw_result != heap->the_hole_value()) return raw_result;
   9788 
   9789   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   9790 
   9791   Object* pt = holder_handle->GetPrototype();
   9792   if (pt == heap->null_value()) return heap->undefined_value();
   9793   return pt->GetElementWithReceiver(*this_handle, index);
   9794 }
   9795 
   9796 
   9797 bool JSObject::HasDenseElements() {
   9798   int capacity = 0;
   9799   int used = 0;
   9800   GetElementsCapacityAndUsage(&capacity, &used);
   9801   return (capacity == 0) || (used > (capacity / 2));
   9802 }
   9803 
   9804 
   9805 void JSObject::GetElementsCapacityAndUsage(int* capacity, int* used) {
   9806   *capacity = 0;
   9807   *used = 0;
   9808 
   9809   FixedArrayBase* backing_store_base = FixedArrayBase::cast(elements());
   9810   FixedArray* backing_store = NULL;
   9811   switch (GetElementsKind()) {
   9812     case NON_STRICT_ARGUMENTS_ELEMENTS:
   9813       backing_store_base =
   9814           FixedArray::cast(FixedArray::cast(backing_store_base)->get(1));
   9815       backing_store = FixedArray::cast(backing_store_base);
   9816       if (backing_store->IsDictionary()) {
   9817         SeededNumberDictionary* dictionary =
   9818             SeededNumberDictionary::cast(backing_store);
   9819         *capacity = dictionary->Capacity();
   9820         *used = dictionary->NumberOfElements();
   9821         break;
   9822       }
   9823       // Fall through.
   9824     case FAST_SMI_ONLY_ELEMENTS:
   9825     case FAST_ELEMENTS:
   9826       backing_store = FixedArray::cast(backing_store_base);
   9827       *capacity = backing_store->length();
   9828       for (int i = 0; i < *capacity; ++i) {
   9829         if (!backing_store->get(i)->IsTheHole()) ++(*used);
   9830       }
   9831       break;
   9832     case DICTIONARY_ELEMENTS: {
   9833       SeededNumberDictionary* dictionary =
   9834           SeededNumberDictionary::cast(FixedArray::cast(elements()));
   9835       *capacity = dictionary->Capacity();
   9836       *used = dictionary->NumberOfElements();
   9837       break;
   9838     }
   9839     case FAST_DOUBLE_ELEMENTS: {
   9840       FixedDoubleArray* elms = FixedDoubleArray::cast(elements());
   9841       *capacity = elms->length();
   9842       for (int i = 0; i < *capacity; i++) {
   9843         if (!elms->is_the_hole(i)) ++(*used);
   9844       }
   9845       break;
   9846     }
   9847     case EXTERNAL_BYTE_ELEMENTS:
   9848     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
   9849     case EXTERNAL_SHORT_ELEMENTS:
   9850     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
   9851     case EXTERNAL_INT_ELEMENTS:
   9852     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
   9853     case EXTERNAL_FLOAT_ELEMENTS:
   9854     case EXTERNAL_DOUBLE_ELEMENTS:
   9855     case EXTERNAL_PIXEL_ELEMENTS:
   9856       // External arrays are considered 100% used.
   9857       ExternalArray* external_array = ExternalArray::cast(elements());
   9858       *capacity = external_array->length();
   9859       *used = external_array->length();
   9860       break;
   9861   }
   9862 }
   9863 
   9864 
   9865 bool JSObject::ShouldConvertToSlowElements(int new_capacity) {
   9866   STATIC_ASSERT(kMaxUncheckedOldFastElementsLength <=
   9867                 kMaxUncheckedFastElementsLength);
   9868   if (new_capacity <= kMaxUncheckedOldFastElementsLength ||
   9869       (new_capacity <= kMaxUncheckedFastElementsLength &&
   9870        GetHeap()->InNewSpace(this))) {
   9871     return false;
   9872   }
   9873   // If the fast-case backing storage takes up roughly three times as
   9874   // much space (in machine words) as a dictionary backing storage
   9875   // would, the object should have slow elements.
   9876   int old_capacity = 0;
   9877   int used_elements = 0;
   9878   GetElementsCapacityAndUsage(&old_capacity, &used_elements);
   9879   int dictionary_size = SeededNumberDictionary::ComputeCapacity(used_elements) *
   9880       SeededNumberDictionary::kEntrySize;
   9881   return 3 * dictionary_size <= new_capacity;
   9882 }
   9883 
   9884 
   9885 bool JSObject::ShouldConvertToFastElements() {
   9886   ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements());
   9887   // If the elements are sparse, we should not go back to fast case.
   9888   if (!HasDenseElements()) return false;
   9889   // An object requiring access checks is never allowed to have fast
   9890   // elements.  If it had fast elements we would skip security checks.
   9891   if (IsAccessCheckNeeded()) return false;
   9892 
   9893   FixedArray* elements = FixedArray::cast(this->elements());
   9894   SeededNumberDictionary* dictionary = NULL;
   9895   if (elements->map() == GetHeap()->non_strict_arguments_elements_map()) {
   9896     dictionary = SeededNumberDictionary::cast(elements->get(1));
   9897   } else {
   9898     dictionary = SeededNumberDictionary::cast(elements);
   9899   }
   9900   // If an element has been added at a very high index in the elements
   9901   // dictionary, we cannot go back to fast case.
   9902   if (dictionary->requires_slow_elements()) return false;
   9903   // If the dictionary backing storage takes up roughly half as much
   9904   // space (in machine words) as a fast-case backing storage would,
   9905   // the object should have fast elements.
   9906   uint32_t array_size = 0;
   9907   if (IsJSArray()) {
   9908     CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_size));
   9909   } else {
   9910     array_size = dictionary->max_number_key();
   9911   }
   9912   uint32_t dictionary_size = static_cast<uint32_t>(dictionary->Capacity()) *
   9913       SeededNumberDictionary::kEntrySize;
   9914   return 2 * dictionary_size >= array_size;
   9915 }
   9916 
   9917 
   9918 bool JSObject::ShouldConvertToFastDoubleElements(
   9919     bool* has_smi_only_elements) {
   9920   *has_smi_only_elements = false;
   9921   if (FLAG_unbox_double_arrays) {
   9922     ASSERT(HasDictionaryElements());
   9923     SeededNumberDictionary* dictionary =
   9924         SeededNumberDictionary::cast(elements());
   9925     bool found_double = false;
   9926     for (int i = 0; i < dictionary->Capacity(); i++) {
   9927       Object* key = dictionary->KeyAt(i);
   9928       if (key->IsNumber()) {
   9929         Object* value = dictionary->ValueAt(i);
   9930         if (!value->IsNumber()) return false;
   9931         if (!value->IsSmi()) {
   9932           found_double = true;
   9933         }
   9934       }
   9935     }
   9936     *has_smi_only_elements = !found_double;
   9937     return found_double;
   9938   } else {
   9939     return false;
   9940   }
   9941 }
   9942 
   9943 
   9944 // Certain compilers request function template instantiation when they
   9945 // see the definition of the other template functions in the
   9946 // class. This requires us to have the template functions put
   9947 // together, so even though this function belongs in objects-debug.cc,
   9948 // we keep it here instead to satisfy certain compilers.
   9949 #ifdef OBJECT_PRINT
   9950 template<typename Shape, typename Key>
   9951 void Dictionary<Shape, Key>::Print(FILE* out) {
   9952   int capacity = HashTable<Shape, Key>::Capacity();
   9953   for (int i = 0; i < capacity; i++) {
   9954     Object* k = HashTable<Shape, Key>::KeyAt(i);
   9955     if (HashTable<Shape, Key>::IsKey(k)) {
   9956       PrintF(out, " ");
   9957       if (k->IsString()) {
   9958         String::cast(k)->StringPrint(out);
   9959       } else {
   9960         k->ShortPrint(out);
   9961       }
   9962       PrintF(out, ": ");
   9963       ValueAt(i)->ShortPrint(out);
   9964       PrintF(out, "\n");
   9965     }
   9966   }
   9967 }
   9968 #endif
   9969 
   9970 
   9971 template<typename Shape, typename Key>
   9972 void Dictionary<Shape, Key>::CopyValuesTo(FixedArray* elements) {
   9973   int pos = 0;
   9974   int capacity = HashTable<Shape, Key>::Capacity();
   9975   AssertNoAllocation no_gc;
   9976   WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc);
   9977   for (int i = 0; i < capacity; i++) {
   9978     Object* k =  Dictionary<Shape, Key>::KeyAt(i);
   9979     if (Dictionary<Shape, Key>::IsKey(k)) {
   9980       elements->set(pos++, ValueAt(i), mode);
   9981     }
   9982   }
   9983   ASSERT(pos == elements->length());
   9984 }
   9985 
   9986 
   9987 InterceptorInfo* JSObject::GetNamedInterceptor() {
   9988   ASSERT(map()->has_named_interceptor());
   9989   JSFunction* constructor = JSFunction::cast(map()->constructor());
   9990   ASSERT(constructor->shared()->IsApiFunction());
   9991   Object* result =
   9992       constructor->shared()->get_api_func_data()->named_property_handler();
   9993   return InterceptorInfo::cast(result);
   9994 }
   9995 
   9996 
   9997 InterceptorInfo* JSObject::GetIndexedInterceptor() {
   9998   ASSERT(map()->has_indexed_interceptor());
   9999   JSFunction* constructor = JSFunction::cast(map()->constructor());
   10000   ASSERT(constructor->shared()->IsApiFunction());
   10001   Object* result =
   10002       constructor->shared()->get_api_func_data()->indexed_property_handler();
   10003   return InterceptorInfo::cast(result);
   10004 }
   10005 
   10006 
   10007 MaybeObject* JSObject::GetPropertyPostInterceptor(
   10008     JSReceiver* receiver,
   10009     String* name,
   10010     PropertyAttributes* attributes) {
   10011   // Check local property in holder, ignore interceptor.
   10012   LookupResult result(GetIsolate());
   10013   LocalLookupRealNamedProperty(name, &result);
   10014   if (result.IsProperty()) {
   10015     return GetProperty(receiver, &result, name, attributes);
   10016   }
   10017   // Continue searching via the prototype chain.
   10018   Object* pt = GetPrototype();
   10019   *attributes = ABSENT;
   10020   if (pt->IsNull()) return GetHeap()->undefined_value();
   10021   return pt->GetPropertyWithReceiver(receiver, name, attributes);
   10022 }
   10023 
   10024 
   10025 MaybeObject* JSObject::GetLocalPropertyPostInterceptor(
   10026     JSReceiver* receiver,
   10027     String* name,
   10028     PropertyAttributes* attributes) {
   10029   // Check local property in holder, ignore interceptor.
   10030   LookupResult result(GetIsolate());
   10031   LocalLookupRealNamedProperty(name, &result);
   10032   if (result.IsProperty()) {
   10033     return GetProperty(receiver, &result, name, attributes);
   10034   }
   10035   return GetHeap()->undefined_value();
   10036 }
   10037 
   10038 
   10039 MaybeObject* JSObject::GetPropertyWithInterceptor(
   10040     JSReceiver* receiver,
   10041     String* name,
   10042     PropertyAttributes* attributes) {
   10043   Isolate* isolate = GetIsolate();
   10044   InterceptorInfo* interceptor = GetNamedInterceptor();
   10045   HandleScope scope(isolate);
   10046   Handle<JSReceiver> receiver_handle(receiver);
   10047   Handle<JSObject> holder_handle(this);
   10048   Handle<String> name_handle(name);
   10049 
   10050   if (!interceptor->getter()->IsUndefined()) {
   10051     v8::NamedPropertyGetter getter =
   10052         v8::ToCData<v8::NamedPropertyGetter>(interceptor->getter());
   10053     LOG(isolate,
   10054         ApiNamedPropertyAccess("interceptor-named-get", *holder_handle, name));
   10055     CustomArguments args(isolate, interceptor->data(), receiver, this);
   10056     v8::AccessorInfo info(args.end());
   10057     v8::Handle<v8::Value> result;
   10058     {
   10059       // Leaving JavaScript.
   10060       VMState state(isolate, EXTERNAL);
   10061       result = getter(v8::Utils::ToLocal(name_handle), info);
   10062     }
   10063     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   10064     if (!result.IsEmpty()) {
   10065       *attributes = NONE;
   10066       return *v8::Utils::OpenHandle(*result);
   10067     }
   10068   }
   10069 
   10070   MaybeObject* result = holder_handle->GetPropertyPostInterceptor(
   10071       *receiver_handle,
   10072       *name_handle,
   10073       attributes);
   10074   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   10075   return result;
   10076 }
   10077 
   10078 
   10079 bool JSObject::HasRealNamedProperty(String* key) {
   10080   // Check access rights if needed.
   10081   Isolate* isolate = GetIsolate();
   10082   if (IsAccessCheckNeeded()) {
   10083     if (!isolate->MayNamedAccess(this, key, v8::ACCESS_HAS)) {
   10084       isolate->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
   10085       return false;
   10086     }
   10087   }
   10088 
   10089   LookupResult result(isolate);
   10090   LocalLookupRealNamedProperty(key, &result);
   10091   return result.IsProperty() && (result.type() != INTERCEPTOR);
   10092 }
   10093 
   10094 
   10095 bool JSObject::HasRealElementProperty(uint32_t index) {
   10096   // Check access rights if needed.
   10097   if (IsAccessCheckNeeded()) {
   10098     Heap* heap = GetHeap();
   10099     if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) {
   10100       heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
   10101       return false;
   10102     }
   10103   }
   10104 
   10105   // Handle [] on String objects.
   10106   if (this->IsStringObjectWithCharacterAt(index)) return true;
   10107 
   10108   switch (GetElementsKind()) {
   10109     case FAST_SMI_ONLY_ELEMENTS:
   10110     case FAST_ELEMENTS: {
   10111       uint32_t length = IsJSArray() ?
   10112           static_cast<uint32_t>(
   10113               Smi::cast(JSArray::cast(this)->length())->value()) :
   10114           static_cast<uint32_t>(FixedArray::cast(elements())->length());
   10115       return (index < length) &&
   10116           !FixedArray::cast(elements())->get(index)->IsTheHole();
   10117     }
   10118     case FAST_DOUBLE_ELEMENTS: {
   10119       uint32_t length = IsJSArray() ?
   10120           static_cast<uint32_t>(
   10121               Smi::cast(JSArray::cast(this)->length())->value()) :
   10122           static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length());
   10123       return (index < length) &&
   10124           !FixedDoubleArray::cast(elements())->is_the_hole(index);
   10125       break;
   10126     }
   10127     case EXTERNAL_PIXEL_ELEMENTS: {
   10128       ExternalPixelArray* pixels = ExternalPixelArray::cast(elements());
   10129       return index < static_cast<uint32_t>(pixels->length());
   10130     }
   10131     case EXTERNAL_BYTE_ELEMENTS:
   10132     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
   10133     case EXTERNAL_SHORT_ELEMENTS:
   10134     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
   10135     case EXTERNAL_INT_ELEMENTS:
   10136     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
   10137     case EXTERNAL_FLOAT_ELEMENTS:
   10138     case EXTERNAL_DOUBLE_ELEMENTS: {
   10139       ExternalArray* array = ExternalArray::cast(elements());
   10140       return index < static_cast<uint32_t>(array->length());
   10141     }
   10142     case DICTIONARY_ELEMENTS: {
   10143       return element_dictionary()->FindEntry(index)
   10144           != SeededNumberDictionary::kNotFound;
   10145     }
   10146     case NON_STRICT_ARGUMENTS_ELEMENTS:
   10147       UNIMPLEMENTED();
   10148       break;
   10149   }
   10150   // All possibilities have been handled above already.
   10151   UNREACHABLE();
   10152   return GetHeap()->null_value();
   10153 }
   10154 
   10155 
   10156 bool JSObject::HasRealNamedCallbackProperty(String* key) {
   10157   // Check access rights if needed.
   10158   Isolate* isolate = GetIsolate();
   10159   if (IsAccessCheckNeeded()) {
   10160     if (!isolate->MayNamedAccess(this, key, v8::ACCESS_HAS)) {
   10161       isolate->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
   10162       return false;
   10163     }
   10164   }
   10165 
   10166   LookupResult result(isolate);
   10167   LocalLookupRealNamedProperty(key, &result);
   10168   return result.IsFound() && (result.type() == CALLBACKS);
   10169 }
   10170 
   10171 
   10172 int JSObject::NumberOfLocalProperties(PropertyAttributes filter) {
   10173   return HasFastProperties() ?
   10174       map()->NumberOfDescribedProperties(filter) :
   10175       property_dictionary()->NumberOfElementsFilterAttributes(filter);
   10176 }
   10177 
   10178 
   10179 void FixedArray::SwapPairs(FixedArray* numbers, int i, int j) {
   10180   Object* temp = get(i);
   10181   set(i, get(j));
   10182   set(j, temp);
   10183   if (this != numbers) {
   10184     temp = numbers->get(i);
   10185     numbers->set(i, Smi::cast(numbers->get(j)));
   10186     numbers->set(j, Smi::cast(temp));
   10187   }
   10188 }
   10189 
   10190 
   10191 static void InsertionSortPairs(FixedArray* content,
   10192                                FixedArray* numbers,
   10193                                int len) {
   10194   for (int i = 1; i < len; i++) {
   10195     int j = i;
   10196     while (j > 0 &&
   10197            (NumberToUint32(numbers->get(j - 1)) >
   10198             NumberToUint32(numbers->get(j)))) {
   10199       content->SwapPairs(numbers, j - 1, j);
   10200       j--;
   10201     }
   10202   }
   10203 }
   10204 
   10205 
   10206 void HeapSortPairs(FixedArray* content, FixedArray* numbers, int len) {
   10207   // In-place heap sort.
   10208   ASSERT(content->length() == numbers->length());
   10209 
   10210   // Bottom-up max-heap construction.
   10211   for (int i = 1; i < len; ++i) {
   10212     int child_index = i;
   10213     while (child_index > 0) {
   10214       int parent_index = ((child_index + 1) >> 1) - 1;
   10215       uint32_t parent_value = NumberToUint32(numbers->get(parent_index));
   10216       uint32_t child_value = NumberToUint32(numbers->get(child_index));
   10217       if (parent_value < child_value) {
   10218         content->SwapPairs(numbers, parent_index, child_index);
   10219       } else {
   10220         break;
   10221       }
   10222       child_index = parent_index;
   10223     }
   10224   }
   10225 
   10226   // Extract elements and create sorted array.
   10227   for (int i = len - 1; i > 0; --i) {
   10228     // Put max element at the back of the array.
   10229     content->SwapPairs(numbers, 0, i);
   10230     // Sift down the new top element.
   10231     int parent_index = 0;
   10232     while (true) {
   10233       int child_index = ((parent_index + 1) << 1) - 1;
   10234       if (child_index >= i) break;
   10235       uint32_t child1_value = NumberToUint32(numbers->get(child_index));
   10236       uint32_t child2_value = NumberToUint32(numbers->get(child_index + 1));
   10237       uint32_t parent_value = NumberToUint32(numbers->get(parent_index));
   10238       if (child_index + 1 >= i || child1_value > child2_value) {
   10239         if (parent_value > child1_value) break;
   10240         content->SwapPairs(numbers, parent_index, child_index);
   10241         parent_index = child_index;
   10242       } else {
   10243         if (parent_value > child2_value) break;
   10244         content->SwapPairs(numbers, parent_index, child_index + 1);
   10245         parent_index = child_index + 1;
   10246       }
   10247     }
   10248   }
   10249 }
   10250 
   10251 
   10252 // Sort this array and the numbers as pairs wrt. the (distinct) numbers.
   10253 void FixedArray::SortPairs(FixedArray* numbers, uint32_t len) {
   10254   ASSERT(this->length() == numbers->length());
   10255   // For small arrays, simply use insertion sort.
   10256   if (len <= 10) {
   10257     InsertionSortPairs(this, numbers, len);
   10258     return;
   10259   }
   10260   // Check the range of indices.
   10261   uint32_t min_index = NumberToUint32(numbers->get(0));
   10262   uint32_t max_index = min_index;
   10263   uint32_t i;
   10264   for (i = 1; i < len; i++) {
   10265     if (NumberToUint32(numbers->get(i)) < min_index) {
   10266       min_index = NumberToUint32(numbers->get(i));
   10267     } else if (NumberToUint32(numbers->get(i)) > max_index) {
   10268       max_index = NumberToUint32(numbers->get(i));
   10269     }
   10270   }
   10271   if (max_index - min_index + 1 == len) {
   10272     // Indices form a contiguous range, unless there are duplicates.
   10273     // Do an in-place linear time sort assuming distinct numbers, but
   10274     // avoid hanging in case they are not.
   10275     for (i = 0; i < len; i++) {
   10276       uint32_t p;
   10277       uint32_t j = 0;
   10278       // While the current element at i is not at its correct position p,
   10279       // swap the elements at these two positions.
   10280       while ((p = NumberToUint32(numbers->get(i)) - min_index) != i &&
   10281              j++ < len) {
   10282         SwapPairs(numbers, i, p);
   10283       }
   10284     }
   10285   } else {
   10286     HeapSortPairs(this, numbers, len);
   10287     return;
   10288   }
   10289 }
   10290 
   10291 
   10292 // Fill in the names of local properties into the supplied storage. The main
   10293 // purpose of this function is to provide reflection information for the object
   10294 // mirrors.
   10295 void JSObject::GetLocalPropertyNames(FixedArray* storage, int index) {
   10296   ASSERT(storage->length() >= (NumberOfLocalProperties() - index));
   10297   if (HasFastProperties()) {
   10298     DescriptorArray* descs = map()->instance_descriptors();
   10299     for (int i = 0; i < descs->number_of_descriptors(); i++) {
   10300       if (descs->IsProperty(i)) storage->set(index++, descs->GetKey(i));
   10301     }
   10302     ASSERT(storage->length() >= index);
   10303   } else {
   10304     property_dictionary()->CopyKeysTo(storage,
   10305                                       index,
   10306                                       StringDictionary::UNSORTED);
   10307   }
   10308 }
   10309 
   10310 
   10311 int JSObject::NumberOfLocalElements(PropertyAttributes filter) {
   10312   return GetLocalElementKeys(NULL, filter);
   10313 }
   10314 
   10315 
   10316 int JSObject::NumberOfEnumElements() {
   10317   // Fast case for objects with no elements.
   10318   if (!IsJSValue() && HasFastElements()) {
   10319     uint32_t length = IsJSArray() ?
   10320         static_cast<uint32_t>(
   10321             Smi::cast(JSArray::cast(this)->length())->value()) :
   10322         static_cast<uint32_t>(FixedArray::cast(elements())->length());
   10323     if (length == 0) return 0;
   10324   }
   10325   // Compute the number of enumerable elements.
   10326   return NumberOfLocalElements(static_cast<PropertyAttributes>(DONT_ENUM));
   10327 }
   10328 
   10329 
   10330 int JSObject::GetLocalElementKeys(FixedArray* storage,
   10331                                   PropertyAttributes filter) {
   10332   int counter = 0;
   10333   switch (GetElementsKind()) {
   10334     case FAST_SMI_ONLY_ELEMENTS:
   10335     case FAST_ELEMENTS: {
   10336       int length = IsJSArray() ?
   10337           Smi::cast(JSArray::cast(this)->length())->value() :
   10338           FixedArray::cast(elements())->length();
   10339       for (int i = 0; i < length; i++) {
   10340         if (!FixedArray::cast(elements())->get(i)->IsTheHole()) {
   10341           if (storage != NULL) {
   10342             storage->set(counter, Smi::FromInt(i));
   10343           }
   10344           counter++;
   10345         }
   10346       }
   10347       ASSERT(!storage || storage->length() >= counter);
   10348       break;
   10349     }
   10350     case FAST_DOUBLE_ELEMENTS: {
   10351       int length = IsJSArray() ?
   10352           Smi::cast(JSArray::cast(this)->length())->value() :
   10353           FixedDoubleArray::cast(elements())->length();
   10354       for (int i = 0; i < length; i++) {
   10355         if (!FixedDoubleArray::cast(elements())->is_the_hole(i)) {
   10356           if (storage != NULL) {
   10357             storage->set(counter, Smi::FromInt(i));
   10358           }
   10359           counter++;
   10360         }
   10361       }
   10362       ASSERT(!storage || storage->length() >= counter);
   10363       break;
   10364     }
   10365     case EXTERNAL_PIXEL_ELEMENTS: {
   10366       int length = ExternalPixelArray::cast(elements())->length();
   10367       while (counter < length) {
   10368         if (storage != NULL) {
   10369           storage->set(counter, Smi::FromInt(counter));
   10370         }
   10371         counter++;
   10372       }
   10373       ASSERT(!storage || storage->length() >= counter);
   10374       break;
   10375     }
   10376     case EXTERNAL_BYTE_ELEMENTS:
   10377     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
   10378     case EXTERNAL_SHORT_ELEMENTS:
   10379     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
   10380     case EXTERNAL_INT_ELEMENTS:
   10381     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
   10382     case EXTERNAL_FLOAT_ELEMENTS:
   10383     case EXTERNAL_DOUBLE_ELEMENTS: {
   10384       int length = ExternalArray::cast(elements())->length();
   10385       while (counter < length) {
   10386         if (storage != NULL) {
   10387           storage->set(counter, Smi::FromInt(counter));
   10388         }
   10389         counter++;
   10390       }
   10391       ASSERT(!storage || storage->length() >= counter);
   10392       break;
   10393     }
   10394     case DICTIONARY_ELEMENTS: {
   10395       if (storage != NULL) {
   10396         element_dictionary()->CopyKeysTo(storage,
   10397                                          filter,
   10398                                          SeededNumberDictionary::SORTED);
   10399       }
   10400       counter += element_dictionary()->NumberOfElementsFilterAttributes(filter);
   10401       break;
   10402     }
   10403     case NON_STRICT_ARGUMENTS_ELEMENTS: {
   10404       FixedArray* parameter_map = FixedArray::cast(elements());
   10405       int mapped_length = parameter_map->length() - 2;
   10406       FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
   10407       if (arguments->IsDictionary()) {
   10408         // Copy the keys from arguments first, because Dictionary::CopyKeysTo
   10409         // will insert in storage starting at index 0.
   10410         SeededNumberDictionary* dictionary =
   10411             SeededNumberDictionary::cast(arguments);
   10412         if (storage != NULL) {
   10413           dictionary->CopyKeysTo(
   10414               storage, filter, SeededNumberDictionary::UNSORTED);
   10415         }
   10416         counter += dictionary->NumberOfElementsFilterAttributes(filter);
   10417         for (int i = 0; i < mapped_length; ++i) {
   10418           if (!parameter_map->get(i + 2)->IsTheHole()) {
   10419             if (storage != NULL) storage->set(counter, Smi::FromInt(i));
   10420             ++counter;
   10421           }
   10422         }
   10423         if (storage != NULL) storage->SortPairs(storage, counter);
   10424 
   10425       } else {
   10426         int backing_length = arguments->length();
   10427         int i = 0;
   10428         for (; i < mapped_length; ++i) {
   10429           if (!parameter_map->get(i + 2)->IsTheHole()) {
   10430             if (storage != NULL) storage->set(counter, Smi::FromInt(i));
   10431             ++counter;
   10432           } else if (i < backing_length && !arguments->get(i)->IsTheHole()) {
   10433             if (storage != NULL) storage->set(counter, Smi::FromInt(i));
   10434             ++counter;
   10435           }
   10436         }
   10437         for (; i < backing_length; ++i) {
   10438           if (storage != NULL) storage->set(counter, Smi::FromInt(i));
   10439           ++counter;
   10440         }
   10441       }
   10442       break;
   10443     }
   10444   }
   10445 
   10446   if (this->IsJSValue()) {
   10447     Object* val = JSValue::cast(this)->value();
   10448     if (val->IsString()) {
   10449       String* str = String::cast(val);
   10450       if (storage) {
   10451         for (int i = 0; i < str->length(); i++) {
   10452           storage->set(counter + i, Smi::FromInt(i));
   10453         }
   10454       }
   10455       counter += str->length();
   10456     }
   10457   }
   10458   ASSERT(!storage || storage->length() == counter);
   10459   return counter;
   10460 }
   10461 
   10462 
   10463 int JSObject::GetEnumElementKeys(FixedArray* storage) {
   10464   return GetLocalElementKeys(storage,
   10465                              static_cast<PropertyAttributes>(DONT_ENUM));
   10466 }
   10467 
   10468 
   10469 // StringKey simply carries a string object as key.
   10470 class StringKey : public HashTableKey {
   10471  public:
   10472   explicit StringKey(String* string) :
   10473       string_(string),
   10474       hash_(HashForObject(string)) { }
   10475 
   10476   bool IsMatch(Object* string) {
   10477     // We know that all entries in a hash table had their hash keys created.
   10478     // Use that knowledge to have fast failure.
   10479     if (hash_ != HashForObject(string)) {
   10480       return false;
   10481     }
   10482     return string_->Equals(String::cast(string));
   10483   }
   10484 
   10485   uint32_t Hash() { return hash_; }
   10486 
   10487   uint32_t HashForObject(Object* other) { return String::cast(other)->Hash(); }
   10488 
   10489   Object* AsObject() { return string_; }
   10490 
   10491   String* string_;
   10492   uint32_t hash_;
   10493 };
   10494 
   10495 
   10496 // StringSharedKeys are used as keys in the eval cache.
   10497 class StringSharedKey : public HashTableKey {
   10498  public:
   10499   StringSharedKey(String* source,
   10500                   SharedFunctionInfo* shared,
   10501                   LanguageMode language_mode,
   10502                   int scope_position)
   10503       : source_(source),
   10504         shared_(shared),
   10505         language_mode_(language_mode),
   10506         scope_position_(scope_position) { }
   10507 
   10508   bool IsMatch(Object* other) {
   10509     if (!other->IsFixedArray()) return false;
   10510     FixedArray* other_array = FixedArray::cast(other);
   10511     SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0));
   10512     if (shared != shared_) return false;
   10513     int language_unchecked = Smi::cast(other_array->get(2))->value();
   10514     ASSERT(language_unchecked == CLASSIC_MODE ||
   10515            language_unchecked == STRICT_MODE ||
   10516            language_unchecked == EXTENDED_MODE);
   10517     LanguageMode language_mode = static_cast<LanguageMode>(language_unchecked);
   10518     if (language_mode != language_mode_) return false;
   10519     int scope_position = Smi::cast(other_array->get(3))->value();
   10520     if (scope_position != scope_position_) return false;
   10521     String* source = String::cast(other_array->get(1));
   10522     return source->Equals(source_);
   10523   }
   10524 
   10525   static uint32_t StringSharedHashHelper(String* source,
   10526                                          SharedFunctionInfo* shared,
   10527                                          LanguageMode language_mode,
   10528                                          int scope_position) {
   10529     uint32_t hash = source->Hash();
   10530     if (shared->HasSourceCode()) {
   10531       // Instead of using the SharedFunctionInfo pointer in the hash
   10532       // code computation, we use a combination of the hash of the
   10533       // script source code and the start position of the calling scope.
   10534       // We do this to ensure that the cache entries can survive garbage
   10535       // collection.
   10536       Script* script = Script::cast(shared->script());
   10537       hash ^= String::cast(script->source())->Hash();
   10538       if (language_mode == STRICT_MODE) hash ^= 0x8000;
   10539       if (language_mode == EXTENDED_MODE) hash ^= 0x0080;
   10540       hash += scope_position;
   10541     }
   10542     return hash;
   10543   }
   10544 
   10545   uint32_t Hash() {
   10546     return StringSharedHashHelper(
   10547         source_, shared_, language_mode_, scope_position_);
   10548   }
   10549 
   10550   uint32_t HashForObject(Object* obj) {
   10551     FixedArray* other_array = FixedArray::cast(obj);
   10552     SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0));
   10553     String* source = String::cast(other_array->get(1));
   10554     int language_unchecked = Smi::cast(other_array->get(2))->value();
   10555     ASSERT(language_unchecked == CLASSIC_MODE ||
   10556            language_unchecked == STRICT_MODE ||
   10557            language_unchecked == EXTENDED_MODE);
   10558     LanguageMode language_mode = static_cast<LanguageMode>(language_unchecked);
   10559     int scope_position = Smi::cast(other_array->get(3))->value();
   10560     return StringSharedHashHelper(
   10561         source, shared, language_mode, scope_position);
   10562   }
   10563 
   10564   MUST_USE_RESULT MaybeObject* AsObject() {
   10565     Object* obj;
   10566     { MaybeObject* maybe_obj = source_->GetHeap()->AllocateFixedArray(4);
   10567       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   10568     }
   10569     FixedArray* other_array = FixedArray::cast(obj);
   10570     other_array->set(0, shared_);
   10571     other_array->set(1, source_);
   10572     other_array->set(2, Smi::FromInt(language_mode_));
   10573     other_array->set(3, Smi::FromInt(scope_position_));
   10574     return other_array;
   10575   }
   10576 
   10577  private:
   10578   String* source_;
   10579   SharedFunctionInfo* shared_;
   10580   LanguageMode language_mode_;
   10581   int scope_position_;
   10582 };
   10583 
   10584 
   10585 // RegExpKey carries the source and flags of a regular expression as key.
   10586 class RegExpKey : public HashTableKey {
   10587  public:
   10588   RegExpKey(String* string, JSRegExp::Flags flags)
   10589       : string_(string),
   10590         flags_(Smi::FromInt(flags.value())) { }
   10591 
   10592   // Rather than storing the key in the hash table, a pointer to the
   10593   // stored value is stored where the key should be.  IsMatch then
   10594   // compares the search key to the found object, rather than comparing
   10595   // a key to a key.
   10596   bool IsMatch(Object* obj) {
   10597     FixedArray* val = FixedArray::cast(obj);
   10598     return string_->Equals(String::cast(val->get(JSRegExp::kSourceIndex)))
   10599         && (flags_ == val->get(JSRegExp::kFlagsIndex));
   10600   }
   10601 
   10602   uint32_t Hash() { return RegExpHash(string_, flags_); }
   10603 
   10604   Object* AsObject() {
   10605     // Plain hash maps, which is where regexp keys are used, don't
   10606     // use this function.
   10607     UNREACHABLE();
   10608     return NULL;
   10609   }
   10610 
   10611   uint32_t HashForObject(Object* obj) {
   10612     FixedArray* val = FixedArray::cast(obj);
   10613     return RegExpHash(String::cast(val->get(JSRegExp::kSourceIndex)),
   10614                       Smi::cast(val->get(JSRegExp::kFlagsIndex)));
   10615   }
   10616 
   10617   static uint32_t RegExpHash(String* string, Smi* flags) {
   10618     return string->Hash() + flags->value();
   10619   }
   10620 
   10621   String* string_;
   10622   Smi* flags_;
   10623 };
   10624 
   10625 // Utf8SymbolKey carries a vector of chars as key.
   10626 class Utf8SymbolKey : public HashTableKey {
   10627  public:
   10628   explicit Utf8SymbolKey(Vector<const char> string, uint32_t seed)
   10629       : string_(string), hash_field_(0), seed_(seed) { }
   10630 
   10631   bool IsMatch(Object* string) {
   10632     return String::cast(string)->IsEqualTo(string_);
   10633   }
   10634 
   10635   uint32_t Hash() {
   10636     if (hash_field_ != 0) return hash_field_ >> String::kHashShift;
   10637     unibrow::Utf8InputBuffer<> buffer(string_.start(),
   10638                                       static_cast<unsigned>(string_.length()));
   10639     chars_ = buffer.Utf16Length();
   10640     hash_field_ = String::ComputeHashField(&buffer, chars_, seed_);
   10641     uint32_t result = hash_field_ >> String::kHashShift;
   10642     ASSERT(result != 0);  // Ensure that the hash value of 0 is never computed.
   10643     return result;
   10644   }
   10645 
   10646   uint32_t HashForObject(Object* other) {
   10647     return String::cast(other)->Hash();
   10648   }
   10649 
   10650   MaybeObject* AsObject() {
   10651     if (hash_field_ == 0) Hash();
   10652     return Isolate::Current()->heap()->AllocateSymbol(
   10653         string_, chars_, hash_field_);
   10654   }
   10655 
   10656   Vector<const char> string_;
   10657   uint32_t hash_field_;
   10658   int chars_;  // Caches the number of characters when computing the hash code.
   10659   uint32_t seed_;
   10660 };
   10661 
   10662 
   10663 template <typename Char>
   10664 class SequentialSymbolKey : public HashTableKey {
   10665  public:
   10666   explicit SequentialSymbolKey(Vector<const Char> string, uint32_t seed)
   10667       : string_(string), hash_field_(0), seed_(seed) { }
   10668 
   10669   uint32_t Hash() {
   10670     StringHasher hasher(string_.length(), seed_);
   10671 
   10672     // Very long strings have a trivial hash that doesn't inspect the
   10673     // string contents.
   10674     if (hasher.has_trivial_hash()) {
   10675       hash_field_ = hasher.GetHashField();
   10676     } else {
   10677       int i = 0;
   10678       // Do the iterative array index computation as long as there is a
   10679       // chance this is an array index.
   10680       while (i < string_.length() && hasher.is_array_index()) {
   10681         hasher.AddCharacter(static_cast<uc32>(string_[i]));
   10682         i++;
   10683       }
   10684 
   10685       // Process the remaining characters without updating the array
   10686       // index.
   10687       while (i < string_.length()) {
   10688         hasher.AddCharacterNoIndex(static_cast<uc32>(string_[i]));
   10689         i++;
   10690       }
   10691       hash_field_ = hasher.GetHashField();
   10692     }
   10693 
   10694     uint32_t result = hash_field_ >> String::kHashShift;
   10695     ASSERT(result != 0);  // Ensure that the hash value of 0 is never computed.
   10696     return result;
   10697   }
   10698 
   10699 
   10700   uint32_t HashForObject(Object* other) {
   10701     return String::cast(other)->Hash();
   10702   }
   10703 
   10704   Vector<const Char> string_;
   10705   uint32_t hash_field_;
   10706   uint32_t seed_;
   10707 };
   10708 
   10709 
   10710 
   10711 class AsciiSymbolKey : public SequentialSymbolKey<char> {
   10712  public:
   10713   AsciiSymbolKey(Vector<const char> str, uint32_t seed)
   10714       : SequentialSymbolKey<char>(str, seed) { }
   10715 
   10716   bool IsMatch(Object* string) {
   10717     return String::cast(string)->IsAsciiEqualTo(string_);
   10718   }
   10719 
   10720   MaybeObject* AsObject() {
   10721     if (hash_field_ == 0) Hash();
   10722     return HEAP->AllocateAsciiSymbol(string_, hash_field_);
   10723   }
   10724 };
   10725 
   10726 
   10727 class SubStringAsciiSymbolKey : public HashTableKey {
   10728  public:
   10729   explicit SubStringAsciiSymbolKey(Handle<SeqAsciiString> string,
   10730                                    int from,
   10731                                    int length,
   10732                                    uint32_t seed)
   10733       : string_(string), from_(from), length_(length), seed_(seed) { }
   10734 
   10735   uint32_t Hash() {
   10736     ASSERT(length_ >= 0);
   10737     ASSERT(from_ + length_ <= string_->length());
   10738     StringHasher hasher(length_, string_->GetHeap()->HashSeed());
   10739 
   10740     // Very long strings have a trivial hash that doesn't inspect the
   10741     // string contents.
   10742     if (hasher.has_trivial_hash()) {
   10743       hash_field_ = hasher.GetHashField();
   10744     } else {
   10745       int i = 0;
   10746       // Do the iterative array index computation as long as there is a
   10747       // chance this is an array index.
   10748       while (i < length_ && hasher.is_array_index()) {
   10749         hasher.AddCharacter(static_cast<uc32>(
   10750             string_->SeqAsciiStringGet(i + from_)));
   10751         i++;
   10752       }
   10753 
   10754       // Process the remaining characters without updating the array
   10755       // index.
   10756       while (i < length_) {
   10757         hasher.AddCharacterNoIndex(static_cast<uc32>(
   10758             string_->SeqAsciiStringGet(i + from_)));
   10759         i++;
   10760       }
   10761       hash_field_ = hasher.GetHashField();
   10762     }
   10763 
   10764     uint32_t result = hash_field_ >> String::kHashShift;
   10765     ASSERT(result != 0);  // Ensure that the hash value of 0 is never computed.
   10766     return result;
   10767   }
   10768 
   10769 
   10770   uint32_t HashForObject(Object* other) {
   10771     return String::cast(other)->Hash();
   10772   }
   10773 
   10774   bool IsMatch(Object* string) {
   10775     Vector<const char> chars(string_->GetChars() + from_, length_);
   10776     return String::cast(string)->IsAsciiEqualTo(chars);
   10777   }
   10778 
   10779   MaybeObject* AsObject() {
   10780     if (hash_field_ == 0) Hash();
   10781     Vector<const char> chars(string_->GetChars() + from_, length_);
   10782     return HEAP->AllocateAsciiSymbol(chars, hash_field_);
   10783   }
   10784 
   10785  private:
   10786   Handle<SeqAsciiString> string_;
   10787   int from_;
   10788   int length_;
   10789   uint32_t hash_field_;
   10790   uint32_t seed_;
   10791 };
   10792 
   10793 
   10794 class TwoByteSymbolKey : public SequentialSymbolKey<uc16> {
   10795  public:
   10796   explicit TwoByteSymbolKey(Vector<const uc16> str, uint32_t seed)
   10797       : SequentialSymbolKey<uc16>(str, seed) { }
   10798 
   10799   bool IsMatch(Object* string) {
   10800     return String::cast(string)->IsTwoByteEqualTo(string_);
   10801   }
   10802 
   10803   MaybeObject* AsObject() {
   10804     if (hash_field_ == 0) Hash();
   10805     return HEAP->AllocateTwoByteSymbol(string_, hash_field_);
   10806   }
   10807 };
   10808 
   10809 
   10810 // SymbolKey carries a string/symbol object as key.
   10811 class SymbolKey : public HashTableKey {
   10812  public:
   10813   explicit SymbolKey(String* string)
   10814       : string_(string) { }
   10815 
   10816   bool IsMatch(Object* string) {
   10817     return String::cast(string)->Equals(string_);
   10818   }
   10819 
   10820   uint32_t Hash() { return string_->Hash(); }
   10821 
   10822   uint32_t HashForObject(Object* other) {
   10823     return String::cast(other)->Hash();
   10824   }
   10825 
   10826   MaybeObject* AsObject() {
   10827     // Attempt to flatten the string, so that symbols will most often
   10828     // be flat strings.
   10829     string_ = string_->TryFlattenGetString();
   10830     Heap* heap = string_->GetHeap();
   10831     // Transform string to symbol if possible.
   10832     Map* map = heap->SymbolMapForString(string_);
   10833     if (map != NULL) {
   10834       string_->set_map_no_write_barrier(map);
   10835       ASSERT(string_->IsSymbol());
   10836       return string_;
   10837     }
   10838     // Otherwise allocate a new symbol.
   10839     StringInputBuffer buffer(string_);
   10840     return heap->AllocateInternalSymbol(&buffer,
   10841                                         string_->length(),
   10842                                         string_->hash_field());
   10843   }
   10844 
   10845   static uint32_t StringHash(Object* obj) {
   10846     return String::cast(obj)->Hash();
   10847   }
   10848 
   10849   String* string_;
   10850 };
   10851 
   10852 
   10853 template<typename Shape, typename Key>
   10854 void HashTable<Shape, Key>::IteratePrefix(ObjectVisitor* v) {
   10855   IteratePointers(v, 0, kElementsStartOffset);
   10856 }
   10857 
   10858 
   10859 template<typename Shape, typename Key>
   10860 void HashTable<Shape, Key>::IterateElements(ObjectVisitor* v) {
   10861   IteratePointers(v,
   10862                   kElementsStartOffset,
   10863                   kHeaderSize + length() * kPointerSize);
   10864 }
   10865 
   10866 
   10867 template<typename Shape, typename Key>
   10868 MaybeObject* HashTable<Shape, Key>::Allocate(int at_least_space_for,
   10869                                              PretenureFlag pretenure) {
   10870   int capacity = ComputeCapacity(at_least_space_for);
   10871   if (capacity > HashTable::kMaxCapacity) {
   10872     return Failure::OutOfMemoryException();
   10873   }
   10874 
   10875   Object* obj;
   10876   { MaybeObject* maybe_obj = Isolate::Current()->heap()->
   10877         AllocateHashTable(EntryToIndex(capacity), pretenure);
   10878     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   10879   }
   10880   HashTable::cast(obj)->SetNumberOfElements(0);
   10881   HashTable::cast(obj)->SetNumberOfDeletedElements(0);
   10882   HashTable::cast(obj)->SetCapacity(capacity);
   10883   return obj;
   10884 }
   10885 
   10886 
   10887 // Find entry for key otherwise return kNotFound.
   10888 int StringDictionary::FindEntry(String* key) {
   10889   if (!key->IsSymbol()) {
   10890     return HashTable<StringDictionaryShape, String*>::FindEntry(key);
   10891   }
   10892 
   10893   // Optimized for symbol key. Knowledge of the key type allows:
   10894   // 1. Move the check if the key is a symbol out of the loop.
   10895   // 2. Avoid comparing hash codes in symbol to symbol comparison.
   10896   // 3. Detect a case when a dictionary key is not a symbol but the key is.
   10897   //    In case of positive result the dictionary key may be replaced by
   10898   //    the symbol with minimal performance penalty. It gives a chance to
   10899   //    perform further lookups in code stubs (and significant performance boost
   10900   //    a certain style of code).
   10901 
   10902   // EnsureCapacity will guarantee the hash table is never full.
   10903   uint32_t capacity = Capacity();
   10904   uint32_t entry = FirstProbe(key->Hash(), capacity);
   10905   uint32_t count = 1;
   10906 
   10907   while (true) {
   10908     int index = EntryToIndex(entry);
   10909     Object* element = get(index);
   10910     if (element->IsUndefined()) break;  // Empty entry.
   10911     if (key == element) return entry;
   10912     if (!element->IsSymbol() &&
   10913         !element->IsTheHole() &&
   10914         String::cast(element)->Equals(key)) {
   10915       // Replace a non-symbol key by the equivalent symbol for faster further
   10916       // lookups.
   10917       set(index, key);
   10918       return entry;
   10919     }
   10920     ASSERT(element->IsTheHole() || !String::cast(element)->Equals(key));
   10921     entry = NextProbe(entry, count++, capacity);
   10922   }
   10923   return kNotFound;
   10924 }
   10925 
   10926 
   10927 bool StringDictionary::ContainsTransition(int entry) {
   10928   switch (DetailsAt(entry).type()) {
   10929     case MAP_TRANSITION:
   10930     case CONSTANT_TRANSITION:
   10931     case ELEMENTS_TRANSITION:
   10932       return true;
   10933     case CALLBACKS: {
   10934       Object* value = ValueAt(entry);
   10935       if (!value->IsAccessorPair()) return false;
   10936       AccessorPair* accessors = AccessorPair::cast(value);
   10937       return accessors->getter()->IsMap() || accessors->setter()->IsMap();
   10938     }
   10939     case NORMAL:
   10940     case FIELD:
   10941     case CONSTANT_FUNCTION:
   10942     case HANDLER:
   10943     case INTERCEPTOR:
   10944     case NULL_DESCRIPTOR:
   10945       return false;
   10946   }
   10947   UNREACHABLE();  // Keep the compiler happy.
   10948   return false;
   10949 }
   10950 
   10951 
   10952 template<typename Shape, typename Key>
   10953 MaybeObject* HashTable<Shape, Key>::Rehash(HashTable* new_table, Key key) {
   10954   ASSERT(NumberOfElements() < new_table->Capacity());
   10955 
   10956   AssertNoAllocation no_gc;
   10957   WriteBarrierMode mode = new_table->GetWriteBarrierMode(no_gc);
   10958 
   10959   // Copy prefix to new array.
   10960   for (int i = kPrefixStartIndex;
   10961        i < kPrefixStartIndex + Shape::kPrefixSize;
   10962        i++) {
   10963     new_table->set(i, get(i), mode);
   10964   }
   10965 
   10966   // Rehash the elements.
   10967   int capacity = Capacity();
   10968   for (int i = 0; i < capacity; i++) {
   10969     uint32_t from_index = EntryToIndex(i);
   10970     Object* k = get(from_index);
   10971     if (IsKey(k)) {
   10972       uint32_t hash = HashTable<Shape, Key>::HashForObject(key, k);
   10973       uint32_t insertion_index =
   10974           EntryToIndex(new_table->FindInsertionEntry(hash));
   10975       for (int j = 0; j < Shape::kEntrySize; j++) {
   10976         new_table->set(insertion_index + j, get(from_index + j), mode);
   10977       }
   10978     }
   10979   }
   10980   new_table->SetNumberOfElements(NumberOfElements());
   10981   new_table->SetNumberOfDeletedElements(0);
   10982   return new_table;
   10983 }
   10984 
   10985 
   10986 template<typename Shape, typename Key>
   10987 MaybeObject* HashTable<Shape, Key>::EnsureCapacity(int n, Key key) {
   10988   int capacity = Capacity();
   10989   int nof = NumberOfElements() + n;
   10990   int nod = NumberOfDeletedElements();
   10991   // Return if:
   10992   //   50% is still free after adding n elements and
   10993   //   at most 50% of the free elements are deleted elements.
   10994   if (nod <= (capacity - nof) >> 1) {
   10995     int needed_free = nof >> 1;
   10996     if (nof + needed_free <= capacity) return this;
   10997   }
   10998 
   10999   const int kMinCapacityForPretenure = 256;
   11000   bool pretenure =
   11001       (capacity > kMinCapacityForPretenure) && !GetHeap()->InNewSpace(this);
   11002   Object* obj;
   11003   { MaybeObject* maybe_obj =
   11004         Allocate(nof * 2, pretenure ? TENURED : NOT_TENURED);
   11005     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   11006   }
   11007 
   11008   return Rehash(HashTable::cast(obj), key);
   11009 }
   11010 
   11011 
   11012 template<typename Shape, typename Key>
   11013 MaybeObject* HashTable<Shape, Key>::Shrink(Key key) {
   11014   int capacity = Capacity();
   11015   int nof = NumberOfElements();
   11016 
   11017   // Shrink to fit the number of elements if only a quarter of the
   11018   // capacity is filled with elements.
   11019   if (nof > (capacity >> 2)) return this;
   11020   // Allocate a new dictionary with room for at least the current
   11021   // number of elements. The allocation method will make sure that
   11022   // there is extra room in the dictionary for additions. Don't go
   11023   // lower than room for 16 elements.
   11024   int at_least_room_for = nof;
   11025   if (at_least_room_for < 16) return this;
   11026 
   11027   const int kMinCapacityForPretenure = 256;
   11028   bool pretenure =
   11029       (at_least_room_for > kMinCapacityForPretenure) &&
   11030       !GetHeap()->InNewSpace(this);
   11031   Object* obj;
   11032   { MaybeObject* maybe_obj =
   11033         Allocate(at_least_room_for, pretenure ? TENURED : NOT_TENURED);
   11034     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   11035   }
   11036 
   11037   return Rehash(HashTable::cast(obj), key);
   11038 }
   11039 
   11040 
   11041 template<typename Shape, typename Key>
   11042 uint32_t HashTable<Shape, Key>::FindInsertionEntry(uint32_t hash) {
   11043   uint32_t capacity = Capacity();
   11044   uint32_t entry = FirstProbe(hash, capacity);
   11045   uint32_t count = 1;
   11046   // EnsureCapacity will guarantee the hash table is never full.
   11047   while (true) {
   11048     Object* element = KeyAt(entry);
   11049     if (element->IsUndefined() || element->IsTheHole()) break;
   11050     entry = NextProbe(entry, count++, capacity);
   11051   }
   11052   return entry;
   11053 }
   11054 
   11055 // Force instantiation of template instances class.
   11056 // Please note this list is compiler dependent.
   11057 
   11058 template class HashTable<SymbolTableShape, HashTableKey*>;
   11059 
   11060 template class HashTable<CompilationCacheShape, HashTableKey*>;
   11061 
   11062 template class HashTable<MapCacheShape, HashTableKey*>;
   11063 
   11064 template class HashTable<ObjectHashTableShape<1>, Object*>;
   11065 
   11066 template class HashTable<ObjectHashTableShape<2>, Object*>;
   11067 
   11068 template class Dictionary<StringDictionaryShape, String*>;
   11069 
   11070 template class Dictionary<SeededNumberDictionaryShape, uint32_t>;
   11071 
   11072 template class Dictionary<UnseededNumberDictionaryShape, uint32_t>;
   11073 
   11074 template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>::
   11075     Allocate(int at_least_space_for);
   11076 
   11077 template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>::
   11078     Allocate(int at_least_space_for);
   11079 
   11080 template MaybeObject* Dictionary<StringDictionaryShape, String*>::Allocate(
   11081     int);
   11082 
   11083 template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>::AtPut(
   11084     uint32_t, Object*);
   11085 
   11086 template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>::
   11087     AtPut(uint32_t, Object*);
   11088 
   11089 template Object* Dictionary<SeededNumberDictionaryShape, uint32_t>::
   11090     SlowReverseLookup(Object* value);
   11091 
   11092 template Object* Dictionary<UnseededNumberDictionaryShape, uint32_t>::
   11093     SlowReverseLookup(Object* value);
   11094 
   11095 template Object* Dictionary<StringDictionaryShape, String*>::SlowReverseLookup(
   11096     Object*);
   11097 
   11098 template void Dictionary<SeededNumberDictionaryShape, uint32_t>::CopyKeysTo(
   11099     FixedArray*,
   11100     PropertyAttributes,
   11101     Dictionary<SeededNumberDictionaryShape, uint32_t>::SortMode);
   11102 
   11103 template Object* Dictionary<StringDictionaryShape, String*>::DeleteProperty(
   11104     int, JSObject::DeleteMode);
   11105 
   11106 template Object* Dictionary<SeededNumberDictionaryShape, uint32_t>::
   11107     DeleteProperty(int, JSObject::DeleteMode);
   11108 
   11109 template MaybeObject* Dictionary<StringDictionaryShape, String*>::Shrink(
   11110     String*);
   11111 
   11112 template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>::Shrink(
   11113     uint32_t);
   11114 
   11115 template void Dictionary<StringDictionaryShape, String*>::CopyKeysTo(
   11116     FixedArray*,
   11117     int,
   11118     Dictionary<StringDictionaryShape, String*>::SortMode);
   11119 
   11120 template int
   11121 Dictionary<StringDictionaryShape, String*>::NumberOfElementsFilterAttributes(
   11122     PropertyAttributes);
   11123 
   11124 template MaybeObject* Dictionary<StringDictionaryShape, String*>::Add(
   11125     String*, Object*, PropertyDetails);
   11126 
   11127 template MaybeObject*
   11128 Dictionary<StringDictionaryShape, String*>::GenerateNewEnumerationIndices();
   11129 
   11130 template int
   11131 Dictionary<SeededNumberDictionaryShape, uint32_t>::
   11132     NumberOfElementsFilterAttributes(PropertyAttributes);
   11133 
   11134 template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>::Add(
   11135     uint32_t, Object*, PropertyDetails);
   11136 
   11137 template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>::Add(
   11138     uint32_t, Object*, PropertyDetails);
   11139 
   11140 template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>::
   11141     EnsureCapacity(int, uint32_t);
   11142 
   11143 template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>::
   11144     EnsureCapacity(int, uint32_t);
   11145 
   11146 template MaybeObject* Dictionary<StringDictionaryShape, String*>::
   11147     EnsureCapacity(int, String*);
   11148 
   11149 template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>::
   11150     AddEntry(uint32_t, Object*, PropertyDetails, uint32_t);
   11151 
   11152 template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>::
   11153     AddEntry(uint32_t, Object*, PropertyDetails, uint32_t);
   11154 
   11155 template MaybeObject* Dictionary<StringDictionaryShape, String*>::AddEntry(
   11156     String*, Object*, PropertyDetails, uint32_t);
   11157 
   11158 template
   11159 int Dictionary<SeededNumberDictionaryShape, uint32_t>::NumberOfEnumElements();
   11160 
   11161 template
   11162 int Dictionary<StringDictionaryShape, String*>::NumberOfEnumElements();
   11163 
   11164 template
   11165 int HashTable<SeededNumberDictionaryShape, uint32_t>::FindEntry(uint32_t);
   11166 
   11167 
   11168 // Collates undefined and unexisting elements below limit from position
   11169 // zero of the elements. The object stays in Dictionary mode.
   11170 MaybeObject* JSObject::PrepareSlowElementsForSort(uint32_t limit) {
   11171   ASSERT(HasDictionaryElements());
   11172   // Must stay in dictionary mode, either because of requires_slow_elements,
   11173   // or because we are not going to sort (and therefore compact) all of the
   11174   // elements.
   11175   SeededNumberDictionary* dict = element_dictionary();
   11176   HeapNumber* result_double = NULL;
   11177   if (limit > static_cast<uint32_t>(Smi::kMaxValue)) {
   11178     // Allocate space for result before we start mutating the object.
   11179     Object* new_double;
   11180     { MaybeObject* maybe_new_double = GetHeap()->AllocateHeapNumber(0.0);
   11181       if (!maybe_new_double->ToObject(&new_double)) return maybe_new_double;
   11182     }
   11183     result_double = HeapNumber::cast(new_double);
   11184   }
   11185 
   11186   Object* obj;
   11187   { MaybeObject* maybe_obj =
   11188         SeededNumberDictionary::Allocate(dict->NumberOfElements());
   11189     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   11190   }
   11191   SeededNumberDictionary* new_dict = SeededNumberDictionary::cast(obj);
   11192 
   11193   AssertNoAllocation no_alloc;
   11194 
   11195   uint32_t pos = 0;
   11196   uint32_t undefs = 0;
   11197   int capacity = dict->Capacity();
   11198   for (int i = 0; i < capacity; i++) {
   11199     Object* k = dict->KeyAt(i);
   11200     if (dict->IsKey(k)) {
   11201       ASSERT(k->IsNumber());
   11202       ASSERT(!k->IsSmi() || Smi::cast(k)->value() >= 0);
   11203       ASSERT(!k->IsHeapNumber() || HeapNumber::cast(k)->value() >= 0);
   11204       ASSERT(!k->IsHeapNumber() || HeapNumber::cast(k)->value() <= kMaxUInt32);
   11205       Object* value = dict->ValueAt(i);
   11206       PropertyDetails details = dict->DetailsAt(i);
   11207       if (details.type() == CALLBACKS) {
   11208         // Bail out and do the sorting of undefineds and array holes in JS.
   11209         return Smi::FromInt(-1);
   11210       }
   11211       uint32_t key = NumberToUint32(k);
   11212       // In the following we assert that adding the entry to the new dictionary
   11213       // does not cause GC.  This is the case because we made sure to allocate
   11214       // the dictionary big enough above, so it need not grow.
   11215       if (key < limit) {
   11216         if (value->IsUndefined()) {
   11217           undefs++;
   11218         } else {
   11219           if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
   11220             // Adding an entry with the key beyond smi-range requires
   11221             // allocation. Bailout.
   11222             return Smi::FromInt(-1);
   11223           }
   11224           new_dict->AddNumberEntry(pos, value, details)->ToObjectUnchecked();
   11225           pos++;
   11226         }
   11227       } else {
   11228         if (key > static_cast<uint32_t>(Smi::kMaxValue)) {
   11229           // Adding an entry with the key beyond smi-range requires
   11230           // allocation. Bailout.
   11231           return Smi::FromInt(-1);
   11232         }
   11233         new_dict->AddNumberEntry(key, value, details)->ToObjectUnchecked();
   11234       }
   11235     }
   11236   }
   11237 
   11238   uint32_t result = pos;
   11239   PropertyDetails no_details = PropertyDetails(NONE, NORMAL);
   11240   Heap* heap = GetHeap();
   11241   while (undefs > 0) {
   11242     if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
   11243       // Adding an entry with the key beyond smi-range requires
   11244       // allocation. Bailout.
   11245       return Smi::FromInt(-1);
   11246     }
   11247     new_dict->AddNumberEntry(pos, heap->undefined_value(), no_details)->
   11248         ToObjectUnchecked();
   11249     pos++;
   11250     undefs--;
   11251   }
   11252 
   11253   set_elements(new_dict);
   11254 
   11255   if (result <= static_cast<uint32_t>(Smi::kMaxValue)) {
   11256     return Smi::FromInt(static_cast<int>(result));
   11257   }
   11258 
   11259   ASSERT_NE(NULL, result_double);
   11260   result_double->set_value(static_cast<double>(result));
   11261   return result_double;
   11262 }
   11263 
   11264 
   11265 // Collects all defined (non-hole) and non-undefined (array) elements at
   11266 // the start of the elements array.
   11267 // If the object is in dictionary mode, it is converted to fast elements
   11268 // mode.
   11269 MaybeObject* JSObject::PrepareElementsForSort(uint32_t limit) {
   11270   Heap* heap = GetHeap();
   11271 
   11272   if (HasDictionaryElements()) {
   11273     // Convert to fast elements containing only the existing properties.
   11274     // Ordering is irrelevant, since we are going to sort anyway.
   11275     SeededNumberDictionary* dict = element_dictionary();
   11276     if (IsJSArray() || dict->requires_slow_elements() ||
   11277         dict->max_number_key() >= limit) {
   11278       return PrepareSlowElementsForSort(limit);
   11279     }
   11280     // Convert to fast elements.
   11281 
   11282     Object* obj;
   11283     { MaybeObject* maybe_obj = GetElementsTransitionMap(GetIsolate(),
   11284                                                         FAST_ELEMENTS);
   11285       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   11286     }
   11287     Map* new_map = Map::cast(obj);
   11288 
   11289     PretenureFlag tenure = heap->InNewSpace(this) ? NOT_TENURED: TENURED;
   11290     Object* new_array;
   11291     { MaybeObject* maybe_new_array =
   11292           heap->AllocateFixedArray(dict->NumberOfElements(), tenure);
   11293       if (!maybe_new_array->ToObject(&new_array)) return maybe_new_array;
   11294     }
   11295     FixedArray* fast_elements = FixedArray::cast(new_array);
   11296     dict->CopyValuesTo(fast_elements);
   11297 
   11298     set_map(new_map);
   11299     set_elements(fast_elements);
   11300   } else if (HasExternalArrayElements()) {
   11301     // External arrays cannot have holes or undefined elements.
   11302     return Smi::FromInt(ExternalArray::cast(elements())->length());
   11303   } else if (!HasFastDoubleElements()) {
   11304     Object* obj;
   11305     { MaybeObject* maybe_obj = EnsureWritableFastElements();
   11306       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   11307     }
   11308   }
   11309   ASSERT(HasFastTypeElements() || HasFastDoubleElements());
   11310 
   11311   // Collect holes at the end, undefined before that and the rest at the
   11312   // start, and return the number of non-hole, non-undefined values.
   11313 
   11314   FixedArrayBase* elements_base = FixedArrayBase::cast(this->elements());
   11315   uint32_t elements_length = static_cast<uint32_t>(elements_base->length());
   11316   if (limit > elements_length) {
   11317     limit = elements_length ;
   11318   }
   11319   if (limit == 0) {
   11320     return Smi::FromInt(0);
   11321   }
   11322 
   11323   HeapNumber* result_double = NULL;
   11324   if (limit > static_cast<uint32_t>(Smi::kMaxValue)) {
   11325     // Pessimistically allocate space for return value before
   11326     // we start mutating the array.
   11327     Object* new_double;
   11328     { MaybeObject* maybe_new_double = heap->AllocateHeapNumber(0.0);
   11329       if (!maybe_new_double->ToObject(&new_double)) return maybe_new_double;
   11330     }
   11331     result_double = HeapNumber::cast(new_double);
   11332   }
   11333 
   11334   uint32_t result = 0;
   11335   if (elements_base->map() == heap->fixed_double_array_map()) {
   11336     FixedDoubleArray* elements = FixedDoubleArray::cast(elements_base);
   11337     // Split elements into defined and the_hole, in that order.
   11338     unsigned int holes = limit;
   11339     // Assume most arrays contain no holes and undefined values, so minimize the
   11340     // number of stores of non-undefined, non-the-hole values.
   11341     for (unsigned int i = 0; i < holes; i++) {
   11342       if (elements->is_the_hole(i)) {
   11343         holes--;
   11344       } else {
   11345         continue;
   11346       }
   11347       // Position i needs to be filled.
   11348       while (holes > i) {
   11349         if (elements->is_the_hole(holes)) {
   11350           holes--;
   11351         } else {
   11352           elements->set(i, elements->get_scalar(holes));
   11353           break;
   11354         }
   11355       }
   11356     }
   11357     result = holes;
   11358     while (holes < limit) {
   11359       elements->set_the_hole(holes);
   11360       holes++;
   11361     }
   11362   } else {
   11363     FixedArray* elements = FixedArray::cast(elements_base);
   11364     AssertNoAllocation no_alloc;
   11365 
   11366     // Split elements into defined, undefined and the_hole, in that order.  Only
   11367     // count locations for undefined and the hole, and fill them afterwards.
   11368     WriteBarrierMode write_barrier = elements->GetWriteBarrierMode(no_alloc);
   11369     unsigned int undefs = limit;
   11370     unsigned int holes = limit;
   11371     // Assume most arrays contain no holes and undefined values, so minimize the
   11372     // number of stores of non-undefined, non-the-hole values.
   11373     for (unsigned int i = 0; i < undefs; i++) {
   11374       Object* current = elements->get(i);
   11375       if (current->IsTheHole()) {
   11376         holes--;
   11377         undefs--;
   11378       } else if (current->IsUndefined()) {
   11379         undefs--;
   11380       } else {
   11381         continue;
   11382       }
   11383       // Position i needs to be filled.
   11384       while (undefs > i) {
   11385         current = elements->get(undefs);
   11386         if (current->IsTheHole()) {
   11387           holes--;
   11388           undefs--;
   11389         } else if (current->IsUndefined()) {
   11390           undefs--;
   11391         } else {
   11392           elements->set(i, current, write_barrier);
   11393           break;
   11394         }
   11395       }
   11396     }
   11397     result = undefs;
   11398     while (undefs < holes) {
   11399       elements->set_undefined(undefs);
   11400       undefs++;
   11401     }
   11402     while (holes < limit) {
   11403       elements->set_the_hole(holes);
   11404       holes++;
   11405     }
   11406   }
   11407 
   11408   if (result <= static_cast<uint32_t>(Smi::kMaxValue)) {
   11409     return Smi::FromInt(static_cast<int>(result));
   11410   }
   11411   ASSERT_NE(NULL, result_double);
   11412   result_double->set_value(static_cast<double>(result));
   11413   return result_double;
   11414 }
   11415 
   11416 
   11417 Object* ExternalPixelArray::SetValue(uint32_t index, Object* value) {
   11418   uint8_t clamped_value = 0;
   11419   if (index < static_cast<uint32_t>(length())) {
   11420     if (value->IsSmi()) {
   11421       int int_value = Smi::cast(value)->value();
   11422       if (int_value < 0) {
   11423         clamped_value = 0;
   11424       } else if (int_value > 255) {
   11425         clamped_value = 255;
   11426       } else {
   11427         clamped_value = static_cast<uint8_t>(int_value);
   11428       }
   11429     } else if (value->IsHeapNumber()) {
   11430       double double_value = HeapNumber::cast(value)->value();
   11431       if (!(double_value > 0)) {
   11432         // NaN and less than zero clamp to zero.
   11433         clamped_value = 0;
   11434       } else if (double_value > 255) {
   11435         // Greater than 255 clamp to 255.
   11436         clamped_value = 255;
   11437       } else {
   11438         // Other doubles are rounded to the nearest integer.
   11439         clamped_value = static_cast<uint8_t>(double_value + 0.5);
   11440       }
   11441     } else {
   11442       // Clamp undefined to zero (default). All other types have been
   11443       // converted to a number type further up in the call chain.
   11444       ASSERT(value->IsUndefined());
   11445     }
   11446     set(index, clamped_value);
   11447   }
   11448   return Smi::FromInt(clamped_value);
   11449 }
   11450 
   11451 
   11452 template<typename ExternalArrayClass, typename ValueType>
   11453 static MaybeObject* ExternalArrayIntSetter(Heap* heap,
   11454                                            ExternalArrayClass* receiver,
   11455                                            uint32_t index,
   11456                                            Object* value) {
   11457   ValueType cast_value = 0;
   11458   if (index < static_cast<uint32_t>(receiver->length())) {
   11459     if (value->IsSmi()) {
   11460       int int_value = Smi::cast(value)->value();
   11461       cast_value = static_cast<ValueType>(int_value);
   11462     } else if (value->IsHeapNumber()) {
   11463       double double_value = HeapNumber::cast(value)->value();
   11464       cast_value = static_cast<ValueType>(DoubleToInt32(double_value));
   11465     } else {
   11466       // Clamp undefined to zero (default). All other types have been
   11467       // converted to a number type further up in the call chain.
   11468       ASSERT(value->IsUndefined());
   11469     }
   11470     receiver->set(index, cast_value);
   11471   }
   11472   return heap->NumberFromInt32(cast_value);
   11473 }
   11474 
   11475 
   11476 MaybeObject* ExternalByteArray::SetValue(uint32_t index, Object* value) {
   11477   return ExternalArrayIntSetter<ExternalByteArray, int8_t>
   11478       (GetHeap(), this, index, value);
   11479 }
   11480 
   11481 
   11482 MaybeObject* ExternalUnsignedByteArray::SetValue(uint32_t index,
   11483                                                  Object* value) {
   11484   return ExternalArrayIntSetter<ExternalUnsignedByteArray, uint8_t>
   11485       (GetHeap(), this, index, value);
   11486 }
   11487 
   11488 
   11489 MaybeObject* ExternalShortArray::SetValue(uint32_t index,
   11490                                           Object* value) {
   11491   return ExternalArrayIntSetter<ExternalShortArray, int16_t>
   11492       (GetHeap(), this, index, value);
   11493 }
   11494 
   11495 
   11496 MaybeObject* ExternalUnsignedShortArray::SetValue(uint32_t index,
   11497                                                   Object* value) {
   11498   return ExternalArrayIntSetter<ExternalUnsignedShortArray, uint16_t>
   11499       (GetHeap(), this, index, value);
   11500 }
   11501 
   11502 
   11503 MaybeObject* ExternalIntArray::SetValue(uint32_t index, Object* value) {
   11504   return ExternalArrayIntSetter<ExternalIntArray, int32_t>
   11505       (GetHeap(), this, index, value);
   11506 }
   11507 
   11508 
   11509 MaybeObject* ExternalUnsignedIntArray::SetValue(uint32_t index, Object* value) {
   11510   uint32_t cast_value = 0;
   11511   Heap* heap = GetHeap();
   11512   if (index < static_cast<uint32_t>(length())) {
   11513     if (value->IsSmi()) {
   11514       int int_value = Smi::cast(value)->value();
   11515       cast_value = static_cast<uint32_t>(int_value);
   11516     } else if (value->IsHeapNumber()) {
   11517       double double_value = HeapNumber::cast(value)->value();
   11518       cast_value = static_cast<uint32_t>(DoubleToUint32(double_value));
   11519     } else {
   11520       // Clamp undefined to zero (default). All other types have been
   11521       // converted to a number type further up in the call chain.
   11522       ASSERT(value->IsUndefined());
   11523     }
   11524     set(index, cast_value);
   11525   }
   11526   return heap->NumberFromUint32(cast_value);
   11527 }
   11528 
   11529 
   11530 MaybeObject* ExternalFloatArray::SetValue(uint32_t index, Object* value) {
   11531   float cast_value = static_cast<float>(OS::nan_value());
   11532   Heap* heap = GetHeap();
   11533   if (index < static_cast<uint32_t>(length())) {
   11534     if (value->IsSmi()) {
   11535       int int_value = Smi::cast(value)->value();
   11536       cast_value = static_cast<float>(int_value);
   11537     } else if (value->IsHeapNumber()) {
   11538       double double_value = HeapNumber::cast(value)->value();
   11539       cast_value = static_cast<float>(double_value);
   11540     } else {
   11541       // Clamp undefined to NaN (default). All other types have been
   11542       // converted to a number type further up in the call chain.
   11543       ASSERT(value->IsUndefined());
   11544     }
   11545     set(index, cast_value);
   11546   }
   11547   return heap->AllocateHeapNumber(cast_value);
   11548 }
   11549 
   11550 
   11551 MaybeObject* ExternalDoubleArray::SetValue(uint32_t index, Object* value) {
   11552   double double_value = OS::nan_value();
   11553   Heap* heap = GetHeap();
   11554   if (index < static_cast<uint32_t>(length())) {
   11555     if (value->IsSmi()) {
   11556       int int_value = Smi::cast(value)->value();
   11557       double_value = static_cast<double>(int_value);
   11558     } else if (value->IsHeapNumber()) {
   11559       double_value = HeapNumber::cast(value)->value();
   11560     } else {
   11561       // Clamp undefined to NaN (default). All other types have been
   11562       // converted to a number type further up in the call chain.
   11563       ASSERT(value->IsUndefined());
   11564     }
   11565     set(index, double_value);
   11566   }
   11567   return heap->AllocateHeapNumber(double_value);
   11568 }
   11569 
   11570 
   11571 JSGlobalPropertyCell* GlobalObject::GetPropertyCell(LookupResult* result) {
   11572   ASSERT(!HasFastProperties());
   11573   Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry());
   11574   return JSGlobalPropertyCell::cast(value);
   11575 }
   11576 
   11577 
   11578 Handle<JSGlobalPropertyCell> GlobalObject::EnsurePropertyCell(
   11579     Handle<GlobalObject> global,
   11580     Handle<String> name) {
   11581   Isolate* isolate = global->GetIsolate();
   11582   CALL_HEAP_FUNCTION(isolate,
   11583                      global->EnsurePropertyCell(*name),
   11584                      JSGlobalPropertyCell);
   11585 }
   11586 
   11587 
   11588 MaybeObject* GlobalObject::EnsurePropertyCell(String* name) {
   11589   ASSERT(!HasFastProperties());
   11590   int entry = property_dictionary()->FindEntry(name);
   11591   if (entry == StringDictionary::kNotFound) {
   11592     Heap* heap = GetHeap();
   11593     Object* cell;
   11594     { MaybeObject* maybe_cell =
   11595           heap->AllocateJSGlobalPropertyCell(heap->the_hole_value());
   11596       if (!maybe_cell->ToObject(&cell)) return maybe_cell;
   11597     }
   11598     PropertyDetails details(NONE, NORMAL);
   11599     details = details.AsDeleted();
   11600     Object* dictionary;
   11601     { MaybeObject* maybe_dictionary =
   11602           property_dictionary()->Add(name, cell, details);
   11603       if (!maybe_dictionary->ToObject(&dictionary)) return maybe_dictionary;
   11604     }
   11605     set_properties(StringDictionary::cast(dictionary));
   11606     return cell;
   11607   } else {
   11608     Object* value = property_dictionary()->ValueAt(entry);
   11609     ASSERT(value->IsJSGlobalPropertyCell());
   11610     return value;
   11611   }
   11612 }
   11613 
   11614 
   11615 MaybeObject* SymbolTable::LookupString(String* string, Object** s) {
   11616   SymbolKey key(string);
   11617   return LookupKey(&key, s);
   11618 }
   11619 
   11620 
   11621 // This class is used for looking up two character strings in the symbol table.
   11622 // If we don't have a hit we don't want to waste much time so we unroll the
   11623 // string hash calculation loop here for speed.  Doesn't work if the two
   11624 // characters form a decimal integer, since such strings have a different hash
   11625 // algorithm.
   11626 class TwoCharHashTableKey : public HashTableKey {
   11627  public:
   11628   TwoCharHashTableKey(uint32_t c1, uint32_t c2, uint32_t seed)
   11629     : c1_(c1), c2_(c2) {
   11630     // Char 1.
   11631     uint32_t hash = seed;
   11632     hash += c1;
   11633     hash += hash << 10;
   11634     hash ^= hash >> 6;
   11635     // Char 2.
   11636     hash += c2;
   11637     hash += hash << 10;
   11638     hash ^= hash >> 6;
   11639     // GetHash.
   11640     hash += hash << 3;
   11641     hash ^= hash >> 11;
   11642     hash += hash << 15;
   11643     if ((hash & String::kHashBitMask) == 0) hash = String::kZeroHash;
   11644 #ifdef DEBUG
   11645     StringHasher hasher(2, seed);
   11646     hasher.AddCharacter(c1);
   11647     hasher.AddCharacter(c2);
   11648     // If this assert fails then we failed to reproduce the two-character
   11649     // version of the string hashing algorithm above.  One reason could be
   11650     // that we were passed two digits as characters, since the hash
   11651     // algorithm is different in that case.
   11652     ASSERT_EQ(static_cast<int>(hasher.GetHash()), static_cast<int>(hash));
   11653 #endif
   11654     hash_ = hash;
   11655   }
   11656 
   11657   bool IsMatch(Object* o) {
   11658     if (!o->IsString()) return false;
   11659     String* other = String::cast(o);
   11660     if (other->length() != 2) return false;
   11661     if (other->Get(0) != c1_) return false;
   11662     return other->Get(1) == c2_;
   11663   }
   11664 
   11665   uint32_t Hash() { return hash_; }
   11666   uint32_t HashForObject(Object* key) {
   11667     if (!key->IsString()) return 0;
   11668     return String::cast(key)->Hash();
   11669   }
   11670 
   11671   Object* AsObject() {
   11672     // The TwoCharHashTableKey is only used for looking in the symbol
   11673     // table, not for adding to it.
   11674     UNREACHABLE();
   11675     return NULL;
   11676   }
   11677 
   11678  private:
   11679   uint32_t c1_;
   11680   uint32_t c2_;
   11681   uint32_t hash_;
   11682 };
   11683 
   11684 
   11685 bool SymbolTable::LookupSymbolIfExists(String* string, String** symbol) {
   11686   SymbolKey key(string);
   11687   int entry = FindEntry(&key);
   11688   if (entry == kNotFound) {
   11689     return false;
   11690   } else {
   11691     String* result = String::cast(KeyAt(entry));
   11692     ASSERT(StringShape(result).IsSymbol());
   11693     *symbol = result;
   11694     return true;
   11695   }
   11696 }
   11697 
   11698 
   11699 bool SymbolTable::LookupTwoCharsSymbolIfExists(uint32_t c1,
   11700                                                uint32_t c2,
   11701                                                String** symbol) {
   11702   TwoCharHashTableKey key(c1, c2, GetHeap()->HashSeed());
   11703   int entry = FindEntry(&key);
   11704   if (entry == kNotFound) {
   11705     return false;
   11706   } else {
   11707     String* result = String::cast(KeyAt(entry));
   11708     ASSERT(StringShape(result).IsSymbol());
   11709     *symbol = result;
   11710     return true;
   11711   }
   11712 }
   11713 
   11714 
   11715 MaybeObject* SymbolTable::LookupSymbol(Vector<const char> str,
   11716                                        Object** s) {
   11717   Utf8SymbolKey key(str, GetHeap()->HashSeed());
   11718   return LookupKey(&key, s);
   11719 }
   11720 
   11721 
   11722 MaybeObject* SymbolTable::LookupAsciiSymbol(Vector<const char> str,
   11723                                             Object** s) {
   11724   AsciiSymbolKey key(str, GetHeap()->HashSeed());
   11725   return LookupKey(&key, s);
   11726 }
   11727 
   11728 
   11729 MaybeObject* SymbolTable::LookupSubStringAsciiSymbol(Handle<SeqAsciiString> str,
   11730                                                      int from,
   11731                                                      int length,
   11732                                                      Object** s) {
   11733   SubStringAsciiSymbolKey key(str, from, length, GetHeap()->HashSeed());
   11734   return LookupKey(&key, s);
   11735 }
   11736 
   11737 
   11738 MaybeObject* SymbolTable::LookupTwoByteSymbol(Vector<const uc16> str,
   11739                                               Object** s) {
   11740   TwoByteSymbolKey key(str, GetHeap()->HashSeed());
   11741   return LookupKey(&key, s);
   11742 }
   11743 
   11744 MaybeObject* SymbolTable::LookupKey(HashTableKey* key, Object** s) {
   11745   int entry = FindEntry(key);
   11746 
   11747   // Symbol already in table.
   11748   if (entry != kNotFound) {
   11749     *s = KeyAt(entry);
   11750     return this;
   11751   }
   11752 
   11753   // Adding new symbol. Grow table if needed.
   11754   Object* obj;
   11755   { MaybeObject* maybe_obj = EnsureCapacity(1, key);
   11756     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   11757   }
   11758 
   11759   // Create symbol object.
   11760   Object* symbol;
   11761   { MaybeObject* maybe_symbol = key->AsObject();
   11762     if (!maybe_symbol->ToObject(&symbol)) return maybe_symbol;
   11763   }
   11764 
   11765   // If the symbol table grew as part of EnsureCapacity, obj is not
   11766   // the current symbol table and therefore we cannot use
   11767   // SymbolTable::cast here.
   11768   SymbolTable* table = reinterpret_cast<SymbolTable*>(obj);
   11769 
   11770   // Add the new symbol and return it along with the symbol table.
   11771   entry = table->FindInsertionEntry(key->Hash());
   11772   table->set(EntryToIndex(entry), symbol);
   11773   table->ElementAdded();
   11774   *s = symbol;
   11775   return table;
   11776 }
   11777 
   11778 
   11779 Object* CompilationCacheTable::Lookup(String* src) {
   11780   StringKey key(src);
   11781   int entry = FindEntry(&key);
   11782   if (entry == kNotFound) return GetHeap()->undefined_value();
   11783   return get(EntryToIndex(entry) + 1);
   11784 }
   11785 
   11786 
   11787 Object* CompilationCacheTable::LookupEval(String* src,
   11788                                           Context* context,
   11789                                           LanguageMode language_mode,
   11790                                           int scope_position) {
   11791   StringSharedKey key(src,
   11792                       context->closure()->shared(),
   11793                       language_mode,
   11794                       scope_position);
   11795   int entry = FindEntry(&key);
   11796   if (entry == kNotFound) return GetHeap()->undefined_value();
   11797   return get(EntryToIndex(entry) + 1);
   11798 }
   11799 
   11800 
   11801 Object* CompilationCacheTable::LookupRegExp(String* src,
   11802                                             JSRegExp::Flags flags) {
   11803   RegExpKey key(src, flags);
   11804   int entry = FindEntry(&key);
   11805   if (entry == kNotFound) return GetHeap()->undefined_value();
   11806   return get(EntryToIndex(entry) + 1);
   11807 }
   11808 
   11809 
   11810 MaybeObject* CompilationCacheTable::Put(String* src, Object* value) {
   11811   StringKey key(src);
   11812   Object* obj;
   11813   { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
   11814     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   11815   }
   11816 
   11817   CompilationCacheTable* cache =
   11818       reinterpret_cast<CompilationCacheTable*>(obj);
   11819   int entry = cache->FindInsertionEntry(key.Hash());
   11820   cache->set(EntryToIndex(entry), src);
   11821   cache->set(EntryToIndex(entry) + 1, value);
   11822   cache->ElementAdded();
   11823   return cache;
   11824 }
   11825 
   11826 
   11827 MaybeObject* CompilationCacheTable::PutEval(String* src,
   11828                                             Context* context,
   11829                                             SharedFunctionInfo* value,
   11830                                             int scope_position) {
   11831   StringSharedKey key(src,
   11832                       context->closure()->shared(),
   11833                       value->language_mode(),
   11834                       scope_position);
   11835   Object* obj;
   11836   { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
   11837     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   11838   }
   11839 
   11840   CompilationCacheTable* cache =
   11841       reinterpret_cast<CompilationCacheTable*>(obj);
   11842   int entry = cache->FindInsertionEntry(key.Hash());
   11843 
   11844   Object* k;
   11845   { MaybeObject* maybe_k = key.AsObject();
   11846     if (!maybe_k->ToObject(&k)) return maybe_k;
   11847   }
   11848 
   11849   cache->set(EntryToIndex(entry), k);
   11850   cache->set(EntryToIndex(entry) + 1, value);
   11851   cache->ElementAdded();
   11852   return cache;
   11853 }
   11854 
   11855 
   11856 MaybeObject* CompilationCacheTable::PutRegExp(String* src,
   11857                                               JSRegExp::Flags flags,
   11858                                               FixedArray* value) {
   11859   RegExpKey key(src, flags);
   11860   Object* obj;
   11861   { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
   11862     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   11863   }
   11864 
   11865   CompilationCacheTable* cache =
   11866       reinterpret_cast<CompilationCacheTable*>(obj);
   11867   int entry = cache->FindInsertionEntry(key.Hash());
   11868   // We store the value in the key slot, and compare the search key
   11869   // to the stored value with a custon IsMatch function during lookups.
   11870   cache->set(EntryToIndex(entry), value);
   11871   cache->set(EntryToIndex(entry) + 1, value);
   11872   cache->ElementAdded();
   11873   return cache;
   11874 }
   11875 
   11876 
   11877 void CompilationCacheTable::Remove(Object* value) {
   11878   Object* the_hole_value = GetHeap()->the_hole_value();
   11879   for (int entry = 0, size = Capacity(); entry < size; entry++) {
   11880     int entry_index = EntryToIndex(entry);
   11881     int value_index = entry_index + 1;
   11882     if (get(value_index) == value) {
   11883       NoWriteBarrierSet(this, entry_index, the_hole_value);
   11884       NoWriteBarrierSet(this, value_index, the_hole_value);
   11885       ElementRemoved();
   11886     }
   11887   }
   11888   return;
   11889 }
   11890 
   11891 
   11892 // SymbolsKey used for HashTable where key is array of symbols.
   11893 class SymbolsKey : public HashTableKey {
   11894  public:
   11895   explicit SymbolsKey(FixedArray* symbols) : symbols_(symbols) { }
   11896 
   11897   bool IsMatch(Object* symbols) {
   11898     FixedArray* o = FixedArray::cast(symbols);
   11899     int len = symbols_->length();
   11900     if (o->length() != len) return false;
   11901     for (int i = 0; i < len; i++) {
   11902       if (o->get(i) != symbols_->get(i)) return false;
   11903     }
   11904     return true;
   11905   }
   11906 
   11907   uint32_t Hash() { return HashForObject(symbols_); }
   11908 
   11909   uint32_t HashForObject(Object* obj) {
   11910     FixedArray* symbols = FixedArray::cast(obj);
   11911     int len = symbols->length();
   11912     uint32_t hash = 0;
   11913     for (int i = 0; i < len; i++) {
   11914       hash ^= String::cast(symbols->get(i))->Hash();
   11915     }
   11916     return hash;
   11917   }
   11918 
   11919   Object* AsObject() { return symbols_; }
   11920 
   11921  private:
   11922   FixedArray* symbols_;
   11923 };
   11924 
   11925 
   11926 Object* MapCache::Lookup(FixedArray* array) {
   11927   SymbolsKey key(array);
   11928   int entry = FindEntry(&key);
   11929   if (entry == kNotFound) return GetHeap()->undefined_value();
   11930   return get(EntryToIndex(entry) + 1);
   11931 }
   11932 
   11933 
   11934 MaybeObject* MapCache::Put(FixedArray* array, Map* value) {
   11935   SymbolsKey key(array);
   11936   Object* obj;
   11937   { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
   11938     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   11939   }
   11940 
   11941   MapCache* cache = reinterpret_cast<MapCache*>(obj);
   11942   int entry = cache->FindInsertionEntry(key.Hash());
   11943   cache->set(EntryToIndex(entry), array);
   11944   cache->set(EntryToIndex(entry) + 1, value);
   11945   cache->ElementAdded();
   11946   return cache;
   11947 }
   11948 
   11949 
   11950 template<typename Shape, typename Key>
   11951 MaybeObject* Dictionary<Shape, Key>::Allocate(int at_least_space_for) {
   11952   Object* obj;
   11953   { MaybeObject* maybe_obj =
   11954         HashTable<Shape, Key>::Allocate(at_least_space_for);
   11955     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   11956   }
   11957   // Initialize the next enumeration index.
   11958   Dictionary<Shape, Key>::cast(obj)->
   11959       SetNextEnumerationIndex(PropertyDetails::kInitialIndex);
   11960   return obj;
   11961 }
   11962 
   11963 
   11964 template<typename Shape, typename Key>
   11965 MaybeObject* Dictionary<Shape, Key>::GenerateNewEnumerationIndices() {
   11966   Heap* heap = Dictionary<Shape, Key>::GetHeap();
   11967   int length = HashTable<Shape, Key>::NumberOfElements();
   11968 
   11969   // Allocate and initialize iteration order array.
   11970   Object* obj;
   11971   { MaybeObject* maybe_obj = heap->AllocateFixedArray(length);
   11972     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   11973   }
   11974   FixedArray* iteration_order = FixedArray::cast(obj);
   11975   for (int i = 0; i < length; i++) {
   11976     iteration_order->set(i, Smi::FromInt(i));
   11977   }
   11978 
   11979   // Allocate array with enumeration order.
   11980   { MaybeObject* maybe_obj = heap->AllocateFixedArray(length);
   11981     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   11982   }
   11983   FixedArray* enumeration_order = FixedArray::cast(obj);
   11984 
   11985   // Fill the enumeration order array with property details.
   11986   int capacity = HashTable<Shape, Key>::Capacity();
   11987   int pos = 0;
   11988   for (int i = 0; i < capacity; i++) {
   11989     if (Dictionary<Shape, Key>::IsKey(Dictionary<Shape, Key>::KeyAt(i))) {
   11990       enumeration_order->set(pos++, Smi::FromInt(DetailsAt(i).index()));
   11991     }
   11992   }
   11993 
   11994   // Sort the arrays wrt. enumeration order.
   11995   iteration_order->SortPairs(enumeration_order, enumeration_order->length());
   11996 
   11997   // Overwrite the enumeration_order with the enumeration indices.
   11998   for (int i = 0; i < length; i++) {
   11999     int index = Smi::cast(iteration_order->get(i))->value();
   12000     int enum_index = PropertyDetails::kInitialIndex + i;
   12001     enumeration_order->set(index, Smi::FromInt(enum_index));
   12002   }
   12003 
   12004   // Update the dictionary with new indices.
   12005   capacity = HashTable<Shape, Key>::Capacity();
   12006   pos = 0;
   12007   for (int i = 0; i < capacity; i++) {
   12008     if (Dictionary<Shape, Key>::IsKey(Dictionary<Shape, Key>::KeyAt(i))) {
   12009       int enum_index = Smi::cast(enumeration_order->get(pos++))->value();
   12010       PropertyDetails details = DetailsAt(i);
   12011       PropertyDetails new_details =
   12012           PropertyDetails(details.attributes(), details.type(), enum_index);
   12013       DetailsAtPut(i, new_details);
   12014     }
   12015   }
   12016 
   12017   // Set the next enumeration index.
   12018   SetNextEnumerationIndex(PropertyDetails::kInitialIndex+length);
   12019   return this;
   12020 }
   12021 
   12022 template<typename Shape, typename Key>
   12023 MaybeObject* Dictionary<Shape, Key>::EnsureCapacity(int n, Key key) {
   12024   // Check whether there are enough enumeration indices to add n elements.
   12025   if (Shape::kIsEnumerable &&
   12026       !PropertyDetails::IsValidIndex(NextEnumerationIndex() + n)) {
   12027     // If not, we generate new indices for the properties.
   12028     Object* result;
   12029     { MaybeObject* maybe_result = GenerateNewEnumerationIndices();
   12030       if (!maybe_result->ToObject(&result)) return maybe_result;
   12031     }
   12032   }
   12033   return HashTable<Shape, Key>::EnsureCapacity(n, key);
   12034 }
   12035 
   12036 
   12037 template<typename Shape, typename Key>
   12038 Object* Dictionary<Shape, Key>::DeleteProperty(int entry,
   12039                                                JSReceiver::DeleteMode mode) {
   12040   Heap* heap = Dictionary<Shape, Key>::GetHeap();
   12041   PropertyDetails details = DetailsAt(entry);
   12042   // Ignore attributes if forcing a deletion.
   12043   if (details.IsDontDelete() && mode != JSReceiver::FORCE_DELETION) {
   12044     return heap->false_value();
   12045   }
   12046   SetEntry(entry, heap->the_hole_value(), heap->the_hole_value());
   12047   HashTable<Shape, Key>::ElementRemoved();
   12048   return heap->true_value();
   12049 }
   12050 
   12051 
   12052 template<typename Shape, typename Key>
   12053 MaybeObject* Dictionary<Shape, Key>::Shrink(Key key) {
   12054   return HashTable<Shape, Key>::Shrink(key);
   12055 }
   12056 
   12057 
   12058 template<typename Shape, typename Key>
   12059 MaybeObject* Dictionary<Shape, Key>::AtPut(Key key, Object* value) {
   12060   int entry = this->FindEntry(key);
   12061 
   12062   // If the entry is present set the value;
   12063   if (entry != Dictionary<Shape, Key>::kNotFound) {
   12064     ValueAtPut(entry, value);
   12065     return this;
   12066   }
   12067 
   12068   // Check whether the dictionary should be extended.
   12069   Object* obj;
   12070   { MaybeObject* maybe_obj = EnsureCapacity(1, key);
   12071     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   12072   }
   12073 
   12074   Object* k;
   12075   { MaybeObject* maybe_k = Shape::AsObject(key);
   12076     if (!maybe_k->ToObject(&k)) return maybe_k;
   12077   }
   12078   PropertyDetails details = PropertyDetails(NONE, NORMAL);
   12079 
   12080   return Dictionary<Shape, Key>::cast(obj)->AddEntry(key, value, details,
   12081       Dictionary<Shape, Key>::Hash(key));
   12082 }
   12083 
   12084 
   12085 template<typename Shape, typename Key>
   12086 MaybeObject* Dictionary<Shape, Key>::Add(Key key,
   12087                                          Object* value,
   12088                                          PropertyDetails details) {
   12089   // Valdate key is absent.
   12090   SLOW_ASSERT((this->FindEntry(key) == Dictionary<Shape, Key>::kNotFound));
   12091   // Check whether the dictionary should be extended.
   12092   Object* obj;
   12093   { MaybeObject* maybe_obj = EnsureCapacity(1, key);
   12094     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   12095   }
   12096 
   12097   return Dictionary<Shape, Key>::cast(obj)->AddEntry(key, value, details,
   12098       Dictionary<Shape, Key>::Hash(key));
   12099 }
   12100 
   12101 
   12102 // Add a key, value pair to the dictionary.
   12103 template<typename Shape, typename Key>
   12104 MaybeObject* Dictionary<Shape, Key>::AddEntry(Key key,
   12105                                               Object* value,
   12106                                               PropertyDetails details,
   12107                                               uint32_t hash) {
   12108   // Compute the key object.
   12109   Object* k;
   12110   { MaybeObject* maybe_k = Shape::AsObject(key);
   12111     if (!maybe_k->ToObject(&k)) return maybe_k;
   12112   }
   12113 
   12114   uint32_t entry = Dictionary<Shape, Key>::FindInsertionEntry(hash);
   12115   // Insert element at empty or deleted entry
   12116   if (!details.IsDeleted() && details.index() == 0 && Shape::kIsEnumerable) {
   12117     // Assign an enumeration index to the property and update
   12118     // SetNextEnumerationIndex.
   12119     int index = NextEnumerationIndex();
   12120     details = PropertyDetails(details.attributes(), details.type(), index);
   12121     SetNextEnumerationIndex(index + 1);
   12122   }
   12123   SetEntry(entry, k, value, details);
   12124   ASSERT((Dictionary<Shape, Key>::KeyAt(entry)->IsNumber()
   12125           || Dictionary<Shape, Key>::KeyAt(entry)->IsString()));
   12126   HashTable<Shape, Key>::ElementAdded();
   12127   return this;
   12128 }
   12129 
   12130 
   12131 void SeededNumberDictionary::UpdateMaxNumberKey(uint32_t key) {
   12132   // If the dictionary requires slow elements an element has already
   12133   // been added at a high index.
   12134   if (requires_slow_elements()) return;
   12135   // Check if this index is high enough that we should require slow
   12136   // elements.
   12137   if (key > kRequiresSlowElementsLimit) {
   12138     set_requires_slow_elements();
   12139     return;
   12140   }
   12141   // Update max key value.
   12142   Object* max_index_object = get(kMaxNumberKeyIndex);
   12143   if (!max_index_object->IsSmi() || max_number_key() < key) {
   12144     FixedArray::set(kMaxNumberKeyIndex,
   12145                     Smi::FromInt(key << kRequiresSlowElementsTagSize));
   12146   }
   12147 }
   12148 
   12149 
   12150 MaybeObject* SeededNumberDictionary::AddNumberEntry(uint32_t key,
   12151                                                     Object* value,
   12152                                                     PropertyDetails details) {
   12153   UpdateMaxNumberKey(key);
   12154   SLOW_ASSERT(this->FindEntry(key) == kNotFound);
   12155   return Add(key, value, details);
   12156 }
   12157 
   12158 
   12159 MaybeObject* UnseededNumberDictionary::AddNumberEntry(uint32_t key,
   12160                                                       Object* value) {
   12161   SLOW_ASSERT(this->FindEntry(key) == kNotFound);
   12162   return Add(key, value, PropertyDetails(NONE, NORMAL));
   12163 }
   12164 
   12165 
   12166 MaybeObject* SeededNumberDictionary::AtNumberPut(uint32_t key, Object* value) {
   12167   UpdateMaxNumberKey(key);
   12168   return AtPut(key, value);
   12169 }
   12170 
   12171 
   12172 MaybeObject* UnseededNumberDictionary::AtNumberPut(uint32_t key,
   12173                                                    Object* value) {
   12174   return AtPut(key, value);
   12175 }
   12176 
   12177 
   12178 Handle<SeededNumberDictionary> SeededNumberDictionary::Set(
   12179     Handle<SeededNumberDictionary> dictionary,
   12180     uint32_t index,
   12181     Handle<Object> value,
   12182     PropertyDetails details) {
   12183   CALL_HEAP_FUNCTION(dictionary->GetIsolate(),
   12184                      dictionary->Set(index, *value, details),
   12185                      SeededNumberDictionary);
   12186 }
   12187 
   12188 
   12189 Handle<UnseededNumberDictionary> UnseededNumberDictionary::Set(
   12190     Handle<UnseededNumberDictionary> dictionary,
   12191     uint32_t index,
   12192     Handle<Object> value) {
   12193   CALL_HEAP_FUNCTION(dictionary->GetIsolate(),
   12194                      dictionary->Set(index, *value),
   12195                      UnseededNumberDictionary);
   12196 }
   12197 
   12198 
   12199 MaybeObject* SeededNumberDictionary::Set(uint32_t key,
   12200                                          Object* value,
   12201                                          PropertyDetails details) {
   12202   int entry = FindEntry(key);
   12203   if (entry == kNotFound) return AddNumberEntry(key, value, details);
   12204   // Preserve enumeration index.
   12205   details = PropertyDetails(details.attributes(),
   12206                             details.type(),
   12207                             DetailsAt(entry).index());
   12208   MaybeObject* maybe_object_key = SeededNumberDictionaryShape::AsObject(key);
   12209   Object* object_key;
   12210   if (!maybe_object_key->ToObject(&object_key)) return maybe_object_key;
   12211   SetEntry(entry, object_key, value, details);
   12212   return this;
   12213 }
   12214 
   12215 
   12216 MaybeObject* UnseededNumberDictionary::Set(uint32_t key,
   12217                                            Object* value) {
   12218   int entry = FindEntry(key);
   12219   if (entry == kNotFound) return AddNumberEntry(key, value);
   12220   MaybeObject* maybe_object_key = UnseededNumberDictionaryShape::AsObject(key);
   12221   Object* object_key;
   12222   if (!maybe_object_key->ToObject(&object_key)) return maybe_object_key;
   12223   SetEntry(entry, object_key, value);
   12224   return this;
   12225 }
   12226 
   12227 
   12228 
   12229 template<typename Shape, typename Key>
   12230 int Dictionary<Shape, Key>::NumberOfElementsFilterAttributes(
   12231     PropertyAttributes filter) {
   12232   int capacity = HashTable<Shape, Key>::Capacity();
   12233   int result = 0;
   12234   for (int i = 0; i < capacity; i++) {
   12235     Object* k = HashTable<Shape, Key>::KeyAt(i);
   12236     if (HashTable<Shape, Key>::IsKey(k)) {
   12237       PropertyDetails details = DetailsAt(i);
   12238       if (details.IsDeleted()) continue;
   12239       PropertyAttributes attr = details.attributes();
   12240       if ((attr & filter) == 0) result++;
   12241     }
   12242   }
   12243   return result;
   12244 }
   12245 
   12246 
   12247 template<typename Shape, typename Key>
   12248 int Dictionary<Shape, Key>::NumberOfEnumElements() {
   12249   return NumberOfElementsFilterAttributes(
   12250       static_cast<PropertyAttributes>(DONT_ENUM));
   12251 }
   12252 
   12253 
   12254 template<typename Shape, typename Key>
   12255 void Dictionary<Shape, Key>::CopyKeysTo(
   12256     FixedArray* storage,
   12257     PropertyAttributes filter,
   12258     typename Dictionary<Shape, Key>::SortMode sort_mode) {
   12259   ASSERT(storage->length() >= NumberOfEnumElements());
   12260   int capacity = HashTable<Shape, Key>::Capacity();
   12261   int index = 0;
   12262   for (int i = 0; i < capacity; i++) {
   12263      Object* k = HashTable<Shape, Key>::KeyAt(i);
   12264      if (HashTable<Shape, Key>::IsKey(k)) {
   12265        PropertyDetails details = DetailsAt(i);
   12266        if (details.IsDeleted()) continue;
   12267        PropertyAttributes attr = details.attributes();
   12268        if ((attr & filter) == 0) storage->set(index++, k);
   12269      }
   12270   }
   12271   if (sort_mode == Dictionary<Shape, Key>::SORTED) {
   12272     storage->SortPairs(storage, index);
   12273   }
   12274   ASSERT(storage->length() >= index);
   12275 }
   12276 
   12277 
   12278 void StringDictionary::CopyEnumKeysTo(FixedArray* storage,
   12279                                       FixedArray* sort_array) {
   12280   ASSERT(storage->length() >= NumberOfEnumElements());
   12281   int capacity = Capacity();
   12282   int index = 0;
   12283   for (int i = 0; i < capacity; i++) {
   12284      Object* k = KeyAt(i);
   12285      if (IsKey(k)) {
   12286        PropertyDetails details = DetailsAt(i);
   12287        if (details.IsDeleted() || details.IsDontEnum()) continue;
   12288        storage->set(index, k);
   12289        sort_array->set(index, Smi::FromInt(details.index()));
   12290        index++;
   12291      }
   12292   }
   12293   storage->SortPairs(sort_array, sort_array->length());
   12294   ASSERT(storage->length() >= index);
   12295 }
   12296 
   12297 
   12298 template<typename Shape, typename Key>
   12299 void Dictionary<Shape, Key>::CopyKeysTo(
   12300     FixedArray* storage,
   12301     int index,
   12302     typename Dictionary<Shape, Key>::SortMode sort_mode) {
   12303   ASSERT(storage->length() >= NumberOfElementsFilterAttributes(
   12304       static_cast<PropertyAttributes>(NONE)));
   12305   int capacity = HashTable<Shape, Key>::Capacity();
   12306   for (int i = 0; i < capacity; i++) {
   12307     Object* k = HashTable<Shape, Key>::KeyAt(i);
   12308     if (HashTable<Shape, Key>::IsKey(k)) {
   12309       PropertyDetails details = DetailsAt(i);
   12310       if (details.IsDeleted()) continue;
   12311       storage->set(index++, k);
   12312     }
   12313   }
   12314   if (sort_mode == Dictionary<Shape, Key>::SORTED) {
   12315     storage->SortPairs(storage, index);
   12316   }
   12317   ASSERT(storage->length() >= index);
   12318 }
   12319 
   12320 
   12321 // Backwards lookup (slow).
   12322 template<typename Shape, typename Key>
   12323 Object* Dictionary<Shape, Key>::SlowReverseLookup(Object* value) {
   12324   int capacity = HashTable<Shape, Key>::Capacity();
   12325   for (int i = 0; i < capacity; i++) {
   12326     Object* k =  HashTable<Shape, Key>::KeyAt(i);
   12327     if (Dictionary<Shape, Key>::IsKey(k)) {
   12328       Object* e = ValueAt(i);
   12329       if (e->IsJSGlobalPropertyCell()) {
   12330         e = JSGlobalPropertyCell::cast(e)->value();
   12331       }
   12332       if (e == value) return k;
   12333     }
   12334   }
   12335   Heap* heap = Dictionary<Shape, Key>::GetHeap();
   12336   return heap->undefined_value();
   12337 }
   12338 
   12339 
   12340 MaybeObject* StringDictionary::TransformPropertiesToFastFor(
   12341     JSObject* obj, int unused_property_fields) {
   12342   // Make sure we preserve dictionary representation if there are too many
   12343   // descriptors.
   12344   if (NumberOfElements() > DescriptorArray::kMaxNumberOfDescriptors) return obj;
   12345 
   12346   // Figure out if it is necessary to generate new enumeration indices.
   12347   int max_enumeration_index =
   12348       NextEnumerationIndex() +
   12349           (DescriptorArray::kMaxNumberOfDescriptors -
   12350            NumberOfElements());
   12351   if (!PropertyDetails::IsValidIndex(max_enumeration_index)) {
   12352     Object* result;
   12353     { MaybeObject* maybe_result = GenerateNewEnumerationIndices();
   12354       if (!maybe_result->ToObject(&result)) return maybe_result;
   12355     }
   12356   }
   12357 
   12358   int instance_descriptor_length = 0;
   12359   int number_of_fields = 0;
   12360 
   12361   Heap* heap = GetHeap();
   12362 
   12363   // Compute the length of the instance descriptor.
   12364   int capacity = Capacity();
   12365   for (int i = 0; i < capacity; i++) {
   12366     Object* k = KeyAt(i);
   12367     if (IsKey(k)) {
   12368       Object* value = ValueAt(i);
   12369       PropertyType type = DetailsAt(i).type();
   12370       ASSERT(type != FIELD);
   12371       instance_descriptor_length++;
   12372       if (type == NORMAL &&
   12373           (!value->IsJSFunction() || heap->InNewSpace(value))) {
   12374         number_of_fields += 1;
   12375       }
   12376     }
   12377   }
   12378 
   12379   // Allocate the instance descriptor.
   12380   DescriptorArray* descriptors;
   12381   { MaybeObject* maybe_descriptors =
   12382         DescriptorArray::Allocate(instance_descriptor_length);
   12383     if (!maybe_descriptors->To<DescriptorArray>(&descriptors)) {
   12384       return maybe_descriptors;
   12385     }
   12386   }
   12387 
   12388   DescriptorArray::WhitenessWitness witness(descriptors);
   12389 
   12390   int inobject_props = obj->map()->inobject_properties();
   12391   int number_of_allocated_fields =
   12392       number_of_fields + unused_property_fields - inobject_props;
   12393   if (number_of_allocated_fields < 0) {
   12394     // There is enough inobject space for all fields (including unused).
   12395     number_of_allocated_fields = 0;
   12396     unused_property_fields = inobject_props - number_of_fields;
   12397   }
   12398 
   12399   // Allocate the fixed array for the fields.
   12400   Object* fields;
   12401   { MaybeObject* maybe_fields =
   12402         heap->AllocateFixedArray(number_of_allocated_fields);
   12403     if (!maybe_fields->ToObject(&fields)) return maybe_fields;
   12404   }
   12405 
   12406   // Fill in the instance descriptor and the fields.
   12407   int next_descriptor = 0;
   12408   int current_offset = 0;
   12409   for (int i = 0; i < capacity; i++) {
   12410     Object* k = KeyAt(i);
   12411     if (IsKey(k)) {
   12412       Object* value = ValueAt(i);
   12413       // Ensure the key is a symbol before writing into the instance descriptor.
   12414       Object* key;
   12415       { MaybeObject* maybe_key = heap->LookupSymbol(String::cast(k));
   12416         if (!maybe_key->ToObject(&key)) return maybe_key;
   12417       }
   12418       PropertyDetails details = DetailsAt(i);
   12419       PropertyType type = details.type();
   12420 
   12421       if (value->IsJSFunction() && !heap->InNewSpace(value)) {
   12422         ConstantFunctionDescriptor d(String::cast(key),
   12423                                      JSFunction::cast(value),
   12424                                      details.attributes(),
   12425                                      details.index());
   12426         descriptors->Set(next_descriptor++, &d, witness);
   12427       } else if (type == NORMAL) {
   12428         if (current_offset < inobject_props) {
   12429           obj->InObjectPropertyAtPut(current_offset,
   12430                                      value,
   12431                                      UPDATE_WRITE_BARRIER);
   12432         } else {
   12433           int offset = current_offset - inobject_props;
   12434           FixedArray::cast(fields)->set(offset, value);
   12435         }
   12436         FieldDescriptor d(String::cast(key),
   12437                           current_offset++,
   12438                           details.attributes(),
   12439                           details.index());
   12440         descriptors->Set(next_descriptor++, &d, witness);
   12441       } else if (type == CALLBACKS) {
   12442         if (value->IsAccessorPair()) {
   12443           MaybeObject* maybe_copy =
   12444               AccessorPair::cast(value)->CopyWithoutTransitions();
   12445           if (!maybe_copy->To(&value)) return maybe_copy;
   12446         }
   12447         CallbacksDescriptor d(String::cast(key),
   12448                               value,
   12449                               details.attributes(),
   12450                               details.index());
   12451         descriptors->Set(next_descriptor++, &d, witness);
   12452       } else {
   12453         UNREACHABLE();
   12454       }
   12455     }
   12456   }
   12457   ASSERT(current_offset == number_of_fields);
   12458 
   12459   descriptors->Sort(witness);
   12460   // Allocate new map.
   12461   Object* new_map;
   12462   { MaybeObject* maybe_new_map = obj->map()->CopyDropDescriptors();
   12463     if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
   12464   }
   12465 
   12466   // Transform the object.
   12467   obj->set_map(Map::cast(new_map));
   12468   obj->map()->set_instance_descriptors(descriptors);
   12469   obj->map()->set_unused_property_fields(unused_property_fields);
   12470 
   12471   obj->set_properties(FixedArray::cast(fields));
   12472   ASSERT(obj->IsJSObject());
   12473 
   12474   descriptors->SetNextEnumerationIndex(NextEnumerationIndex());
   12475   // Check that it really works.
   12476   ASSERT(obj->HasFastProperties());
   12477 
   12478   return obj;
   12479 }
   12480 
   12481 
   12482 bool ObjectHashSet::Contains(Object* key) {
   12483   ASSERT(IsKey(key));
   12484 
   12485   // If the object does not have an identity hash, it was never used as a key.
   12486   { MaybeObject* maybe_hash = key->GetHash(OMIT_CREATION);
   12487     if (maybe_hash->ToObjectUnchecked()->IsUndefined()) return false;
   12488   }
   12489   return (FindEntry(key) != kNotFound);
   12490 }
   12491 
   12492 
   12493 MaybeObject* ObjectHashSet::Add(Object* key) {
   12494   ASSERT(IsKey(key));
   12495 
   12496   // Make sure the key object has an identity hash code.
   12497   int hash;
   12498   { MaybeObject* maybe_hash = key->GetHash(ALLOW_CREATION);
   12499     if (maybe_hash->IsFailure()) return maybe_hash;
   12500     hash = Smi::cast(maybe_hash->ToObjectUnchecked())->value();
   12501   }
   12502   int entry = FindEntry(key);
   12503 
   12504   // Check whether key is already present.
   12505   if (entry != kNotFound) return this;
   12506 
   12507   // Check whether the hash set should be extended and add entry.
   12508   Object* obj;
   12509   { MaybeObject* maybe_obj = EnsureCapacity(1, key);
   12510     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   12511   }
   12512   ObjectHashSet* table = ObjectHashSet::cast(obj);
   12513   entry = table->FindInsertionEntry(hash);
   12514   table->set(EntryToIndex(entry), key);
   12515   table->ElementAdded();
   12516   return table;
   12517 }
   12518 
   12519 
   12520 MaybeObject* ObjectHashSet::Remove(Object* key) {
   12521   ASSERT(IsKey(key));
   12522 
   12523   // If the object does not have an identity hash, it was never used as a key.
   12524   { MaybeObject* maybe_hash = key->GetHash(OMIT_CREATION);
   12525     if (maybe_hash->ToObjectUnchecked()->IsUndefined()) return this;
   12526   }
   12527   int entry = FindEntry(key);
   12528 
   12529   // Check whether key is actually present.
   12530   if (entry == kNotFound) return this;
   12531 
   12532   // Remove entry and try to shrink this hash set.
   12533   set_the_hole(EntryToIndex(entry));
   12534   ElementRemoved();
   12535   return Shrink(key);
   12536 }
   12537 
   12538 
   12539 Object* ObjectHashTable::Lookup(Object* key) {
   12540   ASSERT(IsKey(key));
   12541 
   12542   // If the object does not have an identity hash, it was never used as a key.
   12543   { MaybeObject* maybe_hash = key->GetHash(OMIT_CREATION);
   12544     if (maybe_hash->ToObjectUnchecked()->IsUndefined()) {
   12545       return GetHeap()->undefined_value();
   12546     }
   12547   }
   12548   int entry = FindEntry(key);
   12549   if (entry == kNotFound) return GetHeap()->undefined_value();
   12550   return get(EntryToIndex(entry) + 1);
   12551 }
   12552 
   12553 
   12554 MaybeObject* ObjectHashTable::Put(Object* key, Object* value) {
   12555   ASSERT(IsKey(key));
   12556 
   12557   // Make sure the key object has an identity hash code.
   12558   int hash;
   12559   { MaybeObject* maybe_hash = key->GetHash(ALLOW_CREATION);
   12560     if (maybe_hash->IsFailure()) return maybe_hash;
   12561     hash = Smi::cast(maybe_hash->ToObjectUnchecked())->value();
   12562   }
   12563   int entry = FindEntry(key);
   12564 
   12565   // Check whether to perform removal operation.
   12566   if (value->IsUndefined()) {
   12567     if (entry == kNotFound) return this;
   12568     RemoveEntry(entry);
   12569     return Shrink(key);
   12570   }
   12571 
   12572   // Key is already in table, just overwrite value.
   12573   if (entry != kNotFound) {
   12574     set(EntryToIndex(entry) + 1, value);
   12575     return this;
   12576   }
   12577 
   12578   // Check whether the hash table should be extended.
   12579   Object* obj;
   12580   { MaybeObject* maybe_obj = EnsureCapacity(1, key);
   12581     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   12582   }
   12583   ObjectHashTable* table = ObjectHashTable::cast(obj);
   12584   table->AddEntry(table->FindInsertionEntry(hash), key, value);
   12585   return table;
   12586 }
   12587 
   12588 
   12589 void ObjectHashTable::AddEntry(int entry, Object* key, Object* value) {
   12590   set(EntryToIndex(entry), key);
   12591   set(EntryToIndex(entry) + 1, value);
   12592   ElementAdded();
   12593 }
   12594 
   12595 
   12596 void ObjectHashTable::RemoveEntry(int entry) {
   12597   set_the_hole(EntryToIndex(entry));
   12598   set_the_hole(EntryToIndex(entry) + 1);
   12599   ElementRemoved();
   12600 }
   12601 
   12602 
   12603 #ifdef ENABLE_DEBUGGER_SUPPORT
   12604 // Check if there is a break point at this code position.
   12605 bool DebugInfo::HasBreakPoint(int code_position) {
   12606   // Get the break point info object for this code position.
   12607   Object* break_point_info = GetBreakPointInfo(code_position);
   12608 
   12609   // If there is no break point info object or no break points in the break
   12610   // point info object there is no break point at this code position.
   12611   if (break_point_info->IsUndefined()) return false;
   12612   return BreakPointInfo::cast(break_point_info)->GetBreakPointCount() > 0;
   12613 }
   12614 
   12615 
   12616 // Get the break point info object for this code position.
   12617 Object* DebugInfo::GetBreakPointInfo(int code_position) {
   12618   // Find the index of the break point info object for this code position.
   12619   int index = GetBreakPointInfoIndex(code_position);
   12620 
   12621   // Return the break point info object if any.
   12622   if (index == kNoBreakPointInfo) return GetHeap()->undefined_value();
   12623   return BreakPointInfo::cast(break_points()->get(index));
   12624 }
   12625 
   12626 
   12627 // Clear a break point at the specified code position.
   12628 void DebugInfo::ClearBreakPoint(Handle<DebugInfo> debug_info,
   12629                                 int code_position,
   12630                                 Handle<Object> break_point_object) {
   12631   Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_position));
   12632   if (break_point_info->IsUndefined()) return;
   12633   BreakPointInfo::ClearBreakPoint(
   12634       Handle<BreakPointInfo>::cast(break_point_info),
   12635       break_point_object);
   12636 }
   12637 
   12638 
   12639 void DebugInfo::SetBreakPoint(Handle<DebugInfo> debug_info,
   12640                               int code_position,
   12641                               int source_position,
   12642                               int statement_position,
   12643                               Handle<Object> break_point_object) {
   12644   Isolate* isolate = Isolate::Current();
   12645   Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_position));
   12646   if (!break_point_info->IsUndefined()) {
   12647     BreakPointInfo::SetBreakPoint(
   12648         Handle<BreakPointInfo>::cast(break_point_info),
   12649         break_point_object);
   12650     return;
   12651   }
   12652 
   12653   // Adding a new break point for a code position which did not have any
   12654   // break points before. Try to find a free slot.
   12655   int index = kNoBreakPointInfo;
   12656   for (int i = 0; i < debug_info->break_points()->length(); i++) {
   12657     if (debug_info->break_points()->get(i)->IsUndefined()) {
   12658       index = i;
   12659       break;
   12660     }
   12661   }
   12662   if (index == kNoBreakPointInfo) {
   12663     // No free slot - extend break point info array.
   12664     Handle<FixedArray> old_break_points =
   12665         Handle<FixedArray>(FixedArray::cast(debug_info->break_points()));
   12666     Handle<FixedArray> new_break_points =
   12667         isolate->factory()->NewFixedArray(
   12668             old_break_points->length() +
   12669             Debug::kEstimatedNofBreakPointsInFunction);
   12670 
   12671     debug_info->set_break_points(*new_break_points);
   12672     for (int i = 0; i < old_break_points->length(); i++) {
   12673       new_break_points->set(i, old_break_points->get(i));
   12674     }
   12675     index = old_break_points->length();
   12676   }
   12677   ASSERT(index != kNoBreakPointInfo);
   12678 
   12679   // Allocate new BreakPointInfo object and set the break point.
   12680   Handle<BreakPointInfo> new_break_point_info = Handle<BreakPointInfo>::cast(
   12681       isolate->factory()->NewStruct(BREAK_POINT_INFO_TYPE));
   12682   new_break_point_info->set_code_position(Smi::FromInt(code_position));
   12683   new_break_point_info->set_source_position(Smi::FromInt(source_position));
   12684   new_break_point_info->
   12685       set_statement_position(Smi::FromInt(statement_position));
   12686   new_break_point_info->set_break_point_objects(
   12687       isolate->heap()->undefined_value());
   12688   BreakPointInfo::SetBreakPoint(new_break_point_info, break_point_object);
   12689   debug_info->break_points()->set(index, *new_break_point_info);
   12690 }
   12691 
   12692 
   12693 // Get the break point objects for a code position.
   12694 Object* DebugInfo::GetBreakPointObjects(int code_position) {
   12695   Object* break_point_info = GetBreakPointInfo(code_position);
   12696   if (break_point_info->IsUndefined()) {
   12697     return GetHeap()->undefined_value();
   12698   }
   12699   return BreakPointInfo::cast(break_point_info)->break_point_objects();
   12700 }
   12701 
   12702 
   12703 // Get the total number of break points.
   12704 int DebugInfo::GetBreakPointCount() {
   12705   if (break_points()->IsUndefined()) return 0;
   12706   int count = 0;
   12707   for (int i = 0; i < break_points()->length(); i++) {
   12708     if (!break_points()->get(i)->IsUndefined()) {
   12709       BreakPointInfo* break_point_info =
   12710           BreakPointInfo::cast(break_points()->get(i));
   12711       count += break_point_info->GetBreakPointCount();
   12712     }
   12713   }
   12714   return count;
   12715 }
   12716 
   12717 
   12718 Object* DebugInfo::FindBreakPointInfo(Handle<DebugInfo> debug_info,
   12719                                       Handle<Object> break_point_object) {
   12720   Heap* heap = debug_info->GetHeap();
   12721   if (debug_info->break_points()->IsUndefined()) return heap->undefined_value();
   12722   for (int i = 0; i < debug_info->break_points()->length(); i++) {
   12723     if (!debug_info->break_points()->get(i)->IsUndefined()) {
   12724       Handle<BreakPointInfo> break_point_info =
   12725           Handle<BreakPointInfo>(BreakPointInfo::cast(
   12726               debug_info->break_points()->get(i)));
   12727       if (BreakPointInfo::HasBreakPointObject(break_point_info,
   12728                                               break_point_object)) {
   12729         return *break_point_info;
   12730       }
   12731     }
   12732   }
   12733   return heap->undefined_value();
   12734 }
   12735 
   12736 
   12737 // Find the index of the break point info object for the specified code
   12738 // position.
   12739 int DebugInfo::GetBreakPointInfoIndex(int code_position) {
   12740   if (break_points()->IsUndefined()) return kNoBreakPointInfo;
   12741   for (int i = 0; i < break_points()->length(); i++) {
   12742     if (!break_points()->get(i)->IsUndefined()) {
   12743       BreakPointInfo* break_point_info =
   12744           BreakPointInfo::cast(break_points()->get(i));
   12745       if (break_point_info->code_position()->value() == code_position) {
   12746         return i;
   12747       }
   12748     }
   12749   }
   12750   return kNoBreakPointInfo;
   12751 }
   12752 
   12753 
   12754 // Remove the specified break point object.
   12755 void BreakPointInfo::ClearBreakPoint(Handle<BreakPointInfo> break_point_info,
   12756                                      Handle<Object> break_point_object) {
   12757   Isolate* isolate = Isolate::Current();
   12758   // If there are no break points just ignore.
   12759   if (break_point_info->break_point_objects()->IsUndefined()) return;
   12760   // If there is a single break point clear it if it is the same.
   12761   if (!break_point_info->break_point_objects()->IsFixedArray()) {
   12762     if (break_point_info->break_point_objects() == *break_point_object) {
   12763       break_point_info->set_break_point_objects(
   12764           isolate->heap()->undefined_value());
   12765     }
   12766     return;
   12767   }
   12768   // If there are multiple break points shrink the array
   12769   ASSERT(break_point_info->break_point_objects()->IsFixedArray());
   12770   Handle<FixedArray> old_array =
   12771       Handle<FixedArray>(
   12772           FixedArray::cast(break_point_info->break_point_objects()));
   12773   Handle<FixedArray> new_array =
   12774       isolate->factory()->NewFixedArray(old_array->length() - 1);
   12775   int found_count = 0;
   12776   for (int i = 0; i < old_array->length(); i++) {
   12777     if (old_array->get(i) == *break_point_object) {
   12778       ASSERT(found_count == 0);
   12779       found_count++;
   12780     } else {
   12781       new_array->set(i - found_count, old_array->get(i));
   12782     }
   12783   }
   12784   // If the break point was found in the list change it.
   12785   if (found_count > 0) break_point_info->set_break_point_objects(*new_array);
   12786 }
   12787 
   12788 
   12789 // Add the specified break point object.
   12790 void BreakPointInfo::SetBreakPoint(Handle<BreakPointInfo> break_point_info,
   12791                                    Handle<Object> break_point_object) {
   12792   // If there was no break point objects before just set it.
   12793   if (break_point_info->break_point_objects()->IsUndefined()) {
   12794     break_point_info->set_break_point_objects(*break_point_object);
   12795     return;
   12796   }
   12797   // If the break point object is the same as before just ignore.
   12798   if (break_point_info->break_point_objects() == *break_point_object) return;
   12799   // If there was one break point object before replace with array.
   12800   if (!break_point_info->break_point_objects()->IsFixedArray()) {
   12801     Handle<FixedArray> array = FACTORY->NewFixedArray(2);
   12802     array->set(0, break_point_info->break_point_objects());
   12803     array->set(1, *break_point_object);
   12804     break_point_info->set_break_point_objects(*array);
   12805     return;
   12806   }
   12807   // If there was more than one break point before extend array.
   12808   Handle<FixedArray> old_array =
   12809       Handle<FixedArray>(
   12810           FixedArray::cast(break_point_info->break_point_objects()));
   12811   Handle<FixedArray> new_array =
   12812       FACTORY->NewFixedArray(old_array->length() + 1);
   12813   for (int i = 0; i < old_array->length(); i++) {
   12814     // If the break point was there before just ignore.
   12815     if (old_array->get(i) == *break_point_object) return;
   12816     new_array->set(i, old_array->get(i));
   12817   }
   12818   // Add the new break point.
   12819   new_array->set(old_array->length(), *break_point_object);
   12820   break_point_info->set_break_point_objects(*new_array);
   12821 }
   12822 
   12823 
   12824 bool BreakPointInfo::HasBreakPointObject(
   12825     Handle<BreakPointInfo> break_point_info,
   12826     Handle<Object> break_point_object) {
   12827   // No break point.
   12828   if (break_point_info->break_point_objects()->IsUndefined()) return false;
   12829   // Single break point.
   12830   if (!break_point_info->break_point_objects()->IsFixedArray()) {
   12831     return break_point_info->break_point_objects() == *break_point_object;
   12832   }
   12833   // Multiple break points.
   12834   FixedArray* array = FixedArray::cast(break_point_info->break_point_objects());
   12835   for (int i = 0; i < array->length(); i++) {
   12836     if (array->get(i) == *break_point_object) {
   12837       return true;
   12838     }
   12839   }
   12840   return false;
   12841 }
   12842 
   12843 
   12844 // Get the number of break points.
   12845 int BreakPointInfo::GetBreakPointCount() {
   12846   // No break point.
   12847   if (break_point_objects()->IsUndefined()) return 0;
   12848   // Single break point.
   12849   if (!break_point_objects()->IsFixedArray()) return 1;
   12850   // Multiple break points.
   12851   return FixedArray::cast(break_point_objects())->length();
   12852 }
   12853 #endif  // ENABLE_DEBUGGER_SUPPORT
   12854 
   12855 
   12856 MaybeObject* JSDate::GetField(Object* object, Smi* index) {
   12857   return JSDate::cast(object)->DoGetField(
   12858       static_cast<FieldIndex>(index->value()));
   12859 }
   12860 
   12861 
   12862 Object* JSDate::DoGetField(FieldIndex index) {
   12863   ASSERT(index != kDateValue);
   12864 
   12865   DateCache* date_cache = GetIsolate()->date_cache();
   12866 
   12867   if (index < kFirstUncachedField) {
   12868     Object* stamp = cache_stamp();
   12869     if (stamp != date_cache->stamp() && stamp->IsSmi()) {
   12870       // Since the stamp is not NaN, the value is also not NaN.
   12871       int64_t local_time_ms =
   12872           date_cache->ToLocal(static_cast<int64_t>(value()->Number()));
   12873       SetLocalFields(local_time_ms, date_cache);
   12874     }
   12875     switch (index) {
   12876       case kYear: return year();
   12877       case kMonth: return month();
   12878       case kDay: return day();
   12879       case kWeekday: return weekday();
   12880       case kHour: return hour();
   12881       case kMinute: return min();
   12882       case kSecond: return sec();
   12883       default: UNREACHABLE();
   12884     }
   12885   }
   12886 
   12887   if (index >= kFirstUTCField) {
   12888     return GetUTCField(index, value()->Number(), date_cache);
   12889   }
   12890 
   12891   double time = value()->Number();
   12892   if (isnan(time)) return GetIsolate()->heap()->nan_value();
   12893 
   12894   int64_t local_time_ms = date_cache->ToLocal(static_cast<int64_t>(time));
   12895   int days = DateCache::DaysFromTime(local_time_ms);
   12896 
   12897   if (index == kDays) return Smi::FromInt(days);
   12898 
   12899   int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days);
   12900   if (index == kMillisecond) return Smi::FromInt(time_in_day_ms % 1000);
   12901   ASSERT(index == kTimeInDay);
   12902   return Smi::FromInt(time_in_day_ms);
   12903 }
   12904 
   12905 
   12906 Object* JSDate::GetUTCField(FieldIndex index,
   12907                             double value,
   12908                             DateCache* date_cache) {
   12909   ASSERT(index >= kFirstUTCField);
   12910 
   12911   if (isnan(value)) return GetIsolate()->heap()->nan_value();
   12912 
   12913   int64_t time_ms = static_cast<int64_t>(value);
   12914 
   12915   if (index == kTimezoneOffset) {
   12916     return Smi::FromInt(date_cache->TimezoneOffset(time_ms));
   12917   }
   12918 
   12919   int days = DateCache::DaysFromTime(time_ms);
   12920 
   12921   if (index == kWeekdayUTC) return Smi::FromInt(date_cache->Weekday(days));
   12922 
   12923   if (index <= kDayUTC) {
   12924     int year, month, day;
   12925     date_cache->YearMonthDayFromDays(days, &year, &month, &day);
   12926     if (index == kYearUTC) return Smi::FromInt(year);
   12927     if (index == kMonthUTC) return Smi::FromInt(month);
   12928     ASSERT(index == kDayUTC);
   12929     return Smi::FromInt(day);
   12930   }
   12931 
   12932   int time_in_day_ms = DateCache::TimeInDay(time_ms, days);
   12933   switch (index) {
   12934     case kHourUTC: return Smi::FromInt(time_in_day_ms / (60 * 60 * 1000));
   12935     case kMinuteUTC: return Smi::FromInt((time_in_day_ms / (60 * 1000)) % 60);
   12936     case kSecondUTC: return Smi::FromInt((time_in_day_ms / 1000) % 60);
   12937     case kMillisecondUTC: return Smi::FromInt(time_in_day_ms % 1000);
   12938     case kDaysUTC: return Smi::FromInt(days);
   12939     case kTimeInDayUTC: return Smi::FromInt(time_in_day_ms);
   12940     default: UNREACHABLE();
   12941   }
   12942 
   12943   UNREACHABLE();
   12944   return NULL;
   12945 }
   12946 
   12947 
   12948 void JSDate::SetValue(Object* value, bool is_value_nan) {
   12949   set_value(value);
   12950   if (is_value_nan) {
   12951     HeapNumber* nan = GetIsolate()->heap()->nan_value();
   12952     set_cache_stamp(nan, SKIP_WRITE_BARRIER);
   12953     set_year(nan, SKIP_WRITE_BARRIER);
   12954     set_month(nan, SKIP_WRITE_BARRIER);
   12955     set_day(nan, SKIP_WRITE_BARRIER);
   12956     set_hour(nan, SKIP_WRITE_BARRIER);
   12957     set_min(nan, SKIP_WRITE_BARRIER);
   12958     set_sec(nan, SKIP_WRITE_BARRIER);
   12959     set_weekday(nan, SKIP_WRITE_BARRIER);
   12960   } else {
   12961     set_cache_stamp(Smi::FromInt(DateCache::kInvalidStamp), SKIP_WRITE_BARRIER);
   12962   }
   12963 }
   12964 
   12965 
   12966 void JSDate::SetLocalFields(int64_t local_time_ms, DateCache* date_cache) {
   12967   int days = DateCache::DaysFromTime(local_time_ms);
   12968   int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days);
   12969   int year, month, day;
   12970   date_cache->YearMonthDayFromDays(days, &year, &month, &day);
   12971   int weekday = date_cache->Weekday(days);
   12972   int hour = time_in_day_ms / (60 * 60 * 1000);
   12973   int min = (time_in_day_ms / (60 * 1000)) % 60;
   12974   int sec = (time_in_day_ms / 1000) % 60;
   12975   set_cache_stamp(date_cache->stamp());
   12976   set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
   12977   set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
   12978   set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
   12979   set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
   12980   set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER);
   12981   set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
   12982   set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
   12983 }
   12984 
   12985 } }  // namespace v8::internal
   12986