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