Home | History | Annotate | Download | only in src
      1 // Copyright 2006-2009 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 "debug.h"
     34 #include "execution.h"
     35 #include "objects-inl.h"
     36 #include "macro-assembler.h"
     37 #include "scanner.h"
     38 #include "scopeinfo.h"
     39 #include "string-stream.h"
     40 #include "utils.h"
     41 
     42 #ifdef ENABLE_DISASSEMBLER
     43 #include "disassembler.h"
     44 #endif
     45 
     46 
     47 namespace v8 {
     48 namespace internal {
     49 
     50 // Getters and setters are stored in a fixed array property.  These are
     51 // constants for their indices.
     52 const int kGetterIndex = 0;
     53 const int kSetterIndex = 1;
     54 
     55 
     56 static Object* CreateJSValue(JSFunction* constructor, Object* value) {
     57   Object* result = Heap::AllocateJSObject(constructor);
     58   if (result->IsFailure()) return result;
     59   JSValue::cast(result)->set_value(value);
     60   return result;
     61 }
     62 
     63 
     64 Object* Object::ToObject(Context* global_context) {
     65   if (IsNumber()) {
     66     return CreateJSValue(global_context->number_function(), this);
     67   } else if (IsBoolean()) {
     68     return CreateJSValue(global_context->boolean_function(), this);
     69   } else if (IsString()) {
     70     return CreateJSValue(global_context->string_function(), this);
     71   }
     72   ASSERT(IsJSObject());
     73   return this;
     74 }
     75 
     76 
     77 Object* Object::ToObject() {
     78   Context* global_context = Top::context()->global_context();
     79   if (IsJSObject()) {
     80     return this;
     81   } else if (IsNumber()) {
     82     return CreateJSValue(global_context->number_function(), this);
     83   } else if (IsBoolean()) {
     84     return CreateJSValue(global_context->boolean_function(), this);
     85   } else if (IsString()) {
     86     return CreateJSValue(global_context->string_function(), this);
     87   }
     88 
     89   // Throw a type error.
     90   return Failure::InternalError();
     91 }
     92 
     93 
     94 Object* Object::ToBoolean() {
     95   if (IsTrue()) return Heap::true_value();
     96   if (IsFalse()) return Heap::false_value();
     97   if (IsSmi()) {
     98     return Heap::ToBoolean(Smi::cast(this)->value() != 0);
     99   }
    100   if (IsUndefined() || IsNull()) return Heap::false_value();
    101   // Undetectable object is false
    102   if (IsUndetectableObject()) {
    103     return Heap::false_value();
    104   }
    105   if (IsString()) {
    106     return Heap::ToBoolean(String::cast(this)->length() != 0);
    107   }
    108   if (IsHeapNumber()) {
    109     return HeapNumber::cast(this)->HeapNumberToBoolean();
    110   }
    111   return Heap::true_value();
    112 }
    113 
    114 
    115 void Object::Lookup(String* name, LookupResult* result) {
    116   if (IsJSObject()) return JSObject::cast(this)->Lookup(name, result);
    117   Object* holder = NULL;
    118   Context* global_context = Top::context()->global_context();
    119   if (IsString()) {
    120     holder = global_context->string_function()->instance_prototype();
    121   } else if (IsNumber()) {
    122     holder = global_context->number_function()->instance_prototype();
    123   } else if (IsBoolean()) {
    124     holder = global_context->boolean_function()->instance_prototype();
    125   }
    126   ASSERT(holder != NULL);  // Cannot handle null or undefined.
    127   JSObject::cast(holder)->Lookup(name, result);
    128 }
    129 
    130 
    131 Object* Object::GetPropertyWithReceiver(Object* receiver,
    132                                         String* name,
    133                                         PropertyAttributes* attributes) {
    134   LookupResult result;
    135   Lookup(name, &result);
    136   Object* value = GetProperty(receiver, &result, name, attributes);
    137   ASSERT(*attributes <= ABSENT);
    138   return value;
    139 }
    140 
    141 
    142 Object* Object::GetPropertyWithCallback(Object* receiver,
    143                                         Object* structure,
    144                                         String* name,
    145                                         Object* holder) {
    146   // To accommodate both the old and the new api we switch on the
    147   // data structure used to store the callbacks.  Eventually proxy
    148   // callbacks should be phased out.
    149   if (structure->IsProxy()) {
    150     AccessorDescriptor* callback =
    151         reinterpret_cast<AccessorDescriptor*>(Proxy::cast(structure)->proxy());
    152     Object* value = (callback->getter)(receiver, callback->data);
    153     RETURN_IF_SCHEDULED_EXCEPTION();
    154     return value;
    155   }
    156 
    157   // api style callbacks.
    158   if (structure->IsAccessorInfo()) {
    159     AccessorInfo* data = AccessorInfo::cast(structure);
    160     Object* fun_obj = data->getter();
    161     v8::AccessorGetter call_fun = v8::ToCData<v8::AccessorGetter>(fun_obj);
    162     HandleScope scope;
    163     JSObject* self = JSObject::cast(receiver);
    164     JSObject* holder_handle = JSObject::cast(holder);
    165     Handle<String> key(name);
    166     LOG(ApiNamedPropertyAccess("load", self, name));
    167     CustomArguments args(data->data(), self, holder_handle);
    168     v8::AccessorInfo info(args.end());
    169     v8::Handle<v8::Value> result;
    170     {
    171       // Leaving JavaScript.
    172       VMState state(EXTERNAL);
    173       result = call_fun(v8::Utils::ToLocal(key), info);
    174     }
    175     RETURN_IF_SCHEDULED_EXCEPTION();
    176     if (result.IsEmpty()) return Heap::undefined_value();
    177     return *v8::Utils::OpenHandle(*result);
    178   }
    179 
    180   // __defineGetter__ callback
    181   if (structure->IsFixedArray()) {
    182     Object* getter = FixedArray::cast(structure)->get(kGetterIndex);
    183     if (getter->IsJSFunction()) {
    184       return Object::GetPropertyWithDefinedGetter(receiver,
    185                                                   JSFunction::cast(getter));
    186     }
    187     // Getter is not a function.
    188     return Heap::undefined_value();
    189   }
    190 
    191   UNREACHABLE();
    192   return 0;
    193 }
    194 
    195 
    196 Object* Object::GetPropertyWithDefinedGetter(Object* receiver,
    197                                              JSFunction* getter) {
    198   HandleScope scope;
    199   Handle<JSFunction> fun(JSFunction::cast(getter));
    200   Handle<Object> self(receiver);
    201 #ifdef ENABLE_DEBUGGER_SUPPORT
    202   // Handle stepping into a getter if step into is active.
    203   if (Debug::StepInActive()) {
    204     Debug::HandleStepIn(fun, Handle<Object>::null(), 0, false);
    205   }
    206 #endif
    207   bool has_pending_exception;
    208   Handle<Object> result =
    209       Execution::Call(fun, self, 0, NULL, &has_pending_exception);
    210   // Check for pending exception and return the result.
    211   if (has_pending_exception) return Failure::Exception();
    212   return *result;
    213 }
    214 
    215 
    216 // Only deal with CALLBACKS and INTERCEPTOR
    217 Object* JSObject::GetPropertyWithFailedAccessCheck(
    218     Object* receiver,
    219     LookupResult* result,
    220     String* name,
    221     PropertyAttributes* attributes) {
    222   if (result->IsProperty()) {
    223     switch (result->type()) {
    224       case CALLBACKS: {
    225         // Only allow API accessors.
    226         Object* obj = result->GetCallbackObject();
    227         if (obj->IsAccessorInfo()) {
    228           AccessorInfo* info = AccessorInfo::cast(obj);
    229           if (info->all_can_read()) {
    230             *attributes = result->GetAttributes();
    231             return GetPropertyWithCallback(receiver,
    232                                            result->GetCallbackObject(),
    233                                            name,
    234                                            result->holder());
    235           }
    236         }
    237         break;
    238       }
    239       case NORMAL:
    240       case FIELD:
    241       case CONSTANT_FUNCTION: {
    242         // Search ALL_CAN_READ accessors in prototype chain.
    243         LookupResult r;
    244         result->holder()->LookupRealNamedPropertyInPrototypes(name, &r);
    245         if (r.IsProperty()) {
    246           return GetPropertyWithFailedAccessCheck(receiver,
    247                                                   &r,
    248                                                   name,
    249                                                   attributes);
    250         }
    251         break;
    252       }
    253       case INTERCEPTOR: {
    254         // If the object has an interceptor, try real named properties.
    255         // No access check in GetPropertyAttributeWithInterceptor.
    256         LookupResult r;
    257         result->holder()->LookupRealNamedProperty(name, &r);
    258         if (r.IsProperty()) {
    259           return GetPropertyWithFailedAccessCheck(receiver,
    260                                                   &r,
    261                                                   name,
    262                                                   attributes);
    263         }
    264         break;
    265       }
    266       default:
    267         UNREACHABLE();
    268     }
    269   }
    270 
    271   // No accessible property found.
    272   *attributes = ABSENT;
    273   Top::ReportFailedAccessCheck(this, v8::ACCESS_GET);
    274   return Heap::undefined_value();
    275 }
    276 
    277 
    278 PropertyAttributes JSObject::GetPropertyAttributeWithFailedAccessCheck(
    279     Object* receiver,
    280     LookupResult* result,
    281     String* name,
    282     bool continue_search) {
    283   if (result->IsProperty()) {
    284     switch (result->type()) {
    285       case CALLBACKS: {
    286         // Only allow API accessors.
    287         Object* obj = result->GetCallbackObject();
    288         if (obj->IsAccessorInfo()) {
    289           AccessorInfo* info = AccessorInfo::cast(obj);
    290           if (info->all_can_read()) {
    291             return result->GetAttributes();
    292           }
    293         }
    294         break;
    295       }
    296 
    297       case NORMAL:
    298       case FIELD:
    299       case CONSTANT_FUNCTION: {
    300         if (!continue_search) break;
    301         // Search ALL_CAN_READ accessors in prototype chain.
    302         LookupResult r;
    303         result->holder()->LookupRealNamedPropertyInPrototypes(name, &r);
    304         if (r.IsProperty()) {
    305           return GetPropertyAttributeWithFailedAccessCheck(receiver,
    306                                                            &r,
    307                                                            name,
    308                                                            continue_search);
    309         }
    310         break;
    311       }
    312 
    313       case INTERCEPTOR: {
    314         // If the object has an interceptor, try real named properties.
    315         // No access check in GetPropertyAttributeWithInterceptor.
    316         LookupResult r;
    317         if (continue_search) {
    318           result->holder()->LookupRealNamedProperty(name, &r);
    319         } else {
    320           result->holder()->LocalLookupRealNamedProperty(name, &r);
    321         }
    322         if (r.IsProperty()) {
    323           return GetPropertyAttributeWithFailedAccessCheck(receiver,
    324                                                            &r,
    325                                                            name,
    326                                                            continue_search);
    327         }
    328         break;
    329       }
    330 
    331       default:
    332         UNREACHABLE();
    333     }
    334   }
    335 
    336   Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS);
    337   return ABSENT;
    338 }
    339 
    340 
    341 Object* JSObject::GetNormalizedProperty(LookupResult* result) {
    342   ASSERT(!HasFastProperties());
    343   Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry());
    344   if (IsGlobalObject()) {
    345     value = JSGlobalPropertyCell::cast(value)->value();
    346   }
    347   ASSERT(!value->IsJSGlobalPropertyCell());
    348   return value;
    349 }
    350 
    351 
    352 Object* JSObject::SetNormalizedProperty(LookupResult* result, Object* value) {
    353   ASSERT(!HasFastProperties());
    354   if (IsGlobalObject()) {
    355     JSGlobalPropertyCell* cell =
    356         JSGlobalPropertyCell::cast(
    357             property_dictionary()->ValueAt(result->GetDictionaryEntry()));
    358     cell->set_value(value);
    359   } else {
    360     property_dictionary()->ValueAtPut(result->GetDictionaryEntry(), value);
    361   }
    362   return value;
    363 }
    364 
    365 
    366 Object* JSObject::SetNormalizedProperty(String* name,
    367                                         Object* value,
    368                                         PropertyDetails details) {
    369   ASSERT(!HasFastProperties());
    370   int entry = property_dictionary()->FindEntry(name);
    371   if (entry == StringDictionary::kNotFound) {
    372     Object* store_value = value;
    373     if (IsGlobalObject()) {
    374       store_value = Heap::AllocateJSGlobalPropertyCell(value);
    375       if (store_value->IsFailure()) return store_value;
    376     }
    377     Object* dict = property_dictionary()->Add(name, store_value, details);
    378     if (dict->IsFailure()) return dict;
    379     set_properties(StringDictionary::cast(dict));
    380     return value;
    381   }
    382   // Preserve enumeration index.
    383   details = PropertyDetails(details.attributes(),
    384                             details.type(),
    385                             property_dictionary()->DetailsAt(entry).index());
    386   if (IsGlobalObject()) {
    387     JSGlobalPropertyCell* cell =
    388         JSGlobalPropertyCell::cast(property_dictionary()->ValueAt(entry));
    389     cell->set_value(value);
    390     // Please note we have to update the property details.
    391     property_dictionary()->DetailsAtPut(entry, details);
    392   } else {
    393     property_dictionary()->SetEntry(entry, name, value, details);
    394   }
    395   return value;
    396 }
    397 
    398 
    399 Object* JSObject::DeleteNormalizedProperty(String* name, DeleteMode mode) {
    400   ASSERT(!HasFastProperties());
    401   StringDictionary* dictionary = property_dictionary();
    402   int entry = dictionary->FindEntry(name);
    403   if (entry != StringDictionary::kNotFound) {
    404     // If we have a global object set the cell to the hole.
    405     if (IsGlobalObject()) {
    406       PropertyDetails details = dictionary->DetailsAt(entry);
    407       if (details.IsDontDelete()) {
    408         if (mode != FORCE_DELETION) return Heap::false_value();
    409         // When forced to delete global properties, we have to make a
    410         // map change to invalidate any ICs that think they can load
    411         // from the DontDelete cell without checking if it contains
    412         // the hole value.
    413         Object* new_map = map()->CopyDropDescriptors();
    414         if (new_map->IsFailure()) return new_map;
    415         set_map(Map::cast(new_map));
    416       }
    417       JSGlobalPropertyCell* cell =
    418           JSGlobalPropertyCell::cast(dictionary->ValueAt(entry));
    419       cell->set_value(Heap::the_hole_value());
    420       dictionary->DetailsAtPut(entry, details.AsDeleted());
    421     } else {
    422       return dictionary->DeleteProperty(entry, mode);
    423     }
    424   }
    425   return Heap::true_value();
    426 }
    427 
    428 
    429 bool JSObject::IsDirty() {
    430   Object* cons_obj = map()->constructor();
    431   if (!cons_obj->IsJSFunction())
    432     return true;
    433   JSFunction* fun = JSFunction::cast(cons_obj);
    434   if (!fun->shared()->function_data()->IsFunctionTemplateInfo())
    435     return true;
    436   // If the object is fully fast case and has the same map it was
    437   // created with then no changes can have been made to it.
    438   return map() != fun->initial_map()
    439       || !HasFastElements()
    440       || !HasFastProperties();
    441 }
    442 
    443 
    444 Object* Object::GetProperty(Object* receiver,
    445                             LookupResult* result,
    446                             String* name,
    447                             PropertyAttributes* attributes) {
    448   // Make sure that the top context does not change when doing
    449   // callbacks or interceptor calls.
    450   AssertNoContextChange ncc;
    451 
    452   // Traverse the prototype chain from the current object (this) to
    453   // the holder and check for access rights. This avoid traversing the
    454   // objects more than once in case of interceptors, because the
    455   // holder will always be the interceptor holder and the search may
    456   // only continue with a current object just after the interceptor
    457   // holder in the prototype chain.
    458   Object* last = result->IsProperty() ? result->holder() : Heap::null_value();
    459   for (Object* current = this; true; current = current->GetPrototype()) {
    460     if (current->IsAccessCheckNeeded()) {
    461       // Check if we're allowed to read from the current object. Note
    462       // that even though we may not actually end up loading the named
    463       // property from the current object, we still check that we have
    464       // access to it.
    465       JSObject* checked = JSObject::cast(current);
    466       if (!Top::MayNamedAccess(checked, name, v8::ACCESS_GET)) {
    467         return checked->GetPropertyWithFailedAccessCheck(receiver,
    468                                                          result,
    469                                                          name,
    470                                                          attributes);
    471       }
    472     }
    473     // Stop traversing the chain once we reach the last object in the
    474     // chain; either the holder of the result or null in case of an
    475     // absent property.
    476     if (current == last) break;
    477   }
    478 
    479   if (!result->IsProperty()) {
    480     *attributes = ABSENT;
    481     return Heap::undefined_value();
    482   }
    483   *attributes = result->GetAttributes();
    484   Object* value;
    485   JSObject* holder = result->holder();
    486   switch (result->type()) {
    487     case NORMAL:
    488       value = holder->GetNormalizedProperty(result);
    489       ASSERT(!value->IsTheHole() || result->IsReadOnly());
    490       return value->IsTheHole() ? Heap::undefined_value() : value;
    491     case FIELD:
    492       value = holder->FastPropertyAt(result->GetFieldIndex());
    493       ASSERT(!value->IsTheHole() || result->IsReadOnly());
    494       return value->IsTheHole() ? Heap::undefined_value() : value;
    495     case CONSTANT_FUNCTION:
    496       return result->GetConstantFunction();
    497     case CALLBACKS:
    498       return GetPropertyWithCallback(receiver,
    499                                      result->GetCallbackObject(),
    500                                      name,
    501                                      holder);
    502     case INTERCEPTOR: {
    503       JSObject* recvr = JSObject::cast(receiver);
    504       return holder->GetPropertyWithInterceptor(recvr, name, attributes);
    505     }
    506     default:
    507       UNREACHABLE();
    508       return NULL;
    509   }
    510 }
    511 
    512 
    513 Object* Object::GetElementWithReceiver(Object* receiver, uint32_t index) {
    514   // Non-JS objects do not have integer indexed properties.
    515   if (!IsJSObject()) return Heap::undefined_value();
    516   return JSObject::cast(this)->GetElementWithReceiver(JSObject::cast(receiver),
    517                                                       index);
    518 }
    519 
    520 
    521 Object* Object::GetPrototype() {
    522   // The object is either a number, a string, a boolean, or a real JS object.
    523   if (IsJSObject()) return JSObject::cast(this)->map()->prototype();
    524   Context* context = Top::context()->global_context();
    525 
    526   if (IsNumber()) return context->number_function()->instance_prototype();
    527   if (IsString()) return context->string_function()->instance_prototype();
    528   if (IsBoolean()) {
    529     return context->boolean_function()->instance_prototype();
    530   } else {
    531     return Heap::null_value();
    532   }
    533 }
    534 
    535 
    536 void Object::ShortPrint() {
    537   HeapStringAllocator allocator;
    538   StringStream accumulator(&allocator);
    539   ShortPrint(&accumulator);
    540   accumulator.OutputToStdOut();
    541 }
    542 
    543 
    544 void Object::ShortPrint(StringStream* accumulator) {
    545   if (IsSmi()) {
    546     Smi::cast(this)->SmiPrint(accumulator);
    547   } else if (IsFailure()) {
    548     Failure::cast(this)->FailurePrint(accumulator);
    549   } else {
    550     HeapObject::cast(this)->HeapObjectShortPrint(accumulator);
    551   }
    552 }
    553 
    554 
    555 void Smi::SmiPrint() {
    556   PrintF("%d", value());
    557 }
    558 
    559 
    560 void Smi::SmiPrint(StringStream* accumulator) {
    561   accumulator->Add("%d", value());
    562 }
    563 
    564 
    565 void Failure::FailurePrint(StringStream* accumulator) {
    566   accumulator->Add("Failure(%p)", reinterpret_cast<void*>(value()));
    567 }
    568 
    569 
    570 void Failure::FailurePrint() {
    571   PrintF("Failure(%p)", reinterpret_cast<void*>(value()));
    572 }
    573 
    574 
    575 Failure* Failure::RetryAfterGC(int requested_bytes, AllocationSpace space) {
    576   ASSERT((space & ~kSpaceTagMask) == 0);
    577   // TODO(X64): Stop using Smi validation for non-smi checks, even if they
    578   // happen to be identical at the moment.
    579 
    580   int requested = requested_bytes >> kObjectAlignmentBits;
    581   int value = (requested << kSpaceTagSize) | space;
    582   // We can't very well allocate a heap number in this situation, and if the
    583   // requested memory is so large it seems reasonable to say that this is an
    584   // out of memory situation.  This fixes a crash in
    585   // js1_5/Regress/regress-303213.js.
    586   if (value >> kSpaceTagSize != requested ||
    587       !Smi::IsValid(value) ||
    588       value != ((value << kFailureTypeTagSize) >> kFailureTypeTagSize) ||
    589       !Smi::IsValid(value << kFailureTypeTagSize)) {
    590     Top::context()->mark_out_of_memory();
    591     return Failure::OutOfMemoryException();
    592   }
    593   return Construct(RETRY_AFTER_GC, value);
    594 }
    595 
    596 
    597 // Should a word be prefixed by 'a' or 'an' in order to read naturally in
    598 // English?  Returns false for non-ASCII or words that don't start with
    599 // a capital letter.  The a/an rule follows pronunciation in English.
    600 // We don't use the BBC's overcorrect "an historic occasion" though if
    601 // you speak a dialect you may well say "an 'istoric occasion".
    602 static bool AnWord(String* str) {
    603   if (str->length() == 0) return false;  // A nothing.
    604   int c0 = str->Get(0);
    605   int c1 = str->length() > 1 ? str->Get(1) : 0;
    606   if (c0 == 'U') {
    607     if (c1 > 'Z') {
    608       return true;  // An Umpire, but a UTF8String, a U.
    609     }
    610   } else if (c0 == 'A' || c0 == 'E' || c0 == 'I' || c0 == 'O') {
    611     return true;    // An Ape, an ABCBook.
    612   } else if ((c1 == 0 || (c1 >= 'A' && c1 <= 'Z')) &&
    613            (c0 == 'F' || c0 == 'H' || c0 == 'M' || c0 == 'N' || c0 == 'R' ||
    614             c0 == 'S' || c0 == 'X')) {
    615     return true;    // An MP3File, an M.
    616   }
    617   return false;
    618 }
    619 
    620 
    621 Object* String::TryFlatten() {
    622 #ifdef DEBUG
    623   // Do not attempt to flatten in debug mode when allocation is not
    624   // allowed.  This is to avoid an assertion failure when allocating.
    625   // Flattening strings is the only case where we always allow
    626   // allocation because no GC is performed if the allocation fails.
    627   if (!Heap::IsAllocationAllowed()) return this;
    628 #endif
    629 
    630   switch (StringShape(this).representation_tag()) {
    631     case kConsStringTag: {
    632       ConsString* cs = ConsString::cast(this);
    633       if (cs->second()->length() == 0) {
    634         return this;
    635       }
    636       // There's little point in putting the flat string in new space if the
    637       // cons string is in old space.  It can never get GCed until there is
    638       // an old space GC.
    639       PretenureFlag tenure = Heap::InNewSpace(this) ? NOT_TENURED : TENURED;
    640       int len = length();
    641       Object* object;
    642       String* result;
    643       if (IsAsciiRepresentation()) {
    644         object = Heap::AllocateRawAsciiString(len, tenure);
    645         if (object->IsFailure()) return object;
    646         result = String::cast(object);
    647         String* first = cs->first();
    648         int first_length = first->length();
    649         char* dest = SeqAsciiString::cast(result)->GetChars();
    650         WriteToFlat(first, dest, 0, first_length);
    651         String* second = cs->second();
    652         WriteToFlat(second,
    653                     dest + first_length,
    654                     0,
    655                     len - first_length);
    656       } else {
    657         object = Heap::AllocateRawTwoByteString(len, tenure);
    658         if (object->IsFailure()) return object;
    659         result = String::cast(object);
    660         uc16* dest = SeqTwoByteString::cast(result)->GetChars();
    661         String* first = cs->first();
    662         int first_length = first->length();
    663         WriteToFlat(first, dest, 0, first_length);
    664         String* second = cs->second();
    665         WriteToFlat(second,
    666                     dest + first_length,
    667                     0,
    668                     len - first_length);
    669       }
    670       cs->set_first(result);
    671       cs->set_second(Heap::empty_string());
    672       return this;
    673     }
    674     default:
    675       return this;
    676   }
    677 }
    678 
    679 
    680 bool String::MakeExternal(v8::String::ExternalStringResource* resource) {
    681 #ifdef DEBUG
    682   if (FLAG_enable_slow_asserts) {
    683     // Assert that the resource and the string are equivalent.
    684     ASSERT(static_cast<size_t>(this->length()) == resource->length());
    685     SmartPointer<uc16> smart_chars(NewArray<uc16>(this->length()));
    686     String::WriteToFlat(this, *smart_chars, 0, this->length());
    687     ASSERT(memcmp(*smart_chars,
    688                   resource->data(),
    689                   resource->length() * sizeof(**smart_chars)) == 0);
    690   }
    691 #endif  // DEBUG
    692 
    693   int size = this->Size();  // Byte size of the original string.
    694   if (size < ExternalString::kSize) {
    695     // The string is too small to fit an external String in its place. This can
    696     // only happen for zero length strings.
    697     return false;
    698   }
    699   ASSERT(size >= ExternalString::kSize);
    700   bool is_symbol = this->IsSymbol();
    701   int length = this->length();
    702   int hash_field = this->hash_field();
    703 
    704   // Morph the object to an external string by adjusting the map and
    705   // reinitializing the fields.
    706   this->set_map(Heap::external_string_map());
    707   ExternalTwoByteString* self = ExternalTwoByteString::cast(this);
    708   self->set_length(length);
    709   self->set_hash_field(hash_field);
    710   self->set_resource(resource);
    711   // Additionally make the object into an external symbol if the original string
    712   // was a symbol to start with.
    713   if (is_symbol) {
    714     self->Hash();  // Force regeneration of the hash value.
    715     // Now morph this external string into a external symbol.
    716     this->set_map(Heap::external_symbol_map());
    717   }
    718 
    719   // Fill the remainder of the string with dead wood.
    720   int new_size = this->Size();  // Byte size of the external String object.
    721   Heap::CreateFillerObjectAt(this->address() + new_size, size - new_size);
    722   return true;
    723 }
    724 
    725 
    726 bool String::MakeExternal(v8::String::ExternalAsciiStringResource* resource) {
    727 #ifdef DEBUG
    728   if (FLAG_enable_slow_asserts) {
    729     // Assert that the resource and the string are equivalent.
    730     ASSERT(static_cast<size_t>(this->length()) == resource->length());
    731     SmartPointer<char> smart_chars(NewArray<char>(this->length()));
    732     String::WriteToFlat(this, *smart_chars, 0, this->length());
    733     ASSERT(memcmp(*smart_chars,
    734                   resource->data(),
    735                   resource->length()*sizeof(**smart_chars)) == 0);
    736   }
    737 #endif  // DEBUG
    738 
    739   int size = this->Size();  // Byte size of the original string.
    740   if (size < ExternalString::kSize) {
    741     // The string is too small to fit an external String in its place. This can
    742     // only happen for zero length strings.
    743     return false;
    744   }
    745   ASSERT(size >= ExternalString::kSize);
    746   bool is_symbol = this->IsSymbol();
    747   int length = this->length();
    748   int hash_field = this->hash_field();
    749 
    750   // Morph the object to an external string by adjusting the map and
    751   // reinitializing the fields.
    752   this->set_map(Heap::external_ascii_string_map());
    753   ExternalAsciiString* self = ExternalAsciiString::cast(this);
    754   self->set_length(length);
    755   self->set_hash_field(hash_field);
    756   self->set_resource(resource);
    757   // Additionally make the object into an external symbol if the original string
    758   // was a symbol to start with.
    759   if (is_symbol) {
    760     self->Hash();  // Force regeneration of the hash value.
    761     // Now morph this external string into a external symbol.
    762     this->set_map(Heap::external_ascii_symbol_map());
    763   }
    764 
    765   // Fill the remainder of the string with dead wood.
    766   int new_size = this->Size();  // Byte size of the external String object.
    767   Heap::CreateFillerObjectAt(this->address() + new_size, size - new_size);
    768   return true;
    769 }
    770 
    771 
    772 void String::StringShortPrint(StringStream* accumulator) {
    773   int len = length();
    774   if (len > kMaxShortPrintLength) {
    775     accumulator->Add("<Very long string[%u]>", len);
    776     return;
    777   }
    778 
    779   if (!LooksValid()) {
    780     accumulator->Add("<Invalid String>");
    781     return;
    782   }
    783 
    784   StringInputBuffer buf(this);
    785 
    786   bool truncated = false;
    787   if (len > kMaxShortPrintLength) {
    788     len = kMaxShortPrintLength;
    789     truncated = true;
    790   }
    791   bool ascii = true;
    792   for (int i = 0; i < len; i++) {
    793     int c = buf.GetNext();
    794 
    795     if (c < 32 || c >= 127) {
    796       ascii = false;
    797     }
    798   }
    799   buf.Reset(this);
    800   if (ascii) {
    801     accumulator->Add("<String[%u]: ", length());
    802     for (int i = 0; i < len; i++) {
    803       accumulator->Put(buf.GetNext());
    804     }
    805     accumulator->Put('>');
    806   } else {
    807     // Backslash indicates that the string contains control
    808     // characters and that backslashes are therefore escaped.
    809     accumulator->Add("<String[%u]\\: ", length());
    810     for (int i = 0; i < len; i++) {
    811       int c = buf.GetNext();
    812       if (c == '\n') {
    813         accumulator->Add("\\n");
    814       } else if (c == '\r') {
    815         accumulator->Add("\\r");
    816       } else if (c == '\\') {
    817         accumulator->Add("\\\\");
    818       } else if (c < 32 || c > 126) {
    819         accumulator->Add("\\x%02x", c);
    820       } else {
    821         accumulator->Put(c);
    822       }
    823     }
    824     if (truncated) {
    825       accumulator->Put('.');
    826       accumulator->Put('.');
    827       accumulator->Put('.');
    828     }
    829     accumulator->Put('>');
    830   }
    831   return;
    832 }
    833 
    834 
    835 void JSObject::JSObjectShortPrint(StringStream* accumulator) {
    836   switch (map()->instance_type()) {
    837     case JS_ARRAY_TYPE: {
    838       double length = JSArray::cast(this)->length()->Number();
    839       accumulator->Add("<JS array[%u]>", static_cast<uint32_t>(length));
    840       break;
    841     }
    842     case JS_REGEXP_TYPE: {
    843       accumulator->Add("<JS RegExp>");
    844       break;
    845     }
    846     case JS_FUNCTION_TYPE: {
    847       Object* fun_name = JSFunction::cast(this)->shared()->name();
    848       bool printed = false;
    849       if (fun_name->IsString()) {
    850         String* str = String::cast(fun_name);
    851         if (str->length() > 0) {
    852           accumulator->Add("<JS Function ");
    853           accumulator->Put(str);
    854           accumulator->Put('>');
    855           printed = true;
    856         }
    857       }
    858       if (!printed) {
    859         accumulator->Add("<JS Function>");
    860       }
    861       break;
    862     }
    863     // All other JSObjects are rather similar to each other (JSObject,
    864     // JSGlobalProxy, JSGlobalObject, JSUndetectableObject, JSValue).
    865     default: {
    866       Object* constructor = map()->constructor();
    867       bool printed = false;
    868       if (constructor->IsHeapObject() &&
    869           !Heap::Contains(HeapObject::cast(constructor))) {
    870         accumulator->Add("!!!INVALID CONSTRUCTOR!!!");
    871       } else {
    872         bool global_object = IsJSGlobalProxy();
    873         if (constructor->IsJSFunction()) {
    874           if (!Heap::Contains(JSFunction::cast(constructor)->shared())) {
    875             accumulator->Add("!!!INVALID SHARED ON CONSTRUCTOR!!!");
    876           } else {
    877             Object* constructor_name =
    878                 JSFunction::cast(constructor)->shared()->name();
    879             if (constructor_name->IsString()) {
    880               String* str = String::cast(constructor_name);
    881               if (str->length() > 0) {
    882                 bool vowel = AnWord(str);
    883                 accumulator->Add("<%sa%s ",
    884                        global_object ? "Global Object: " : "",
    885                        vowel ? "n" : "");
    886                 accumulator->Put(str);
    887                 accumulator->Put('>');
    888                 printed = true;
    889               }
    890             }
    891           }
    892         }
    893         if (!printed) {
    894           accumulator->Add("<JS %sObject", global_object ? "Global " : "");
    895         }
    896       }
    897       if (IsJSValue()) {
    898         accumulator->Add(" value = ");
    899         JSValue::cast(this)->value()->ShortPrint(accumulator);
    900       }
    901       accumulator->Put('>');
    902       break;
    903     }
    904   }
    905 }
    906 
    907 
    908 void HeapObject::HeapObjectShortPrint(StringStream* accumulator) {
    909   // if (!Heap::InNewSpace(this)) PrintF("*", this);
    910   if (!Heap::Contains(this)) {
    911     accumulator->Add("!!!INVALID POINTER!!!");
    912     return;
    913   }
    914   if (!Heap::Contains(map())) {
    915     accumulator->Add("!!!INVALID MAP!!!");
    916     return;
    917   }
    918 
    919   accumulator->Add("%p ", this);
    920 
    921   if (IsString()) {
    922     String::cast(this)->StringShortPrint(accumulator);
    923     return;
    924   }
    925   if (IsJSObject()) {
    926     JSObject::cast(this)->JSObjectShortPrint(accumulator);
    927     return;
    928   }
    929   switch (map()->instance_type()) {
    930     case MAP_TYPE:
    931       accumulator->Add("<Map>");
    932       break;
    933     case FIXED_ARRAY_TYPE:
    934       accumulator->Add("<FixedArray[%u]>", FixedArray::cast(this)->length());
    935       break;
    936     case BYTE_ARRAY_TYPE:
    937       accumulator->Add("<ByteArray[%u]>", ByteArray::cast(this)->length());
    938       break;
    939     case PIXEL_ARRAY_TYPE:
    940       accumulator->Add("<PixelArray[%u]>", PixelArray::cast(this)->length());
    941       break;
    942     case EXTERNAL_BYTE_ARRAY_TYPE:
    943       accumulator->Add("<ExternalByteArray[%u]>",
    944                        ExternalByteArray::cast(this)->length());
    945       break;
    946     case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
    947       accumulator->Add("<ExternalUnsignedByteArray[%u]>",
    948                        ExternalUnsignedByteArray::cast(this)->length());
    949       break;
    950     case EXTERNAL_SHORT_ARRAY_TYPE:
    951       accumulator->Add("<ExternalShortArray[%u]>",
    952                        ExternalShortArray::cast(this)->length());
    953       break;
    954     case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
    955       accumulator->Add("<ExternalUnsignedShortArray[%u]>",
    956                        ExternalUnsignedShortArray::cast(this)->length());
    957       break;
    958     case EXTERNAL_INT_ARRAY_TYPE:
    959       accumulator->Add("<ExternalIntArray[%u]>",
    960                        ExternalIntArray::cast(this)->length());
    961       break;
    962     case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
    963       accumulator->Add("<ExternalUnsignedIntArray[%u]>",
    964                        ExternalUnsignedIntArray::cast(this)->length());
    965       break;
    966     case EXTERNAL_FLOAT_ARRAY_TYPE:
    967       accumulator->Add("<ExternalFloatArray[%u]>",
    968                        ExternalFloatArray::cast(this)->length());
    969       break;
    970     case SHARED_FUNCTION_INFO_TYPE:
    971       accumulator->Add("<SharedFunctionInfo>");
    972       break;
    973 #define MAKE_STRUCT_CASE(NAME, Name, name) \
    974   case NAME##_TYPE:                        \
    975     accumulator->Put('<');                 \
    976     accumulator->Add(#Name);               \
    977     accumulator->Put('>');                 \
    978     break;
    979   STRUCT_LIST(MAKE_STRUCT_CASE)
    980 #undef MAKE_STRUCT_CASE
    981     case CODE_TYPE:
    982       accumulator->Add("<Code>");
    983       break;
    984     case ODDBALL_TYPE: {
    985       if (IsUndefined())
    986         accumulator->Add("<undefined>");
    987       else if (IsTheHole())
    988         accumulator->Add("<the hole>");
    989       else if (IsNull())
    990         accumulator->Add("<null>");
    991       else if (IsTrue())
    992         accumulator->Add("<true>");
    993       else if (IsFalse())
    994         accumulator->Add("<false>");
    995       else
    996         accumulator->Add("<Odd Oddball>");
    997       break;
    998     }
    999     case HEAP_NUMBER_TYPE:
   1000       accumulator->Add("<Number: ");
   1001       HeapNumber::cast(this)->HeapNumberPrint(accumulator);
   1002       accumulator->Put('>');
   1003       break;
   1004     case PROXY_TYPE:
   1005       accumulator->Add("<Proxy>");
   1006       break;
   1007     case JS_GLOBAL_PROPERTY_CELL_TYPE:
   1008       accumulator->Add("Cell for ");
   1009       JSGlobalPropertyCell::cast(this)->value()->ShortPrint(accumulator);
   1010       break;
   1011     default:
   1012       accumulator->Add("<Other heap object (%d)>", map()->instance_type());
   1013       break;
   1014   }
   1015 }
   1016 
   1017 
   1018 int HeapObject::SlowSizeFromMap(Map* map) {
   1019   // Avoid calling functions such as FixedArray::cast during GC, which
   1020   // read map pointer of this object again.
   1021   InstanceType instance_type = map->instance_type();
   1022   uint32_t type = static_cast<uint32_t>(instance_type);
   1023 
   1024   if (instance_type < FIRST_NONSTRING_TYPE
   1025       && (StringShape(instance_type).IsSequential())) {
   1026     if ((type & kStringEncodingMask) == kAsciiStringTag) {
   1027       SeqAsciiString* seq_ascii_this = reinterpret_cast<SeqAsciiString*>(this);
   1028       return seq_ascii_this->SeqAsciiStringSize(instance_type);
   1029     } else {
   1030       SeqTwoByteString* self = reinterpret_cast<SeqTwoByteString*>(this);
   1031       return self->SeqTwoByteStringSize(instance_type);
   1032     }
   1033   }
   1034 
   1035   switch (instance_type) {
   1036     case FIXED_ARRAY_TYPE:
   1037       return reinterpret_cast<FixedArray*>(this)->FixedArraySize();
   1038     case BYTE_ARRAY_TYPE:
   1039       return reinterpret_cast<ByteArray*>(this)->ByteArraySize();
   1040     case CODE_TYPE:
   1041       return reinterpret_cast<Code*>(this)->CodeSize();
   1042     case MAP_TYPE:
   1043       return Map::kSize;
   1044     default:
   1045       return map->instance_size();
   1046   }
   1047 }
   1048 
   1049 
   1050 void HeapObject::Iterate(ObjectVisitor* v) {
   1051   // Handle header
   1052   IteratePointer(v, kMapOffset);
   1053   // Handle object body
   1054   Map* m = map();
   1055   IterateBody(m->instance_type(), SizeFromMap(m), v);
   1056 }
   1057 
   1058 
   1059 void HeapObject::IterateBody(InstanceType type, int object_size,
   1060                              ObjectVisitor* v) {
   1061   // Avoiding <Type>::cast(this) because it accesses the map pointer field.
   1062   // During GC, the map pointer field is encoded.
   1063   if (type < FIRST_NONSTRING_TYPE) {
   1064     switch (type & kStringRepresentationMask) {
   1065       case kSeqStringTag:
   1066         break;
   1067       case kConsStringTag:
   1068         reinterpret_cast<ConsString*>(this)->ConsStringIterateBody(v);
   1069         break;
   1070       case kExternalStringTag:
   1071         if ((type & kStringEncodingMask) == kAsciiStringTag) {
   1072           reinterpret_cast<ExternalAsciiString*>(this)->
   1073               ExternalAsciiStringIterateBody(v);
   1074         } else {
   1075           reinterpret_cast<ExternalTwoByteString*>(this)->
   1076               ExternalTwoByteStringIterateBody(v);
   1077         }
   1078         break;
   1079     }
   1080     return;
   1081   }
   1082 
   1083   switch (type) {
   1084     case FIXED_ARRAY_TYPE:
   1085       reinterpret_cast<FixedArray*>(this)->FixedArrayIterateBody(v);
   1086       break;
   1087     case JS_OBJECT_TYPE:
   1088     case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
   1089     case JS_VALUE_TYPE:
   1090     case JS_ARRAY_TYPE:
   1091     case JS_REGEXP_TYPE:
   1092     case JS_FUNCTION_TYPE:
   1093     case JS_GLOBAL_PROXY_TYPE:
   1094     case JS_GLOBAL_OBJECT_TYPE:
   1095     case JS_BUILTINS_OBJECT_TYPE:
   1096       reinterpret_cast<JSObject*>(this)->JSObjectIterateBody(object_size, v);
   1097       break;
   1098     case ODDBALL_TYPE:
   1099       reinterpret_cast<Oddball*>(this)->OddballIterateBody(v);
   1100       break;
   1101     case PROXY_TYPE:
   1102       reinterpret_cast<Proxy*>(this)->ProxyIterateBody(v);
   1103       break;
   1104     case MAP_TYPE:
   1105       reinterpret_cast<Map*>(this)->MapIterateBody(v);
   1106       break;
   1107     case CODE_TYPE:
   1108       reinterpret_cast<Code*>(this)->CodeIterateBody(v);
   1109       break;
   1110     case JS_GLOBAL_PROPERTY_CELL_TYPE:
   1111       reinterpret_cast<JSGlobalPropertyCell*>(this)
   1112           ->JSGlobalPropertyCellIterateBody(v);
   1113       break;
   1114     case HEAP_NUMBER_TYPE:
   1115     case FILLER_TYPE:
   1116     case BYTE_ARRAY_TYPE:
   1117     case PIXEL_ARRAY_TYPE:
   1118     case EXTERNAL_BYTE_ARRAY_TYPE:
   1119     case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
   1120     case EXTERNAL_SHORT_ARRAY_TYPE:
   1121     case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
   1122     case EXTERNAL_INT_ARRAY_TYPE:
   1123     case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
   1124     case EXTERNAL_FLOAT_ARRAY_TYPE:
   1125       break;
   1126     case SHARED_FUNCTION_INFO_TYPE: {
   1127       SharedFunctionInfo* shared = reinterpret_cast<SharedFunctionInfo*>(this);
   1128       shared->SharedFunctionInfoIterateBody(v);
   1129       break;
   1130     }
   1131 #define MAKE_STRUCT_CASE(NAME, Name, name) \
   1132         case NAME##_TYPE:
   1133       STRUCT_LIST(MAKE_STRUCT_CASE)
   1134 #undef MAKE_STRUCT_CASE
   1135       IterateStructBody(object_size, v);
   1136       break;
   1137     default:
   1138       PrintF("Unknown type: %d\n", type);
   1139       UNREACHABLE();
   1140   }
   1141 }
   1142 
   1143 
   1144 void HeapObject::IterateStructBody(int object_size, ObjectVisitor* v) {
   1145   IteratePointers(v, HeapObject::kHeaderSize, object_size);
   1146 }
   1147 
   1148 
   1149 Object* HeapNumber::HeapNumberToBoolean() {
   1150   // NaN, +0, and -0 should return the false object
   1151   switch (fpclassify(value())) {
   1152     case FP_NAN:  // fall through
   1153     case FP_ZERO: return Heap::false_value();
   1154     default: return Heap::true_value();
   1155   }
   1156 }
   1157 
   1158 
   1159 void HeapNumber::HeapNumberPrint() {
   1160   PrintF("%.16g", Number());
   1161 }
   1162 
   1163 
   1164 void HeapNumber::HeapNumberPrint(StringStream* accumulator) {
   1165   // The Windows version of vsnprintf can allocate when printing a %g string
   1166   // into a buffer that may not be big enough.  We don't want random memory
   1167   // allocation when producing post-crash stack traces, so we print into a
   1168   // buffer that is plenty big enough for any floating point number, then
   1169   // print that using vsnprintf (which may truncate but never allocate if
   1170   // there is no more space in the buffer).
   1171   EmbeddedVector<char, 100> buffer;
   1172   OS::SNPrintF(buffer, "%.16g", Number());
   1173   accumulator->Add("%s", buffer.start());
   1174 }
   1175 
   1176 
   1177 String* JSObject::class_name() {
   1178   if (IsJSFunction()) {
   1179     return Heap::function_class_symbol();
   1180   }
   1181   if (map()->constructor()->IsJSFunction()) {
   1182     JSFunction* constructor = JSFunction::cast(map()->constructor());
   1183     return String::cast(constructor->shared()->instance_class_name());
   1184   }
   1185   // If the constructor is not present, return "Object".
   1186   return Heap::Object_symbol();
   1187 }
   1188 
   1189 
   1190 String* JSObject::constructor_name() {
   1191   if (IsJSFunction()) {
   1192     return JSFunction::cast(this)->IsBoilerplate() ?
   1193       Heap::function_class_symbol() : Heap::closure_symbol();
   1194   }
   1195   if (map()->constructor()->IsJSFunction()) {
   1196     JSFunction* constructor = JSFunction::cast(map()->constructor());
   1197     String* name = String::cast(constructor->shared()->name());
   1198     return name->length() > 0 ? name : constructor->shared()->inferred_name();
   1199   }
   1200   // If the constructor is not present, return "Object".
   1201   return Heap::Object_symbol();
   1202 }
   1203 
   1204 
   1205 void JSObject::JSObjectIterateBody(int object_size, ObjectVisitor* v) {
   1206   // Iterate over all fields in the body. Assumes all are Object*.
   1207   IteratePointers(v, kPropertiesOffset, object_size);
   1208 }
   1209 
   1210 
   1211 Object* JSObject::AddFastPropertyUsingMap(Map* new_map,
   1212                                           String* name,
   1213                                           Object* value) {
   1214   int index = new_map->PropertyIndexFor(name);
   1215   if (map()->unused_property_fields() == 0) {
   1216     ASSERT(map()->unused_property_fields() == 0);
   1217     int new_unused = new_map->unused_property_fields();
   1218     Object* values =
   1219         properties()->CopySize(properties()->length() + new_unused + 1);
   1220     if (values->IsFailure()) return values;
   1221     set_properties(FixedArray::cast(values));
   1222   }
   1223   set_map(new_map);
   1224   return FastPropertyAtPut(index, value);
   1225 }
   1226 
   1227 
   1228 Object* JSObject::AddFastProperty(String* name,
   1229                                   Object* value,
   1230                                   PropertyAttributes attributes) {
   1231   // Normalize the object if the name is an actual string (not the
   1232   // hidden symbols) and is not a real identifier.
   1233   StringInputBuffer buffer(name);
   1234   if (!Scanner::IsIdentifier(&buffer) && name != Heap::hidden_symbol()) {
   1235     Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
   1236     if (obj->IsFailure()) return obj;
   1237     return AddSlowProperty(name, value, attributes);
   1238   }
   1239 
   1240   DescriptorArray* old_descriptors = map()->instance_descriptors();
   1241   // Compute the new index for new field.
   1242   int index = map()->NextFreePropertyIndex();
   1243 
   1244   // Allocate new instance descriptors with (name, index) added
   1245   FieldDescriptor new_field(name, index, attributes);
   1246   Object* new_descriptors =
   1247       old_descriptors->CopyInsert(&new_field, REMOVE_TRANSITIONS);
   1248   if (new_descriptors->IsFailure()) return new_descriptors;
   1249 
   1250   // Only allow map transition if the object's map is NOT equal to the
   1251   // global object_function's map and there is not a transition for name.
   1252   bool allow_map_transition =
   1253         !old_descriptors->Contains(name) &&
   1254         (Top::context()->global_context()->object_function()->map() != map());
   1255 
   1256   ASSERT(index < map()->inobject_properties() ||
   1257          (index - map()->inobject_properties()) < properties()->length() ||
   1258          map()->unused_property_fields() == 0);
   1259   // Allocate a new map for the object.
   1260   Object* r = map()->CopyDropDescriptors();
   1261   if (r->IsFailure()) return r;
   1262   Map* new_map = Map::cast(r);
   1263   if (allow_map_transition) {
   1264     // Allocate new instance descriptors for the old map with map transition.
   1265     MapTransitionDescriptor d(name, Map::cast(new_map), attributes);
   1266     Object* r = old_descriptors->CopyInsert(&d, KEEP_TRANSITIONS);
   1267     if (r->IsFailure()) return r;
   1268     old_descriptors = DescriptorArray::cast(r);
   1269   }
   1270 
   1271   if (map()->unused_property_fields() == 0) {
   1272     if (properties()->length() > kMaxFastProperties) {
   1273       Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
   1274       if (obj->IsFailure()) return obj;
   1275       return AddSlowProperty(name, value, attributes);
   1276     }
   1277     // Make room for the new value
   1278     Object* values =
   1279         properties()->CopySize(properties()->length() + kFieldsAdded);
   1280     if (values->IsFailure()) return values;
   1281     set_properties(FixedArray::cast(values));
   1282     new_map->set_unused_property_fields(kFieldsAdded - 1);
   1283   } else {
   1284     new_map->set_unused_property_fields(map()->unused_property_fields() - 1);
   1285   }
   1286   // We have now allocated all the necessary objects.
   1287   // All the changes can be applied at once, so they are atomic.
   1288   map()->set_instance_descriptors(old_descriptors);
   1289   new_map->set_instance_descriptors(DescriptorArray::cast(new_descriptors));
   1290   set_map(new_map);
   1291   return FastPropertyAtPut(index, value);
   1292 }
   1293 
   1294 
   1295 Object* JSObject::AddConstantFunctionProperty(String* name,
   1296                                               JSFunction* function,
   1297                                               PropertyAttributes attributes) {
   1298   ASSERT(!Heap::InNewSpace(function));
   1299 
   1300   // Allocate new instance descriptors with (name, function) added
   1301   ConstantFunctionDescriptor d(name, function, attributes);
   1302   Object* new_descriptors =
   1303       map()->instance_descriptors()->CopyInsert(&d, REMOVE_TRANSITIONS);
   1304   if (new_descriptors->IsFailure()) return new_descriptors;
   1305 
   1306   // Allocate a new map for the object.
   1307   Object* new_map = map()->CopyDropDescriptors();
   1308   if (new_map->IsFailure()) return new_map;
   1309 
   1310   DescriptorArray* descriptors = DescriptorArray::cast(new_descriptors);
   1311   Map::cast(new_map)->set_instance_descriptors(descriptors);
   1312   Map* old_map = map();
   1313   set_map(Map::cast(new_map));
   1314 
   1315   // If the old map is the global object map (from new Object()),
   1316   // then transitions are not added to it, so we are done.
   1317   if (old_map == Top::context()->global_context()->object_function()->map()) {
   1318     return function;
   1319   }
   1320 
   1321   // Do not add CONSTANT_TRANSITIONS to global objects
   1322   if (IsGlobalObject()) {
   1323     return function;
   1324   }
   1325 
   1326   // Add a CONSTANT_TRANSITION descriptor to the old map,
   1327   // so future assignments to this property on other objects
   1328   // of the same type will create a normal field, not a constant function.
   1329   // Don't do this for special properties, with non-trival attributes.
   1330   if (attributes != NONE) {
   1331     return function;
   1332   }
   1333   ConstTransitionDescriptor mark(name);
   1334   new_descriptors =
   1335       old_map->instance_descriptors()->CopyInsert(&mark, KEEP_TRANSITIONS);
   1336   if (new_descriptors->IsFailure()) {
   1337     return function;  // We have accomplished the main goal, so return success.
   1338   }
   1339   old_map->set_instance_descriptors(DescriptorArray::cast(new_descriptors));
   1340 
   1341   return function;
   1342 }
   1343 
   1344 
   1345 // Add property in slow mode
   1346 Object* JSObject::AddSlowProperty(String* name,
   1347                                   Object* value,
   1348                                   PropertyAttributes attributes) {
   1349   ASSERT(!HasFastProperties());
   1350   StringDictionary* dict = property_dictionary();
   1351   Object* store_value = value;
   1352   if (IsGlobalObject()) {
   1353     // In case name is an orphaned property reuse the cell.
   1354     int entry = dict->FindEntry(name);
   1355     if (entry != StringDictionary::kNotFound) {
   1356       store_value = dict->ValueAt(entry);
   1357       JSGlobalPropertyCell::cast(store_value)->set_value(value);
   1358       // Assign an enumeration index to the property and update
   1359       // SetNextEnumerationIndex.
   1360       int index = dict->NextEnumerationIndex();
   1361       PropertyDetails details = PropertyDetails(attributes, NORMAL, index);
   1362       dict->SetNextEnumerationIndex(index + 1);
   1363       dict->SetEntry(entry, name, store_value, details);
   1364       return value;
   1365     }
   1366     store_value = Heap::AllocateJSGlobalPropertyCell(value);
   1367     if (store_value->IsFailure()) return store_value;
   1368     JSGlobalPropertyCell::cast(store_value)->set_value(value);
   1369   }
   1370   PropertyDetails details = PropertyDetails(attributes, NORMAL);
   1371   Object* result = dict->Add(name, store_value, details);
   1372   if (result->IsFailure()) return result;
   1373   if (dict != result) set_properties(StringDictionary::cast(result));
   1374   return value;
   1375 }
   1376 
   1377 
   1378 Object* JSObject::AddProperty(String* name,
   1379                               Object* value,
   1380                               PropertyAttributes attributes) {
   1381   ASSERT(!IsJSGlobalProxy());
   1382   if (HasFastProperties()) {
   1383     // Ensure the descriptor array does not get too big.
   1384     if (map()->instance_descriptors()->number_of_descriptors() <
   1385         DescriptorArray::kMaxNumberOfDescriptors) {
   1386       if (value->IsJSFunction() && !Heap::InNewSpace(value)) {
   1387         return AddConstantFunctionProperty(name,
   1388                                            JSFunction::cast(value),
   1389                                            attributes);
   1390       } else {
   1391         return AddFastProperty(name, value, attributes);
   1392       }
   1393     } else {
   1394       // Normalize the object to prevent very large instance descriptors.
   1395       // This eliminates unwanted N^2 allocation and lookup behavior.
   1396       Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
   1397       if (obj->IsFailure()) return obj;
   1398     }
   1399   }
   1400   return AddSlowProperty(name, value, attributes);
   1401 }
   1402 
   1403 
   1404 Object* JSObject::SetPropertyPostInterceptor(String* name,
   1405                                              Object* value,
   1406                                              PropertyAttributes attributes) {
   1407   // Check local property, ignore interceptor.
   1408   LookupResult result;
   1409   LocalLookupRealNamedProperty(name, &result);
   1410   if (result.IsFound()) {
   1411     // An existing property, a map transition or a null descriptor was
   1412     // found.  Use set property to handle all these cases.
   1413     return SetProperty(&result, name, value, attributes);
   1414   }
   1415   // Add a new real property.
   1416   return AddProperty(name, value, attributes);
   1417 }
   1418 
   1419 
   1420 Object* JSObject::ReplaceSlowProperty(String* name,
   1421                                       Object* value,
   1422                                       PropertyAttributes attributes) {
   1423   StringDictionary* dictionary = property_dictionary();
   1424   int old_index = dictionary->FindEntry(name);
   1425   int new_enumeration_index = 0;  // 0 means "Use the next available index."
   1426   if (old_index != -1) {
   1427     // All calls to ReplaceSlowProperty have had all transitions removed.
   1428     ASSERT(!dictionary->DetailsAt(old_index).IsTransition());
   1429     new_enumeration_index = dictionary->DetailsAt(old_index).index();
   1430   }
   1431 
   1432   PropertyDetails new_details(attributes, NORMAL, new_enumeration_index);
   1433   return SetNormalizedProperty(name, value, new_details);
   1434 }
   1435 
   1436 
   1437 Object* JSObject::ConvertDescriptorToFieldAndMapTransition(
   1438     String* name,
   1439     Object* new_value,
   1440     PropertyAttributes attributes) {
   1441   Map* old_map = map();
   1442   Object* result = ConvertDescriptorToField(name, new_value, attributes);
   1443   if (result->IsFailure()) return result;
   1444   // If we get to this point we have succeeded - do not return failure
   1445   // after this point.  Later stuff is optional.
   1446   if (!HasFastProperties()) {
   1447     return result;
   1448   }
   1449   // Do not add transitions to the map of "new Object()".
   1450   if (map() == Top::context()->global_context()->object_function()->map()) {
   1451     return result;
   1452   }
   1453 
   1454   MapTransitionDescriptor transition(name,
   1455                                      map(),
   1456                                      attributes);
   1457   Object* new_descriptors =
   1458       old_map->instance_descriptors()->
   1459           CopyInsert(&transition, KEEP_TRANSITIONS);
   1460   if (new_descriptors->IsFailure()) return result;  // Yes, return _result_.
   1461   old_map->set_instance_descriptors(DescriptorArray::cast(new_descriptors));
   1462   return result;
   1463 }
   1464 
   1465 
   1466 Object* JSObject::ConvertDescriptorToField(String* name,
   1467                                            Object* new_value,
   1468                                            PropertyAttributes attributes) {
   1469   if (map()->unused_property_fields() == 0 &&
   1470       properties()->length() > kMaxFastProperties) {
   1471     Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
   1472     if (obj->IsFailure()) return obj;
   1473     return ReplaceSlowProperty(name, new_value, attributes);
   1474   }
   1475 
   1476   int index = map()->NextFreePropertyIndex();
   1477   FieldDescriptor new_field(name, index, attributes);
   1478   // Make a new DescriptorArray replacing an entry with FieldDescriptor.
   1479   Object* descriptors_unchecked = map()->instance_descriptors()->
   1480       CopyInsert(&new_field, REMOVE_TRANSITIONS);
   1481   if (descriptors_unchecked->IsFailure()) return descriptors_unchecked;
   1482   DescriptorArray* new_descriptors =
   1483       DescriptorArray::cast(descriptors_unchecked);
   1484 
   1485   // Make a new map for the object.
   1486   Object* new_map_unchecked = map()->CopyDropDescriptors();
   1487   if (new_map_unchecked->IsFailure()) return new_map_unchecked;
   1488   Map* new_map = Map::cast(new_map_unchecked);
   1489   new_map->set_instance_descriptors(new_descriptors);
   1490 
   1491   // Make new properties array if necessary.
   1492   FixedArray* new_properties = 0;  // Will always be NULL or a valid pointer.
   1493   int new_unused_property_fields = map()->unused_property_fields() - 1;
   1494   if (map()->unused_property_fields() == 0) {
   1495      new_unused_property_fields = kFieldsAdded - 1;
   1496      Object* new_properties_unchecked =
   1497         properties()->CopySize(properties()->length() + kFieldsAdded);
   1498     if (new_properties_unchecked->IsFailure()) return new_properties_unchecked;
   1499     new_properties = FixedArray::cast(new_properties_unchecked);
   1500   }
   1501 
   1502   // Update pointers to commit changes.
   1503   // Object points to the new map.
   1504   new_map->set_unused_property_fields(new_unused_property_fields);
   1505   set_map(new_map);
   1506   if (new_properties) {
   1507     set_properties(FixedArray::cast(new_properties));
   1508   }
   1509   return FastPropertyAtPut(index, new_value);
   1510 }
   1511 
   1512 
   1513 
   1514 Object* JSObject::SetPropertyWithInterceptor(String* name,
   1515                                              Object* value,
   1516                                              PropertyAttributes attributes) {
   1517   HandleScope scope;
   1518   Handle<JSObject> this_handle(this);
   1519   Handle<String> name_handle(name);
   1520   Handle<Object> value_handle(value);
   1521   Handle<InterceptorInfo> interceptor(GetNamedInterceptor());
   1522   if (!interceptor->setter()->IsUndefined()) {
   1523     LOG(ApiNamedPropertyAccess("interceptor-named-set", this, name));
   1524     CustomArguments args(interceptor->data(), this, this);
   1525     v8::AccessorInfo info(args.end());
   1526     v8::NamedPropertySetter setter =
   1527         v8::ToCData<v8::NamedPropertySetter>(interceptor->setter());
   1528     v8::Handle<v8::Value> result;
   1529     {
   1530       // Leaving JavaScript.
   1531       VMState state(EXTERNAL);
   1532       Handle<Object> value_unhole(value->IsTheHole() ?
   1533                                   Heap::undefined_value() :
   1534                                   value);
   1535       result = setter(v8::Utils::ToLocal(name_handle),
   1536                       v8::Utils::ToLocal(value_unhole),
   1537                       info);
   1538     }
   1539     RETURN_IF_SCHEDULED_EXCEPTION();
   1540     if (!result.IsEmpty()) return *value_handle;
   1541   }
   1542   Object* raw_result = this_handle->SetPropertyPostInterceptor(*name_handle,
   1543                                                                *value_handle,
   1544                                                                attributes);
   1545   RETURN_IF_SCHEDULED_EXCEPTION();
   1546   return raw_result;
   1547 }
   1548 
   1549 
   1550 Object* JSObject::SetProperty(String* name,
   1551                               Object* value,
   1552                               PropertyAttributes attributes) {
   1553   LookupResult result;
   1554   LocalLookup(name, &result);
   1555   return SetProperty(&result, name, value, attributes);
   1556 }
   1557 
   1558 
   1559 Object* JSObject::SetPropertyWithCallback(Object* structure,
   1560                                           String* name,
   1561                                           Object* value,
   1562                                           JSObject* holder) {
   1563   HandleScope scope;
   1564 
   1565   // We should never get here to initialize a const with the hole
   1566   // value since a const declaration would conflict with the setter.
   1567   ASSERT(!value->IsTheHole());
   1568   Handle<Object> value_handle(value);
   1569 
   1570   // To accommodate both the old and the new api we switch on the
   1571   // data structure used to store the callbacks.  Eventually proxy
   1572   // callbacks should be phased out.
   1573   if (structure->IsProxy()) {
   1574     AccessorDescriptor* callback =
   1575         reinterpret_cast<AccessorDescriptor*>(Proxy::cast(structure)->proxy());
   1576     Object* obj = (callback->setter)(this,  value, callback->data);
   1577     RETURN_IF_SCHEDULED_EXCEPTION();
   1578     if (obj->IsFailure()) return obj;
   1579     return *value_handle;
   1580   }
   1581 
   1582   if (structure->IsAccessorInfo()) {
   1583     // api style callbacks
   1584     AccessorInfo* data = AccessorInfo::cast(structure);
   1585     Object* call_obj = data->setter();
   1586     v8::AccessorSetter call_fun = v8::ToCData<v8::AccessorSetter>(call_obj);
   1587     if (call_fun == NULL) return value;
   1588     Handle<String> key(name);
   1589     LOG(ApiNamedPropertyAccess("store", this, name));
   1590     CustomArguments args(data->data(), this, JSObject::cast(holder));
   1591     v8::AccessorInfo info(args.end());
   1592     {
   1593       // Leaving JavaScript.
   1594       VMState state(EXTERNAL);
   1595       call_fun(v8::Utils::ToLocal(key),
   1596                v8::Utils::ToLocal(value_handle),
   1597                info);
   1598     }
   1599     RETURN_IF_SCHEDULED_EXCEPTION();
   1600     return *value_handle;
   1601   }
   1602 
   1603   if (structure->IsFixedArray()) {
   1604     Object* setter = FixedArray::cast(structure)->get(kSetterIndex);
   1605     if (setter->IsJSFunction()) {
   1606      return SetPropertyWithDefinedSetter(JSFunction::cast(setter), value);
   1607     } else {
   1608       Handle<String> key(name);
   1609       Handle<Object> holder_handle(holder);
   1610       Handle<Object> args[2] = { key, holder_handle };
   1611       return Top::Throw(*Factory::NewTypeError("no_setter_in_callback",
   1612                                                HandleVector(args, 2)));
   1613     }
   1614   }
   1615 
   1616   UNREACHABLE();
   1617   return 0;
   1618 }
   1619 
   1620 
   1621 Object* JSObject::SetPropertyWithDefinedSetter(JSFunction* setter,
   1622                                                Object* value) {
   1623   Handle<Object> value_handle(value);
   1624   Handle<JSFunction> fun(JSFunction::cast(setter));
   1625   Handle<JSObject> self(this);
   1626 #ifdef ENABLE_DEBUGGER_SUPPORT
   1627   // Handle stepping into a setter if step into is active.
   1628   if (Debug::StepInActive()) {
   1629     Debug::HandleStepIn(fun, Handle<Object>::null(), 0, false);
   1630   }
   1631 #endif
   1632   bool has_pending_exception;
   1633   Object** argv[] = { value_handle.location() };
   1634   Execution::Call(fun, self, 1, argv, &has_pending_exception);
   1635   // Check for pending exception and return the result.
   1636   if (has_pending_exception) return Failure::Exception();
   1637   return *value_handle;
   1638 }
   1639 
   1640 
   1641 void JSObject::LookupCallbackSetterInPrototypes(String* name,
   1642                                                 LookupResult* result) {
   1643   for (Object* pt = GetPrototype();
   1644        pt != Heap::null_value();
   1645        pt = pt->GetPrototype()) {
   1646     JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result);
   1647     if (result->IsProperty()) {
   1648       if (result->IsReadOnly()) {
   1649         result->NotFound();
   1650         return;
   1651       }
   1652       if (result->type() == CALLBACKS) {
   1653         return;
   1654       }
   1655     }
   1656   }
   1657   result->NotFound();
   1658 }
   1659 
   1660 
   1661 Object* JSObject::LookupCallbackSetterInPrototypes(uint32_t index) {
   1662   for (Object* pt = GetPrototype();
   1663        pt != Heap::null_value();
   1664        pt = pt->GetPrototype()) {
   1665     if (!JSObject::cast(pt)->HasDictionaryElements()) {
   1666         continue;
   1667     }
   1668     NumberDictionary* dictionary = JSObject::cast(pt)->element_dictionary();
   1669     int entry = dictionary->FindEntry(index);
   1670     if (entry != NumberDictionary::kNotFound) {
   1671       Object* element = dictionary->ValueAt(entry);
   1672       PropertyDetails details = dictionary->DetailsAt(entry);
   1673       if (details.type() == CALLBACKS) {
   1674         // Only accessors allowed as elements.
   1675         return FixedArray::cast(element)->get(kSetterIndex);
   1676       }
   1677     }
   1678   }
   1679   return Heap::undefined_value();
   1680 }
   1681 
   1682 
   1683 void JSObject::LookupInDescriptor(String* name, LookupResult* result) {
   1684   DescriptorArray* descriptors = map()->instance_descriptors();
   1685   int number = DescriptorLookupCache::Lookup(descriptors, name);
   1686   if (number == DescriptorLookupCache::kAbsent) {
   1687     number = descriptors->Search(name);
   1688     DescriptorLookupCache::Update(descriptors, name, number);
   1689   }
   1690   if (number != DescriptorArray::kNotFound) {
   1691     result->DescriptorResult(this, descriptors->GetDetails(number), number);
   1692   } else {
   1693     result->NotFound();
   1694   }
   1695 }
   1696 
   1697 
   1698 void JSObject::LocalLookupRealNamedProperty(String* name,
   1699                                             LookupResult* result) {
   1700   if (IsJSGlobalProxy()) {
   1701     Object* proto = GetPrototype();
   1702     if (proto->IsNull()) return result->NotFound();
   1703     ASSERT(proto->IsJSGlobalObject());
   1704     return JSObject::cast(proto)->LocalLookupRealNamedProperty(name, result);
   1705   }
   1706 
   1707   if (HasFastProperties()) {
   1708     LookupInDescriptor(name, result);
   1709     if (result->IsFound()) {
   1710       // A property, a map transition or a null descriptor was found.
   1711       // We return all of these result types because
   1712       // LocalLookupRealNamedProperty is used when setting properties
   1713       // where map transitions and null descriptors are handled.
   1714       ASSERT(result->holder() == this && result->type() != NORMAL);
   1715       // Disallow caching for uninitialized constants. These can only
   1716       // occur as fields.
   1717       if (result->IsReadOnly() && result->type() == FIELD &&
   1718           FastPropertyAt(result->GetFieldIndex())->IsTheHole()) {
   1719         result->DisallowCaching();
   1720       }
   1721       return;
   1722     }
   1723   } else {
   1724     int entry = property_dictionary()->FindEntry(name);
   1725     if (entry != StringDictionary::kNotFound) {
   1726       Object* value = property_dictionary()->ValueAt(entry);
   1727       if (IsGlobalObject()) {
   1728         PropertyDetails d = property_dictionary()->DetailsAt(entry);
   1729         if (d.IsDeleted()) {
   1730           result->NotFound();
   1731           return;
   1732         }
   1733         value = JSGlobalPropertyCell::cast(value)->value();
   1734       }
   1735       // Make sure to disallow caching for uninitialized constants
   1736       // found in the dictionary-mode objects.
   1737       if (value->IsTheHole()) result->DisallowCaching();
   1738       result->DictionaryResult(this, entry);
   1739       return;
   1740     }
   1741     // Slow case object skipped during lookup. Do not use inline caching.
   1742     if (!IsGlobalObject()) result->DisallowCaching();
   1743   }
   1744   result->NotFound();
   1745 }
   1746 
   1747 
   1748 void JSObject::LookupRealNamedProperty(String* name, LookupResult* result) {
   1749   LocalLookupRealNamedProperty(name, result);
   1750   if (result->IsProperty()) return;
   1751 
   1752   LookupRealNamedPropertyInPrototypes(name, result);
   1753 }
   1754 
   1755 
   1756 void JSObject::LookupRealNamedPropertyInPrototypes(String* name,
   1757                                                    LookupResult* result) {
   1758   for (Object* pt = GetPrototype();
   1759        pt != Heap::null_value();
   1760        pt = JSObject::cast(pt)->GetPrototype()) {
   1761     JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result);
   1762     if (result->IsProperty() && (result->type() != INTERCEPTOR)) return;
   1763   }
   1764   result->NotFound();
   1765 }
   1766 
   1767 
   1768 // We only need to deal with CALLBACKS and INTERCEPTORS
   1769 Object* JSObject::SetPropertyWithFailedAccessCheck(LookupResult* result,
   1770                                                    String* name,
   1771                                                    Object* value) {
   1772   if (!result->IsProperty()) {
   1773     LookupCallbackSetterInPrototypes(name, result);
   1774   }
   1775 
   1776   if (result->IsProperty()) {
   1777     if (!result->IsReadOnly()) {
   1778       switch (result->type()) {
   1779         case CALLBACKS: {
   1780           Object* obj = result->GetCallbackObject();
   1781           if (obj->IsAccessorInfo()) {
   1782             AccessorInfo* info = AccessorInfo::cast(obj);
   1783             if (info->all_can_write()) {
   1784               return SetPropertyWithCallback(result->GetCallbackObject(),
   1785                                              name,
   1786                                              value,
   1787                                              result->holder());
   1788             }
   1789           }
   1790           break;
   1791         }
   1792         case INTERCEPTOR: {
   1793           // Try lookup real named properties. Note that only property can be
   1794           // set is callbacks marked as ALL_CAN_WRITE on the prototype chain.
   1795           LookupResult r;
   1796           LookupRealNamedProperty(name, &r);
   1797           if (r.IsProperty()) {
   1798             return SetPropertyWithFailedAccessCheck(&r, name, value);
   1799           }
   1800           break;
   1801         }
   1802         default: {
   1803           break;
   1804         }
   1805       }
   1806     }
   1807   }
   1808 
   1809   Top::ReportFailedAccessCheck(this, v8::ACCESS_SET);
   1810   return value;
   1811 }
   1812 
   1813 
   1814 Object* JSObject::SetProperty(LookupResult* result,
   1815                               String* name,
   1816                               Object* value,
   1817                               PropertyAttributes attributes) {
   1818   // Make sure that the top context does not change when doing callbacks or
   1819   // interceptor calls.
   1820   AssertNoContextChange ncc;
   1821 
   1822   // Optimization for 2-byte strings often used as keys in a decompression
   1823   // dictionary.  We make these short keys into symbols to avoid constantly
   1824   // reallocating them.
   1825   if (!name->IsSymbol() && name->length() <= 2) {
   1826     Object* symbol_version = Heap::LookupSymbol(name);
   1827     if (!symbol_version->IsFailure()) name = String::cast(symbol_version);
   1828   }
   1829 
   1830   // Check access rights if needed.
   1831   if (IsAccessCheckNeeded()
   1832       && !Top::MayNamedAccess(this, name, v8::ACCESS_SET)) {
   1833     return SetPropertyWithFailedAccessCheck(result, name, value);
   1834   }
   1835 
   1836   if (IsJSGlobalProxy()) {
   1837     Object* proto = GetPrototype();
   1838     if (proto->IsNull()) return value;
   1839     ASSERT(proto->IsJSGlobalObject());
   1840     return JSObject::cast(proto)->SetProperty(result, name, value, attributes);
   1841   }
   1842 
   1843   if (!result->IsProperty() && !IsJSContextExtensionObject()) {
   1844     // We could not find a local property so let's check whether there is an
   1845     // accessor that wants to handle the property.
   1846     LookupResult accessor_result;
   1847     LookupCallbackSetterInPrototypes(name, &accessor_result);
   1848     if (accessor_result.IsProperty()) {
   1849       return SetPropertyWithCallback(accessor_result.GetCallbackObject(),
   1850                                      name,
   1851                                      value,
   1852                                      accessor_result.holder());
   1853     }
   1854   }
   1855   if (!result->IsFound()) {
   1856     // Neither properties nor transitions found.
   1857     return AddProperty(name, value, attributes);
   1858   }
   1859   if (result->IsReadOnly() && result->IsProperty()) return value;
   1860   // This is a real property that is not read-only, or it is a
   1861   // transition or null descriptor and there are no setters in the prototypes.
   1862   switch (result->type()) {
   1863     case NORMAL:
   1864       return SetNormalizedProperty(result, value);
   1865     case FIELD:
   1866       return FastPropertyAtPut(result->GetFieldIndex(), value);
   1867     case MAP_TRANSITION:
   1868       if (attributes == result->GetAttributes()) {
   1869         // Only use map transition if the attributes match.
   1870         return AddFastPropertyUsingMap(result->GetTransitionMap(),
   1871                                        name,
   1872                                        value);
   1873       }
   1874       return ConvertDescriptorToField(name, value, attributes);
   1875     case CONSTANT_FUNCTION:
   1876       // Only replace the function if necessary.
   1877       if (value == result->GetConstantFunction()) return value;
   1878       // Preserve the attributes of this existing property.
   1879       attributes = result->GetAttributes();
   1880       return ConvertDescriptorToField(name, value, attributes);
   1881     case CALLBACKS:
   1882       return SetPropertyWithCallback(result->GetCallbackObject(),
   1883                                      name,
   1884                                      value,
   1885                                      result->holder());
   1886     case INTERCEPTOR:
   1887       return SetPropertyWithInterceptor(name, value, attributes);
   1888     case CONSTANT_TRANSITION:
   1889       // Replace with a MAP_TRANSITION to a new map with a FIELD, even
   1890       // if the value is a function.
   1891       return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
   1892     case NULL_DESCRIPTOR:
   1893       return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
   1894     default:
   1895       UNREACHABLE();
   1896   }
   1897   UNREACHABLE();
   1898   return value;
   1899 }
   1900 
   1901 
   1902 // Set a real local property, even if it is READ_ONLY.  If the property is not
   1903 // present, add it with attributes NONE.  This code is an exact clone of
   1904 // SetProperty, with the check for IsReadOnly and the check for a
   1905 // callback setter removed.  The two lines looking up the LookupResult
   1906 // result are also added.  If one of the functions is changed, the other
   1907 // should be.
   1908 Object* JSObject::IgnoreAttributesAndSetLocalProperty(
   1909     String* name,
   1910     Object* value,
   1911     PropertyAttributes attributes) {
   1912   // Make sure that the top context does not change when doing callbacks or
   1913   // interceptor calls.
   1914   AssertNoContextChange ncc;
   1915   LookupResult result;
   1916   LocalLookup(name, &result);
   1917   // Check access rights if needed.
   1918   if (IsAccessCheckNeeded()
   1919       && !Top::MayNamedAccess(this, name, v8::ACCESS_SET)) {
   1920     return SetPropertyWithFailedAccessCheck(&result, name, value);
   1921   }
   1922 
   1923   if (IsJSGlobalProxy()) {
   1924     Object* proto = GetPrototype();
   1925     if (proto->IsNull()) return value;
   1926     ASSERT(proto->IsJSGlobalObject());
   1927     return JSObject::cast(proto)->IgnoreAttributesAndSetLocalProperty(
   1928         name,
   1929         value,
   1930         attributes);
   1931   }
   1932 
   1933   // Check for accessor in prototype chain removed here in clone.
   1934   if (!result.IsFound()) {
   1935     // Neither properties nor transitions found.
   1936     return AddProperty(name, value, attributes);
   1937   }
   1938   PropertyDetails details = PropertyDetails(attributes, NORMAL);
   1939 
   1940   // Check of IsReadOnly removed from here in clone.
   1941   switch (result.type()) {
   1942     case NORMAL:
   1943       return SetNormalizedProperty(name, value, details);
   1944     case FIELD:
   1945       return FastPropertyAtPut(result.GetFieldIndex(), value);
   1946     case MAP_TRANSITION:
   1947       if (attributes == result.GetAttributes()) {
   1948         // Only use map transition if the attributes match.
   1949         return AddFastPropertyUsingMap(result.GetTransitionMap(),
   1950                                        name,
   1951                                        value);
   1952       }
   1953       return ConvertDescriptorToField(name, value, attributes);
   1954     case CONSTANT_FUNCTION:
   1955       // Only replace the function if necessary.
   1956       if (value == result.GetConstantFunction()) return value;
   1957       // Preserve the attributes of this existing property.
   1958       attributes = result.GetAttributes();
   1959       return ConvertDescriptorToField(name, value, attributes);
   1960     case CALLBACKS:
   1961     case INTERCEPTOR:
   1962       // Override callback in clone
   1963       return ConvertDescriptorToField(name, value, attributes);
   1964     case CONSTANT_TRANSITION:
   1965       // Replace with a MAP_TRANSITION to a new map with a FIELD, even
   1966       // if the value is a function.
   1967       return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
   1968     case NULL_DESCRIPTOR:
   1969       return ConvertDescriptorToFieldAndMapTransition(name, value, attributes);
   1970     default:
   1971       UNREACHABLE();
   1972   }
   1973   UNREACHABLE();
   1974   return value;
   1975 }
   1976 
   1977 
   1978 PropertyAttributes JSObject::GetPropertyAttributePostInterceptor(
   1979       JSObject* receiver,
   1980       String* name,
   1981       bool continue_search) {
   1982   // Check local property, ignore interceptor.
   1983   LookupResult result;
   1984   LocalLookupRealNamedProperty(name, &result);
   1985   if (result.IsProperty()) return result.GetAttributes();
   1986 
   1987   if (continue_search) {
   1988     // Continue searching via the prototype chain.
   1989     Object* pt = GetPrototype();
   1990     if (pt != Heap::null_value()) {
   1991       return JSObject::cast(pt)->
   1992         GetPropertyAttributeWithReceiver(receiver, name);
   1993     }
   1994   }
   1995   return ABSENT;
   1996 }
   1997 
   1998 
   1999 PropertyAttributes JSObject::GetPropertyAttributeWithInterceptor(
   2000       JSObject* receiver,
   2001       String* name,
   2002       bool continue_search) {
   2003   // Make sure that the top context does not change when doing
   2004   // callbacks or interceptor calls.
   2005   AssertNoContextChange ncc;
   2006 
   2007   HandleScope scope;
   2008   Handle<InterceptorInfo> interceptor(GetNamedInterceptor());
   2009   Handle<JSObject> receiver_handle(receiver);
   2010   Handle<JSObject> holder_handle(this);
   2011   Handle<String> name_handle(name);
   2012   CustomArguments args(interceptor->data(), receiver, this);
   2013   v8::AccessorInfo info(args.end());
   2014   if (!interceptor->query()->IsUndefined()) {
   2015     v8::NamedPropertyQuery query =
   2016         v8::ToCData<v8::NamedPropertyQuery>(interceptor->query());
   2017     LOG(ApiNamedPropertyAccess("interceptor-named-has", *holder_handle, name));
   2018     v8::Handle<v8::Boolean> result;
   2019     {
   2020       // Leaving JavaScript.
   2021       VMState state(EXTERNAL);
   2022       result = query(v8::Utils::ToLocal(name_handle), info);
   2023     }
   2024     if (!result.IsEmpty()) {
   2025       // Convert the boolean result to a property attribute
   2026       // specification.
   2027       return result->IsTrue() ? NONE : ABSENT;
   2028     }
   2029   } else if (!interceptor->getter()->IsUndefined()) {
   2030     v8::NamedPropertyGetter getter =
   2031         v8::ToCData<v8::NamedPropertyGetter>(interceptor->getter());
   2032     LOG(ApiNamedPropertyAccess("interceptor-named-get-has", this, name));
   2033     v8::Handle<v8::Value> result;
   2034     {
   2035       // Leaving JavaScript.
   2036       VMState state(EXTERNAL);
   2037       result = getter(v8::Utils::ToLocal(name_handle), info);
   2038     }
   2039     if (!result.IsEmpty()) return NONE;
   2040   }
   2041   return holder_handle->GetPropertyAttributePostInterceptor(*receiver_handle,
   2042                                                             *name_handle,
   2043                                                             continue_search);
   2044 }
   2045 
   2046 
   2047 PropertyAttributes JSObject::GetPropertyAttributeWithReceiver(
   2048       JSObject* receiver,
   2049       String* key) {
   2050   uint32_t index = 0;
   2051   if (key->AsArrayIndex(&index)) {
   2052     if (HasElementWithReceiver(receiver, index)) return NONE;
   2053     return ABSENT;
   2054   }
   2055   // Named property.
   2056   LookupResult result;
   2057   Lookup(key, &result);
   2058   return GetPropertyAttribute(receiver, &result, key, true);
   2059 }
   2060 
   2061 
   2062 PropertyAttributes JSObject::GetPropertyAttribute(JSObject* receiver,
   2063                                                   LookupResult* result,
   2064                                                   String* name,
   2065                                                   bool continue_search) {
   2066   // Check access rights if needed.
   2067   if (IsAccessCheckNeeded() &&
   2068       !Top::MayNamedAccess(this, name, v8::ACCESS_HAS)) {
   2069     return GetPropertyAttributeWithFailedAccessCheck(receiver,
   2070                                                      result,
   2071                                                      name,
   2072                                                      continue_search);
   2073   }
   2074   if (result->IsProperty()) {
   2075     switch (result->type()) {
   2076       case NORMAL:  // fall through
   2077       case FIELD:
   2078       case CONSTANT_FUNCTION:
   2079       case CALLBACKS:
   2080         return result->GetAttributes();
   2081       case INTERCEPTOR:
   2082         return result->holder()->
   2083           GetPropertyAttributeWithInterceptor(receiver, name, continue_search);
   2084       default:
   2085         UNREACHABLE();
   2086     }
   2087   }
   2088   return ABSENT;
   2089 }
   2090 
   2091 
   2092 PropertyAttributes JSObject::GetLocalPropertyAttribute(String* name) {
   2093   // Check whether the name is an array index.
   2094   uint32_t index = 0;
   2095   if (name->AsArrayIndex(&index)) {
   2096     if (HasLocalElement(index)) return NONE;
   2097     return ABSENT;
   2098   }
   2099   // Named property.
   2100   LookupResult result;
   2101   LocalLookup(name, &result);
   2102   return GetPropertyAttribute(this, &result, name, false);
   2103 }
   2104 
   2105 
   2106 Object* JSObject::NormalizeProperties(PropertyNormalizationMode mode,
   2107                                       int expected_additional_properties) {
   2108   if (!HasFastProperties()) return this;
   2109 
   2110   // The global object is always normalized.
   2111   ASSERT(!IsGlobalObject());
   2112 
   2113   // Allocate new content.
   2114   int property_count = map()->NumberOfDescribedProperties();
   2115   if (expected_additional_properties > 0) {
   2116     property_count += expected_additional_properties;
   2117   } else {
   2118     property_count += 2;  // Make space for two more properties.
   2119   }
   2120   Object* obj =
   2121       StringDictionary::Allocate(property_count * 2);
   2122   if (obj->IsFailure()) return obj;
   2123   StringDictionary* dictionary = StringDictionary::cast(obj);
   2124 
   2125   DescriptorArray* descs = map()->instance_descriptors();
   2126   for (int i = 0; i < descs->number_of_descriptors(); i++) {
   2127     PropertyDetails details = descs->GetDetails(i);
   2128     switch (details.type()) {
   2129       case CONSTANT_FUNCTION: {
   2130         PropertyDetails d =
   2131             PropertyDetails(details.attributes(), NORMAL, details.index());
   2132         Object* value = descs->GetConstantFunction(i);
   2133         Object* result = dictionary->Add(descs->GetKey(i), value, d);
   2134         if (result->IsFailure()) return result;
   2135         dictionary = StringDictionary::cast(result);
   2136         break;
   2137       }
   2138       case FIELD: {
   2139         PropertyDetails d =
   2140             PropertyDetails(details.attributes(), NORMAL, details.index());
   2141         Object* value = FastPropertyAt(descs->GetFieldIndex(i));
   2142         Object* result = dictionary->Add(descs->GetKey(i), value, d);
   2143         if (result->IsFailure()) return result;
   2144         dictionary = StringDictionary::cast(result);
   2145         break;
   2146       }
   2147       case CALLBACKS: {
   2148         PropertyDetails d =
   2149             PropertyDetails(details.attributes(), CALLBACKS, details.index());
   2150         Object* value = descs->GetCallbacksObject(i);
   2151         Object* result = dictionary->Add(descs->GetKey(i), value, d);
   2152         if (result->IsFailure()) return result;
   2153         dictionary = StringDictionary::cast(result);
   2154         break;
   2155       }
   2156       case MAP_TRANSITION:
   2157       case CONSTANT_TRANSITION:
   2158       case NULL_DESCRIPTOR:
   2159       case INTERCEPTOR:
   2160         break;
   2161       default:
   2162         UNREACHABLE();
   2163     }
   2164   }
   2165 
   2166   // Copy the next enumeration index from instance descriptor.
   2167   int index = map()->instance_descriptors()->NextEnumerationIndex();
   2168   dictionary->SetNextEnumerationIndex(index);
   2169 
   2170   // Allocate new map.
   2171   obj = map()->CopyDropDescriptors();
   2172   if (obj->IsFailure()) return obj;
   2173   Map* new_map = Map::cast(obj);
   2174 
   2175   // Clear inobject properties if needed by adjusting the instance size and
   2176   // putting in a filler object instead of the inobject properties.
   2177   if (mode == CLEAR_INOBJECT_PROPERTIES && map()->inobject_properties() > 0) {
   2178     int instance_size_delta = map()->inobject_properties() * kPointerSize;
   2179     int new_instance_size = map()->instance_size() - instance_size_delta;
   2180     new_map->set_inobject_properties(0);
   2181     new_map->set_instance_size(new_instance_size);
   2182     Heap::CreateFillerObjectAt(this->address() + new_instance_size,
   2183                                instance_size_delta);
   2184   }
   2185   new_map->set_unused_property_fields(0);
   2186 
   2187   // We have now successfully allocated all the necessary objects.
   2188   // Changes can now be made with the guarantee that all of them take effect.
   2189   set_map(new_map);
   2190   map()->set_instance_descriptors(Heap::empty_descriptor_array());
   2191 
   2192   set_properties(dictionary);
   2193 
   2194   Counters::props_to_dictionary.Increment();
   2195 
   2196 #ifdef DEBUG
   2197   if (FLAG_trace_normalization) {
   2198     PrintF("Object properties have been normalized:\n");
   2199     Print();
   2200   }
   2201 #endif
   2202   return this;
   2203 }
   2204 
   2205 
   2206 Object* JSObject::TransformToFastProperties(int unused_property_fields) {
   2207   if (HasFastProperties()) return this;
   2208   ASSERT(!IsGlobalObject());
   2209   return property_dictionary()->
   2210       TransformPropertiesToFastFor(this, unused_property_fields);
   2211 }
   2212 
   2213 
   2214 Object* JSObject::NormalizeElements() {
   2215   ASSERT(!HasPixelElements() && !HasExternalArrayElements());
   2216   if (HasDictionaryElements()) return this;
   2217 
   2218   // Get number of entries.
   2219   FixedArray* array = FixedArray::cast(elements());
   2220 
   2221   // Compute the effective length.
   2222   int length = IsJSArray() ?
   2223                Smi::cast(JSArray::cast(this)->length())->value() :
   2224                array->length();
   2225   Object* obj = NumberDictionary::Allocate(length);
   2226   if (obj->IsFailure()) return obj;
   2227   NumberDictionary* dictionary = NumberDictionary::cast(obj);
   2228   // Copy entries.
   2229   for (int i = 0; i < length; i++) {
   2230     Object* value = array->get(i);
   2231     if (!value->IsTheHole()) {
   2232       PropertyDetails details = PropertyDetails(NONE, NORMAL);
   2233       Object* result = dictionary->AddNumberEntry(i, array->get(i), details);
   2234       if (result->IsFailure()) return result;
   2235       dictionary = NumberDictionary::cast(result);
   2236     }
   2237   }
   2238   // Switch to using the dictionary as the backing storage for elements.
   2239   set_elements(dictionary);
   2240 
   2241   Counters::elements_to_dictionary.Increment();
   2242 
   2243 #ifdef DEBUG
   2244   if (FLAG_trace_normalization) {
   2245     PrintF("Object elements have been normalized:\n");
   2246     Print();
   2247   }
   2248 #endif
   2249 
   2250   return this;
   2251 }
   2252 
   2253 
   2254 Object* JSObject::DeletePropertyPostInterceptor(String* name, DeleteMode mode) {
   2255   // Check local property, ignore interceptor.
   2256   LookupResult result;
   2257   LocalLookupRealNamedProperty(name, &result);
   2258   if (!result.IsProperty()) return Heap::true_value();
   2259 
   2260   // Normalize object if needed.
   2261   Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
   2262   if (obj->IsFailure()) return obj;
   2263 
   2264   return DeleteNormalizedProperty(name, mode);
   2265 }
   2266 
   2267 
   2268 Object* JSObject::DeletePropertyWithInterceptor(String* name) {
   2269   HandleScope scope;
   2270   Handle<InterceptorInfo> interceptor(GetNamedInterceptor());
   2271   Handle<String> name_handle(name);
   2272   Handle<JSObject> this_handle(this);
   2273   if (!interceptor->deleter()->IsUndefined()) {
   2274     v8::NamedPropertyDeleter deleter =
   2275         v8::ToCData<v8::NamedPropertyDeleter>(interceptor->deleter());
   2276     LOG(ApiNamedPropertyAccess("interceptor-named-delete", *this_handle, name));
   2277     CustomArguments args(interceptor->data(), this, this);
   2278     v8::AccessorInfo info(args.end());
   2279     v8::Handle<v8::Boolean> result;
   2280     {
   2281       // Leaving JavaScript.
   2282       VMState state(EXTERNAL);
   2283       result = deleter(v8::Utils::ToLocal(name_handle), info);
   2284     }
   2285     RETURN_IF_SCHEDULED_EXCEPTION();
   2286     if (!result.IsEmpty()) {
   2287       ASSERT(result->IsBoolean());
   2288       return *v8::Utils::OpenHandle(*result);
   2289     }
   2290   }
   2291   Object* raw_result =
   2292       this_handle->DeletePropertyPostInterceptor(*name_handle, NORMAL_DELETION);
   2293   RETURN_IF_SCHEDULED_EXCEPTION();
   2294   return raw_result;
   2295 }
   2296 
   2297 
   2298 Object* JSObject::DeleteElementPostInterceptor(uint32_t index,
   2299                                                DeleteMode mode) {
   2300   ASSERT(!HasPixelElements() && !HasExternalArrayElements());
   2301   switch (GetElementsKind()) {
   2302     case FAST_ELEMENTS: {
   2303       uint32_t length = IsJSArray() ?
   2304       static_cast<uint32_t>(Smi::cast(JSArray::cast(this)->length())->value()) :
   2305       static_cast<uint32_t>(FixedArray::cast(elements())->length());
   2306       if (index < length) {
   2307         FixedArray::cast(elements())->set_the_hole(index);
   2308       }
   2309       break;
   2310     }
   2311     case DICTIONARY_ELEMENTS: {
   2312       NumberDictionary* dictionary = element_dictionary();
   2313       int entry = dictionary->FindEntry(index);
   2314       if (entry != NumberDictionary::kNotFound) {
   2315         return dictionary->DeleteProperty(entry, mode);
   2316       }
   2317       break;
   2318     }
   2319     default:
   2320       UNREACHABLE();
   2321       break;
   2322   }
   2323   return Heap::true_value();
   2324 }
   2325 
   2326 
   2327 Object* JSObject::DeleteElementWithInterceptor(uint32_t index) {
   2328   // Make sure that the top context does not change when doing
   2329   // callbacks or interceptor calls.
   2330   AssertNoContextChange ncc;
   2331   HandleScope scope;
   2332   Handle<InterceptorInfo> interceptor(GetIndexedInterceptor());
   2333   if (interceptor->deleter()->IsUndefined()) return Heap::false_value();
   2334   v8::IndexedPropertyDeleter deleter =
   2335       v8::ToCData<v8::IndexedPropertyDeleter>(interceptor->deleter());
   2336   Handle<JSObject> this_handle(this);
   2337   LOG(ApiIndexedPropertyAccess("interceptor-indexed-delete", this, index));
   2338   CustomArguments args(interceptor->data(), this, this);
   2339   v8::AccessorInfo info(args.end());
   2340   v8::Handle<v8::Boolean> result;
   2341   {
   2342     // Leaving JavaScript.
   2343     VMState state(EXTERNAL);
   2344     result = deleter(index, info);
   2345   }
   2346   RETURN_IF_SCHEDULED_EXCEPTION();
   2347   if (!result.IsEmpty()) {
   2348     ASSERT(result->IsBoolean());
   2349     return *v8::Utils::OpenHandle(*result);
   2350   }
   2351   Object* raw_result =
   2352       this_handle->DeleteElementPostInterceptor(index, NORMAL_DELETION);
   2353   RETURN_IF_SCHEDULED_EXCEPTION();
   2354   return raw_result;
   2355 }
   2356 
   2357 
   2358 Object* JSObject::DeleteElement(uint32_t index, DeleteMode mode) {
   2359   // Check access rights if needed.
   2360   if (IsAccessCheckNeeded() &&
   2361       !Top::MayIndexedAccess(this, index, v8::ACCESS_DELETE)) {
   2362     Top::ReportFailedAccessCheck(this, v8::ACCESS_DELETE);
   2363     return Heap::false_value();
   2364   }
   2365 
   2366   if (IsJSGlobalProxy()) {
   2367     Object* proto = GetPrototype();
   2368     if (proto->IsNull()) return Heap::false_value();
   2369     ASSERT(proto->IsJSGlobalObject());
   2370     return JSGlobalObject::cast(proto)->DeleteElement(index, mode);
   2371   }
   2372 
   2373   if (HasIndexedInterceptor()) {
   2374     // Skip interceptor if forcing deletion.
   2375     if (mode == FORCE_DELETION) {
   2376       return DeleteElementPostInterceptor(index, mode);
   2377     }
   2378     return DeleteElementWithInterceptor(index);
   2379   }
   2380 
   2381   switch (GetElementsKind()) {
   2382     case FAST_ELEMENTS: {
   2383       uint32_t length = IsJSArray() ?
   2384       static_cast<uint32_t>(Smi::cast(JSArray::cast(this)->length())->value()) :
   2385       static_cast<uint32_t>(FixedArray::cast(elements())->length());
   2386       if (index < length) {
   2387         FixedArray::cast(elements())->set_the_hole(index);
   2388       }
   2389       break;
   2390     }
   2391     case PIXEL_ELEMENTS:
   2392     case EXTERNAL_BYTE_ELEMENTS:
   2393     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
   2394     case EXTERNAL_SHORT_ELEMENTS:
   2395     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
   2396     case EXTERNAL_INT_ELEMENTS:
   2397     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
   2398     case EXTERNAL_FLOAT_ELEMENTS:
   2399       // Pixel and external array elements cannot be deleted. Just
   2400       // silently ignore here.
   2401       break;
   2402     case DICTIONARY_ELEMENTS: {
   2403       NumberDictionary* dictionary = element_dictionary();
   2404       int entry = dictionary->FindEntry(index);
   2405       if (entry != NumberDictionary::kNotFound) {
   2406         return dictionary->DeleteProperty(entry, mode);
   2407       }
   2408       break;
   2409     }
   2410     default:
   2411       UNREACHABLE();
   2412       break;
   2413   }
   2414   return Heap::true_value();
   2415 }
   2416 
   2417 
   2418 Object* JSObject::DeleteProperty(String* name, DeleteMode mode) {
   2419   // ECMA-262, 3rd, 8.6.2.5
   2420   ASSERT(name->IsString());
   2421 
   2422   // Check access rights if needed.
   2423   if (IsAccessCheckNeeded() &&
   2424       !Top::MayNamedAccess(this, name, v8::ACCESS_DELETE)) {
   2425     Top::ReportFailedAccessCheck(this, v8::ACCESS_DELETE);
   2426     return Heap::false_value();
   2427   }
   2428 
   2429   if (IsJSGlobalProxy()) {
   2430     Object* proto = GetPrototype();
   2431     if (proto->IsNull()) return Heap::false_value();
   2432     ASSERT(proto->IsJSGlobalObject());
   2433     return JSGlobalObject::cast(proto)->DeleteProperty(name, mode);
   2434   }
   2435 
   2436   uint32_t index = 0;
   2437   if (name->AsArrayIndex(&index)) {
   2438     return DeleteElement(index, mode);
   2439   } else {
   2440     LookupResult result;
   2441     LocalLookup(name, &result);
   2442     if (!result.IsProperty()) return Heap::true_value();
   2443     // Ignore attributes if forcing a deletion.
   2444     if (result.IsDontDelete() && mode != FORCE_DELETION) {
   2445       return Heap::false_value();
   2446     }
   2447     // Check for interceptor.
   2448     if (result.type() == INTERCEPTOR) {
   2449       // Skip interceptor if forcing a deletion.
   2450       if (mode == FORCE_DELETION) {
   2451         return DeletePropertyPostInterceptor(name, mode);
   2452       }
   2453       return DeletePropertyWithInterceptor(name);
   2454     }
   2455     // Normalize object if needed.
   2456     Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
   2457     if (obj->IsFailure()) return obj;
   2458     // Make sure the properties are normalized before removing the entry.
   2459     return DeleteNormalizedProperty(name, mode);
   2460   }
   2461 }
   2462 
   2463 
   2464 // Check whether this object references another object.
   2465 bool JSObject::ReferencesObject(Object* obj) {
   2466   AssertNoAllocation no_alloc;
   2467 
   2468   // Is the object the constructor for this object?
   2469   if (map()->constructor() == obj) {
   2470     return true;
   2471   }
   2472 
   2473   // Is the object the prototype for this object?
   2474   if (map()->prototype() == obj) {
   2475     return true;
   2476   }
   2477 
   2478   // Check if the object is among the named properties.
   2479   Object* key = SlowReverseLookup(obj);
   2480   if (key != Heap::undefined_value()) {
   2481     return true;
   2482   }
   2483 
   2484   // Check if the object is among the indexed properties.
   2485   switch (GetElementsKind()) {
   2486     case PIXEL_ELEMENTS:
   2487     case EXTERNAL_BYTE_ELEMENTS:
   2488     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
   2489     case EXTERNAL_SHORT_ELEMENTS:
   2490     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
   2491     case EXTERNAL_INT_ELEMENTS:
   2492     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
   2493     case EXTERNAL_FLOAT_ELEMENTS:
   2494       // Raw pixels and external arrays do not reference other
   2495       // objects.
   2496       break;
   2497     case FAST_ELEMENTS: {
   2498       int length = IsJSArray() ?
   2499           Smi::cast(JSArray::cast(this)->length())->value() :
   2500           FixedArray::cast(elements())->length();
   2501       for (int i = 0; i < length; i++) {
   2502         Object* element = FixedArray::cast(elements())->get(i);
   2503         if (!element->IsTheHole() && element == obj) {
   2504           return true;
   2505         }
   2506       }
   2507       break;
   2508     }
   2509     case DICTIONARY_ELEMENTS: {
   2510       key = element_dictionary()->SlowReverseLookup(obj);
   2511       if (key != Heap::undefined_value()) {
   2512         return true;
   2513       }
   2514       break;
   2515     }
   2516     default:
   2517       UNREACHABLE();
   2518       break;
   2519   }
   2520 
   2521   // For functions check the context. Boilerplate functions do
   2522   // not have to be traversed since they have no real context.
   2523   if (IsJSFunction() && !JSFunction::cast(this)->IsBoilerplate()) {
   2524     // Get the constructor function for arguments array.
   2525     JSObject* arguments_boilerplate =
   2526         Top::context()->global_context()->arguments_boilerplate();
   2527     JSFunction* arguments_function =
   2528         JSFunction::cast(arguments_boilerplate->map()->constructor());
   2529 
   2530     // Get the context and don't check if it is the global context.
   2531     JSFunction* f = JSFunction::cast(this);
   2532     Context* context = f->context();
   2533     if (context->IsGlobalContext()) {
   2534       return false;
   2535     }
   2536 
   2537     // Check the non-special context slots.
   2538     for (int i = Context::MIN_CONTEXT_SLOTS; i < context->length(); i++) {
   2539       // Only check JS objects.
   2540       if (context->get(i)->IsJSObject()) {
   2541         JSObject* ctxobj = JSObject::cast(context->get(i));
   2542         // If it is an arguments array check the content.
   2543         if (ctxobj->map()->constructor() == arguments_function) {
   2544           if (ctxobj->ReferencesObject(obj)) {
   2545             return true;
   2546           }
   2547         } else if (ctxobj == obj) {
   2548           return true;
   2549         }
   2550       }
   2551     }
   2552 
   2553     // Check the context extension if any.
   2554     if (context->has_extension()) {
   2555       return context->extension()->ReferencesObject(obj);
   2556     }
   2557   }
   2558 
   2559   // No references to object.
   2560   return false;
   2561 }
   2562 
   2563 
   2564 // Tests for the fast common case for property enumeration:
   2565 // - This object and all prototypes has an enum cache (which means that it has
   2566 //   no interceptors and needs no access checks).
   2567 // - This object has no elements.
   2568 // - No prototype has enumerable properties/elements.
   2569 bool JSObject::IsSimpleEnum() {
   2570   for (Object* o = this;
   2571        o != Heap::null_value();
   2572        o = JSObject::cast(o)->GetPrototype()) {
   2573     JSObject* curr = JSObject::cast(o);
   2574     if (!curr->map()->instance_descriptors()->HasEnumCache()) return false;
   2575     ASSERT(!curr->HasNamedInterceptor());
   2576     ASSERT(!curr->HasIndexedInterceptor());
   2577     ASSERT(!curr->IsAccessCheckNeeded());
   2578     if (curr->NumberOfEnumElements() > 0) return false;
   2579     if (curr != this) {
   2580       FixedArray* curr_fixed_array =
   2581           FixedArray::cast(curr->map()->instance_descriptors()->GetEnumCache());
   2582       if (curr_fixed_array->length() > 0) return false;
   2583     }
   2584   }
   2585   return true;
   2586 }
   2587 
   2588 
   2589 int Map::NumberOfDescribedProperties() {
   2590   int result = 0;
   2591   DescriptorArray* descs = instance_descriptors();
   2592   for (int i = 0; i < descs->number_of_descriptors(); i++) {
   2593     if (descs->IsProperty(i)) result++;
   2594   }
   2595   return result;
   2596 }
   2597 
   2598 
   2599 int Map::PropertyIndexFor(String* name) {
   2600   DescriptorArray* descs = instance_descriptors();
   2601   for (int i = 0; i < descs->number_of_descriptors(); i++) {
   2602     if (name->Equals(descs->GetKey(i)) && !descs->IsNullDescriptor(i)) {
   2603       return descs->GetFieldIndex(i);
   2604     }
   2605   }
   2606   return -1;
   2607 }
   2608 
   2609 
   2610 int Map::NextFreePropertyIndex() {
   2611   int max_index = -1;
   2612   DescriptorArray* descs = instance_descriptors();
   2613   for (int i = 0; i < descs->number_of_descriptors(); i++) {
   2614     if (descs->GetType(i) == FIELD) {
   2615       int current_index = descs->GetFieldIndex(i);
   2616       if (current_index > max_index) max_index = current_index;
   2617     }
   2618   }
   2619   return max_index + 1;
   2620 }
   2621 
   2622 
   2623 AccessorDescriptor* Map::FindAccessor(String* name) {
   2624   DescriptorArray* descs = instance_descriptors();
   2625   for (int i = 0; i < descs->number_of_descriptors(); i++) {
   2626     if (name->Equals(descs->GetKey(i)) && descs->GetType(i) == CALLBACKS) {
   2627       return descs->GetCallbacks(i);
   2628     }
   2629   }
   2630   return NULL;
   2631 }
   2632 
   2633 
   2634 void JSObject::LocalLookup(String* name, LookupResult* result) {
   2635   ASSERT(name->IsString());
   2636 
   2637   if (IsJSGlobalProxy()) {
   2638     Object* proto = GetPrototype();
   2639     if (proto->IsNull()) return result->NotFound();
   2640     ASSERT(proto->IsJSGlobalObject());
   2641     return JSObject::cast(proto)->LocalLookup(name, result);
   2642   }
   2643 
   2644   // Do not use inline caching if the object is a non-global object
   2645   // that requires access checks.
   2646   if (!IsJSGlobalProxy() && IsAccessCheckNeeded()) {
   2647     result->DisallowCaching();
   2648   }
   2649 
   2650   // Check __proto__ before interceptor.
   2651   if (name->Equals(Heap::Proto_symbol()) && !IsJSContextExtensionObject()) {
   2652     result->ConstantResult(this);
   2653     return;
   2654   }
   2655 
   2656   // Check for lookup interceptor except when bootstrapping.
   2657   if (HasNamedInterceptor() && !Bootstrapper::IsActive()) {
   2658     result->InterceptorResult(this);
   2659     return;
   2660   }
   2661 
   2662   LocalLookupRealNamedProperty(name, result);
   2663 }
   2664 
   2665 
   2666 void JSObject::Lookup(String* name, LookupResult* result) {
   2667   // Ecma-262 3rd 8.6.2.4
   2668   for (Object* current = this;
   2669        current != Heap::null_value();
   2670        current = JSObject::cast(current)->GetPrototype()) {
   2671     JSObject::cast(current)->LocalLookup(name, result);
   2672     if (result->IsProperty()) return;
   2673   }
   2674   result->NotFound();
   2675 }
   2676 
   2677 
   2678 // Search object and it's prototype chain for callback properties.
   2679 void JSObject::LookupCallback(String* name, LookupResult* result) {
   2680   for (Object* current = this;
   2681        current != Heap::null_value();
   2682        current = JSObject::cast(current)->GetPrototype()) {
   2683     JSObject::cast(current)->LocalLookupRealNamedProperty(name, result);
   2684     if (result->IsProperty() && result->type() == CALLBACKS) return;
   2685   }
   2686   result->NotFound();
   2687 }
   2688 
   2689 
   2690 Object* JSObject::DefineGetterSetter(String* name,
   2691                                      PropertyAttributes attributes) {
   2692   // Make sure that the top context does not change when doing callbacks or
   2693   // interceptor calls.
   2694   AssertNoContextChange ncc;
   2695 
   2696   // Check access rights if needed.
   2697   if (IsAccessCheckNeeded() &&
   2698       !Top::MayNamedAccess(this, name, v8::ACCESS_SET)) {
   2699     Top::ReportFailedAccessCheck(this, v8::ACCESS_SET);
   2700     return Heap::undefined_value();
   2701   }
   2702 
   2703   // Try to flatten before operating on the string.
   2704   name->TryFlattenIfNotFlat();
   2705 
   2706   // Check if there is an API defined callback object which prohibits
   2707   // callback overwriting in this object or it's prototype chain.
   2708   // This mechanism is needed for instance in a browser setting, where
   2709   // certain accessors such as window.location should not be allowed
   2710   // to be overwritten because allowing overwriting could potentially
   2711   // cause security problems.
   2712   LookupResult callback_result;
   2713   LookupCallback(name, &callback_result);
   2714   if (callback_result.IsFound()) {
   2715     Object* obj = callback_result.GetCallbackObject();
   2716     if (obj->IsAccessorInfo() &&
   2717         AccessorInfo::cast(obj)->prohibits_overwriting()) {
   2718       return Heap::undefined_value();
   2719     }
   2720   }
   2721 
   2722   uint32_t index;
   2723   bool is_element = name->AsArrayIndex(&index);
   2724   if (is_element && IsJSArray()) return Heap::undefined_value();
   2725 
   2726   if (is_element) {
   2727     switch (GetElementsKind()) {
   2728       case FAST_ELEMENTS:
   2729         break;
   2730       case PIXEL_ELEMENTS:
   2731       case EXTERNAL_BYTE_ELEMENTS:
   2732       case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
   2733       case EXTERNAL_SHORT_ELEMENTS:
   2734       case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
   2735       case EXTERNAL_INT_ELEMENTS:
   2736       case EXTERNAL_UNSIGNED_INT_ELEMENTS:
   2737       case EXTERNAL_FLOAT_ELEMENTS:
   2738         // Ignore getters and setters on pixel and external array
   2739         // elements.
   2740         return Heap::undefined_value();
   2741       case DICTIONARY_ELEMENTS: {
   2742         // Lookup the index.
   2743         NumberDictionary* dictionary = element_dictionary();
   2744         int entry = dictionary->FindEntry(index);
   2745         if (entry != NumberDictionary::kNotFound) {
   2746           Object* result = dictionary->ValueAt(entry);
   2747           PropertyDetails details = dictionary->DetailsAt(entry);
   2748           if (details.IsReadOnly()) return Heap::undefined_value();
   2749           if (details.type() == CALLBACKS) {
   2750             // Only accessors allowed as elements.
   2751             ASSERT(result->IsFixedArray());
   2752             return result;
   2753           }
   2754         }
   2755         break;
   2756       }
   2757       default:
   2758         UNREACHABLE();
   2759         break;
   2760     }
   2761   } else {
   2762     // Lookup the name.
   2763     LookupResult result;
   2764     LocalLookup(name, &result);
   2765     if (result.IsProperty()) {
   2766       if (result.IsReadOnly()) return Heap::undefined_value();
   2767       if (result.type() == CALLBACKS) {
   2768         Object* obj = result.GetCallbackObject();
   2769         if (obj->IsFixedArray()) {
   2770           // The object might be in fast mode even though it has
   2771           // a getter/setter.
   2772           Object* ok = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
   2773           if (ok->IsFailure()) return ok;
   2774 
   2775           PropertyDetails details = PropertyDetails(attributes, CALLBACKS);
   2776           SetNormalizedProperty(name, obj, details);
   2777           return obj;
   2778         }
   2779       }
   2780     }
   2781   }
   2782 
   2783   // Allocate the fixed array to hold getter and setter.
   2784   Object* structure = Heap::AllocateFixedArray(2, TENURED);
   2785   if (structure->IsFailure()) return structure;
   2786   PropertyDetails details = PropertyDetails(attributes, CALLBACKS);
   2787 
   2788   if (is_element) {
   2789     // Normalize object to make this operation simple.
   2790     Object* ok = NormalizeElements();
   2791     if (ok->IsFailure()) return ok;
   2792 
   2793     // Update the dictionary with the new CALLBACKS property.
   2794     Object* dict =
   2795         element_dictionary()->Set(index, structure, details);
   2796     if (dict->IsFailure()) return dict;
   2797 
   2798     // If name is an index we need to stay in slow case.
   2799     NumberDictionary* elements = NumberDictionary::cast(dict);
   2800     elements->set_requires_slow_elements();
   2801     // Set the potential new dictionary on the object.
   2802     set_elements(NumberDictionary::cast(dict));
   2803   } else {
   2804     // Normalize object to make this operation simple.
   2805     Object* ok = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
   2806     if (ok->IsFailure()) return ok;
   2807 
   2808     // For the global object allocate a new map to invalidate the global inline
   2809     // caches which have a global property cell reference directly in the code.
   2810     if (IsGlobalObject()) {
   2811       Object* new_map = map()->CopyDropDescriptors();
   2812       if (new_map->IsFailure()) return new_map;
   2813       set_map(Map::cast(new_map));
   2814     }
   2815 
   2816     // Update the dictionary with the new CALLBACKS property.
   2817     return SetNormalizedProperty(name, structure, details);
   2818   }
   2819 
   2820   return structure;
   2821 }
   2822 
   2823 
   2824 Object* JSObject::DefineAccessor(String* name, bool is_getter, JSFunction* fun,
   2825                                  PropertyAttributes attributes) {
   2826   // Check access rights if needed.
   2827   if (IsAccessCheckNeeded() &&
   2828       !Top::MayNamedAccess(this, name, v8::ACCESS_HAS)) {
   2829     Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS);
   2830     return Heap::undefined_value();
   2831   }
   2832 
   2833   if (IsJSGlobalProxy()) {
   2834     Object* proto = GetPrototype();
   2835     if (proto->IsNull()) return this;
   2836     ASSERT(proto->IsJSGlobalObject());
   2837     return JSObject::cast(proto)->DefineAccessor(name, is_getter,
   2838                                                  fun, attributes);
   2839   }
   2840 
   2841   Object* array = DefineGetterSetter(name, attributes);
   2842   if (array->IsFailure() || array->IsUndefined()) return array;
   2843   FixedArray::cast(array)->set(is_getter ? 0 : 1, fun);
   2844   return this;
   2845 }
   2846 
   2847 
   2848 Object* JSObject::LookupAccessor(String* name, bool is_getter) {
   2849   // Make sure that the top context does not change when doing callbacks or
   2850   // interceptor calls.
   2851   AssertNoContextChange ncc;
   2852 
   2853   // Check access rights if needed.
   2854   if (IsAccessCheckNeeded() &&
   2855       !Top::MayNamedAccess(this, name, v8::ACCESS_HAS)) {
   2856     Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS);
   2857     return Heap::undefined_value();
   2858   }
   2859 
   2860   // Make the lookup and include prototypes.
   2861   int accessor_index = is_getter ? kGetterIndex : kSetterIndex;
   2862   uint32_t index;
   2863   if (name->AsArrayIndex(&index)) {
   2864     for (Object* obj = this;
   2865          obj != Heap::null_value();
   2866          obj = JSObject::cast(obj)->GetPrototype()) {
   2867       JSObject* js_object = JSObject::cast(obj);
   2868       if (js_object->HasDictionaryElements()) {
   2869         NumberDictionary* dictionary = js_object->element_dictionary();
   2870         int entry = dictionary->FindEntry(index);
   2871         if (entry != NumberDictionary::kNotFound) {
   2872           Object* element = dictionary->ValueAt(entry);
   2873           PropertyDetails details = dictionary->DetailsAt(entry);
   2874           if (details.type() == CALLBACKS) {
   2875             // Only accessors allowed as elements.
   2876             return FixedArray::cast(element)->get(accessor_index);
   2877           }
   2878         }
   2879       }
   2880     }
   2881   } else {
   2882     for (Object* obj = this;
   2883          obj != Heap::null_value();
   2884          obj = JSObject::cast(obj)->GetPrototype()) {
   2885       LookupResult result;
   2886       JSObject::cast(obj)->LocalLookup(name, &result);
   2887       if (result.IsProperty()) {
   2888         if (result.IsReadOnly()) return Heap::undefined_value();
   2889         if (result.type() == CALLBACKS) {
   2890           Object* obj = result.GetCallbackObject();
   2891           if (obj->IsFixedArray()) {
   2892             return FixedArray::cast(obj)->get(accessor_index);
   2893           }
   2894         }
   2895       }
   2896     }
   2897   }
   2898   return Heap::undefined_value();
   2899 }
   2900 
   2901 
   2902 Object* JSObject::SlowReverseLookup(Object* value) {
   2903   if (HasFastProperties()) {
   2904     DescriptorArray* descs = map()->instance_descriptors();
   2905     for (int i = 0; i < descs->number_of_descriptors(); i++) {
   2906       if (descs->GetType(i) == FIELD) {
   2907         if (FastPropertyAt(descs->GetFieldIndex(i)) == value) {
   2908           return descs->GetKey(i);
   2909         }
   2910       } else if (descs->GetType(i) == CONSTANT_FUNCTION) {
   2911         if (descs->GetConstantFunction(i) == value) {
   2912           return descs->GetKey(i);
   2913         }
   2914       }
   2915     }
   2916     return Heap::undefined_value();
   2917   } else {
   2918     return property_dictionary()->SlowReverseLookup(value);
   2919   }
   2920 }
   2921 
   2922 
   2923 Object* Map::CopyDropDescriptors() {
   2924   Object* result = Heap::AllocateMap(instance_type(), instance_size());
   2925   if (result->IsFailure()) return result;
   2926   Map::cast(result)->set_prototype(prototype());
   2927   Map::cast(result)->set_constructor(constructor());
   2928   // Don't copy descriptors, so map transitions always remain a forest.
   2929   // If we retained the same descriptors we would have two maps
   2930   // pointing to the same transition which is bad because the garbage
   2931   // collector relies on being able to reverse pointers from transitions
   2932   // to maps.  If properties need to be retained use CopyDropTransitions.
   2933   Map::cast(result)->set_instance_descriptors(Heap::empty_descriptor_array());
   2934   // Please note instance_type and instance_size are set when allocated.
   2935   Map::cast(result)->set_inobject_properties(inobject_properties());
   2936   Map::cast(result)->set_unused_property_fields(unused_property_fields());
   2937 
   2938   // If the map has pre-allocated properties always start out with a descriptor
   2939   // array describing these properties.
   2940   if (pre_allocated_property_fields() > 0) {
   2941     ASSERT(constructor()->IsJSFunction());
   2942     JSFunction* ctor = JSFunction::cast(constructor());
   2943     Object* descriptors =
   2944         ctor->initial_map()->instance_descriptors()->RemoveTransitions();
   2945     if (descriptors->IsFailure()) return descriptors;
   2946     Map::cast(result)->set_instance_descriptors(
   2947         DescriptorArray::cast(descriptors));
   2948     Map::cast(result)->set_pre_allocated_property_fields(
   2949         pre_allocated_property_fields());
   2950   }
   2951   Map::cast(result)->set_bit_field(bit_field());
   2952   Map::cast(result)->set_bit_field2(bit_field2());
   2953   Map::cast(result)->ClearCodeCache();
   2954   return result;
   2955 }
   2956 
   2957 
   2958 Object* Map::CopyDropTransitions() {
   2959   Object* new_map = CopyDropDescriptors();
   2960   if (new_map->IsFailure()) return new_map;
   2961   Object* descriptors = instance_descriptors()->RemoveTransitions();
   2962   if (descriptors->IsFailure()) return descriptors;
   2963   cast(new_map)->set_instance_descriptors(DescriptorArray::cast(descriptors));
   2964   return cast(new_map);
   2965 }
   2966 
   2967 
   2968 Object* Map::UpdateCodeCache(String* name, Code* code) {
   2969   ASSERT(code->ic_state() == MONOMORPHIC);
   2970   FixedArray* cache = code_cache();
   2971 
   2972   // When updating the code cache we disregard the type encoded in the
   2973   // flags. This allows call constant stubs to overwrite call field
   2974   // stubs, etc.
   2975   Code::Flags flags = Code::RemoveTypeFromFlags(code->flags());
   2976 
   2977   // First check whether we can update existing code cache without
   2978   // extending it.
   2979   int length = cache->length();
   2980   int deleted_index = -1;
   2981   for (int i = 0; i < length; i += 2) {
   2982     Object* key = cache->get(i);
   2983     if (key->IsNull()) {
   2984       if (deleted_index < 0) deleted_index = i;
   2985       continue;
   2986     }
   2987     if (key->IsUndefined()) {
   2988       if (deleted_index >= 0) i = deleted_index;
   2989       cache->set(i + 0, name);
   2990       cache->set(i + 1, code);
   2991       return this;
   2992     }
   2993     if (name->Equals(String::cast(key))) {
   2994       Code::Flags found = Code::cast(cache->get(i + 1))->flags();
   2995       if (Code::RemoveTypeFromFlags(found) == flags) {
   2996         cache->set(i + 1, code);
   2997         return this;
   2998       }
   2999     }
   3000   }
   3001 
   3002   // Reached the end of the code cache.  If there were deleted
   3003   // elements, reuse the space for the first of them.
   3004   if (deleted_index >= 0) {
   3005     cache->set(deleted_index + 0, name);
   3006     cache->set(deleted_index + 1, code);
   3007     return this;
   3008   }
   3009 
   3010   // Extend the code cache with some new entries (at least one).
   3011   int new_length = length + ((length >> 1) & ~1) + 2;
   3012   ASSERT((new_length & 1) == 0);  // must be a multiple of two
   3013   Object* result = cache->CopySize(new_length);
   3014   if (result->IsFailure()) return result;
   3015 
   3016   // Add the (name, code) pair to the new cache.
   3017   cache = FixedArray::cast(result);
   3018   cache->set(length + 0, name);
   3019   cache->set(length + 1, code);
   3020   set_code_cache(cache);
   3021   return this;
   3022 }
   3023 
   3024 
   3025 Object* Map::FindInCodeCache(String* name, Code::Flags flags) {
   3026   FixedArray* cache = code_cache();
   3027   int length = cache->length();
   3028   for (int i = 0; i < length; i += 2) {
   3029     Object* key = cache->get(i);
   3030     // Skip deleted elements.
   3031     if (key->IsNull()) continue;
   3032     if (key->IsUndefined()) return key;
   3033     if (name->Equals(String::cast(key))) {
   3034       Code* code = Code::cast(cache->get(i + 1));
   3035       if (code->flags() == flags) return code;
   3036     }
   3037   }
   3038   return Heap::undefined_value();
   3039 }
   3040 
   3041 
   3042 int Map::IndexInCodeCache(Code* code) {
   3043   FixedArray* array = code_cache();
   3044   int len = array->length();
   3045   for (int i = 0; i < len; i += 2) {
   3046     if (array->get(i + 1) == code) return i + 1;
   3047   }
   3048   return -1;
   3049 }
   3050 
   3051 
   3052 void Map::RemoveFromCodeCache(int index) {
   3053   FixedArray* array = code_cache();
   3054   ASSERT(array->length() >= index && array->get(index)->IsCode());
   3055   // Use null instead of undefined for deleted elements to distinguish
   3056   // deleted elements from unused elements.  This distinction is used
   3057   // when looking up in the cache and when updating the cache.
   3058   array->set_null(index - 1);  // key
   3059   array->set_null(index);  // code
   3060 }
   3061 
   3062 
   3063 void FixedArray::FixedArrayIterateBody(ObjectVisitor* v) {
   3064   IteratePointers(v, kHeaderSize, kHeaderSize + length() * kPointerSize);
   3065 }
   3066 
   3067 
   3068 static bool HasKey(FixedArray* array, Object* key) {
   3069   int len0 = array->length();
   3070   for (int i = 0; i < len0; i++) {
   3071     Object* element = array->get(i);
   3072     if (element->IsSmi() && key->IsSmi() && (element == key)) return true;
   3073     if (element->IsString() &&
   3074         key->IsString() && String::cast(element)->Equals(String::cast(key))) {
   3075       return true;
   3076     }
   3077   }
   3078   return false;
   3079 }
   3080 
   3081 
   3082 Object* FixedArray::AddKeysFromJSArray(JSArray* array) {
   3083   ASSERT(!array->HasPixelElements() && !array->HasExternalArrayElements());
   3084   switch (array->GetElementsKind()) {
   3085     case JSObject::FAST_ELEMENTS:
   3086       return UnionOfKeys(FixedArray::cast(array->elements()));
   3087     case JSObject::DICTIONARY_ELEMENTS: {
   3088       NumberDictionary* dict = array->element_dictionary();
   3089       int size = dict->NumberOfElements();
   3090 
   3091       // Allocate a temporary fixed array.
   3092       Object* object = Heap::AllocateFixedArray(size);
   3093       if (object->IsFailure()) return object;
   3094       FixedArray* key_array = FixedArray::cast(object);
   3095 
   3096       int capacity = dict->Capacity();
   3097       int pos = 0;
   3098       // Copy the elements from the JSArray to the temporary fixed array.
   3099       for (int i = 0; i < capacity; i++) {
   3100         if (dict->IsKey(dict->KeyAt(i))) {
   3101           key_array->set(pos++, dict->ValueAt(i));
   3102         }
   3103       }
   3104       // Compute the union of this and the temporary fixed array.
   3105       return UnionOfKeys(key_array);
   3106     }
   3107     default:
   3108       UNREACHABLE();
   3109   }
   3110   UNREACHABLE();
   3111   return Heap::null_value();  // Failure case needs to "return" a value.
   3112 }
   3113 
   3114 
   3115 Object* FixedArray::UnionOfKeys(FixedArray* other) {
   3116   int len0 = length();
   3117   int len1 = other->length();
   3118   // Optimize if either is empty.
   3119   if (len0 == 0) return other;
   3120   if (len1 == 0) return this;
   3121 
   3122   // Compute how many elements are not in this.
   3123   int extra = 0;
   3124   for (int y = 0; y < len1; y++) {
   3125     Object* value = other->get(y);
   3126     if (!value->IsTheHole() && !HasKey(this, value)) extra++;
   3127   }
   3128 
   3129   if (extra == 0) return this;
   3130 
   3131   // Allocate the result
   3132   Object* obj = Heap::AllocateFixedArray(len0 + extra);
   3133   if (obj->IsFailure()) return obj;
   3134   // Fill in the content
   3135   AssertNoAllocation no_gc;
   3136   FixedArray* result = FixedArray::cast(obj);
   3137   WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
   3138   for (int i = 0; i < len0; i++) {
   3139     result->set(i, get(i), mode);
   3140   }
   3141   // Fill in the extra keys.
   3142   int index = 0;
   3143   for (int y = 0; y < len1; y++) {
   3144     Object* value = other->get(y);
   3145     if (!value->IsTheHole() && !HasKey(this, value)) {
   3146       result->set(len0 + index, other->get(y), mode);
   3147       index++;
   3148     }
   3149   }
   3150   ASSERT(extra == index);
   3151   return result;
   3152 }
   3153 
   3154 
   3155 Object* FixedArray::CopySize(int new_length) {
   3156   if (new_length == 0) return Heap::empty_fixed_array();
   3157   Object* obj = Heap::AllocateFixedArray(new_length);
   3158   if (obj->IsFailure()) return obj;
   3159   FixedArray* result = FixedArray::cast(obj);
   3160   // Copy the content
   3161   AssertNoAllocation no_gc;
   3162   int len = length();
   3163   if (new_length < len) len = new_length;
   3164   result->set_map(map());
   3165   WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
   3166   for (int i = 0; i < len; i++) {
   3167     result->set(i, get(i), mode);
   3168   }
   3169   return result;
   3170 }
   3171 
   3172 
   3173 void FixedArray::CopyTo(int pos, FixedArray* dest, int dest_pos, int len) {
   3174   AssertNoAllocation no_gc;
   3175   WriteBarrierMode mode = dest->GetWriteBarrierMode(no_gc);
   3176   for (int index = 0; index < len; index++) {
   3177     dest->set(dest_pos+index, get(pos+index), mode);
   3178   }
   3179 }
   3180 
   3181 
   3182 #ifdef DEBUG
   3183 bool FixedArray::IsEqualTo(FixedArray* other) {
   3184   if (length() != other->length()) return false;
   3185   for (int i = 0 ; i < length(); ++i) {
   3186     if (get(i) != other->get(i)) return false;
   3187   }
   3188   return true;
   3189 }
   3190 #endif
   3191 
   3192 
   3193 Object* DescriptorArray::Allocate(int number_of_descriptors) {
   3194   if (number_of_descriptors == 0) {
   3195     return Heap::empty_descriptor_array();
   3196   }
   3197   // Allocate the array of keys.
   3198   Object* array =
   3199       Heap::AllocateFixedArray(ToKeyIndex(number_of_descriptors));
   3200   if (array->IsFailure()) return array;
   3201   // Do not use DescriptorArray::cast on incomplete object.
   3202   FixedArray* result = FixedArray::cast(array);
   3203 
   3204   // Allocate the content array and set it in the descriptor array.
   3205   array = Heap::AllocateFixedArray(number_of_descriptors << 1);
   3206   if (array->IsFailure()) return array;
   3207   result->set(kContentArrayIndex, array);
   3208   result->set(kEnumerationIndexIndex,
   3209               Smi::FromInt(PropertyDetails::kInitialIndex));
   3210   return result;
   3211 }
   3212 
   3213 
   3214 void DescriptorArray::SetEnumCache(FixedArray* bridge_storage,
   3215                                    FixedArray* new_cache) {
   3216   ASSERT(bridge_storage->length() >= kEnumCacheBridgeLength);
   3217   if (HasEnumCache()) {
   3218     FixedArray::cast(get(kEnumerationIndexIndex))->
   3219       set(kEnumCacheBridgeCacheIndex, new_cache);
   3220   } else {
   3221     if (IsEmpty()) return;  // Do nothing for empty descriptor array.
   3222     FixedArray::cast(bridge_storage)->
   3223       set(kEnumCacheBridgeCacheIndex, new_cache);
   3224     fast_set(FixedArray::cast(bridge_storage),
   3225              kEnumCacheBridgeEnumIndex,
   3226              get(kEnumerationIndexIndex));
   3227     set(kEnumerationIndexIndex, bridge_storage);
   3228   }
   3229 }
   3230 
   3231 
   3232 Object* DescriptorArray::CopyInsert(Descriptor* descriptor,
   3233                                     TransitionFlag transition_flag) {
   3234   // Transitions are only kept when inserting another transition.
   3235   // This precondition is not required by this function's implementation, but
   3236   // is currently required by the semantics of maps, so we check it.
   3237   // Conversely, we filter after replacing, so replacing a transition and
   3238   // removing all other transitions is not supported.
   3239   bool remove_transitions = transition_flag == REMOVE_TRANSITIONS;
   3240   ASSERT(remove_transitions == !descriptor->GetDetails().IsTransition());
   3241   ASSERT(descriptor->GetDetails().type() != NULL_DESCRIPTOR);
   3242 
   3243   // Ensure the key is a symbol.
   3244   Object* result = descriptor->KeyToSymbol();
   3245   if (result->IsFailure()) return result;
   3246 
   3247   int transitions = 0;
   3248   int null_descriptors = 0;
   3249   if (remove_transitions) {
   3250     for (int i = 0; i < number_of_descriptors(); i++) {
   3251       if (IsTransition(i)) transitions++;
   3252       if (IsNullDescriptor(i)) null_descriptors++;
   3253     }
   3254   } else {
   3255     for (int i = 0; i < number_of_descriptors(); i++) {
   3256       if (IsNullDescriptor(i)) null_descriptors++;
   3257     }
   3258   }
   3259   int new_size = number_of_descriptors() - transitions - null_descriptors;
   3260 
   3261   // If key is in descriptor, we replace it in-place when filtering.
   3262   // Count a null descriptor for key as inserted, not replaced.
   3263   int index = Search(descriptor->GetKey());
   3264   const bool inserting = (index == kNotFound);
   3265   const bool replacing = !inserting;
   3266   bool keep_enumeration_index = false;
   3267   if (inserting) {
   3268     ++new_size;
   3269   }
   3270   if (replacing) {
   3271     // We are replacing an existing descriptor.  We keep the enumeration
   3272     // index of a visible property.
   3273     PropertyType t = PropertyDetails(GetDetails(index)).type();
   3274     if (t == CONSTANT_FUNCTION ||
   3275         t == FIELD ||
   3276         t == CALLBACKS ||
   3277         t == INTERCEPTOR) {
   3278       keep_enumeration_index = true;
   3279     } else if (remove_transitions) {
   3280      // Replaced descriptor has been counted as removed if it is
   3281      // a transition that will be replaced.  Adjust count in this case.
   3282       ++new_size;
   3283     }
   3284   }
   3285   result = Allocate(new_size);
   3286   if (result->IsFailure()) return result;
   3287   DescriptorArray* new_descriptors = DescriptorArray::cast(result);
   3288   // Set the enumeration index in the descriptors and set the enumeration index
   3289   // in the result.
   3290   int enumeration_index = NextEnumerationIndex();
   3291   if (!descriptor->GetDetails().IsTransition()) {
   3292     if (keep_enumeration_index) {
   3293       descriptor->SetEnumerationIndex(
   3294           PropertyDetails(GetDetails(index)).index());
   3295     } else {
   3296       descriptor->SetEnumerationIndex(enumeration_index);
   3297       ++enumeration_index;
   3298     }
   3299   }
   3300   new_descriptors->SetNextEnumerationIndex(enumeration_index);
   3301 
   3302   // Copy the descriptors, filtering out transitions and null descriptors,
   3303   // and inserting or replacing a descriptor.
   3304   uint32_t descriptor_hash = descriptor->GetKey()->Hash();
   3305   int from_index = 0;
   3306   int to_index = 0;
   3307 
   3308   for (; from_index < number_of_descriptors(); from_index++) {
   3309     String* key = GetKey(from_index);
   3310     if (key->Hash() > descriptor_hash || key == descriptor->GetKey()) {
   3311       break;
   3312     }
   3313     if (IsNullDescriptor(from_index)) continue;
   3314     if (remove_transitions && IsTransition(from_index)) continue;
   3315     new_descriptors->CopyFrom(to_index++, this, from_index);
   3316   }
   3317 
   3318   new_descriptors->Set(to_index++, descriptor);
   3319   if (replacing) from_index++;
   3320 
   3321   for (; from_index < number_of_descriptors(); from_index++) {
   3322     if (IsNullDescriptor(from_index)) continue;
   3323     if (remove_transitions && IsTransition(from_index)) continue;
   3324     new_descriptors->CopyFrom(to_index++, this, from_index);
   3325   }
   3326 
   3327   ASSERT(to_index == new_descriptors->number_of_descriptors());
   3328   SLOW_ASSERT(new_descriptors->IsSortedNoDuplicates());
   3329 
   3330   return new_descriptors;
   3331 }
   3332 
   3333 
   3334 Object* DescriptorArray::RemoveTransitions() {
   3335   // Remove all transitions and null descriptors. Return a copy of the array
   3336   // with all transitions removed, or a Failure object if the new array could
   3337   // not be allocated.
   3338 
   3339   // Compute the size of the map transition entries to be removed.
   3340   int num_removed = 0;
   3341   for (int i = 0; i < number_of_descriptors(); i++) {
   3342     if (!IsProperty(i)) num_removed++;
   3343   }
   3344 
   3345   // Allocate the new descriptor array.
   3346   Object* result = Allocate(number_of_descriptors() - num_removed);
   3347   if (result->IsFailure()) return result;
   3348   DescriptorArray* new_descriptors = DescriptorArray::cast(result);
   3349 
   3350   // Copy the content.
   3351   int next_descriptor = 0;
   3352   for (int i = 0; i < number_of_descriptors(); i++) {
   3353     if (IsProperty(i)) new_descriptors->CopyFrom(next_descriptor++, this, i);
   3354   }
   3355   ASSERT(next_descriptor == new_descriptors->number_of_descriptors());
   3356 
   3357   return new_descriptors;
   3358 }
   3359 
   3360 
   3361 void DescriptorArray::Sort() {
   3362   // In-place heap sort.
   3363   int len = number_of_descriptors();
   3364 
   3365   // Bottom-up max-heap construction.
   3366   for (int i = 1; i < len; ++i) {
   3367     int child_index = i;
   3368     while (child_index > 0) {
   3369       int parent_index = ((child_index + 1) >> 1) - 1;
   3370       uint32_t parent_hash = GetKey(parent_index)->Hash();
   3371       uint32_t child_hash = GetKey(child_index)->Hash();
   3372       if (parent_hash < child_hash) {
   3373         Swap(parent_index, child_index);
   3374       } else {
   3375         break;
   3376       }
   3377       child_index = parent_index;
   3378     }
   3379   }
   3380 
   3381   // Extract elements and create sorted array.
   3382   for (int i = len - 1; i > 0; --i) {
   3383     // Put max element at the back of the array.
   3384     Swap(0, i);
   3385     // Sift down the new top element.
   3386     int parent_index = 0;
   3387     while (true) {
   3388       int child_index = ((parent_index + 1) << 1) - 1;
   3389       if (child_index >= i) break;
   3390       uint32_t child1_hash = GetKey(child_index)->Hash();
   3391       uint32_t child2_hash = GetKey(child_index + 1)->Hash();
   3392       uint32_t parent_hash = GetKey(parent_index)->Hash();
   3393       if (child_index + 1 >= i || child1_hash > child2_hash) {
   3394         if (parent_hash > child1_hash) break;
   3395         Swap(parent_index, child_index);
   3396         parent_index = child_index;
   3397       } else {
   3398         if (parent_hash > child2_hash) break;
   3399         Swap(parent_index, child_index + 1);
   3400         parent_index = child_index + 1;
   3401       }
   3402     }
   3403   }
   3404 
   3405   SLOW_ASSERT(IsSortedNoDuplicates());
   3406 }
   3407 
   3408 
   3409 int DescriptorArray::BinarySearch(String* name, int low, int high) {
   3410   uint32_t hash = name->Hash();
   3411 
   3412   while (low <= high) {
   3413     int mid = (low + high) / 2;
   3414     String* mid_name = GetKey(mid);
   3415     uint32_t mid_hash = mid_name->Hash();
   3416 
   3417     if (mid_hash > hash) {
   3418       high = mid - 1;
   3419       continue;
   3420     }
   3421     if (mid_hash < hash) {
   3422       low = mid + 1;
   3423       continue;
   3424     }
   3425     // Found an element with the same hash-code.
   3426     ASSERT(hash == mid_hash);
   3427     // There might be more, so we find the first one and
   3428     // check them all to see if we have a match.
   3429     if (name == mid_name  && !is_null_descriptor(mid)) return mid;
   3430     while ((mid > low) && (GetKey(mid - 1)->Hash() == hash)) mid--;
   3431     for (; (mid <= high) && (GetKey(mid)->Hash() == hash); mid++) {
   3432       if (GetKey(mid)->Equals(name) && !is_null_descriptor(mid)) return mid;
   3433     }
   3434     break;
   3435   }
   3436   return kNotFound;
   3437 }
   3438 
   3439 
   3440 int DescriptorArray::LinearSearch(String* name, int len) {
   3441   uint32_t hash = name->Hash();
   3442   for (int number = 0; number < len; number++) {
   3443     String* entry = GetKey(number);
   3444     if ((entry->Hash() == hash) &&
   3445         name->Equals(entry) &&
   3446         !is_null_descriptor(number)) {
   3447       return number;
   3448     }
   3449   }
   3450   return kNotFound;
   3451 }
   3452 
   3453 
   3454 #ifdef DEBUG
   3455 bool DescriptorArray::IsEqualTo(DescriptorArray* other) {
   3456   if (IsEmpty()) return other->IsEmpty();
   3457   if (other->IsEmpty()) return false;
   3458   if (length() != other->length()) return false;
   3459   for (int i = 0; i < length(); ++i) {
   3460     if (get(i) != other->get(i) && i != kContentArrayIndex) return false;
   3461   }
   3462   return GetContentArray()->IsEqualTo(other->GetContentArray());
   3463 }
   3464 #endif
   3465 
   3466 
   3467 static StaticResource<StringInputBuffer> string_input_buffer;
   3468 
   3469 
   3470 bool String::LooksValid() {
   3471   if (!Heap::Contains(this)) return false;
   3472   return true;
   3473 }
   3474 
   3475 
   3476 int String::Utf8Length() {
   3477   if (IsAsciiRepresentation()) return length();
   3478   // Attempt to flatten before accessing the string.  It probably
   3479   // doesn't make Utf8Length faster, but it is very likely that
   3480   // the string will be accessed later (for example by WriteUtf8)
   3481   // so it's still a good idea.
   3482   TryFlattenIfNotFlat();
   3483   Access<StringInputBuffer> buffer(&string_input_buffer);
   3484   buffer->Reset(0, this);
   3485   int result = 0;
   3486   while (buffer->has_more())
   3487     result += unibrow::Utf8::Length(buffer->GetNext());
   3488   return result;
   3489 }
   3490 
   3491 
   3492 Vector<const char> String::ToAsciiVector() {
   3493   ASSERT(IsAsciiRepresentation());
   3494   ASSERT(IsFlat());
   3495 
   3496   int offset = 0;
   3497   int length = this->length();
   3498   StringRepresentationTag string_tag = StringShape(this).representation_tag();
   3499   String* string = this;
   3500   if (string_tag == kConsStringTag) {
   3501     ConsString* cons = ConsString::cast(string);
   3502     ASSERT(cons->second()->length() == 0);
   3503     string = cons->first();
   3504     string_tag = StringShape(string).representation_tag();
   3505   }
   3506   if (string_tag == kSeqStringTag) {
   3507     SeqAsciiString* seq = SeqAsciiString::cast(string);
   3508     char* start = seq->GetChars();
   3509     return Vector<const char>(start + offset, length);
   3510   }
   3511   ASSERT(string_tag == kExternalStringTag);
   3512   ExternalAsciiString* ext = ExternalAsciiString::cast(string);
   3513   const char* start = ext->resource()->data();
   3514   return Vector<const char>(start + offset, length);
   3515 }
   3516 
   3517 
   3518 Vector<const uc16> String::ToUC16Vector() {
   3519   ASSERT(IsTwoByteRepresentation());
   3520   ASSERT(IsFlat());
   3521 
   3522   int offset = 0;
   3523   int length = this->length();
   3524   StringRepresentationTag string_tag = StringShape(this).representation_tag();
   3525   String* string = this;
   3526   if (string_tag == kConsStringTag) {
   3527     ConsString* cons = ConsString::cast(string);
   3528     ASSERT(cons->second()->length() == 0);
   3529     string = cons->first();
   3530     string_tag = StringShape(string).representation_tag();
   3531   }
   3532   if (string_tag == kSeqStringTag) {
   3533     SeqTwoByteString* seq = SeqTwoByteString::cast(string);
   3534     return Vector<const uc16>(seq->GetChars() + offset, length);
   3535   }
   3536   ASSERT(string_tag == kExternalStringTag);
   3537   ExternalTwoByteString* ext = ExternalTwoByteString::cast(string);
   3538   const uc16* start =
   3539       reinterpret_cast<const uc16*>(ext->resource()->data());
   3540   return Vector<const uc16>(start + offset, length);
   3541 }
   3542 
   3543 
   3544 SmartPointer<char> String::ToCString(AllowNullsFlag allow_nulls,
   3545                                      RobustnessFlag robust_flag,
   3546                                      int offset,
   3547                                      int length,
   3548                                      int* length_return) {
   3549   ASSERT(NativeAllocationChecker::allocation_allowed());
   3550   if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) {
   3551     return SmartPointer<char>(NULL);
   3552   }
   3553 
   3554   // Negative length means the to the end of the string.
   3555   if (length < 0) length = kMaxInt - offset;
   3556 
   3557   // Compute the size of the UTF-8 string. Start at the specified offset.
   3558   Access<StringInputBuffer> buffer(&string_input_buffer);
   3559   buffer->Reset(offset, this);
   3560   int character_position = offset;
   3561   int utf8_bytes = 0;
   3562   while (buffer->has_more()) {
   3563     uint16_t character = buffer->GetNext();
   3564     if (character_position < offset + length) {
   3565       utf8_bytes += unibrow::Utf8::Length(character);
   3566     }
   3567     character_position++;
   3568   }
   3569 
   3570   if (length_return) {
   3571     *length_return = utf8_bytes;
   3572   }
   3573 
   3574   char* result = NewArray<char>(utf8_bytes + 1);
   3575 
   3576   // Convert the UTF-16 string to a UTF-8 buffer. Start at the specified offset.
   3577   buffer->Rewind();
   3578   buffer->Seek(offset);
   3579   character_position = offset;
   3580   int utf8_byte_position = 0;
   3581   while (buffer->has_more()) {
   3582     uint16_t character = buffer->GetNext();
   3583     if (character_position < offset + length) {
   3584       if (allow_nulls == DISALLOW_NULLS && character == 0) {
   3585         character = ' ';
   3586       }
   3587       utf8_byte_position +=
   3588           unibrow::Utf8::Encode(result + utf8_byte_position, character);
   3589     }
   3590     character_position++;
   3591   }
   3592   result[utf8_byte_position] = 0;
   3593   return SmartPointer<char>(result);
   3594 }
   3595 
   3596 
   3597 SmartPointer<char> String::ToCString(AllowNullsFlag allow_nulls,
   3598                                      RobustnessFlag robust_flag,
   3599                                      int* length_return) {
   3600   return ToCString(allow_nulls, robust_flag, 0, -1, length_return);
   3601 }
   3602 
   3603 
   3604 const uc16* String::GetTwoByteData() {
   3605   return GetTwoByteData(0);
   3606 }
   3607 
   3608 
   3609 const uc16* String::GetTwoByteData(unsigned start) {
   3610   ASSERT(!IsAsciiRepresentation());
   3611   switch (StringShape(this).representation_tag()) {
   3612     case kSeqStringTag:
   3613       return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start);
   3614     case kExternalStringTag:
   3615       return ExternalTwoByteString::cast(this)->
   3616         ExternalTwoByteStringGetData(start);
   3617     case kConsStringTag:
   3618       UNREACHABLE();
   3619       return NULL;
   3620   }
   3621   UNREACHABLE();
   3622   return NULL;
   3623 }
   3624 
   3625 
   3626 SmartPointer<uc16> String::ToWideCString(RobustnessFlag robust_flag) {
   3627   ASSERT(NativeAllocationChecker::allocation_allowed());
   3628 
   3629   if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) {
   3630     return SmartPointer<uc16>();
   3631   }
   3632 
   3633   Access<StringInputBuffer> buffer(&string_input_buffer);
   3634   buffer->Reset(this);
   3635 
   3636   uc16* result = NewArray<uc16>(length() + 1);
   3637 
   3638   int i = 0;
   3639   while (buffer->has_more()) {
   3640     uint16_t character = buffer->GetNext();
   3641     result[i++] = character;
   3642   }
   3643   result[i] = 0;
   3644   return SmartPointer<uc16>(result);
   3645 }
   3646 
   3647 
   3648 const uc16* SeqTwoByteString::SeqTwoByteStringGetData(unsigned start) {
   3649   return reinterpret_cast<uc16*>(
   3650       reinterpret_cast<char*>(this) - kHeapObjectTag + kHeaderSize) + start;
   3651 }
   3652 
   3653 
   3654 void SeqTwoByteString::SeqTwoByteStringReadBlockIntoBuffer(ReadBlockBuffer* rbb,
   3655                                                            unsigned* offset_ptr,
   3656                                                            unsigned max_chars) {
   3657   unsigned chars_read = 0;
   3658   unsigned offset = *offset_ptr;
   3659   while (chars_read < max_chars) {
   3660     uint16_t c = *reinterpret_cast<uint16_t*>(
   3661         reinterpret_cast<char*>(this) -
   3662             kHeapObjectTag + kHeaderSize + offset * kShortSize);
   3663     if (c <= kMaxAsciiCharCode) {
   3664       // Fast case for ASCII characters.   Cursor is an input output argument.
   3665       if (!unibrow::CharacterStream::EncodeAsciiCharacter(c,
   3666                                                           rbb->util_buffer,
   3667                                                           rbb->capacity,
   3668                                                           rbb->cursor)) {
   3669         break;
   3670       }
   3671     } else {
   3672       if (!unibrow::CharacterStream::EncodeNonAsciiCharacter(c,
   3673                                                              rbb->util_buffer,
   3674                                                              rbb->capacity,
   3675                                                              rbb->cursor)) {
   3676         break;
   3677       }
   3678     }
   3679     offset++;
   3680     chars_read++;
   3681   }
   3682   *offset_ptr = offset;
   3683   rbb->remaining += chars_read;
   3684 }
   3685 
   3686 
   3687 const unibrow::byte* SeqAsciiString::SeqAsciiStringReadBlock(
   3688     unsigned* remaining,
   3689     unsigned* offset_ptr,
   3690     unsigned max_chars) {
   3691   const unibrow::byte* b = reinterpret_cast<unibrow::byte*>(this) -
   3692       kHeapObjectTag + kHeaderSize + *offset_ptr * kCharSize;
   3693   *remaining = max_chars;
   3694   *offset_ptr += max_chars;
   3695   return b;
   3696 }
   3697 
   3698 
   3699 // This will iterate unless the block of string data spans two 'halves' of
   3700 // a ConsString, in which case it will recurse.  Since the block of string
   3701 // data to be read has a maximum size this limits the maximum recursion
   3702 // depth to something sane.  Since C++ does not have tail call recursion
   3703 // elimination, the iteration must be explicit. Since this is not an
   3704 // -IntoBuffer method it can delegate to one of the efficient
   3705 // *AsciiStringReadBlock routines.
   3706 const unibrow::byte* ConsString::ConsStringReadBlock(ReadBlockBuffer* rbb,
   3707                                                      unsigned* offset_ptr,
   3708                                                      unsigned max_chars) {
   3709   ConsString* current = this;
   3710   unsigned offset = *offset_ptr;
   3711   int offset_correction = 0;
   3712 
   3713   while (true) {
   3714     String* left = current->first();
   3715     unsigned left_length = (unsigned)left->length();
   3716     if (left_length > offset &&
   3717         (max_chars <= left_length - offset ||
   3718          (rbb->capacity <= left_length - offset &&
   3719           (max_chars = left_length - offset, true)))) {  // comma operator!
   3720       // Left hand side only - iterate unless we have reached the bottom of
   3721       // the cons tree.  The assignment on the left of the comma operator is
   3722       // in order to make use of the fact that the -IntoBuffer routines can
   3723       // produce at most 'capacity' characters.  This enables us to postpone
   3724       // the point where we switch to the -IntoBuffer routines (below) in order
   3725       // to maximize the chances of delegating a big chunk of work to the
   3726       // efficient *AsciiStringReadBlock routines.
   3727       if (StringShape(left).IsCons()) {
   3728         current = ConsString::cast(left);
   3729         continue;
   3730       } else {
   3731         const unibrow::byte* answer =
   3732             String::ReadBlock(left, rbb, &offset, max_chars);
   3733         *offset_ptr = offset + offset_correction;
   3734         return answer;
   3735       }
   3736     } else if (left_length <= offset) {
   3737       // Right hand side only - iterate unless we have reached the bottom of
   3738       // the cons tree.
   3739       String* right = current->second();
   3740       offset -= left_length;
   3741       offset_correction += left_length;
   3742       if (StringShape(right).IsCons()) {
   3743         current = ConsString::cast(right);
   3744         continue;
   3745       } else {
   3746         const unibrow::byte* answer =
   3747             String::ReadBlock(right, rbb, &offset, max_chars);
   3748         *offset_ptr = offset + offset_correction;
   3749         return answer;
   3750       }
   3751     } else {
   3752       // The block to be read spans two sides of the ConsString, so we call the
   3753       // -IntoBuffer version, which will recurse.  The -IntoBuffer methods
   3754       // are able to assemble data from several part strings because they use
   3755       // the util_buffer to store their data and never return direct pointers
   3756       // to their storage.  We don't try to read more than the buffer capacity
   3757       // here or we can get too much recursion.
   3758       ASSERT(rbb->remaining == 0);
   3759       ASSERT(rbb->cursor == 0);
   3760       current->ConsStringReadBlockIntoBuffer(
   3761           rbb,
   3762           &offset,
   3763           max_chars > rbb->capacity ? rbb->capacity : max_chars);
   3764       *offset_ptr = offset + offset_correction;
   3765       return rbb->util_buffer;
   3766     }
   3767   }
   3768 }
   3769 
   3770 
   3771 uint16_t ExternalAsciiString::ExternalAsciiStringGet(int index) {
   3772   ASSERT(index >= 0 && index < length());
   3773   return resource()->data()[index];
   3774 }
   3775 
   3776 
   3777 const unibrow::byte* ExternalAsciiString::ExternalAsciiStringReadBlock(
   3778       unsigned* remaining,
   3779       unsigned* offset_ptr,
   3780       unsigned max_chars) {
   3781   // Cast const char* to unibrow::byte* (signedness difference).
   3782   const unibrow::byte* b =
   3783       reinterpret_cast<const unibrow::byte*>(resource()->data()) + *offset_ptr;
   3784   *remaining = max_chars;
   3785   *offset_ptr += max_chars;
   3786   return b;
   3787 }
   3788 
   3789 
   3790 const uc16* ExternalTwoByteString::ExternalTwoByteStringGetData(
   3791       unsigned start) {
   3792   return resource()->data() + start;
   3793 }
   3794 
   3795 
   3796 uint16_t ExternalTwoByteString::ExternalTwoByteStringGet(int index) {
   3797   ASSERT(index >= 0 && index < length());
   3798   return resource()->data()[index];
   3799 }
   3800 
   3801 
   3802 void ExternalTwoByteString::ExternalTwoByteStringReadBlockIntoBuffer(
   3803       ReadBlockBuffer* rbb,
   3804       unsigned* offset_ptr,
   3805       unsigned max_chars) {
   3806   unsigned chars_read = 0;
   3807   unsigned offset = *offset_ptr;
   3808   const uint16_t* data = resource()->data();
   3809   while (chars_read < max_chars) {
   3810     uint16_t c = data[offset];
   3811     if (c <= kMaxAsciiCharCode) {
   3812       // Fast case for ASCII characters. Cursor is an input output argument.
   3813       if (!unibrow::CharacterStream::EncodeAsciiCharacter(c,
   3814                                                           rbb->util_buffer,
   3815                                                           rbb->capacity,
   3816                                                           rbb->cursor))
   3817         break;
   3818     } else {
   3819       if (!unibrow::CharacterStream::EncodeNonAsciiCharacter(c,
   3820                                                              rbb->util_buffer,
   3821                                                              rbb->capacity,
   3822                                                              rbb->cursor))
   3823         break;
   3824     }
   3825     offset++;
   3826     chars_read++;
   3827   }
   3828   *offset_ptr = offset;
   3829   rbb->remaining += chars_read;
   3830 }
   3831 
   3832 
   3833 void SeqAsciiString::SeqAsciiStringReadBlockIntoBuffer(ReadBlockBuffer* rbb,
   3834                                                  unsigned* offset_ptr,
   3835                                                  unsigned max_chars) {
   3836   unsigned capacity = rbb->capacity - rbb->cursor;
   3837   if (max_chars > capacity) max_chars = capacity;
   3838   memcpy(rbb->util_buffer + rbb->cursor,
   3839          reinterpret_cast<char*>(this) - kHeapObjectTag + kHeaderSize +
   3840              *offset_ptr * kCharSize,
   3841          max_chars);
   3842   rbb->remaining += max_chars;
   3843   *offset_ptr += max_chars;
   3844   rbb->cursor += max_chars;
   3845 }
   3846 
   3847 
   3848 void ExternalAsciiString::ExternalAsciiStringReadBlockIntoBuffer(
   3849       ReadBlockBuffer* rbb,
   3850       unsigned* offset_ptr,
   3851       unsigned max_chars) {
   3852   unsigned capacity = rbb->capacity - rbb->cursor;
   3853   if (max_chars > capacity) max_chars = capacity;
   3854   memcpy(rbb->util_buffer + rbb->cursor,
   3855          resource()->data() + *offset_ptr,
   3856          max_chars);
   3857   rbb->remaining += max_chars;
   3858   *offset_ptr += max_chars;
   3859   rbb->cursor += max_chars;
   3860 }
   3861 
   3862 
   3863 // This method determines the type of string involved and then copies
   3864 // a whole chunk of characters into a buffer, or returns a pointer to a buffer
   3865 // where they can be found.  The pointer is not necessarily valid across a GC
   3866 // (see AsciiStringReadBlock).
   3867 const unibrow::byte* String::ReadBlock(String* input,
   3868                                        ReadBlockBuffer* rbb,
   3869                                        unsigned* offset_ptr,
   3870                                        unsigned max_chars) {
   3871   ASSERT(*offset_ptr <= static_cast<unsigned>(input->length()));
   3872   if (max_chars == 0) {
   3873     rbb->remaining = 0;
   3874     return NULL;
   3875   }
   3876   switch (StringShape(input).representation_tag()) {
   3877     case kSeqStringTag:
   3878       if (input->IsAsciiRepresentation()) {
   3879         SeqAsciiString* str = SeqAsciiString::cast(input);
   3880         return str->SeqAsciiStringReadBlock(&rbb->remaining,
   3881                                             offset_ptr,
   3882                                             max_chars);
   3883       } else {
   3884         SeqTwoByteString* str = SeqTwoByteString::cast(input);
   3885         str->SeqTwoByteStringReadBlockIntoBuffer(rbb,
   3886                                                  offset_ptr,
   3887                                                  max_chars);
   3888         return rbb->util_buffer;
   3889       }
   3890     case kConsStringTag:
   3891       return ConsString::cast(input)->ConsStringReadBlock(rbb,
   3892                                                           offset_ptr,
   3893                                                           max_chars);
   3894     case kExternalStringTag:
   3895       if (input->IsAsciiRepresentation()) {
   3896         return ExternalAsciiString::cast(input)->ExternalAsciiStringReadBlock(
   3897             &rbb->remaining,
   3898             offset_ptr,
   3899             max_chars);
   3900       } else {
   3901         ExternalTwoByteString::cast(input)->
   3902             ExternalTwoByteStringReadBlockIntoBuffer(rbb,
   3903                                                      offset_ptr,
   3904                                                      max_chars);
   3905         return rbb->util_buffer;
   3906       }
   3907     default:
   3908       break;
   3909   }
   3910 
   3911   UNREACHABLE();
   3912   return 0;
   3913 }
   3914 
   3915 
   3916 Relocatable* Relocatable::top_ = NULL;
   3917 
   3918 
   3919 void Relocatable::PostGarbageCollectionProcessing() {
   3920   Relocatable* current = top_;
   3921   while (current != NULL) {
   3922     current->PostGarbageCollection();
   3923     current = current->prev_;
   3924   }
   3925 }
   3926 
   3927 
   3928 // Reserve space for statics needing saving and restoring.
   3929 int Relocatable::ArchiveSpacePerThread() {
   3930   return sizeof(top_);
   3931 }
   3932 
   3933 
   3934 // Archive statics that are thread local.
   3935 char* Relocatable::ArchiveState(char* to) {
   3936   *reinterpret_cast<Relocatable**>(to) = top_;
   3937   top_ = NULL;
   3938   return to + ArchiveSpacePerThread();
   3939 }
   3940 
   3941 
   3942 // Restore statics that are thread local.
   3943 char* Relocatable::RestoreState(char* from) {
   3944   top_ = *reinterpret_cast<Relocatable**>(from);
   3945   return from + ArchiveSpacePerThread();
   3946 }
   3947 
   3948 
   3949 char* Relocatable::Iterate(ObjectVisitor* v, char* thread_storage) {
   3950   Relocatable* top = *reinterpret_cast<Relocatable**>(thread_storage);
   3951   Iterate(v, top);
   3952   return thread_storage + ArchiveSpacePerThread();
   3953 }
   3954 
   3955 
   3956 void Relocatable::Iterate(ObjectVisitor* v) {
   3957   Iterate(v, top_);
   3958 }
   3959 
   3960 
   3961 void Relocatable::Iterate(ObjectVisitor* v, Relocatable* top) {
   3962   Relocatable* current = top;
   3963   while (current != NULL) {
   3964     current->IterateInstance(v);
   3965     current = current->prev_;
   3966   }
   3967 }
   3968 
   3969 
   3970 FlatStringReader::FlatStringReader(Handle<String> str)
   3971     : str_(str.location()),
   3972       length_(str->length()) {
   3973   PostGarbageCollection();
   3974 }
   3975 
   3976 
   3977 FlatStringReader::FlatStringReader(Vector<const char> input)
   3978     : str_(0),
   3979       is_ascii_(true),
   3980       length_(input.length()),
   3981       start_(input.start()) { }
   3982 
   3983 
   3984 void FlatStringReader::PostGarbageCollection() {
   3985   if (str_ == NULL) return;
   3986   Handle<String> str(str_);
   3987   ASSERT(str->IsFlat());
   3988   is_ascii_ = str->IsAsciiRepresentation();
   3989   if (is_ascii_) {
   3990     start_ = str->ToAsciiVector().start();
   3991   } else {
   3992     start_ = str->ToUC16Vector().start();
   3993   }
   3994 }
   3995 
   3996 
   3997 void StringInputBuffer::Seek(unsigned pos) {
   3998   Reset(pos, input_);
   3999 }
   4000 
   4001 
   4002 void SafeStringInputBuffer::Seek(unsigned pos) {
   4003   Reset(pos, input_);
   4004 }
   4005 
   4006 
   4007 // This method determines the type of string involved and then copies
   4008 // a whole chunk of characters into a buffer.  It can be used with strings
   4009 // that have been glued together to form a ConsString and which must cooperate
   4010 // to fill up a buffer.
   4011 void String::ReadBlockIntoBuffer(String* input,
   4012                                  ReadBlockBuffer* rbb,
   4013                                  unsigned* offset_ptr,
   4014                                  unsigned max_chars) {
   4015   ASSERT(*offset_ptr <= (unsigned)input->length());
   4016   if (max_chars == 0) return;
   4017 
   4018   switch (StringShape(input).representation_tag()) {
   4019     case kSeqStringTag:
   4020       if (input->IsAsciiRepresentation()) {
   4021         SeqAsciiString::cast(input)->SeqAsciiStringReadBlockIntoBuffer(rbb,
   4022                                                                  offset_ptr,
   4023                                                                  max_chars);
   4024         return;
   4025       } else {
   4026         SeqTwoByteString::cast(input)->SeqTwoByteStringReadBlockIntoBuffer(rbb,
   4027                                                                      offset_ptr,
   4028                                                                      max_chars);
   4029         return;
   4030       }
   4031     case kConsStringTag:
   4032       ConsString::cast(input)->ConsStringReadBlockIntoBuffer(rbb,
   4033                                                              offset_ptr,
   4034                                                              max_chars);
   4035       return;
   4036     case kExternalStringTag:
   4037       if (input->IsAsciiRepresentation()) {
   4038         ExternalAsciiString::cast(input)->
   4039             ExternalAsciiStringReadBlockIntoBuffer(rbb, offset_ptr, max_chars);
   4040       } else {
   4041         ExternalTwoByteString::cast(input)->
   4042             ExternalTwoByteStringReadBlockIntoBuffer(rbb,
   4043                                                      offset_ptr,
   4044                                                      max_chars);
   4045        }
   4046        return;
   4047     default:
   4048       break;
   4049   }
   4050 
   4051   UNREACHABLE();
   4052   return;
   4053 }
   4054 
   4055 
   4056 const unibrow::byte* String::ReadBlock(String* input,
   4057                                        unibrow::byte* util_buffer,
   4058                                        unsigned capacity,
   4059                                        unsigned* remaining,
   4060                                        unsigned* offset_ptr) {
   4061   ASSERT(*offset_ptr <= (unsigned)input->length());
   4062   unsigned chars = input->length() - *offset_ptr;
   4063   ReadBlockBuffer rbb(util_buffer, 0, capacity, 0);
   4064   const unibrow::byte* answer = ReadBlock(input, &rbb, offset_ptr, chars);
   4065   ASSERT(rbb.remaining <= static_cast<unsigned>(input->length()));
   4066   *remaining = rbb.remaining;
   4067   return answer;
   4068 }
   4069 
   4070 
   4071 const unibrow::byte* String::ReadBlock(String** raw_input,
   4072                                        unibrow::byte* util_buffer,
   4073                                        unsigned capacity,
   4074                                        unsigned* remaining,
   4075                                        unsigned* offset_ptr) {
   4076   Handle<String> input(raw_input);
   4077   ASSERT(*offset_ptr <= (unsigned)input->length());
   4078   unsigned chars = input->length() - *offset_ptr;
   4079   if (chars > capacity) chars = capacity;
   4080   ReadBlockBuffer rbb(util_buffer, 0, capacity, 0);
   4081   ReadBlockIntoBuffer(*input, &rbb, offset_ptr, chars);
   4082   ASSERT(rbb.remaining <= static_cast<unsigned>(input->length()));
   4083   *remaining = rbb.remaining;
   4084   return rbb.util_buffer;
   4085 }
   4086 
   4087 
   4088 // This will iterate unless the block of string data spans two 'halves' of
   4089 // a ConsString, in which case it will recurse.  Since the block of string
   4090 // data to be read has a maximum size this limits the maximum recursion
   4091 // depth to something sane.  Since C++ does not have tail call recursion
   4092 // elimination, the iteration must be explicit.
   4093 void ConsString::ConsStringReadBlockIntoBuffer(ReadBlockBuffer* rbb,
   4094                                                unsigned* offset_ptr,
   4095                                                unsigned max_chars) {
   4096   ConsString* current = this;
   4097   unsigned offset = *offset_ptr;
   4098   int offset_correction = 0;
   4099 
   4100   while (true) {
   4101     String* left = current->first();
   4102     unsigned left_length = (unsigned)left->length();
   4103     if (left_length > offset &&
   4104       max_chars <= left_length - offset) {
   4105       // Left hand side only - iterate unless we have reached the bottom of
   4106       // the cons tree.
   4107       if (StringShape(left).IsCons()) {
   4108         current = ConsString::cast(left);
   4109         continue;
   4110       } else {
   4111         String::ReadBlockIntoBuffer(left, rbb, &offset, max_chars);
   4112         *offset_ptr = offset + offset_correction;
   4113         return;
   4114       }
   4115     } else if (left_length <= offset) {
   4116       // Right hand side only - iterate unless we have reached the bottom of
   4117       // the cons tree.
   4118       offset -= left_length;
   4119       offset_correction += left_length;
   4120       String* right = current->second();
   4121       if (StringShape(right).IsCons()) {
   4122         current = ConsString::cast(right);
   4123         continue;
   4124       } else {
   4125         String::ReadBlockIntoBuffer(right, rbb, &offset, max_chars);
   4126         *offset_ptr = offset + offset_correction;
   4127         return;
   4128       }
   4129     } else {
   4130       // The block to be read spans two sides of the ConsString, so we recurse.
   4131       // First recurse on the left.
   4132       max_chars -= left_length - offset;
   4133       String::ReadBlockIntoBuffer(left, rbb, &offset, left_length - offset);
   4134       // We may have reached the max or there may not have been enough space
   4135       // in the buffer for the characters in the left hand side.
   4136       if (offset == left_length) {
   4137         // Recurse on the right.
   4138         String* right = String::cast(current->second());
   4139         offset -= left_length;
   4140         offset_correction += left_length;
   4141         String::ReadBlockIntoBuffer(right, rbb, &offset, max_chars);
   4142       }
   4143       *offset_ptr = offset + offset_correction;
   4144       return;
   4145     }
   4146   }
   4147 }
   4148 
   4149 
   4150 void ConsString::ConsStringIterateBody(ObjectVisitor* v) {
   4151   IteratePointers(v, kFirstOffset, kSecondOffset + kPointerSize);
   4152 }
   4153 
   4154 
   4155 void JSGlobalPropertyCell::JSGlobalPropertyCellIterateBody(ObjectVisitor* v) {
   4156   IteratePointers(v, kValueOffset, kValueOffset + kPointerSize);
   4157 }
   4158 
   4159 
   4160 uint16_t ConsString::ConsStringGet(int index) {
   4161   ASSERT(index >= 0 && index < this->length());
   4162 
   4163   // Check for a flattened cons string
   4164   if (second()->length() == 0) {
   4165     String* left = first();
   4166     return left->Get(index);
   4167   }
   4168 
   4169   String* string = String::cast(this);
   4170 
   4171   while (true) {
   4172     if (StringShape(string).IsCons()) {
   4173       ConsString* cons_string = ConsString::cast(string);
   4174       String* left = cons_string->first();
   4175       if (left->length() > index) {
   4176         string = left;
   4177       } else {
   4178         index -= left->length();
   4179         string = cons_string->second();
   4180       }
   4181     } else {
   4182       return string->Get(index);
   4183     }
   4184   }
   4185 
   4186   UNREACHABLE();
   4187   return 0;
   4188 }
   4189 
   4190 
   4191 template <typename sinkchar>
   4192 void String::WriteToFlat(String* src,
   4193                          sinkchar* sink,
   4194                          int f,
   4195                          int t) {
   4196   String* source = src;
   4197   int from = f;
   4198   int to = t;
   4199   while (true) {
   4200     ASSERT(0 <= from && from <= to && to <= source->length());
   4201     switch (StringShape(source).full_representation_tag()) {
   4202       case kAsciiStringTag | kExternalStringTag: {
   4203         CopyChars(sink,
   4204                   ExternalAsciiString::cast(source)->resource()->data() + from,
   4205                   to - from);
   4206         return;
   4207       }
   4208       case kTwoByteStringTag | kExternalStringTag: {
   4209         const uc16* data =
   4210             ExternalTwoByteString::cast(source)->resource()->data();
   4211         CopyChars(sink,
   4212                   data + from,
   4213                   to - from);
   4214         return;
   4215       }
   4216       case kAsciiStringTag | kSeqStringTag: {
   4217         CopyChars(sink,
   4218                   SeqAsciiString::cast(source)->GetChars() + from,
   4219                   to - from);
   4220         return;
   4221       }
   4222       case kTwoByteStringTag | kSeqStringTag: {
   4223         CopyChars(sink,
   4224                   SeqTwoByteString::cast(source)->GetChars() + from,
   4225                   to - from);
   4226         return;
   4227       }
   4228       case kAsciiStringTag | kConsStringTag:
   4229       case kTwoByteStringTag | kConsStringTag: {
   4230         ConsString* cons_string = ConsString::cast(source);
   4231         String* first = cons_string->first();
   4232         int boundary = first->length();
   4233         if (to - boundary >= boundary - from) {
   4234           // Right hand side is longer.  Recurse over left.
   4235           if (from < boundary) {
   4236             WriteToFlat(first, sink, from, boundary);
   4237             sink += boundary - from;
   4238             from = 0;
   4239           } else {
   4240             from -= boundary;
   4241           }
   4242           to -= boundary;
   4243           source = cons_string->second();
   4244         } else {
   4245           // Left hand side is longer.  Recurse over right.
   4246           if (to > boundary) {
   4247             String* second = cons_string->second();
   4248             WriteToFlat(second,
   4249                         sink + boundary - from,
   4250                         0,
   4251                         to - boundary);
   4252             to = boundary;
   4253           }
   4254           source = first;
   4255         }
   4256         break;
   4257       }
   4258     }
   4259   }
   4260 }
   4261 
   4262 
   4263 #define FIELD_ADDR(p, offset) \
   4264   (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag)
   4265 
   4266 void ExternalAsciiString::ExternalAsciiStringIterateBody(ObjectVisitor* v) {
   4267   typedef v8::String::ExternalAsciiStringResource Resource;
   4268   v->VisitExternalAsciiString(
   4269       reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
   4270 }
   4271 
   4272 
   4273 void ExternalTwoByteString::ExternalTwoByteStringIterateBody(ObjectVisitor* v) {
   4274   typedef v8::String::ExternalStringResource Resource;
   4275   v->VisitExternalTwoByteString(
   4276       reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)));
   4277 }
   4278 
   4279 #undef FIELD_ADDR
   4280 
   4281 template <typename IteratorA, typename IteratorB>
   4282 static inline bool CompareStringContents(IteratorA* ia, IteratorB* ib) {
   4283   // General slow case check.  We know that the ia and ib iterators
   4284   // have the same length.
   4285   while (ia->has_more()) {
   4286     uc32 ca = ia->GetNext();
   4287     uc32 cb = ib->GetNext();
   4288     if (ca != cb)
   4289       return false;
   4290   }
   4291   return true;
   4292 }
   4293 
   4294 
   4295 // Compares the contents of two strings by reading and comparing
   4296 // int-sized blocks of characters.
   4297 template <typename Char>
   4298 static inline bool CompareRawStringContents(Vector<Char> a, Vector<Char> b) {
   4299   int length = a.length();
   4300   ASSERT_EQ(length, b.length());
   4301   const Char* pa = a.start();
   4302   const Char* pb = b.start();
   4303   int i = 0;
   4304 #ifndef V8_HOST_CAN_READ_UNALIGNED
   4305   // If this architecture isn't comfortable reading unaligned ints
   4306   // then we have to check that the strings are aligned before
   4307   // comparing them blockwise.
   4308   const int kAlignmentMask = sizeof(uint32_t) - 1;  // NOLINT
   4309   uint32_t pa_addr = reinterpret_cast<uint32_t>(pa);
   4310   uint32_t pb_addr = reinterpret_cast<uint32_t>(pb);
   4311   if (((pa_addr & kAlignmentMask) | (pb_addr & kAlignmentMask)) == 0) {
   4312 #endif
   4313     const int kStepSize = sizeof(int) / sizeof(Char);  // NOLINT
   4314     int endpoint = length - kStepSize;
   4315     // Compare blocks until we reach near the end of the string.
   4316     for (; i <= endpoint; i += kStepSize) {
   4317       uint32_t wa = *reinterpret_cast<const uint32_t*>(pa + i);
   4318       uint32_t wb = *reinterpret_cast<const uint32_t*>(pb + i);
   4319       if (wa != wb) {
   4320         return false;
   4321       }
   4322     }
   4323 #ifndef V8_HOST_CAN_READ_UNALIGNED
   4324   }
   4325 #endif
   4326   // Compare the remaining characters that didn't fit into a block.
   4327   for (; i < length; i++) {
   4328     if (a[i] != b[i]) {
   4329       return false;
   4330     }
   4331   }
   4332   return true;
   4333 }
   4334 
   4335 
   4336 static StringInputBuffer string_compare_buffer_b;
   4337 
   4338 
   4339 template <typename IteratorA>
   4340 static inline bool CompareStringContentsPartial(IteratorA* ia, String* b) {
   4341   if (b->IsFlat()) {
   4342     if (b->IsAsciiRepresentation()) {
   4343       VectorIterator<char> ib(b->ToAsciiVector());
   4344       return CompareStringContents(ia, &ib);
   4345     } else {
   4346       VectorIterator<uc16> ib(b->ToUC16Vector());
   4347       return CompareStringContents(ia, &ib);
   4348     }
   4349   } else {
   4350     string_compare_buffer_b.Reset(0, b);
   4351     return CompareStringContents(ia, &string_compare_buffer_b);
   4352   }
   4353 }
   4354 
   4355 
   4356 static StringInputBuffer string_compare_buffer_a;
   4357 
   4358 
   4359 bool String::SlowEquals(String* other) {
   4360   // Fast check: negative check with lengths.
   4361   int len = length();
   4362   if (len != other->length()) return false;
   4363   if (len == 0) return true;
   4364 
   4365   // Fast check: if hash code is computed for both strings
   4366   // a fast negative check can be performed.
   4367   if (HasHashCode() && other->HasHashCode()) {
   4368     if (Hash() != other->Hash()) return false;
   4369   }
   4370 
   4371   if (StringShape(this).IsSequentialAscii() &&
   4372       StringShape(other).IsSequentialAscii()) {
   4373     const char* str1 = SeqAsciiString::cast(this)->GetChars();
   4374     const char* str2 = SeqAsciiString::cast(other)->GetChars();
   4375     return CompareRawStringContents(Vector<const char>(str1, len),
   4376                                     Vector<const char>(str2, len));
   4377   }
   4378 
   4379   if (this->IsFlat()) {
   4380     if (IsAsciiRepresentation()) {
   4381       Vector<const char> vec1 = this->ToAsciiVector();
   4382       if (other->IsFlat()) {
   4383         if (other->IsAsciiRepresentation()) {
   4384           Vector<const char> vec2 = other->ToAsciiVector();
   4385           return CompareRawStringContents(vec1, vec2);
   4386         } else {
   4387           VectorIterator<char> buf1(vec1);
   4388           VectorIterator<uc16> ib(other->ToUC16Vector());
   4389           return CompareStringContents(&buf1, &ib);
   4390         }
   4391       } else {
   4392         VectorIterator<char> buf1(vec1);
   4393         string_compare_buffer_b.Reset(0, other);
   4394         return CompareStringContents(&buf1, &string_compare_buffer_b);
   4395       }
   4396     } else {
   4397       Vector<const uc16> vec1 = this->ToUC16Vector();
   4398       if (other->IsFlat()) {
   4399         if (other->IsAsciiRepresentation()) {
   4400           VectorIterator<uc16> buf1(vec1);
   4401           VectorIterator<char> ib(other->ToAsciiVector());
   4402           return CompareStringContents(&buf1, &ib);
   4403         } else {
   4404           Vector<const uc16> vec2(other->ToUC16Vector());
   4405           return CompareRawStringContents(vec1, vec2);
   4406         }
   4407       } else {
   4408         VectorIterator<uc16> buf1(vec1);
   4409         string_compare_buffer_b.Reset(0, other);
   4410         return CompareStringContents(&buf1, &string_compare_buffer_b);
   4411       }
   4412     }
   4413   } else {
   4414     string_compare_buffer_a.Reset(0, this);
   4415     return CompareStringContentsPartial(&string_compare_buffer_a, other);
   4416   }
   4417 }
   4418 
   4419 
   4420 bool String::MarkAsUndetectable() {
   4421   if (StringShape(this).IsSymbol()) return false;
   4422 
   4423   Map* map = this->map();
   4424   if (map == Heap::string_map()) {
   4425     this->set_map(Heap::undetectable_string_map());
   4426     return true;
   4427   } else if (map == Heap::ascii_string_map()) {
   4428     this->set_map(Heap::undetectable_ascii_string_map());
   4429     return true;
   4430   }
   4431   // Rest cannot be marked as undetectable
   4432   return false;
   4433 }
   4434 
   4435 
   4436 bool String::IsEqualTo(Vector<const char> str) {
   4437   int slen = length();
   4438   Access<Scanner::Utf8Decoder> decoder(Scanner::utf8_decoder());
   4439   decoder->Reset(str.start(), str.length());
   4440   int i;
   4441   for (i = 0; i < slen && decoder->has_more(); i++) {
   4442     uc32 r = decoder->GetNext();
   4443     if (Get(i) != r) return false;
   4444   }
   4445   return i == slen && !decoder->has_more();
   4446 }
   4447 
   4448 
   4449 uint32_t String::ComputeAndSetHash() {
   4450   // Should only be called if hash code has not yet been computed.
   4451   ASSERT(!(hash_field() & kHashComputedMask));
   4452 
   4453   // Compute the hash code.
   4454   StringInputBuffer buffer(this);
   4455   uint32_t field = ComputeHashField(&buffer, length());
   4456 
   4457   // Store the hash code in the object.
   4458   set_hash_field(field);
   4459 
   4460   // Check the hash code is there.
   4461   ASSERT(hash_field() & kHashComputedMask);
   4462   uint32_t result = field >> kHashShift;
   4463   ASSERT(result != 0);  // Ensure that the hash value of 0 is never computed.
   4464   return result;
   4465 }
   4466 
   4467 
   4468 bool String::ComputeArrayIndex(unibrow::CharacterStream* buffer,
   4469                                uint32_t* index,
   4470                                int length) {
   4471   if (length == 0 || length > kMaxArrayIndexSize) return false;
   4472   uc32 ch = buffer->GetNext();
   4473 
   4474   // If the string begins with a '0' character, it must only consist
   4475   // of it to be a legal array index.
   4476   if (ch == '0') {
   4477     *index = 0;
   4478     return length == 1;
   4479   }
   4480 
   4481   // Convert string to uint32 array index; character by character.
   4482   int d = ch - '0';
   4483   if (d < 0 || d > 9) return false;
   4484   uint32_t result = d;
   4485   while (buffer->has_more()) {
   4486     d = buffer->GetNext() - '0';
   4487     if (d < 0 || d > 9) return false;
   4488     // Check that the new result is below the 32 bit limit.
   4489     if (result > 429496729U - ((d > 5) ? 1 : 0)) return false;
   4490     result = (result * 10) + d;
   4491   }
   4492 
   4493   *index = result;
   4494   return true;
   4495 }
   4496 
   4497 
   4498 bool String::SlowAsArrayIndex(uint32_t* index) {
   4499   if (length() <= kMaxCachedArrayIndexLength) {
   4500     Hash();  // force computation of hash code
   4501     uint32_t field = hash_field();
   4502     if ((field & kIsArrayIndexMask) == 0) return false;
   4503     // Isolate the array index form the full hash field.
   4504     *index = (kArrayIndexHashMask & field) >> kHashShift;
   4505     return true;
   4506   } else {
   4507     StringInputBuffer buffer(this);
   4508     return ComputeArrayIndex(&buffer, index, length());
   4509   }
   4510 }
   4511 
   4512 
   4513 static inline uint32_t HashField(uint32_t hash,
   4514                                  bool is_array_index,
   4515                                  int length = -1) {
   4516   uint32_t result =
   4517       (hash << String::kHashShift) | String::kHashComputedMask;
   4518   if (is_array_index) {
   4519     // For array indexes mix the length into the hash as an array index could
   4520     // be zero.
   4521     ASSERT(length > 0);
   4522     ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) <
   4523            (1 << String::kArrayIndexValueBits));
   4524     result |= String::kIsArrayIndexMask;
   4525     result |= length << String::kArrayIndexHashLengthShift;
   4526   }
   4527   return result;
   4528 }
   4529 
   4530 
   4531 uint32_t StringHasher::GetHashField() {
   4532   ASSERT(is_valid());
   4533   if (length_ <= String::kMaxHashCalcLength) {
   4534     if (is_array_index()) {
   4535       return v8::internal::HashField(array_index(), true, length_);
   4536     } else {
   4537       return v8::internal::HashField(GetHash(), false);
   4538     }
   4539     uint32_t payload = v8::internal::HashField(GetHash(), false);
   4540     return payload;
   4541   } else {
   4542     return v8::internal::HashField(length_, false);
   4543   }
   4544 }
   4545 
   4546 
   4547 uint32_t String::ComputeHashField(unibrow::CharacterStream* buffer,
   4548                                   int length) {
   4549   StringHasher hasher(length);
   4550 
   4551   // Very long strings have a trivial hash that doesn't inspect the
   4552   // string contents.
   4553   if (hasher.has_trivial_hash()) {
   4554     return hasher.GetHashField();
   4555   }
   4556 
   4557   // Do the iterative array index computation as long as there is a
   4558   // chance this is an array index.
   4559   while (buffer->has_more() && hasher.is_array_index()) {
   4560     hasher.AddCharacter(buffer->GetNext());
   4561   }
   4562 
   4563   // Process the remaining characters without updating the array
   4564   // index.
   4565   while (buffer->has_more()) {
   4566     hasher.AddCharacterNoIndex(buffer->GetNext());
   4567   }
   4568 
   4569   return hasher.GetHashField();
   4570 }
   4571 
   4572 
   4573 Object* String::SubString(int start, int end) {
   4574   if (start == 0 && end == length()) return this;
   4575   Object* result = Heap::AllocateSubString(this, start, end);
   4576   return result;
   4577 }
   4578 
   4579 
   4580 void String::PrintOn(FILE* file) {
   4581   int length = this->length();
   4582   for (int i = 0; i < length; i++) {
   4583     fprintf(file, "%c", Get(i));
   4584   }
   4585 }
   4586 
   4587 
   4588 void Map::CreateBackPointers() {
   4589   DescriptorArray* descriptors = instance_descriptors();
   4590   for (int i = 0; i < descriptors->number_of_descriptors(); i++) {
   4591     if (descriptors->GetType(i) == MAP_TRANSITION) {
   4592       // Get target.
   4593       Map* target = Map::cast(descriptors->GetValue(i));
   4594 #ifdef DEBUG
   4595       // Verify target.
   4596       Object* source_prototype = prototype();
   4597       Object* target_prototype = target->prototype();
   4598       ASSERT(source_prototype->IsJSObject() ||
   4599              source_prototype->IsMap() ||
   4600              source_prototype->IsNull());
   4601       ASSERT(target_prototype->IsJSObject() ||
   4602              target_prototype->IsNull());
   4603       ASSERT(source_prototype->IsMap() ||
   4604              source_prototype == target_prototype);
   4605 #endif
   4606       // Point target back to source.  set_prototype() will not let us set
   4607       // the prototype to a map, as we do here.
   4608       *RawField(target, kPrototypeOffset) = this;
   4609     }
   4610   }
   4611 }
   4612 
   4613 
   4614 void Map::ClearNonLiveTransitions(Object* real_prototype) {
   4615   // Live DescriptorArray objects will be marked, so we must use
   4616   // low-level accessors to get and modify their data.
   4617   DescriptorArray* d = reinterpret_cast<DescriptorArray*>(
   4618       *RawField(this, Map::kInstanceDescriptorsOffset));
   4619   if (d == Heap::raw_unchecked_empty_descriptor_array()) return;
   4620   Smi* NullDescriptorDetails =
   4621     PropertyDetails(NONE, NULL_DESCRIPTOR).AsSmi();
   4622   FixedArray* contents = reinterpret_cast<FixedArray*>(
   4623       d->get(DescriptorArray::kContentArrayIndex));
   4624   ASSERT(contents->length() >= 2);
   4625   for (int i = 0; i < contents->length(); i += 2) {
   4626     // If the pair (value, details) is a map transition,
   4627     // check if the target is live.  If not, null the descriptor.
   4628     // Also drop the back pointer for that map transition, so that this
   4629     // map is not reached again by following a back pointer from a
   4630     // non-live object.
   4631     PropertyDetails details(Smi::cast(contents->get(i + 1)));
   4632     if (details.type() == MAP_TRANSITION) {
   4633       Map* target = reinterpret_cast<Map*>(contents->get(i));
   4634       ASSERT(target->IsHeapObject());
   4635       if (!target->IsMarked()) {
   4636         ASSERT(target->IsMap());
   4637         contents->set(i + 1, NullDescriptorDetails);
   4638         contents->set_null(i);
   4639         ASSERT(target->prototype() == this ||
   4640                target->prototype() == real_prototype);
   4641         // Getter prototype() is read-only, set_prototype() has side effects.
   4642         *RawField(target, Map::kPrototypeOffset) = real_prototype;
   4643       }
   4644     }
   4645   }
   4646 }
   4647 
   4648 
   4649 void Map::MapIterateBody(ObjectVisitor* v) {
   4650   // Assumes all Object* members are contiguously allocated!
   4651   IteratePointers(v, kPrototypeOffset, kCodeCacheOffset + kPointerSize);
   4652 }
   4653 
   4654 
   4655 Object* JSFunction::SetInstancePrototype(Object* value) {
   4656   ASSERT(value->IsJSObject());
   4657 
   4658   if (has_initial_map()) {
   4659     initial_map()->set_prototype(value);
   4660   } else {
   4661     // Put the value in the initial map field until an initial map is
   4662     // needed.  At that point, a new initial map is created and the
   4663     // prototype is put into the initial map where it belongs.
   4664     set_prototype_or_initial_map(value);
   4665   }
   4666   return value;
   4667 }
   4668 
   4669 
   4670 
   4671 Object* JSFunction::SetPrototype(Object* value) {
   4672   Object* construct_prototype = value;
   4673 
   4674   // If the value is not a JSObject, store the value in the map's
   4675   // constructor field so it can be accessed.  Also, set the prototype
   4676   // used for constructing objects to the original object prototype.
   4677   // See ECMA-262 13.2.2.
   4678   if (!value->IsJSObject()) {
   4679     // Copy the map so this does not affect unrelated functions.
   4680     // Remove map transitions because they point to maps with a
   4681     // different prototype.
   4682     Object* new_map = map()->CopyDropTransitions();
   4683     if (new_map->IsFailure()) return new_map;
   4684     set_map(Map::cast(new_map));
   4685     map()->set_constructor(value);
   4686     map()->set_non_instance_prototype(true);
   4687     construct_prototype =
   4688         Top::context()->global_context()->initial_object_prototype();
   4689   } else {
   4690     map()->set_non_instance_prototype(false);
   4691   }
   4692 
   4693   return SetInstancePrototype(construct_prototype);
   4694 }
   4695 
   4696 
   4697 Object* JSFunction::SetInstanceClassName(String* name) {
   4698   shared()->set_instance_class_name(name);
   4699   return this;
   4700 }
   4701 
   4702 
   4703 Context* JSFunction::GlobalContextFromLiterals(FixedArray* literals) {
   4704   return Context::cast(literals->get(JSFunction::kLiteralGlobalContextIndex));
   4705 }
   4706 
   4707 
   4708 void Oddball::OddballIterateBody(ObjectVisitor* v) {
   4709   // Assumes all Object* members are contiguously allocated!
   4710   IteratePointers(v, kToStringOffset, kToNumberOffset + kPointerSize);
   4711 }
   4712 
   4713 
   4714 Object* Oddball::Initialize(const char* to_string, Object* to_number) {
   4715   Object* symbol = Heap::LookupAsciiSymbol(to_string);
   4716   if (symbol->IsFailure()) return symbol;
   4717   set_to_string(String::cast(symbol));
   4718   set_to_number(to_number);
   4719   return this;
   4720 }
   4721 
   4722 
   4723 bool SharedFunctionInfo::HasSourceCode() {
   4724   return !script()->IsUndefined() &&
   4725          !Script::cast(script())->source()->IsUndefined();
   4726 }
   4727 
   4728 
   4729 Object* SharedFunctionInfo::GetSourceCode() {
   4730   HandleScope scope;
   4731   if (script()->IsUndefined()) return Heap::undefined_value();
   4732   Object* source = Script::cast(script())->source();
   4733   if (source->IsUndefined()) return Heap::undefined_value();
   4734   return *SubString(Handle<String>(String::cast(source)),
   4735                     start_position(), end_position());
   4736 }
   4737 
   4738 
   4739 int SharedFunctionInfo::CalculateInstanceSize() {
   4740   int instance_size =
   4741       JSObject::kHeaderSize +
   4742       expected_nof_properties() * kPointerSize;
   4743   if (instance_size > JSObject::kMaxInstanceSize) {
   4744     instance_size = JSObject::kMaxInstanceSize;
   4745   }
   4746   return instance_size;
   4747 }
   4748 
   4749 
   4750 int SharedFunctionInfo::CalculateInObjectProperties() {
   4751   return (CalculateInstanceSize() - JSObject::kHeaderSize) / kPointerSize;
   4752 }
   4753 
   4754 
   4755 bool SharedFunctionInfo::CanGenerateInlineConstructor(Object* prototype) {
   4756   // Check the basic conditions for generating inline constructor code.
   4757   if (!FLAG_inline_new
   4758       || !has_only_simple_this_property_assignments()
   4759       || this_property_assignments_count() == 0) {
   4760     return false;
   4761   }
   4762 
   4763   // If the prototype is null inline constructors cause no problems.
   4764   if (!prototype->IsJSObject()) {
   4765     ASSERT(prototype->IsNull());
   4766     return true;
   4767   }
   4768 
   4769   // Traverse the proposed prototype chain looking for setters for properties of
   4770   // the same names as are set by the inline constructor.
   4771   for (Object* obj = prototype;
   4772        obj != Heap::null_value();
   4773        obj = obj->GetPrototype()) {
   4774     JSObject* js_object = JSObject::cast(obj);
   4775     for (int i = 0; i < this_property_assignments_count(); i++) {
   4776       LookupResult result;
   4777       String* name = GetThisPropertyAssignmentName(i);
   4778       js_object->LocalLookupRealNamedProperty(name, &result);
   4779       if (result.IsProperty() && result.type() == CALLBACKS) {
   4780         return false;
   4781       }
   4782     }
   4783   }
   4784 
   4785   return true;
   4786 }
   4787 
   4788 
   4789 void SharedFunctionInfo::SetThisPropertyAssignmentsInfo(
   4790     bool only_simple_this_property_assignments,
   4791     FixedArray* assignments) {
   4792   set_compiler_hints(BooleanBit::set(compiler_hints(),
   4793                                      kHasOnlySimpleThisPropertyAssignments,
   4794                                      only_simple_this_property_assignments));
   4795   set_this_property_assignments(assignments);
   4796   set_this_property_assignments_count(assignments->length() / 3);
   4797 }
   4798 
   4799 
   4800 void SharedFunctionInfo::ClearThisPropertyAssignmentsInfo() {
   4801   set_compiler_hints(BooleanBit::set(compiler_hints(),
   4802                                      kHasOnlySimpleThisPropertyAssignments,
   4803                                      false));
   4804   set_this_property_assignments(Heap::undefined_value());
   4805   set_this_property_assignments_count(0);
   4806 }
   4807 
   4808 
   4809 String* SharedFunctionInfo::GetThisPropertyAssignmentName(int index) {
   4810   Object* obj = this_property_assignments();
   4811   ASSERT(obj->IsFixedArray());
   4812   ASSERT(index < this_property_assignments_count());
   4813   obj = FixedArray::cast(obj)->get(index * 3);
   4814   ASSERT(obj->IsString());
   4815   return String::cast(obj);
   4816 }
   4817 
   4818 
   4819 bool SharedFunctionInfo::IsThisPropertyAssignmentArgument(int index) {
   4820   Object* obj = this_property_assignments();
   4821   ASSERT(obj->IsFixedArray());
   4822   ASSERT(index < this_property_assignments_count());
   4823   obj = FixedArray::cast(obj)->get(index * 3 + 1);
   4824   return Smi::cast(obj)->value() != -1;
   4825 }
   4826 
   4827 
   4828 int SharedFunctionInfo::GetThisPropertyAssignmentArgument(int index) {
   4829   ASSERT(IsThisPropertyAssignmentArgument(index));
   4830   Object* obj =
   4831       FixedArray::cast(this_property_assignments())->get(index * 3 + 1);
   4832   return Smi::cast(obj)->value();
   4833 }
   4834 
   4835 
   4836 Object* SharedFunctionInfo::GetThisPropertyAssignmentConstant(int index) {
   4837   ASSERT(!IsThisPropertyAssignmentArgument(index));
   4838   Object* obj =
   4839       FixedArray::cast(this_property_assignments())->get(index * 3 + 2);
   4840   return obj;
   4841 }
   4842 
   4843 
   4844 // Support function for printing the source code to a StringStream
   4845 // without any allocation in the heap.
   4846 void SharedFunctionInfo::SourceCodePrint(StringStream* accumulator,
   4847                                          int max_length) {
   4848   // For some native functions there is no source.
   4849   if (script()->IsUndefined() ||
   4850       Script::cast(script())->source()->IsUndefined()) {
   4851     accumulator->Add("<No Source>");
   4852     return;
   4853   }
   4854 
   4855   // Get the source for the script which this function came from.
   4856   // Don't use String::cast because we don't want more assertion errors while
   4857   // we are already creating a stack dump.
   4858   String* script_source =
   4859       reinterpret_cast<String*>(Script::cast(script())->source());
   4860 
   4861   if (!script_source->LooksValid()) {
   4862     accumulator->Add("<Invalid Source>");
   4863     return;
   4864   }
   4865 
   4866   if (!is_toplevel()) {
   4867     accumulator->Add("function ");
   4868     Object* name = this->name();
   4869     if (name->IsString() && String::cast(name)->length() > 0) {
   4870       accumulator->PrintName(name);
   4871     }
   4872   }
   4873 
   4874   int len = end_position() - start_position();
   4875   if (len > max_length) {
   4876     accumulator->Put(script_source,
   4877                      start_position(),
   4878                      start_position() + max_length);
   4879     accumulator->Add("...\n");
   4880   } else {
   4881     accumulator->Put(script_source, start_position(), end_position());
   4882   }
   4883 }
   4884 
   4885 
   4886 void SharedFunctionInfo::SharedFunctionInfoIterateBody(ObjectVisitor* v) {
   4887   IteratePointers(v, kNameOffset, kConstructStubOffset + kPointerSize);
   4888   IteratePointers(v, kInstanceClassNameOffset, kScriptOffset + kPointerSize);
   4889   IteratePointers(v, kDebugInfoOffset, kInferredNameOffset + kPointerSize);
   4890   IteratePointers(v, kThisPropertyAssignmentsOffset,
   4891       kThisPropertyAssignmentsOffset + kPointerSize);
   4892 }
   4893 
   4894 
   4895 void ObjectVisitor::VisitCodeTarget(RelocInfo* rinfo) {
   4896   ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode()));
   4897   Object* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
   4898   Object* old_target = target;
   4899   VisitPointer(&target);
   4900   CHECK_EQ(target, old_target);  // VisitPointer doesn't change Code* *target.
   4901 }
   4902 
   4903 
   4904 void ObjectVisitor::VisitDebugTarget(RelocInfo* rinfo) {
   4905   ASSERT(RelocInfo::IsJSReturn(rinfo->rmode()) &&
   4906          rinfo->IsPatchedReturnSequence());
   4907   Object* target = Code::GetCodeFromTargetAddress(rinfo->call_address());
   4908   Object* old_target = target;
   4909   VisitPointer(&target);
   4910   CHECK_EQ(target, old_target);  // VisitPointer doesn't change Code* *target.
   4911 }
   4912 
   4913 
   4914 void Code::CodeIterateBody(ObjectVisitor* v) {
   4915   int mode_mask = RelocInfo::kCodeTargetMask |
   4916                   RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
   4917                   RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
   4918                   RelocInfo::ModeMask(RelocInfo::JS_RETURN) |
   4919                   RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY);
   4920 
   4921   for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
   4922     RelocInfo::Mode rmode = it.rinfo()->rmode();
   4923     if (rmode == RelocInfo::EMBEDDED_OBJECT) {
   4924       v->VisitPointer(it.rinfo()->target_object_address());
   4925     } else if (RelocInfo::IsCodeTarget(rmode)) {
   4926       v->VisitCodeTarget(it.rinfo());
   4927     } else if (rmode == RelocInfo::EXTERNAL_REFERENCE) {
   4928       v->VisitExternalReference(it.rinfo()->target_reference_address());
   4929 #ifdef ENABLE_DEBUGGER_SUPPORT
   4930     } else if (Debug::has_break_points() &&
   4931                RelocInfo::IsJSReturn(rmode) &&
   4932                it.rinfo()->IsPatchedReturnSequence()) {
   4933       v->VisitDebugTarget(it.rinfo());
   4934 #endif
   4935     } else if (rmode == RelocInfo::RUNTIME_ENTRY) {
   4936       v->VisitRuntimeEntry(it.rinfo());
   4937     }
   4938   }
   4939 
   4940   ScopeInfo<>::IterateScopeInfo(this, v);
   4941 }
   4942 
   4943 
   4944 void Code::Relocate(intptr_t delta) {
   4945   for (RelocIterator it(this, RelocInfo::kApplyMask); !it.done(); it.next()) {
   4946     it.rinfo()->apply(delta);
   4947   }
   4948   CPU::FlushICache(instruction_start(), instruction_size());
   4949 }
   4950 
   4951 
   4952 void Code::CopyFrom(const CodeDesc& desc) {
   4953   // copy code
   4954   memmove(instruction_start(), desc.buffer, desc.instr_size);
   4955 
   4956   // fill gap with zero bytes
   4957   { byte* p = instruction_start() + desc.instr_size;
   4958     byte* q = relocation_start();
   4959     while (p < q) {
   4960       *p++ = 0;
   4961     }
   4962   }
   4963 
   4964   // copy reloc info
   4965   memmove(relocation_start(),
   4966           desc.buffer + desc.buffer_size - desc.reloc_size,
   4967           desc.reloc_size);
   4968 
   4969   // unbox handles and relocate
   4970   intptr_t delta = instruction_start() - desc.buffer;
   4971   int mode_mask = RelocInfo::kCodeTargetMask |
   4972                   RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
   4973                   RelocInfo::kApplyMask;
   4974   Assembler* origin = desc.origin;  // Needed to find target_object on X64.
   4975   for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
   4976     RelocInfo::Mode mode = it.rinfo()->rmode();
   4977     if (mode == RelocInfo::EMBEDDED_OBJECT) {
   4978       Handle<Object> p = it.rinfo()->target_object_handle(origin);
   4979       it.rinfo()->set_target_object(*p);
   4980     } else if (RelocInfo::IsCodeTarget(mode)) {
   4981       // rewrite code handles in inline cache targets to direct
   4982       // pointers to the first instruction in the code object
   4983       Handle<Object> p = it.rinfo()->target_object_handle(origin);
   4984       Code* code = Code::cast(*p);
   4985       it.rinfo()->set_target_address(code->instruction_start());
   4986     } else {
   4987       it.rinfo()->apply(delta);
   4988     }
   4989   }
   4990   CPU::FlushICache(instruction_start(), instruction_size());
   4991 }
   4992 
   4993 
   4994 // Locate the source position which is closest to the address in the code. This
   4995 // is using the source position information embedded in the relocation info.
   4996 // The position returned is relative to the beginning of the script where the
   4997 // source for this function is found.
   4998 int Code::SourcePosition(Address pc) {
   4999   int distance = kMaxInt;
   5000   int position = RelocInfo::kNoPosition;  // Initially no position found.
   5001   // Run through all the relocation info to find the best matching source
   5002   // position. All the code needs to be considered as the sequence of the
   5003   // instructions in the code does not necessarily follow the same order as the
   5004   // source.
   5005   RelocIterator it(this, RelocInfo::kPositionMask);
   5006   while (!it.done()) {
   5007     // Only look at positions after the current pc.
   5008     if (it.rinfo()->pc() < pc) {
   5009       // Get position and distance.
   5010 
   5011       int dist = static_cast<int>(pc - it.rinfo()->pc());
   5012       int pos = static_cast<int>(it.rinfo()->data());
   5013       // If this position is closer than the current candidate or if it has the
   5014       // same distance as the current candidate and the position is higher then
   5015       // this position is the new candidate.
   5016       if ((dist < distance) ||
   5017           (dist == distance && pos > position)) {
   5018         position = pos;
   5019         distance = dist;
   5020       }
   5021     }
   5022     it.next();
   5023   }
   5024   return position;
   5025 }
   5026 
   5027 
   5028 // Same as Code::SourcePosition above except it only looks for statement
   5029 // positions.
   5030 int Code::SourceStatementPosition(Address pc) {
   5031   // First find the position as close as possible using all position
   5032   // information.
   5033   int position = SourcePosition(pc);
   5034   // Now find the closest statement position before the position.
   5035   int statement_position = 0;
   5036   RelocIterator it(this, RelocInfo::kPositionMask);
   5037   while (!it.done()) {
   5038     if (RelocInfo::IsStatementPosition(it.rinfo()->rmode())) {
   5039       int p = static_cast<int>(it.rinfo()->data());
   5040       if (statement_position < p && p <= position) {
   5041         statement_position = p;
   5042       }
   5043     }
   5044     it.next();
   5045   }
   5046   return statement_position;
   5047 }
   5048 
   5049 
   5050 #ifdef ENABLE_DISASSEMBLER
   5051 // Identify kind of code.
   5052 const char* Code::Kind2String(Kind kind) {
   5053   switch (kind) {
   5054     case FUNCTION: return "FUNCTION";
   5055     case STUB: return "STUB";
   5056     case BUILTIN: return "BUILTIN";
   5057     case LOAD_IC: return "LOAD_IC";
   5058     case KEYED_LOAD_IC: return "KEYED_LOAD_IC";
   5059     case STORE_IC: return "STORE_IC";
   5060     case KEYED_STORE_IC: return "KEYED_STORE_IC";
   5061     case CALL_IC: return "CALL_IC";
   5062   }
   5063   UNREACHABLE();
   5064   return NULL;
   5065 }
   5066 
   5067 
   5068 const char* Code::ICState2String(InlineCacheState state) {
   5069   switch (state) {
   5070     case UNINITIALIZED: return "UNINITIALIZED";
   5071     case PREMONOMORPHIC: return "PREMONOMORPHIC";
   5072     case MONOMORPHIC: return "MONOMORPHIC";
   5073     case MONOMORPHIC_PROTOTYPE_FAILURE: return "MONOMORPHIC_PROTOTYPE_FAILURE";
   5074     case MEGAMORPHIC: return "MEGAMORPHIC";
   5075     case DEBUG_BREAK: return "DEBUG_BREAK";
   5076     case DEBUG_PREPARE_STEP_IN: return "DEBUG_PREPARE_STEP_IN";
   5077   }
   5078   UNREACHABLE();
   5079   return NULL;
   5080 }
   5081 
   5082 
   5083 const char* Code::PropertyType2String(PropertyType type) {
   5084   switch (type) {
   5085     case NORMAL: return "NORMAL";
   5086     case FIELD: return "FIELD";
   5087     case CONSTANT_FUNCTION: return "CONSTANT_FUNCTION";
   5088     case CALLBACKS: return "CALLBACKS";
   5089     case INTERCEPTOR: return "INTERCEPTOR";
   5090     case MAP_TRANSITION: return "MAP_TRANSITION";
   5091     case CONSTANT_TRANSITION: return "CONSTANT_TRANSITION";
   5092     case NULL_DESCRIPTOR: return "NULL_DESCRIPTOR";
   5093   }
   5094   UNREACHABLE();
   5095   return NULL;
   5096 }
   5097 
   5098 void Code::Disassemble(const char* name) {
   5099   PrintF("kind = %s\n", Kind2String(kind()));
   5100   if (is_inline_cache_stub()) {
   5101     PrintF("ic_state = %s\n", ICState2String(ic_state()));
   5102     PrintF("ic_in_loop = %d\n", ic_in_loop() == IN_LOOP);
   5103     if (ic_state() == MONOMORPHIC) {
   5104       PrintF("type = %s\n", PropertyType2String(type()));
   5105     }
   5106   }
   5107   if ((name != NULL) && (name[0] != '\0')) {
   5108     PrintF("name = %s\n", name);
   5109   }
   5110 
   5111   PrintF("Instructions (size = %d)\n", instruction_size());
   5112   Disassembler::Decode(NULL, this);
   5113   PrintF("\n");
   5114 
   5115   PrintF("RelocInfo (size = %d)\n", relocation_size());
   5116   for (RelocIterator it(this); !it.done(); it.next())
   5117     it.rinfo()->Print();
   5118   PrintF("\n");
   5119 }
   5120 #endif  // ENABLE_DISASSEMBLER
   5121 
   5122 
   5123 void JSObject::SetFastElements(FixedArray* elems) {
   5124   // We should never end in here with a pixel or external array.
   5125   ASSERT(!HasPixelElements() && !HasExternalArrayElements());
   5126 #ifdef DEBUG
   5127   // Check the provided array is filled with the_hole.
   5128   uint32_t len = static_cast<uint32_t>(elems->length());
   5129   for (uint32_t i = 0; i < len; i++) ASSERT(elems->get(i)->IsTheHole());
   5130 #endif
   5131   AssertNoAllocation no_gc;
   5132   WriteBarrierMode mode = elems->GetWriteBarrierMode(no_gc);
   5133   switch (GetElementsKind()) {
   5134     case FAST_ELEMENTS: {
   5135       FixedArray* old_elements = FixedArray::cast(elements());
   5136       uint32_t old_length = static_cast<uint32_t>(old_elements->length());
   5137       // Fill out the new array with this content and array holes.
   5138       for (uint32_t i = 0; i < old_length; i++) {
   5139         elems->set(i, old_elements->get(i), mode);
   5140       }
   5141       break;
   5142     }
   5143     case DICTIONARY_ELEMENTS: {
   5144       NumberDictionary* dictionary = NumberDictionary::cast(elements());
   5145       for (int i = 0; i < dictionary->Capacity(); i++) {
   5146         Object* key = dictionary->KeyAt(i);
   5147         if (key->IsNumber()) {
   5148           uint32_t entry = static_cast<uint32_t>(key->Number());
   5149           elems->set(entry, dictionary->ValueAt(i), mode);
   5150         }
   5151       }
   5152       break;
   5153     }
   5154     default:
   5155       UNREACHABLE();
   5156       break;
   5157   }
   5158   set_elements(elems);
   5159 }
   5160 
   5161 
   5162 Object* JSObject::SetSlowElements(Object* len) {
   5163   // We should never end in here with a pixel or external array.
   5164   ASSERT(!HasPixelElements() && !HasExternalArrayElements());
   5165 
   5166   uint32_t new_length = static_cast<uint32_t>(len->Number());
   5167 
   5168   switch (GetElementsKind()) {
   5169     case FAST_ELEMENTS: {
   5170       // Make sure we never try to shrink dense arrays into sparse arrays.
   5171       ASSERT(static_cast<uint32_t>(FixedArray::cast(elements())->length()) <=
   5172                                    new_length);
   5173       Object* obj = NormalizeElements();
   5174       if (obj->IsFailure()) return obj;
   5175 
   5176       // Update length for JSArrays.
   5177       if (IsJSArray()) JSArray::cast(this)->set_length(len);
   5178       break;
   5179     }
   5180     case DICTIONARY_ELEMENTS: {
   5181       if (IsJSArray()) {
   5182         uint32_t old_length =
   5183         static_cast<uint32_t>(JSArray::cast(this)->length()->Number());
   5184         element_dictionary()->RemoveNumberEntries(new_length, old_length),
   5185         JSArray::cast(this)->set_length(len);
   5186       }
   5187       break;
   5188     }
   5189     default:
   5190       UNREACHABLE();
   5191       break;
   5192   }
   5193   return this;
   5194 }
   5195 
   5196 
   5197 Object* JSArray::Initialize(int capacity) {
   5198   ASSERT(capacity >= 0);
   5199   set_length(Smi::FromInt(0));
   5200   FixedArray* new_elements;
   5201   if (capacity == 0) {
   5202     new_elements = Heap::empty_fixed_array();
   5203   } else {
   5204     Object* obj = Heap::AllocateFixedArrayWithHoles(capacity);
   5205     if (obj->IsFailure()) return obj;
   5206     new_elements = FixedArray::cast(obj);
   5207   }
   5208   set_elements(new_elements);
   5209   return this;
   5210 }
   5211 
   5212 
   5213 void JSArray::Expand(int required_size) {
   5214   Handle<JSArray> self(this);
   5215   Handle<FixedArray> old_backing(FixedArray::cast(elements()));
   5216   int old_size = old_backing->length();
   5217   int new_size = required_size > old_size ? required_size : old_size;
   5218   Handle<FixedArray> new_backing = Factory::NewFixedArray(new_size);
   5219   // Can't use this any more now because we may have had a GC!
   5220   for (int i = 0; i < old_size; i++) new_backing->set(i, old_backing->get(i));
   5221   self->SetContent(*new_backing);
   5222 }
   5223 
   5224 
   5225 // Computes the new capacity when expanding the elements of a JSObject.
   5226 static int NewElementsCapacity(int old_capacity) {
   5227   // (old_capacity + 50%) + 16
   5228   return old_capacity + (old_capacity >> 1) + 16;
   5229 }
   5230 
   5231 
   5232 static Object* ArrayLengthRangeError() {
   5233   HandleScope scope;
   5234   return Top::Throw(*Factory::NewRangeError("invalid_array_length",
   5235                                             HandleVector<Object>(NULL, 0)));
   5236 }
   5237 
   5238 
   5239 Object* JSObject::SetElementsLength(Object* len) {
   5240   // We should never end in here with a pixel or external array.
   5241   ASSERT(!HasPixelElements() && !HasExternalArrayElements());
   5242 
   5243   Object* smi_length = len->ToSmi();
   5244   if (smi_length->IsSmi()) {
   5245     int value = Smi::cast(smi_length)->value();
   5246     if (value < 0) return ArrayLengthRangeError();
   5247     switch (GetElementsKind()) {
   5248       case FAST_ELEMENTS: {
   5249         int old_capacity = FixedArray::cast(elements())->length();
   5250         if (value <= old_capacity) {
   5251           if (IsJSArray()) {
   5252             int old_length = FastD2I(JSArray::cast(this)->length()->Number());
   5253             // NOTE: We may be able to optimize this by removing the
   5254             // last part of the elements backing storage array and
   5255             // setting the capacity to the new size.
   5256             for (int i = value; i < old_length; i++) {
   5257               FixedArray::cast(elements())->set_the_hole(i);
   5258             }
   5259             JSArray::cast(this)->set_length(Smi::cast(smi_length));
   5260           }
   5261           return this;
   5262         }
   5263         int min = NewElementsCapacity(old_capacity);
   5264         int new_capacity = value > min ? value : min;
   5265         if (new_capacity <= kMaxFastElementsLength ||
   5266             !ShouldConvertToSlowElements(new_capacity)) {
   5267           Object* obj = Heap::AllocateFixedArrayWithHoles(new_capacity);
   5268           if (obj->IsFailure()) return obj;
   5269           if (IsJSArray()) {
   5270             JSArray::cast(this)->set_length(Smi::cast(smi_length));
   5271           }
   5272           SetFastElements(FixedArray::cast(obj));
   5273           return this;
   5274         }
   5275         break;
   5276       }
   5277       case DICTIONARY_ELEMENTS: {
   5278         if (IsJSArray()) {
   5279           if (value == 0) {
   5280             // If the length of a slow array is reset to zero, we clear
   5281             // the array and flush backing storage. This has the added
   5282             // benefit that the array returns to fast mode.
   5283             initialize_elements();
   5284           } else {
   5285             // Remove deleted elements.
   5286             uint32_t old_length =
   5287             static_cast<uint32_t>(JSArray::cast(this)->length()->Number());
   5288             element_dictionary()->RemoveNumberEntries(value, old_length);
   5289           }
   5290           JSArray::cast(this)->set_length(Smi::cast(smi_length));
   5291         }
   5292         return this;
   5293       }
   5294       default:
   5295         UNREACHABLE();
   5296         break;
   5297     }
   5298   }
   5299 
   5300   // General slow case.
   5301   if (len->IsNumber()) {
   5302     uint32_t length;
   5303     if (Array::IndexFromObject(len, &length)) {
   5304       return SetSlowElements(len);
   5305     } else {
   5306       return ArrayLengthRangeError();
   5307     }
   5308   }
   5309 
   5310   // len is not a number so make the array size one and
   5311   // set only element to len.
   5312   Object* obj = Heap::AllocateFixedArray(1);
   5313   if (obj->IsFailure()) return obj;
   5314   FixedArray::cast(obj)->set(0, len);
   5315   if (IsJSArray()) JSArray::cast(this)->set_length(Smi::FromInt(1));
   5316   set_elements(FixedArray::cast(obj));
   5317   return this;
   5318 }
   5319 
   5320 
   5321 Object* JSObject::SetPrototype(Object* value,
   5322                                bool skip_hidden_prototypes) {
   5323   // Silently ignore the change if value is not a JSObject or null.
   5324   // SpiderMonkey behaves this way.
   5325   if (!value->IsJSObject() && !value->IsNull()) return value;
   5326 
   5327   // Before we can set the prototype we need to be sure
   5328   // prototype cycles are prevented.
   5329   // It is sufficient to validate that the receiver is not in the new prototype
   5330   // chain.
   5331   for (Object* pt = value; pt != Heap::null_value(); pt = pt->GetPrototype()) {
   5332     if (JSObject::cast(pt) == this) {
   5333       // Cycle detected.
   5334       HandleScope scope;
   5335       return Top::Throw(*Factory::NewError("cyclic_proto",
   5336                                            HandleVector<Object>(NULL, 0)));
   5337     }
   5338   }
   5339 
   5340   JSObject* real_receiver = this;
   5341 
   5342   if (skip_hidden_prototypes) {
   5343     // Find the first object in the chain whose prototype object is not
   5344     // hidden and set the new prototype on that object.
   5345     Object* current_proto = real_receiver->GetPrototype();
   5346     while (current_proto->IsJSObject() &&
   5347           JSObject::cast(current_proto)->map()->is_hidden_prototype()) {
   5348       real_receiver = JSObject::cast(current_proto);
   5349       current_proto = current_proto->GetPrototype();
   5350     }
   5351   }
   5352 
   5353   // Set the new prototype of the object.
   5354   Object* new_map = real_receiver->map()->CopyDropTransitions();
   5355   if (new_map->IsFailure()) return new_map;
   5356   Map::cast(new_map)->set_prototype(value);
   5357   real_receiver->set_map(Map::cast(new_map));
   5358 
   5359   return value;
   5360 }
   5361 
   5362 
   5363 bool JSObject::HasElementPostInterceptor(JSObject* receiver, uint32_t index) {
   5364   switch (GetElementsKind()) {
   5365     case FAST_ELEMENTS: {
   5366       uint32_t length = IsJSArray() ?
   5367           static_cast<uint32_t>
   5368               (Smi::cast(JSArray::cast(this)->length())->value()) :
   5369           static_cast<uint32_t>(FixedArray::cast(elements())->length());
   5370       if ((index < length) &&
   5371           !FixedArray::cast(elements())->get(index)->IsTheHole()) {
   5372         return true;
   5373       }
   5374       break;
   5375     }
   5376     case PIXEL_ELEMENTS: {
   5377       // TODO(iposva): Add testcase.
   5378       PixelArray* pixels = PixelArray::cast(elements());
   5379       if (index < static_cast<uint32_t>(pixels->length())) {
   5380         return true;
   5381       }
   5382       break;
   5383     }
   5384     case EXTERNAL_BYTE_ELEMENTS:
   5385     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
   5386     case EXTERNAL_SHORT_ELEMENTS:
   5387     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
   5388     case EXTERNAL_INT_ELEMENTS:
   5389     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
   5390     case EXTERNAL_FLOAT_ELEMENTS: {
   5391       // TODO(kbr): Add testcase.
   5392       ExternalArray* array = ExternalArray::cast(elements());
   5393       if (index < static_cast<uint32_t>(array->length())) {
   5394         return true;
   5395       }
   5396       break;
   5397     }
   5398     case DICTIONARY_ELEMENTS: {
   5399       if (element_dictionary()->FindEntry(index)
   5400           != NumberDictionary::kNotFound) {
   5401         return true;
   5402       }
   5403       break;
   5404     }
   5405     default:
   5406       UNREACHABLE();
   5407       break;
   5408   }
   5409 
   5410   // Handle [] on String objects.
   5411   if (this->IsStringObjectWithCharacterAt(index)) return true;
   5412 
   5413   Object* pt = GetPrototype();
   5414   if (pt == Heap::null_value()) return false;
   5415   return JSObject::cast(pt)->HasElementWithReceiver(receiver, index);
   5416 }
   5417 
   5418 
   5419 bool JSObject::HasElementWithInterceptor(JSObject* receiver, uint32_t index) {
   5420   // Make sure that the top context does not change when doing
   5421   // callbacks or interceptor calls.
   5422   AssertNoContextChange ncc;
   5423   HandleScope scope;
   5424   Handle<InterceptorInfo> interceptor(GetIndexedInterceptor());
   5425   Handle<JSObject> receiver_handle(receiver);
   5426   Handle<JSObject> holder_handle(this);
   5427   CustomArguments args(interceptor->data(), receiver, this);
   5428   v8::AccessorInfo info(args.end());
   5429   if (!interceptor->query()->IsUndefined()) {
   5430     v8::IndexedPropertyQuery query =
   5431         v8::ToCData<v8::IndexedPropertyQuery>(interceptor->query());
   5432     LOG(ApiIndexedPropertyAccess("interceptor-indexed-has", this, index));
   5433     v8::Handle<v8::Boolean> result;
   5434     {
   5435       // Leaving JavaScript.
   5436       VMState state(EXTERNAL);
   5437       result = query(index, info);
   5438     }
   5439     if (!result.IsEmpty()) return result->IsTrue();
   5440   } else if (!interceptor->getter()->IsUndefined()) {
   5441     v8::IndexedPropertyGetter getter =
   5442         v8::ToCData<v8::IndexedPropertyGetter>(interceptor->getter());
   5443     LOG(ApiIndexedPropertyAccess("interceptor-indexed-has-get", this, index));
   5444     v8::Handle<v8::Value> result;
   5445     {
   5446       // Leaving JavaScript.
   5447       VMState state(EXTERNAL);
   5448       result = getter(index, info);
   5449     }
   5450     if (!result.IsEmpty()) return true;
   5451   }
   5452   return holder_handle->HasElementPostInterceptor(*receiver_handle, index);
   5453 }
   5454 
   5455 
   5456 bool JSObject::HasLocalElement(uint32_t index) {
   5457   // Check access rights if needed.
   5458   if (IsAccessCheckNeeded() &&
   5459       !Top::MayIndexedAccess(this, index, v8::ACCESS_HAS)) {
   5460     Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS);
   5461     return false;
   5462   }
   5463 
   5464   // Check for lookup interceptor
   5465   if (HasIndexedInterceptor()) {
   5466     return HasElementWithInterceptor(this, index);
   5467   }
   5468 
   5469   // Handle [] on String objects.
   5470   if (this->IsStringObjectWithCharacterAt(index)) return true;
   5471 
   5472   switch (GetElementsKind()) {
   5473     case FAST_ELEMENTS: {
   5474       uint32_t length = IsJSArray() ?
   5475           static_cast<uint32_t>
   5476               (Smi::cast(JSArray::cast(this)->length())->value()) :
   5477           static_cast<uint32_t>(FixedArray::cast(elements())->length());
   5478       return (index < length) &&
   5479           !FixedArray::cast(elements())->get(index)->IsTheHole();
   5480     }
   5481     case PIXEL_ELEMENTS: {
   5482       PixelArray* pixels = PixelArray::cast(elements());
   5483       return (index < static_cast<uint32_t>(pixels->length()));
   5484     }
   5485     case EXTERNAL_BYTE_ELEMENTS:
   5486     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
   5487     case EXTERNAL_SHORT_ELEMENTS:
   5488     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
   5489     case EXTERNAL_INT_ELEMENTS:
   5490     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
   5491     case EXTERNAL_FLOAT_ELEMENTS: {
   5492       ExternalArray* array = ExternalArray::cast(elements());
   5493       return (index < static_cast<uint32_t>(array->length()));
   5494     }
   5495     case DICTIONARY_ELEMENTS: {
   5496       return element_dictionary()->FindEntry(index)
   5497           != NumberDictionary::kNotFound;
   5498     }
   5499     default:
   5500       UNREACHABLE();
   5501       break;
   5502   }
   5503   UNREACHABLE();
   5504   return Heap::null_value();
   5505 }
   5506 
   5507 
   5508 bool JSObject::HasElementWithReceiver(JSObject* receiver, uint32_t index) {
   5509   // Check access rights if needed.
   5510   if (IsAccessCheckNeeded() &&
   5511       !Top::MayIndexedAccess(this, index, v8::ACCESS_HAS)) {
   5512     Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS);
   5513     return false;
   5514   }
   5515 
   5516   // Check for lookup interceptor
   5517   if (HasIndexedInterceptor()) {
   5518     return HasElementWithInterceptor(receiver, index);
   5519   }
   5520 
   5521   switch (GetElementsKind()) {
   5522     case FAST_ELEMENTS: {
   5523       uint32_t length = IsJSArray() ?
   5524           static_cast<uint32_t>
   5525               (Smi::cast(JSArray::cast(this)->length())->value()) :
   5526           static_cast<uint32_t>(FixedArray::cast(elements())->length());
   5527       if ((index < length) &&
   5528           !FixedArray::cast(elements())->get(index)->IsTheHole()) return true;
   5529       break;
   5530     }
   5531     case PIXEL_ELEMENTS: {
   5532       PixelArray* pixels = PixelArray::cast(elements());
   5533       if (index < static_cast<uint32_t>(pixels->length())) {
   5534         return true;
   5535       }
   5536       break;
   5537     }
   5538     case EXTERNAL_BYTE_ELEMENTS:
   5539     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
   5540     case EXTERNAL_SHORT_ELEMENTS:
   5541     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
   5542     case EXTERNAL_INT_ELEMENTS:
   5543     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
   5544     case EXTERNAL_FLOAT_ELEMENTS: {
   5545       ExternalArray* array = ExternalArray::cast(elements());
   5546       if (index < static_cast<uint32_t>(array->length())) {
   5547         return true;
   5548       }
   5549       break;
   5550     }
   5551     case DICTIONARY_ELEMENTS: {
   5552       if (element_dictionary()->FindEntry(index)
   5553           != NumberDictionary::kNotFound) {
   5554         return true;
   5555       }
   5556       break;
   5557     }
   5558     default:
   5559       UNREACHABLE();
   5560       break;
   5561   }
   5562 
   5563   // Handle [] on String objects.
   5564   if (this->IsStringObjectWithCharacterAt(index)) return true;
   5565 
   5566   Object* pt = GetPrototype();
   5567   if (pt == Heap::null_value()) return false;
   5568   return JSObject::cast(pt)->HasElementWithReceiver(receiver, index);
   5569 }
   5570 
   5571 
   5572 Object* JSObject::SetElementWithInterceptor(uint32_t index, Object* value) {
   5573   // Make sure that the top context does not change when doing
   5574   // callbacks or interceptor calls.
   5575   AssertNoContextChange ncc;
   5576   HandleScope scope;
   5577   Handle<InterceptorInfo> interceptor(GetIndexedInterceptor());
   5578   Handle<JSObject> this_handle(this);
   5579   Handle<Object> value_handle(value);
   5580   if (!interceptor->setter()->IsUndefined()) {
   5581     v8::IndexedPropertySetter setter =
   5582         v8::ToCData<v8::IndexedPropertySetter>(interceptor->setter());
   5583     LOG(ApiIndexedPropertyAccess("interceptor-indexed-set", this, index));
   5584     CustomArguments args(interceptor->data(), this, this);
   5585     v8::AccessorInfo info(args.end());
   5586     v8::Handle<v8::Value> result;
   5587     {
   5588       // Leaving JavaScript.
   5589       VMState state(EXTERNAL);
   5590       result = setter(index, v8::Utils::ToLocal(value_handle), info);
   5591     }
   5592     RETURN_IF_SCHEDULED_EXCEPTION();
   5593     if (!result.IsEmpty()) return *value_handle;
   5594   }
   5595   Object* raw_result =
   5596       this_handle->SetElementWithoutInterceptor(index, *value_handle);
   5597   RETURN_IF_SCHEDULED_EXCEPTION();
   5598   return raw_result;
   5599 }
   5600 
   5601 
   5602 // Adding n elements in fast case is O(n*n).
   5603 // Note: revisit design to have dual undefined values to capture absent
   5604 // elements.
   5605 Object* JSObject::SetFastElement(uint32_t index, Object* value) {
   5606   ASSERT(HasFastElements());
   5607 
   5608   FixedArray* elms = FixedArray::cast(elements());
   5609   uint32_t elms_length = static_cast<uint32_t>(elms->length());
   5610 
   5611   if (!IsJSArray() && (index >= elms_length || elms->get(index)->IsTheHole())) {
   5612     Object* setter = LookupCallbackSetterInPrototypes(index);
   5613     if (setter->IsJSFunction()) {
   5614       return SetPropertyWithDefinedSetter(JSFunction::cast(setter), value);
   5615     }
   5616   }
   5617 
   5618   // Check whether there is extra space in fixed array..
   5619   if (index < elms_length) {
   5620     elms->set(index, value);
   5621     if (IsJSArray()) {
   5622       // Update the length of the array if needed.
   5623       uint32_t array_length = 0;
   5624       CHECK(Array::IndexFromObject(JSArray::cast(this)->length(),
   5625                                    &array_length));
   5626       if (index >= array_length) {
   5627         JSArray::cast(this)->set_length(Smi::FromInt(index + 1));
   5628       }
   5629     }
   5630     return value;
   5631   }
   5632 
   5633   // Allow gap in fast case.
   5634   if ((index - elms_length) < kMaxGap) {
   5635     // Try allocating extra space.
   5636     int new_capacity = NewElementsCapacity(index+1);
   5637     if (new_capacity <= kMaxFastElementsLength ||
   5638         !ShouldConvertToSlowElements(new_capacity)) {
   5639       ASSERT(static_cast<uint32_t>(new_capacity) > index);
   5640       Object* obj = Heap::AllocateFixedArrayWithHoles(new_capacity);
   5641       if (obj->IsFailure()) return obj;
   5642       SetFastElements(FixedArray::cast(obj));
   5643       if (IsJSArray()) {
   5644         JSArray::cast(this)->set_length(Smi::FromInt(index + 1));
   5645       }
   5646       FixedArray::cast(elements())->set(index, value);
   5647       return value;
   5648     }
   5649   }
   5650 
   5651   // Otherwise default to slow case.
   5652   Object* obj = NormalizeElements();
   5653   if (obj->IsFailure()) return obj;
   5654   ASSERT(HasDictionaryElements());
   5655   return SetElement(index, value);
   5656 }
   5657 
   5658 Object* JSObject::SetElement(uint32_t index, Object* value) {
   5659   // Check access rights if needed.
   5660   if (IsAccessCheckNeeded() &&
   5661       !Top::MayIndexedAccess(this, index, v8::ACCESS_SET)) {
   5662     Top::ReportFailedAccessCheck(this, v8::ACCESS_SET);
   5663     return value;
   5664   }
   5665 
   5666   if (IsJSGlobalProxy()) {
   5667     Object* proto = GetPrototype();
   5668     if (proto->IsNull()) return value;
   5669     ASSERT(proto->IsJSGlobalObject());
   5670     return JSObject::cast(proto)->SetElement(index, value);
   5671   }
   5672 
   5673   // Check for lookup interceptor
   5674   if (HasIndexedInterceptor()) {
   5675     return SetElementWithInterceptor(index, value);
   5676   }
   5677 
   5678   return SetElementWithoutInterceptor(index, value);
   5679 }
   5680 
   5681 
   5682 Object* JSObject::SetElementWithoutInterceptor(uint32_t index, Object* value) {
   5683   switch (GetElementsKind()) {
   5684     case FAST_ELEMENTS:
   5685       // Fast case.
   5686       return SetFastElement(index, value);
   5687     case PIXEL_ELEMENTS: {
   5688       PixelArray* pixels = PixelArray::cast(elements());
   5689       return pixels->SetValue(index, value);
   5690     }
   5691     case EXTERNAL_BYTE_ELEMENTS: {
   5692       ExternalByteArray* array = ExternalByteArray::cast(elements());
   5693       return array->SetValue(index, value);
   5694     }
   5695     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: {
   5696       ExternalUnsignedByteArray* array =
   5697           ExternalUnsignedByteArray::cast(elements());
   5698       return array->SetValue(index, value);
   5699     }
   5700     case EXTERNAL_SHORT_ELEMENTS: {
   5701       ExternalShortArray* array = ExternalShortArray::cast(elements());
   5702       return array->SetValue(index, value);
   5703     }
   5704     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: {
   5705       ExternalUnsignedShortArray* array =
   5706           ExternalUnsignedShortArray::cast(elements());
   5707       return array->SetValue(index, value);
   5708     }
   5709     case EXTERNAL_INT_ELEMENTS: {
   5710       ExternalIntArray* array = ExternalIntArray::cast(elements());
   5711       return array->SetValue(index, value);
   5712     }
   5713     case EXTERNAL_UNSIGNED_INT_ELEMENTS: {
   5714       ExternalUnsignedIntArray* array =
   5715           ExternalUnsignedIntArray::cast(elements());
   5716       return array->SetValue(index, value);
   5717     }
   5718     case EXTERNAL_FLOAT_ELEMENTS: {
   5719       ExternalFloatArray* array = ExternalFloatArray::cast(elements());
   5720       return array->SetValue(index, value);
   5721     }
   5722     case DICTIONARY_ELEMENTS: {
   5723       // Insert element in the dictionary.
   5724       FixedArray* elms = FixedArray::cast(elements());
   5725       NumberDictionary* dictionary = NumberDictionary::cast(elms);
   5726 
   5727       int entry = dictionary->FindEntry(index);
   5728       if (entry != NumberDictionary::kNotFound) {
   5729         Object* element = dictionary->ValueAt(entry);
   5730         PropertyDetails details = dictionary->DetailsAt(entry);
   5731         if (details.type() == CALLBACKS) {
   5732           // Only accessors allowed as elements.
   5733           FixedArray* structure = FixedArray::cast(element);
   5734           if (structure->get(kSetterIndex)->IsJSFunction()) {
   5735             JSFunction* setter = JSFunction::cast(structure->get(kSetterIndex));
   5736             return SetPropertyWithDefinedSetter(setter, value);
   5737           } else {
   5738             Handle<Object> self(this);
   5739             Handle<Object> key(Factory::NewNumberFromUint(index));
   5740             Handle<Object> args[2] = { key, self };
   5741             return Top::Throw(*Factory::NewTypeError("no_setter_in_callback",
   5742                                                      HandleVector(args, 2)));
   5743           }
   5744         } else {
   5745           dictionary->UpdateMaxNumberKey(index);
   5746           dictionary->ValueAtPut(entry, value);
   5747         }
   5748       } else {
   5749         // Index not already used. Look for an accessor in the prototype chain.
   5750         if (!IsJSArray()) {
   5751           Object* setter = LookupCallbackSetterInPrototypes(index);
   5752           if (setter->IsJSFunction()) {
   5753             return SetPropertyWithDefinedSetter(JSFunction::cast(setter),
   5754                                                 value);
   5755           }
   5756         }
   5757         Object* result = dictionary->AtNumberPut(index, value);
   5758         if (result->IsFailure()) return result;
   5759         if (elms != FixedArray::cast(result)) {
   5760           set_elements(FixedArray::cast(result));
   5761         }
   5762       }
   5763 
   5764       // Update the array length if this JSObject is an array.
   5765       if (IsJSArray()) {
   5766         JSArray* array = JSArray::cast(this);
   5767         Object* return_value = array->JSArrayUpdateLengthFromIndex(index,
   5768                                                                    value);
   5769         if (return_value->IsFailure()) return return_value;
   5770       }
   5771 
   5772       // Attempt to put this object back in fast case.
   5773       if (ShouldConvertToFastElements()) {
   5774         uint32_t new_length = 0;
   5775         if (IsJSArray()) {
   5776           CHECK(Array::IndexFromObject(JSArray::cast(this)->length(),
   5777                                        &new_length));
   5778           JSArray::cast(this)->set_length(Smi::FromInt(new_length));
   5779         } else {
   5780           new_length = NumberDictionary::cast(elements())->max_number_key() + 1;
   5781         }
   5782         Object* obj = Heap::AllocateFixedArrayWithHoles(new_length);
   5783         if (obj->IsFailure()) return obj;
   5784         SetFastElements(FixedArray::cast(obj));
   5785 #ifdef DEBUG
   5786         if (FLAG_trace_normalization) {
   5787           PrintF("Object elements are fast case again:\n");
   5788           Print();
   5789         }
   5790 #endif
   5791       }
   5792 
   5793       return value;
   5794     }
   5795     default:
   5796       UNREACHABLE();
   5797       break;
   5798   }
   5799   // All possible cases have been handled above. Add a return to avoid the
   5800   // complaints from the compiler.
   5801   UNREACHABLE();
   5802   return Heap::null_value();
   5803 }
   5804 
   5805 
   5806 Object* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index, Object* value) {
   5807   uint32_t old_len = 0;
   5808   CHECK(Array::IndexFromObject(length(), &old_len));
   5809   // Check to see if we need to update the length. For now, we make
   5810   // sure that the length stays within 32-bits (unsigned).
   5811   if (index >= old_len && index != 0xffffffff) {
   5812     Object* len =
   5813         Heap::NumberFromDouble(static_cast<double>(index) + 1);
   5814     if (len->IsFailure()) return len;
   5815     set_length(len);
   5816   }
   5817   return value;
   5818 }
   5819 
   5820 
   5821 Object* JSObject::GetElementPostInterceptor(JSObject* receiver,
   5822                                             uint32_t index) {
   5823   // Get element works for both JSObject and JSArray since
   5824   // JSArray::length cannot change.
   5825   switch (GetElementsKind()) {
   5826     case FAST_ELEMENTS: {
   5827       FixedArray* elms = FixedArray::cast(elements());
   5828       if (index < static_cast<uint32_t>(elms->length())) {
   5829         Object* value = elms->get(index);
   5830         if (!value->IsTheHole()) return value;
   5831       }
   5832       break;
   5833     }
   5834     case PIXEL_ELEMENTS: {
   5835       // TODO(iposva): Add testcase and implement.
   5836       UNIMPLEMENTED();
   5837       break;
   5838     }
   5839     case EXTERNAL_BYTE_ELEMENTS:
   5840     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
   5841     case EXTERNAL_SHORT_ELEMENTS:
   5842     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
   5843     case EXTERNAL_INT_ELEMENTS:
   5844     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
   5845     case EXTERNAL_FLOAT_ELEMENTS: {
   5846       // TODO(kbr): Add testcase and implement.
   5847       UNIMPLEMENTED();
   5848       break;
   5849     }
   5850     case DICTIONARY_ELEMENTS: {
   5851       NumberDictionary* dictionary = element_dictionary();
   5852       int entry = dictionary->FindEntry(index);
   5853       if (entry != NumberDictionary::kNotFound) {
   5854         Object* element = dictionary->ValueAt(entry);
   5855         PropertyDetails details = dictionary->DetailsAt(entry);
   5856         if (details.type() == CALLBACKS) {
   5857           // Only accessors allowed as elements.
   5858           FixedArray* structure = FixedArray::cast(element);
   5859           Object* getter = structure->get(kGetterIndex);
   5860           if (getter->IsJSFunction()) {
   5861             return GetPropertyWithDefinedGetter(receiver,
   5862                                                 JSFunction::cast(getter));
   5863           } else {
   5864             // Getter is not a function.
   5865             return Heap::undefined_value();
   5866           }
   5867         }
   5868         return element;
   5869       }
   5870       break;
   5871     }
   5872     default:
   5873       UNREACHABLE();
   5874       break;
   5875   }
   5876 
   5877   // Continue searching via the prototype chain.
   5878   Object* pt = GetPrototype();
   5879   if (pt == Heap::null_value()) return Heap::undefined_value();
   5880   return pt->GetElementWithReceiver(receiver, index);
   5881 }
   5882 
   5883 
   5884 Object* JSObject::GetElementWithInterceptor(JSObject* receiver,
   5885                                             uint32_t index) {
   5886   // Make sure that the top context does not change when doing
   5887   // callbacks or interceptor calls.
   5888   AssertNoContextChange ncc;
   5889   HandleScope scope;
   5890   Handle<InterceptorInfo> interceptor(GetIndexedInterceptor());
   5891   Handle<JSObject> this_handle(receiver);
   5892   Handle<JSObject> holder_handle(this);
   5893 
   5894   if (!interceptor->getter()->IsUndefined()) {
   5895     v8::IndexedPropertyGetter getter =
   5896         v8::ToCData<v8::IndexedPropertyGetter>(interceptor->getter());
   5897     LOG(ApiIndexedPropertyAccess("interceptor-indexed-get", this, index));
   5898     CustomArguments args(interceptor->data(), receiver, this);
   5899     v8::AccessorInfo info(args.end());
   5900     v8::Handle<v8::Value> result;
   5901     {
   5902       // Leaving JavaScript.
   5903       VMState state(EXTERNAL);
   5904       result = getter(index, info);
   5905     }
   5906     RETURN_IF_SCHEDULED_EXCEPTION();
   5907     if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
   5908   }
   5909 
   5910   Object* raw_result =
   5911       holder_handle->GetElementPostInterceptor(*this_handle, index);
   5912   RETURN_IF_SCHEDULED_EXCEPTION();
   5913   return raw_result;
   5914 }
   5915 
   5916 
   5917 Object* JSObject::GetElementWithReceiver(JSObject* receiver, uint32_t index) {
   5918   // Check access rights if needed.
   5919   if (IsAccessCheckNeeded() &&
   5920       !Top::MayIndexedAccess(this, index, v8::ACCESS_GET)) {
   5921     Top::ReportFailedAccessCheck(this, v8::ACCESS_GET);
   5922     return Heap::undefined_value();
   5923   }
   5924 
   5925   if (HasIndexedInterceptor()) {
   5926     return GetElementWithInterceptor(receiver, index);
   5927   }
   5928 
   5929   // Get element works for both JSObject and JSArray since
   5930   // JSArray::length cannot change.
   5931   switch (GetElementsKind()) {
   5932     case FAST_ELEMENTS: {
   5933       FixedArray* elms = FixedArray::cast(elements());
   5934       if (index < static_cast<uint32_t>(elms->length())) {
   5935         Object* value = elms->get(index);
   5936         if (!value->IsTheHole()) return value;
   5937       }
   5938       break;
   5939     }
   5940     case PIXEL_ELEMENTS: {
   5941       PixelArray* pixels = PixelArray::cast(elements());
   5942       if (index < static_cast<uint32_t>(pixels->length())) {
   5943         uint8_t value = pixels->get(index);
   5944         return Smi::FromInt(value);
   5945       }
   5946       break;
   5947     }
   5948     case EXTERNAL_BYTE_ELEMENTS: {
   5949       ExternalByteArray* array = ExternalByteArray::cast(elements());
   5950       if (index < static_cast<uint32_t>(array->length())) {
   5951         int8_t value = array->get(index);
   5952         return Smi::FromInt(value);
   5953       }
   5954       break;
   5955     }
   5956     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: {
   5957       ExternalUnsignedByteArray* array =
   5958           ExternalUnsignedByteArray::cast(elements());
   5959       if (index < static_cast<uint32_t>(array->length())) {
   5960         uint8_t value = array->get(index);
   5961         return Smi::FromInt(value);
   5962       }
   5963       break;
   5964     }
   5965     case EXTERNAL_SHORT_ELEMENTS: {
   5966       ExternalShortArray* array = ExternalShortArray::cast(elements());
   5967       if (index < static_cast<uint32_t>(array->length())) {
   5968         int16_t value = array->get(index);
   5969         return Smi::FromInt(value);
   5970       }
   5971       break;
   5972     }
   5973     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: {
   5974       ExternalUnsignedShortArray* array =
   5975           ExternalUnsignedShortArray::cast(elements());
   5976       if (index < static_cast<uint32_t>(array->length())) {
   5977         uint16_t value = array->get(index);
   5978         return Smi::FromInt(value);
   5979       }
   5980       break;
   5981     }
   5982     case EXTERNAL_INT_ELEMENTS: {
   5983       ExternalIntArray* array = ExternalIntArray::cast(elements());
   5984       if (index < static_cast<uint32_t>(array->length())) {
   5985         int32_t value = array->get(index);
   5986         return Heap::NumberFromInt32(value);
   5987       }
   5988       break;
   5989     }
   5990     case EXTERNAL_UNSIGNED_INT_ELEMENTS: {
   5991       ExternalUnsignedIntArray* array =
   5992           ExternalUnsignedIntArray::cast(elements());
   5993       if (index < static_cast<uint32_t>(array->length())) {
   5994         uint32_t value = array->get(index);
   5995         return Heap::NumberFromUint32(value);
   5996       }
   5997       break;
   5998     }
   5999     case EXTERNAL_FLOAT_ELEMENTS: {
   6000       ExternalFloatArray* array = ExternalFloatArray::cast(elements());
   6001       if (index < static_cast<uint32_t>(array->length())) {
   6002         float value = array->get(index);
   6003         return Heap::AllocateHeapNumber(value);
   6004       }
   6005       break;
   6006     }
   6007     case DICTIONARY_ELEMENTS: {
   6008       NumberDictionary* dictionary = element_dictionary();
   6009       int entry = dictionary->FindEntry(index);
   6010       if (entry != NumberDictionary::kNotFound) {
   6011         Object* element = dictionary->ValueAt(entry);
   6012         PropertyDetails details = dictionary->DetailsAt(entry);
   6013         if (details.type() == CALLBACKS) {
   6014           // Only accessors allowed as elements.
   6015           FixedArray* structure = FixedArray::cast(element);
   6016           Object* getter = structure->get(kGetterIndex);
   6017           if (getter->IsJSFunction()) {
   6018             return GetPropertyWithDefinedGetter(receiver,
   6019                                                 JSFunction::cast(getter));
   6020           } else {
   6021             // Getter is not a function.
   6022             return Heap::undefined_value();
   6023           }
   6024         }
   6025         return element;
   6026       }
   6027       break;
   6028     }
   6029   }
   6030 
   6031   Object* pt = GetPrototype();
   6032   if (pt == Heap::null_value()) return Heap::undefined_value();
   6033   return pt->GetElementWithReceiver(receiver, index);
   6034 }
   6035 
   6036 
   6037 bool JSObject::HasDenseElements() {
   6038   int capacity = 0;
   6039   int number_of_elements = 0;
   6040 
   6041   switch (GetElementsKind()) {
   6042     case FAST_ELEMENTS: {
   6043       FixedArray* elms = FixedArray::cast(elements());
   6044       capacity = elms->length();
   6045       for (int i = 0; i < capacity; i++) {
   6046         if (!elms->get(i)->IsTheHole()) number_of_elements++;
   6047       }
   6048       break;
   6049     }
   6050     case PIXEL_ELEMENTS:
   6051     case EXTERNAL_BYTE_ELEMENTS:
   6052     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
   6053     case EXTERNAL_SHORT_ELEMENTS:
   6054     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
   6055     case EXTERNAL_INT_ELEMENTS:
   6056     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
   6057     case EXTERNAL_FLOAT_ELEMENTS: {
   6058       return true;
   6059     }
   6060     case DICTIONARY_ELEMENTS: {
   6061       NumberDictionary* dictionary = NumberDictionary::cast(elements());
   6062       capacity = dictionary->Capacity();
   6063       number_of_elements = dictionary->NumberOfElements();
   6064       break;
   6065     }
   6066     default:
   6067       UNREACHABLE();
   6068       break;
   6069   }
   6070 
   6071   if (capacity == 0) return true;
   6072   return (number_of_elements > (capacity / 2));
   6073 }
   6074 
   6075 
   6076 bool JSObject::ShouldConvertToSlowElements(int new_capacity) {
   6077   ASSERT(HasFastElements());
   6078   // Keep the array in fast case if the current backing storage is
   6079   // almost filled and if the new capacity is no more than twice the
   6080   // old capacity.
   6081   int elements_length = FixedArray::cast(elements())->length();
   6082   return !HasDenseElements() || ((new_capacity / 2) > elements_length);
   6083 }
   6084 
   6085 
   6086 bool JSObject::ShouldConvertToFastElements() {
   6087   ASSERT(HasDictionaryElements());
   6088   NumberDictionary* dictionary = NumberDictionary::cast(elements());
   6089   // If the elements are sparse, we should not go back to fast case.
   6090   if (!HasDenseElements()) return false;
   6091   // If an element has been added at a very high index in the elements
   6092   // dictionary, we cannot go back to fast case.
   6093   if (dictionary->requires_slow_elements()) return false;
   6094   // An object requiring access checks is never allowed to have fast
   6095   // elements.  If it had fast elements we would skip security checks.
   6096   if (IsAccessCheckNeeded()) return false;
   6097   // If the dictionary backing storage takes up roughly half as much
   6098   // space as a fast-case backing storage would the array should have
   6099   // fast elements.
   6100   uint32_t length = 0;
   6101   if (IsJSArray()) {
   6102     CHECK(Array::IndexFromObject(JSArray::cast(this)->length(), &length));
   6103   } else {
   6104     length = dictionary->max_number_key();
   6105   }
   6106   return static_cast<uint32_t>(dictionary->Capacity()) >=
   6107       (length / (2 * NumberDictionary::kEntrySize));
   6108 }
   6109 
   6110 
   6111 // Certain compilers request function template instantiation when they
   6112 // see the definition of the other template functions in the
   6113 // class. This requires us to have the template functions put
   6114 // together, so even though this function belongs in objects-debug.cc,
   6115 // we keep it here instead to satisfy certain compilers.
   6116 #ifdef DEBUG
   6117 template<typename Shape, typename Key>
   6118 void Dictionary<Shape, Key>::Print() {
   6119   int capacity = HashTable<Shape, Key>::Capacity();
   6120   for (int i = 0; i < capacity; i++) {
   6121     Object* k = HashTable<Shape, Key>::KeyAt(i);
   6122     if (HashTable<Shape, Key>::IsKey(k)) {
   6123       PrintF(" ");
   6124       if (k->IsString()) {
   6125         String::cast(k)->StringPrint();
   6126       } else {
   6127         k->ShortPrint();
   6128       }
   6129       PrintF(": ");
   6130       ValueAt(i)->ShortPrint();
   6131       PrintF("\n");
   6132     }
   6133   }
   6134 }
   6135 #endif
   6136 
   6137 
   6138 template<typename Shape, typename Key>
   6139 void Dictionary<Shape, Key>::CopyValuesTo(FixedArray* elements) {
   6140   int pos = 0;
   6141   int capacity = HashTable<Shape, Key>::Capacity();
   6142   AssertNoAllocation no_gc;
   6143   WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc);
   6144   for (int i = 0; i < capacity; i++) {
   6145     Object* k =  Dictionary<Shape, Key>::KeyAt(i);
   6146     if (Dictionary<Shape, Key>::IsKey(k)) {
   6147       elements->set(pos++, ValueAt(i), mode);
   6148     }
   6149   }
   6150   ASSERT(pos == elements->length());
   6151 }
   6152 
   6153 
   6154 InterceptorInfo* JSObject::GetNamedInterceptor() {
   6155   ASSERT(map()->has_named_interceptor());
   6156   JSFunction* constructor = JSFunction::cast(map()->constructor());
   6157   Object* template_info = constructor->shared()->function_data();
   6158   Object* result =
   6159       FunctionTemplateInfo::cast(template_info)->named_property_handler();
   6160   return InterceptorInfo::cast(result);
   6161 }
   6162 
   6163 
   6164 InterceptorInfo* JSObject::GetIndexedInterceptor() {
   6165   ASSERT(map()->has_indexed_interceptor());
   6166   JSFunction* constructor = JSFunction::cast(map()->constructor());
   6167   Object* template_info = constructor->shared()->function_data();
   6168   Object* result =
   6169       FunctionTemplateInfo::cast(template_info)->indexed_property_handler();
   6170   return InterceptorInfo::cast(result);
   6171 }
   6172 
   6173 
   6174 Object* JSObject::GetPropertyPostInterceptor(JSObject* receiver,
   6175                                              String* name,
   6176                                              PropertyAttributes* attributes) {
   6177   // Check local property in holder, ignore interceptor.
   6178   LookupResult result;
   6179   LocalLookupRealNamedProperty(name, &result);
   6180   if (result.IsProperty()) {
   6181     return GetProperty(receiver, &result, name, attributes);
   6182   }
   6183   // Continue searching via the prototype chain.
   6184   Object* pt = GetPrototype();
   6185   *attributes = ABSENT;
   6186   if (pt == Heap::null_value()) return Heap::undefined_value();
   6187   return pt->GetPropertyWithReceiver(receiver, name, attributes);
   6188 }
   6189 
   6190 
   6191 Object* JSObject::GetLocalPropertyPostInterceptor(
   6192     JSObject* receiver,
   6193     String* name,
   6194     PropertyAttributes* attributes) {
   6195   // Check local property in holder, ignore interceptor.
   6196   LookupResult result;
   6197   LocalLookupRealNamedProperty(name, &result);
   6198   if (result.IsProperty()) {
   6199     return GetProperty(receiver, &result, name, attributes);
   6200   }
   6201   return Heap::undefined_value();
   6202 }
   6203 
   6204 
   6205 Object* JSObject::GetPropertyWithInterceptor(
   6206     JSObject* receiver,
   6207     String* name,
   6208     PropertyAttributes* attributes) {
   6209   InterceptorInfo* interceptor = GetNamedInterceptor();
   6210   HandleScope scope;
   6211   Handle<JSObject> receiver_handle(receiver);
   6212   Handle<JSObject> holder_handle(this);
   6213   Handle<String> name_handle(name);
   6214 
   6215   if (!interceptor->getter()->IsUndefined()) {
   6216     v8::NamedPropertyGetter getter =
   6217         v8::ToCData<v8::NamedPropertyGetter>(interceptor->getter());
   6218     LOG(ApiNamedPropertyAccess("interceptor-named-get", *holder_handle, name));
   6219     CustomArguments args(interceptor->data(), receiver, this);
   6220     v8::AccessorInfo info(args.end());
   6221     v8::Handle<v8::Value> result;
   6222     {
   6223       // Leaving JavaScript.
   6224       VMState state(EXTERNAL);
   6225       result = getter(v8::Utils::ToLocal(name_handle), info);
   6226     }
   6227     RETURN_IF_SCHEDULED_EXCEPTION();
   6228     if (!result.IsEmpty()) {
   6229       *attributes = NONE;
   6230       return *v8::Utils::OpenHandle(*result);
   6231     }
   6232   }
   6233 
   6234   Object* result = holder_handle->GetPropertyPostInterceptor(
   6235       *receiver_handle,
   6236       *name_handle,
   6237       attributes);
   6238   RETURN_IF_SCHEDULED_EXCEPTION();
   6239   return result;
   6240 }
   6241 
   6242 
   6243 bool JSObject::HasRealNamedProperty(String* key) {
   6244   // Check access rights if needed.
   6245   if (IsAccessCheckNeeded() &&
   6246       !Top::MayNamedAccess(this, key, v8::ACCESS_HAS)) {
   6247     Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS);
   6248     return false;
   6249   }
   6250 
   6251   LookupResult result;
   6252   LocalLookupRealNamedProperty(key, &result);
   6253   return result.IsProperty() && (result.type() != INTERCEPTOR);
   6254 }
   6255 
   6256 
   6257 bool JSObject::HasRealElementProperty(uint32_t index) {
   6258   // Check access rights if needed.
   6259   if (IsAccessCheckNeeded() &&
   6260       !Top::MayIndexedAccess(this, index, v8::ACCESS_HAS)) {
   6261     Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS);
   6262     return false;
   6263   }
   6264 
   6265   // Handle [] on String objects.
   6266   if (this->IsStringObjectWithCharacterAt(index)) return true;
   6267 
   6268   switch (GetElementsKind()) {
   6269     case FAST_ELEMENTS: {
   6270       uint32_t length = IsJSArray() ?
   6271           static_cast<uint32_t>(
   6272               Smi::cast(JSArray::cast(this)->length())->value()) :
   6273           static_cast<uint32_t>(FixedArray::cast(elements())->length());
   6274       return (index < length) &&
   6275           !FixedArray::cast(elements())->get(index)->IsTheHole();
   6276     }
   6277     case PIXEL_ELEMENTS: {
   6278       PixelArray* pixels = PixelArray::cast(elements());
   6279       return index < static_cast<uint32_t>(pixels->length());
   6280     }
   6281     case EXTERNAL_BYTE_ELEMENTS:
   6282     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
   6283     case EXTERNAL_SHORT_ELEMENTS:
   6284     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
   6285     case EXTERNAL_INT_ELEMENTS:
   6286     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
   6287     case EXTERNAL_FLOAT_ELEMENTS: {
   6288       ExternalArray* array = ExternalArray::cast(elements());
   6289       return index < static_cast<uint32_t>(array->length());
   6290     }
   6291     case DICTIONARY_ELEMENTS: {
   6292       return element_dictionary()->FindEntry(index)
   6293           != NumberDictionary::kNotFound;
   6294     }
   6295     default:
   6296       UNREACHABLE();
   6297       break;
   6298   }
   6299   // All possibilities have been handled above already.
   6300   UNREACHABLE();
   6301   return Heap::null_value();
   6302 }
   6303 
   6304 
   6305 bool JSObject::HasRealNamedCallbackProperty(String* key) {
   6306   // Check access rights if needed.
   6307   if (IsAccessCheckNeeded() &&
   6308       !Top::MayNamedAccess(this, key, v8::ACCESS_HAS)) {
   6309     Top::ReportFailedAccessCheck(this, v8::ACCESS_HAS);
   6310     return false;
   6311   }
   6312 
   6313   LookupResult result;
   6314   LocalLookupRealNamedProperty(key, &result);
   6315   return result.IsProperty() && (result.type() == CALLBACKS);
   6316 }
   6317 
   6318 
   6319 int JSObject::NumberOfLocalProperties(PropertyAttributes filter) {
   6320   if (HasFastProperties()) {
   6321     DescriptorArray* descs = map()->instance_descriptors();
   6322     int result = 0;
   6323     for (int i = 0; i < descs->number_of_descriptors(); i++) {
   6324       PropertyDetails details = descs->GetDetails(i);
   6325       if (details.IsProperty() && (details.attributes() & filter) == 0) {
   6326         result++;
   6327       }
   6328     }
   6329     return result;
   6330   } else {
   6331     return property_dictionary()->NumberOfElementsFilterAttributes(filter);
   6332   }
   6333 }
   6334 
   6335 
   6336 int JSObject::NumberOfEnumProperties() {
   6337   return NumberOfLocalProperties(static_cast<PropertyAttributes>(DONT_ENUM));
   6338 }
   6339 
   6340 
   6341 void FixedArray::SwapPairs(FixedArray* numbers, int i, int j) {
   6342   Object* temp = get(i);
   6343   set(i, get(j));
   6344   set(j, temp);
   6345   if (this != numbers) {
   6346     temp = numbers->get(i);
   6347     numbers->set(i, numbers->get(j));
   6348     numbers->set(j, temp);
   6349   }
   6350 }
   6351 
   6352 
   6353 static void InsertionSortPairs(FixedArray* content,
   6354                                FixedArray* numbers,
   6355                                int len) {
   6356   for (int i = 1; i < len; i++) {
   6357     int j = i;
   6358     while (j > 0 &&
   6359            (NumberToUint32(numbers->get(j - 1)) >
   6360             NumberToUint32(numbers->get(j)))) {
   6361       content->SwapPairs(numbers, j - 1, j);
   6362       j--;
   6363     }
   6364   }
   6365 }
   6366 
   6367 
   6368 void HeapSortPairs(FixedArray* content, FixedArray* numbers, int len) {
   6369   // In-place heap sort.
   6370   ASSERT(content->length() == numbers->length());
   6371 
   6372   // Bottom-up max-heap construction.
   6373   for (int i = 1; i < len; ++i) {
   6374     int child_index = i;
   6375     while (child_index > 0) {
   6376       int parent_index = ((child_index + 1) >> 1) - 1;
   6377       uint32_t parent_value = NumberToUint32(numbers->get(parent_index));
   6378       uint32_t child_value = NumberToUint32(numbers->get(child_index));
   6379       if (parent_value < child_value) {
   6380         content->SwapPairs(numbers, parent_index, child_index);
   6381       } else {
   6382         break;
   6383       }
   6384       child_index = parent_index;
   6385     }
   6386   }
   6387 
   6388   // Extract elements and create sorted array.
   6389   for (int i = len - 1; i > 0; --i) {
   6390     // Put max element at the back of the array.
   6391     content->SwapPairs(numbers, 0, i);
   6392     // Sift down the new top element.
   6393     int parent_index = 0;
   6394     while (true) {
   6395       int child_index = ((parent_index + 1) << 1) - 1;
   6396       if (child_index >= i) break;
   6397       uint32_t child1_value = NumberToUint32(numbers->get(child_index));
   6398       uint32_t child2_value = NumberToUint32(numbers->get(child_index + 1));
   6399       uint32_t parent_value = NumberToUint32(numbers->get(parent_index));
   6400       if (child_index + 1 >= i || child1_value > child2_value) {
   6401         if (parent_value > child1_value) break;
   6402         content->SwapPairs(numbers, parent_index, child_index);
   6403         parent_index = child_index;
   6404       } else {
   6405         if (parent_value > child2_value) break;
   6406         content->SwapPairs(numbers, parent_index, child_index + 1);
   6407         parent_index = child_index + 1;
   6408       }
   6409     }
   6410   }
   6411 }
   6412 
   6413 
   6414 // Sort this array and the numbers as pairs wrt. the (distinct) numbers.
   6415 void FixedArray::SortPairs(FixedArray* numbers, uint32_t len) {
   6416   ASSERT(this->length() == numbers->length());
   6417   // For small arrays, simply use insertion sort.
   6418   if (len <= 10) {
   6419     InsertionSortPairs(this, numbers, len);
   6420     return;
   6421   }
   6422   // Check the range of indices.
   6423   uint32_t min_index = NumberToUint32(numbers->get(0));
   6424   uint32_t max_index = min_index;
   6425   uint32_t i;
   6426   for (i = 1; i < len; i++) {
   6427     if (NumberToUint32(numbers->get(i)) < min_index) {
   6428       min_index = NumberToUint32(numbers->get(i));
   6429     } else if (NumberToUint32(numbers->get(i)) > max_index) {
   6430       max_index = NumberToUint32(numbers->get(i));
   6431     }
   6432   }
   6433   if (max_index - min_index + 1 == len) {
   6434     // Indices form a contiguous range, unless there are duplicates.
   6435     // Do an in-place linear time sort assuming distinct numbers, but
   6436     // avoid hanging in case they are not.
   6437     for (i = 0; i < len; i++) {
   6438       uint32_t p;
   6439       uint32_t j = 0;
   6440       // While the current element at i is not at its correct position p,
   6441       // swap the elements at these two positions.
   6442       while ((p = NumberToUint32(numbers->get(i)) - min_index) != i &&
   6443              j++ < len) {
   6444         SwapPairs(numbers, i, p);
   6445       }
   6446     }
   6447   } else {
   6448     HeapSortPairs(this, numbers, len);
   6449     return;
   6450   }
   6451 }
   6452 
   6453 
   6454 // Fill in the names of local properties into the supplied storage. The main
   6455 // purpose of this function is to provide reflection information for the object
   6456 // mirrors.
   6457 void JSObject::GetLocalPropertyNames(FixedArray* storage, int index) {
   6458   ASSERT(storage->length() >= (NumberOfLocalProperties(NONE) - index));
   6459   if (HasFastProperties()) {
   6460     DescriptorArray* descs = map()->instance_descriptors();
   6461     for (int i = 0; i < descs->number_of_descriptors(); i++) {
   6462       if (descs->IsProperty(i)) storage->set(index++, descs->GetKey(i));
   6463     }
   6464     ASSERT(storage->length() >= index);
   6465   } else {
   6466     property_dictionary()->CopyKeysTo(storage);
   6467   }
   6468 }
   6469 
   6470 
   6471 int JSObject::NumberOfLocalElements(PropertyAttributes filter) {
   6472   return GetLocalElementKeys(NULL, filter);
   6473 }
   6474 
   6475 
   6476 int JSObject::NumberOfEnumElements() {
   6477   // Fast case for objects with no elements.
   6478   if (!IsJSValue() && HasFastElements()) {
   6479     uint32_t length = IsJSArray() ?
   6480         static_cast<uint32_t>(
   6481             Smi::cast(JSArray::cast(this)->length())->value()) :
   6482         static_cast<uint32_t>(FixedArray::cast(elements())->length());
   6483     if (length == 0) return 0;
   6484   }
   6485   // Compute the number of enumerable elements.
   6486   return NumberOfLocalElements(static_cast<PropertyAttributes>(DONT_ENUM));
   6487 }
   6488 
   6489 
   6490 int JSObject::GetLocalElementKeys(FixedArray* storage,
   6491                                   PropertyAttributes filter) {
   6492   int counter = 0;
   6493   switch (GetElementsKind()) {
   6494     case FAST_ELEMENTS: {
   6495       int length = IsJSArray() ?
   6496           Smi::cast(JSArray::cast(this)->length())->value() :
   6497           FixedArray::cast(elements())->length();
   6498       for (int i = 0; i < length; i++) {
   6499         if (!FixedArray::cast(elements())->get(i)->IsTheHole()) {
   6500           if (storage != NULL) {
   6501             storage->set(counter, Smi::FromInt(i));
   6502           }
   6503           counter++;
   6504         }
   6505       }
   6506       ASSERT(!storage || storage->length() >= counter);
   6507       break;
   6508     }
   6509     case PIXEL_ELEMENTS: {
   6510       int length = PixelArray::cast(elements())->length();
   6511       while (counter < length) {
   6512         if (storage != NULL) {
   6513           storage->set(counter, Smi::FromInt(counter));
   6514         }
   6515         counter++;
   6516       }
   6517       ASSERT(!storage || storage->length() >= counter);
   6518       break;
   6519     }
   6520     case EXTERNAL_BYTE_ELEMENTS:
   6521     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
   6522     case EXTERNAL_SHORT_ELEMENTS:
   6523     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
   6524     case EXTERNAL_INT_ELEMENTS:
   6525     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
   6526     case EXTERNAL_FLOAT_ELEMENTS: {
   6527       int length = ExternalArray::cast(elements())->length();
   6528       while (counter < length) {
   6529         if (storage != NULL) {
   6530           storage->set(counter, Smi::FromInt(counter));
   6531         }
   6532         counter++;
   6533       }
   6534       ASSERT(!storage || storage->length() >= counter);
   6535       break;
   6536     }
   6537     case DICTIONARY_ELEMENTS: {
   6538       if (storage != NULL) {
   6539         element_dictionary()->CopyKeysTo(storage, filter);
   6540       }
   6541       counter = element_dictionary()->NumberOfElementsFilterAttributes(filter);
   6542       break;
   6543     }
   6544     default:
   6545       UNREACHABLE();
   6546       break;
   6547   }
   6548 
   6549   if (this->IsJSValue()) {
   6550     Object* val = JSValue::cast(this)->value();
   6551     if (val->IsString()) {
   6552       String* str = String::cast(val);
   6553       if (storage) {
   6554         for (int i = 0; i < str->length(); i++) {
   6555           storage->set(counter + i, Smi::FromInt(i));
   6556         }
   6557       }
   6558       counter += str->length();
   6559     }
   6560   }
   6561   ASSERT(!storage || storage->length() == counter);
   6562   return counter;
   6563 }
   6564 
   6565 
   6566 int JSObject::GetEnumElementKeys(FixedArray* storage) {
   6567   return GetLocalElementKeys(storage,
   6568                              static_cast<PropertyAttributes>(DONT_ENUM));
   6569 }
   6570 
   6571 
   6572 bool NumberDictionaryShape::IsMatch(uint32_t key, Object* other) {
   6573   ASSERT(other->IsNumber());
   6574   return key == static_cast<uint32_t>(other->Number());
   6575 }
   6576 
   6577 
   6578 uint32_t NumberDictionaryShape::Hash(uint32_t key) {
   6579   return ComputeIntegerHash(key);
   6580 }
   6581 
   6582 
   6583 uint32_t NumberDictionaryShape::HashForObject(uint32_t key, Object* other) {
   6584   ASSERT(other->IsNumber());
   6585   return ComputeIntegerHash(static_cast<uint32_t>(other->Number()));
   6586 }
   6587 
   6588 
   6589 Object* NumberDictionaryShape::AsObject(uint32_t key) {
   6590   return Heap::NumberFromUint32(key);
   6591 }
   6592 
   6593 
   6594 bool StringDictionaryShape::IsMatch(String* key, Object* other) {
   6595   // We know that all entries in a hash table had their hash keys created.
   6596   // Use that knowledge to have fast failure.
   6597   if (key->Hash() != String::cast(other)->Hash()) return false;
   6598   return key->Equals(String::cast(other));
   6599 }
   6600 
   6601 
   6602 uint32_t StringDictionaryShape::Hash(String* key) {
   6603   return key->Hash();
   6604 }
   6605 
   6606 
   6607 uint32_t StringDictionaryShape::HashForObject(String* key, Object* other) {
   6608   return String::cast(other)->Hash();
   6609 }
   6610 
   6611 
   6612 Object* StringDictionaryShape::AsObject(String* key) {
   6613   return key;
   6614 }
   6615 
   6616 
   6617 // StringKey simply carries a string object as key.
   6618 class StringKey : public HashTableKey {
   6619  public:
   6620   explicit StringKey(String* string) :
   6621       string_(string),
   6622       hash_(HashForObject(string)) { }
   6623 
   6624   bool IsMatch(Object* string) {
   6625     // We know that all entries in a hash table had their hash keys created.
   6626     // Use that knowledge to have fast failure.
   6627     if (hash_ != HashForObject(string)) {
   6628       return false;
   6629     }
   6630     return string_->Equals(String::cast(string));
   6631   }
   6632 
   6633   uint32_t Hash() { return hash_; }
   6634 
   6635   uint32_t HashForObject(Object* other) { return String::cast(other)->Hash(); }
   6636 
   6637   Object* AsObject() { return string_; }
   6638 
   6639   String* string_;
   6640   uint32_t hash_;
   6641 };
   6642 
   6643 
   6644 // StringSharedKeys are used as keys in the eval cache.
   6645 class StringSharedKey : public HashTableKey {
   6646  public:
   6647   StringSharedKey(String* source, SharedFunctionInfo* shared)
   6648       : source_(source), shared_(shared) { }
   6649 
   6650   bool IsMatch(Object* other) {
   6651     if (!other->IsFixedArray()) return false;
   6652     FixedArray* pair = FixedArray::cast(other);
   6653     SharedFunctionInfo* shared = SharedFunctionInfo::cast(pair->get(0));
   6654     if (shared != shared_) return false;
   6655     String* source = String::cast(pair->get(1));
   6656     return source->Equals(source_);
   6657   }
   6658 
   6659   static uint32_t StringSharedHashHelper(String* source,
   6660                                          SharedFunctionInfo* shared) {
   6661     uint32_t hash = source->Hash();
   6662     if (shared->HasSourceCode()) {
   6663       // Instead of using the SharedFunctionInfo pointer in the hash
   6664       // code computation, we use a combination of the hash of the
   6665       // script source code and the start and end positions.  We do
   6666       // this to ensure that the cache entries can survive garbage
   6667       // collection.
   6668       Script* script = Script::cast(shared->script());
   6669       hash ^= String::cast(script->source())->Hash();
   6670       hash += shared->start_position();
   6671     }
   6672     return hash;
   6673   }
   6674 
   6675   uint32_t Hash() {
   6676     return StringSharedHashHelper(source_, shared_);
   6677   }
   6678 
   6679   uint32_t HashForObject(Object* obj) {
   6680     FixedArray* pair = FixedArray::cast(obj);
   6681     SharedFunctionInfo* shared = SharedFunctionInfo::cast(pair->get(0));
   6682     String* source = String::cast(pair->get(1));
   6683     return StringSharedHashHelper(source, shared);
   6684   }
   6685 
   6686   Object* AsObject() {
   6687     Object* obj = Heap::AllocateFixedArray(2);
   6688     if (obj->IsFailure()) return obj;
   6689     FixedArray* pair = FixedArray::cast(obj);
   6690     pair->set(0, shared_);
   6691     pair->set(1, source_);
   6692     return pair;
   6693   }
   6694 
   6695  private:
   6696   String* source_;
   6697   SharedFunctionInfo* shared_;
   6698 };
   6699 
   6700 
   6701 // RegExpKey carries the source and flags of a regular expression as key.
   6702 class RegExpKey : public HashTableKey {
   6703  public:
   6704   RegExpKey(String* string, JSRegExp::Flags flags)
   6705       : string_(string),
   6706         flags_(Smi::FromInt(flags.value())) { }
   6707 
   6708   // Rather than storing the key in the hash table, a pointer to the
   6709   // stored value is stored where the key should be.  IsMatch then
   6710   // compares the search key to the found object, rather than comparing
   6711   // a key to a key.
   6712   bool IsMatch(Object* obj) {
   6713     FixedArray* val = FixedArray::cast(obj);
   6714     return string_->Equals(String::cast(val->get(JSRegExp::kSourceIndex)))
   6715         && (flags_ == val->get(JSRegExp::kFlagsIndex));
   6716   }
   6717 
   6718   uint32_t Hash() { return RegExpHash(string_, flags_); }
   6719 
   6720   Object* AsObject() {
   6721     // Plain hash maps, which is where regexp keys are used, don't
   6722     // use this function.
   6723     UNREACHABLE();
   6724     return NULL;
   6725   }
   6726 
   6727   uint32_t HashForObject(Object* obj) {
   6728     FixedArray* val = FixedArray::cast(obj);
   6729     return RegExpHash(String::cast(val->get(JSRegExp::kSourceIndex)),
   6730                       Smi::cast(val->get(JSRegExp::kFlagsIndex)));
   6731   }
   6732 
   6733   static uint32_t RegExpHash(String* string, Smi* flags) {
   6734     return string->Hash() + flags->value();
   6735   }
   6736 
   6737   String* string_;
   6738   Smi* flags_;
   6739 };
   6740 
   6741 // Utf8SymbolKey carries a vector of chars as key.
   6742 class Utf8SymbolKey : public HashTableKey {
   6743  public:
   6744   explicit Utf8SymbolKey(Vector<const char> string)
   6745       : string_(string), hash_field_(0) { }
   6746 
   6747   bool IsMatch(Object* string) {
   6748     return String::cast(string)->IsEqualTo(string_);
   6749   }
   6750 
   6751   uint32_t Hash() {
   6752     if (hash_field_ != 0) return hash_field_ >> String::kHashShift;
   6753     unibrow::Utf8InputBuffer<> buffer(string_.start(),
   6754                                       static_cast<unsigned>(string_.length()));
   6755     chars_ = buffer.Length();
   6756     hash_field_ = String::ComputeHashField(&buffer, chars_);
   6757     uint32_t result = hash_field_ >> String::kHashShift;
   6758     ASSERT(result != 0);  // Ensure that the hash value of 0 is never computed.
   6759     return result;
   6760   }
   6761 
   6762   uint32_t HashForObject(Object* other) {
   6763     return String::cast(other)->Hash();
   6764   }
   6765 
   6766   Object* AsObject() {
   6767     if (hash_field_ == 0) Hash();
   6768     return Heap::AllocateSymbol(string_, chars_, hash_field_);
   6769   }
   6770 
   6771   Vector<const char> string_;
   6772   uint32_t hash_field_;
   6773   int chars_;  // Caches the number of characters when computing the hash code.
   6774 };
   6775 
   6776 
   6777 // SymbolKey carries a string/symbol object as key.
   6778 class SymbolKey : public HashTableKey {
   6779  public:
   6780   explicit SymbolKey(String* string) : string_(string) { }
   6781 
   6782   bool IsMatch(Object* string) {
   6783     return String::cast(string)->Equals(string_);
   6784   }
   6785 
   6786   uint32_t Hash() { return string_->Hash(); }
   6787 
   6788   uint32_t HashForObject(Object* other) {
   6789     return String::cast(other)->Hash();
   6790   }
   6791 
   6792   Object* AsObject() {
   6793     // If the string is a cons string, attempt to flatten it so that
   6794     // symbols will most often be flat strings.
   6795     if (StringShape(string_).IsCons()) {
   6796       ConsString* cons_string = ConsString::cast(string_);
   6797       cons_string->TryFlatten();
   6798       if (cons_string->second()->length() == 0) {
   6799         string_ = cons_string->first();
   6800       }
   6801     }
   6802     // Transform string to symbol if possible.
   6803     Map* map = Heap::SymbolMapForString(string_);
   6804     if (map != NULL) {
   6805       string_->set_map(map);
   6806       ASSERT(string_->IsSymbol());
   6807       return string_;
   6808     }
   6809     // Otherwise allocate a new symbol.
   6810     StringInputBuffer buffer(string_);
   6811     return Heap::AllocateInternalSymbol(&buffer,
   6812                                         string_->length(),
   6813                                         string_->hash_field());
   6814   }
   6815 
   6816   static uint32_t StringHash(Object* obj) {
   6817     return String::cast(obj)->Hash();
   6818   }
   6819 
   6820   String* string_;
   6821 };
   6822 
   6823 
   6824 template<typename Shape, typename Key>
   6825 void HashTable<Shape, Key>::IteratePrefix(ObjectVisitor* v) {
   6826   IteratePointers(v, 0, kElementsStartOffset);
   6827 }
   6828 
   6829 
   6830 template<typename Shape, typename Key>
   6831 void HashTable<Shape, Key>::IterateElements(ObjectVisitor* v) {
   6832   IteratePointers(v,
   6833                   kElementsStartOffset,
   6834                   kHeaderSize + length() * kPointerSize);
   6835 }
   6836 
   6837 
   6838 template<typename Shape, typename Key>
   6839 Object* HashTable<Shape, Key>::Allocate(int at_least_space_for) {
   6840   int capacity = RoundUpToPowerOf2(at_least_space_for);
   6841   if (capacity < 4) {
   6842     capacity = 4;  // Guarantee min capacity.
   6843   } else if (capacity > HashTable::kMaxCapacity) {
   6844     return Failure::OutOfMemoryException();
   6845   }
   6846 
   6847   Object* obj = Heap::AllocateHashTable(EntryToIndex(capacity));
   6848   if (!obj->IsFailure()) {
   6849     HashTable::cast(obj)->SetNumberOfElements(0);
   6850     HashTable::cast(obj)->SetNumberOfDeletedElements(0);
   6851     HashTable::cast(obj)->SetCapacity(capacity);
   6852   }
   6853   return obj;
   6854 }
   6855 
   6856 
   6857 // Find entry for key otherwise return kNotFound.
   6858 template<typename Shape, typename Key>
   6859 int HashTable<Shape, Key>::FindEntry(Key key) {
   6860   uint32_t capacity = Capacity();
   6861   uint32_t entry = FirstProbe(Shape::Hash(key), capacity);
   6862   uint32_t count = 1;
   6863   // EnsureCapacity will guarantee the hash table is never full.
   6864   while (true) {
   6865     Object* element = KeyAt(entry);
   6866     if (element->IsUndefined()) break;  // Empty entry.
   6867     if (!element->IsNull() && Shape::IsMatch(key, element)) return entry;
   6868     entry = NextProbe(entry, count++, capacity);
   6869   }
   6870   return kNotFound;
   6871 }
   6872 
   6873 
   6874 template<typename Shape, typename Key>
   6875 Object* HashTable<Shape, Key>::EnsureCapacity(int n, Key key) {
   6876   int capacity = Capacity();
   6877   int nof = NumberOfElements() + n;
   6878   int nod = NumberOfDeletedElements();
   6879   // Return if:
   6880   //   50% is still free after adding n elements and
   6881   //   at most 50% of the free elements are deleted elements.
   6882   if ((nof + (nof >> 1) <= capacity) &&
   6883       (nod <= (capacity - nof) >> 1)) return this;
   6884 
   6885   Object* obj = Allocate(nof * 2);
   6886   if (obj->IsFailure()) return obj;
   6887 
   6888   AssertNoAllocation no_gc;
   6889   HashTable* table = HashTable::cast(obj);
   6890   WriteBarrierMode mode = table->GetWriteBarrierMode(no_gc);
   6891 
   6892   // Copy prefix to new array.
   6893   for (int i = kPrefixStartIndex;
   6894        i < kPrefixStartIndex + Shape::kPrefixSize;
   6895        i++) {
   6896     table->set(i, get(i), mode);
   6897   }
   6898   // Rehash the elements.
   6899   for (int i = 0; i < capacity; i++) {
   6900     uint32_t from_index = EntryToIndex(i);
   6901     Object* k = get(from_index);
   6902     if (IsKey(k)) {
   6903       uint32_t hash = Shape::HashForObject(key, k);
   6904       uint32_t insertion_index =
   6905           EntryToIndex(table->FindInsertionEntry(hash));
   6906       for (int j = 0; j < Shape::kEntrySize; j++) {
   6907         table->set(insertion_index + j, get(from_index + j), mode);
   6908       }
   6909     }
   6910   }
   6911   table->SetNumberOfElements(NumberOfElements());
   6912   table->SetNumberOfDeletedElements(0);
   6913   return table;
   6914 }
   6915 
   6916 
   6917 
   6918 template<typename Shape, typename Key>
   6919 uint32_t HashTable<Shape, Key>::FindInsertionEntry(uint32_t hash) {
   6920   uint32_t capacity = Capacity();
   6921   uint32_t entry = FirstProbe(hash, capacity);
   6922   uint32_t count = 1;
   6923   // EnsureCapacity will guarantee the hash table is never full.
   6924   while (true) {
   6925     Object* element = KeyAt(entry);
   6926     if (element->IsUndefined() || element->IsNull()) break;
   6927     entry = NextProbe(entry, count++, capacity);
   6928   }
   6929   return entry;
   6930 }
   6931 
   6932 // Force instantiation of template instances class.
   6933 // Please note this list is compiler dependent.
   6934 
   6935 template class HashTable<SymbolTableShape, HashTableKey*>;
   6936 
   6937 template class HashTable<CompilationCacheShape, HashTableKey*>;
   6938 
   6939 template class HashTable<MapCacheShape, HashTableKey*>;
   6940 
   6941 template class Dictionary<StringDictionaryShape, String*>;
   6942 
   6943 template class Dictionary<NumberDictionaryShape, uint32_t>;
   6944 
   6945 template Object* Dictionary<NumberDictionaryShape, uint32_t>::Allocate(
   6946     int);
   6947 
   6948 template Object* Dictionary<StringDictionaryShape, String*>::Allocate(
   6949     int);
   6950 
   6951 template Object* Dictionary<NumberDictionaryShape, uint32_t>::AtPut(
   6952     uint32_t, Object*);
   6953 
   6954 template Object* Dictionary<NumberDictionaryShape, uint32_t>::SlowReverseLookup(
   6955     Object*);
   6956 
   6957 template Object* Dictionary<StringDictionaryShape, String*>::SlowReverseLookup(
   6958     Object*);
   6959 
   6960 template void Dictionary<NumberDictionaryShape, uint32_t>::CopyKeysTo(
   6961     FixedArray*, PropertyAttributes);
   6962 
   6963 template Object* Dictionary<StringDictionaryShape, String*>::DeleteProperty(
   6964     int, JSObject::DeleteMode);
   6965 
   6966 template Object* Dictionary<NumberDictionaryShape, uint32_t>::DeleteProperty(
   6967     int, JSObject::DeleteMode);
   6968 
   6969 template void Dictionary<StringDictionaryShape, String*>::CopyKeysTo(
   6970     FixedArray*);
   6971 
   6972 template int
   6973 Dictionary<StringDictionaryShape, String*>::NumberOfElementsFilterAttributes(
   6974     PropertyAttributes);
   6975 
   6976 template Object* Dictionary<StringDictionaryShape, String*>::Add(
   6977     String*, Object*, PropertyDetails);
   6978 
   6979 template Object*
   6980 Dictionary<StringDictionaryShape, String*>::GenerateNewEnumerationIndices();
   6981 
   6982 template int
   6983 Dictionary<NumberDictionaryShape, uint32_t>::NumberOfElementsFilterAttributes(
   6984     PropertyAttributes);
   6985 
   6986 template Object* Dictionary<NumberDictionaryShape, uint32_t>::Add(
   6987     uint32_t, Object*, PropertyDetails);
   6988 
   6989 template Object* Dictionary<NumberDictionaryShape, uint32_t>::EnsureCapacity(
   6990     int, uint32_t);
   6991 
   6992 template Object* Dictionary<StringDictionaryShape, String*>::EnsureCapacity(
   6993     int, String*);
   6994 
   6995 template Object* Dictionary<NumberDictionaryShape, uint32_t>::AddEntry(
   6996     uint32_t, Object*, PropertyDetails, uint32_t);
   6997 
   6998 template Object* Dictionary<StringDictionaryShape, String*>::AddEntry(
   6999     String*, Object*, PropertyDetails, uint32_t);
   7000 
   7001 template
   7002 int Dictionary<NumberDictionaryShape, uint32_t>::NumberOfEnumElements();
   7003 
   7004 template
   7005 int Dictionary<StringDictionaryShape, String*>::NumberOfEnumElements();
   7006 
   7007 template
   7008 int HashTable<NumberDictionaryShape, uint32_t>::FindEntry(uint32_t);
   7009 
   7010 
   7011 // Collates undefined and unexisting elements below limit from position
   7012 // zero of the elements. The object stays in Dictionary mode.
   7013 Object* JSObject::PrepareSlowElementsForSort(uint32_t limit) {
   7014   ASSERT(HasDictionaryElements());
   7015   // Must stay in dictionary mode, either because of requires_slow_elements,
   7016   // or because we are not going to sort (and therefore compact) all of the
   7017   // elements.
   7018   NumberDictionary* dict = element_dictionary();
   7019   HeapNumber* result_double = NULL;
   7020   if (limit > static_cast<uint32_t>(Smi::kMaxValue)) {
   7021     // Allocate space for result before we start mutating the object.
   7022     Object* new_double = Heap::AllocateHeapNumber(0.0);
   7023     if (new_double->IsFailure()) return new_double;
   7024     result_double = HeapNumber::cast(new_double);
   7025   }
   7026 
   7027   int capacity = dict->Capacity();
   7028   Object* obj = NumberDictionary::Allocate(dict->Capacity());
   7029   if (obj->IsFailure()) return obj;
   7030   NumberDictionary* new_dict = NumberDictionary::cast(obj);
   7031 
   7032   AssertNoAllocation no_alloc;
   7033 
   7034   uint32_t pos = 0;
   7035   uint32_t undefs = 0;
   7036   for (int i = 0; i < capacity; i++) {
   7037     Object* k = dict->KeyAt(i);
   7038     if (dict->IsKey(k)) {
   7039       ASSERT(k->IsNumber());
   7040       ASSERT(!k->IsSmi() || Smi::cast(k)->value() >= 0);
   7041       ASSERT(!k->IsHeapNumber() || HeapNumber::cast(k)->value() >= 0);
   7042       ASSERT(!k->IsHeapNumber() || HeapNumber::cast(k)->value() <= kMaxUInt32);
   7043       Object* value = dict->ValueAt(i);
   7044       PropertyDetails details = dict->DetailsAt(i);
   7045       if (details.type() == CALLBACKS) {
   7046         // Bail out and do the sorting of undefineds and array holes in JS.
   7047         return Smi::FromInt(-1);
   7048       }
   7049       uint32_t key = NumberToUint32(k);
   7050       if (key < limit) {
   7051         if (value->IsUndefined()) {
   7052           undefs++;
   7053         } else {
   7054           new_dict->AddNumberEntry(pos, value, details);
   7055           pos++;
   7056         }
   7057       } else {
   7058         new_dict->AddNumberEntry(key, value, details);
   7059       }
   7060     }
   7061   }
   7062 
   7063   uint32_t result = pos;
   7064   PropertyDetails no_details = PropertyDetails(NONE, NORMAL);
   7065   while (undefs > 0) {
   7066     new_dict->AddNumberEntry(pos, Heap::undefined_value(), no_details);
   7067     pos++;
   7068     undefs--;
   7069   }
   7070 
   7071   set_elements(new_dict);
   7072 
   7073   if (result <= static_cast<uint32_t>(Smi::kMaxValue)) {
   7074     return Smi::FromInt(static_cast<int>(result));
   7075   }
   7076 
   7077   ASSERT_NE(NULL, result_double);
   7078   result_double->set_value(static_cast<double>(result));
   7079   return result_double;
   7080 }
   7081 
   7082 
   7083 // Collects all defined (non-hole) and non-undefined (array) elements at
   7084 // the start of the elements array.
   7085 // If the object is in dictionary mode, it is converted to fast elements
   7086 // mode.
   7087 Object* JSObject::PrepareElementsForSort(uint32_t limit) {
   7088   ASSERT(!HasPixelElements() && !HasExternalArrayElements());
   7089 
   7090   if (HasDictionaryElements()) {
   7091     // Convert to fast elements containing only the existing properties.
   7092     // Ordering is irrelevant, since we are going to sort anyway.
   7093     NumberDictionary* dict = element_dictionary();
   7094     if (IsJSArray() || dict->requires_slow_elements() ||
   7095         dict->max_number_key() >= limit) {
   7096       return PrepareSlowElementsForSort(limit);
   7097     }
   7098     // Convert to fast elements.
   7099 
   7100     PretenureFlag tenure = Heap::InNewSpace(this) ? NOT_TENURED: TENURED;
   7101     Object* new_array =
   7102         Heap::AllocateFixedArray(dict->NumberOfElements(), tenure);
   7103     if (new_array->IsFailure()) {
   7104       return new_array;
   7105     }
   7106     FixedArray* fast_elements = FixedArray::cast(new_array);
   7107     dict->CopyValuesTo(fast_elements);
   7108     set_elements(fast_elements);
   7109   }
   7110   ASSERT(HasFastElements());
   7111 
   7112   // Collect holes at the end, undefined before that and the rest at the
   7113   // start, and return the number of non-hole, non-undefined values.
   7114 
   7115   FixedArray* elements = FixedArray::cast(this->elements());
   7116   uint32_t elements_length = static_cast<uint32_t>(elements->length());
   7117   if (limit > elements_length) {
   7118     limit = elements_length ;
   7119   }
   7120   if (limit == 0) {
   7121     return Smi::FromInt(0);
   7122   }
   7123 
   7124   HeapNumber* result_double = NULL;
   7125   if (limit > static_cast<uint32_t>(Smi::kMaxValue)) {
   7126     // Pessimistically allocate space for return value before
   7127     // we start mutating the array.
   7128     Object* new_double = Heap::AllocateHeapNumber(0.0);
   7129     if (new_double->IsFailure()) return new_double;
   7130     result_double = HeapNumber::cast(new_double);
   7131   }
   7132 
   7133   AssertNoAllocation no_alloc;
   7134 
   7135   // Split elements into defined, undefined and the_hole, in that order.
   7136   // Only count locations for undefined and the hole, and fill them afterwards.
   7137   WriteBarrierMode write_barrier = elements->GetWriteBarrierMode(no_alloc);
   7138   unsigned int undefs = limit;
   7139   unsigned int holes = limit;
   7140   // Assume most arrays contain no holes and undefined values, so minimize the
   7141   // number of stores of non-undefined, non-the-hole values.
   7142   for (unsigned int i = 0; i < undefs; i++) {
   7143     Object* current = elements->get(i);
   7144     if (current->IsTheHole()) {
   7145       holes--;
   7146       undefs--;
   7147     } else if (current->IsUndefined()) {
   7148       undefs--;
   7149     } else {
   7150       continue;
   7151     }
   7152     // Position i needs to be filled.
   7153     while (undefs > i) {
   7154       current = elements->get(undefs);
   7155       if (current->IsTheHole()) {
   7156         holes--;
   7157         undefs--;
   7158       } else if (current->IsUndefined()) {
   7159         undefs--;
   7160       } else {
   7161         elements->set(i, current, write_barrier);
   7162         break;
   7163       }
   7164     }
   7165   }
   7166   uint32_t result = undefs;
   7167   while (undefs < holes) {
   7168     elements->set_undefined(undefs);
   7169     undefs++;
   7170   }
   7171   while (holes < limit) {
   7172     elements->set_the_hole(holes);
   7173     holes++;
   7174   }
   7175 
   7176   if (result <= static_cast<uint32_t>(Smi::kMaxValue)) {
   7177     return Smi::FromInt(static_cast<int>(result));
   7178   }
   7179   ASSERT_NE(NULL, result_double);
   7180   result_double->set_value(static_cast<double>(result));
   7181   return result_double;
   7182 }
   7183 
   7184 
   7185 Object* PixelArray::SetValue(uint32_t index, Object* value) {
   7186   uint8_t clamped_value = 0;
   7187   if (index < static_cast<uint32_t>(length())) {
   7188     if (value->IsSmi()) {
   7189       int int_value = Smi::cast(value)->value();
   7190       if (int_value < 0) {
   7191         clamped_value = 0;
   7192       } else if (int_value > 255) {
   7193         clamped_value = 255;
   7194       } else {
   7195         clamped_value = static_cast<uint8_t>(int_value);
   7196       }
   7197     } else if (value->IsHeapNumber()) {
   7198       double double_value = HeapNumber::cast(value)->value();
   7199       if (!(double_value > 0)) {
   7200         // NaN and less than zero clamp to zero.
   7201         clamped_value = 0;
   7202       } else if (double_value > 255) {
   7203         // Greater than 255 clamp to 255.
   7204         clamped_value = 255;
   7205       } else {
   7206         // Other doubles are rounded to the nearest integer.
   7207         clamped_value = static_cast<uint8_t>(double_value + 0.5);
   7208       }
   7209     } else {
   7210       // Clamp undefined to zero (default). All other types have been
   7211       // converted to a number type further up in the call chain.
   7212       ASSERT(value->IsUndefined());
   7213     }
   7214     set(index, clamped_value);
   7215   }
   7216   return Smi::FromInt(clamped_value);
   7217 }
   7218 
   7219 
   7220 template<typename ExternalArrayClass, typename ValueType>
   7221 static Object* ExternalArrayIntSetter(ExternalArrayClass* receiver,
   7222                                       uint32_t index,
   7223                                       Object* value) {
   7224   ValueType cast_value = 0;
   7225   if (index < static_cast<uint32_t>(receiver->length())) {
   7226     if (value->IsSmi()) {
   7227       int int_value = Smi::cast(value)->value();
   7228       cast_value = static_cast<ValueType>(int_value);
   7229     } else if (value->IsHeapNumber()) {
   7230       double double_value = HeapNumber::cast(value)->value();
   7231       cast_value = static_cast<ValueType>(DoubleToInt32(double_value));
   7232     } else {
   7233       // Clamp undefined to zero (default). All other types have been
   7234       // converted to a number type further up in the call chain.
   7235       ASSERT(value->IsUndefined());
   7236     }
   7237     receiver->set(index, cast_value);
   7238   }
   7239   return Heap::NumberFromInt32(cast_value);
   7240 }
   7241 
   7242 
   7243 Object* ExternalByteArray::SetValue(uint32_t index, Object* value) {
   7244   return ExternalArrayIntSetter<ExternalByteArray, int8_t>
   7245       (this, index, value);
   7246 }
   7247 
   7248 
   7249 Object* ExternalUnsignedByteArray::SetValue(uint32_t index, Object* value) {
   7250   return ExternalArrayIntSetter<ExternalUnsignedByteArray, uint8_t>
   7251       (this, index, value);
   7252 }
   7253 
   7254 
   7255 Object* ExternalShortArray::SetValue(uint32_t index, Object* value) {
   7256   return ExternalArrayIntSetter<ExternalShortArray, int16_t>
   7257       (this, index, value);
   7258 }
   7259 
   7260 
   7261 Object* ExternalUnsignedShortArray::SetValue(uint32_t index, Object* value) {
   7262   return ExternalArrayIntSetter<ExternalUnsignedShortArray, uint16_t>
   7263       (this, index, value);
   7264 }
   7265 
   7266 
   7267 Object* ExternalIntArray::SetValue(uint32_t index, Object* value) {
   7268   return ExternalArrayIntSetter<ExternalIntArray, int32_t>
   7269       (this, index, value);
   7270 }
   7271 
   7272 
   7273 Object* ExternalUnsignedIntArray::SetValue(uint32_t index, Object* value) {
   7274   uint32_t cast_value = 0;
   7275   if (index < static_cast<uint32_t>(length())) {
   7276     if (value->IsSmi()) {
   7277       int int_value = Smi::cast(value)->value();
   7278       cast_value = static_cast<uint32_t>(int_value);
   7279     } else if (value->IsHeapNumber()) {
   7280       double double_value = HeapNumber::cast(value)->value();
   7281       cast_value = static_cast<uint32_t>(DoubleToUint32(double_value));
   7282     } else {
   7283       // Clamp undefined to zero (default). All other types have been
   7284       // converted to a number type further up in the call chain.
   7285       ASSERT(value->IsUndefined());
   7286     }
   7287     set(index, cast_value);
   7288   }
   7289   return Heap::NumberFromUint32(cast_value);
   7290 }
   7291 
   7292 
   7293 Object* ExternalFloatArray::SetValue(uint32_t index, Object* value) {
   7294   float cast_value = 0;
   7295   if (index < static_cast<uint32_t>(length())) {
   7296     if (value->IsSmi()) {
   7297       int int_value = Smi::cast(value)->value();
   7298       cast_value = static_cast<float>(int_value);
   7299     } else if (value->IsHeapNumber()) {
   7300       double double_value = HeapNumber::cast(value)->value();
   7301       cast_value = static_cast<float>(double_value);
   7302     } else {
   7303       // Clamp undefined to zero (default). All other types have been
   7304       // converted to a number type further up in the call chain.
   7305       ASSERT(value->IsUndefined());
   7306     }
   7307     set(index, cast_value);
   7308   }
   7309   return Heap::AllocateHeapNumber(cast_value);
   7310 }
   7311 
   7312 
   7313 Object* GlobalObject::GetPropertyCell(LookupResult* result) {
   7314   ASSERT(!HasFastProperties());
   7315   Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry());
   7316   ASSERT(value->IsJSGlobalPropertyCell());
   7317   return value;
   7318 }
   7319 
   7320 
   7321 Object* GlobalObject::EnsurePropertyCell(String* name) {
   7322   ASSERT(!HasFastProperties());
   7323   int entry = property_dictionary()->FindEntry(name);
   7324   if (entry == StringDictionary::kNotFound) {
   7325     Object* cell = Heap::AllocateJSGlobalPropertyCell(Heap::the_hole_value());
   7326     if (cell->IsFailure()) return cell;
   7327     PropertyDetails details(NONE, NORMAL);
   7328     details = details.AsDeleted();
   7329     Object* dictionary = property_dictionary()->Add(name, cell, details);
   7330     if (dictionary->IsFailure()) return dictionary;
   7331     set_properties(StringDictionary::cast(dictionary));
   7332     return cell;
   7333   } else {
   7334     Object* value = property_dictionary()->ValueAt(entry);
   7335     ASSERT(value->IsJSGlobalPropertyCell());
   7336     return value;
   7337   }
   7338 }
   7339 
   7340 
   7341 Object* SymbolTable::LookupString(String* string, Object** s) {
   7342   SymbolKey key(string);
   7343   return LookupKey(&key, s);
   7344 }
   7345 
   7346 
   7347 // This class is used for looking up two character strings in the symbol table.
   7348 // If we don't have a hit we don't want to waste much time so we unroll the
   7349 // string hash calculation loop here for speed.  Doesn't work if the two
   7350 // characters form a decimal integer, since such strings have a different hash
   7351 // algorithm.
   7352 class TwoCharHashTableKey : public HashTableKey {
   7353  public:
   7354   TwoCharHashTableKey(uint32_t c1, uint32_t c2)
   7355     : c1_(c1), c2_(c2) {
   7356     // Char 1.
   7357     uint32_t hash = c1 + (c1 << 10);
   7358     hash ^= hash >> 6;
   7359     // Char 2.
   7360     hash += c2;
   7361     hash += hash << 10;
   7362     hash ^= hash >> 6;
   7363     // GetHash.
   7364     hash += hash << 3;
   7365     hash ^= hash >> 11;
   7366     hash += hash << 15;
   7367     if (hash == 0) hash = 27;
   7368 #ifdef DEBUG
   7369     StringHasher hasher(2);
   7370     hasher.AddCharacter(c1);
   7371     hasher.AddCharacter(c2);
   7372     // If this assert fails then we failed to reproduce the two-character
   7373     // version of the string hashing algorithm above.  One reason could be
   7374     // that we were passed two digits as characters, since the hash
   7375     // algorithm is different in that case.
   7376     ASSERT_EQ(static_cast<int>(hasher.GetHash()), static_cast<int>(hash));
   7377 #endif
   7378     hash_ = hash;
   7379   }
   7380 
   7381   bool IsMatch(Object* o) {
   7382     if (!o->IsString()) return false;
   7383     String* other = String::cast(o);
   7384     if (other->length() != 2) return false;
   7385     if (other->Get(0) != c1_) return false;
   7386     return other->Get(1) == c2_;
   7387   }
   7388 
   7389   uint32_t Hash() { return hash_; }
   7390   uint32_t HashForObject(Object* key) {
   7391     if (!key->IsString()) return 0;
   7392     return String::cast(key)->Hash();
   7393   }
   7394 
   7395   Object* AsObject() {
   7396     // The TwoCharHashTableKey is only used for looking in the symbol
   7397     // table, not for adding to it.
   7398     UNREACHABLE();
   7399     return NULL;
   7400   }
   7401  private:
   7402   uint32_t c1_;
   7403   uint32_t c2_;
   7404   uint32_t hash_;
   7405 };
   7406 
   7407 
   7408 bool SymbolTable::LookupSymbolIfExists(String* string, String** symbol) {
   7409   SymbolKey key(string);
   7410   int entry = FindEntry(&key);
   7411   if (entry == kNotFound) {
   7412     return false;
   7413   } else {
   7414     String* result = String::cast(KeyAt(entry));
   7415     ASSERT(StringShape(result).IsSymbol());
   7416     *symbol = result;
   7417     return true;
   7418   }
   7419 }
   7420 
   7421 
   7422 bool SymbolTable::LookupTwoCharsSymbolIfExists(uint32_t c1,
   7423                                                uint32_t c2,
   7424                                                String** symbol) {
   7425   TwoCharHashTableKey key(c1, c2);
   7426   int entry = FindEntry(&key);
   7427   if (entry == kNotFound) {
   7428     return false;
   7429   } else {
   7430     String* result = String::cast(KeyAt(entry));
   7431     ASSERT(StringShape(result).IsSymbol());
   7432     *symbol = result;
   7433     return true;
   7434   }
   7435 }
   7436 
   7437 
   7438 Object* SymbolTable::LookupSymbol(Vector<const char> str, Object** s) {
   7439   Utf8SymbolKey key(str);
   7440   return LookupKey(&key, s);
   7441 }
   7442 
   7443 
   7444 Object* SymbolTable::LookupKey(HashTableKey* key, Object** s) {
   7445   int entry = FindEntry(key);
   7446 
   7447   // Symbol already in table.
   7448   if (entry != kNotFound) {
   7449     *s = KeyAt(entry);
   7450     return this;
   7451   }
   7452 
   7453   // Adding new symbol. Grow table if needed.
   7454   Object* obj = EnsureCapacity(1, key);
   7455   if (obj->IsFailure()) return obj;
   7456 
   7457   // Create symbol object.
   7458   Object* symbol = key->AsObject();
   7459   if (symbol->IsFailure()) return symbol;
   7460 
   7461   // If the symbol table grew as part of EnsureCapacity, obj is not
   7462   // the current symbol table and therefore we cannot use
   7463   // SymbolTable::cast here.
   7464   SymbolTable* table = reinterpret_cast<SymbolTable*>(obj);
   7465 
   7466   // Add the new symbol and return it along with the symbol table.
   7467   entry = table->FindInsertionEntry(key->Hash());
   7468   table->set(EntryToIndex(entry), symbol);
   7469   table->ElementAdded();
   7470   *s = symbol;
   7471   return table;
   7472 }
   7473 
   7474 
   7475 Object* CompilationCacheTable::Lookup(String* src) {
   7476   StringKey key(src);
   7477   int entry = FindEntry(&key);
   7478   if (entry == kNotFound) return Heap::undefined_value();
   7479   return get(EntryToIndex(entry) + 1);
   7480 }
   7481 
   7482 
   7483 Object* CompilationCacheTable::LookupEval(String* src, Context* context) {
   7484   StringSharedKey key(src, context->closure()->shared());
   7485   int entry = FindEntry(&key);
   7486   if (entry == kNotFound) return Heap::undefined_value();
   7487   return get(EntryToIndex(entry) + 1);
   7488 }
   7489 
   7490 
   7491 Object* CompilationCacheTable::LookupRegExp(String* src,
   7492                                             JSRegExp::Flags flags) {
   7493   RegExpKey key(src, flags);
   7494   int entry = FindEntry(&key);
   7495   if (entry == kNotFound) return Heap::undefined_value();
   7496   return get(EntryToIndex(entry) + 1);
   7497 }
   7498 
   7499 
   7500 Object* CompilationCacheTable::Put(String* src, Object* value) {
   7501   StringKey key(src);
   7502   Object* obj = EnsureCapacity(1, &key);
   7503   if (obj->IsFailure()) return obj;
   7504 
   7505   CompilationCacheTable* cache =
   7506       reinterpret_cast<CompilationCacheTable*>(obj);
   7507   int entry = cache->FindInsertionEntry(key.Hash());
   7508   cache->set(EntryToIndex(entry), src);
   7509   cache->set(EntryToIndex(entry) + 1, value);
   7510   cache->ElementAdded();
   7511   return cache;
   7512 }
   7513 
   7514 
   7515 Object* CompilationCacheTable::PutEval(String* src,
   7516                                        Context* context,
   7517                                        Object* value) {
   7518   StringSharedKey key(src, context->closure()->shared());
   7519   Object* obj = EnsureCapacity(1, &key);
   7520   if (obj->IsFailure()) return obj;
   7521 
   7522   CompilationCacheTable* cache =
   7523       reinterpret_cast<CompilationCacheTable*>(obj);
   7524   int entry = cache->FindInsertionEntry(key.Hash());
   7525 
   7526   Object* k = key.AsObject();
   7527   if (k->IsFailure()) return k;
   7528 
   7529   cache->set(EntryToIndex(entry), k);
   7530   cache->set(EntryToIndex(entry) + 1, value);
   7531   cache->ElementAdded();
   7532   return cache;
   7533 }
   7534 
   7535 
   7536 Object* CompilationCacheTable::PutRegExp(String* src,
   7537                                          JSRegExp::Flags flags,
   7538                                          FixedArray* value) {
   7539   RegExpKey key(src, flags);
   7540   Object* obj = EnsureCapacity(1, &key);
   7541   if (obj->IsFailure()) return obj;
   7542 
   7543   CompilationCacheTable* cache =
   7544       reinterpret_cast<CompilationCacheTable*>(obj);
   7545   int entry = cache->FindInsertionEntry(key.Hash());
   7546   // We store the value in the key slot, and compare the search key
   7547   // to the stored value with a custon IsMatch function during lookups.
   7548   cache->set(EntryToIndex(entry), value);
   7549   cache->set(EntryToIndex(entry) + 1, value);
   7550   cache->ElementAdded();
   7551   return cache;
   7552 }
   7553 
   7554 
   7555 // SymbolsKey used for HashTable where key is array of symbols.
   7556 class SymbolsKey : public HashTableKey {
   7557  public:
   7558   explicit SymbolsKey(FixedArray* symbols) : symbols_(symbols) { }
   7559 
   7560   bool IsMatch(Object* symbols) {
   7561     FixedArray* o = FixedArray::cast(symbols);
   7562     int len = symbols_->length();
   7563     if (o->length() != len) return false;
   7564     for (int i = 0; i < len; i++) {
   7565       if (o->get(i) != symbols_->get(i)) return false;
   7566     }
   7567     return true;
   7568   }
   7569 
   7570   uint32_t Hash() { return HashForObject(symbols_); }
   7571 
   7572   uint32_t HashForObject(Object* obj) {
   7573     FixedArray* symbols = FixedArray::cast(obj);
   7574     int len = symbols->length();
   7575     uint32_t hash = 0;
   7576     for (int i = 0; i < len; i++) {
   7577       hash ^= String::cast(symbols->get(i))->Hash();
   7578     }
   7579     return hash;
   7580   }
   7581 
   7582   Object* AsObject() { return symbols_; }
   7583 
   7584  private:
   7585   FixedArray* symbols_;
   7586 };
   7587 
   7588 
   7589 Object* MapCache::Lookup(FixedArray* array) {
   7590   SymbolsKey key(array);
   7591   int entry = FindEntry(&key);
   7592   if (entry == kNotFound) return Heap::undefined_value();
   7593   return get(EntryToIndex(entry) + 1);
   7594 }
   7595 
   7596 
   7597 Object* MapCache::Put(FixedArray* array, Map* value) {
   7598   SymbolsKey key(array);
   7599   Object* obj = EnsureCapacity(1, &key);
   7600   if (obj->IsFailure()) return obj;
   7601 
   7602   MapCache* cache = reinterpret_cast<MapCache*>(obj);
   7603   int entry = cache->FindInsertionEntry(key.Hash());
   7604   cache->set(EntryToIndex(entry), array);
   7605   cache->set(EntryToIndex(entry) + 1, value);
   7606   cache->ElementAdded();
   7607   return cache;
   7608 }
   7609 
   7610 
   7611 template<typename Shape, typename Key>
   7612 Object* Dictionary<Shape, Key>::Allocate(int at_least_space_for) {
   7613   Object* obj = HashTable<Shape, Key>::Allocate(at_least_space_for);
   7614   // Initialize the next enumeration index.
   7615   if (!obj->IsFailure()) {
   7616     Dictionary<Shape, Key>::cast(obj)->
   7617         SetNextEnumerationIndex(PropertyDetails::kInitialIndex);
   7618   }
   7619   return obj;
   7620 }
   7621 
   7622 
   7623 template<typename Shape, typename Key>
   7624 Object* Dictionary<Shape, Key>::GenerateNewEnumerationIndices() {
   7625   int length = HashTable<Shape, Key>::NumberOfElements();
   7626 
   7627   // Allocate and initialize iteration order array.
   7628   Object* obj = Heap::AllocateFixedArray(length);
   7629   if (obj->IsFailure()) return obj;
   7630   FixedArray* iteration_order = FixedArray::cast(obj);
   7631   for (int i = 0; i < length; i++) {
   7632     iteration_order->set(i, Smi::FromInt(i));
   7633   }
   7634 
   7635   // Allocate array with enumeration order.
   7636   obj = Heap::AllocateFixedArray(length);
   7637   if (obj->IsFailure()) return obj;
   7638   FixedArray* enumeration_order = FixedArray::cast(obj);
   7639 
   7640   // Fill the enumeration order array with property details.
   7641   int capacity = HashTable<Shape, Key>::Capacity();
   7642   int pos = 0;
   7643   for (int i = 0; i < capacity; i++) {
   7644     if (Dictionary<Shape, Key>::IsKey(Dictionary<Shape, Key>::KeyAt(i))) {
   7645       enumeration_order->set(pos++, Smi::FromInt(DetailsAt(i).index()));
   7646     }
   7647   }
   7648 
   7649   // Sort the arrays wrt. enumeration order.
   7650   iteration_order->SortPairs(enumeration_order, enumeration_order->length());
   7651 
   7652   // Overwrite the enumeration_order with the enumeration indices.
   7653   for (int i = 0; i < length; i++) {
   7654     int index = Smi::cast(iteration_order->get(i))->value();
   7655     int enum_index = PropertyDetails::kInitialIndex + i;
   7656     enumeration_order->set(index, Smi::FromInt(enum_index));
   7657   }
   7658 
   7659   // Update the dictionary with new indices.
   7660   capacity = HashTable<Shape, Key>::Capacity();
   7661   pos = 0;
   7662   for (int i = 0; i < capacity; i++) {
   7663     if (Dictionary<Shape, Key>::IsKey(Dictionary<Shape, Key>::KeyAt(i))) {
   7664       int enum_index = Smi::cast(enumeration_order->get(pos++))->value();
   7665       PropertyDetails details = DetailsAt(i);
   7666       PropertyDetails new_details =
   7667           PropertyDetails(details.attributes(), details.type(), enum_index);
   7668       DetailsAtPut(i, new_details);
   7669     }
   7670   }
   7671 
   7672   // Set the next enumeration index.
   7673   SetNextEnumerationIndex(PropertyDetails::kInitialIndex+length);
   7674   return this;
   7675 }
   7676 
   7677 template<typename Shape, typename Key>
   7678 Object* Dictionary<Shape, Key>::EnsureCapacity(int n, Key key) {
   7679   // Check whether there are enough enumeration indices to add n elements.
   7680   if (Shape::kIsEnumerable &&
   7681       !PropertyDetails::IsValidIndex(NextEnumerationIndex() + n)) {
   7682     // If not, we generate new indices for the properties.
   7683     Object* result = GenerateNewEnumerationIndices();
   7684     if (result->IsFailure()) return result;
   7685   }
   7686   return HashTable<Shape, Key>::EnsureCapacity(n, key);
   7687 }
   7688 
   7689 
   7690 void NumberDictionary::RemoveNumberEntries(uint32_t from, uint32_t to) {
   7691   // Do nothing if the interval [from, to) is empty.
   7692   if (from >= to) return;
   7693 
   7694   int removed_entries = 0;
   7695   Object* sentinel = Heap::null_value();
   7696   int capacity = Capacity();
   7697   for (int i = 0; i < capacity; i++) {
   7698     Object* key = KeyAt(i);
   7699     if (key->IsNumber()) {
   7700       uint32_t number = static_cast<uint32_t>(key->Number());
   7701       if (from <= number && number < to) {
   7702         SetEntry(i, sentinel, sentinel, Smi::FromInt(0));
   7703         removed_entries++;
   7704       }
   7705     }
   7706   }
   7707 
   7708   // Update the number of elements.
   7709   ElementsRemoved(removed_entries);
   7710 }
   7711 
   7712 
   7713 template<typename Shape, typename Key>
   7714 Object* Dictionary<Shape, Key>::DeleteProperty(int entry,
   7715                                                JSObject::DeleteMode mode) {
   7716   PropertyDetails details = DetailsAt(entry);
   7717   // Ignore attributes if forcing a deletion.
   7718   if (details.IsDontDelete() && mode == JSObject::NORMAL_DELETION) {
   7719     return Heap::false_value();
   7720   }
   7721   SetEntry(entry, Heap::null_value(), Heap::null_value(), Smi::FromInt(0));
   7722   HashTable<Shape, Key>::ElementRemoved();
   7723   return Heap::true_value();
   7724 }
   7725 
   7726 
   7727 template<typename Shape, typename Key>
   7728 Object* Dictionary<Shape, Key>::AtPut(Key key, Object* value) {
   7729   int entry = FindEntry(key);
   7730 
   7731   // If the entry is present set the value;
   7732   if (entry != Dictionary<Shape, Key>::kNotFound) {
   7733     ValueAtPut(entry, value);
   7734     return this;
   7735   }
   7736 
   7737   // Check whether the dictionary should be extended.
   7738   Object* obj = EnsureCapacity(1, key);
   7739   if (obj->IsFailure()) return obj;
   7740 
   7741   Object* k = Shape::AsObject(key);
   7742   if (k->IsFailure()) return k;
   7743   PropertyDetails details = PropertyDetails(NONE, NORMAL);
   7744   return Dictionary<Shape, Key>::cast(obj)->
   7745       AddEntry(key, value, details, Shape::Hash(key));
   7746 }
   7747 
   7748 
   7749 template<typename Shape, typename Key>
   7750 Object* Dictionary<Shape, Key>::Add(Key key,
   7751                                     Object* value,
   7752                                     PropertyDetails details) {
   7753   // Valdate key is absent.
   7754   SLOW_ASSERT((FindEntry(key) == Dictionary<Shape, Key>::kNotFound));
   7755   // Check whether the dictionary should be extended.
   7756   Object* obj = EnsureCapacity(1, key);
   7757   if (obj->IsFailure()) return obj;
   7758   return Dictionary<Shape, Key>::cast(obj)->
   7759       AddEntry(key, value, details, Shape::Hash(key));
   7760 }
   7761 
   7762 
   7763 // Add a key, value pair to the dictionary.
   7764 template<typename Shape, typename Key>
   7765 Object* Dictionary<Shape, Key>::AddEntry(Key key,
   7766                                          Object* value,
   7767                                          PropertyDetails details,
   7768                                          uint32_t hash) {
   7769   // Compute the key object.
   7770   Object* k = Shape::AsObject(key);
   7771   if (k->IsFailure()) return k;
   7772 
   7773   uint32_t entry = Dictionary<Shape, Key>::FindInsertionEntry(hash);
   7774   // Insert element at empty or deleted entry
   7775   if (!details.IsDeleted() && details.index() == 0 && Shape::kIsEnumerable) {
   7776     // Assign an enumeration index to the property and update
   7777     // SetNextEnumerationIndex.
   7778     int index = NextEnumerationIndex();
   7779     details = PropertyDetails(details.attributes(), details.type(), index);
   7780     SetNextEnumerationIndex(index + 1);
   7781   }
   7782   SetEntry(entry, k, value, details);
   7783   ASSERT((Dictionary<Shape, Key>::KeyAt(entry)->IsNumber()
   7784           || Dictionary<Shape, Key>::KeyAt(entry)->IsString()));
   7785   HashTable<Shape, Key>::ElementAdded();
   7786   return this;
   7787 }
   7788 
   7789 
   7790 void NumberDictionary::UpdateMaxNumberKey(uint32_t key) {
   7791   // If the dictionary requires slow elements an element has already
   7792   // been added at a high index.
   7793   if (requires_slow_elements()) return;
   7794   // Check if this index is high enough that we should require slow
   7795   // elements.
   7796   if (key > kRequiresSlowElementsLimit) {
   7797     set_requires_slow_elements();
   7798     return;
   7799   }
   7800   // Update max key value.
   7801   Object* max_index_object = get(kMaxNumberKeyIndex);
   7802   if (!max_index_object->IsSmi() || max_number_key() < key) {
   7803     FixedArray::set(kMaxNumberKeyIndex,
   7804                     Smi::FromInt(key << kRequiresSlowElementsTagSize));
   7805   }
   7806 }
   7807 
   7808 
   7809 Object* NumberDictionary::AddNumberEntry(uint32_t key,
   7810                                          Object* value,
   7811                                          PropertyDetails details) {
   7812   UpdateMaxNumberKey(key);
   7813   SLOW_ASSERT(FindEntry(key) == kNotFound);
   7814   return Add(key, value, details);
   7815 }
   7816 
   7817 
   7818 Object* NumberDictionary::AtNumberPut(uint32_t key, Object* value) {
   7819   UpdateMaxNumberKey(key);
   7820   return AtPut(key, value);
   7821 }
   7822 
   7823 
   7824 Object* NumberDictionary::Set(uint32_t key,
   7825                               Object* value,
   7826                               PropertyDetails details) {
   7827   int entry = FindEntry(key);
   7828   if (entry == kNotFound) return AddNumberEntry(key, value, details);
   7829   // Preserve enumeration index.
   7830   details = PropertyDetails(details.attributes(),
   7831                             details.type(),
   7832                             DetailsAt(entry).index());
   7833   SetEntry(entry, NumberDictionaryShape::AsObject(key), value, details);
   7834   return this;
   7835 }
   7836 
   7837 
   7838 
   7839 template<typename Shape, typename Key>
   7840 int Dictionary<Shape, Key>::NumberOfElementsFilterAttributes(
   7841     PropertyAttributes filter) {
   7842   int capacity = HashTable<Shape, Key>::Capacity();
   7843   int result = 0;
   7844   for (int i = 0; i < capacity; i++) {
   7845     Object* k = HashTable<Shape, Key>::KeyAt(i);
   7846     if (HashTable<Shape, Key>::IsKey(k)) {
   7847       PropertyDetails details = DetailsAt(i);
   7848       if (details.IsDeleted()) continue;
   7849       PropertyAttributes attr = details.attributes();
   7850       if ((attr & filter) == 0) result++;
   7851     }
   7852   }
   7853   return result;
   7854 }
   7855 
   7856 
   7857 template<typename Shape, typename Key>
   7858 int Dictionary<Shape, Key>::NumberOfEnumElements() {
   7859   return NumberOfElementsFilterAttributes(
   7860       static_cast<PropertyAttributes>(DONT_ENUM));
   7861 }
   7862 
   7863 
   7864 template<typename Shape, typename Key>
   7865 void Dictionary<Shape, Key>::CopyKeysTo(FixedArray* storage,
   7866                                         PropertyAttributes filter) {
   7867   ASSERT(storage->length() >= NumberOfEnumElements());
   7868   int capacity = HashTable<Shape, Key>::Capacity();
   7869   int index = 0;
   7870   for (int i = 0; i < capacity; i++) {
   7871      Object* k = HashTable<Shape, Key>::KeyAt(i);
   7872      if (HashTable<Shape, Key>::IsKey(k)) {
   7873        PropertyDetails details = DetailsAt(i);
   7874        if (details.IsDeleted()) continue;
   7875        PropertyAttributes attr = details.attributes();
   7876        if ((attr & filter) == 0) storage->set(index++, k);
   7877      }
   7878   }
   7879   storage->SortPairs(storage, index);
   7880   ASSERT(storage->length() >= index);
   7881 }
   7882 
   7883 
   7884 void StringDictionary::CopyEnumKeysTo(FixedArray* storage,
   7885                                       FixedArray* sort_array) {
   7886   ASSERT(storage->length() >= NumberOfEnumElements());
   7887   int capacity = Capacity();
   7888   int index = 0;
   7889   for (int i = 0; i < capacity; i++) {
   7890      Object* k = KeyAt(i);
   7891      if (IsKey(k)) {
   7892        PropertyDetails details = DetailsAt(i);
   7893        if (details.IsDeleted() || details.IsDontEnum()) continue;
   7894        storage->set(index, k);
   7895        sort_array->set(index, Smi::FromInt(details.index()));
   7896        index++;
   7897      }
   7898   }
   7899   storage->SortPairs(sort_array, sort_array->length());
   7900   ASSERT(storage->length() >= index);
   7901 }
   7902 
   7903 
   7904 template<typename Shape, typename Key>
   7905 void Dictionary<Shape, Key>::CopyKeysTo(FixedArray* storage) {
   7906   ASSERT(storage->length() >= NumberOfElementsFilterAttributes(
   7907       static_cast<PropertyAttributes>(NONE)));
   7908   int capacity = HashTable<Shape, Key>::Capacity();
   7909   int index = 0;
   7910   for (int i = 0; i < capacity; i++) {
   7911     Object* k = HashTable<Shape, Key>::KeyAt(i);
   7912     if (HashTable<Shape, Key>::IsKey(k)) {
   7913       PropertyDetails details = DetailsAt(i);
   7914       if (details.IsDeleted()) continue;
   7915       storage->set(index++, k);
   7916     }
   7917   }
   7918   ASSERT(storage->length() >= index);
   7919 }
   7920 
   7921 
   7922 // Backwards lookup (slow).
   7923 template<typename Shape, typename Key>
   7924 Object* Dictionary<Shape, Key>::SlowReverseLookup(Object* value) {
   7925   int capacity = HashTable<Shape, Key>::Capacity();
   7926   for (int i = 0; i < capacity; i++) {
   7927     Object* k =  HashTable<Shape, Key>::KeyAt(i);
   7928     if (Dictionary<Shape, Key>::IsKey(k)) {
   7929       Object* e = ValueAt(i);
   7930       if (e->IsJSGlobalPropertyCell()) {
   7931         e = JSGlobalPropertyCell::cast(e)->value();
   7932       }
   7933       if (e == value) return k;
   7934     }
   7935   }
   7936   return Heap::undefined_value();
   7937 }
   7938 
   7939 
   7940 Object* StringDictionary::TransformPropertiesToFastFor(
   7941     JSObject* obj, int unused_property_fields) {
   7942   // Make sure we preserve dictionary representation if there are too many
   7943   // descriptors.
   7944   if (NumberOfElements() > DescriptorArray::kMaxNumberOfDescriptors) return obj;
   7945 
   7946   // Figure out if it is necessary to generate new enumeration indices.
   7947   int max_enumeration_index =
   7948       NextEnumerationIndex() +
   7949           (DescriptorArray::kMaxNumberOfDescriptors -
   7950            NumberOfElements());
   7951   if (!PropertyDetails::IsValidIndex(max_enumeration_index)) {
   7952     Object* result = GenerateNewEnumerationIndices();
   7953     if (result->IsFailure()) return result;
   7954   }
   7955 
   7956   int instance_descriptor_length = 0;
   7957   int number_of_fields = 0;
   7958 
   7959   // Compute the length of the instance descriptor.
   7960   int capacity = Capacity();
   7961   for (int i = 0; i < capacity; i++) {
   7962     Object* k = KeyAt(i);
   7963     if (IsKey(k)) {
   7964       Object* value = ValueAt(i);
   7965       PropertyType type = DetailsAt(i).type();
   7966       ASSERT(type != FIELD);
   7967       instance_descriptor_length++;
   7968       if (type == NORMAL &&
   7969           (!value->IsJSFunction() || Heap::InNewSpace(value))) {
   7970         number_of_fields += 1;
   7971       }
   7972     }
   7973   }
   7974 
   7975   // Allocate the instance descriptor.
   7976   Object* descriptors_unchecked =
   7977       DescriptorArray::Allocate(instance_descriptor_length);
   7978   if (descriptors_unchecked->IsFailure()) return descriptors_unchecked;
   7979   DescriptorArray* descriptors = DescriptorArray::cast(descriptors_unchecked);
   7980 
   7981   int inobject_props = obj->map()->inobject_properties();
   7982   int number_of_allocated_fields =
   7983       number_of_fields + unused_property_fields - inobject_props;
   7984 
   7985   // Allocate the fixed array for the fields.
   7986   Object* fields = Heap::AllocateFixedArray(number_of_allocated_fields);
   7987   if (fields->IsFailure()) return fields;
   7988 
   7989   // Fill in the instance descriptor and the fields.
   7990   int next_descriptor = 0;
   7991   int current_offset = 0;
   7992   for (int i = 0; i < capacity; i++) {
   7993     Object* k = KeyAt(i);
   7994     if (IsKey(k)) {
   7995       Object* value = ValueAt(i);
   7996       // Ensure the key is a symbol before writing into the instance descriptor.
   7997       Object* key = Heap::LookupSymbol(String::cast(k));
   7998       if (key->IsFailure()) return key;
   7999       PropertyDetails details = DetailsAt(i);
   8000       PropertyType type = details.type();
   8001 
   8002       if (value->IsJSFunction() && !Heap::InNewSpace(value)) {
   8003         ConstantFunctionDescriptor d(String::cast(key),
   8004                                      JSFunction::cast(value),
   8005                                      details.attributes(),
   8006                                      details.index());
   8007         descriptors->Set(next_descriptor++, &d);
   8008       } else if (type == NORMAL) {
   8009         if (current_offset < inobject_props) {
   8010           obj->InObjectPropertyAtPut(current_offset,
   8011                                      value,
   8012                                      UPDATE_WRITE_BARRIER);
   8013         } else {
   8014           int offset = current_offset - inobject_props;
   8015           FixedArray::cast(fields)->set(offset, value);
   8016         }
   8017         FieldDescriptor d(String::cast(key),
   8018                           current_offset++,
   8019                           details.attributes(),
   8020                           details.index());
   8021         descriptors->Set(next_descriptor++, &d);
   8022       } else if (type == CALLBACKS) {
   8023         CallbacksDescriptor d(String::cast(key),
   8024                               value,
   8025                               details.attributes(),
   8026                               details.index());
   8027         descriptors->Set(next_descriptor++, &d);
   8028       } else {
   8029         UNREACHABLE();
   8030       }
   8031     }
   8032   }
   8033   ASSERT(current_offset == number_of_fields);
   8034 
   8035   descriptors->Sort();
   8036   // Allocate new map.
   8037   Object* new_map = obj->map()->CopyDropDescriptors();
   8038   if (new_map->IsFailure()) return new_map;
   8039 
   8040   // Transform the object.
   8041   obj->set_map(Map::cast(new_map));
   8042   obj->map()->set_instance_descriptors(descriptors);
   8043   obj->map()->set_unused_property_fields(unused_property_fields);
   8044 
   8045   obj->set_properties(FixedArray::cast(fields));
   8046   ASSERT(obj->IsJSObject());
   8047 
   8048   descriptors->SetNextEnumerationIndex(NextEnumerationIndex());
   8049   // Check that it really works.
   8050   ASSERT(obj->HasFastProperties());
   8051 
   8052   return obj;
   8053 }
   8054 
   8055 
   8056 #ifdef ENABLE_DEBUGGER_SUPPORT
   8057 // Check if there is a break point at this code position.
   8058 bool DebugInfo::HasBreakPoint(int code_position) {
   8059   // Get the break point info object for this code position.
   8060   Object* break_point_info = GetBreakPointInfo(code_position);
   8061 
   8062   // If there is no break point info object or no break points in the break
   8063   // point info object there is no break point at this code position.
   8064   if (break_point_info->IsUndefined()) return false;
   8065   return BreakPointInfo::cast(break_point_info)->GetBreakPointCount() > 0;
   8066 }
   8067 
   8068 
   8069 // Get the break point info object for this code position.
   8070 Object* DebugInfo::GetBreakPointInfo(int code_position) {
   8071   // Find the index of the break point info object for this code position.
   8072   int index = GetBreakPointInfoIndex(code_position);
   8073 
   8074   // Return the break point info object if any.
   8075   if (index == kNoBreakPointInfo) return Heap::undefined_value();
   8076   return BreakPointInfo::cast(break_points()->get(index));
   8077 }
   8078 
   8079 
   8080 // Clear a break point at the specified code position.
   8081 void DebugInfo::ClearBreakPoint(Handle<DebugInfo> debug_info,
   8082                                 int code_position,
   8083                                 Handle<Object> break_point_object) {
   8084   Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_position));
   8085   if (break_point_info->IsUndefined()) return;
   8086   BreakPointInfo::ClearBreakPoint(
   8087       Handle<BreakPointInfo>::cast(break_point_info),
   8088       break_point_object);
   8089 }
   8090 
   8091 
   8092 void DebugInfo::SetBreakPoint(Handle<DebugInfo> debug_info,
   8093                               int code_position,
   8094                               int source_position,
   8095                               int statement_position,
   8096                               Handle<Object> break_point_object) {
   8097   Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_position));
   8098   if (!break_point_info->IsUndefined()) {
   8099     BreakPointInfo::SetBreakPoint(
   8100         Handle<BreakPointInfo>::cast(break_point_info),
   8101         break_point_object);
   8102     return;
   8103   }
   8104 
   8105   // Adding a new break point for a code position which did not have any
   8106   // break points before. Try to find a free slot.
   8107   int index = kNoBreakPointInfo;
   8108   for (int i = 0; i < debug_info->break_points()->length(); i++) {
   8109     if (debug_info->break_points()->get(i)->IsUndefined()) {
   8110       index = i;
   8111       break;
   8112     }
   8113   }
   8114   if (index == kNoBreakPointInfo) {
   8115     // No free slot - extend break point info array.
   8116     Handle<FixedArray> old_break_points =
   8117         Handle<FixedArray>(FixedArray::cast(debug_info->break_points()));
   8118     debug_info->set_break_points(*Factory::NewFixedArray(
   8119         old_break_points->length() +
   8120             Debug::kEstimatedNofBreakPointsInFunction));
   8121     Handle<FixedArray> new_break_points =
   8122         Handle<FixedArray>(FixedArray::cast(debug_info->break_points()));
   8123     for (int i = 0; i < old_break_points->length(); i++) {
   8124       new_break_points->set(i, old_break_points->get(i));
   8125     }
   8126     index = old_break_points->length();
   8127   }
   8128   ASSERT(index != kNoBreakPointInfo);
   8129 
   8130   // Allocate new BreakPointInfo object and set the break point.
   8131   Handle<BreakPointInfo> new_break_point_info =
   8132       Handle<BreakPointInfo>::cast(Factory::NewStruct(BREAK_POINT_INFO_TYPE));
   8133   new_break_point_info->set_code_position(Smi::FromInt(code_position));
   8134   new_break_point_info->set_source_position(Smi::FromInt(source_position));
   8135   new_break_point_info->
   8136       set_statement_position(Smi::FromInt(statement_position));
   8137   new_break_point_info->set_break_point_objects(Heap::undefined_value());
   8138   BreakPointInfo::SetBreakPoint(new_break_point_info, break_point_object);
   8139   debug_info->break_points()->set(index, *new_break_point_info);
   8140 }
   8141 
   8142 
   8143 // Get the break point objects for a code position.
   8144 Object* DebugInfo::GetBreakPointObjects(int code_position) {
   8145   Object* break_point_info = GetBreakPointInfo(code_position);
   8146   if (break_point_info->IsUndefined()) {
   8147     return Heap::undefined_value();
   8148   }
   8149   return BreakPointInfo::cast(break_point_info)->break_point_objects();
   8150 }
   8151 
   8152 
   8153 // Get the total number of break points.
   8154 int DebugInfo::GetBreakPointCount() {
   8155   if (break_points()->IsUndefined()) return 0;
   8156   int count = 0;
   8157   for (int i = 0; i < break_points()->length(); i++) {
   8158     if (!break_points()->get(i)->IsUndefined()) {
   8159       BreakPointInfo* break_point_info =
   8160           BreakPointInfo::cast(break_points()->get(i));
   8161       count += break_point_info->GetBreakPointCount();
   8162     }
   8163   }
   8164   return count;
   8165 }
   8166 
   8167 
   8168 Object* DebugInfo::FindBreakPointInfo(Handle<DebugInfo> debug_info,
   8169                                       Handle<Object> break_point_object) {
   8170   if (debug_info->break_points()->IsUndefined()) return Heap::undefined_value();
   8171   for (int i = 0; i < debug_info->break_points()->length(); i++) {
   8172     if (!debug_info->break_points()->get(i)->IsUndefined()) {
   8173       Handle<BreakPointInfo> break_point_info =
   8174           Handle<BreakPointInfo>(BreakPointInfo::cast(
   8175               debug_info->break_points()->get(i)));
   8176       if (BreakPointInfo::HasBreakPointObject(break_point_info,
   8177                                               break_point_object)) {
   8178         return *break_point_info;
   8179       }
   8180     }
   8181   }
   8182   return Heap::undefined_value();
   8183 }
   8184 
   8185 
   8186 // Find the index of the break point info object for the specified code
   8187 // position.
   8188 int DebugInfo::GetBreakPointInfoIndex(int code_position) {
   8189   if (break_points()->IsUndefined()) return kNoBreakPointInfo;
   8190   for (int i = 0; i < break_points()->length(); i++) {
   8191     if (!break_points()->get(i)->IsUndefined()) {
   8192       BreakPointInfo* break_point_info =
   8193           BreakPointInfo::cast(break_points()->get(i));
   8194       if (break_point_info->code_position()->value() == code_position) {
   8195         return i;
   8196       }
   8197     }
   8198   }
   8199   return kNoBreakPointInfo;
   8200 }
   8201 
   8202 
   8203 // Remove the specified break point object.
   8204 void BreakPointInfo::ClearBreakPoint(Handle<BreakPointInfo> break_point_info,
   8205                                      Handle<Object> break_point_object) {
   8206   // If there are no break points just ignore.
   8207   if (break_point_info->break_point_objects()->IsUndefined()) return;
   8208   // If there is a single break point clear it if it is the same.
   8209   if (!break_point_info->break_point_objects()->IsFixedArray()) {
   8210     if (break_point_info->break_point_objects() == *break_point_object) {
   8211       break_point_info->set_break_point_objects(Heap::undefined_value());
   8212     }
   8213     return;
   8214   }
   8215   // If there are multiple break points shrink the array
   8216   ASSERT(break_point_info->break_point_objects()->IsFixedArray());
   8217   Handle<FixedArray> old_array =
   8218       Handle<FixedArray>(
   8219           FixedArray::cast(break_point_info->break_point_objects()));
   8220   Handle<FixedArray> new_array =
   8221       Factory::NewFixedArray(old_array->length() - 1);
   8222   int found_count = 0;
   8223   for (int i = 0; i < old_array->length(); i++) {
   8224     if (old_array->get(i) == *break_point_object) {
   8225       ASSERT(found_count == 0);
   8226       found_count++;
   8227     } else {
   8228       new_array->set(i - found_count, old_array->get(i));
   8229     }
   8230   }
   8231   // If the break point was found in the list change it.
   8232   if (found_count > 0) break_point_info->set_break_point_objects(*new_array);
   8233 }
   8234 
   8235 
   8236 // Add the specified break point object.
   8237 void BreakPointInfo::SetBreakPoint(Handle<BreakPointInfo> break_point_info,
   8238                                    Handle<Object> break_point_object) {
   8239   // If there was no break point objects before just set it.
   8240   if (break_point_info->break_point_objects()->IsUndefined()) {
   8241     break_point_info->set_break_point_objects(*break_point_object);
   8242     return;
   8243   }
   8244   // If the break point object is the same as before just ignore.
   8245   if (break_point_info->break_point_objects() == *break_point_object) return;
   8246   // If there was one break point object before replace with array.
   8247   if (!break_point_info->break_point_objects()->IsFixedArray()) {
   8248     Handle<FixedArray> array = Factory::NewFixedArray(2);
   8249     array->set(0, break_point_info->break_point_objects());
   8250     array->set(1, *break_point_object);
   8251     break_point_info->set_break_point_objects(*array);
   8252     return;
   8253   }
   8254   // If there was more than one break point before extend array.
   8255   Handle<FixedArray> old_array =
   8256       Handle<FixedArray>(
   8257           FixedArray::cast(break_point_info->break_point_objects()));
   8258   Handle<FixedArray> new_array =
   8259       Factory::NewFixedArray(old_array->length() + 1);
   8260   for (int i = 0; i < old_array->length(); i++) {
   8261     // If the break point was there before just ignore.
   8262     if (old_array->get(i) == *break_point_object) return;
   8263     new_array->set(i, old_array->get(i));
   8264   }
   8265   // Add the new break point.
   8266   new_array->set(old_array->length(), *break_point_object);
   8267   break_point_info->set_break_point_objects(*new_array);
   8268 }
   8269 
   8270 
   8271 bool BreakPointInfo::HasBreakPointObject(
   8272     Handle<BreakPointInfo> break_point_info,
   8273     Handle<Object> break_point_object) {
   8274   // No break point.
   8275   if (break_point_info->break_point_objects()->IsUndefined()) return false;
   8276   // Single beak point.
   8277   if (!break_point_info->break_point_objects()->IsFixedArray()) {
   8278     return break_point_info->break_point_objects() == *break_point_object;
   8279   }
   8280   // Multiple break points.
   8281   FixedArray* array = FixedArray::cast(break_point_info->break_point_objects());
   8282   for (int i = 0; i < array->length(); i++) {
   8283     if (array->get(i) == *break_point_object) {
   8284       return true;
   8285     }
   8286   }
   8287   return false;
   8288 }
   8289 
   8290 
   8291 // Get the number of break points.
   8292 int BreakPointInfo::GetBreakPointCount() {
   8293   // No break point.
   8294   if (break_point_objects()->IsUndefined()) return 0;
   8295   // Single beak point.
   8296   if (!break_point_objects()->IsFixedArray()) return 1;
   8297   // Multiple break points.
   8298   return FixedArray::cast(break_point_objects())->length();
   8299 }
   8300 #endif
   8301 
   8302 
   8303 } }  // namespace v8::internal
   8304