Home | History | Annotate | Download | only in src
      1 // Copyright 2013 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 "accessors.h"
     31 #include "api.h"
     32 #include "arguments.h"
     33 #include "bootstrapper.h"
     34 #include "codegen.h"
     35 #include "debug.h"
     36 #include "deoptimizer.h"
     37 #include "date.h"
     38 #include "elements.h"
     39 #include "execution.h"
     40 #include "full-codegen.h"
     41 #include "hydrogen.h"
     42 #include "isolate-inl.h"
     43 #include "objects-inl.h"
     44 #include "objects-visiting.h"
     45 #include "objects-visiting-inl.h"
     46 #include "macro-assembler.h"
     47 #include "mark-compact.h"
     48 #include "safepoint-table.h"
     49 #include "string-stream.h"
     50 #include "utils.h"
     51 
     52 #ifdef ENABLE_DISASSEMBLER
     53 #include "disasm.h"
     54 #include "disassembler.h"
     55 #endif
     56 
     57 namespace v8 {
     58 namespace internal {
     59 
     60 
     61 MUST_USE_RESULT static MaybeObject* CreateJSValue(JSFunction* constructor,
     62                                                   Object* value) {
     63   Object* result;
     64   { MaybeObject* maybe_result =
     65         constructor->GetHeap()->AllocateJSObject(constructor);
     66     if (!maybe_result->ToObject(&result)) return maybe_result;
     67   }
     68   JSValue::cast(result)->set_value(value);
     69   return result;
     70 }
     71 
     72 
     73 MaybeObject* Object::ToObject(Context* native_context) {
     74   if (IsNumber()) {
     75     return CreateJSValue(native_context->number_function(), this);
     76   } else if (IsBoolean()) {
     77     return CreateJSValue(native_context->boolean_function(), this);
     78   } else if (IsString()) {
     79     return CreateJSValue(native_context->string_function(), this);
     80   }
     81   ASSERT(IsJSObject());
     82   return this;
     83 }
     84 
     85 
     86 MaybeObject* Object::ToObject() {
     87   if (IsJSReceiver()) {
     88     return this;
     89   } else if (IsNumber()) {
     90     Isolate* isolate = Isolate::Current();
     91     Context* native_context = isolate->context()->native_context();
     92     return CreateJSValue(native_context->number_function(), this);
     93   } else if (IsBoolean()) {
     94     Isolate* isolate = HeapObject::cast(this)->GetIsolate();
     95     Context* native_context = isolate->context()->native_context();
     96     return CreateJSValue(native_context->boolean_function(), this);
     97   } else if (IsString()) {
     98     Isolate* isolate = HeapObject::cast(this)->GetIsolate();
     99     Context* native_context = isolate->context()->native_context();
    100     return CreateJSValue(native_context->string_function(), this);
    101   } else if (IsSymbol()) {
    102     Isolate* isolate = HeapObject::cast(this)->GetIsolate();
    103     Context* native_context = isolate->context()->native_context();
    104     return CreateJSValue(native_context->symbol_function(), this);
    105   }
    106 
    107   // Throw a type error.
    108   return Failure::InternalError();
    109 }
    110 
    111 
    112 bool Object::BooleanValue() {
    113   if (IsBoolean()) return IsTrue();
    114   if (IsSmi()) return Smi::cast(this)->value() != 0;
    115   if (IsUndefined() || IsNull()) return false;
    116   if (IsUndetectableObject()) return false;   // Undetectable object is false.
    117   if (IsString()) return String::cast(this)->length() != 0;
    118   if (IsHeapNumber()) return HeapNumber::cast(this)->HeapNumberBooleanValue();
    119   return true;
    120 }
    121 
    122 
    123 void Object::Lookup(Name* name, LookupResult* result) {
    124   Object* holder = NULL;
    125   if (IsJSReceiver()) {
    126     holder = this;
    127   } else {
    128     Context* native_context = result->isolate()->context()->native_context();
    129     if (IsNumber()) {
    130       holder = native_context->number_function()->instance_prototype();
    131     } else if (IsString()) {
    132       holder = native_context->string_function()->instance_prototype();
    133     } else if (IsSymbol()) {
    134       holder = native_context->symbol_function()->instance_prototype();
    135     } else if (IsBoolean()) {
    136       holder = native_context->boolean_function()->instance_prototype();
    137     } else {
    138       Isolate::Current()->PushStackTraceAndDie(
    139           0xDEAD0000, this, JSReceiver::cast(this)->map(), 0xDEAD0001);
    140     }
    141   }
    142   ASSERT(holder != NULL);  // Cannot handle null or undefined.
    143   JSReceiver::cast(holder)->Lookup(name, result);
    144 }
    145 
    146 
    147 MaybeObject* Object::GetPropertyWithReceiver(Object* receiver,
    148                                              Name* name,
    149                                              PropertyAttributes* attributes) {
    150   LookupResult result(name->GetIsolate());
    151   Lookup(name, &result);
    152   MaybeObject* value = GetProperty(receiver, &result, name, attributes);
    153   ASSERT(*attributes <= ABSENT);
    154   return value;
    155 }
    156 
    157 
    158 bool Object::ToInt32(int32_t* value) {
    159   if (IsSmi()) {
    160     *value = Smi::cast(this)->value();
    161     return true;
    162   }
    163   if (IsHeapNumber()) {
    164     double num = HeapNumber::cast(this)->value();
    165     if (FastI2D(FastD2I(num)) == num) {
    166       *value = FastD2I(num);
    167       return true;
    168     }
    169   }
    170   return false;
    171 }
    172 
    173 
    174 bool Object::ToUint32(uint32_t* value) {
    175   if (IsSmi()) {
    176     int num = Smi::cast(this)->value();
    177     if (num >= 0) {
    178       *value = static_cast<uint32_t>(num);
    179       return true;
    180     }
    181   }
    182   if (IsHeapNumber()) {
    183     double num = HeapNumber::cast(this)->value();
    184     if (num >= 0 && FastUI2D(FastD2UI(num)) == num) {
    185       *value = FastD2UI(num);
    186       return true;
    187     }
    188   }
    189   return false;
    190 }
    191 
    192 
    193 template<typename To>
    194 static inline To* CheckedCast(void *from) {
    195   uintptr_t temp = reinterpret_cast<uintptr_t>(from);
    196   ASSERT(temp % sizeof(To) == 0);
    197   return reinterpret_cast<To*>(temp);
    198 }
    199 
    200 
    201 static MaybeObject* PerformCompare(const BitmaskCompareDescriptor& descriptor,
    202                                    char* ptr,
    203                                    Heap* heap) {
    204   uint32_t bitmask = descriptor.bitmask;
    205   uint32_t compare_value = descriptor.compare_value;
    206   uint32_t value;
    207   switch (descriptor.size) {
    208     case 1:
    209       value = static_cast<uint32_t>(*CheckedCast<uint8_t>(ptr));
    210       compare_value &= 0xff;
    211       bitmask &= 0xff;
    212       break;
    213     case 2:
    214       value = static_cast<uint32_t>(*CheckedCast<uint16_t>(ptr));
    215       compare_value &= 0xffff;
    216       bitmask &= 0xffff;
    217       break;
    218     case 4:
    219       value = *CheckedCast<uint32_t>(ptr);
    220       break;
    221     default:
    222       UNREACHABLE();
    223       return NULL;
    224   }
    225   return heap->ToBoolean((bitmask & value) == (bitmask & compare_value));
    226 }
    227 
    228 
    229 static MaybeObject* PerformCompare(const PointerCompareDescriptor& descriptor,
    230                                    char* ptr,
    231                                    Heap* heap) {
    232   uintptr_t compare_value =
    233       reinterpret_cast<uintptr_t>(descriptor.compare_value);
    234   uintptr_t value = *CheckedCast<uintptr_t>(ptr);
    235   return heap->ToBoolean(compare_value == value);
    236 }
    237 
    238 
    239 static MaybeObject* GetPrimitiveValue(
    240     const PrimitiveValueDescriptor& descriptor,
    241     char* ptr,
    242     Heap* heap) {
    243   int32_t int32_value = 0;
    244   switch (descriptor.data_type) {
    245     case kDescriptorInt8Type:
    246       int32_value = *CheckedCast<int8_t>(ptr);
    247       break;
    248     case kDescriptorUint8Type:
    249       int32_value = *CheckedCast<uint8_t>(ptr);
    250       break;
    251     case kDescriptorInt16Type:
    252       int32_value = *CheckedCast<int16_t>(ptr);
    253       break;
    254     case kDescriptorUint16Type:
    255       int32_value = *CheckedCast<uint16_t>(ptr);
    256       break;
    257     case kDescriptorInt32Type:
    258       int32_value = *CheckedCast<int32_t>(ptr);
    259       break;
    260     case kDescriptorUint32Type: {
    261       uint32_t value = *CheckedCast<uint32_t>(ptr);
    262       return heap->NumberFromUint32(value);
    263     }
    264     case kDescriptorBoolType: {
    265       uint8_t byte = *CheckedCast<uint8_t>(ptr);
    266       return heap->ToBoolean(byte & (0x1 << descriptor.bool_offset));
    267     }
    268     case kDescriptorFloatType: {
    269       float value = *CheckedCast<float>(ptr);
    270       return heap->NumberFromDouble(value);
    271     }
    272     case kDescriptorDoubleType: {
    273       double value = *CheckedCast<double>(ptr);
    274       return heap->NumberFromDouble(value);
    275     }
    276   }
    277   return heap->NumberFromInt32(int32_value);
    278 }
    279 
    280 
    281 static MaybeObject* GetDeclaredAccessorProperty(Object* receiver,
    282                                                 DeclaredAccessorInfo* info,
    283                                                 Isolate* isolate) {
    284   char* current = reinterpret_cast<char*>(receiver);
    285   DeclaredAccessorDescriptorIterator iterator(info->descriptor());
    286   while (true) {
    287     const DeclaredAccessorDescriptorData* data = iterator.Next();
    288     switch (data->type) {
    289       case kDescriptorReturnObject: {
    290         ASSERT(iterator.Complete());
    291         current = *CheckedCast<char*>(current);
    292         return *CheckedCast<Object*>(current);
    293       }
    294       case kDescriptorPointerDereference:
    295         ASSERT(!iterator.Complete());
    296         current = *reinterpret_cast<char**>(current);
    297         break;
    298       case kDescriptorPointerShift:
    299         ASSERT(!iterator.Complete());
    300         current += data->pointer_shift_descriptor.byte_offset;
    301         break;
    302       case kDescriptorObjectDereference: {
    303         ASSERT(!iterator.Complete());
    304         Object* object = CheckedCast<Object>(current);
    305         int field = data->object_dereference_descriptor.internal_field;
    306         Object* smi = JSObject::cast(object)->GetInternalField(field);
    307         ASSERT(smi->IsSmi());
    308         current = reinterpret_cast<char*>(smi);
    309         break;
    310       }
    311       case kDescriptorBitmaskCompare:
    312         ASSERT(iterator.Complete());
    313         return PerformCompare(data->bitmask_compare_descriptor,
    314                               current,
    315                               isolate->heap());
    316       case kDescriptorPointerCompare:
    317         ASSERT(iterator.Complete());
    318         return PerformCompare(data->pointer_compare_descriptor,
    319                               current,
    320                               isolate->heap());
    321       case kDescriptorPrimitiveValue:
    322         ASSERT(iterator.Complete());
    323         return GetPrimitiveValue(data->primitive_value_descriptor,
    324                                  current,
    325                                  isolate->heap());
    326     }
    327   }
    328   UNREACHABLE();
    329   return NULL;
    330 }
    331 
    332 
    333 MaybeObject* JSObject::GetPropertyWithCallback(Object* receiver,
    334                                                Object* structure,
    335                                                Name* name) {
    336   Isolate* isolate = name->GetIsolate();
    337   // To accommodate both the old and the new api we switch on the
    338   // data structure used to store the callbacks.  Eventually foreign
    339   // callbacks should be phased out.
    340   if (structure->IsForeign()) {
    341     AccessorDescriptor* callback =
    342         reinterpret_cast<AccessorDescriptor*>(
    343             Foreign::cast(structure)->foreign_address());
    344     MaybeObject* value = (callback->getter)(receiver, callback->data);
    345     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
    346     return value;
    347   }
    348 
    349   // api style callbacks.
    350   if (structure->IsAccessorInfo()) {
    351     if (!AccessorInfo::cast(structure)->IsCompatibleReceiver(receiver)) {
    352       Handle<Object> name_handle(name, isolate);
    353       Handle<Object> receiver_handle(receiver, isolate);
    354       Handle<Object> args[2] = { name_handle, receiver_handle };
    355       Handle<Object> error =
    356           isolate->factory()->NewTypeError("incompatible_method_receiver",
    357                                            HandleVector(args,
    358                                                         ARRAY_SIZE(args)));
    359       return isolate->Throw(*error);
    360     }
    361     // TODO(rossberg): Handling symbols in the API requires changing the API,
    362     // so we do not support it for now.
    363     if (name->IsSymbol()) return isolate->heap()->undefined_value();
    364     if (structure->IsDeclaredAccessorInfo()) {
    365       return GetDeclaredAccessorProperty(receiver,
    366                                          DeclaredAccessorInfo::cast(structure),
    367                                          isolate);
    368     }
    369     ExecutableAccessorInfo* data = ExecutableAccessorInfo::cast(structure);
    370     Object* fun_obj = data->getter();
    371     v8::AccessorGetter call_fun = v8::ToCData<v8::AccessorGetter>(fun_obj);
    372     if (call_fun == NULL) return isolate->heap()->undefined_value();
    373     HandleScope scope(isolate);
    374     JSObject* self = JSObject::cast(receiver);
    375     Handle<String> key(String::cast(name));
    376     LOG(isolate, ApiNamedPropertyAccess("load", self, name));
    377     PropertyCallbackArguments args(isolate, data->data(), self, this);
    378     v8::Handle<v8::Value> result =
    379         args.Call(call_fun, v8::Utils::ToLocal(key));
    380     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
    381     if (result.IsEmpty()) {
    382       return isolate->heap()->undefined_value();
    383     }
    384     Object* return_value = *v8::Utils::OpenHandle(*result);
    385     return_value->VerifyApiCallResultType();
    386     return return_value;
    387   }
    388 
    389   // __defineGetter__ callback
    390   if (structure->IsAccessorPair()) {
    391     Object* getter = AccessorPair::cast(structure)->getter();
    392     if (getter->IsSpecFunction()) {
    393       // TODO(rossberg): nicer would be to cast to some JSCallable here...
    394       return GetPropertyWithDefinedGetter(receiver, JSReceiver::cast(getter));
    395     }
    396     // Getter is not a function.
    397     return isolate->heap()->undefined_value();
    398   }
    399 
    400   UNREACHABLE();
    401   return NULL;
    402 }
    403 
    404 
    405 MaybeObject* JSProxy::GetPropertyWithHandler(Object* receiver_raw,
    406                                              Name* name_raw) {
    407   Isolate* isolate = GetIsolate();
    408   HandleScope scope(isolate);
    409   Handle<Object> receiver(receiver_raw, isolate);
    410   Handle<Object> name(name_raw, isolate);
    411 
    412   // TODO(rossberg): adjust once there is a story for symbols vs proxies.
    413   if (name->IsSymbol()) return isolate->heap()->undefined_value();
    414 
    415   Handle<Object> args[] = { receiver, name };
    416   Handle<Object> result = CallTrap(
    417     "get", isolate->derived_get_trap(), ARRAY_SIZE(args), args);
    418   if (isolate->has_pending_exception()) return Failure::Exception();
    419 
    420   return *result;
    421 }
    422 
    423 
    424 Handle<Object> Object::GetProperty(Handle<Object> object, Handle<Name> name) {
    425   // TODO(rossberg): The index test should not be here but in the GetProperty
    426   // method (or somewhere else entirely). Needs more global clean-up.
    427   uint32_t index;
    428   if (name->AsArrayIndex(&index))
    429     return GetElement(object, index);
    430   Isolate* isolate = object->IsHeapObject()
    431       ? Handle<HeapObject>::cast(object)->GetIsolate()
    432       : Isolate::Current();
    433   CALL_HEAP_FUNCTION(isolate, object->GetProperty(*name), Object);
    434 }
    435 
    436 
    437 Handle<Object> Object::GetElement(Handle<Object> object, uint32_t index) {
    438   Isolate* isolate = object->IsHeapObject()
    439       ? Handle<HeapObject>::cast(object)->GetIsolate()
    440       : Isolate::Current();
    441   CALL_HEAP_FUNCTION(isolate, object->GetElement(index), Object);
    442 }
    443 
    444 
    445 MaybeObject* JSProxy::GetElementWithHandler(Object* receiver,
    446                                             uint32_t index) {
    447   String* name;
    448   MaybeObject* maybe = GetHeap()->Uint32ToString(index);
    449   if (!maybe->To<String>(&name)) return maybe;
    450   return GetPropertyWithHandler(receiver, name);
    451 }
    452 
    453 
    454 MaybeObject* JSProxy::SetElementWithHandler(JSReceiver* receiver,
    455                                             uint32_t index,
    456                                             Object* value,
    457                                             StrictModeFlag strict_mode) {
    458   String* name;
    459   MaybeObject* maybe = GetHeap()->Uint32ToString(index);
    460   if (!maybe->To<String>(&name)) return maybe;
    461   return SetPropertyWithHandler(receiver, name, value, NONE, strict_mode);
    462 }
    463 
    464 
    465 bool JSProxy::HasElementWithHandler(uint32_t index) {
    466   String* name;
    467   MaybeObject* maybe = GetHeap()->Uint32ToString(index);
    468   if (!maybe->To<String>(&name)) return maybe;
    469   return HasPropertyWithHandler(name);
    470 }
    471 
    472 
    473 MaybeObject* Object::GetPropertyWithDefinedGetter(Object* receiver,
    474                                                   JSReceiver* getter) {
    475   Isolate* isolate = getter->GetIsolate();
    476   HandleScope scope(isolate);
    477   Handle<JSReceiver> fun(getter);
    478   Handle<Object> self(receiver, isolate);
    479 #ifdef ENABLE_DEBUGGER_SUPPORT
    480   Debug* debug = isolate->debug();
    481   // Handle stepping into a getter if step into is active.
    482   // TODO(rossberg): should this apply to getters that are function proxies?
    483   if (debug->StepInActive() && fun->IsJSFunction()) {
    484     debug->HandleStepIn(
    485         Handle<JSFunction>::cast(fun), Handle<Object>::null(), 0, false);
    486   }
    487 #endif
    488 
    489   bool has_pending_exception;
    490   Handle<Object> result =
    491       Execution::Call(fun, self, 0, NULL, &has_pending_exception, true);
    492   // Check for pending exception and return the result.
    493   if (has_pending_exception) return Failure::Exception();
    494   return *result;
    495 }
    496 
    497 
    498 // Only deal with CALLBACKS and INTERCEPTOR
    499 MaybeObject* JSObject::GetPropertyWithFailedAccessCheck(
    500     Object* receiver,
    501     LookupResult* result,
    502     Name* name,
    503     PropertyAttributes* attributes) {
    504   if (result->IsProperty()) {
    505     switch (result->type()) {
    506       case CALLBACKS: {
    507         // Only allow API accessors.
    508         Object* obj = result->GetCallbackObject();
    509         if (obj->IsAccessorInfo()) {
    510           AccessorInfo* info = AccessorInfo::cast(obj);
    511           if (info->all_can_read()) {
    512             *attributes = result->GetAttributes();
    513             return result->holder()->GetPropertyWithCallback(
    514                 receiver, result->GetCallbackObject(), name);
    515           }
    516         }
    517         break;
    518       }
    519       case NORMAL:
    520       case FIELD:
    521       case CONSTANT: {
    522         // Search ALL_CAN_READ accessors in prototype chain.
    523         LookupResult r(GetIsolate());
    524         result->holder()->LookupRealNamedPropertyInPrototypes(name, &r);
    525         if (r.IsProperty()) {
    526           return GetPropertyWithFailedAccessCheck(receiver,
    527                                                   &r,
    528                                                   name,
    529                                                   attributes);
    530         }
    531         break;
    532       }
    533       case INTERCEPTOR: {
    534         // If the object has an interceptor, try real named properties.
    535         // No access check in GetPropertyAttributeWithInterceptor.
    536         LookupResult r(GetIsolate());
    537         result->holder()->LookupRealNamedProperty(name, &r);
    538         if (r.IsProperty()) {
    539           return GetPropertyWithFailedAccessCheck(receiver,
    540                                                   &r,
    541                                                   name,
    542                                                   attributes);
    543         }
    544         break;
    545       }
    546       default:
    547         UNREACHABLE();
    548     }
    549   }
    550 
    551   // No accessible property found.
    552   *attributes = ABSENT;
    553   Heap* heap = name->GetHeap();
    554   Isolate* isolate = heap->isolate();
    555   isolate->ReportFailedAccessCheck(this, v8::ACCESS_GET);
    556   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
    557   return heap->undefined_value();
    558 }
    559 
    560 
    561 PropertyAttributes JSObject::GetPropertyAttributeWithFailedAccessCheck(
    562     Object* receiver,
    563     LookupResult* result,
    564     Name* name,
    565     bool continue_search) {
    566   if (result->IsProperty()) {
    567     switch (result->type()) {
    568       case CALLBACKS: {
    569         // Only allow API accessors.
    570         Object* obj = result->GetCallbackObject();
    571         if (obj->IsAccessorInfo()) {
    572           AccessorInfo* info = AccessorInfo::cast(obj);
    573           if (info->all_can_read()) {
    574             return result->GetAttributes();
    575           }
    576         }
    577         break;
    578       }
    579 
    580       case NORMAL:
    581       case FIELD:
    582       case CONSTANT: {
    583         if (!continue_search) break;
    584         // Search ALL_CAN_READ accessors in prototype chain.
    585         LookupResult r(GetIsolate());
    586         result->holder()->LookupRealNamedPropertyInPrototypes(name, &r);
    587         if (r.IsProperty()) {
    588           return GetPropertyAttributeWithFailedAccessCheck(receiver,
    589                                                            &r,
    590                                                            name,
    591                                                            continue_search);
    592         }
    593         break;
    594       }
    595 
    596       case INTERCEPTOR: {
    597         // If the object has an interceptor, try real named properties.
    598         // No access check in GetPropertyAttributeWithInterceptor.
    599         LookupResult r(GetIsolate());
    600         if (continue_search) {
    601           result->holder()->LookupRealNamedProperty(name, &r);
    602         } else {
    603           result->holder()->LocalLookupRealNamedProperty(name, &r);
    604         }
    605         if (!r.IsFound()) break;
    606         return GetPropertyAttributeWithFailedAccessCheck(receiver,
    607                                                          &r,
    608                                                          name,
    609                                                          continue_search);
    610       }
    611 
    612       case HANDLER:
    613       case TRANSITION:
    614       case NONEXISTENT:
    615         UNREACHABLE();
    616     }
    617   }
    618 
    619   GetIsolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
    620   return ABSENT;
    621 }
    622 
    623 
    624 Object* JSObject::GetNormalizedProperty(LookupResult* result) {
    625   ASSERT(!HasFastProperties());
    626   Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry());
    627   if (IsGlobalObject()) {
    628     value = PropertyCell::cast(value)->value();
    629   }
    630   ASSERT(!value->IsPropertyCell() && !value->IsCell());
    631   return value;
    632 }
    633 
    634 
    635 Handle<Object> JSObject::SetNormalizedProperty(Handle<JSObject> object,
    636                                                LookupResult* result,
    637                                                Handle<Object> value) {
    638   CALL_HEAP_FUNCTION(object->GetIsolate(),
    639                      object->SetNormalizedProperty(result, *value),
    640                      Object);
    641 }
    642 
    643 
    644 MaybeObject* JSObject::SetNormalizedProperty(LookupResult* result,
    645                                              Object* value) {
    646   ASSERT(!HasFastProperties());
    647   if (IsGlobalObject()) {
    648     PropertyCell* cell = PropertyCell::cast(
    649         property_dictionary()->ValueAt(result->GetDictionaryEntry()));
    650     MaybeObject* maybe_type = cell->SetValueInferType(value);
    651     if (maybe_type->IsFailure()) return maybe_type;
    652   } else {
    653     property_dictionary()->ValueAtPut(result->GetDictionaryEntry(), value);
    654   }
    655   return value;
    656 }
    657 
    658 
    659 Handle<Object> JSObject::SetNormalizedProperty(Handle<JSObject> object,
    660                                                Handle<Name> key,
    661                                                Handle<Object> value,
    662                                                PropertyDetails details) {
    663   CALL_HEAP_FUNCTION(object->GetIsolate(),
    664                      object->SetNormalizedProperty(*key, *value, details),
    665                      Object);
    666 }
    667 
    668 
    669 MaybeObject* JSObject::SetNormalizedProperty(Name* name,
    670                                              Object* value,
    671                                              PropertyDetails details) {
    672   ASSERT(!HasFastProperties());
    673   int entry = property_dictionary()->FindEntry(name);
    674   if (entry == NameDictionary::kNotFound) {
    675     Object* store_value = value;
    676     if (IsGlobalObject()) {
    677       Heap* heap = name->GetHeap();
    678       MaybeObject* maybe_store_value = heap->AllocatePropertyCell(value);
    679       if (!maybe_store_value->ToObject(&store_value)) return maybe_store_value;
    680     }
    681     Object* dict;
    682     { MaybeObject* maybe_dict =
    683           property_dictionary()->Add(name, store_value, details);
    684       if (!maybe_dict->ToObject(&dict)) return maybe_dict;
    685     }
    686     set_properties(NameDictionary::cast(dict));
    687     return value;
    688   }
    689 
    690   PropertyDetails original_details = property_dictionary()->DetailsAt(entry);
    691   int enumeration_index;
    692   // Preserve the enumeration index unless the property was deleted.
    693   if (original_details.IsDeleted()) {
    694     enumeration_index = property_dictionary()->NextEnumerationIndex();
    695     property_dictionary()->SetNextEnumerationIndex(enumeration_index + 1);
    696   } else {
    697     enumeration_index = original_details.dictionary_index();
    698     ASSERT(enumeration_index > 0);
    699   }
    700 
    701   details = PropertyDetails(
    702       details.attributes(), details.type(), enumeration_index);
    703 
    704   if (IsGlobalObject()) {
    705     PropertyCell* cell =
    706         PropertyCell::cast(property_dictionary()->ValueAt(entry));
    707     MaybeObject* maybe_type = cell->SetValueInferType(value);
    708     if (maybe_type->IsFailure()) return maybe_type;
    709     // Please note we have to update the property details.
    710     property_dictionary()->DetailsAtPut(entry, details);
    711   } else {
    712     property_dictionary()->SetEntry(entry, name, value, details);
    713   }
    714   return value;
    715 }
    716 
    717 
    718 // TODO(mstarzinger): Temporary wrapper until target is handlified.
    719 Handle<NameDictionary> NameDictionaryShrink(Handle<NameDictionary> dict,
    720                                             Handle<Name> name) {
    721   CALL_HEAP_FUNCTION(dict->GetIsolate(), dict->Shrink(*name), NameDictionary);
    722 }
    723 
    724 
    725 static void CellSetValueInferType(Handle<PropertyCell> cell,
    726                                   Handle<Object> value) {
    727   CALL_HEAP_FUNCTION_VOID(cell->GetIsolate(), cell->SetValueInferType(*value));
    728 }
    729 
    730 
    731 Handle<Object> JSObject::DeleteNormalizedProperty(Handle<JSObject> object,
    732                                                   Handle<Name> name,
    733                                                   DeleteMode mode) {
    734   ASSERT(!object->HasFastProperties());
    735   Isolate* isolate = object->GetIsolate();
    736   Handle<NameDictionary> dictionary(object->property_dictionary());
    737   int entry = dictionary->FindEntry(*name);
    738   if (entry != NameDictionary::kNotFound) {
    739     // If we have a global object set the cell to the hole.
    740     if (object->IsGlobalObject()) {
    741       PropertyDetails details = dictionary->DetailsAt(entry);
    742       if (details.IsDontDelete()) {
    743         if (mode != FORCE_DELETION) return isolate->factory()->false_value();
    744         // When forced to delete global properties, we have to make a
    745         // map change to invalidate any ICs that think they can load
    746         // from the DontDelete cell without checking if it contains
    747         // the hole value.
    748         Handle<Map> new_map = Map::CopyDropDescriptors(handle(object->map()));
    749         ASSERT(new_map->is_dictionary_map());
    750         object->set_map(*new_map);
    751       }
    752       Handle<PropertyCell> cell(PropertyCell::cast(dictionary->ValueAt(entry)));
    753       CellSetValueInferType(cell, isolate->factory()->the_hole_value());
    754       dictionary->DetailsAtPut(entry, details.AsDeleted());
    755     } else {
    756       Handle<Object> deleted(dictionary->DeleteProperty(entry, mode), isolate);
    757       if (*deleted == isolate->heap()->true_value()) {
    758         Handle<NameDictionary> new_properties =
    759             NameDictionaryShrink(dictionary, name);
    760         object->set_properties(*new_properties);
    761       }
    762       return deleted;
    763     }
    764   }
    765   return isolate->factory()->true_value();
    766 }
    767 
    768 
    769 bool JSObject::IsDirty() {
    770   Object* cons_obj = map()->constructor();
    771   if (!cons_obj->IsJSFunction())
    772     return true;
    773   JSFunction* fun = JSFunction::cast(cons_obj);
    774   if (!fun->shared()->IsApiFunction())
    775     return true;
    776   // If the object is fully fast case and has the same map it was
    777   // created with then no changes can have been made to it.
    778   return map() != fun->initial_map()
    779       || !HasFastObjectElements()
    780       || !HasFastProperties();
    781 }
    782 
    783 
    784 Handle<Object> Object::GetProperty(Handle<Object> object,
    785                                    Handle<Object> receiver,
    786                                    LookupResult* result,
    787                                    Handle<Name> key,
    788                                    PropertyAttributes* attributes) {
    789   Isolate* isolate = object->IsHeapObject()
    790       ? Handle<HeapObject>::cast(object)->GetIsolate()
    791       : Isolate::Current();
    792   CALL_HEAP_FUNCTION(
    793       isolate,
    794       object->GetProperty(*receiver, result, *key, attributes),
    795       Object);
    796 }
    797 
    798 
    799 MaybeObject* Object::GetPropertyOrFail(Handle<Object> object,
    800                                        Handle<Object> receiver,
    801                                        LookupResult* result,
    802                                        Handle<Name> key,
    803                                        PropertyAttributes* attributes) {
    804   Isolate* isolate = object->IsHeapObject()
    805       ? Handle<HeapObject>::cast(object)->GetIsolate()
    806       : Isolate::Current();
    807   CALL_HEAP_FUNCTION_PASS_EXCEPTION(
    808       isolate,
    809       object->GetProperty(*receiver, result, *key, attributes));
    810 }
    811 
    812 
    813 MaybeObject* Object::GetProperty(Object* receiver,
    814                                  LookupResult* result,
    815                                  Name* name,
    816                                  PropertyAttributes* attributes) {
    817   // Make sure that the top context does not change when doing
    818   // callbacks or interceptor calls.
    819   AssertNoContextChange ncc;
    820   Isolate* isolate = name->GetIsolate();
    821   Heap* heap = isolate->heap();
    822 
    823   // Traverse the prototype chain from the current object (this) to
    824   // the holder and check for access rights. This avoids traversing the
    825   // objects more than once in case of interceptors, because the
    826   // holder will always be the interceptor holder and the search may
    827   // only continue with a current object just after the interceptor
    828   // holder in the prototype chain.
    829   // Proxy handlers do not use the proxy's prototype, so we can skip this.
    830   if (!result->IsHandler()) {
    831     Object* last = result->IsProperty()
    832         ? result->holder()
    833         : Object::cast(heap->null_value());
    834     ASSERT(this != this->GetPrototype(isolate));
    835     for (Object* current = this;
    836          true;
    837          current = current->GetPrototype(isolate)) {
    838       if (current->IsAccessCheckNeeded()) {
    839         // Check if we're allowed to read from the current object. Note
    840         // that even though we may not actually end up loading the named
    841         // property from the current object, we still check that we have
    842         // access to it.
    843         JSObject* checked = JSObject::cast(current);
    844         if (!heap->isolate()->MayNamedAccess(checked, name, v8::ACCESS_GET)) {
    845           return checked->GetPropertyWithFailedAccessCheck(receiver,
    846                                                            result,
    847                                                            name,
    848                                                            attributes);
    849         }
    850       }
    851       // Stop traversing the chain once we reach the last object in the
    852       // chain; either the holder of the result or null in case of an
    853       // absent property.
    854       if (current == last) break;
    855     }
    856   }
    857 
    858   if (!result->IsProperty()) {
    859     *attributes = ABSENT;
    860     return heap->undefined_value();
    861   }
    862   *attributes = result->GetAttributes();
    863   Object* value;
    864   switch (result->type()) {
    865     case NORMAL:
    866       value = result->holder()->GetNormalizedProperty(result);
    867       ASSERT(!value->IsTheHole() || result->IsReadOnly());
    868       return value->IsTheHole() ? heap->undefined_value() : value;
    869     case FIELD: {
    870       MaybeObject* maybe_result = result->holder()->FastPropertyAt(
    871           result->representation(),
    872           result->GetFieldIndex().field_index());
    873       if (!maybe_result->To(&value)) return maybe_result;
    874       ASSERT(!value->IsTheHole() || result->IsReadOnly());
    875       return value->IsTheHole() ? heap->undefined_value() : value;
    876     }
    877     case CONSTANT:
    878       return result->GetConstant();
    879     case CALLBACKS:
    880       return result->holder()->GetPropertyWithCallback(
    881           receiver, result->GetCallbackObject(), name);
    882     case HANDLER:
    883       return result->proxy()->GetPropertyWithHandler(receiver, name);
    884     case INTERCEPTOR:
    885       return result->holder()->GetPropertyWithInterceptor(
    886           receiver, name, attributes);
    887     case TRANSITION:
    888     case NONEXISTENT:
    889       UNREACHABLE();
    890       break;
    891   }
    892   UNREACHABLE();
    893   return NULL;
    894 }
    895 
    896 
    897 MaybeObject* Object::GetElementWithReceiver(Object* receiver, uint32_t index) {
    898   Isolate* isolate = IsSmi()
    899       ? Isolate::Current()
    900       : HeapObject::cast(this)->GetIsolate();
    901   Heap* heap = isolate->heap();
    902   Object* holder = this;
    903 
    904   // Iterate up the prototype chain until an element is found or the null
    905   // prototype is encountered.
    906   for (holder = this;
    907        holder != heap->null_value();
    908        holder = holder->GetPrototype(isolate)) {
    909     if (!holder->IsJSObject()) {
    910       Context* native_context = isolate->context()->native_context();
    911       if (holder->IsNumber()) {
    912         holder = native_context->number_function()->instance_prototype();
    913       } else if (holder->IsString()) {
    914         holder = native_context->string_function()->instance_prototype();
    915       } else if (holder->IsSymbol()) {
    916         holder = native_context->symbol_function()->instance_prototype();
    917       } else if (holder->IsBoolean()) {
    918         holder = native_context->boolean_function()->instance_prototype();
    919       } else if (holder->IsJSProxy()) {
    920         return JSProxy::cast(holder)->GetElementWithHandler(receiver, index);
    921       } else {
    922         // Undefined and null have no indexed properties.
    923         ASSERT(holder->IsUndefined() || holder->IsNull());
    924         return heap->undefined_value();
    925       }
    926     }
    927 
    928     // Inline the case for JSObjects. Doing so significantly improves the
    929     // performance of fetching elements where checking the prototype chain is
    930     // necessary.
    931     JSObject* js_object = JSObject::cast(holder);
    932 
    933     // Check access rights if needed.
    934     if (js_object->IsAccessCheckNeeded()) {
    935       Isolate* isolate = heap->isolate();
    936       if (!isolate->MayIndexedAccess(js_object, index, v8::ACCESS_GET)) {
    937         isolate->ReportFailedAccessCheck(js_object, v8::ACCESS_GET);
    938         RETURN_IF_SCHEDULED_EXCEPTION(isolate);
    939         return heap->undefined_value();
    940       }
    941     }
    942 
    943     if (js_object->HasIndexedInterceptor()) {
    944       return js_object->GetElementWithInterceptor(receiver, index);
    945     }
    946 
    947     if (js_object->elements() != heap->empty_fixed_array()) {
    948       MaybeObject* result = js_object->GetElementsAccessor()->Get(
    949           receiver, js_object, index);
    950       if (result != heap->the_hole_value()) return result;
    951     }
    952   }
    953 
    954   return heap->undefined_value();
    955 }
    956 
    957 
    958 Object* Object::GetPrototype(Isolate* isolate) {
    959   if (IsSmi()) {
    960     Context* context = isolate->context()->native_context();
    961     return context->number_function()->instance_prototype();
    962   }
    963 
    964   HeapObject* heap_object = HeapObject::cast(this);
    965 
    966   // The object is either a number, a string, a boolean,
    967   // a real JS object, or a Harmony proxy.
    968   if (heap_object->IsJSReceiver()) {
    969     return heap_object->map()->prototype();
    970   }
    971   Context* context = isolate->context()->native_context();
    972 
    973   if (heap_object->IsHeapNumber()) {
    974     return context->number_function()->instance_prototype();
    975   }
    976   if (heap_object->IsString()) {
    977     return context->string_function()->instance_prototype();
    978   }
    979   if (heap_object->IsSymbol()) {
    980     return context->symbol_function()->instance_prototype();
    981   }
    982   if (heap_object->IsBoolean()) {
    983     return context->boolean_function()->instance_prototype();
    984   } else {
    985     return isolate->heap()->null_value();
    986   }
    987 }
    988 
    989 
    990 MaybeObject* Object::GetHash(CreationFlag flag) {
    991   // The object is either a number, a name, an odd-ball,
    992   // a real JS object, or a Harmony proxy.
    993   if (IsNumber()) {
    994     uint32_t hash = ComputeLongHash(double_to_uint64(Number()));
    995     return Smi::FromInt(hash & Smi::kMaxValue);
    996   }
    997   if (IsName()) {
    998     uint32_t hash = Name::cast(this)->Hash();
    999     return Smi::FromInt(hash);
   1000   }
   1001   if (IsOddball()) {
   1002     uint32_t hash = Oddball::cast(this)->to_string()->Hash();
   1003     return Smi::FromInt(hash);
   1004   }
   1005   if (IsJSReceiver()) {
   1006     return JSReceiver::cast(this)->GetIdentityHash(flag);
   1007   }
   1008 
   1009   UNREACHABLE();
   1010   return Smi::FromInt(0);
   1011 }
   1012 
   1013 
   1014 bool Object::SameValue(Object* other) {
   1015   if (other == this) return true;
   1016 
   1017   // The object is either a number, a name, an odd-ball,
   1018   // a real JS object, or a Harmony proxy.
   1019   if (IsNumber() && other->IsNumber()) {
   1020     double this_value = Number();
   1021     double other_value = other->Number();
   1022     return (this_value == other_value) ||
   1023         (std::isnan(this_value) && std::isnan(other_value));
   1024   }
   1025   if (IsString() && other->IsString()) {
   1026     return String::cast(this)->Equals(String::cast(other));
   1027   }
   1028   return false;
   1029 }
   1030 
   1031 
   1032 void Object::ShortPrint(FILE* out) {
   1033   HeapStringAllocator allocator;
   1034   StringStream accumulator(&allocator);
   1035   ShortPrint(&accumulator);
   1036   accumulator.OutputToFile(out);
   1037 }
   1038 
   1039 
   1040 void Object::ShortPrint(StringStream* accumulator) {
   1041   if (IsSmi()) {
   1042     Smi::cast(this)->SmiPrint(accumulator);
   1043   } else if (IsFailure()) {
   1044     Failure::cast(this)->FailurePrint(accumulator);
   1045   } else {
   1046     HeapObject::cast(this)->HeapObjectShortPrint(accumulator);
   1047   }
   1048 }
   1049 
   1050 
   1051 void Smi::SmiPrint(FILE* out) {
   1052   PrintF(out, "%d", value());
   1053 }
   1054 
   1055 
   1056 void Smi::SmiPrint(StringStream* accumulator) {
   1057   accumulator->Add("%d", value());
   1058 }
   1059 
   1060 
   1061 void Failure::FailurePrint(StringStream* accumulator) {
   1062   accumulator->Add("Failure(%p)", reinterpret_cast<void*>(value()));
   1063 }
   1064 
   1065 
   1066 void Failure::FailurePrint(FILE* out) {
   1067   PrintF(out, "Failure(%p)", reinterpret_cast<void*>(value()));
   1068 }
   1069 
   1070 
   1071 // Should a word be prefixed by 'a' or 'an' in order to read naturally in
   1072 // English?  Returns false for non-ASCII or words that don't start with
   1073 // a capital letter.  The a/an rule follows pronunciation in English.
   1074 // We don't use the BBC's overcorrect "an historic occasion" though if
   1075 // you speak a dialect you may well say "an 'istoric occasion".
   1076 static bool AnWord(String* str) {
   1077   if (str->length() == 0) return false;  // A nothing.
   1078   int c0 = str->Get(0);
   1079   int c1 = str->length() > 1 ? str->Get(1) : 0;
   1080   if (c0 == 'U') {
   1081     if (c1 > 'Z') {
   1082       return true;  // An Umpire, but a UTF8String, a U.
   1083     }
   1084   } else if (c0 == 'A' || c0 == 'E' || c0 == 'I' || c0 == 'O') {
   1085     return true;    // An Ape, an ABCBook.
   1086   } else if ((c1 == 0 || (c1 >= 'A' && c1 <= 'Z')) &&
   1087            (c0 == 'F' || c0 == 'H' || c0 == 'M' || c0 == 'N' || c0 == 'R' ||
   1088             c0 == 'S' || c0 == 'X')) {
   1089     return true;    // An MP3File, an M.
   1090   }
   1091   return false;
   1092 }
   1093 
   1094 
   1095 MaybeObject* String::SlowTryFlatten(PretenureFlag pretenure) {
   1096 #ifdef DEBUG
   1097   // Do not attempt to flatten in debug mode when allocation is not
   1098   // allowed.  This is to avoid an assertion failure when allocating.
   1099   // Flattening strings is the only case where we always allow
   1100   // allocation because no GC is performed if the allocation fails.
   1101   if (!AllowHeapAllocation::IsAllowed()) return this;
   1102 #endif
   1103 
   1104   Heap* heap = GetHeap();
   1105   switch (StringShape(this).representation_tag()) {
   1106     case kConsStringTag: {
   1107       ConsString* cs = ConsString::cast(this);
   1108       if (cs->second()->length() == 0) {
   1109         return cs->first();
   1110       }
   1111       // There's little point in putting the flat string in new space if the
   1112       // cons string is in old space.  It can never get GCed until there is
   1113       // an old space GC.
   1114       PretenureFlag tenure = heap->InNewSpace(this) ? pretenure : TENURED;
   1115       int len = length();
   1116       Object* object;
   1117       String* result;
   1118       if (IsOneByteRepresentation()) {
   1119         { MaybeObject* maybe_object =
   1120               heap->AllocateRawOneByteString(len, tenure);
   1121           if (!maybe_object->ToObject(&object)) return maybe_object;
   1122         }
   1123         result = String::cast(object);
   1124         String* first = cs->first();
   1125         int first_length = first->length();
   1126         uint8_t* dest = SeqOneByteString::cast(result)->GetChars();
   1127         WriteToFlat(first, dest, 0, first_length);
   1128         String* second = cs->second();
   1129         WriteToFlat(second,
   1130                     dest + first_length,
   1131                     0,
   1132                     len - first_length);
   1133       } else {
   1134         { MaybeObject* maybe_object =
   1135               heap->AllocateRawTwoByteString(len, tenure);
   1136           if (!maybe_object->ToObject(&object)) return maybe_object;
   1137         }
   1138         result = String::cast(object);
   1139         uc16* dest = SeqTwoByteString::cast(result)->GetChars();
   1140         String* first = cs->first();
   1141         int first_length = first->length();
   1142         WriteToFlat(first, dest, 0, first_length);
   1143         String* second = cs->second();
   1144         WriteToFlat(second,
   1145                     dest + first_length,
   1146                     0,
   1147                     len - first_length);
   1148       }
   1149       cs->set_first(result);
   1150       cs->set_second(heap->empty_string(), SKIP_WRITE_BARRIER);
   1151       return result;
   1152     }
   1153     default:
   1154       return this;
   1155   }
   1156 }
   1157 
   1158 
   1159 bool String::MakeExternal(v8::String::ExternalStringResource* resource) {
   1160   // Externalizing twice leaks the external resource, so it's
   1161   // prohibited by the API.
   1162   ASSERT(!this->IsExternalString());
   1163 #ifdef DEBUG
   1164   if (FLAG_enable_slow_asserts) {
   1165     // Assert that the resource and the string are equivalent.
   1166     ASSERT(static_cast<size_t>(this->length()) == resource->length());
   1167     ScopedVector<uc16> smart_chars(this->length());
   1168     String::WriteToFlat(this, smart_chars.start(), 0, this->length());
   1169     ASSERT(memcmp(smart_chars.start(),
   1170                   resource->data(),
   1171                   resource->length() * sizeof(smart_chars[0])) == 0);
   1172   }
   1173 #endif  // DEBUG
   1174   Heap* heap = GetHeap();
   1175   int size = this->Size();  // Byte size of the original string.
   1176   if (size < ExternalString::kShortSize) {
   1177     return false;
   1178   }
   1179   bool is_ascii = this->IsOneByteRepresentation();
   1180   bool is_internalized = this->IsInternalizedString();
   1181 
   1182   // Morph the object to an external string by adjusting the map and
   1183   // reinitializing the fields.
   1184   if (size >= ExternalString::kSize) {
   1185     this->set_map_no_write_barrier(
   1186         is_internalized
   1187             ? (is_ascii
   1188                    ? heap->external_internalized_string_with_one_byte_data_map()
   1189                    : heap->external_internalized_string_map())
   1190             : (is_ascii
   1191                    ? heap->external_string_with_one_byte_data_map()
   1192                    : heap->external_string_map()));
   1193   } else {
   1194     this->set_map_no_write_barrier(
   1195         is_internalized
   1196           ? (is_ascii
   1197                ? heap->
   1198                    short_external_internalized_string_with_one_byte_data_map()
   1199                : heap->short_external_internalized_string_map())
   1200           : (is_ascii
   1201                  ? heap->short_external_string_with_one_byte_data_map()
   1202                  : heap->short_external_string_map()));
   1203   }
   1204   ExternalTwoByteString* self = ExternalTwoByteString::cast(this);
   1205   self->set_resource(resource);
   1206   if (is_internalized) self->Hash();  // Force regeneration of the hash value.
   1207 
   1208   // Fill the remainder of the string with dead wood.
   1209   int new_size = this->Size();  // Byte size of the external String object.
   1210   heap->CreateFillerObjectAt(this->address() + new_size, size - new_size);
   1211   if (Marking::IsBlack(Marking::MarkBitFrom(this))) {
   1212     MemoryChunk::IncrementLiveBytesFromMutator(this->address(),
   1213                                                new_size - size);
   1214   }
   1215   return true;
   1216 }
   1217 
   1218 
   1219 bool String::MakeExternal(v8::String::ExternalAsciiStringResource* resource) {
   1220 #ifdef DEBUG
   1221   if (FLAG_enable_slow_asserts) {
   1222     // Assert that the resource and the string are equivalent.
   1223     ASSERT(static_cast<size_t>(this->length()) == resource->length());
   1224     if (this->IsTwoByteRepresentation()) {
   1225       ScopedVector<uint16_t> smart_chars(this->length());
   1226       String::WriteToFlat(this, smart_chars.start(), 0, this->length());
   1227       ASSERT(String::IsOneByte(smart_chars.start(), this->length()));
   1228     }
   1229     ScopedVector<char> smart_chars(this->length());
   1230     String::WriteToFlat(this, smart_chars.start(), 0, this->length());
   1231     ASSERT(memcmp(smart_chars.start(),
   1232                   resource->data(),
   1233                   resource->length() * sizeof(smart_chars[0])) == 0);
   1234   }
   1235 #endif  // DEBUG
   1236   Heap* heap = GetHeap();
   1237   int size = this->Size();  // Byte size of the original string.
   1238   if (size < ExternalString::kShortSize) {
   1239     return false;
   1240   }
   1241   bool is_internalized = this->IsInternalizedString();
   1242 
   1243   // Morph the object to an external string by adjusting the map and
   1244   // reinitializing the fields.  Use short version if space is limited.
   1245   if (size >= ExternalString::kSize) {
   1246     this->set_map_no_write_barrier(
   1247         is_internalized ? heap->external_ascii_internalized_string_map()
   1248                         : heap->external_ascii_string_map());
   1249   } else {
   1250     this->set_map_no_write_barrier(
   1251         is_internalized ? heap->short_external_ascii_internalized_string_map()
   1252                         : heap->short_external_ascii_string_map());
   1253   }
   1254   ExternalAsciiString* self = ExternalAsciiString::cast(this);
   1255   self->set_resource(resource);
   1256   if (is_internalized) self->Hash();  // Force regeneration of the hash value.
   1257 
   1258   // Fill the remainder of the string with dead wood.
   1259   int new_size = this->Size();  // Byte size of the external String object.
   1260   heap->CreateFillerObjectAt(this->address() + new_size, size - new_size);
   1261   if (Marking::IsBlack(Marking::MarkBitFrom(this))) {
   1262     MemoryChunk::IncrementLiveBytesFromMutator(this->address(),
   1263                                                new_size - size);
   1264   }
   1265   return true;
   1266 }
   1267 
   1268 
   1269 void String::StringShortPrint(StringStream* accumulator) {
   1270   int len = length();
   1271   if (len > kMaxShortPrintLength) {
   1272     accumulator->Add("<Very long string[%u]>", len);
   1273     return;
   1274   }
   1275 
   1276   if (!LooksValid()) {
   1277     accumulator->Add("<Invalid String>");
   1278     return;
   1279   }
   1280 
   1281   ConsStringIteratorOp op;
   1282   StringCharacterStream stream(this, &op);
   1283 
   1284   bool truncated = false;
   1285   if (len > kMaxShortPrintLength) {
   1286     len = kMaxShortPrintLength;
   1287     truncated = true;
   1288   }
   1289   bool ascii = true;
   1290   for (int i = 0; i < len; i++) {
   1291     uint16_t c = stream.GetNext();
   1292 
   1293     if (c < 32 || c >= 127) {
   1294       ascii = false;
   1295     }
   1296   }
   1297   stream.Reset(this);
   1298   if (ascii) {
   1299     accumulator->Add("<String[%u]: ", length());
   1300     for (int i = 0; i < len; i++) {
   1301       accumulator->Put(static_cast<char>(stream.GetNext()));
   1302     }
   1303     accumulator->Put('>');
   1304   } else {
   1305     // Backslash indicates that the string contains control
   1306     // characters and that backslashes are therefore escaped.
   1307     accumulator->Add("<String[%u]\\: ", length());
   1308     for (int i = 0; i < len; i++) {
   1309       uint16_t c = stream.GetNext();
   1310       if (c == '\n') {
   1311         accumulator->Add("\\n");
   1312       } else if (c == '\r') {
   1313         accumulator->Add("\\r");
   1314       } else if (c == '\\') {
   1315         accumulator->Add("\\\\");
   1316       } else if (c < 32 || c > 126) {
   1317         accumulator->Add("\\x%02x", c);
   1318       } else {
   1319         accumulator->Put(static_cast<char>(c));
   1320       }
   1321     }
   1322     if (truncated) {
   1323       accumulator->Put('.');
   1324       accumulator->Put('.');
   1325       accumulator->Put('.');
   1326     }
   1327     accumulator->Put('>');
   1328   }
   1329   return;
   1330 }
   1331 
   1332 
   1333 void JSObject::JSObjectShortPrint(StringStream* accumulator) {
   1334   switch (map()->instance_type()) {
   1335     case JS_ARRAY_TYPE: {
   1336       double length = JSArray::cast(this)->length()->IsUndefined()
   1337           ? 0
   1338           : JSArray::cast(this)->length()->Number();
   1339       accumulator->Add("<JS Array[%u]>", static_cast<uint32_t>(length));
   1340       break;
   1341     }
   1342     case JS_WEAK_MAP_TYPE: {
   1343       accumulator->Add("<JS WeakMap>");
   1344       break;
   1345     }
   1346     case JS_WEAK_SET_TYPE: {
   1347       accumulator->Add("<JS WeakSet>");
   1348       break;
   1349     }
   1350     case JS_REGEXP_TYPE: {
   1351       accumulator->Add("<JS RegExp>");
   1352       break;
   1353     }
   1354     case JS_FUNCTION_TYPE: {
   1355       JSFunction* function = JSFunction::cast(this);
   1356       Object* fun_name = function->shared()->DebugName();
   1357       bool printed = false;
   1358       if (fun_name->IsString()) {
   1359         String* str = String::cast(fun_name);
   1360         if (str->length() > 0) {
   1361           accumulator->Add("<JS Function ");
   1362           accumulator->Put(str);
   1363           printed = true;
   1364         }
   1365       }
   1366       if (!printed) {
   1367         accumulator->Add("<JS Function");
   1368       }
   1369       accumulator->Add(" (SharedFunctionInfo %p)",
   1370                        reinterpret_cast<void*>(function->shared()));
   1371       accumulator->Put('>');
   1372       break;
   1373     }
   1374     case JS_GENERATOR_OBJECT_TYPE: {
   1375       accumulator->Add("<JS Generator>");
   1376       break;
   1377     }
   1378     case JS_MODULE_TYPE: {
   1379       accumulator->Add("<JS Module>");
   1380       break;
   1381     }
   1382     // All other JSObjects are rather similar to each other (JSObject,
   1383     // JSGlobalProxy, JSGlobalObject, JSUndetectableObject, JSValue).
   1384     default: {
   1385       Map* map_of_this = map();
   1386       Heap* heap = GetHeap();
   1387       Object* constructor = map_of_this->constructor();
   1388       bool printed = false;
   1389       if (constructor->IsHeapObject() &&
   1390           !heap->Contains(HeapObject::cast(constructor))) {
   1391         accumulator->Add("!!!INVALID CONSTRUCTOR!!!");
   1392       } else {
   1393         bool global_object = IsJSGlobalProxy();
   1394         if (constructor->IsJSFunction()) {
   1395           if (!heap->Contains(JSFunction::cast(constructor)->shared())) {
   1396             accumulator->Add("!!!INVALID SHARED ON CONSTRUCTOR!!!");
   1397           } else {
   1398             Object* constructor_name =
   1399                 JSFunction::cast(constructor)->shared()->name();
   1400             if (constructor_name->IsString()) {
   1401               String* str = String::cast(constructor_name);
   1402               if (str->length() > 0) {
   1403                 bool vowel = AnWord(str);
   1404                 accumulator->Add("<%sa%s ",
   1405                        global_object ? "Global Object: " : "",
   1406                        vowel ? "n" : "");
   1407                 accumulator->Put(str);
   1408                 accumulator->Add(" with %smap %p",
   1409                     map_of_this->is_deprecated() ? "deprecated " : "",
   1410                     map_of_this);
   1411                 printed = true;
   1412               }
   1413             }
   1414           }
   1415         }
   1416         if (!printed) {
   1417           accumulator->Add("<JS %sObject", global_object ? "Global " : "");
   1418         }
   1419       }
   1420       if (IsJSValue()) {
   1421         accumulator->Add(" value = ");
   1422         JSValue::cast(this)->value()->ShortPrint(accumulator);
   1423       }
   1424       accumulator->Put('>');
   1425       break;
   1426     }
   1427   }
   1428 }
   1429 
   1430 
   1431 void JSObject::PrintElementsTransition(
   1432     FILE* file, ElementsKind from_kind, FixedArrayBase* from_elements,
   1433     ElementsKind to_kind, FixedArrayBase* to_elements) {
   1434   if (from_kind != to_kind) {
   1435     PrintF(file, "elements transition [");
   1436     PrintElementsKind(file, from_kind);
   1437     PrintF(file, " -> ");
   1438     PrintElementsKind(file, to_kind);
   1439     PrintF(file, "] in ");
   1440     JavaScriptFrame::PrintTop(GetIsolate(), file, false, true);
   1441     PrintF(file, " for ");
   1442     ShortPrint(file);
   1443     PrintF(file, " from ");
   1444     from_elements->ShortPrint(file);
   1445     PrintF(file, " to ");
   1446     to_elements->ShortPrint(file);
   1447     PrintF(file, "\n");
   1448   }
   1449 }
   1450 
   1451 
   1452 void HeapObject::HeapObjectShortPrint(StringStream* accumulator) {
   1453   Heap* heap = GetHeap();
   1454   if (!heap->Contains(this)) {
   1455     accumulator->Add("!!!INVALID POINTER!!!");
   1456     return;
   1457   }
   1458   if (!heap->Contains(map())) {
   1459     accumulator->Add("!!!INVALID MAP!!!");
   1460     return;
   1461   }
   1462 
   1463   accumulator->Add("%p ", this);
   1464 
   1465   if (IsString()) {
   1466     String::cast(this)->StringShortPrint(accumulator);
   1467     return;
   1468   }
   1469   if (IsJSObject()) {
   1470     JSObject::cast(this)->JSObjectShortPrint(accumulator);
   1471     return;
   1472   }
   1473   switch (map()->instance_type()) {
   1474     case MAP_TYPE:
   1475       accumulator->Add("<Map(elements=%u)>", Map::cast(this)->elements_kind());
   1476       break;
   1477     case FIXED_ARRAY_TYPE:
   1478       accumulator->Add("<FixedArray[%u]>", FixedArray::cast(this)->length());
   1479       break;
   1480     case FIXED_DOUBLE_ARRAY_TYPE:
   1481       accumulator->Add("<FixedDoubleArray[%u]>",
   1482                        FixedDoubleArray::cast(this)->length());
   1483       break;
   1484     case BYTE_ARRAY_TYPE:
   1485       accumulator->Add("<ByteArray[%u]>", ByteArray::cast(this)->length());
   1486       break;
   1487     case FREE_SPACE_TYPE:
   1488       accumulator->Add("<FreeSpace[%u]>", FreeSpace::cast(this)->Size());
   1489       break;
   1490     case EXTERNAL_PIXEL_ARRAY_TYPE:
   1491       accumulator->Add("<ExternalPixelArray[%u]>",
   1492                        ExternalPixelArray::cast(this)->length());
   1493       break;
   1494     case EXTERNAL_BYTE_ARRAY_TYPE:
   1495       accumulator->Add("<ExternalByteArray[%u]>",
   1496                        ExternalByteArray::cast(this)->length());
   1497       break;
   1498     case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
   1499       accumulator->Add("<ExternalUnsignedByteArray[%u]>",
   1500                        ExternalUnsignedByteArray::cast(this)->length());
   1501       break;
   1502     case EXTERNAL_SHORT_ARRAY_TYPE:
   1503       accumulator->Add("<ExternalShortArray[%u]>",
   1504                        ExternalShortArray::cast(this)->length());
   1505       break;
   1506     case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
   1507       accumulator->Add("<ExternalUnsignedShortArray[%u]>",
   1508                        ExternalUnsignedShortArray::cast(this)->length());
   1509       break;
   1510     case EXTERNAL_INT_ARRAY_TYPE:
   1511       accumulator->Add("<ExternalIntArray[%u]>",
   1512                        ExternalIntArray::cast(this)->length());
   1513       break;
   1514     case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
   1515       accumulator->Add("<ExternalUnsignedIntArray[%u]>",
   1516                        ExternalUnsignedIntArray::cast(this)->length());
   1517       break;
   1518     case EXTERNAL_FLOAT_ARRAY_TYPE:
   1519       accumulator->Add("<ExternalFloatArray[%u]>",
   1520                        ExternalFloatArray::cast(this)->length());
   1521       break;
   1522     case EXTERNAL_DOUBLE_ARRAY_TYPE:
   1523       accumulator->Add("<ExternalDoubleArray[%u]>",
   1524                        ExternalDoubleArray::cast(this)->length());
   1525       break;
   1526     case SHARED_FUNCTION_INFO_TYPE: {
   1527       SharedFunctionInfo* shared = SharedFunctionInfo::cast(this);
   1528       SmartArrayPointer<char> debug_name =
   1529           shared->DebugName()->ToCString();
   1530       if (debug_name[0] != 0) {
   1531         accumulator->Add("<SharedFunctionInfo %s>", *debug_name);
   1532       } else {
   1533         accumulator->Add("<SharedFunctionInfo>");
   1534       }
   1535       break;
   1536     }
   1537     case JS_MESSAGE_OBJECT_TYPE:
   1538       accumulator->Add("<JSMessageObject>");
   1539       break;
   1540 #define MAKE_STRUCT_CASE(NAME, Name, name) \
   1541   case NAME##_TYPE:                        \
   1542     accumulator->Put('<');                 \
   1543     accumulator->Add(#Name);               \
   1544     accumulator->Put('>');                 \
   1545     break;
   1546   STRUCT_LIST(MAKE_STRUCT_CASE)
   1547 #undef MAKE_STRUCT_CASE
   1548     case CODE_TYPE:
   1549       accumulator->Add("<Code>");
   1550       break;
   1551     case ODDBALL_TYPE: {
   1552       if (IsUndefined())
   1553         accumulator->Add("<undefined>");
   1554       else if (IsTheHole())
   1555         accumulator->Add("<the hole>");
   1556       else if (IsNull())
   1557         accumulator->Add("<null>");
   1558       else if (IsTrue())
   1559         accumulator->Add("<true>");
   1560       else if (IsFalse())
   1561         accumulator->Add("<false>");
   1562       else
   1563         accumulator->Add("<Odd Oddball>");
   1564       break;
   1565     }
   1566     case SYMBOL_TYPE: {
   1567       Symbol* symbol = Symbol::cast(this);
   1568       accumulator->Add("<Symbol: %d", symbol->Hash());
   1569       if (!symbol->name()->IsUndefined()) {
   1570         accumulator->Add(" ");
   1571         String::cast(symbol->name())->StringShortPrint(accumulator);
   1572       }
   1573       accumulator->Add(">");
   1574       break;
   1575     }
   1576     case HEAP_NUMBER_TYPE:
   1577       accumulator->Add("<Number: ");
   1578       HeapNumber::cast(this)->HeapNumberPrint(accumulator);
   1579       accumulator->Put('>');
   1580       break;
   1581     case JS_PROXY_TYPE:
   1582       accumulator->Add("<JSProxy>");
   1583       break;
   1584     case JS_FUNCTION_PROXY_TYPE:
   1585       accumulator->Add("<JSFunctionProxy>");
   1586       break;
   1587     case FOREIGN_TYPE:
   1588       accumulator->Add("<Foreign>");
   1589       break;
   1590     case CELL_TYPE:
   1591       accumulator->Add("Cell for ");
   1592       Cell::cast(this)->value()->ShortPrint(accumulator);
   1593       break;
   1594     case PROPERTY_CELL_TYPE:
   1595       accumulator->Add("PropertyCell for ");
   1596       PropertyCell::cast(this)->value()->ShortPrint(accumulator);
   1597       break;
   1598     default:
   1599       accumulator->Add("<Other heap object (%d)>", map()->instance_type());
   1600       break;
   1601   }
   1602 }
   1603 
   1604 
   1605 void HeapObject::Iterate(ObjectVisitor* v) {
   1606   // Handle header
   1607   IteratePointer(v, kMapOffset);
   1608   // Handle object body
   1609   Map* m = map();
   1610   IterateBody(m->instance_type(), SizeFromMap(m), v);
   1611 }
   1612 
   1613 
   1614 void HeapObject::IterateBody(InstanceType type, int object_size,
   1615                              ObjectVisitor* v) {
   1616   // Avoiding <Type>::cast(this) because it accesses the map pointer field.
   1617   // During GC, the map pointer field is encoded.
   1618   if (type < FIRST_NONSTRING_TYPE) {
   1619     switch (type & kStringRepresentationMask) {
   1620       case kSeqStringTag:
   1621         break;
   1622       case kConsStringTag:
   1623         ConsString::BodyDescriptor::IterateBody(this, v);
   1624         break;
   1625       case kSlicedStringTag:
   1626         SlicedString::BodyDescriptor::IterateBody(this, v);
   1627         break;
   1628       case kExternalStringTag:
   1629         if ((type & kStringEncodingMask) == kOneByteStringTag) {
   1630           reinterpret_cast<ExternalAsciiString*>(this)->
   1631               ExternalAsciiStringIterateBody(v);
   1632         } else {
   1633           reinterpret_cast<ExternalTwoByteString*>(this)->
   1634               ExternalTwoByteStringIterateBody(v);
   1635         }
   1636         break;
   1637     }
   1638     return;
   1639   }
   1640 
   1641   switch (type) {
   1642     case FIXED_ARRAY_TYPE:
   1643       FixedArray::BodyDescriptor::IterateBody(this, object_size, v);
   1644       break;
   1645     case FIXED_DOUBLE_ARRAY_TYPE:
   1646       break;
   1647     case JS_OBJECT_TYPE:
   1648     case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
   1649     case JS_GENERATOR_OBJECT_TYPE:
   1650     case JS_MODULE_TYPE:
   1651     case JS_VALUE_TYPE:
   1652     case JS_DATE_TYPE:
   1653     case JS_ARRAY_TYPE:
   1654     case JS_ARRAY_BUFFER_TYPE:
   1655     case JS_TYPED_ARRAY_TYPE:
   1656     case JS_DATA_VIEW_TYPE:
   1657     case JS_SET_TYPE:
   1658     case JS_MAP_TYPE:
   1659     case JS_WEAK_MAP_TYPE:
   1660     case JS_WEAK_SET_TYPE:
   1661     case JS_REGEXP_TYPE:
   1662     case JS_GLOBAL_PROXY_TYPE:
   1663     case JS_GLOBAL_OBJECT_TYPE:
   1664     case JS_BUILTINS_OBJECT_TYPE:
   1665     case JS_MESSAGE_OBJECT_TYPE:
   1666       JSObject::BodyDescriptor::IterateBody(this, object_size, v);
   1667       break;
   1668     case JS_FUNCTION_TYPE:
   1669       reinterpret_cast<JSFunction*>(this)
   1670           ->JSFunctionIterateBody(object_size, v);
   1671       break;
   1672     case ODDBALL_TYPE:
   1673       Oddball::BodyDescriptor::IterateBody(this, v);
   1674       break;
   1675     case JS_PROXY_TYPE:
   1676       JSProxy::BodyDescriptor::IterateBody(this, v);
   1677       break;
   1678     case JS_FUNCTION_PROXY_TYPE:
   1679       JSFunctionProxy::BodyDescriptor::IterateBody(this, v);
   1680       break;
   1681     case FOREIGN_TYPE:
   1682       reinterpret_cast<Foreign*>(this)->ForeignIterateBody(v);
   1683       break;
   1684     case MAP_TYPE:
   1685       Map::BodyDescriptor::IterateBody(this, v);
   1686       break;
   1687     case CODE_TYPE:
   1688       reinterpret_cast<Code*>(this)->CodeIterateBody(v);
   1689       break;
   1690     case CELL_TYPE:
   1691       Cell::BodyDescriptor::IterateBody(this, v);
   1692       break;
   1693     case PROPERTY_CELL_TYPE:
   1694       PropertyCell::BodyDescriptor::IterateBody(this, v);
   1695       break;
   1696     case SYMBOL_TYPE:
   1697       Symbol::BodyDescriptor::IterateBody(this, v);
   1698       break;
   1699     case HEAP_NUMBER_TYPE:
   1700     case FILLER_TYPE:
   1701     case BYTE_ARRAY_TYPE:
   1702     case FREE_SPACE_TYPE:
   1703     case EXTERNAL_PIXEL_ARRAY_TYPE:
   1704     case EXTERNAL_BYTE_ARRAY_TYPE:
   1705     case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
   1706     case EXTERNAL_SHORT_ARRAY_TYPE:
   1707     case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
   1708     case EXTERNAL_INT_ARRAY_TYPE:
   1709     case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
   1710     case EXTERNAL_FLOAT_ARRAY_TYPE:
   1711     case EXTERNAL_DOUBLE_ARRAY_TYPE:
   1712       break;
   1713     case SHARED_FUNCTION_INFO_TYPE: {
   1714       SharedFunctionInfo::BodyDescriptor::IterateBody(this, v);
   1715       break;
   1716     }
   1717 
   1718 #define MAKE_STRUCT_CASE(NAME, Name, name) \
   1719         case NAME##_TYPE:
   1720       STRUCT_LIST(MAKE_STRUCT_CASE)
   1721 #undef MAKE_STRUCT_CASE
   1722       if (type == ALLOCATION_SITE_TYPE) {
   1723         AllocationSite::BodyDescriptor::IterateBody(this, v);
   1724       } else {
   1725         StructBodyDescriptor::IterateBody(this, object_size, v);
   1726       }
   1727       break;
   1728     default:
   1729       PrintF("Unknown type: %d\n", type);
   1730       UNREACHABLE();
   1731   }
   1732 }
   1733 
   1734 
   1735 bool HeapNumber::HeapNumberBooleanValue() {
   1736   // NaN, +0, and -0 should return the false object
   1737 #if __BYTE_ORDER == __LITTLE_ENDIAN
   1738   union IeeeDoubleLittleEndianArchType u;
   1739 #elif __BYTE_ORDER == __BIG_ENDIAN
   1740   union IeeeDoubleBigEndianArchType u;
   1741 #endif
   1742   u.d = value();
   1743   if (u.bits.exp == 2047) {
   1744     // Detect NaN for IEEE double precision floating point.
   1745     if ((u.bits.man_low | u.bits.man_high) != 0) return false;
   1746   }
   1747   if (u.bits.exp == 0) {
   1748     // Detect +0, and -0 for IEEE double precision floating point.
   1749     if ((u.bits.man_low | u.bits.man_high) == 0) return false;
   1750   }
   1751   return true;
   1752 }
   1753 
   1754 
   1755 void HeapNumber::HeapNumberPrint(FILE* out) {
   1756   PrintF(out, "%.16g", Number());
   1757 }
   1758 
   1759 
   1760 void HeapNumber::HeapNumberPrint(StringStream* accumulator) {
   1761   // The Windows version of vsnprintf can allocate when printing a %g string
   1762   // into a buffer that may not be big enough.  We don't want random memory
   1763   // allocation when producing post-crash stack traces, so we print into a
   1764   // buffer that is plenty big enough for any floating point number, then
   1765   // print that using vsnprintf (which may truncate but never allocate if
   1766   // there is no more space in the buffer).
   1767   EmbeddedVector<char, 100> buffer;
   1768   OS::SNPrintF(buffer, "%.16g", Number());
   1769   accumulator->Add("%s", buffer.start());
   1770 }
   1771 
   1772 
   1773 String* JSReceiver::class_name() {
   1774   if (IsJSFunction() && IsJSFunctionProxy()) {
   1775     return GetHeap()->function_class_string();
   1776   }
   1777   if (map()->constructor()->IsJSFunction()) {
   1778     JSFunction* constructor = JSFunction::cast(map()->constructor());
   1779     return String::cast(constructor->shared()->instance_class_name());
   1780   }
   1781   // If the constructor is not present, return "Object".
   1782   return GetHeap()->Object_string();
   1783 }
   1784 
   1785 
   1786 String* JSReceiver::constructor_name() {
   1787   if (map()->constructor()->IsJSFunction()) {
   1788     JSFunction* constructor = JSFunction::cast(map()->constructor());
   1789     String* name = String::cast(constructor->shared()->name());
   1790     if (name->length() > 0) return name;
   1791     String* inferred_name = constructor->shared()->inferred_name();
   1792     if (inferred_name->length() > 0) return inferred_name;
   1793     Object* proto = GetPrototype();
   1794     if (proto->IsJSObject()) return JSObject::cast(proto)->constructor_name();
   1795   }
   1796   // TODO(rossberg): what about proxies?
   1797   // If the constructor is not present, return "Object".
   1798   return GetHeap()->Object_string();
   1799 }
   1800 
   1801 
   1802 MaybeObject* JSObject::AddFastPropertyUsingMap(Map* new_map,
   1803                                                Name* name,
   1804                                                Object* value,
   1805                                                int field_index,
   1806                                                Representation representation) {
   1807   // This method is used to transition to a field. If we are transitioning to a
   1808   // double field, allocate new storage.
   1809   Object* storage;
   1810   MaybeObject* maybe_storage =
   1811       value->AllocateNewStorageFor(GetHeap(), representation);
   1812   if (!maybe_storage->To(&storage)) return maybe_storage;
   1813 
   1814   if (map()->unused_property_fields() == 0) {
   1815     int new_unused = new_map->unused_property_fields();
   1816     FixedArray* values;
   1817     MaybeObject* maybe_values =
   1818         properties()->CopySize(properties()->length() + new_unused + 1);
   1819     if (!maybe_values->To(&values)) return maybe_values;
   1820 
   1821     set_properties(values);
   1822   }
   1823 
   1824   set_map(new_map);
   1825 
   1826   FastPropertyAtPut(field_index, storage);
   1827   return value;
   1828 }
   1829 
   1830 
   1831 static bool IsIdentifier(UnicodeCache* cache, Name* name) {
   1832   // Checks whether the buffer contains an identifier (no escape).
   1833   if (!name->IsString()) return false;
   1834   String* string = String::cast(name);
   1835   if (string->length() == 0) return false;
   1836   ConsStringIteratorOp op;
   1837   StringCharacterStream stream(string, &op);
   1838   if (!cache->IsIdentifierStart(stream.GetNext())) {
   1839     return false;
   1840   }
   1841   while (stream.HasMore()) {
   1842     if (!cache->IsIdentifierPart(stream.GetNext())) {
   1843       return false;
   1844     }
   1845   }
   1846   return true;
   1847 }
   1848 
   1849 
   1850 MaybeObject* JSObject::AddFastProperty(Name* name,
   1851                                        Object* value,
   1852                                        PropertyAttributes attributes,
   1853                                        StoreFromKeyed store_mode,
   1854                                        ValueType value_type) {
   1855   ASSERT(!IsJSGlobalProxy());
   1856   ASSERT(DescriptorArray::kNotFound ==
   1857          map()->instance_descriptors()->Search(
   1858              name, map()->NumberOfOwnDescriptors()));
   1859 
   1860   // Normalize the object if the name is an actual name (not the
   1861   // hidden strings) and is not a real identifier.
   1862   // Normalize the object if it will have too many fast properties.
   1863   Isolate* isolate = GetHeap()->isolate();
   1864   if ((!name->IsSymbol() && !IsIdentifier(isolate->unicode_cache(), name)
   1865        && name != isolate->heap()->hidden_string()) ||
   1866       (map()->unused_property_fields() == 0 &&
   1867        TooManyFastProperties(properties()->length(), store_mode))) {
   1868     Object* obj;
   1869     MaybeObject* maybe_obj =
   1870         NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
   1871     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   1872 
   1873     return AddSlowProperty(name, value, attributes);
   1874   }
   1875 
   1876   // Compute the new index for new field.
   1877   int index = map()->NextFreePropertyIndex();
   1878 
   1879   // Allocate new instance descriptors with (name, index) added
   1880   if (IsJSContextExtensionObject()) value_type = FORCE_TAGGED;
   1881   Representation representation = value->OptimalRepresentation(value_type);
   1882 
   1883   FieldDescriptor new_field(name, index, attributes, representation);
   1884 
   1885   ASSERT(index < map()->inobject_properties() ||
   1886          (index - map()->inobject_properties()) < properties()->length() ||
   1887          map()->unused_property_fields() == 0);
   1888 
   1889   FixedArray* values = NULL;
   1890 
   1891   // TODO(verwaest): Merge with AddFastPropertyUsingMap.
   1892   if (map()->unused_property_fields() == 0) {
   1893     // Make room for the new value
   1894     MaybeObject* maybe_values =
   1895         properties()->CopySize(properties()->length() + kFieldsAdded);
   1896     if (!maybe_values->To(&values)) return maybe_values;
   1897   }
   1898 
   1899   TransitionFlag flag = INSERT_TRANSITION;
   1900 
   1901   Heap* heap = isolate->heap();
   1902 
   1903   Object* storage;
   1904   MaybeObject* maybe_storage =
   1905       value->AllocateNewStorageFor(heap, representation);
   1906   if (!maybe_storage->To(&storage)) return maybe_storage;
   1907 
   1908   // Note that Map::CopyAddDescriptor has side-effects, the new map is already
   1909   // inserted in the transition tree. No more allocations that might fail are
   1910   // allowed after this point.
   1911   Map* new_map;
   1912   MaybeObject* maybe_new_map = map()->CopyAddDescriptor(&new_field, flag);
   1913   if (!maybe_new_map->To(&new_map)) return maybe_new_map;
   1914 
   1915   if (map()->unused_property_fields() == 0) {
   1916     ASSERT(values != NULL);
   1917     set_properties(values);
   1918     new_map->set_unused_property_fields(kFieldsAdded - 1);
   1919   } else {
   1920     new_map->set_unused_property_fields(map()->unused_property_fields() - 1);
   1921   }
   1922 
   1923   set_map(new_map);
   1924 
   1925   FastPropertyAtPut(index, storage);
   1926   return value;
   1927 }
   1928 
   1929 
   1930 MaybeObject* JSObject::AddConstantProperty(
   1931     Name* name,
   1932     Object* constant,
   1933     PropertyAttributes attributes) {
   1934   // Allocate new instance descriptors with (name, constant) added
   1935   ConstantDescriptor d(name, constant, attributes);
   1936 
   1937   TransitionFlag flag =
   1938       // Do not add transitions to  global objects.
   1939       (IsGlobalObject() ||
   1940       // Don't add transitions to special properties with non-trivial
   1941       // attributes.
   1942        attributes != NONE)
   1943       ? OMIT_TRANSITION
   1944       : INSERT_TRANSITION;
   1945 
   1946   Map* new_map;
   1947   MaybeObject* maybe_new_map = map()->CopyAddDescriptor(&d, flag);
   1948   if (!maybe_new_map->To(&new_map)) return maybe_new_map;
   1949 
   1950   set_map(new_map);
   1951   return constant;
   1952 }
   1953 
   1954 
   1955 // Add property in slow mode
   1956 MaybeObject* JSObject::AddSlowProperty(Name* name,
   1957                                        Object* value,
   1958                                        PropertyAttributes attributes) {
   1959   ASSERT(!HasFastProperties());
   1960   NameDictionary* dict = property_dictionary();
   1961   Object* store_value = value;
   1962   if (IsGlobalObject()) {
   1963     // In case name is an orphaned property reuse the cell.
   1964     int entry = dict->FindEntry(name);
   1965     if (entry != NameDictionary::kNotFound) {
   1966       store_value = dict->ValueAt(entry);
   1967       MaybeObject* maybe_type =
   1968           PropertyCell::cast(store_value)->SetValueInferType(value);
   1969       if (maybe_type->IsFailure()) return maybe_type;
   1970       // Assign an enumeration index to the property and update
   1971       // SetNextEnumerationIndex.
   1972       int index = dict->NextEnumerationIndex();
   1973       PropertyDetails details = PropertyDetails(attributes, NORMAL, index);
   1974       dict->SetNextEnumerationIndex(index + 1);
   1975       dict->SetEntry(entry, name, store_value, details);
   1976       return value;
   1977     }
   1978     Heap* heap = GetHeap();
   1979     { MaybeObject* maybe_store_value =
   1980           heap->AllocatePropertyCell(value);
   1981       if (!maybe_store_value->ToObject(&store_value)) return maybe_store_value;
   1982     }
   1983     MaybeObject* maybe_type =
   1984         PropertyCell::cast(store_value)->SetValueInferType(value);
   1985     if (maybe_type->IsFailure()) return maybe_type;
   1986   }
   1987   PropertyDetails details = PropertyDetails(attributes, NORMAL, 0);
   1988   Object* result;
   1989   { MaybeObject* maybe_result = dict->Add(name, store_value, details);
   1990     if (!maybe_result->ToObject(&result)) return maybe_result;
   1991   }
   1992   if (dict != result) set_properties(NameDictionary::cast(result));
   1993   return value;
   1994 }
   1995 
   1996 
   1997 MaybeObject* JSObject::AddProperty(Name* name,
   1998                                    Object* value,
   1999                                    PropertyAttributes attributes,
   2000                                    StrictModeFlag strict_mode,
   2001                                    JSReceiver::StoreFromKeyed store_mode,
   2002                                    ExtensibilityCheck extensibility_check,
   2003                                    ValueType value_type,
   2004                                    StoreMode mode) {
   2005   ASSERT(!IsJSGlobalProxy());
   2006   Map* map_of_this = map();
   2007   Heap* heap = GetHeap();
   2008   Isolate* isolate = heap->isolate();
   2009   MaybeObject* result;
   2010   if (extensibility_check == PERFORM_EXTENSIBILITY_CHECK &&
   2011       !map_of_this->is_extensible()) {
   2012     if (strict_mode == kNonStrictMode) {
   2013       return value;
   2014     } else {
   2015       Handle<Object> args[1] = {Handle<Name>(name)};
   2016       return isolate->Throw(
   2017           *isolate->factory()->NewTypeError("object_not_extensible",
   2018                                             HandleVector(args, 1)));
   2019     }
   2020   }
   2021 
   2022   if (HasFastProperties()) {
   2023     // Ensure the descriptor array does not get too big.
   2024     if (map_of_this->NumberOfOwnDescriptors() <
   2025         DescriptorArray::kMaxNumberOfDescriptors) {
   2026       // TODO(verwaest): Support other constants.
   2027       // if (mode == ALLOW_AS_CONSTANT &&
   2028       //     !value->IsTheHole() &&
   2029       //     !value->IsConsString()) {
   2030       if (value->IsJSFunction()) {
   2031         result = AddConstantProperty(name, value, attributes);
   2032       } else {
   2033         result = AddFastProperty(
   2034             name, value, attributes, store_mode, value_type);
   2035       }
   2036     } else {
   2037       // Normalize the object to prevent very large instance descriptors.
   2038       // This eliminates unwanted N^2 allocation and lookup behavior.
   2039       Object* obj;
   2040       MaybeObject* maybe = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
   2041       if (!maybe->To(&obj)) return maybe;
   2042       result = AddSlowProperty(name, value, attributes);
   2043     }
   2044   } else {
   2045     result = AddSlowProperty(name, value, attributes);
   2046   }
   2047 
   2048   Handle<Object> hresult;
   2049   if (!result->ToHandle(&hresult, isolate)) return result;
   2050 
   2051   if (FLAG_harmony_observation && map()->is_observed()) {
   2052     EnqueueChangeRecord(handle(this, isolate),
   2053                         "new",
   2054                         handle(name, isolate),
   2055                         handle(heap->the_hole_value(), isolate));
   2056   }
   2057 
   2058   return *hresult;
   2059 }
   2060 
   2061 
   2062 void JSObject::EnqueueChangeRecord(Handle<JSObject> object,
   2063                                    const char* type_str,
   2064                                    Handle<Name> name,
   2065                                    Handle<Object> old_value) {
   2066   Isolate* isolate = object->GetIsolate();
   2067   HandleScope scope(isolate);
   2068   Handle<String> type = isolate->factory()->InternalizeUtf8String(type_str);
   2069   if (object->IsJSGlobalObject()) {
   2070     object = handle(JSGlobalObject::cast(*object)->global_receiver(), isolate);
   2071   }
   2072   Handle<Object> args[] = { type, object, name, old_value };
   2073   bool threw;
   2074   Execution::Call(Handle<JSFunction>(isolate->observers_notify_change()),
   2075                   isolate->factory()->undefined_value(),
   2076                   old_value->IsTheHole() ? 3 : 4, args,
   2077                   &threw);
   2078   ASSERT(!threw);
   2079 }
   2080 
   2081 
   2082 void JSObject::DeliverChangeRecords(Isolate* isolate) {
   2083   ASSERT(isolate->observer_delivery_pending());
   2084   bool threw = false;
   2085   Execution::Call(
   2086       isolate->observers_deliver_changes(),
   2087       isolate->factory()->undefined_value(),
   2088       0,
   2089       NULL,
   2090       &threw);
   2091   ASSERT(!threw);
   2092   isolate->set_observer_delivery_pending(false);
   2093 }
   2094 
   2095 
   2096 MaybeObject* JSObject::SetPropertyPostInterceptor(
   2097     Name* name,
   2098     Object* value,
   2099     PropertyAttributes attributes,
   2100     StrictModeFlag strict_mode,
   2101     ExtensibilityCheck extensibility_check,
   2102     StoreMode mode) {
   2103   // Check local property, ignore interceptor.
   2104   LookupResult result(GetIsolate());
   2105   LocalLookupRealNamedProperty(name, &result);
   2106   if (!result.IsFound()) map()->LookupTransition(this, name, &result);
   2107   if (result.IsFound()) {
   2108     // An existing property or a map transition was found. Use set property to
   2109     // handle all these cases.
   2110     return SetProperty(&result, name, value, attributes, strict_mode);
   2111   }
   2112   bool done = false;
   2113   MaybeObject* result_object;
   2114   result_object =
   2115       SetPropertyViaPrototypes(name, value, attributes, strict_mode, &done);
   2116   if (done) return result_object;
   2117   // Add a new real property.
   2118   return AddProperty(name, value, attributes, strict_mode,
   2119                      MAY_BE_STORE_FROM_KEYED, extensibility_check,
   2120                      OPTIMAL_REPRESENTATION, mode);
   2121 }
   2122 
   2123 
   2124 MaybeObject* JSObject::ReplaceSlowProperty(Name* name,
   2125                                            Object* value,
   2126                                            PropertyAttributes attributes) {
   2127   NameDictionary* dictionary = property_dictionary();
   2128   int old_index = dictionary->FindEntry(name);
   2129   int new_enumeration_index = 0;  // 0 means "Use the next available index."
   2130   if (old_index != -1) {
   2131     // All calls to ReplaceSlowProperty have had all transitions removed.
   2132     new_enumeration_index = dictionary->DetailsAt(old_index).dictionary_index();
   2133   }
   2134 
   2135   PropertyDetails new_details(attributes, NORMAL, new_enumeration_index);
   2136   return SetNormalizedProperty(name, value, new_details);
   2137 }
   2138 
   2139 
   2140 MaybeObject* JSObject::ConvertTransitionToMapTransition(
   2141     int transition_index,
   2142     Name* name,
   2143     Object* new_value,
   2144     PropertyAttributes attributes) {
   2145   Map* old_map = map();
   2146   Map* old_target = old_map->GetTransition(transition_index);
   2147   Object* result;
   2148 
   2149   MaybeObject* maybe_result = ConvertDescriptorToField(
   2150       name, new_value, attributes, OMIT_TRANSITION_KEEP_REPRESENTATIONS);
   2151   if (!maybe_result->To(&result)) return maybe_result;
   2152 
   2153   if (!HasFastProperties()) return result;
   2154 
   2155   // This method should only be used to convert existing transitions.
   2156   Map* new_map = map();
   2157 
   2158   // TODO(verwaest): From here on we lose existing map transitions, causing
   2159   // invalid back pointers. This will change once we can store multiple
   2160   // transitions with the same key.
   2161   bool owned_descriptors = old_map->owns_descriptors();
   2162   if (owned_descriptors ||
   2163       old_target->instance_descriptors() == old_map->instance_descriptors()) {
   2164     // Since the conversion above generated a new fast map with an additional
   2165     // property which can be shared as well, install this descriptor pointer
   2166     // along the entire chain of smaller maps.
   2167     Map* map;
   2168     DescriptorArray* new_descriptors = new_map->instance_descriptors();
   2169     DescriptorArray* old_descriptors = old_map->instance_descriptors();
   2170     for (Object* current = old_map;
   2171          !current->IsUndefined();
   2172          current = map->GetBackPointer()) {
   2173       map = Map::cast(current);
   2174       if (map->instance_descriptors() != old_descriptors) break;
   2175       map->SetEnumLength(Map::kInvalidEnumCache);
   2176       map->set_instance_descriptors(new_descriptors);
   2177     }
   2178     old_map->set_owns_descriptors(false);
   2179   }
   2180 
   2181   old_target->DeprecateTransitionTree();
   2182 
   2183   old_map->SetTransition(transition_index, new_map);
   2184   new_map->SetBackPointer(old_map);
   2185   return result;
   2186 }
   2187 
   2188 
   2189 MaybeObject* JSObject::ConvertDescriptorToField(Name* name,
   2190                                                 Object* new_value,
   2191                                                 PropertyAttributes attributes,
   2192                                                 TransitionFlag flag) {
   2193   if (map()->unused_property_fields() == 0 &&
   2194       TooManyFastProperties(properties()->length(), MAY_BE_STORE_FROM_KEYED)) {
   2195     Object* obj;
   2196     MaybeObject* maybe_obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
   2197     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   2198     return ReplaceSlowProperty(name, new_value, attributes);
   2199   }
   2200 
   2201   Representation representation = IsJSContextExtensionObject()
   2202       ? Representation::Tagged() : new_value->OptimalRepresentation();
   2203   int index = map()->NextFreePropertyIndex();
   2204   FieldDescriptor new_field(name, index, attributes, representation);
   2205 
   2206   // Make a new map for the object.
   2207   Map* new_map;
   2208   MaybeObject* maybe_new_map = map()->CopyInsertDescriptor(&new_field, flag);
   2209   if (!maybe_new_map->To(&new_map)) return maybe_new_map;
   2210 
   2211   // Make new properties array if necessary.
   2212   FixedArray* new_properties = NULL;
   2213   int new_unused_property_fields = map()->unused_property_fields() - 1;
   2214   if (map()->unused_property_fields() == 0) {
   2215     new_unused_property_fields = kFieldsAdded - 1;
   2216     MaybeObject* maybe_new_properties =
   2217         properties()->CopySize(properties()->length() + kFieldsAdded);
   2218     if (!maybe_new_properties->To(&new_properties)) return maybe_new_properties;
   2219   }
   2220 
   2221   Heap* heap = GetHeap();
   2222   Object* storage;
   2223   MaybeObject* maybe_storage =
   2224       new_value->AllocateNewStorageFor(heap, representation);
   2225   if (!maybe_storage->To(&storage)) return maybe_storage;
   2226 
   2227   // Update pointers to commit changes.
   2228   // Object points to the new map.
   2229   new_map->set_unused_property_fields(new_unused_property_fields);
   2230   set_map(new_map);
   2231   if (new_properties != NULL) {
   2232     set_properties(new_properties);
   2233   }
   2234   FastPropertyAtPut(index, new_value);
   2235   return new_value;
   2236 }
   2237 
   2238 
   2239 const char* Representation::Mnemonic() const {
   2240   switch (kind_) {
   2241     case kNone: return "v";
   2242     case kTagged: return "t";
   2243     case kSmi: return "s";
   2244     case kDouble: return "d";
   2245     case kInteger32: return "i";
   2246     case kHeapObject: return "h";
   2247     case kExternal: return "x";
   2248     default:
   2249       UNREACHABLE();
   2250       return NULL;
   2251   }
   2252 }
   2253 
   2254 
   2255 enum RightTrimMode { FROM_GC, FROM_MUTATOR };
   2256 
   2257 
   2258 static void ZapEndOfFixedArray(Address new_end, int to_trim) {
   2259   // If we are doing a big trim in old space then we zap the space.
   2260   Object** zap = reinterpret_cast<Object**>(new_end);
   2261   zap++;  // Header of filler must be at least one word so skip that.
   2262   for (int i = 1; i < to_trim; i++) {
   2263     *zap++ = Smi::FromInt(0);
   2264   }
   2265 }
   2266 
   2267 
   2268 template<RightTrimMode trim_mode>
   2269 static void RightTrimFixedArray(Heap* heap, FixedArray* elms, int to_trim) {
   2270   ASSERT(elms->map() != HEAP->fixed_cow_array_map());
   2271   // For now this trick is only applied to fixed arrays in new and paged space.
   2272   ASSERT(!HEAP->lo_space()->Contains(elms));
   2273 
   2274   const int len = elms->length();
   2275 
   2276   ASSERT(to_trim < len);
   2277 
   2278   Address new_end = elms->address() + FixedArray::SizeFor(len - to_trim);
   2279 
   2280   if (trim_mode != FROM_GC || Heap::ShouldZapGarbage()) {
   2281     ZapEndOfFixedArray(new_end, to_trim);
   2282   }
   2283 
   2284   int size_delta = to_trim * kPointerSize;
   2285 
   2286   // Technically in new space this write might be omitted (except for
   2287   // debug mode which iterates through the heap), but to play safer
   2288   // we still do it.
   2289   heap->CreateFillerObjectAt(new_end, size_delta);
   2290 
   2291   elms->set_length(len - to_trim);
   2292 
   2293   // Maintain marking consistency for IncrementalMarking.
   2294   if (Marking::IsBlack(Marking::MarkBitFrom(elms))) {
   2295     if (trim_mode == FROM_GC) {
   2296       MemoryChunk::IncrementLiveBytesFromGC(elms->address(), -size_delta);
   2297     } else {
   2298       MemoryChunk::IncrementLiveBytesFromMutator(elms->address(), -size_delta);
   2299     }
   2300   }
   2301 }
   2302 
   2303 
   2304 bool Map::InstancesNeedRewriting(Map* target,
   2305                                  int target_number_of_fields,
   2306                                  int target_inobject,
   2307                                  int target_unused) {
   2308   // If fields were added (or removed), rewrite the instance.
   2309   int number_of_fields = NumberOfFields();
   2310   ASSERT(target_number_of_fields >= number_of_fields);
   2311   if (target_number_of_fields != number_of_fields) return true;
   2312 
   2313   if (FLAG_track_double_fields) {
   2314     // If smi descriptors were replaced by double descriptors, rewrite.
   2315     DescriptorArray* old_desc = instance_descriptors();
   2316     DescriptorArray* new_desc = target->instance_descriptors();
   2317     int limit = NumberOfOwnDescriptors();
   2318     for (int i = 0; i < limit; i++) {
   2319       if (new_desc->GetDetails(i).representation().IsDouble() &&
   2320           !old_desc->GetDetails(i).representation().IsDouble()) {
   2321         return true;
   2322       }
   2323     }
   2324   }
   2325 
   2326   // If no fields were added, and no inobject properties were removed, setting
   2327   // the map is sufficient.
   2328   if (target_inobject == inobject_properties()) return false;
   2329   // In-object slack tracking may have reduced the object size of the new map.
   2330   // In that case, succeed if all existing fields were inobject, and they still
   2331   // fit within the new inobject size.
   2332   ASSERT(target_inobject < inobject_properties());
   2333   if (target_number_of_fields <= target_inobject) {
   2334     ASSERT(target_number_of_fields + target_unused == target_inobject);
   2335     return false;
   2336   }
   2337   // Otherwise, properties will need to be moved to the backing store.
   2338   return true;
   2339 }
   2340 
   2341 
   2342 // To migrate an instance to a map:
   2343 // - First check whether the instance needs to be rewritten. If not, simply
   2344 //   change the map.
   2345 // - Otherwise, allocate a fixed array large enough to hold all fields, in
   2346 //   addition to unused space.
   2347 // - Copy all existing properties in, in the following order: backing store
   2348 //   properties, unused fields, inobject properties.
   2349 // - If all allocation succeeded, commit the state atomically:
   2350 //   * Copy inobject properties from the backing store back into the object.
   2351 //   * Trim the difference in instance size of the object. This also cleanly
   2352 //     frees inobject properties that moved to the backing store.
   2353 //   * If there are properties left in the backing store, trim of the space used
   2354 //     to temporarily store the inobject properties.
   2355 //   * If there are properties left in the backing store, install the backing
   2356 //     store.
   2357 MaybeObject* JSObject::MigrateToMap(Map* new_map) {
   2358   Heap* heap = GetHeap();
   2359   Map* old_map = map();
   2360   int number_of_fields = new_map->NumberOfFields();
   2361   int inobject = new_map->inobject_properties();
   2362   int unused = new_map->unused_property_fields();
   2363 
   2364   // Nothing to do if no functions were converted to fields.
   2365   if (!old_map->InstancesNeedRewriting(
   2366           new_map, number_of_fields, inobject, unused)) {
   2367     set_map(new_map);
   2368     return this;
   2369   }
   2370 
   2371   int total_size = number_of_fields + unused;
   2372   int external = total_size - inobject;
   2373   FixedArray* array;
   2374   MaybeObject* maybe_array = heap->AllocateFixedArray(total_size);
   2375   if (!maybe_array->To(&array)) return maybe_array;
   2376 
   2377   DescriptorArray* old_descriptors = old_map->instance_descriptors();
   2378   DescriptorArray* new_descriptors = new_map->instance_descriptors();
   2379   int descriptors = new_map->NumberOfOwnDescriptors();
   2380 
   2381   for (int i = 0; i < descriptors; i++) {
   2382     PropertyDetails details = new_descriptors->GetDetails(i);
   2383     if (details.type() != FIELD) continue;
   2384     PropertyDetails old_details = old_descriptors->GetDetails(i);
   2385     ASSERT(old_details.type() == CONSTANT ||
   2386            old_details.type() == FIELD);
   2387     Object* value = old_details.type() == CONSTANT
   2388         ? old_descriptors->GetValue(i)
   2389         : RawFastPropertyAt(old_descriptors->GetFieldIndex(i));
   2390     if (FLAG_track_double_fields &&
   2391         !old_details.representation().IsDouble() &&
   2392         details.representation().IsDouble()) {
   2393       if (old_details.representation().IsNone()) value = Smi::FromInt(0);
   2394       // Objects must be allocated in the old object space, since the
   2395       // overall number of HeapNumbers needed for the conversion might
   2396       // exceed the capacity of new space, and we would fail repeatedly
   2397       // trying to migrate the instance.
   2398       MaybeObject* maybe_storage =
   2399           value->AllocateNewStorageFor(heap, details.representation(), TENURED);
   2400       if (!maybe_storage->To(&value)) return maybe_storage;
   2401     }
   2402     ASSERT(!(FLAG_track_double_fields &&
   2403              details.representation().IsDouble() &&
   2404              value->IsSmi()));
   2405     int target_index = new_descriptors->GetFieldIndex(i) - inobject;
   2406     if (target_index < 0) target_index += total_size;
   2407     array->set(target_index, value);
   2408   }
   2409 
   2410   // From here on we cannot fail anymore.
   2411 
   2412   // Copy (real) inobject properties. If necessary, stop at number_of_fields to
   2413   // avoid overwriting |one_pointer_filler_map|.
   2414   int limit = Min(inobject, number_of_fields);
   2415   for (int i = 0; i < limit; i++) {
   2416     FastPropertyAtPut(i, array->get(external + i));
   2417   }
   2418 
   2419   // Create filler object past the new instance size.
   2420   int new_instance_size = new_map->instance_size();
   2421   int instance_size_delta = old_map->instance_size() - new_instance_size;
   2422   ASSERT(instance_size_delta >= 0);
   2423   Address address = this->address() + new_instance_size;
   2424   heap->CreateFillerObjectAt(address, instance_size_delta);
   2425 
   2426   // If there are properties in the new backing store, trim it to the correct
   2427   // size and install the backing store into the object.
   2428   if (external > 0) {
   2429     RightTrimFixedArray<FROM_MUTATOR>(heap, array, inobject);
   2430     set_properties(array);
   2431   }
   2432 
   2433   set_map(new_map);
   2434 
   2435   return this;
   2436 }
   2437 
   2438 
   2439 MaybeObject* JSObject::GeneralizeFieldRepresentation(
   2440     int modify_index,
   2441     Representation new_representation) {
   2442   Map* new_map;
   2443   MaybeObject* maybe_new_map =
   2444       map()->GeneralizeRepresentation(modify_index, new_representation);
   2445   if (!maybe_new_map->To(&new_map)) return maybe_new_map;
   2446   if (map() == new_map) return this;
   2447 
   2448   return MigrateToMap(new_map);
   2449 }
   2450 
   2451 
   2452 int Map::NumberOfFields() {
   2453   DescriptorArray* descriptors = instance_descriptors();
   2454   int result = 0;
   2455   for (int i = 0; i < NumberOfOwnDescriptors(); i++) {
   2456     if (descriptors->GetDetails(i).type() == FIELD) result++;
   2457   }
   2458   return result;
   2459 }
   2460 
   2461 
   2462 MaybeObject* Map::CopyGeneralizeAllRepresentations() {
   2463   Map* new_map;
   2464   MaybeObject* maybe_map = this->Copy();
   2465   if (!maybe_map->To(&new_map)) return maybe_map;
   2466 
   2467   new_map->instance_descriptors()->InitializeRepresentations(
   2468       Representation::Tagged());
   2469   if (FLAG_trace_generalization) {
   2470     PrintF("failed generalization %p -> %p\n",
   2471            static_cast<void*>(this), static_cast<void*>(new_map));
   2472   }
   2473   return new_map;
   2474 }
   2475 
   2476 
   2477 void Map::DeprecateTransitionTree() {
   2478   if (!FLAG_track_fields) return;
   2479   if (is_deprecated()) return;
   2480   if (HasTransitionArray()) {
   2481     TransitionArray* transitions = this->transitions();
   2482     for (int i = 0; i < transitions->number_of_transitions(); i++) {
   2483       transitions->GetTarget(i)->DeprecateTransitionTree();
   2484     }
   2485   }
   2486   deprecate();
   2487   dependent_code()->DeoptimizeDependentCodeGroup(
   2488       GetIsolate(), DependentCode::kTransitionGroup);
   2489   NotifyLeafMapLayoutChange();
   2490 }
   2491 
   2492 
   2493 // Invalidates a transition target at |key|, and installs |new_descriptors| over
   2494 // the current instance_descriptors to ensure proper sharing of descriptor
   2495 // arrays.
   2496 void Map::DeprecateTarget(Name* key, DescriptorArray* new_descriptors) {
   2497   if (HasTransitionArray()) {
   2498     TransitionArray* transitions = this->transitions();
   2499     int transition = transitions->Search(key);
   2500     if (transition != TransitionArray::kNotFound) {
   2501       transitions->GetTarget(transition)->DeprecateTransitionTree();
   2502     }
   2503   }
   2504 
   2505   // Don't overwrite the empty descriptor array.
   2506   if (NumberOfOwnDescriptors() == 0) return;
   2507 
   2508   DescriptorArray* to_replace = instance_descriptors();
   2509   Map* current = this;
   2510   while (current->instance_descriptors() == to_replace) {
   2511     current->SetEnumLength(Map::kInvalidEnumCache);
   2512     current->set_instance_descriptors(new_descriptors);
   2513     Object* next = current->GetBackPointer();
   2514     if (next->IsUndefined()) break;
   2515     current = Map::cast(next);
   2516   }
   2517 
   2518   set_owns_descriptors(false);
   2519 }
   2520 
   2521 
   2522 Map* Map::FindRootMap() {
   2523   Map* result = this;
   2524   while (true) {
   2525     Object* back = result->GetBackPointer();
   2526     if (back->IsUndefined()) return result;
   2527     result = Map::cast(back);
   2528   }
   2529 }
   2530 
   2531 
   2532 // Returns NULL if the updated map is incompatible.
   2533 Map* Map::FindUpdatedMap(int verbatim,
   2534                          int length,
   2535                          DescriptorArray* descriptors) {
   2536   // This can only be called on roots of transition trees.
   2537   ASSERT(GetBackPointer()->IsUndefined());
   2538 
   2539   Map* current = this;
   2540 
   2541   for (int i = verbatim; i < length; i++) {
   2542     if (!current->HasTransitionArray()) break;
   2543     Name* name = descriptors->GetKey(i);
   2544     TransitionArray* transitions = current->transitions();
   2545     int transition = transitions->Search(name);
   2546     if (transition == TransitionArray::kNotFound) break;
   2547     current = transitions->GetTarget(transition);
   2548     PropertyDetails details = descriptors->GetDetails(i);
   2549     PropertyDetails target_details =
   2550         current->instance_descriptors()->GetDetails(i);
   2551     if (details.attributes() != target_details.attributes()) return NULL;
   2552     if (details.type() == CALLBACKS) {
   2553       if (target_details.type() != CALLBACKS) return NULL;
   2554       if (descriptors->GetValue(i) !=
   2555               current->instance_descriptors()->GetValue(i)) {
   2556         return NULL;
   2557       }
   2558     }
   2559   }
   2560 
   2561   return current;
   2562 }
   2563 
   2564 
   2565 Map* Map::FindLastMatchMap(int verbatim,
   2566                            int length,
   2567                            DescriptorArray* descriptors) {
   2568   // This can only be called on roots of transition trees.
   2569   ASSERT(GetBackPointer()->IsUndefined());
   2570 
   2571   Map* current = this;
   2572 
   2573   for (int i = verbatim; i < length; i++) {
   2574     if (!current->HasTransitionArray()) break;
   2575     Name* name = descriptors->GetKey(i);
   2576     TransitionArray* transitions = current->transitions();
   2577     int transition = transitions->Search(name);
   2578     if (transition == TransitionArray::kNotFound) break;
   2579 
   2580     Map* next = transitions->GetTarget(transition);
   2581     DescriptorArray* next_descriptors = next->instance_descriptors();
   2582 
   2583     if (next_descriptors->GetValue(i) != descriptors->GetValue(i)) break;
   2584 
   2585     PropertyDetails details = descriptors->GetDetails(i);
   2586     PropertyDetails next_details = next_descriptors->GetDetails(i);
   2587     if (details.type() != next_details.type()) break;
   2588     if (details.attributes() != next_details.attributes()) break;
   2589     if (!details.representation().Equals(next_details.representation())) break;
   2590 
   2591     current = next;
   2592   }
   2593   return current;
   2594 }
   2595 
   2596 
   2597 // Generalize the representation of the descriptor at |modify_index|.
   2598 // This method rewrites the transition tree to reflect the new change. To avoid
   2599 // high degrees over polymorphism, and to stabilize quickly, on every rewrite
   2600 // the new type is deduced by merging the current type with any potential new
   2601 // (partial) version of the type in the transition tree.
   2602 // To do this, on each rewrite:
   2603 // - Search the root of the transition tree using FindRootMap.
   2604 // - Find |updated|, the newest matching version of this map using
   2605 //   FindUpdatedMap. This uses the keys in the own map's descriptor array to
   2606 //   walk the transition tree.
   2607 // - Merge/generalize the descriptor array of the current map and |updated|.
   2608 // - Generalize the |modify_index| descriptor using |new_representation|.
   2609 // - Walk the tree again starting from the root towards |updated|. Stop at
   2610 //   |split_map|, the first map who's descriptor array does not match the merged
   2611 //   descriptor array.
   2612 // - If |updated| == |split_map|, |updated| is in the expected state. Return it.
   2613 // - Otherwise, invalidate the outdated transition target from |updated|, and
   2614 //   replace its transition tree with a new branch for the updated descriptors.
   2615 MaybeObject* Map::GeneralizeRepresentation(int modify_index,
   2616                                            Representation new_representation) {
   2617   Map* old_map = this;
   2618   DescriptorArray* old_descriptors = old_map->instance_descriptors();
   2619   Representation old_representation =
   2620       old_descriptors->GetDetails(modify_index).representation();
   2621 
   2622   // It's fine to transition from None to anything but double without any
   2623   // modification to the object, because the default uninitialized value for
   2624   // representation None can be overwritten by both smi and tagged values.
   2625   // Doubles, however, would require a box allocation.
   2626   if (old_representation.IsNone() &&
   2627       !new_representation.IsNone() &&
   2628       !new_representation.IsDouble()) {
   2629     if (FLAG_trace_generalization) {
   2630       PrintF("initializing representation %i: %p -> %s\n",
   2631              modify_index,
   2632              static_cast<void*>(this),
   2633              new_representation.Mnemonic());
   2634     }
   2635     old_descriptors->SetRepresentation(modify_index, new_representation);
   2636     return old_map;
   2637   }
   2638 
   2639   int descriptors = old_map->NumberOfOwnDescriptors();
   2640   Map* root_map = old_map->FindRootMap();
   2641 
   2642   // Check the state of the root map.
   2643   if (!old_map->EquivalentToForTransition(root_map)) {
   2644     return CopyGeneralizeAllRepresentations();
   2645   }
   2646 
   2647   int verbatim = root_map->NumberOfOwnDescriptors();
   2648 
   2649   Map* updated = root_map->FindUpdatedMap(
   2650       verbatim, descriptors, old_descriptors);
   2651   if (updated == NULL) return CopyGeneralizeAllRepresentations();
   2652 
   2653   DescriptorArray* updated_descriptors = updated->instance_descriptors();
   2654 
   2655   int valid = updated->NumberOfOwnDescriptors();
   2656   if (updated_descriptors->IsMoreGeneralThan(
   2657           verbatim, valid, descriptors, old_descriptors)) {
   2658     Representation updated_representation =
   2659         updated_descriptors->GetDetails(modify_index).representation();
   2660     if (new_representation.fits_into(updated_representation)) {
   2661       if (FLAG_trace_generalization &&
   2662           !(modify_index == 0 && new_representation.IsNone())) {
   2663         PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
   2664         PrintF("migrating to existing map %p(%s) -> %p(%s)\n",
   2665                static_cast<void*>(this),
   2666                old_details.representation().Mnemonic(),
   2667                static_cast<void*>(updated),
   2668                updated_representation.Mnemonic());
   2669       }
   2670       return updated;
   2671     }
   2672   }
   2673 
   2674   DescriptorArray* new_descriptors;
   2675   MaybeObject* maybe_descriptors = updated_descriptors->Merge(
   2676       verbatim, valid, descriptors, old_descriptors);
   2677   if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
   2678 
   2679   old_representation =
   2680       new_descriptors->GetDetails(modify_index).representation();
   2681   Representation updated_representation =
   2682       new_representation.generalize(old_representation);
   2683   if (!updated_representation.Equals(old_representation)) {
   2684     new_descriptors->SetRepresentation(modify_index, updated_representation);
   2685   }
   2686 
   2687   Map* split_map = root_map->FindLastMatchMap(
   2688       verbatim, descriptors, new_descriptors);
   2689 
   2690   int split_descriptors = split_map->NumberOfOwnDescriptors();
   2691   // This is shadowed by |updated_descriptors| being more general than
   2692   // |old_descriptors|.
   2693   ASSERT(descriptors != split_descriptors);
   2694 
   2695   int descriptor = split_descriptors;
   2696   split_map->DeprecateTarget(
   2697       old_descriptors->GetKey(descriptor), new_descriptors);
   2698 
   2699   if (FLAG_trace_generalization &&
   2700       !(modify_index == 0 && new_representation.IsNone())) {
   2701     PrintF("migrating to new map %i: %p(%s) -> %p(%s) (%i steps)\n",
   2702            modify_index,
   2703            static_cast<void*>(this),
   2704            old_representation.Mnemonic(),
   2705            static_cast<void*>(new_descriptors),
   2706            updated_representation.Mnemonic(),
   2707            descriptors - descriptor);
   2708   }
   2709 
   2710   Map* new_map = split_map;
   2711   // Add missing transitions.
   2712   for (; descriptor < descriptors; descriptor++) {
   2713     MaybeObject* maybe_map = new_map->CopyInstallDescriptors(
   2714         descriptor, new_descriptors);
   2715     if (!maybe_map->To(&new_map)) {
   2716       // Create a handle for the last created map to ensure it stays alive
   2717       // during GC. Its descriptor array is too large, but it will be
   2718       // overwritten during retry anyway.
   2719       Handle<Map>(new_map);
   2720       return maybe_map;
   2721     }
   2722     new_map->set_migration_target(true);
   2723   }
   2724 
   2725   new_map->set_owns_descriptors(true);
   2726   return new_map;
   2727 }
   2728 
   2729 
   2730 Map* Map::CurrentMapForDeprecated() {
   2731   DisallowHeapAllocation no_allocation;
   2732   if (!is_deprecated()) return this;
   2733 
   2734   DescriptorArray* old_descriptors = instance_descriptors();
   2735 
   2736   int descriptors = NumberOfOwnDescriptors();
   2737   Map* root_map = FindRootMap();
   2738 
   2739   // Check the state of the root map.
   2740   if (!EquivalentToForTransition(root_map)) return NULL;
   2741   int verbatim = root_map->NumberOfOwnDescriptors();
   2742 
   2743   Map* updated = root_map->FindUpdatedMap(
   2744       verbatim, descriptors, old_descriptors);
   2745   if (updated == NULL) return NULL;
   2746 
   2747   DescriptorArray* updated_descriptors = updated->instance_descriptors();
   2748   int valid = updated->NumberOfOwnDescriptors();
   2749   if (!updated_descriptors->IsMoreGeneralThan(
   2750           verbatim, valid, descriptors, old_descriptors)) {
   2751     return NULL;
   2752   }
   2753 
   2754   return updated;
   2755 }
   2756 
   2757 
   2758 MaybeObject* JSObject::SetPropertyWithInterceptor(
   2759     Name* name,
   2760     Object* value,
   2761     PropertyAttributes attributes,
   2762     StrictModeFlag strict_mode) {
   2763   // TODO(rossberg): Support symbols in the API.
   2764   if (name->IsSymbol()) return value;
   2765   Isolate* isolate = GetIsolate();
   2766   HandleScope scope(isolate);
   2767   Handle<JSObject> this_handle(this);
   2768   Handle<String> name_handle(String::cast(name));
   2769   Handle<Object> value_handle(value, isolate);
   2770   Handle<InterceptorInfo> interceptor(GetNamedInterceptor());
   2771   if (!interceptor->setter()->IsUndefined()) {
   2772     LOG(isolate, ApiNamedPropertyAccess("interceptor-named-set", this, name));
   2773     PropertyCallbackArguments args(isolate, interceptor->data(), this, this);
   2774     v8::NamedPropertySetter setter =
   2775         v8::ToCData<v8::NamedPropertySetter>(interceptor->setter());
   2776     Handle<Object> value_unhole(value->IsTheHole() ?
   2777                                 isolate->heap()->undefined_value() :
   2778                                 value,
   2779                                 isolate);
   2780     v8::Handle<v8::Value> result = args.Call(setter,
   2781                                              v8::Utils::ToLocal(name_handle),
   2782                                              v8::Utils::ToLocal(value_unhole));
   2783     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   2784     if (!result.IsEmpty()) return *value_handle;
   2785   }
   2786   MaybeObject* raw_result =
   2787       this_handle->SetPropertyPostInterceptor(*name_handle,
   2788                                               *value_handle,
   2789                                               attributes,
   2790                                               strict_mode,
   2791                                               PERFORM_EXTENSIBILITY_CHECK);
   2792   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   2793   return raw_result;
   2794 }
   2795 
   2796 
   2797 Handle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object,
   2798                                        Handle<Name> key,
   2799                                        Handle<Object> value,
   2800                                        PropertyAttributes attributes,
   2801                                        StrictModeFlag strict_mode) {
   2802   CALL_HEAP_FUNCTION(object->GetIsolate(),
   2803                      object->SetProperty(*key, *value, attributes, strict_mode),
   2804                      Object);
   2805 }
   2806 
   2807 
   2808 MaybeObject* JSReceiver::SetPropertyOrFail(
   2809     Handle<JSReceiver> object,
   2810     Handle<Name> key,
   2811     Handle<Object> value,
   2812     PropertyAttributes attributes,
   2813     StrictModeFlag strict_mode,
   2814     JSReceiver::StoreFromKeyed store_mode) {
   2815   CALL_HEAP_FUNCTION_PASS_EXCEPTION(
   2816       object->GetIsolate(),
   2817       object->SetProperty(*key, *value, attributes, strict_mode, store_mode));
   2818 }
   2819 
   2820 
   2821 MaybeObject* JSReceiver::SetProperty(Name* name,
   2822                                      Object* value,
   2823                                      PropertyAttributes attributes,
   2824                                      StrictModeFlag strict_mode,
   2825                                      JSReceiver::StoreFromKeyed store_mode) {
   2826   LookupResult result(GetIsolate());
   2827   LocalLookup(name, &result, true);
   2828   if (!result.IsFound()) {
   2829     map()->LookupTransition(JSObject::cast(this), name, &result);
   2830   }
   2831   return SetProperty(&result, name, value, attributes, strict_mode, store_mode);
   2832 }
   2833 
   2834 
   2835 MaybeObject* JSObject::SetPropertyWithCallback(Object* structure,
   2836                                                Name* name,
   2837                                                Object* value,
   2838                                                JSObject* holder,
   2839                                                StrictModeFlag strict_mode) {
   2840   Isolate* isolate = GetIsolate();
   2841   HandleScope scope(isolate);
   2842 
   2843   // We should never get here to initialize a const with the hole
   2844   // value since a const declaration would conflict with the setter.
   2845   ASSERT(!value->IsTheHole());
   2846   Handle<Object> value_handle(value, isolate);
   2847 
   2848   // To accommodate both the old and the new api we switch on the
   2849   // data structure used to store the callbacks.  Eventually foreign
   2850   // callbacks should be phased out.
   2851   if (structure->IsForeign()) {
   2852     AccessorDescriptor* callback =
   2853         reinterpret_cast<AccessorDescriptor*>(
   2854             Foreign::cast(structure)->foreign_address());
   2855     MaybeObject* obj = (callback->setter)(this,  value, callback->data);
   2856     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   2857     if (obj->IsFailure()) return obj;
   2858     return *value_handle;
   2859   }
   2860 
   2861   if (structure->IsExecutableAccessorInfo()) {
   2862     // api style callbacks
   2863     ExecutableAccessorInfo* data = ExecutableAccessorInfo::cast(structure);
   2864     if (!data->IsCompatibleReceiver(this)) {
   2865       Handle<Object> name_handle(name, isolate);
   2866       Handle<Object> receiver_handle(this, isolate);
   2867       Handle<Object> args[2] = { name_handle, receiver_handle };
   2868       Handle<Object> error =
   2869           isolate->factory()->NewTypeError("incompatible_method_receiver",
   2870                                            HandleVector(args,
   2871                                                         ARRAY_SIZE(args)));
   2872       return isolate->Throw(*error);
   2873     }
   2874     // TODO(rossberg): Support symbols in the API.
   2875     if (name->IsSymbol()) return value;
   2876     Object* call_obj = data->setter();
   2877     v8::AccessorSetter call_fun = v8::ToCData<v8::AccessorSetter>(call_obj);
   2878     if (call_fun == NULL) return value;
   2879     Handle<String> key(String::cast(name));
   2880     LOG(isolate, ApiNamedPropertyAccess("store", this, name));
   2881     PropertyCallbackArguments args(
   2882         isolate, data->data(), this, JSObject::cast(holder));
   2883     args.Call(call_fun,
   2884               v8::Utils::ToLocal(key),
   2885               v8::Utils::ToLocal(value_handle));
   2886     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   2887     return *value_handle;
   2888   }
   2889 
   2890   if (structure->IsAccessorPair()) {
   2891     Object* setter = AccessorPair::cast(structure)->setter();
   2892     if (setter->IsSpecFunction()) {
   2893       // TODO(rossberg): nicer would be to cast to some JSCallable here...
   2894      return SetPropertyWithDefinedSetter(JSReceiver::cast(setter), value);
   2895     } else {
   2896       if (strict_mode == kNonStrictMode) {
   2897         return value;
   2898       }
   2899       Handle<Name> key(name);
   2900       Handle<Object> holder_handle(holder, isolate);
   2901       Handle<Object> args[2] = { key, holder_handle };
   2902       return isolate->Throw(
   2903           *isolate->factory()->NewTypeError("no_setter_in_callback",
   2904                                             HandleVector(args, 2)));
   2905     }
   2906   }
   2907 
   2908   // TODO(dcarney): Handle correctly.
   2909   if (structure->IsDeclaredAccessorInfo()) {
   2910     return value;
   2911   }
   2912 
   2913   UNREACHABLE();
   2914   return NULL;
   2915 }
   2916 
   2917 
   2918 MaybeObject* JSReceiver::SetPropertyWithDefinedSetter(JSReceiver* setter,
   2919                                                       Object* value) {
   2920   Isolate* isolate = GetIsolate();
   2921   Handle<Object> value_handle(value, isolate);
   2922   Handle<JSReceiver> fun(setter, isolate);
   2923   Handle<JSReceiver> self(this, isolate);
   2924 #ifdef ENABLE_DEBUGGER_SUPPORT
   2925   Debug* debug = isolate->debug();
   2926   // Handle stepping into a setter if step into is active.
   2927   // TODO(rossberg): should this apply to getters that are function proxies?
   2928   if (debug->StepInActive() && fun->IsJSFunction()) {
   2929     debug->HandleStepIn(
   2930         Handle<JSFunction>::cast(fun), Handle<Object>::null(), 0, false);
   2931   }
   2932 #endif
   2933   bool has_pending_exception;
   2934   Handle<Object> argv[] = { value_handle };
   2935   Execution::Call(fun, self, ARRAY_SIZE(argv), argv, &has_pending_exception);
   2936   // Check for pending exception and return the result.
   2937   if (has_pending_exception) return Failure::Exception();
   2938   return *value_handle;
   2939 }
   2940 
   2941 
   2942 MaybeObject* JSObject::SetElementWithCallbackSetterInPrototypes(
   2943     uint32_t index,
   2944     Object* value,
   2945     bool* found,
   2946     StrictModeFlag strict_mode) {
   2947   Heap* heap = GetHeap();
   2948   for (Object* pt = GetPrototype();
   2949        pt != heap->null_value();
   2950        pt = pt->GetPrototype(GetIsolate())) {
   2951     if (pt->IsJSProxy()) {
   2952       String* name;
   2953       MaybeObject* maybe = heap->Uint32ToString(index);
   2954       if (!maybe->To<String>(&name)) {
   2955         *found = true;  // Force abort
   2956         return maybe;
   2957       }
   2958       return JSProxy::cast(pt)->SetPropertyViaPrototypesWithHandler(
   2959           this, name, value, NONE, strict_mode, found);
   2960     }
   2961     if (!JSObject::cast(pt)->HasDictionaryElements()) {
   2962       continue;
   2963     }
   2964     SeededNumberDictionary* dictionary =
   2965         JSObject::cast(pt)->element_dictionary();
   2966     int entry = dictionary->FindEntry(index);
   2967     if (entry != SeededNumberDictionary::kNotFound) {
   2968       PropertyDetails details = dictionary->DetailsAt(entry);
   2969       if (details.type() == CALLBACKS) {
   2970         *found = true;
   2971         return SetElementWithCallback(dictionary->ValueAt(entry),
   2972                                       index,
   2973                                       value,
   2974                                       JSObject::cast(pt),
   2975                                       strict_mode);
   2976       }
   2977     }
   2978   }
   2979   *found = false;
   2980   return heap->the_hole_value();
   2981 }
   2982 
   2983 MaybeObject* JSObject::SetPropertyViaPrototypes(
   2984     Name* name,
   2985     Object* value,
   2986     PropertyAttributes attributes,
   2987     StrictModeFlag strict_mode,
   2988     bool* done) {
   2989   Heap* heap = GetHeap();
   2990   Isolate* isolate = heap->isolate();
   2991 
   2992   *done = false;
   2993   // We could not find a local property so let's check whether there is an
   2994   // accessor that wants to handle the property, or whether the property is
   2995   // read-only on the prototype chain.
   2996   LookupResult result(isolate);
   2997   LookupRealNamedPropertyInPrototypes(name, &result);
   2998   if (result.IsFound()) {
   2999     switch (result.type()) {
   3000       case NORMAL:
   3001       case FIELD:
   3002       case CONSTANT:
   3003         *done = result.IsReadOnly();
   3004         break;
   3005       case INTERCEPTOR: {
   3006         PropertyAttributes attr =
   3007             result.holder()->GetPropertyAttributeWithInterceptor(
   3008                 this, name, true);
   3009         *done = !!(attr & READ_ONLY);
   3010         break;
   3011       }
   3012       case CALLBACKS: {
   3013         if (!FLAG_es5_readonly && result.IsReadOnly()) break;
   3014         *done = true;
   3015         return SetPropertyWithCallback(result.GetCallbackObject(),
   3016             name, value, result.holder(), strict_mode);
   3017       }
   3018       case HANDLER: {
   3019         return result.proxy()->SetPropertyViaPrototypesWithHandler(
   3020             this, name, value, attributes, strict_mode, done);
   3021       }
   3022       case TRANSITION:
   3023       case NONEXISTENT:
   3024         UNREACHABLE();
   3025         break;
   3026     }
   3027   }
   3028 
   3029   // If we get here with *done true, we have encountered a read-only property.
   3030   if (!FLAG_es5_readonly) *done = false;
   3031   if (*done) {
   3032     if (strict_mode == kNonStrictMode) return value;
   3033     Handle<Object> args[] = { Handle<Object>(name, isolate),
   3034                               Handle<Object>(this, isolate)};
   3035     return isolate->Throw(*isolate->factory()->NewTypeError(
   3036       "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args))));
   3037   }
   3038   return heap->the_hole_value();
   3039 }
   3040 
   3041 
   3042 void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) {
   3043   Handle<DescriptorArray> descriptors(map->instance_descriptors());
   3044   if (slack <= descriptors->NumberOfSlackDescriptors()) return;
   3045   int number_of_descriptors = descriptors->number_of_descriptors();
   3046   Isolate* isolate = map->GetIsolate();
   3047   Handle<DescriptorArray> new_descriptors =
   3048       isolate->factory()->NewDescriptorArray(number_of_descriptors, slack);
   3049   DescriptorArray::WhitenessWitness witness(*new_descriptors);
   3050 
   3051   for (int i = 0; i < number_of_descriptors; ++i) {
   3052     new_descriptors->CopyFrom(i, *descriptors, i, witness);
   3053   }
   3054 
   3055   map->set_instance_descriptors(*new_descriptors);
   3056 }
   3057 
   3058 
   3059 void Map::AppendCallbackDescriptors(Handle<Map> map,
   3060                                     Handle<Object> descriptors) {
   3061   Isolate* isolate = map->GetIsolate();
   3062   Handle<DescriptorArray> array(map->instance_descriptors());
   3063   NeanderArray callbacks(descriptors);
   3064   int nof_callbacks = callbacks.length();
   3065 
   3066   ASSERT(array->NumberOfSlackDescriptors() >= nof_callbacks);
   3067 
   3068   // Ensure the keys are unique names before writing them into the
   3069   // instance descriptor. Since it may cause a GC, it has to be done before we
   3070   // temporarily put the heap in an invalid state while appending descriptors.
   3071   for (int i = 0; i < nof_callbacks; ++i) {
   3072     Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks.get(i)));
   3073     if (!entry->name()->IsUniqueName()) {
   3074       Handle<String> key =
   3075           isolate->factory()->InternalizedStringFromString(
   3076               Handle<String>(String::cast(entry->name())));
   3077       entry->set_name(*key);
   3078     }
   3079   }
   3080 
   3081   int nof = map->NumberOfOwnDescriptors();
   3082 
   3083   // Fill in new callback descriptors.  Process the callbacks from
   3084   // back to front so that the last callback with a given name takes
   3085   // precedence over previously added callbacks with that name.
   3086   for (int i = nof_callbacks - 1; i >= 0; i--) {
   3087     AccessorInfo* entry = AccessorInfo::cast(callbacks.get(i));
   3088     Name* key = Name::cast(entry->name());
   3089     // Check if a descriptor with this name already exists before writing.
   3090     if (array->Search(key, nof) == DescriptorArray::kNotFound) {
   3091       CallbacksDescriptor desc(key, entry, entry->property_attributes());
   3092       array->Append(&desc);
   3093       nof += 1;
   3094     }
   3095   }
   3096 
   3097   map->SetNumberOfOwnDescriptors(nof);
   3098 }
   3099 
   3100 
   3101 static bool ContainsMap(MapHandleList* maps, Handle<Map> map) {
   3102   ASSERT(!map.is_null());
   3103   for (int i = 0; i < maps->length(); ++i) {
   3104     if (!maps->at(i).is_null() && maps->at(i).is_identical_to(map)) return true;
   3105   }
   3106   return false;
   3107 }
   3108 
   3109 
   3110 template <class T>
   3111 static Handle<T> MaybeNull(T* p) {
   3112   if (p == NULL) return Handle<T>::null();
   3113   return Handle<T>(p);
   3114 }
   3115 
   3116 
   3117 Handle<Map> Map::FindTransitionedMap(MapHandleList* candidates) {
   3118   ElementsKind kind = elements_kind();
   3119   Handle<Map> transitioned_map = Handle<Map>::null();
   3120   Handle<Map> current_map(this);
   3121   bool packed = IsFastPackedElementsKind(kind);
   3122   if (IsTransitionableFastElementsKind(kind)) {
   3123     while (CanTransitionToMoreGeneralFastElementsKind(kind, false)) {
   3124       kind = GetNextMoreGeneralFastElementsKind(kind, false);
   3125       Handle<Map> maybe_transitioned_map =
   3126           MaybeNull(current_map->LookupElementsTransitionMap(kind));
   3127       if (maybe_transitioned_map.is_null()) break;
   3128       if (ContainsMap(candidates, maybe_transitioned_map) &&
   3129           (packed || !IsFastPackedElementsKind(kind))) {
   3130         transitioned_map = maybe_transitioned_map;
   3131         if (!IsFastPackedElementsKind(kind)) packed = false;
   3132       }
   3133       current_map = maybe_transitioned_map;
   3134     }
   3135   }
   3136   return transitioned_map;
   3137 }
   3138 
   3139 
   3140 static Map* FindClosestElementsTransition(Map* map, ElementsKind to_kind) {
   3141   Map* current_map = map;
   3142   int index = GetSequenceIndexFromFastElementsKind(map->elements_kind());
   3143   int to_index = IsFastElementsKind(to_kind)
   3144       ? GetSequenceIndexFromFastElementsKind(to_kind)
   3145       : GetSequenceIndexFromFastElementsKind(TERMINAL_FAST_ELEMENTS_KIND);
   3146 
   3147   ASSERT(index <= to_index);
   3148 
   3149   for (; index < to_index; ++index) {
   3150     if (!current_map->HasElementsTransition()) return current_map;
   3151     current_map = current_map->elements_transition_map();
   3152   }
   3153   if (!IsFastElementsKind(to_kind) && current_map->HasElementsTransition()) {
   3154     Map* next_map = current_map->elements_transition_map();
   3155     if (next_map->elements_kind() == to_kind) return next_map;
   3156   }
   3157   ASSERT(IsFastElementsKind(to_kind)
   3158          ? current_map->elements_kind() == to_kind
   3159          : current_map->elements_kind() == TERMINAL_FAST_ELEMENTS_KIND);
   3160   return current_map;
   3161 }
   3162 
   3163 
   3164 Map* Map::LookupElementsTransitionMap(ElementsKind to_kind) {
   3165   Map* to_map = FindClosestElementsTransition(this, to_kind);
   3166   if (to_map->elements_kind() == to_kind) return to_map;
   3167   return NULL;
   3168 }
   3169 
   3170 
   3171 bool Map::IsMapInArrayPrototypeChain() {
   3172   Isolate* isolate = GetIsolate();
   3173   if (isolate->initial_array_prototype()->map() == this) {
   3174     return true;
   3175   }
   3176 
   3177   if (isolate->initial_object_prototype()->map() == this) {
   3178     return true;
   3179   }
   3180 
   3181   return false;
   3182 }
   3183 
   3184 
   3185 static MaybeObject* AddMissingElementsTransitions(Map* map,
   3186                                                   ElementsKind to_kind) {
   3187   ASSERT(IsFastElementsKind(map->elements_kind()));
   3188   int index = GetSequenceIndexFromFastElementsKind(map->elements_kind());
   3189   int to_index = IsFastElementsKind(to_kind)
   3190       ? GetSequenceIndexFromFastElementsKind(to_kind)
   3191       : GetSequenceIndexFromFastElementsKind(TERMINAL_FAST_ELEMENTS_KIND);
   3192 
   3193   ASSERT(index <= to_index);
   3194 
   3195   Map* current_map = map;
   3196 
   3197   for (; index < to_index; ++index) {
   3198     ElementsKind next_kind = GetFastElementsKindFromSequenceIndex(index + 1);
   3199     MaybeObject* maybe_next_map =
   3200         current_map->CopyAsElementsKind(next_kind, INSERT_TRANSITION);
   3201     if (!maybe_next_map->To(&current_map)) return maybe_next_map;
   3202   }
   3203 
   3204   // In case we are exiting the fast elements kind system, just add the map in
   3205   // the end.
   3206   if (!IsFastElementsKind(to_kind)) {
   3207     MaybeObject* maybe_next_map =
   3208         current_map->CopyAsElementsKind(to_kind, INSERT_TRANSITION);
   3209     if (!maybe_next_map->To(&current_map)) return maybe_next_map;
   3210   }
   3211 
   3212   ASSERT(current_map->elements_kind() == to_kind);
   3213   return current_map;
   3214 }
   3215 
   3216 
   3217 Handle<Map> JSObject::GetElementsTransitionMap(Handle<JSObject> object,
   3218                                                ElementsKind to_kind) {
   3219   Isolate* isolate = object->GetIsolate();
   3220   CALL_HEAP_FUNCTION(isolate,
   3221                      object->GetElementsTransitionMap(isolate, to_kind),
   3222                      Map);
   3223 }
   3224 
   3225 
   3226 MaybeObject* JSObject::GetElementsTransitionMapSlow(ElementsKind to_kind) {
   3227   Map* start_map = map();
   3228   ElementsKind from_kind = start_map->elements_kind();
   3229 
   3230   if (from_kind == to_kind) {
   3231     return start_map;
   3232   }
   3233 
   3234   bool allow_store_transition =
   3235       // Only remember the map transition if there is not an already existing
   3236       // non-matching element transition.
   3237       !start_map->IsUndefined() && !start_map->is_shared() &&
   3238       IsFastElementsKind(from_kind);
   3239 
   3240   // Only store fast element maps in ascending generality.
   3241   if (IsFastElementsKind(to_kind)) {
   3242     allow_store_transition &=
   3243         IsTransitionableFastElementsKind(from_kind) &&
   3244         IsMoreGeneralElementsKindTransition(from_kind, to_kind);
   3245   }
   3246 
   3247   if (!allow_store_transition) {
   3248     return start_map->CopyAsElementsKind(to_kind, OMIT_TRANSITION);
   3249   }
   3250 
   3251   return start_map->AsElementsKind(to_kind);
   3252 }
   3253 
   3254 
   3255 MaybeObject* Map::AsElementsKind(ElementsKind kind) {
   3256   Map* closest_map = FindClosestElementsTransition(this, kind);
   3257 
   3258   if (closest_map->elements_kind() == kind) {
   3259     return closest_map;
   3260   }
   3261 
   3262   return AddMissingElementsTransitions(closest_map, kind);
   3263 }
   3264 
   3265 
   3266 void JSObject::LocalLookupRealNamedProperty(Name* name, LookupResult* result) {
   3267   if (IsJSGlobalProxy()) {
   3268     Object* proto = GetPrototype();
   3269     if (proto->IsNull()) return result->NotFound();
   3270     ASSERT(proto->IsJSGlobalObject());
   3271     return JSObject::cast(proto)->LocalLookupRealNamedProperty(name, result);
   3272   }
   3273 
   3274   if (HasFastProperties()) {
   3275     map()->LookupDescriptor(this, name, result);
   3276     // A property or a map transition was found. We return all of these result
   3277     // types because LocalLookupRealNamedProperty is used when setting
   3278     // properties where map transitions are handled.
   3279     ASSERT(!result->IsFound() ||
   3280            (result->holder() == this && result->IsFastPropertyType()));
   3281     // Disallow caching for uninitialized constants. These can only
   3282     // occur as fields.
   3283     if (result->IsField() &&
   3284         result->IsReadOnly() &&
   3285         RawFastPropertyAt(result->GetFieldIndex().field_index())->IsTheHole()) {
   3286       result->DisallowCaching();
   3287     }
   3288     return;
   3289   }
   3290 
   3291   int entry = property_dictionary()->FindEntry(name);
   3292   if (entry != NameDictionary::kNotFound) {
   3293     Object* value = property_dictionary()->ValueAt(entry);
   3294     if (IsGlobalObject()) {
   3295       PropertyDetails d = property_dictionary()->DetailsAt(entry);
   3296       if (d.IsDeleted()) {
   3297         result->NotFound();
   3298         return;
   3299       }
   3300       value = PropertyCell::cast(value)->value();
   3301     }
   3302     // Make sure to disallow caching for uninitialized constants
   3303     // found in the dictionary-mode objects.
   3304     if (value->IsTheHole()) result->DisallowCaching();
   3305     result->DictionaryResult(this, entry);
   3306     return;
   3307   }
   3308 
   3309   result->NotFound();
   3310 }
   3311 
   3312 
   3313 void JSObject::LookupRealNamedProperty(Name* name, LookupResult* result) {
   3314   LocalLookupRealNamedProperty(name, result);
   3315   if (result->IsFound()) return;
   3316 
   3317   LookupRealNamedPropertyInPrototypes(name, result);
   3318 }
   3319 
   3320 
   3321 void JSObject::LookupRealNamedPropertyInPrototypes(Name* name,
   3322                                                    LookupResult* result) {
   3323   Isolate* isolate = GetIsolate();
   3324   Heap* heap = isolate->heap();
   3325   for (Object* pt = GetPrototype();
   3326        pt != heap->null_value();
   3327        pt = pt->GetPrototype(isolate)) {
   3328     if (pt->IsJSProxy()) {
   3329       return result->HandlerResult(JSProxy::cast(pt));
   3330     }
   3331     JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result);
   3332     ASSERT(!(result->IsFound() && result->type() == INTERCEPTOR));
   3333     if (result->IsFound()) return;
   3334   }
   3335   result->NotFound();
   3336 }
   3337 
   3338 
   3339 // We only need to deal with CALLBACKS and INTERCEPTORS
   3340 MaybeObject* JSObject::SetPropertyWithFailedAccessCheck(
   3341     LookupResult* result,
   3342     Name* name,
   3343     Object* value,
   3344     bool check_prototype,
   3345     StrictModeFlag strict_mode) {
   3346   if (check_prototype && !result->IsProperty()) {
   3347     LookupRealNamedPropertyInPrototypes(name, result);
   3348   }
   3349 
   3350   if (result->IsProperty()) {
   3351     if (!result->IsReadOnly()) {
   3352       switch (result->type()) {
   3353         case CALLBACKS: {
   3354           Object* obj = result->GetCallbackObject();
   3355           if (obj->IsAccessorInfo()) {
   3356             AccessorInfo* info = AccessorInfo::cast(obj);
   3357             if (info->all_can_write()) {
   3358               return SetPropertyWithCallback(result->GetCallbackObject(),
   3359                                              name,
   3360                                              value,
   3361                                              result->holder(),
   3362                                              strict_mode);
   3363             }
   3364           }
   3365           break;
   3366         }
   3367         case INTERCEPTOR: {
   3368           // Try lookup real named properties. Note that only property can be
   3369           // set is callbacks marked as ALL_CAN_WRITE on the prototype chain.
   3370           LookupResult r(GetIsolate());
   3371           LookupRealNamedProperty(name, &r);
   3372           if (r.IsProperty()) {
   3373             return SetPropertyWithFailedAccessCheck(&r,
   3374                                                     name,
   3375                                                     value,
   3376                                                     check_prototype,
   3377                                                     strict_mode);
   3378           }
   3379           break;
   3380         }
   3381         default: {
   3382           break;
   3383         }
   3384       }
   3385     }
   3386   }
   3387 
   3388   Isolate* isolate = GetIsolate();
   3389   HandleScope scope(isolate);
   3390   Handle<Object> value_handle(value, isolate);
   3391   isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET);
   3392   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   3393   return *value_handle;
   3394 }
   3395 
   3396 
   3397 MaybeObject* JSReceiver::SetProperty(LookupResult* result,
   3398                                      Name* key,
   3399                                      Object* value,
   3400                                      PropertyAttributes attributes,
   3401                                      StrictModeFlag strict_mode,
   3402                                      JSReceiver::StoreFromKeyed store_mode) {
   3403   if (result->IsHandler()) {
   3404     return result->proxy()->SetPropertyWithHandler(
   3405         this, key, value, attributes, strict_mode);
   3406   } else {
   3407     return JSObject::cast(this)->SetPropertyForResult(
   3408         result, key, value, attributes, strict_mode, store_mode);
   3409   }
   3410 }
   3411 
   3412 
   3413 bool JSProxy::HasPropertyWithHandler(Name* name_raw) {
   3414   Isolate* isolate = GetIsolate();
   3415   HandleScope scope(isolate);
   3416   Handle<Object> receiver(this, isolate);
   3417   Handle<Object> name(name_raw, isolate);
   3418 
   3419   // TODO(rossberg): adjust once there is a story for symbols vs proxies.
   3420   if (name->IsSymbol()) return false;
   3421 
   3422   Handle<Object> args[] = { name };
   3423   Handle<Object> result = CallTrap(
   3424     "has", isolate->derived_has_trap(), ARRAY_SIZE(args), args);
   3425   if (isolate->has_pending_exception()) return false;
   3426 
   3427   return result->BooleanValue();
   3428 }
   3429 
   3430 
   3431 MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyWithHandler(
   3432     JSReceiver* receiver_raw,
   3433     Name* name_raw,
   3434     Object* value_raw,
   3435     PropertyAttributes attributes,
   3436     StrictModeFlag strict_mode) {
   3437   Isolate* isolate = GetIsolate();
   3438   HandleScope scope(isolate);
   3439   Handle<JSReceiver> receiver(receiver_raw);
   3440   Handle<Object> name(name_raw, isolate);
   3441   Handle<Object> value(value_raw, isolate);
   3442 
   3443   // TODO(rossberg): adjust once there is a story for symbols vs proxies.
   3444   if (name->IsSymbol()) return *value;
   3445 
   3446   Handle<Object> args[] = { receiver, name, value };
   3447   CallTrap("set", isolate->derived_set_trap(), ARRAY_SIZE(args), args);
   3448   if (isolate->has_pending_exception()) return Failure::Exception();
   3449 
   3450   return *value;
   3451 }
   3452 
   3453 
   3454 MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyViaPrototypesWithHandler(
   3455     JSReceiver* receiver_raw,
   3456     Name* name_raw,
   3457     Object* value_raw,
   3458     PropertyAttributes attributes,
   3459     StrictModeFlag strict_mode,
   3460     bool* done) {
   3461   Isolate* isolate = GetIsolate();
   3462   Handle<JSProxy> proxy(this);
   3463   Handle<JSReceiver> receiver(receiver_raw);
   3464   Handle<Name> name(name_raw);
   3465   Handle<Object> value(value_raw, isolate);
   3466   Handle<Object> handler(this->handler(), isolate);  // Trap might morph proxy.
   3467 
   3468   // TODO(rossberg): adjust once there is a story for symbols vs proxies.
   3469   if (name->IsSymbol()) {
   3470     *done = false;
   3471     return isolate->heap()->the_hole_value();
   3472   }
   3473 
   3474   *done = true;  // except where redefined...
   3475   Handle<Object> args[] = { name };
   3476   Handle<Object> result = proxy->CallTrap(
   3477       "getPropertyDescriptor", Handle<Object>(), ARRAY_SIZE(args), args);
   3478   if (isolate->has_pending_exception()) return Failure::Exception();
   3479 
   3480   if (result->IsUndefined()) {
   3481     *done = false;
   3482     return isolate->heap()->the_hole_value();
   3483   }
   3484 
   3485   // Emulate [[GetProperty]] semantics for proxies.
   3486   bool has_pending_exception;
   3487   Handle<Object> argv[] = { result };
   3488   Handle<Object> desc =
   3489       Execution::Call(isolate->to_complete_property_descriptor(), result,
   3490                       ARRAY_SIZE(argv), argv, &has_pending_exception);
   3491   if (has_pending_exception) return Failure::Exception();
   3492 
   3493   // [[GetProperty]] requires to check that all properties are configurable.
   3494   Handle<String> configurable_name =
   3495       isolate->factory()->InternalizeOneByteString(
   3496           STATIC_ASCII_VECTOR("configurable_"));
   3497   Handle<Object> configurable(
   3498       v8::internal::GetProperty(isolate, desc, configurable_name));
   3499   ASSERT(!isolate->has_pending_exception());
   3500   ASSERT(configurable->IsTrue() || configurable->IsFalse());
   3501   if (configurable->IsFalse()) {
   3502     Handle<String> trap =
   3503         isolate->factory()->InternalizeOneByteString(
   3504             STATIC_ASCII_VECTOR("getPropertyDescriptor"));
   3505     Handle<Object> args[] = { handler, trap, name };
   3506     Handle<Object> error = isolate->factory()->NewTypeError(
   3507         "proxy_prop_not_configurable", HandleVector(args, ARRAY_SIZE(args)));
   3508     return isolate->Throw(*error);
   3509   }
   3510   ASSERT(configurable->IsTrue());
   3511 
   3512   // Check for DataDescriptor.
   3513   Handle<String> hasWritable_name =
   3514       isolate->factory()->InternalizeOneByteString(
   3515           STATIC_ASCII_VECTOR("hasWritable_"));
   3516   Handle<Object> hasWritable(
   3517       v8::internal::GetProperty(isolate, desc, hasWritable_name));
   3518   ASSERT(!isolate->has_pending_exception());
   3519   ASSERT(hasWritable->IsTrue() || hasWritable->IsFalse());
   3520   if (hasWritable->IsTrue()) {
   3521     Handle<String> writable_name =
   3522         isolate->factory()->InternalizeOneByteString(
   3523             STATIC_ASCII_VECTOR("writable_"));
   3524     Handle<Object> writable(
   3525         v8::internal::GetProperty(isolate, desc, writable_name));
   3526     ASSERT(!isolate->has_pending_exception());
   3527     ASSERT(writable->IsTrue() || writable->IsFalse());
   3528     *done = writable->IsFalse();
   3529     if (!*done) return GetHeap()->the_hole_value();
   3530     if (strict_mode == kNonStrictMode) return *value;
   3531     Handle<Object> args[] = { name, receiver };
   3532     Handle<Object> error = isolate->factory()->NewTypeError(
   3533         "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args)));
   3534     return isolate->Throw(*error);
   3535   }
   3536 
   3537   // We have an AccessorDescriptor.
   3538   Handle<String> set_name = isolate->factory()->InternalizeOneByteString(
   3539       STATIC_ASCII_VECTOR("set_"));
   3540   Handle<Object> setter(v8::internal::GetProperty(isolate, desc, set_name));
   3541   ASSERT(!isolate->has_pending_exception());
   3542   if (!setter->IsUndefined()) {
   3543     // TODO(rossberg): nicer would be to cast to some JSCallable here...
   3544     return receiver->SetPropertyWithDefinedSetter(
   3545         JSReceiver::cast(*setter), *value);
   3546   }
   3547 
   3548   if (strict_mode == kNonStrictMode) return *value;
   3549   Handle<Object> args2[] = { name, proxy };
   3550   Handle<Object> error = isolate->factory()->NewTypeError(
   3551       "no_setter_in_callback", HandleVector(args2, ARRAY_SIZE(args2)));
   3552   return isolate->Throw(*error);
   3553 }
   3554 
   3555 
   3556 Handle<Object> JSProxy::DeletePropertyWithHandler(
   3557     Handle<JSProxy> object, Handle<Name> name, DeleteMode mode) {
   3558   Isolate* isolate = object->GetIsolate();
   3559 
   3560   // TODO(rossberg): adjust once there is a story for symbols vs proxies.
   3561   if (name->IsSymbol()) return isolate->factory()->false_value();
   3562 
   3563   Handle<Object> args[] = { name };
   3564   Handle<Object> result = object->CallTrap(
   3565       "delete", Handle<Object>(), ARRAY_SIZE(args), args);
   3566   if (isolate->has_pending_exception()) return Handle<Object>();
   3567 
   3568   bool result_bool = result->BooleanValue();
   3569   if (mode == STRICT_DELETION && !result_bool) {
   3570     Handle<Object> handler(object->handler(), isolate);
   3571     Handle<String> trap_name = isolate->factory()->InternalizeOneByteString(
   3572         STATIC_ASCII_VECTOR("delete"));
   3573     Handle<Object> args[] = { handler, trap_name };
   3574     Handle<Object> error = isolate->factory()->NewTypeError(
   3575         "handler_failed", HandleVector(args, ARRAY_SIZE(args)));
   3576     isolate->Throw(*error);
   3577     return Handle<Object>();
   3578   }
   3579   return isolate->factory()->ToBoolean(result_bool);
   3580 }
   3581 
   3582 
   3583 Handle<Object> JSProxy::DeleteElementWithHandler(
   3584     Handle<JSProxy> object, uint32_t index, DeleteMode mode) {
   3585   Isolate* isolate = object->GetIsolate();
   3586   Handle<String> name = isolate->factory()->Uint32ToString(index);
   3587   return JSProxy::DeletePropertyWithHandler(object, name, mode);
   3588 }
   3589 
   3590 
   3591 MUST_USE_RESULT PropertyAttributes JSProxy::GetPropertyAttributeWithHandler(
   3592     JSReceiver* receiver_raw,
   3593     Name* name_raw) {
   3594   Isolate* isolate = GetIsolate();
   3595   HandleScope scope(isolate);
   3596   Handle<JSProxy> proxy(this);
   3597   Handle<Object> handler(this->handler(), isolate);  // Trap might morph proxy.
   3598   Handle<JSReceiver> receiver(receiver_raw);
   3599   Handle<Object> name(name_raw, isolate);
   3600 
   3601   // TODO(rossberg): adjust once there is a story for symbols vs proxies.
   3602   if (name->IsSymbol()) return ABSENT;
   3603 
   3604   Handle<Object> args[] = { name };
   3605   Handle<Object> result = CallTrap(
   3606     "getPropertyDescriptor", Handle<Object>(), ARRAY_SIZE(args), args);
   3607   if (isolate->has_pending_exception()) return NONE;
   3608 
   3609   if (result->IsUndefined()) return ABSENT;
   3610 
   3611   bool has_pending_exception;
   3612   Handle<Object> argv[] = { result };
   3613   Handle<Object> desc =
   3614       Execution::Call(isolate->to_complete_property_descriptor(), result,
   3615                       ARRAY_SIZE(argv), argv, &has_pending_exception);
   3616   if (has_pending_exception) return NONE;
   3617 
   3618   // Convert result to PropertyAttributes.
   3619   Handle<String> enum_n = isolate->factory()->InternalizeOneByteString(
   3620       STATIC_ASCII_VECTOR("enumerable_"));
   3621   Handle<Object> enumerable(v8::internal::GetProperty(isolate, desc, enum_n));
   3622   if (isolate->has_pending_exception()) return NONE;
   3623   Handle<String> conf_n = isolate->factory()->InternalizeOneByteString(
   3624       STATIC_ASCII_VECTOR("configurable_"));
   3625   Handle<Object> configurable(v8::internal::GetProperty(isolate, desc, conf_n));
   3626   if (isolate->has_pending_exception()) return NONE;
   3627   Handle<String> writ_n = isolate->factory()->InternalizeOneByteString(
   3628       STATIC_ASCII_VECTOR("writable_"));
   3629   Handle<Object> writable(v8::internal::GetProperty(isolate, desc, writ_n));
   3630   if (isolate->has_pending_exception()) return NONE;
   3631   if (!writable->BooleanValue()) {
   3632     Handle<String> set_n = isolate->factory()->InternalizeOneByteString(
   3633         STATIC_ASCII_VECTOR("set_"));
   3634     Handle<Object> setter(v8::internal::GetProperty(isolate, desc, set_n));
   3635     if (isolate->has_pending_exception()) return NONE;
   3636     writable = isolate->factory()->ToBoolean(!setter->IsUndefined());
   3637   }
   3638 
   3639   if (configurable->IsFalse()) {
   3640     Handle<String> trap = isolate->factory()->InternalizeOneByteString(
   3641         STATIC_ASCII_VECTOR("getPropertyDescriptor"));
   3642     Handle<Object> args[] = { handler, trap, name };
   3643     Handle<Object> error = isolate->factory()->NewTypeError(
   3644         "proxy_prop_not_configurable", HandleVector(args, ARRAY_SIZE(args)));
   3645     isolate->Throw(*error);
   3646     return NONE;
   3647   }
   3648 
   3649   int attributes = NONE;
   3650   if (!enumerable->BooleanValue()) attributes |= DONT_ENUM;
   3651   if (!configurable->BooleanValue()) attributes |= DONT_DELETE;
   3652   if (!writable->BooleanValue()) attributes |= READ_ONLY;
   3653   return static_cast<PropertyAttributes>(attributes);
   3654 }
   3655 
   3656 
   3657 MUST_USE_RESULT PropertyAttributes JSProxy::GetElementAttributeWithHandler(
   3658     JSReceiver* receiver_raw,
   3659     uint32_t index) {
   3660   Isolate* isolate = GetIsolate();
   3661   HandleScope scope(isolate);
   3662   Handle<JSProxy> proxy(this);
   3663   Handle<JSReceiver> receiver(receiver_raw);
   3664   Handle<String> name = isolate->factory()->Uint32ToString(index);
   3665   return proxy->GetPropertyAttributeWithHandler(*receiver, *name);
   3666 }
   3667 
   3668 
   3669 void JSProxy::Fix() {
   3670   Isolate* isolate = GetIsolate();
   3671   HandleScope scope(isolate);
   3672   Handle<JSProxy> self(this);
   3673 
   3674   // Save identity hash.
   3675   MaybeObject* maybe_hash = GetIdentityHash(OMIT_CREATION);
   3676 
   3677   if (IsJSFunctionProxy()) {
   3678     isolate->factory()->BecomeJSFunction(self);
   3679     // Code will be set on the JavaScript side.
   3680   } else {
   3681     isolate->factory()->BecomeJSObject(self);
   3682   }
   3683   ASSERT(self->IsJSObject());
   3684 
   3685   // Inherit identity, if it was present.
   3686   Object* hash;
   3687   if (maybe_hash->To<Object>(&hash) && hash->IsSmi()) {
   3688     Handle<JSObject> new_self(JSObject::cast(*self));
   3689     isolate->factory()->SetIdentityHash(new_self, Smi::cast(hash));
   3690   }
   3691 }
   3692 
   3693 
   3694 MUST_USE_RESULT Handle<Object> JSProxy::CallTrap(const char* name,
   3695                                                  Handle<Object> derived,
   3696                                                  int argc,
   3697                                                  Handle<Object> argv[]) {
   3698   Isolate* isolate = GetIsolate();
   3699   Handle<Object> handler(this->handler(), isolate);
   3700 
   3701   Handle<String> trap_name = isolate->factory()->InternalizeUtf8String(name);
   3702   Handle<Object> trap(v8::internal::GetProperty(isolate, handler, trap_name));
   3703   if (isolate->has_pending_exception()) return trap;
   3704 
   3705   if (trap->IsUndefined()) {
   3706     if (derived.is_null()) {
   3707       Handle<Object> args[] = { handler, trap_name };
   3708       Handle<Object> error = isolate->factory()->NewTypeError(
   3709         "handler_trap_missing", HandleVector(args, ARRAY_SIZE(args)));
   3710       isolate->Throw(*error);
   3711       return Handle<Object>();
   3712     }
   3713     trap = Handle<Object>(derived);
   3714   }
   3715 
   3716   bool threw;
   3717   return Execution::Call(trap, handler, argc, argv, &threw);
   3718 }
   3719 
   3720 
   3721 void JSObject::AllocateStorageForMap(Handle<JSObject> object, Handle<Map> map) {
   3722   CALL_HEAP_FUNCTION_VOID(
   3723       object->GetIsolate(),
   3724       object->AllocateStorageForMap(*map));
   3725 }
   3726 
   3727 
   3728 void JSObject::MigrateInstance(Handle<JSObject> object) {
   3729   if (FLAG_trace_migration) {
   3730     PrintF("migrating instance %p (%p)\n",
   3731            static_cast<void*>(*object),
   3732            static_cast<void*>(object->map()));
   3733   }
   3734   CALL_HEAP_FUNCTION_VOID(
   3735       object->GetIsolate(),
   3736       object->MigrateInstance());
   3737 }
   3738 
   3739 
   3740 Handle<Object> JSObject::TryMigrateInstance(Handle<JSObject> object) {
   3741   if (FLAG_trace_migration) {
   3742     PrintF("migrating instance (no new maps) %p (%p)\n",
   3743            static_cast<void*>(*object),
   3744            static_cast<void*>(object->map()));
   3745   }
   3746   CALL_HEAP_FUNCTION(
   3747       object->GetIsolate(),
   3748       object->MigrateInstance(),
   3749       Object);
   3750 }
   3751 
   3752 
   3753 Handle<Map> Map::GeneralizeRepresentation(Handle<Map> map,
   3754                                           int modify_index,
   3755                                           Representation representation) {
   3756   CALL_HEAP_FUNCTION(
   3757       map->GetIsolate(),
   3758       map->GeneralizeRepresentation(modify_index, representation),
   3759       Map);
   3760 }
   3761 
   3762 
   3763 MaybeObject* JSObject::SetPropertyForResult(LookupResult* lookup,
   3764                                             Name* name_raw,
   3765                                             Object* value_raw,
   3766                                             PropertyAttributes attributes,
   3767                                             StrictModeFlag strict_mode,
   3768                                             StoreFromKeyed store_mode) {
   3769   Heap* heap = GetHeap();
   3770   Isolate* isolate = heap->isolate();
   3771   // Make sure that the top context does not change when doing callbacks or
   3772   // interceptor calls.
   3773   AssertNoContextChange ncc;
   3774 
   3775   // Optimization for 2-byte strings often used as keys in a decompression
   3776   // dictionary.  We internalize these short keys to avoid constantly
   3777   // reallocating them.
   3778   if (name_raw->IsString() && !name_raw->IsInternalizedString() &&
   3779       String::cast(name_raw)->length() <= 2) {
   3780     Object* internalized_version;
   3781     { MaybeObject* maybe_string_version =
   3782         heap->InternalizeString(String::cast(name_raw));
   3783       if (maybe_string_version->ToObject(&internalized_version)) {
   3784         name_raw = String::cast(internalized_version);
   3785       }
   3786     }
   3787   }
   3788 
   3789   // Check access rights if needed.
   3790   if (IsAccessCheckNeeded()) {
   3791     if (!isolate->MayNamedAccess(this, name_raw, v8::ACCESS_SET)) {
   3792       return SetPropertyWithFailedAccessCheck(
   3793           lookup, name_raw, value_raw, true, strict_mode);
   3794     }
   3795   }
   3796 
   3797   if (IsJSGlobalProxy()) {
   3798     Object* proto = GetPrototype();
   3799     if (proto->IsNull()) return value_raw;
   3800     ASSERT(proto->IsJSGlobalObject());
   3801     return JSObject::cast(proto)->SetPropertyForResult(
   3802         lookup, name_raw, value_raw, attributes, strict_mode, store_mode);
   3803   }
   3804 
   3805   ASSERT(!lookup->IsFound() || lookup->holder() == this ||
   3806          lookup->holder()->map()->is_hidden_prototype());
   3807 
   3808   // From this point on everything needs to be handlified, because
   3809   // SetPropertyViaPrototypes might call back into JavaScript.
   3810   HandleScope scope(isolate);
   3811   Handle<JSObject> self(this);
   3812   Handle<Name> name(name_raw);
   3813   Handle<Object> value(value_raw, isolate);
   3814 
   3815   if (!lookup->IsProperty() && !self->IsJSContextExtensionObject()) {
   3816     bool done = false;
   3817     MaybeObject* result_object = self->SetPropertyViaPrototypes(
   3818         *name, *value, attributes, strict_mode, &done);
   3819     if (done) return result_object;
   3820   }
   3821 
   3822   if (!lookup->IsFound()) {
   3823     // Neither properties nor transitions found.
   3824     return self->AddProperty(
   3825         *name, *value, attributes, strict_mode, store_mode);
   3826   }
   3827 
   3828   if (lookup->IsProperty() && lookup->IsReadOnly()) {
   3829     if (strict_mode == kStrictMode) {
   3830       Handle<Object> args[] = { name, self };
   3831       return isolate->Throw(*isolate->factory()->NewTypeError(
   3832           "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args))));
   3833     } else {
   3834       return *value;
   3835     }
   3836   }
   3837 
   3838   Handle<Object> old_value(heap->the_hole_value(), isolate);
   3839   if (FLAG_harmony_observation &&
   3840       map()->is_observed() && lookup->IsDataProperty()) {
   3841     old_value = Object::GetProperty(self, name);
   3842   }
   3843 
   3844   // This is a real property that is not read-only, or it is a
   3845   // transition or null descriptor and there are no setters in the prototypes.
   3846   MaybeObject* result = *value;
   3847   switch (lookup->type()) {
   3848     case NORMAL:
   3849       result = lookup->holder()->SetNormalizedProperty(lookup, *value);
   3850       break;
   3851     case FIELD: {
   3852       Representation representation = lookup->representation();
   3853       if (!value->FitsRepresentation(representation)) {
   3854         MaybeObject* maybe_failure =
   3855             lookup->holder()->GeneralizeFieldRepresentation(
   3856                 lookup->GetDescriptorIndex(), value->OptimalRepresentation());
   3857         if (maybe_failure->IsFailure()) return maybe_failure;
   3858         DescriptorArray* desc = lookup->holder()->map()->instance_descriptors();
   3859         int descriptor = lookup->GetDescriptorIndex();
   3860         representation = desc->GetDetails(descriptor).representation();
   3861       }
   3862       if (FLAG_track_double_fields && representation.IsDouble()) {
   3863         HeapNumber* storage =
   3864             HeapNumber::cast(lookup->holder()->RawFastPropertyAt(
   3865                 lookup->GetFieldIndex().field_index()));
   3866         storage->set_value(value->Number());
   3867         result = *value;
   3868         break;
   3869       }
   3870       lookup->holder()->FastPropertyAtPut(
   3871           lookup->GetFieldIndex().field_index(), *value);
   3872       result = *value;
   3873       break;
   3874     }
   3875     case CONSTANT:
   3876       // Only replace the constant if necessary.
   3877       if (*value == lookup->GetConstant()) return *value;
   3878       // Preserve the attributes of this existing property.
   3879       attributes = lookup->GetAttributes();
   3880       result = lookup->holder()->ConvertDescriptorToField(
   3881           *name, *value, attributes);
   3882       break;
   3883     case CALLBACKS: {
   3884       Object* callback_object = lookup->GetCallbackObject();
   3885       return self->SetPropertyWithCallback(
   3886           callback_object, *name, *value, lookup->holder(), strict_mode);
   3887     }
   3888     case INTERCEPTOR:
   3889       result = lookup->holder()->SetPropertyWithInterceptor(
   3890           *name, *value, attributes, strict_mode);
   3891       break;
   3892     case TRANSITION: {
   3893       Map* transition_map = lookup->GetTransitionTarget();
   3894       int descriptor = transition_map->LastAdded();
   3895 
   3896       DescriptorArray* descriptors = transition_map->instance_descriptors();
   3897       PropertyDetails details = descriptors->GetDetails(descriptor);
   3898 
   3899       if (details.type() == FIELD) {
   3900         if (attributes == details.attributes()) {
   3901           Representation representation = details.representation();
   3902           if (!value->FitsRepresentation(representation)) {
   3903             MaybeObject* maybe_map = transition_map->GeneralizeRepresentation(
   3904                 descriptor, value->OptimalRepresentation());
   3905             if (!maybe_map->To(&transition_map)) return maybe_map;
   3906             Object* back = transition_map->GetBackPointer();
   3907             if (back->IsMap()) {
   3908               MaybeObject* maybe_failure =
   3909                   lookup->holder()->MigrateToMap(Map::cast(back));
   3910               if (maybe_failure->IsFailure()) return maybe_failure;
   3911             }
   3912             descriptors = transition_map->instance_descriptors();
   3913             representation =
   3914                 descriptors->GetDetails(descriptor).representation();
   3915           }
   3916           int field_index = descriptors->GetFieldIndex(descriptor);
   3917           result = lookup->holder()->AddFastPropertyUsingMap(
   3918               transition_map, *name, *value, field_index, representation);
   3919         } else {
   3920           result = lookup->holder()->ConvertDescriptorToField(
   3921               *name, *value, attributes);
   3922         }
   3923       } else if (details.type() == CALLBACKS) {
   3924         result = lookup->holder()->ConvertDescriptorToField(
   3925             *name, *value, attributes);
   3926       } else {
   3927         ASSERT(details.type() == CONSTANT);
   3928 
   3929         Object* constant = descriptors->GetValue(descriptor);
   3930         if (constant == *value) {
   3931           // If the same constant function is being added we can simply
   3932           // transition to the target map.
   3933           lookup->holder()->set_map(transition_map);
   3934           result = constant;
   3935         } else {
   3936           // Otherwise, replace with a map transition to a new map with a FIELD,
   3937           // even if the value is a constant function.
   3938           result = lookup->holder()->ConvertTransitionToMapTransition(
   3939               lookup->GetTransitionIndex(), *name, *value, attributes);
   3940         }
   3941       }
   3942       break;
   3943     }
   3944     case HANDLER:
   3945     case NONEXISTENT:
   3946       UNREACHABLE();
   3947   }
   3948 
   3949   Handle<Object> hresult;
   3950   if (!result->ToHandle(&hresult, isolate)) return result;
   3951 
   3952   if (FLAG_harmony_observation && self->map()->is_observed()) {
   3953     if (lookup->IsTransition()) {
   3954       EnqueueChangeRecord(self, "new", name, old_value);
   3955     } else {
   3956       LookupResult new_lookup(isolate);
   3957       self->LocalLookup(*name, &new_lookup, true);
   3958       if (new_lookup.IsDataProperty()) {
   3959         Handle<Object> new_value = Object::GetProperty(self, name);
   3960         if (!new_value->SameValue(*old_value)) {
   3961           EnqueueChangeRecord(self, "updated", name, old_value);
   3962         }
   3963       }
   3964     }
   3965   }
   3966 
   3967   return *hresult;
   3968 }
   3969 
   3970 
   3971 // Set a real local property, even if it is READ_ONLY.  If the property is not
   3972 // present, add it with attributes NONE.  This code is an exact clone of
   3973 // SetProperty, with the check for IsReadOnly and the check for a
   3974 // callback setter removed.  The two lines looking up the LookupResult
   3975 // result are also added.  If one of the functions is changed, the other
   3976 // should be.
   3977 // Note that this method cannot be used to set the prototype of a function
   3978 // because ConvertDescriptorToField() which is called in "case CALLBACKS:"
   3979 // doesn't handle function prototypes correctly.
   3980 Handle<Object> JSObject::SetLocalPropertyIgnoreAttributes(
   3981     Handle<JSObject> object,
   3982     Handle<Name> key,
   3983     Handle<Object> value,
   3984     PropertyAttributes attributes,
   3985     ValueType value_type,
   3986     StoreMode mode) {
   3987   CALL_HEAP_FUNCTION(
   3988     object->GetIsolate(),
   3989     object->SetLocalPropertyIgnoreAttributes(
   3990         *key, *value, attributes, value_type, mode),
   3991     Object);
   3992 }
   3993 
   3994 
   3995 MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes(
   3996     Name* name_raw,
   3997     Object* value_raw,
   3998     PropertyAttributes attributes,
   3999     ValueType value_type,
   4000     StoreMode mode) {
   4001   // Make sure that the top context does not change when doing callbacks or
   4002   // interceptor calls.
   4003   AssertNoContextChange ncc;
   4004   Isolate* isolate = GetIsolate();
   4005   LookupResult lookup(isolate);
   4006   LocalLookup(name_raw, &lookup, true);
   4007   if (!lookup.IsFound()) map()->LookupTransition(this, name_raw, &lookup);
   4008   // Check access rights if needed.
   4009   if (IsAccessCheckNeeded()) {
   4010     if (!isolate->MayNamedAccess(this, name_raw, v8::ACCESS_SET)) {
   4011       return SetPropertyWithFailedAccessCheck(&lookup,
   4012                                               name_raw,
   4013                                               value_raw,
   4014                                               false,
   4015                                               kNonStrictMode);
   4016     }
   4017   }
   4018 
   4019   if (IsJSGlobalProxy()) {
   4020     Object* proto = GetPrototype();
   4021     if (proto->IsNull()) return value_raw;
   4022     ASSERT(proto->IsJSGlobalObject());
   4023     return JSObject::cast(proto)->SetLocalPropertyIgnoreAttributes(
   4024         name_raw,
   4025         value_raw,
   4026         attributes,
   4027         value_type,
   4028         mode);
   4029   }
   4030 
   4031   // Check for accessor in prototype chain removed here in clone.
   4032   if (!lookup.IsFound()) {
   4033     // Neither properties nor transitions found.
   4034     return AddProperty(
   4035         name_raw, value_raw, attributes, kNonStrictMode,
   4036         MAY_BE_STORE_FROM_KEYED, PERFORM_EXTENSIBILITY_CHECK, value_type, mode);
   4037   }
   4038 
   4039   // From this point on everything needs to be handlified.
   4040   HandleScope scope(isolate);
   4041   Handle<JSObject> self(this);
   4042   Handle<Name> name(name_raw);
   4043   Handle<Object> value(value_raw, isolate);
   4044 
   4045   Handle<Object> old_value(isolate->heap()->the_hole_value(), isolate);
   4046   PropertyAttributes old_attributes = ABSENT;
   4047   bool is_observed = FLAG_harmony_observation && self->map()->is_observed();
   4048   if (is_observed && lookup.IsProperty()) {
   4049     if (lookup.IsDataProperty()) old_value = Object::GetProperty(self, name);
   4050     old_attributes = lookup.GetAttributes();
   4051   }
   4052 
   4053   // Check of IsReadOnly removed from here in clone.
   4054   MaybeObject* result = *value;
   4055   switch (lookup.type()) {
   4056     case NORMAL: {
   4057       PropertyDetails details = PropertyDetails(attributes, NORMAL, 0);
   4058       result = self->SetNormalizedProperty(*name, *value, details);
   4059       break;
   4060     }
   4061     case FIELD: {
   4062       Representation representation = lookup.representation();
   4063       Representation value_representation =
   4064           value->OptimalRepresentation(value_type);
   4065       if (value_representation.IsNone()) break;
   4066       if (!value_representation.fits_into(representation)) {
   4067         MaybeObject* maybe_failure = self->GeneralizeFieldRepresentation(
   4068             lookup.GetDescriptorIndex(), value_representation);
   4069         if (maybe_failure->IsFailure()) return maybe_failure;
   4070         DescriptorArray* desc = self->map()->instance_descriptors();
   4071         int descriptor = lookup.GetDescriptorIndex();
   4072         representation = desc->GetDetails(descriptor).representation();
   4073       }
   4074       if (FLAG_track_double_fields && representation.IsDouble()) {
   4075         HeapNumber* storage =
   4076             HeapNumber::cast(self->RawFastPropertyAt(
   4077                 lookup.GetFieldIndex().field_index()));
   4078         storage->set_value(value->Number());
   4079         result = *value;
   4080         break;
   4081       }
   4082       self->FastPropertyAtPut(lookup.GetFieldIndex().field_index(), *value);
   4083       result = *value;
   4084       break;
   4085     }
   4086     case CONSTANT:
   4087       // Only replace the function if necessary.
   4088       if (*value != lookup.GetConstant()) {
   4089         // Preserve the attributes of this existing property.
   4090         attributes = lookup.GetAttributes();
   4091         result = self->ConvertDescriptorToField(*name, *value, attributes);
   4092       }
   4093       break;
   4094     case CALLBACKS:
   4095     case INTERCEPTOR:
   4096       // Override callback in clone
   4097       result = self->ConvertDescriptorToField(*name, *value, attributes);
   4098       break;
   4099     case TRANSITION: {
   4100       Map* transition_map = lookup.GetTransitionTarget();
   4101       int descriptor = transition_map->LastAdded();
   4102 
   4103       DescriptorArray* descriptors = transition_map->instance_descriptors();
   4104       PropertyDetails details = descriptors->GetDetails(descriptor);
   4105 
   4106       if (details.type() == FIELD) {
   4107         if (attributes == details.attributes()) {
   4108           Representation representation = details.representation();
   4109           Representation value_representation =
   4110               value->OptimalRepresentation(value_type);
   4111           if (!value_representation.fits_into(representation)) {
   4112             MaybeObject* maybe_map = transition_map->GeneralizeRepresentation(
   4113                 descriptor, value_representation);
   4114             if (!maybe_map->To(&transition_map)) return maybe_map;
   4115             Object* back = transition_map->GetBackPointer();
   4116             if (back->IsMap()) {
   4117               MaybeObject* maybe_failure = self->MigrateToMap(Map::cast(back));
   4118               if (maybe_failure->IsFailure()) return maybe_failure;
   4119             }
   4120             descriptors = transition_map->instance_descriptors();
   4121             representation =
   4122                 descriptors->GetDetails(descriptor).representation();
   4123           }
   4124           int field_index = descriptors->GetFieldIndex(descriptor);
   4125           result = self->AddFastPropertyUsingMap(
   4126               transition_map, *name, *value, field_index, representation);
   4127         } else {
   4128           result = self->ConvertDescriptorToField(*name, *value, attributes);
   4129         }
   4130       } else if (details.type() == CALLBACKS) {
   4131         result = self->ConvertDescriptorToField(*name, *value, attributes);
   4132       } else {
   4133         ASSERT(details.type() == CONSTANT);
   4134 
   4135         // Replace transition to CONSTANT FUNCTION with a map transition to a
   4136         // new map with a FIELD, even if the value is a function.
   4137         result = self->ConvertTransitionToMapTransition(
   4138             lookup.GetTransitionIndex(), *name, *value, attributes);
   4139       }
   4140       break;
   4141     }
   4142     case HANDLER:
   4143     case NONEXISTENT:
   4144       UNREACHABLE();
   4145   }
   4146 
   4147   Handle<Object> hresult;
   4148   if (!result->ToHandle(&hresult, isolate)) return result;
   4149 
   4150   if (is_observed) {
   4151     if (lookup.IsTransition()) {
   4152       EnqueueChangeRecord(self, "new", name, old_value);
   4153     } else if (old_value->IsTheHole()) {
   4154       EnqueueChangeRecord(self, "reconfigured", name, old_value);
   4155     } else {
   4156       LookupResult new_lookup(isolate);
   4157       self->LocalLookup(*name, &new_lookup, true);
   4158       bool value_changed = false;
   4159       if (new_lookup.IsDataProperty()) {
   4160         Handle<Object> new_value = Object::GetProperty(self, name);
   4161         value_changed = !old_value->SameValue(*new_value);
   4162       }
   4163       if (new_lookup.GetAttributes() != old_attributes) {
   4164         if (!value_changed) old_value = isolate->factory()->the_hole_value();
   4165         EnqueueChangeRecord(self, "reconfigured", name, old_value);
   4166       } else if (value_changed) {
   4167         EnqueueChangeRecord(self, "updated", name, old_value);
   4168       }
   4169     }
   4170   }
   4171 
   4172   return *hresult;
   4173 }
   4174 
   4175 
   4176 PropertyAttributes JSObject::GetPropertyAttributePostInterceptor(
   4177       JSObject* receiver,
   4178       Name* name,
   4179       bool continue_search) {
   4180   // Check local property, ignore interceptor.
   4181   LookupResult result(GetIsolate());
   4182   LocalLookupRealNamedProperty(name, &result);
   4183   if (result.IsFound()) return result.GetAttributes();
   4184 
   4185   if (continue_search) {
   4186     // Continue searching via the prototype chain.
   4187     Object* pt = GetPrototype();
   4188     if (!pt->IsNull()) {
   4189       return JSObject::cast(pt)->
   4190         GetPropertyAttributeWithReceiver(receiver, name);
   4191     }
   4192   }
   4193   return ABSENT;
   4194 }
   4195 
   4196 
   4197 PropertyAttributes JSObject::GetPropertyAttributeWithInterceptor(
   4198       JSObject* receiver,
   4199       Name* name,
   4200       bool continue_search) {
   4201   // TODO(rossberg): Support symbols in the API.
   4202   if (name->IsSymbol()) return ABSENT;
   4203 
   4204   Isolate* isolate = GetIsolate();
   4205 
   4206   // Make sure that the top context does not change when doing
   4207   // callbacks or interceptor calls.
   4208   AssertNoContextChange ncc;
   4209 
   4210   HandleScope scope(isolate);
   4211   Handle<InterceptorInfo> interceptor(GetNamedInterceptor());
   4212   Handle<JSObject> receiver_handle(receiver);
   4213   Handle<JSObject> holder_handle(this);
   4214   Handle<String> name_handle(String::cast(name));
   4215   PropertyCallbackArguments args(isolate, interceptor->data(), receiver, this);
   4216   if (!interceptor->query()->IsUndefined()) {
   4217     v8::NamedPropertyQuery query =
   4218         v8::ToCData<v8::NamedPropertyQuery>(interceptor->query());
   4219     LOG(isolate,
   4220         ApiNamedPropertyAccess("interceptor-named-has", *holder_handle, name));
   4221     v8::Handle<v8::Integer> result =
   4222         args.Call(query, v8::Utils::ToLocal(name_handle));
   4223     if (!result.IsEmpty()) {
   4224       ASSERT(result->IsInt32());
   4225       return static_cast<PropertyAttributes>(result->Int32Value());
   4226     }
   4227   } else if (!interceptor->getter()->IsUndefined()) {
   4228     v8::NamedPropertyGetter getter =
   4229         v8::ToCData<v8::NamedPropertyGetter>(interceptor->getter());
   4230     LOG(isolate,
   4231         ApiNamedPropertyAccess("interceptor-named-get-has", this, name));
   4232     v8::Handle<v8::Value> result =
   4233         args.Call(getter, v8::Utils::ToLocal(name_handle));
   4234     if (!result.IsEmpty()) return DONT_ENUM;
   4235   }
   4236   return holder_handle->GetPropertyAttributePostInterceptor(*receiver_handle,
   4237                                                             *name_handle,
   4238                                                             continue_search);
   4239 }
   4240 
   4241 
   4242 PropertyAttributes JSReceiver::GetPropertyAttributeWithReceiver(
   4243       JSReceiver* receiver,
   4244       Name* key) {
   4245   uint32_t index = 0;
   4246   if (IsJSObject() && key->AsArrayIndex(&index)) {
   4247     return JSObject::cast(this)->GetElementAttributeWithReceiver(
   4248         receiver, index, true);
   4249   }
   4250   // Named property.
   4251   LookupResult lookup(GetIsolate());
   4252   Lookup(key, &lookup);
   4253   return GetPropertyAttributeForResult(receiver, &lookup, key, true);
   4254 }
   4255 
   4256 
   4257 PropertyAttributes JSReceiver::GetPropertyAttributeForResult(
   4258     JSReceiver* receiver,
   4259     LookupResult* lookup,
   4260     Name* name,
   4261     bool continue_search) {
   4262   // Check access rights if needed.
   4263   if (IsAccessCheckNeeded()) {
   4264     JSObject* this_obj = JSObject::cast(this);
   4265     Heap* heap = GetHeap();
   4266     if (!heap->isolate()->MayNamedAccess(this_obj, name, v8::ACCESS_HAS)) {
   4267       return this_obj->GetPropertyAttributeWithFailedAccessCheck(
   4268           receiver, lookup, name, continue_search);
   4269     }
   4270   }
   4271   if (lookup->IsFound()) {
   4272     switch (lookup->type()) {
   4273       case NORMAL:  // fall through
   4274       case FIELD:
   4275       case CONSTANT:
   4276       case CALLBACKS:
   4277         return lookup->GetAttributes();
   4278       case HANDLER: {
   4279         return JSProxy::cast(lookup->proxy())->GetPropertyAttributeWithHandler(
   4280             receiver, name);
   4281       }
   4282       case INTERCEPTOR:
   4283         return lookup->holder()->GetPropertyAttributeWithInterceptor(
   4284             JSObject::cast(receiver), name, continue_search);
   4285       case TRANSITION:
   4286       case NONEXISTENT:
   4287         UNREACHABLE();
   4288     }
   4289   }
   4290   return ABSENT;
   4291 }
   4292 
   4293 
   4294 PropertyAttributes JSReceiver::GetLocalPropertyAttribute(Name* name) {
   4295   // Check whether the name is an array index.
   4296   uint32_t index = 0;
   4297   if (IsJSObject() && name->AsArrayIndex(&index)) {
   4298     return GetLocalElementAttribute(index);
   4299   }
   4300   // Named property.
   4301   LookupResult lookup(GetIsolate());
   4302   LocalLookup(name, &lookup, true);
   4303   return GetPropertyAttributeForResult(this, &lookup, name, false);
   4304 }
   4305 
   4306 
   4307 PropertyAttributes JSObject::GetElementAttributeWithReceiver(
   4308     JSReceiver* receiver, uint32_t index, bool continue_search) {
   4309   Isolate* isolate = GetIsolate();
   4310 
   4311   // Check access rights if needed.
   4312   if (IsAccessCheckNeeded()) {
   4313     if (!isolate->MayIndexedAccess(this, index, v8::ACCESS_HAS)) {
   4314       isolate->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
   4315       return ABSENT;
   4316     }
   4317   }
   4318 
   4319   if (IsJSGlobalProxy()) {
   4320     Object* proto = GetPrototype();
   4321     if (proto->IsNull()) return ABSENT;
   4322     ASSERT(proto->IsJSGlobalObject());
   4323     return JSObject::cast(proto)->GetElementAttributeWithReceiver(
   4324         receiver, index, continue_search);
   4325   }
   4326 
   4327   // Check for lookup interceptor except when bootstrapping.
   4328   if (HasIndexedInterceptor() && !isolate->bootstrapper()->IsActive()) {
   4329     return GetElementAttributeWithInterceptor(receiver, index, continue_search);
   4330   }
   4331 
   4332   return GetElementAttributeWithoutInterceptor(
   4333       receiver, index, continue_search);
   4334 }
   4335 
   4336 
   4337 PropertyAttributes JSObject::GetElementAttributeWithInterceptor(
   4338     JSReceiver* receiver, uint32_t index, bool continue_search) {
   4339   Isolate* isolate = GetIsolate();
   4340   // Make sure that the top context does not change when doing
   4341   // callbacks or interceptor calls.
   4342   AssertNoContextChange ncc;
   4343   HandleScope scope(isolate);
   4344   Handle<InterceptorInfo> interceptor(GetIndexedInterceptor());
   4345   Handle<JSReceiver> hreceiver(receiver);
   4346   Handle<JSObject> holder(this);
   4347   PropertyCallbackArguments args(isolate, interceptor->data(), receiver, this);
   4348   if (!interceptor->query()->IsUndefined()) {
   4349     v8::IndexedPropertyQuery query =
   4350         v8::ToCData<v8::IndexedPropertyQuery>(interceptor->query());
   4351     LOG(isolate,
   4352         ApiIndexedPropertyAccess("interceptor-indexed-has", this, index));
   4353     v8::Handle<v8::Integer> result = args.Call(query, index);
   4354     if (!result.IsEmpty())
   4355       return static_cast<PropertyAttributes>(result->Int32Value());
   4356   } else if (!interceptor->getter()->IsUndefined()) {
   4357     v8::IndexedPropertyGetter getter =
   4358         v8::ToCData<v8::IndexedPropertyGetter>(interceptor->getter());
   4359     LOG(isolate,
   4360         ApiIndexedPropertyAccess("interceptor-indexed-get-has", this, index));
   4361     v8::Handle<v8::Value> result = args.Call(getter, index);
   4362     if (!result.IsEmpty()) return NONE;
   4363   }
   4364 
   4365   return holder->GetElementAttributeWithoutInterceptor(
   4366       *hreceiver, index, continue_search);
   4367 }
   4368 
   4369 
   4370 PropertyAttributes JSObject::GetElementAttributeWithoutInterceptor(
   4371       JSReceiver* receiver, uint32_t index, bool continue_search) {
   4372   PropertyAttributes attr = GetElementsAccessor()->GetAttributes(
   4373       receiver, this, index);
   4374   if (attr != ABSENT) return attr;
   4375 
   4376   // Handle [] on String objects.
   4377   if (IsStringObjectWithCharacterAt(index)) {
   4378     return static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE);
   4379   }
   4380 
   4381   if (!continue_search) return ABSENT;
   4382 
   4383   Object* pt = GetPrototype();
   4384   if (pt->IsJSProxy()) {
   4385     // We need to follow the spec and simulate a call to [[GetOwnProperty]].
   4386     return JSProxy::cast(pt)->GetElementAttributeWithHandler(receiver, index);
   4387   }
   4388   if (pt->IsNull()) return ABSENT;
   4389   return JSObject::cast(pt)->GetElementAttributeWithReceiver(
   4390       receiver, index, true);
   4391 }
   4392 
   4393 
   4394 MaybeObject* NormalizedMapCache::Get(JSObject* obj,
   4395                                      PropertyNormalizationMode mode) {
   4396   Isolate* isolate = obj->GetIsolate();
   4397   Map* fast = obj->map();
   4398   int index = fast->Hash() % kEntries;
   4399   Object* result = get(index);
   4400   if (result->IsMap() &&
   4401       Map::cast(result)->EquivalentToForNormalization(fast, mode)) {
   4402 #ifdef VERIFY_HEAP
   4403     if (FLAG_verify_heap) {
   4404       Map::cast(result)->SharedMapVerify();
   4405     }
   4406 #endif
   4407 #ifdef DEBUG
   4408     if (FLAG_enable_slow_asserts) {
   4409       // The cached map should match newly created normalized map bit-by-bit,
   4410       // except for the code cache, which can contain some ics which can be
   4411       // applied to the shared map.
   4412       Object* fresh;
   4413       MaybeObject* maybe_fresh =
   4414           fast->CopyNormalized(mode, SHARED_NORMALIZED_MAP);
   4415       if (maybe_fresh->ToObject(&fresh)) {
   4416         ASSERT(memcmp(Map::cast(fresh)->address(),
   4417                       Map::cast(result)->address(),
   4418                       Map::kCodeCacheOffset) == 0);
   4419         STATIC_ASSERT(Map::kDependentCodeOffset ==
   4420                       Map::kCodeCacheOffset + kPointerSize);
   4421         int offset = Map::kDependentCodeOffset + kPointerSize;
   4422         ASSERT(memcmp(Map::cast(fresh)->address() + offset,
   4423                       Map::cast(result)->address() + offset,
   4424                       Map::kSize - offset) == 0);
   4425       }
   4426     }
   4427 #endif
   4428     return result;
   4429   }
   4430 
   4431   { MaybeObject* maybe_result =
   4432         fast->CopyNormalized(mode, SHARED_NORMALIZED_MAP);
   4433     if (!maybe_result->ToObject(&result)) return maybe_result;
   4434   }
   4435   ASSERT(Map::cast(result)->is_dictionary_map());
   4436   set(index, result);
   4437   isolate->counters()->normalized_maps()->Increment();
   4438 
   4439   return result;
   4440 }
   4441 
   4442 
   4443 void NormalizedMapCache::Clear() {
   4444   int entries = length();
   4445   for (int i = 0; i != entries; i++) {
   4446     set_undefined(i);
   4447   }
   4448 }
   4449 
   4450 
   4451 void JSObject::UpdateMapCodeCache(Handle<JSObject> object,
   4452                                   Handle<Name> name,
   4453                                   Handle<Code> code) {
   4454   Isolate* isolate = object->GetIsolate();
   4455   CALL_HEAP_FUNCTION_VOID(isolate,
   4456                           object->UpdateMapCodeCache(*name, *code));
   4457 }
   4458 
   4459 
   4460 MaybeObject* JSObject::UpdateMapCodeCache(Name* name, Code* code) {
   4461   if (map()->is_shared()) {
   4462     // Fast case maps are never marked as shared.
   4463     ASSERT(!HasFastProperties());
   4464     // Replace the map with an identical copy that can be safely modified.
   4465     Object* obj;
   4466     { MaybeObject* maybe_obj = map()->CopyNormalized(KEEP_INOBJECT_PROPERTIES,
   4467                                                      UNIQUE_NORMALIZED_MAP);
   4468       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   4469     }
   4470     GetIsolate()->counters()->normalized_maps()->Increment();
   4471 
   4472     set_map(Map::cast(obj));
   4473   }
   4474   return map()->UpdateCodeCache(name, code);
   4475 }
   4476 
   4477 
   4478 void JSObject::NormalizeProperties(Handle<JSObject> object,
   4479                                    PropertyNormalizationMode mode,
   4480                                    int expected_additional_properties) {
   4481   CALL_HEAP_FUNCTION_VOID(object->GetIsolate(),
   4482                           object->NormalizeProperties(
   4483                               mode, expected_additional_properties));
   4484 }
   4485 
   4486 
   4487 MaybeObject* JSObject::NormalizeProperties(PropertyNormalizationMode mode,
   4488                                            int expected_additional_properties) {
   4489   if (!HasFastProperties()) return this;
   4490 
   4491   // The global object is always normalized.
   4492   ASSERT(!IsGlobalObject());
   4493   // JSGlobalProxy must never be normalized
   4494   ASSERT(!IsJSGlobalProxy());
   4495 
   4496   Map* map_of_this = map();
   4497 
   4498   // Allocate new content.
   4499   int real_size = map_of_this->NumberOfOwnDescriptors();
   4500   int property_count = real_size;
   4501   if (expected_additional_properties > 0) {
   4502     property_count += expected_additional_properties;
   4503   } else {
   4504     property_count += 2;  // Make space for two more properties.
   4505   }
   4506   NameDictionary* dictionary;
   4507   MaybeObject* maybe_dictionary =
   4508       NameDictionary::Allocate(GetHeap(), property_count);
   4509   if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
   4510 
   4511   DescriptorArray* descs = map_of_this->instance_descriptors();
   4512   for (int i = 0; i < real_size; i++) {
   4513     PropertyDetails details = descs->GetDetails(i);
   4514     switch (details.type()) {
   4515       case CONSTANT: {
   4516         PropertyDetails d = PropertyDetails(
   4517             details.attributes(), NORMAL, i + 1);
   4518         Object* value = descs->GetConstant(i);
   4519         MaybeObject* maybe_dictionary =
   4520             dictionary->Add(descs->GetKey(i), value, d);
   4521         if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
   4522         break;
   4523       }
   4524       case FIELD: {
   4525         PropertyDetails d =
   4526             PropertyDetails(details.attributes(), NORMAL, i + 1);
   4527         Object* value = RawFastPropertyAt(descs->GetFieldIndex(i));
   4528         MaybeObject* maybe_dictionary =
   4529             dictionary->Add(descs->GetKey(i), value, d);
   4530         if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
   4531         break;
   4532       }
   4533       case CALLBACKS: {
   4534         Object* value = descs->GetCallbacksObject(i);
   4535         PropertyDetails d = PropertyDetails(
   4536             details.attributes(), CALLBACKS, i + 1);
   4537         MaybeObject* maybe_dictionary =
   4538             dictionary->Add(descs->GetKey(i), value, d);
   4539         if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
   4540         break;
   4541       }
   4542       case INTERCEPTOR:
   4543         break;
   4544       case HANDLER:
   4545       case NORMAL:
   4546       case TRANSITION:
   4547       case NONEXISTENT:
   4548         UNREACHABLE();
   4549         break;
   4550     }
   4551   }
   4552 
   4553   Heap* current_heap = GetHeap();
   4554 
   4555   // Copy the next enumeration index from instance descriptor.
   4556   dictionary->SetNextEnumerationIndex(real_size + 1);
   4557 
   4558   Map* new_map;
   4559   MaybeObject* maybe_map =
   4560       current_heap->isolate()->context()->native_context()->
   4561       normalized_map_cache()->Get(this, mode);
   4562   if (!maybe_map->To(&new_map)) return maybe_map;
   4563   ASSERT(new_map->is_dictionary_map());
   4564 
   4565   // We have now successfully allocated all the necessary objects.
   4566   // Changes can now be made with the guarantee that all of them take effect.
   4567 
   4568   // Resize the object in the heap if necessary.
   4569   int new_instance_size = new_map->instance_size();
   4570   int instance_size_delta = map_of_this->instance_size() - new_instance_size;
   4571   ASSERT(instance_size_delta >= 0);
   4572   current_heap->CreateFillerObjectAt(this->address() + new_instance_size,
   4573                                      instance_size_delta);
   4574   if (Marking::IsBlack(Marking::MarkBitFrom(this))) {
   4575     MemoryChunk::IncrementLiveBytesFromMutator(this->address(),
   4576                                                -instance_size_delta);
   4577   }
   4578 
   4579   set_map(new_map);
   4580   map_of_this->NotifyLeafMapLayoutChange();
   4581 
   4582   set_properties(dictionary);
   4583 
   4584   current_heap->isolate()->counters()->props_to_dictionary()->Increment();
   4585 
   4586 #ifdef DEBUG
   4587   if (FLAG_trace_normalization) {
   4588     PrintF("Object properties have been normalized:\n");
   4589     Print();
   4590   }
   4591 #endif
   4592   return this;
   4593 }
   4594 
   4595 
   4596 void JSObject::TransformToFastProperties(Handle<JSObject> object,
   4597                                          int unused_property_fields) {
   4598   CALL_HEAP_FUNCTION_VOID(
   4599       object->GetIsolate(),
   4600       object->TransformToFastProperties(unused_property_fields));
   4601 }
   4602 
   4603 
   4604 MaybeObject* JSObject::TransformToFastProperties(int unused_property_fields) {
   4605   if (HasFastProperties()) return this;
   4606   ASSERT(!IsGlobalObject());
   4607   return property_dictionary()->
   4608       TransformPropertiesToFastFor(this, unused_property_fields);
   4609 }
   4610 
   4611 
   4612 static MUST_USE_RESULT MaybeObject* CopyFastElementsToDictionary(
   4613     Isolate* isolate,
   4614     FixedArrayBase* array,
   4615     int length,
   4616     SeededNumberDictionary* dictionary) {
   4617   Heap* heap = isolate->heap();
   4618   bool has_double_elements = array->IsFixedDoubleArray();
   4619   for (int i = 0; i < length; i++) {
   4620     Object* value = NULL;
   4621     if (has_double_elements) {
   4622       FixedDoubleArray* double_array = FixedDoubleArray::cast(array);
   4623       if (double_array->is_the_hole(i)) {
   4624         value = isolate->heap()->the_hole_value();
   4625       } else {
   4626         // Objects must be allocated in the old object space, since the
   4627         // overall number of HeapNumbers needed for the conversion might
   4628         // exceed the capacity of new space, and we would fail repeatedly
   4629         // trying to convert the FixedDoubleArray.
   4630         MaybeObject* maybe_value_object =
   4631             heap->AllocateHeapNumber(double_array->get_scalar(i), TENURED);
   4632         if (!maybe_value_object->ToObject(&value)) return maybe_value_object;
   4633       }
   4634     } else {
   4635       value = FixedArray::cast(array)->get(i);
   4636     }
   4637     if (!value->IsTheHole()) {
   4638       PropertyDetails details = PropertyDetails(NONE, NORMAL, 0);
   4639       MaybeObject* maybe_result =
   4640           dictionary->AddNumberEntry(i, value, details);
   4641       if (!maybe_result->To(&dictionary)) return maybe_result;
   4642     }
   4643   }
   4644   return dictionary;
   4645 }
   4646 
   4647 
   4648 Handle<SeededNumberDictionary> JSObject::NormalizeElements(
   4649     Handle<JSObject> object) {
   4650   CALL_HEAP_FUNCTION(object->GetIsolate(),
   4651                      object->NormalizeElements(),
   4652                      SeededNumberDictionary);
   4653 }
   4654 
   4655 
   4656 MaybeObject* JSObject::NormalizeElements() {
   4657   ASSERT(!HasExternalArrayElements());
   4658 
   4659   // Find the backing store.
   4660   FixedArrayBase* array = FixedArrayBase::cast(elements());
   4661   Map* old_map = array->map();
   4662   bool is_arguments =
   4663       (old_map == old_map->GetHeap()->non_strict_arguments_elements_map());
   4664   if (is_arguments) {
   4665     array = FixedArrayBase::cast(FixedArray::cast(array)->get(1));
   4666   }
   4667   if (array->IsDictionary()) return array;
   4668 
   4669   ASSERT(HasFastSmiOrObjectElements() ||
   4670          HasFastDoubleElements() ||
   4671          HasFastArgumentsElements());
   4672   // Compute the effective length and allocate a new backing store.
   4673   int length = IsJSArray()
   4674       ? Smi::cast(JSArray::cast(this)->length())->value()
   4675       : array->length();
   4676   int old_capacity = 0;
   4677   int used_elements = 0;
   4678   GetElementsCapacityAndUsage(&old_capacity, &used_elements);
   4679   SeededNumberDictionary* dictionary;
   4680   MaybeObject* maybe_dictionary =
   4681       SeededNumberDictionary::Allocate(GetHeap(), used_elements);
   4682   if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
   4683 
   4684   maybe_dictionary = CopyFastElementsToDictionary(
   4685       GetIsolate(), array, length, dictionary);
   4686   if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
   4687 
   4688   // Switch to using the dictionary as the backing storage for elements.
   4689   if (is_arguments) {
   4690     FixedArray::cast(elements())->set(1, dictionary);
   4691   } else {
   4692     // Set the new map first to satify the elements type assert in
   4693     // set_elements().
   4694     Map* new_map;
   4695     MaybeObject* maybe = GetElementsTransitionMap(GetIsolate(),
   4696                                                   DICTIONARY_ELEMENTS);
   4697     if (!maybe->To(&new_map)) return maybe;
   4698     set_map(new_map);
   4699     set_elements(dictionary);
   4700   }
   4701 
   4702   old_map->GetHeap()->isolate()->counters()->elements_to_dictionary()->
   4703       Increment();
   4704 
   4705 #ifdef DEBUG
   4706   if (FLAG_trace_normalization) {
   4707     PrintF("Object elements have been normalized:\n");
   4708     Print();
   4709   }
   4710 #endif
   4711 
   4712   ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements());
   4713   return dictionary;
   4714 }
   4715 
   4716 
   4717 Smi* JSReceiver::GenerateIdentityHash() {
   4718   Isolate* isolate = GetIsolate();
   4719 
   4720   int hash_value;
   4721   int attempts = 0;
   4722   do {
   4723     // Generate a random 32-bit hash value but limit range to fit
   4724     // within a smi.
   4725     hash_value = V8::RandomPrivate(isolate) & Smi::kMaxValue;
   4726     attempts++;
   4727   } while (hash_value == 0 && attempts < 30);
   4728   hash_value = hash_value != 0 ? hash_value : 1;  // never return 0
   4729 
   4730   return Smi::FromInt(hash_value);
   4731 }
   4732 
   4733 
   4734 MaybeObject* JSObject::SetIdentityHash(Smi* hash, CreationFlag flag) {
   4735   MaybeObject* maybe = SetHiddenProperty(GetHeap()->identity_hash_string(),
   4736                                          hash);
   4737   if (maybe->IsFailure()) return maybe;
   4738   return this;
   4739 }
   4740 
   4741 
   4742 int JSObject::GetIdentityHash(Handle<JSObject> obj) {
   4743   CALL_AND_RETRY_OR_DIE(obj->GetIsolate(),
   4744                         obj->GetIdentityHash(ALLOW_CREATION),
   4745                         return Smi::cast(__object__)->value(),
   4746                         return 0);
   4747 }
   4748 
   4749 
   4750 MaybeObject* JSObject::GetIdentityHash(CreationFlag flag) {
   4751   Object* stored_value = GetHiddenProperty(GetHeap()->identity_hash_string());
   4752   if (stored_value->IsSmi()) return stored_value;
   4753 
   4754   // Do not generate permanent identity hash code if not requested.
   4755   if (flag == OMIT_CREATION) return GetHeap()->undefined_value();
   4756 
   4757   Smi* hash = GenerateIdentityHash();
   4758   MaybeObject* result = SetHiddenProperty(GetHeap()->identity_hash_string(),
   4759                                           hash);
   4760   if (result->IsFailure()) return result;
   4761   if (result->ToObjectUnchecked()->IsUndefined()) {
   4762     // Trying to get hash of detached proxy.
   4763     return Smi::FromInt(0);
   4764   }
   4765   return hash;
   4766 }
   4767 
   4768 
   4769 MaybeObject* JSProxy::GetIdentityHash(CreationFlag flag) {
   4770   Object* hash = this->hash();
   4771   if (!hash->IsSmi() && flag == ALLOW_CREATION) {
   4772     hash = GenerateIdentityHash();
   4773     set_hash(hash);
   4774   }
   4775   return hash;
   4776 }
   4777 
   4778 
   4779 Object* JSObject::GetHiddenProperty(Name* key) {
   4780   ASSERT(key->IsUniqueName());
   4781   if (IsJSGlobalProxy()) {
   4782     // For a proxy, use the prototype as target object.
   4783     Object* proxy_parent = GetPrototype();
   4784     // If the proxy is detached, return undefined.
   4785     if (proxy_parent->IsNull()) return GetHeap()->the_hole_value();
   4786     ASSERT(proxy_parent->IsJSGlobalObject());
   4787     return JSObject::cast(proxy_parent)->GetHiddenProperty(key);
   4788   }
   4789   ASSERT(!IsJSGlobalProxy());
   4790   MaybeObject* hidden_lookup =
   4791       GetHiddenPropertiesHashTable(ONLY_RETURN_INLINE_VALUE);
   4792   Object* inline_value = hidden_lookup->ToObjectUnchecked();
   4793 
   4794   if (inline_value->IsSmi()) {
   4795     // Handle inline-stored identity hash.
   4796     if (key == GetHeap()->identity_hash_string()) {
   4797       return inline_value;
   4798     } else {
   4799       return GetHeap()->the_hole_value();
   4800     }
   4801   }
   4802 
   4803   if (inline_value->IsUndefined()) return GetHeap()->the_hole_value();
   4804 
   4805   ObjectHashTable* hashtable = ObjectHashTable::cast(inline_value);
   4806   Object* entry = hashtable->Lookup(key);
   4807   return entry;
   4808 }
   4809 
   4810 
   4811 Handle<Object> JSObject::SetHiddenProperty(Handle<JSObject> obj,
   4812                                            Handle<Name> key,
   4813                                            Handle<Object> value) {
   4814   CALL_HEAP_FUNCTION(obj->GetIsolate(),
   4815                      obj->SetHiddenProperty(*key, *value),
   4816                      Object);
   4817 }
   4818 
   4819 
   4820 MaybeObject* JSObject::SetHiddenProperty(Name* key, Object* value) {
   4821   ASSERT(key->IsUniqueName());
   4822   if (IsJSGlobalProxy()) {
   4823     // For a proxy, use the prototype as target object.
   4824     Object* proxy_parent = GetPrototype();
   4825     // If the proxy is detached, return undefined.
   4826     if (proxy_parent->IsNull()) return GetHeap()->undefined_value();
   4827     ASSERT(proxy_parent->IsJSGlobalObject());
   4828     return JSObject::cast(proxy_parent)->SetHiddenProperty(key, value);
   4829   }
   4830   ASSERT(!IsJSGlobalProxy());
   4831   MaybeObject* hidden_lookup =
   4832       GetHiddenPropertiesHashTable(ONLY_RETURN_INLINE_VALUE);
   4833   Object* inline_value = hidden_lookup->ToObjectUnchecked();
   4834 
   4835   // If there is no backing store yet, store the identity hash inline.
   4836   if (value->IsSmi() &&
   4837       key == GetHeap()->identity_hash_string() &&
   4838       (inline_value->IsUndefined() || inline_value->IsSmi())) {
   4839     return SetHiddenPropertiesHashTable(value);
   4840   }
   4841 
   4842   hidden_lookup = GetHiddenPropertiesHashTable(CREATE_NEW_IF_ABSENT);
   4843   ObjectHashTable* hashtable;
   4844   if (!hidden_lookup->To(&hashtable)) return hidden_lookup;
   4845 
   4846   // If it was found, check if the key is already in the dictionary.
   4847   MaybeObject* insert_result = hashtable->Put(key, value);
   4848   ObjectHashTable* new_table;
   4849   if (!insert_result->To(&new_table)) return insert_result;
   4850   if (new_table != hashtable) {
   4851     // If adding the key expanded the dictionary (i.e., Add returned a new
   4852     // dictionary), store it back to the object.
   4853     MaybeObject* store_result = SetHiddenPropertiesHashTable(new_table);
   4854     if (store_result->IsFailure()) return store_result;
   4855   }
   4856   // Return this to mark success.
   4857   return this;
   4858 }
   4859 
   4860 
   4861 void JSObject::DeleteHiddenProperty(Name* key) {
   4862   ASSERT(key->IsUniqueName());
   4863   if (IsJSGlobalProxy()) {
   4864     // For a proxy, use the prototype as target object.
   4865     Object* proxy_parent = GetPrototype();
   4866     // If the proxy is detached, return immediately.
   4867     if (proxy_parent->IsNull()) return;
   4868     ASSERT(proxy_parent->IsJSGlobalObject());
   4869     JSObject::cast(proxy_parent)->DeleteHiddenProperty(key);
   4870     return;
   4871   }
   4872   ASSERT(!IsJSGlobalProxy());
   4873   MaybeObject* hidden_lookup =
   4874       GetHiddenPropertiesHashTable(ONLY_RETURN_INLINE_VALUE);
   4875   Object* inline_value = hidden_lookup->ToObjectUnchecked();
   4876 
   4877   // We never delete (inline-stored) identity hashes.
   4878   ASSERT(key != GetHeap()->identity_hash_string());
   4879   if (inline_value->IsUndefined() || inline_value->IsSmi()) return;
   4880 
   4881   ObjectHashTable* hashtable = ObjectHashTable::cast(inline_value);
   4882   MaybeObject* delete_result = hashtable->Put(key, GetHeap()->the_hole_value());
   4883   USE(delete_result);
   4884   ASSERT(!delete_result->IsFailure());  // Delete does not cause GC.
   4885 }
   4886 
   4887 
   4888 bool JSObject::HasHiddenProperties() {
   4889   return GetPropertyAttributePostInterceptor(this,
   4890                                              GetHeap()->hidden_string(),
   4891                                              false) != ABSENT;
   4892 }
   4893 
   4894 
   4895 MaybeObject* JSObject::GetHiddenPropertiesHashTable(
   4896     InitializeHiddenProperties init_option) {
   4897   ASSERT(!IsJSGlobalProxy());
   4898   Object* inline_value;
   4899   if (HasFastProperties()) {
   4900     // If the object has fast properties, check whether the first slot
   4901     // in the descriptor array matches the hidden string. Since the
   4902     // hidden strings hash code is zero (and no other name has hash
   4903     // code zero) it will always occupy the first entry if present.
   4904     DescriptorArray* descriptors = this->map()->instance_descriptors();
   4905     if (descriptors->number_of_descriptors() > 0) {
   4906       int sorted_index = descriptors->GetSortedKeyIndex(0);
   4907       if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_string() &&
   4908           sorted_index < map()->NumberOfOwnDescriptors()) {
   4909         ASSERT(descriptors->GetType(sorted_index) == FIELD);
   4910         MaybeObject* maybe_value = this->FastPropertyAt(
   4911             descriptors->GetDetails(sorted_index).representation(),
   4912             descriptors->GetFieldIndex(sorted_index));
   4913         if (!maybe_value->To(&inline_value)) return maybe_value;
   4914       } else {
   4915         inline_value = GetHeap()->undefined_value();
   4916       }
   4917     } else {
   4918       inline_value = GetHeap()->undefined_value();
   4919     }
   4920   } else {
   4921     PropertyAttributes attributes;
   4922     // You can't install a getter on a property indexed by the hidden string,
   4923     // so we can be sure that GetLocalPropertyPostInterceptor returns a real
   4924     // object.
   4925     inline_value =
   4926         GetLocalPropertyPostInterceptor(this,
   4927                                         GetHeap()->hidden_string(),
   4928                                         &attributes)->ToObjectUnchecked();
   4929   }
   4930 
   4931   if (init_option == ONLY_RETURN_INLINE_VALUE ||
   4932       inline_value->IsHashTable()) {
   4933     return inline_value;
   4934   }
   4935 
   4936   ObjectHashTable* hashtable;
   4937   static const int kInitialCapacity = 4;
   4938   MaybeObject* maybe_obj =
   4939       ObjectHashTable::Allocate(GetHeap(),
   4940                                 kInitialCapacity,
   4941                                 ObjectHashTable::USE_CUSTOM_MINIMUM_CAPACITY);
   4942   if (!maybe_obj->To<ObjectHashTable>(&hashtable)) return maybe_obj;
   4943 
   4944   if (inline_value->IsSmi()) {
   4945     // We were storing the identity hash inline and now allocated an actual
   4946     // dictionary.  Put the identity hash into the new dictionary.
   4947     MaybeObject* insert_result =
   4948         hashtable->Put(GetHeap()->identity_hash_string(), inline_value);
   4949     ObjectHashTable* new_table;
   4950     if (!insert_result->To(&new_table)) return insert_result;
   4951     // We expect no resizing for the first insert.
   4952     ASSERT_EQ(hashtable, new_table);
   4953   }
   4954 
   4955   MaybeObject* store_result =
   4956       SetPropertyPostInterceptor(GetHeap()->hidden_string(),
   4957                                  hashtable,
   4958                                  DONT_ENUM,
   4959                                  kNonStrictMode,
   4960                                  OMIT_EXTENSIBILITY_CHECK,
   4961                                  FORCE_FIELD);
   4962   if (store_result->IsFailure()) return store_result;
   4963   return hashtable;
   4964 }
   4965 
   4966 
   4967 MaybeObject* JSObject::SetHiddenPropertiesHashTable(Object* value) {
   4968   ASSERT(!IsJSGlobalProxy());
   4969   // We can store the identity hash inline iff there is no backing store
   4970   // for hidden properties yet.
   4971   ASSERT(HasHiddenProperties() != value->IsSmi());
   4972   if (HasFastProperties()) {
   4973     // If the object has fast properties, check whether the first slot
   4974     // in the descriptor array matches the hidden string. Since the
   4975     // hidden strings hash code is zero (and no other name has hash
   4976     // code zero) it will always occupy the first entry if present.
   4977     DescriptorArray* descriptors = this->map()->instance_descriptors();
   4978     if (descriptors->number_of_descriptors() > 0) {
   4979       int sorted_index = descriptors->GetSortedKeyIndex(0);
   4980       if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_string() &&
   4981           sorted_index < map()->NumberOfOwnDescriptors()) {
   4982         ASSERT(descriptors->GetType(sorted_index) == FIELD);
   4983         FastPropertyAtPut(descriptors->GetFieldIndex(sorted_index), value);
   4984         return this;
   4985       }
   4986     }
   4987   }
   4988   MaybeObject* store_result =
   4989       SetPropertyPostInterceptor(GetHeap()->hidden_string(),
   4990                                  value,
   4991                                  DONT_ENUM,
   4992                                  kNonStrictMode,
   4993                                  OMIT_EXTENSIBILITY_CHECK,
   4994                                  FORCE_FIELD);
   4995   if (store_result->IsFailure()) return store_result;
   4996   return this;
   4997 }
   4998 
   4999 
   5000 Handle<Object> JSObject::DeletePropertyPostInterceptor(Handle<JSObject> object,
   5001                                                        Handle<Name> name,
   5002                                                        DeleteMode mode) {
   5003   // Check local property, ignore interceptor.
   5004   Isolate* isolate = object->GetIsolate();
   5005   LookupResult result(isolate);
   5006   object->LocalLookupRealNamedProperty(*name, &result);
   5007   if (!result.IsFound()) return isolate->factory()->true_value();
   5008 
   5009   // Normalize object if needed.
   5010   NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0);
   5011 
   5012   return DeleteNormalizedProperty(object, name, mode);
   5013 }
   5014 
   5015 
   5016 Handle<Object> JSObject::DeletePropertyWithInterceptor(Handle<JSObject> object,
   5017                                                        Handle<Name> name) {
   5018   Isolate* isolate = object->GetIsolate();
   5019 
   5020   // TODO(rossberg): Support symbols in the API.
   5021   if (name->IsSymbol()) return isolate->factory()->false_value();
   5022 
   5023   Handle<InterceptorInfo> interceptor(object->GetNamedInterceptor());
   5024   if (!interceptor->deleter()->IsUndefined()) {
   5025     v8::NamedPropertyDeleter deleter =
   5026         v8::ToCData<v8::NamedPropertyDeleter>(interceptor->deleter());
   5027     LOG(isolate,
   5028         ApiNamedPropertyAccess("interceptor-named-delete", *object, *name));
   5029     PropertyCallbackArguments args(
   5030         isolate, interceptor->data(), *object, *object);
   5031     v8::Handle<v8::Boolean> result =
   5032         args.Call(deleter, v8::Utils::ToLocal(Handle<String>::cast(name)));
   5033     RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
   5034     if (!result.IsEmpty()) {
   5035       ASSERT(result->IsBoolean());
   5036       Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
   5037       result_internal->VerifyApiCallResultType();
   5038       // Rebox CustomArguments::kReturnValueOffset before returning.
   5039       return handle(*result_internal, isolate);
   5040     }
   5041   }
   5042   Handle<Object> result =
   5043       DeletePropertyPostInterceptor(object, name, NORMAL_DELETION);
   5044   RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
   5045   return result;
   5046 }
   5047 
   5048 
   5049 MaybeObject* JSObject::DeleteElementWithInterceptor(uint32_t index) {
   5050   Isolate* isolate = GetIsolate();
   5051   Heap* heap = isolate->heap();
   5052   // Make sure that the top context does not change when doing
   5053   // callbacks or interceptor calls.
   5054   AssertNoContextChange ncc;
   5055   HandleScope scope(isolate);
   5056   Handle<InterceptorInfo> interceptor(GetIndexedInterceptor());
   5057   if (interceptor->deleter()->IsUndefined()) return heap->false_value();
   5058   v8::IndexedPropertyDeleter deleter =
   5059       v8::ToCData<v8::IndexedPropertyDeleter>(interceptor->deleter());
   5060   Handle<JSObject> this_handle(this);
   5061   LOG(isolate,
   5062       ApiIndexedPropertyAccess("interceptor-indexed-delete", this, index));
   5063   PropertyCallbackArguments args(isolate, interceptor->data(), this, this);
   5064   v8::Handle<v8::Boolean> result = args.Call(deleter, index);
   5065   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   5066   if (!result.IsEmpty()) {
   5067     ASSERT(result->IsBoolean());
   5068     Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
   5069     result_internal->VerifyApiCallResultType();
   5070     return *result_internal;
   5071   }
   5072   MaybeObject* raw_result = this_handle->GetElementsAccessor()->Delete(
   5073       *this_handle,
   5074       index,
   5075       NORMAL_DELETION);
   5076   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   5077   return raw_result;
   5078 }
   5079 
   5080 
   5081 Handle<Object> JSObject::DeleteElement(Handle<JSObject> obj,
   5082                                        uint32_t index,
   5083                                        DeleteMode mode) {
   5084   CALL_HEAP_FUNCTION(obj->GetIsolate(),
   5085                      obj->DeleteElement(index, mode),
   5086                      Object);
   5087 }
   5088 
   5089 
   5090 MaybeObject* JSObject::DeleteElement(uint32_t index, DeleteMode mode) {
   5091   Isolate* isolate = GetIsolate();
   5092   // Check access rights if needed.
   5093   if (IsAccessCheckNeeded() &&
   5094       !isolate->MayIndexedAccess(this, index, v8::ACCESS_DELETE)) {
   5095     isolate->ReportFailedAccessCheck(this, v8::ACCESS_DELETE);
   5096     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   5097     return isolate->heap()->false_value();
   5098   }
   5099 
   5100   if (IsStringObjectWithCharacterAt(index)) {
   5101     if (mode == STRICT_DELETION) {
   5102       // Deleting a non-configurable property in strict mode.
   5103       HandleScope scope(isolate);
   5104       Handle<Object> holder(this, isolate);
   5105       Handle<Object> name = isolate->factory()->NewNumberFromUint(index);
   5106       Handle<Object> args[2] = { name, holder };
   5107       Handle<Object> error =
   5108           isolate->factory()->NewTypeError("strict_delete_property",
   5109                                            HandleVector(args, 2));
   5110       return isolate->Throw(*error);
   5111     }
   5112     return isolate->heap()->false_value();
   5113   }
   5114 
   5115   if (IsJSGlobalProxy()) {
   5116     Object* proto = GetPrototype();
   5117     if (proto->IsNull()) return isolate->heap()->false_value();
   5118     ASSERT(proto->IsJSGlobalObject());
   5119     return JSGlobalObject::cast(proto)->DeleteElement(index, mode);
   5120   }
   5121 
   5122   // From this point on everything needs to be handlified.
   5123   HandleScope scope(isolate);
   5124   Handle<JSObject> self(this);
   5125 
   5126   Handle<Object> old_value;
   5127   bool should_enqueue_change_record = false;
   5128   if (FLAG_harmony_observation && self->map()->is_observed()) {
   5129     should_enqueue_change_record = self->HasLocalElement(index);
   5130     if (should_enqueue_change_record) {
   5131       old_value = self->GetLocalElementAccessorPair(index) != NULL
   5132           ? Handle<Object>::cast(isolate->factory()->the_hole_value())
   5133           : Object::GetElement(self, index);
   5134     }
   5135   }
   5136 
   5137   MaybeObject* result;
   5138   // Skip interceptor if forcing deletion.
   5139   if (self->HasIndexedInterceptor() && mode != FORCE_DELETION) {
   5140     result = self->DeleteElementWithInterceptor(index);
   5141   } else {
   5142     result = self->GetElementsAccessor()->Delete(*self, index, mode);
   5143   }
   5144 
   5145   Handle<Object> hresult;
   5146   if (!result->ToHandle(&hresult, isolate)) return result;
   5147 
   5148   if (should_enqueue_change_record && !self->HasLocalElement(index)) {
   5149     Handle<String> name = isolate->factory()->Uint32ToString(index);
   5150     EnqueueChangeRecord(self, "deleted", name, old_value);
   5151   }
   5152 
   5153   return *hresult;
   5154 }
   5155 
   5156 
   5157 Handle<Object> JSObject::DeleteProperty(Handle<JSObject> object,
   5158                                         Handle<Name> name,
   5159                                         DeleteMode mode) {
   5160   Isolate* isolate = object->GetIsolate();
   5161   // ECMA-262, 3rd, 8.6.2.5
   5162   ASSERT(name->IsName());
   5163 
   5164   // Check access rights if needed.
   5165   if (object->IsAccessCheckNeeded() &&
   5166       !isolate->MayNamedAccess(*object, *name, v8::ACCESS_DELETE)) {
   5167     isolate->ReportFailedAccessCheck(*object, v8::ACCESS_DELETE);
   5168     RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
   5169     return isolate->factory()->false_value();
   5170   }
   5171 
   5172   if (object->IsJSGlobalProxy()) {
   5173     Object* proto = object->GetPrototype();
   5174     if (proto->IsNull()) return isolate->factory()->false_value();
   5175     ASSERT(proto->IsJSGlobalObject());
   5176     return JSGlobalObject::DeleteProperty(
   5177         handle(JSGlobalObject::cast(proto)), name, mode);
   5178   }
   5179 
   5180   uint32_t index = 0;
   5181   if (name->AsArrayIndex(&index)) {
   5182     return DeleteElement(object, index, mode);
   5183   }
   5184 
   5185   LookupResult lookup(isolate);
   5186   object->LocalLookup(*name, &lookup, true);
   5187   if (!lookup.IsFound()) return isolate->factory()->true_value();
   5188   // Ignore attributes if forcing a deletion.
   5189   if (lookup.IsDontDelete() && mode != FORCE_DELETION) {
   5190     if (mode == STRICT_DELETION) {
   5191       // Deleting a non-configurable property in strict mode.
   5192       Handle<Object> args[2] = { name, object };
   5193       Handle<Object> error = isolate->factory()->NewTypeError(
   5194           "strict_delete_property", HandleVector(args, ARRAY_SIZE(args)));
   5195       isolate->Throw(*error);
   5196       return Handle<Object>();
   5197     }
   5198     return isolate->factory()->false_value();
   5199   }
   5200 
   5201   Handle<Object> old_value = isolate->factory()->the_hole_value();
   5202   bool is_observed = FLAG_harmony_observation && object->map()->is_observed();
   5203   if (is_observed && lookup.IsDataProperty()) {
   5204     old_value = Object::GetProperty(object, name);
   5205   }
   5206   Handle<Object> result;
   5207 
   5208   // Check for interceptor.
   5209   if (lookup.IsInterceptor()) {
   5210     // Skip interceptor if forcing a deletion.
   5211     if (mode == FORCE_DELETION) {
   5212       result = DeletePropertyPostInterceptor(object, name, mode);
   5213     } else {
   5214       result = DeletePropertyWithInterceptor(object, name);
   5215     }
   5216   } else {
   5217     // Normalize object if needed.
   5218     NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0);
   5219     // Make sure the properties are normalized before removing the entry.
   5220     result = DeleteNormalizedProperty(object, name, mode);
   5221   }
   5222 
   5223   if (is_observed && !object->HasLocalProperty(*name)) {
   5224     EnqueueChangeRecord(object, "deleted", name, old_value);
   5225   }
   5226 
   5227   return result;
   5228 }
   5229 
   5230 
   5231 Handle<Object> JSReceiver::DeleteElement(Handle<JSReceiver> object,
   5232                                          uint32_t index,
   5233                                          DeleteMode mode) {
   5234   if (object->IsJSProxy()) {
   5235     return JSProxy::DeleteElementWithHandler(
   5236         Handle<JSProxy>::cast(object), index, mode);
   5237   }
   5238   return JSObject::DeleteElement(Handle<JSObject>::cast(object), index, mode);
   5239 }
   5240 
   5241 
   5242 Handle<Object> JSReceiver::DeleteProperty(Handle<JSReceiver> object,
   5243                                           Handle<Name> name,
   5244                                           DeleteMode mode) {
   5245   if (object->IsJSProxy()) {
   5246     return JSProxy::DeletePropertyWithHandler(
   5247         Handle<JSProxy>::cast(object), name, mode);
   5248   }
   5249   return JSObject::DeleteProperty(Handle<JSObject>::cast(object), name, mode);
   5250 }
   5251 
   5252 
   5253 bool JSObject::ReferencesObjectFromElements(FixedArray* elements,
   5254                                             ElementsKind kind,
   5255                                             Object* object) {
   5256   ASSERT(IsFastObjectElementsKind(kind) ||
   5257          kind == DICTIONARY_ELEMENTS);
   5258   if (IsFastObjectElementsKind(kind)) {
   5259     int length = IsJSArray()
   5260         ? Smi::cast(JSArray::cast(this)->length())->value()
   5261         : elements->length();
   5262     for (int i = 0; i < length; ++i) {
   5263       Object* element = elements->get(i);
   5264       if (!element->IsTheHole() && element == object) return true;
   5265     }
   5266   } else {
   5267     Object* key =
   5268         SeededNumberDictionary::cast(elements)->SlowReverseLookup(object);
   5269     if (!key->IsUndefined()) return true;
   5270   }
   5271   return false;
   5272 }
   5273 
   5274 
   5275 // Check whether this object references another object.
   5276 bool JSObject::ReferencesObject(Object* obj) {
   5277   Map* map_of_this = map();
   5278   Heap* heap = GetHeap();
   5279   DisallowHeapAllocation no_allocation;
   5280 
   5281   // Is the object the constructor for this object?
   5282   if (map_of_this->constructor() == obj) {
   5283     return true;
   5284   }
   5285 
   5286   // Is the object the prototype for this object?
   5287   if (map_of_this->prototype() == obj) {
   5288     return true;
   5289   }
   5290 
   5291   // Check if the object is among the named properties.
   5292   Object* key = SlowReverseLookup(obj);
   5293   if (!key->IsUndefined()) {
   5294     return true;
   5295   }
   5296 
   5297   // Check if the object is among the indexed properties.
   5298   ElementsKind kind = GetElementsKind();
   5299   switch (kind) {
   5300     case EXTERNAL_PIXEL_ELEMENTS:
   5301     case EXTERNAL_BYTE_ELEMENTS:
   5302     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
   5303     case EXTERNAL_SHORT_ELEMENTS:
   5304     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
   5305     case EXTERNAL_INT_ELEMENTS:
   5306     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
   5307     case EXTERNAL_FLOAT_ELEMENTS:
   5308     case EXTERNAL_DOUBLE_ELEMENTS:
   5309     case FAST_DOUBLE_ELEMENTS:
   5310     case FAST_HOLEY_DOUBLE_ELEMENTS:
   5311       // Raw pixels and external arrays do not reference other
   5312       // objects.
   5313       break;
   5314     case FAST_SMI_ELEMENTS:
   5315     case FAST_HOLEY_SMI_ELEMENTS:
   5316       break;
   5317     case FAST_ELEMENTS:
   5318     case FAST_HOLEY_ELEMENTS:
   5319     case DICTIONARY_ELEMENTS: {
   5320       FixedArray* elements = FixedArray::cast(this->elements());
   5321       if (ReferencesObjectFromElements(elements, kind, obj)) return true;
   5322       break;
   5323     }
   5324     case NON_STRICT_ARGUMENTS_ELEMENTS: {
   5325       FixedArray* parameter_map = FixedArray::cast(elements());
   5326       // Check the mapped parameters.
   5327       int length = parameter_map->length();
   5328       for (int i = 2; i < length; ++i) {
   5329         Object* value = parameter_map->get(i);
   5330         if (!value->IsTheHole() && value == obj) return true;
   5331       }
   5332       // Check the arguments.
   5333       FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
   5334       kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS :
   5335           FAST_HOLEY_ELEMENTS;
   5336       if (ReferencesObjectFromElements(arguments, kind, obj)) return true;
   5337       break;
   5338     }
   5339   }
   5340 
   5341   // For functions check the context.
   5342   if (IsJSFunction()) {
   5343     // Get the constructor function for arguments array.
   5344     JSObject* arguments_boilerplate =
   5345         heap->isolate()->context()->native_context()->
   5346             arguments_boilerplate();
   5347     JSFunction* arguments_function =
   5348         JSFunction::cast(arguments_boilerplate->map()->constructor());
   5349 
   5350     // Get the context and don't check if it is the native context.
   5351     JSFunction* f = JSFunction::cast(this);
   5352     Context* context = f->context();
   5353     if (context->IsNativeContext()) {
   5354       return false;
   5355     }
   5356 
   5357     // Check the non-special context slots.
   5358     for (int i = Context::MIN_CONTEXT_SLOTS; i < context->length(); i++) {
   5359       // Only check JS objects.
   5360       if (context->get(i)->IsJSObject()) {
   5361         JSObject* ctxobj = JSObject::cast(context->get(i));
   5362         // If it is an arguments array check the content.
   5363         if (ctxobj->map()->constructor() == arguments_function) {
   5364           if (ctxobj->ReferencesObject(obj)) {
   5365             return true;
   5366           }
   5367         } else if (ctxobj == obj) {
   5368           return true;
   5369         }
   5370       }
   5371     }
   5372 
   5373     // Check the context extension (if any) if it can have references.
   5374     if (context->has_extension() && !context->IsCatchContext()) {
   5375       return JSObject::cast(context->extension())->ReferencesObject(obj);
   5376     }
   5377   }
   5378 
   5379   // No references to object.
   5380   return false;
   5381 }
   5382 
   5383 
   5384 Handle<Object> JSObject::PreventExtensions(Handle<JSObject> object) {
   5385   CALL_HEAP_FUNCTION(object->GetIsolate(), object->PreventExtensions(), Object);
   5386 }
   5387 
   5388 
   5389 MaybeObject* JSObject::PreventExtensions() {
   5390   Isolate* isolate = GetIsolate();
   5391   if (IsAccessCheckNeeded() &&
   5392       !isolate->MayNamedAccess(this,
   5393                                isolate->heap()->undefined_value(),
   5394                                v8::ACCESS_KEYS)) {
   5395     isolate->ReportFailedAccessCheck(this, v8::ACCESS_KEYS);
   5396     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   5397     return isolate->heap()->false_value();
   5398   }
   5399 
   5400   if (IsJSGlobalProxy()) {
   5401     Object* proto = GetPrototype();
   5402     if (proto->IsNull()) return this;
   5403     ASSERT(proto->IsJSGlobalObject());
   5404     return JSObject::cast(proto)->PreventExtensions();
   5405   }
   5406 
   5407   // It's not possible to seal objects with external array elements
   5408   if (HasExternalArrayElements()) {
   5409     HandleScope scope(isolate);
   5410     Handle<Object> object(this, isolate);
   5411     Handle<Object> error  =
   5412         isolate->factory()->NewTypeError(
   5413             "cant_prevent_ext_external_array_elements",
   5414             HandleVector(&object, 1));
   5415     return isolate->Throw(*error);
   5416   }
   5417 
   5418   // If there are fast elements we normalize.
   5419   SeededNumberDictionary* dictionary = NULL;
   5420   { MaybeObject* maybe = NormalizeElements();
   5421     if (!maybe->To<SeededNumberDictionary>(&dictionary)) return maybe;
   5422   }
   5423   ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements());
   5424   // Make sure that we never go back to fast case.
   5425   dictionary->set_requires_slow_elements();
   5426 
   5427   // Do a map transition, other objects with this map may still
   5428   // be extensible.
   5429   // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps.
   5430   Map* new_map;
   5431   MaybeObject* maybe = map()->Copy();
   5432   if (!maybe->To(&new_map)) return maybe;
   5433 
   5434   new_map->set_is_extensible(false);
   5435   set_map(new_map);
   5436   ASSERT(!map()->is_extensible());
   5437   return new_map;
   5438 }
   5439 
   5440 
   5441 template<typename Dictionary>
   5442 static void FreezeDictionary(Dictionary* dictionary) {
   5443   int capacity = dictionary->Capacity();
   5444   for (int i = 0; i < capacity; i++) {
   5445     Object* k = dictionary->KeyAt(i);
   5446     if (dictionary->IsKey(k)) {
   5447       PropertyDetails details = dictionary->DetailsAt(i);
   5448       int attrs = DONT_DELETE;
   5449       // READ_ONLY is an invalid attribute for JS setters/getters.
   5450       if (details.type() != CALLBACKS ||
   5451           !dictionary->ValueAt(i)->IsAccessorPair()) {
   5452         attrs |= READ_ONLY;
   5453       }
   5454       details = details.CopyAddAttributes(
   5455           static_cast<PropertyAttributes>(attrs));
   5456       dictionary->DetailsAtPut(i, details);
   5457     }
   5458   }
   5459 }
   5460 
   5461 
   5462 MUST_USE_RESULT MaybeObject* JSObject::Freeze(Isolate* isolate) {
   5463   // Freezing non-strict arguments should be handled elsewhere.
   5464   ASSERT(!HasNonStrictArgumentsElements());
   5465 
   5466   Heap* heap = isolate->heap();
   5467 
   5468   if (map()->is_frozen()) return this;
   5469 
   5470   if (IsAccessCheckNeeded() &&
   5471       !isolate->MayNamedAccess(this,
   5472                                heap->undefined_value(),
   5473                                v8::ACCESS_KEYS)) {
   5474     isolate->ReportFailedAccessCheck(this, v8::ACCESS_KEYS);
   5475     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   5476     return heap->false_value();
   5477   }
   5478 
   5479   if (IsJSGlobalProxy()) {
   5480     Object* proto = GetPrototype();
   5481     if (proto->IsNull()) return this;
   5482     ASSERT(proto->IsJSGlobalObject());
   5483     return JSObject::cast(proto)->Freeze(isolate);
   5484   }
   5485 
   5486   // It's not possible to freeze objects with external array elements
   5487   if (HasExternalArrayElements()) {
   5488     HandleScope scope(isolate);
   5489     Handle<Object> object(this, isolate);
   5490     Handle<Object> error  =
   5491         isolate->factory()->NewTypeError(
   5492             "cant_prevent_ext_external_array_elements",
   5493             HandleVector(&object, 1));
   5494     return isolate->Throw(*error);
   5495   }
   5496 
   5497   SeededNumberDictionary* new_element_dictionary = NULL;
   5498   if (!elements()->IsDictionary()) {
   5499     int length = IsJSArray()
   5500         ? Smi::cast(JSArray::cast(this)->length())->value()
   5501         : elements()->length();
   5502     if (length > 0) {
   5503       int capacity = 0;
   5504       int used = 0;
   5505       GetElementsCapacityAndUsage(&capacity, &used);
   5506       MaybeObject* maybe_dict = SeededNumberDictionary::Allocate(heap, used);
   5507       if (!maybe_dict->To(&new_element_dictionary)) return maybe_dict;
   5508 
   5509       // Move elements to a dictionary; avoid calling NormalizeElements to avoid
   5510       // unnecessary transitions.
   5511       maybe_dict = CopyFastElementsToDictionary(isolate, elements(), length,
   5512                                                 new_element_dictionary);
   5513       if (!maybe_dict->To(&new_element_dictionary)) return maybe_dict;
   5514     } else {
   5515       // No existing elements, use a pre-allocated empty backing store
   5516       new_element_dictionary = heap->empty_slow_element_dictionary();
   5517     }
   5518   }
   5519 
   5520   LookupResult result(isolate);
   5521   map()->LookupTransition(this, heap->frozen_symbol(), &result);
   5522   if (result.IsTransition()) {
   5523     Map* transition_map = result.GetTransitionTarget();
   5524     ASSERT(transition_map->has_dictionary_elements());
   5525     ASSERT(transition_map->is_frozen());
   5526     ASSERT(!transition_map->is_extensible());
   5527     set_map(transition_map);
   5528   } else if (HasFastProperties() && map()->CanHaveMoreTransitions()) {
   5529     // Create a new descriptor array with fully-frozen properties
   5530     int num_descriptors = map()->NumberOfOwnDescriptors();
   5531     DescriptorArray* new_descriptors;
   5532     MaybeObject* maybe_descriptors =
   5533         map()->instance_descriptors()->CopyUpToAddAttributes(num_descriptors,
   5534                                                              FROZEN);
   5535     if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
   5536 
   5537     Map* new_map;
   5538     MaybeObject* maybe_new_map = map()->CopyReplaceDescriptors(
   5539         new_descriptors, INSERT_TRANSITION, heap->frozen_symbol());
   5540     if (!maybe_new_map->To(&new_map)) return maybe_new_map;
   5541     new_map->freeze();
   5542     new_map->set_is_extensible(false);
   5543     new_map->set_elements_kind(DICTIONARY_ELEMENTS);
   5544     set_map(new_map);
   5545   } else {
   5546     // Slow path: need to normalize properties for safety
   5547     MaybeObject* maybe = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
   5548     if (maybe->IsFailure()) return maybe;
   5549 
   5550     // Create a new map, since other objects with this map may be extensible.
   5551     // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps.
   5552     Map* new_map;
   5553     MaybeObject* maybe_copy = map()->Copy();
   5554     if (!maybe_copy->To(&new_map)) return maybe_copy;
   5555     new_map->freeze();
   5556     new_map->set_is_extensible(false);
   5557     new_map->set_elements_kind(DICTIONARY_ELEMENTS);
   5558     set_map(new_map);
   5559 
   5560     // Freeze dictionary-mode properties
   5561     FreezeDictionary(property_dictionary());
   5562   }
   5563 
   5564   ASSERT(map()->has_dictionary_elements());
   5565   if (new_element_dictionary != NULL) {
   5566     set_elements(new_element_dictionary);
   5567   }
   5568 
   5569   if (elements() != heap->empty_slow_element_dictionary()) {
   5570     SeededNumberDictionary* dictionary = element_dictionary();
   5571     // Make sure we never go back to the fast case
   5572     dictionary->set_requires_slow_elements();
   5573     // Freeze all elements in the dictionary
   5574     FreezeDictionary(dictionary);
   5575   }
   5576 
   5577   return this;
   5578 }
   5579 
   5580 
   5581 MUST_USE_RESULT MaybeObject* JSObject::SetObserved(Isolate* isolate) {
   5582   if (map()->is_observed())
   5583     return isolate->heap()->undefined_value();
   5584 
   5585   Heap* heap = isolate->heap();
   5586 
   5587   if (!HasExternalArrayElements()) {
   5588     // Go to dictionary mode, so that we don't skip map checks.
   5589     MaybeObject* maybe = NormalizeElements();
   5590     if (maybe->IsFailure()) return maybe;
   5591     ASSERT(!HasFastElements());
   5592   }
   5593 
   5594   LookupResult result(isolate);
   5595   map()->LookupTransition(this, heap->observed_symbol(), &result);
   5596 
   5597   Map* new_map;
   5598   if (result.IsTransition()) {
   5599     new_map = result.GetTransitionTarget();
   5600     ASSERT(new_map->is_observed());
   5601   } else if (map()->CanHaveMoreTransitions()) {
   5602     MaybeObject* maybe_new_map = map()->CopyForObserved();
   5603     if (!maybe_new_map->To(&new_map)) return maybe_new_map;
   5604   } else {
   5605     MaybeObject* maybe_copy = map()->Copy();
   5606     if (!maybe_copy->To(&new_map)) return maybe_copy;
   5607     new_map->set_is_observed(true);
   5608   }
   5609   set_map(new_map);
   5610 
   5611   return heap->undefined_value();
   5612 }
   5613 
   5614 
   5615 MUST_USE_RESULT MaybeObject* JSObject::DeepCopy(Isolate* isolate) {
   5616   StackLimitCheck check(isolate);
   5617   if (check.HasOverflowed()) return isolate->StackOverflow();
   5618 
   5619   if (map()->is_deprecated()) {
   5620     MaybeObject* maybe_failure = MigrateInstance();
   5621     if (maybe_failure->IsFailure()) return maybe_failure;
   5622   }
   5623 
   5624   Heap* heap = isolate->heap();
   5625   Object* result;
   5626   { MaybeObject* maybe_result = heap->CopyJSObject(this);
   5627     if (!maybe_result->ToObject(&result)) return maybe_result;
   5628   }
   5629   JSObject* copy = JSObject::cast(result);
   5630 
   5631   // Deep copy local properties.
   5632   if (copy->HasFastProperties()) {
   5633     DescriptorArray* descriptors = copy->map()->instance_descriptors();
   5634     int limit = copy->map()->NumberOfOwnDescriptors();
   5635     for (int i = 0; i < limit; i++) {
   5636       PropertyDetails details = descriptors->GetDetails(i);
   5637       if (details.type() != FIELD) continue;
   5638       int index = descriptors->GetFieldIndex(i);
   5639       Object* value = RawFastPropertyAt(index);
   5640       if (value->IsJSObject()) {
   5641         JSObject* js_object = JSObject::cast(value);
   5642         MaybeObject* maybe_copy = js_object->DeepCopy(isolate);
   5643         if (!maybe_copy->To(&value)) return maybe_copy;
   5644       } else {
   5645         Representation representation = details.representation();
   5646         MaybeObject* maybe_storage =
   5647             value->AllocateNewStorageFor(heap, representation);
   5648         if (!maybe_storage->To(&value)) return maybe_storage;
   5649       }
   5650       copy->FastPropertyAtPut(index, value);
   5651     }
   5652   } else {
   5653     { MaybeObject* maybe_result =
   5654           heap->AllocateFixedArray(copy->NumberOfLocalProperties());
   5655       if (!maybe_result->ToObject(&result)) return maybe_result;
   5656     }
   5657     FixedArray* names = FixedArray::cast(result);
   5658     copy->GetLocalPropertyNames(names, 0);
   5659     for (int i = 0; i < names->length(); i++) {
   5660       ASSERT(names->get(i)->IsString());
   5661       String* key_string = String::cast(names->get(i));
   5662       PropertyAttributes attributes =
   5663           copy->GetLocalPropertyAttribute(key_string);
   5664       // Only deep copy fields from the object literal expression.
   5665       // In particular, don't try to copy the length attribute of
   5666       // an array.
   5667       if (attributes != NONE) continue;
   5668       Object* value =
   5669           copy->GetProperty(key_string, &attributes)->ToObjectUnchecked();
   5670       if (value->IsJSObject()) {
   5671         JSObject* js_object = JSObject::cast(value);
   5672         { MaybeObject* maybe_result = js_object->DeepCopy(isolate);
   5673           if (!maybe_result->ToObject(&result)) return maybe_result;
   5674         }
   5675         { MaybeObject* maybe_result =
   5676               // Creating object copy for literals. No strict mode needed.
   5677               copy->SetProperty(key_string, result, NONE, kNonStrictMode);
   5678           if (!maybe_result->ToObject(&result)) return maybe_result;
   5679         }
   5680       }
   5681     }
   5682   }
   5683 
   5684   // Deep copy local elements.
   5685   // Pixel elements cannot be created using an object literal.
   5686   ASSERT(!copy->HasExternalArrayElements());
   5687   switch (copy->GetElementsKind()) {
   5688     case FAST_SMI_ELEMENTS:
   5689     case FAST_ELEMENTS:
   5690     case FAST_HOLEY_SMI_ELEMENTS:
   5691     case FAST_HOLEY_ELEMENTS: {
   5692       FixedArray* elements = FixedArray::cast(copy->elements());
   5693       if (elements->map() == heap->fixed_cow_array_map()) {
   5694         isolate->counters()->cow_arrays_created_runtime()->Increment();
   5695 #ifdef DEBUG
   5696         for (int i = 0; i < elements->length(); i++) {
   5697           ASSERT(!elements->get(i)->IsJSObject());
   5698         }
   5699 #endif
   5700       } else {
   5701         for (int i = 0; i < elements->length(); i++) {
   5702           Object* value = elements->get(i);
   5703           ASSERT(value->IsSmi() ||
   5704                  value->IsTheHole() ||
   5705                  (IsFastObjectElementsKind(copy->GetElementsKind())));
   5706           if (value->IsJSObject()) {
   5707             JSObject* js_object = JSObject::cast(value);
   5708             { MaybeObject* maybe_result = js_object->DeepCopy(isolate);
   5709               if (!maybe_result->ToObject(&result)) return maybe_result;
   5710             }
   5711             elements->set(i, result);
   5712           }
   5713         }
   5714       }
   5715       break;
   5716     }
   5717     case DICTIONARY_ELEMENTS: {
   5718       SeededNumberDictionary* element_dictionary = copy->element_dictionary();
   5719       int capacity = element_dictionary->Capacity();
   5720       for (int i = 0; i < capacity; i++) {
   5721         Object* k = element_dictionary->KeyAt(i);
   5722         if (element_dictionary->IsKey(k)) {
   5723           Object* value = element_dictionary->ValueAt(i);
   5724           if (value->IsJSObject()) {
   5725             JSObject* js_object = JSObject::cast(value);
   5726             { MaybeObject* maybe_result = js_object->DeepCopy(isolate);
   5727               if (!maybe_result->ToObject(&result)) return maybe_result;
   5728             }
   5729             element_dictionary->ValueAtPut(i, result);
   5730           }
   5731         }
   5732       }
   5733       break;
   5734     }
   5735     case NON_STRICT_ARGUMENTS_ELEMENTS:
   5736       UNIMPLEMENTED();
   5737       break;
   5738     case EXTERNAL_PIXEL_ELEMENTS:
   5739     case EXTERNAL_BYTE_ELEMENTS:
   5740     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
   5741     case EXTERNAL_SHORT_ELEMENTS:
   5742     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
   5743     case EXTERNAL_INT_ELEMENTS:
   5744     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
   5745     case EXTERNAL_FLOAT_ELEMENTS:
   5746     case EXTERNAL_DOUBLE_ELEMENTS:
   5747     case FAST_DOUBLE_ELEMENTS:
   5748     case FAST_HOLEY_DOUBLE_ELEMENTS:
   5749       // No contained objects, nothing to do.
   5750       break;
   5751   }
   5752   return copy;
   5753 }
   5754 
   5755 
   5756 // Tests for the fast common case for property enumeration:
   5757 // - This object and all prototypes has an enum cache (which means that
   5758 //   it is no proxy, has no interceptors and needs no access checks).
   5759 // - This object has no elements.
   5760 // - No prototype has enumerable properties/elements.
   5761 bool JSReceiver::IsSimpleEnum() {
   5762   Heap* heap = GetHeap();
   5763   for (Object* o = this;
   5764        o != heap->null_value();
   5765        o = JSObject::cast(o)->GetPrototype()) {
   5766     if (!o->IsJSObject()) return false;
   5767     JSObject* curr = JSObject::cast(o);
   5768     int enum_length = curr->map()->EnumLength();
   5769     if (enum_length == Map::kInvalidEnumCache) return false;
   5770     ASSERT(!curr->HasNamedInterceptor());
   5771     ASSERT(!curr->HasIndexedInterceptor());
   5772     ASSERT(!curr->IsAccessCheckNeeded());
   5773     if (curr->NumberOfEnumElements() > 0) return false;
   5774     if (curr != this && enum_length != 0) return false;
   5775   }
   5776   return true;
   5777 }
   5778 
   5779 
   5780 int Map::NumberOfDescribedProperties(DescriptorFlag which,
   5781                                      PropertyAttributes filter) {
   5782   int result = 0;
   5783   DescriptorArray* descs = instance_descriptors();
   5784   int limit = which == ALL_DESCRIPTORS
   5785       ? descs->number_of_descriptors()
   5786       : NumberOfOwnDescriptors();
   5787   for (int i = 0; i < limit; i++) {
   5788     if ((descs->GetDetails(i).attributes() & filter) == 0 &&
   5789         ((filter & SYMBOLIC) == 0 || !descs->GetKey(i)->IsSymbol())) {
   5790       result++;
   5791     }
   5792   }
   5793   return result;
   5794 }
   5795 
   5796 
   5797 int Map::NextFreePropertyIndex() {
   5798   int max_index = -1;
   5799   int number_of_own_descriptors = NumberOfOwnDescriptors();
   5800   DescriptorArray* descs = instance_descriptors();
   5801   for (int i = 0; i < number_of_own_descriptors; i++) {
   5802     if (descs->GetType(i) == FIELD) {
   5803       int current_index = descs->GetFieldIndex(i);
   5804       if (current_index > max_index) max_index = current_index;
   5805     }
   5806   }
   5807   return max_index + 1;
   5808 }
   5809 
   5810 
   5811 AccessorDescriptor* Map::FindAccessor(Name* name) {
   5812   DescriptorArray* descs = instance_descriptors();
   5813   int number_of_own_descriptors = NumberOfOwnDescriptors();
   5814   for (int i = 0; i < number_of_own_descriptors; i++) {
   5815     if (descs->GetType(i) == CALLBACKS && name->Equals(descs->GetKey(i))) {
   5816       return descs->GetCallbacks(i);
   5817     }
   5818   }
   5819   return NULL;
   5820 }
   5821 
   5822 
   5823 void JSReceiver::LocalLookup(
   5824     Name* name, LookupResult* result, bool search_hidden_prototypes) {
   5825   ASSERT(name->IsName());
   5826 
   5827   Heap* heap = GetHeap();
   5828 
   5829   if (IsJSGlobalProxy()) {
   5830     Object* proto = GetPrototype();
   5831     if (proto->IsNull()) return result->NotFound();
   5832     ASSERT(proto->IsJSGlobalObject());
   5833     return JSReceiver::cast(proto)->LocalLookup(
   5834         name, result, search_hidden_prototypes);
   5835   }
   5836 
   5837   if (IsJSProxy()) {
   5838     result->HandlerResult(JSProxy::cast(this));
   5839     return;
   5840   }
   5841 
   5842   // Do not use inline caching if the object is a non-global object
   5843   // that requires access checks.
   5844   if (IsAccessCheckNeeded()) {
   5845     result->DisallowCaching();
   5846   }
   5847 
   5848   JSObject* js_object = JSObject::cast(this);
   5849 
   5850   // Check for lookup interceptor except when bootstrapping.
   5851   if (js_object->HasNamedInterceptor() &&
   5852       !heap->isolate()->bootstrapper()->IsActive()) {
   5853     result->InterceptorResult(js_object);
   5854     return;
   5855   }
   5856 
   5857   js_object->LocalLookupRealNamedProperty(name, result);
   5858   if (result->IsFound() || !search_hidden_prototypes) return;
   5859 
   5860   Object* proto = js_object->GetPrototype();
   5861   if (!proto->IsJSReceiver()) return;
   5862   JSReceiver* receiver = JSReceiver::cast(proto);
   5863   if (receiver->map()->is_hidden_prototype()) {
   5864     receiver->LocalLookup(name, result, search_hidden_prototypes);
   5865   }
   5866 }
   5867 
   5868 
   5869 void JSReceiver::Lookup(Name* name, LookupResult* result) {
   5870   // Ecma-262 3rd 8.6.2.4
   5871   Heap* heap = GetHeap();
   5872   for (Object* current = this;
   5873        current != heap->null_value();
   5874        current = JSObject::cast(current)->GetPrototype()) {
   5875     JSReceiver::cast(current)->LocalLookup(name, result, false);
   5876     if (result->IsFound()) return;
   5877   }
   5878   result->NotFound();
   5879 }
   5880 
   5881 
   5882 // Search object and its prototype chain for callback properties.
   5883 void JSObject::LookupCallbackProperty(Name* name, LookupResult* result) {
   5884   Heap* heap = GetHeap();
   5885   for (Object* current = this;
   5886        current != heap->null_value() && current->IsJSObject();
   5887        current = JSObject::cast(current)->GetPrototype()) {
   5888     JSObject::cast(current)->LocalLookupRealNamedProperty(name, result);
   5889     if (result->IsPropertyCallbacks()) return;
   5890   }
   5891   result->NotFound();
   5892 }
   5893 
   5894 
   5895 // Try to update an accessor in an elements dictionary. Return true if the
   5896 // update succeeded, and false otherwise.
   5897 static bool UpdateGetterSetterInDictionary(
   5898     SeededNumberDictionary* dictionary,
   5899     uint32_t index,
   5900     Object* getter,
   5901     Object* setter,
   5902     PropertyAttributes attributes) {
   5903   int entry = dictionary->FindEntry(index);
   5904   if (entry != SeededNumberDictionary::kNotFound) {
   5905     Object* result = dictionary->ValueAt(entry);
   5906     PropertyDetails details = dictionary->DetailsAt(entry);
   5907     if (details.type() == CALLBACKS && result->IsAccessorPair()) {
   5908       ASSERT(!details.IsDontDelete());
   5909       if (details.attributes() != attributes) {
   5910         dictionary->DetailsAtPut(
   5911             entry,
   5912             PropertyDetails(attributes, CALLBACKS, index));
   5913       }
   5914       AccessorPair::cast(result)->SetComponents(getter, setter);
   5915       return true;
   5916     }
   5917   }
   5918   return false;
   5919 }
   5920 
   5921 
   5922 void JSObject::DefineElementAccessor(Handle<JSObject> object,
   5923                                      uint32_t index,
   5924                                      Handle<Object> getter,
   5925                                      Handle<Object> setter,
   5926                                      PropertyAttributes attributes) {
   5927   switch (object->GetElementsKind()) {
   5928     case FAST_SMI_ELEMENTS:
   5929     case FAST_ELEMENTS:
   5930     case FAST_DOUBLE_ELEMENTS:
   5931     case FAST_HOLEY_SMI_ELEMENTS:
   5932     case FAST_HOLEY_ELEMENTS:
   5933     case FAST_HOLEY_DOUBLE_ELEMENTS:
   5934       break;
   5935     case EXTERNAL_PIXEL_ELEMENTS:
   5936     case EXTERNAL_BYTE_ELEMENTS:
   5937     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
   5938     case EXTERNAL_SHORT_ELEMENTS:
   5939     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
   5940     case EXTERNAL_INT_ELEMENTS:
   5941     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
   5942     case EXTERNAL_FLOAT_ELEMENTS:
   5943     case EXTERNAL_DOUBLE_ELEMENTS:
   5944       // Ignore getters and setters on pixel and external array elements.
   5945       return;
   5946     case DICTIONARY_ELEMENTS:
   5947       if (UpdateGetterSetterInDictionary(object->element_dictionary(),
   5948                                          index,
   5949                                          *getter,
   5950                                          *setter,
   5951                                          attributes)) {
   5952         return;
   5953       }
   5954       break;
   5955     case NON_STRICT_ARGUMENTS_ELEMENTS: {
   5956       // Ascertain whether we have read-only properties or an existing
   5957       // getter/setter pair in an arguments elements dictionary backing
   5958       // store.
   5959       FixedArray* parameter_map = FixedArray::cast(object->elements());
   5960       uint32_t length = parameter_map->length();
   5961       Object* probe =
   5962           index < (length - 2) ? parameter_map->get(index + 2) : NULL;
   5963       if (probe == NULL || probe->IsTheHole()) {
   5964         FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
   5965         if (arguments->IsDictionary()) {
   5966           SeededNumberDictionary* dictionary =
   5967               SeededNumberDictionary::cast(arguments);
   5968           if (UpdateGetterSetterInDictionary(dictionary,
   5969                                              index,
   5970                                              *getter,
   5971                                              *setter,
   5972                                              attributes)) {
   5973             return;
   5974           }
   5975         }
   5976       }
   5977       break;
   5978     }
   5979   }
   5980 
   5981   Isolate* isolate = object->GetIsolate();
   5982   Handle<AccessorPair> accessors = isolate->factory()->NewAccessorPair();
   5983   accessors->SetComponents(*getter, *setter);
   5984 
   5985   CALL_HEAP_FUNCTION_VOID(
   5986       isolate, object->SetElementCallback(index, *accessors, attributes));
   5987 }
   5988 
   5989 
   5990 Handle<AccessorPair> JSObject::CreateAccessorPairFor(Handle<JSObject> object,
   5991                                                      Handle<Name> name) {
   5992   Isolate* isolate = object->GetIsolate();
   5993   LookupResult result(isolate);
   5994   object->LocalLookupRealNamedProperty(*name, &result);
   5995   if (result.IsPropertyCallbacks()) {
   5996     // Note that the result can actually have IsDontDelete() == true when we
   5997     // e.g. have to fall back to the slow case while adding a setter after
   5998     // successfully reusing a map transition for a getter. Nevertheless, this is
   5999     // OK, because the assertion only holds for the whole addition of both
   6000     // accessors, not for the addition of each part. See first comment in
   6001     // DefinePropertyAccessor below.
   6002     Object* obj = result.GetCallbackObject();
   6003     if (obj->IsAccessorPair()) {
   6004       return AccessorPair::Copy(handle(AccessorPair::cast(obj), isolate));
   6005     }
   6006   }
   6007   return isolate->factory()->NewAccessorPair();
   6008 }
   6009 
   6010 
   6011 void JSObject::DefinePropertyAccessor(Handle<JSObject> object,
   6012                                       Handle<Name> name,
   6013                                       Handle<Object> getter,
   6014                                       Handle<Object> setter,
   6015                                       PropertyAttributes attributes) {
   6016   // We could assert that the property is configurable here, but we would need
   6017   // to do a lookup, which seems to be a bit of overkill.
   6018   bool only_attribute_changes = getter->IsNull() && setter->IsNull();
   6019   if (object->HasFastProperties() && !only_attribute_changes &&
   6020       (object->map()->NumberOfOwnDescriptors() <
   6021        DescriptorArray::kMaxNumberOfDescriptors)) {
   6022     bool getterOk = getter->IsNull() ||
   6023         DefineFastAccessor(object, name, ACCESSOR_GETTER, getter, attributes);
   6024     bool setterOk = !getterOk || setter->IsNull() ||
   6025         DefineFastAccessor(object, name, ACCESSOR_SETTER, setter, attributes);
   6026     if (getterOk && setterOk) return;
   6027   }
   6028 
   6029   Handle<AccessorPair> accessors = CreateAccessorPairFor(object, name);
   6030   accessors->SetComponents(*getter, *setter);
   6031 
   6032   CALL_HEAP_FUNCTION_VOID(
   6033       object->GetIsolate(),
   6034       object->SetPropertyCallback(*name, *accessors, attributes));
   6035 }
   6036 
   6037 
   6038 bool JSObject::CanSetCallback(Name* name) {
   6039   ASSERT(!IsAccessCheckNeeded() ||
   6040          GetIsolate()->MayNamedAccess(this, name, v8::ACCESS_SET));
   6041 
   6042   // Check if there is an API defined callback object which prohibits
   6043   // callback overwriting in this object or its prototype chain.
   6044   // This mechanism is needed for instance in a browser setting, where
   6045   // certain accessors such as window.location should not be allowed
   6046   // to be overwritten because allowing overwriting could potentially
   6047   // cause security problems.
   6048   LookupResult callback_result(GetIsolate());
   6049   LookupCallbackProperty(name, &callback_result);
   6050   if (callback_result.IsFound()) {
   6051     Object* obj = callback_result.GetCallbackObject();
   6052     if (obj->IsAccessorInfo() &&
   6053         AccessorInfo::cast(obj)->prohibits_overwriting()) {
   6054       return false;
   6055     }
   6056   }
   6057 
   6058   return true;
   6059 }
   6060 
   6061 
   6062 MaybeObject* JSObject::SetElementCallback(uint32_t index,
   6063                                           Object* structure,
   6064                                           PropertyAttributes attributes) {
   6065   PropertyDetails details = PropertyDetails(attributes, CALLBACKS, 0);
   6066 
   6067   // Normalize elements to make this operation simple.
   6068   SeededNumberDictionary* dictionary;
   6069   { MaybeObject* maybe_dictionary = NormalizeElements();
   6070     if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
   6071   }
   6072   ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements());
   6073 
   6074   // Update the dictionary with the new CALLBACKS property.
   6075   { MaybeObject* maybe_dictionary = dictionary->Set(index, structure, details);
   6076     if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary;
   6077   }
   6078 
   6079   dictionary->set_requires_slow_elements();
   6080   // Update the dictionary backing store on the object.
   6081   if (elements()->map() == GetHeap()->non_strict_arguments_elements_map()) {
   6082     // Also delete any parameter alias.
   6083     //
   6084     // TODO(kmillikin): when deleting the last parameter alias we could
   6085     // switch to a direct backing store without the parameter map.  This
   6086     // would allow GC of the context.
   6087     FixedArray* parameter_map = FixedArray::cast(elements());
   6088     if (index < static_cast<uint32_t>(parameter_map->length()) - 2) {
   6089       parameter_map->set(index + 2, GetHeap()->the_hole_value());
   6090     }
   6091     parameter_map->set(1, dictionary);
   6092   } else {
   6093     set_elements(dictionary);
   6094   }
   6095 
   6096   return GetHeap()->undefined_value();
   6097 }
   6098 
   6099 
   6100 MaybeObject* JSObject::SetPropertyCallback(Name* name,
   6101                                            Object* structure,
   6102                                            PropertyAttributes attributes) {
   6103   // Normalize object to make this operation simple.
   6104   MaybeObject* maybe_ok = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
   6105   if (maybe_ok->IsFailure()) return maybe_ok;
   6106 
   6107   // For the global object allocate a new map to invalidate the global inline
   6108   // caches which have a global property cell reference directly in the code.
   6109   if (IsGlobalObject()) {
   6110     Map* new_map;
   6111     MaybeObject* maybe_new_map = map()->CopyDropDescriptors();
   6112     if (!maybe_new_map->To(&new_map)) return maybe_new_map;
   6113     ASSERT(new_map->is_dictionary_map());
   6114 
   6115     set_map(new_map);
   6116     // When running crankshaft, changing the map is not enough. We
   6117     // need to deoptimize all functions that rely on this global
   6118     // object.
   6119     Deoptimizer::DeoptimizeGlobalObject(this);
   6120   }
   6121 
   6122   // Update the dictionary with the new CALLBACKS property.
   6123   PropertyDetails details = PropertyDetails(attributes, CALLBACKS, 0);
   6124   maybe_ok = SetNormalizedProperty(name, structure, details);
   6125   if (maybe_ok->IsFailure()) return maybe_ok;
   6126 
   6127   return GetHeap()->undefined_value();
   6128 }
   6129 
   6130 
   6131 void JSObject::DefineAccessor(Handle<JSObject> object,
   6132                               Handle<Name> name,
   6133                               Handle<Object> getter,
   6134                               Handle<Object> setter,
   6135                               PropertyAttributes attributes) {
   6136   Isolate* isolate = object->GetIsolate();
   6137   // Check access rights if needed.
   6138   if (object->IsAccessCheckNeeded() &&
   6139       !isolate->MayNamedAccess(*object, *name, v8::ACCESS_SET)) {
   6140     isolate->ReportFailedAccessCheck(*object, v8::ACCESS_SET);
   6141     return;
   6142   }
   6143 
   6144   if (object->IsJSGlobalProxy()) {
   6145     Handle<Object> proto(object->GetPrototype(), isolate);
   6146     if (proto->IsNull()) return;
   6147     ASSERT(proto->IsJSGlobalObject());
   6148     DefineAccessor(
   6149         Handle<JSObject>::cast(proto), name, getter, setter, attributes);
   6150     return;
   6151   }
   6152 
   6153   // Make sure that the top context does not change when doing callbacks or
   6154   // interceptor calls.
   6155   AssertNoContextChange ncc;
   6156 
   6157   // Try to flatten before operating on the string.
   6158   if (name->IsString()) String::cast(*name)->TryFlatten();
   6159 
   6160   if (!object->CanSetCallback(*name)) return;
   6161 
   6162   uint32_t index = 0;
   6163   bool is_element = name->AsArrayIndex(&index);
   6164 
   6165   Handle<Object> old_value = isolate->factory()->the_hole_value();
   6166   bool is_observed = FLAG_harmony_observation && object->map()->is_observed();
   6167   bool preexists = false;
   6168   if (is_observed) {
   6169     if (is_element) {
   6170       preexists = object->HasLocalElement(index);
   6171       if (preexists && object->GetLocalElementAccessorPair(index) == NULL) {
   6172         old_value = Object::GetElement(object, index);
   6173       }
   6174     } else {
   6175       LookupResult lookup(isolate);
   6176       object->LocalLookup(*name, &lookup, true);
   6177       preexists = lookup.IsProperty();
   6178       if (preexists && lookup.IsDataProperty()) {
   6179         old_value = Object::GetProperty(object, name);
   6180       }
   6181     }
   6182   }
   6183 
   6184   if (is_element) {
   6185     DefineElementAccessor(object, index, getter, setter, attributes);
   6186   } else {
   6187     DefinePropertyAccessor(object, name, getter, setter, attributes);
   6188   }
   6189 
   6190   if (is_observed) {
   6191     const char* type = preexists ? "reconfigured" : "new";
   6192     EnqueueChangeRecord(object, type, name, old_value);
   6193   }
   6194 }
   6195 
   6196 
   6197 static bool TryAccessorTransition(JSObject* self,
   6198                                   Map* transitioned_map,
   6199                                   int target_descriptor,
   6200                                   AccessorComponent component,
   6201                                   Object* accessor,
   6202                                   PropertyAttributes attributes) {
   6203   DescriptorArray* descs = transitioned_map->instance_descriptors();
   6204   PropertyDetails details = descs->GetDetails(target_descriptor);
   6205 
   6206   // If the transition target was not callbacks, fall back to the slow case.
   6207   if (details.type() != CALLBACKS) return false;
   6208   Object* descriptor = descs->GetCallbacksObject(target_descriptor);
   6209   if (!descriptor->IsAccessorPair()) return false;
   6210 
   6211   Object* target_accessor = AccessorPair::cast(descriptor)->get(component);
   6212   PropertyAttributes target_attributes = details.attributes();
   6213 
   6214   // Reuse transition if adding same accessor with same attributes.
   6215   if (target_accessor == accessor && target_attributes == attributes) {
   6216     self->set_map(transitioned_map);
   6217     return true;
   6218   }
   6219 
   6220   // If either not the same accessor, or not the same attributes, fall back to
   6221   // the slow case.
   6222   return false;
   6223 }
   6224 
   6225 
   6226 static MaybeObject* CopyInsertDescriptor(Map* map,
   6227                                          Name* name,
   6228                                          AccessorPair* accessors,
   6229                                          PropertyAttributes attributes) {
   6230   CallbacksDescriptor new_accessors_desc(name, accessors, attributes);
   6231   return map->CopyInsertDescriptor(&new_accessors_desc, INSERT_TRANSITION);
   6232 }
   6233 
   6234 
   6235 static Handle<Map> CopyInsertDescriptor(Handle<Map> map,
   6236                                         Handle<Name> name,
   6237                                         Handle<AccessorPair> accessors,
   6238                                         PropertyAttributes attributes) {
   6239   CALL_HEAP_FUNCTION(map->GetIsolate(),
   6240                      CopyInsertDescriptor(*map, *name, *accessors, attributes),
   6241                      Map);
   6242 }
   6243 
   6244 
   6245 bool JSObject::DefineFastAccessor(Handle<JSObject> object,
   6246                                   Handle<Name> name,
   6247                                   AccessorComponent component,
   6248                                   Handle<Object> accessor,
   6249                                   PropertyAttributes attributes) {
   6250   ASSERT(accessor->IsSpecFunction() || accessor->IsUndefined());
   6251   Isolate* isolate = object->GetIsolate();
   6252   LookupResult result(isolate);
   6253   object->LocalLookup(*name, &result);
   6254 
   6255   if (result.IsFound() && !result.IsPropertyCallbacks()) {
   6256     return false;
   6257   }
   6258 
   6259   // Return success if the same accessor with the same attributes already exist.
   6260   AccessorPair* source_accessors = NULL;
   6261   if (result.IsPropertyCallbacks()) {
   6262     Object* callback_value = result.GetCallbackObject();
   6263     if (callback_value->IsAccessorPair()) {
   6264       source_accessors = AccessorPair::cast(callback_value);
   6265       Object* entry = source_accessors->get(component);
   6266       if (entry == *accessor && result.GetAttributes() == attributes) {
   6267         return true;
   6268       }
   6269     } else {
   6270       return false;
   6271     }
   6272 
   6273     int descriptor_number = result.GetDescriptorIndex();
   6274 
   6275     object->map()->LookupTransition(*object, *name, &result);
   6276 
   6277     if (result.IsFound()) {
   6278       Map* target = result.GetTransitionTarget();
   6279       ASSERT(target->NumberOfOwnDescriptors() ==
   6280              object->map()->NumberOfOwnDescriptors());
   6281       // This works since descriptors are sorted in order of addition.
   6282       ASSERT(object->map()->instance_descriptors()->
   6283              GetKey(descriptor_number) == *name);
   6284       return TryAccessorTransition(*object, target, descriptor_number,
   6285                                    component, *accessor, attributes);
   6286     }
   6287   } else {
   6288     // If not, lookup a transition.
   6289     object->map()->LookupTransition(*object, *name, &result);
   6290 
   6291     // If there is a transition, try to follow it.
   6292     if (result.IsFound()) {
   6293       Map* target = result.GetTransitionTarget();
   6294       int descriptor_number = target->LastAdded();
   6295       ASSERT(target->instance_descriptors()->GetKey(descriptor_number)
   6296              ->Equals(*name));
   6297       return TryAccessorTransition(*object, target, descriptor_number,
   6298                                    component, *accessor, attributes);
   6299     }
   6300   }
   6301 
   6302   // If there is no transition yet, add a transition to the a new accessor pair
   6303   // containing the accessor.  Allocate a new pair if there were no source
   6304   // accessors.  Otherwise, copy the pair and modify the accessor.
   6305   Handle<AccessorPair> accessors = source_accessors != NULL
   6306       ? AccessorPair::Copy(Handle<AccessorPair>(source_accessors))
   6307       : isolate->factory()->NewAccessorPair();
   6308   accessors->set(component, *accessor);
   6309   Handle<Map> new_map = CopyInsertDescriptor(Handle<Map>(object->map()),
   6310                                              name, accessors, attributes);
   6311   object->set_map(*new_map);
   6312   return true;
   6313 }
   6314 
   6315 
   6316 MaybeObject* JSObject::DefineAccessor(AccessorInfo* info) {
   6317   Isolate* isolate = GetIsolate();
   6318   Name* name = Name::cast(info->name());
   6319   // Check access rights if needed.
   6320   if (IsAccessCheckNeeded() &&
   6321       !isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) {
   6322     isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET);
   6323     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   6324     return isolate->heap()->undefined_value();
   6325   }
   6326 
   6327   if (IsJSGlobalProxy()) {
   6328     Object* proto = GetPrototype();
   6329     if (proto->IsNull()) return this;
   6330     ASSERT(proto->IsJSGlobalObject());
   6331     return JSObject::cast(proto)->DefineAccessor(info);
   6332   }
   6333 
   6334   // Make sure that the top context does not change when doing callbacks or
   6335   // interceptor calls.
   6336   AssertNoContextChange ncc;
   6337 
   6338   // Try to flatten before operating on the string.
   6339   if (name->IsString()) String::cast(name)->TryFlatten();
   6340 
   6341   if (!CanSetCallback(name)) return isolate->heap()->undefined_value();
   6342 
   6343   uint32_t index = 0;
   6344   bool is_element = name->AsArrayIndex(&index);
   6345 
   6346   if (is_element) {
   6347     if (IsJSArray()) return isolate->heap()->undefined_value();
   6348 
   6349     // Accessors overwrite previous callbacks (cf. with getters/setters).
   6350     switch (GetElementsKind()) {
   6351       case FAST_SMI_ELEMENTS:
   6352       case FAST_ELEMENTS:
   6353       case FAST_DOUBLE_ELEMENTS:
   6354       case FAST_HOLEY_SMI_ELEMENTS:
   6355       case FAST_HOLEY_ELEMENTS:
   6356       case FAST_HOLEY_DOUBLE_ELEMENTS:
   6357         break;
   6358       case EXTERNAL_PIXEL_ELEMENTS:
   6359       case EXTERNAL_BYTE_ELEMENTS:
   6360       case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
   6361       case EXTERNAL_SHORT_ELEMENTS:
   6362       case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
   6363       case EXTERNAL_INT_ELEMENTS:
   6364       case EXTERNAL_UNSIGNED_INT_ELEMENTS:
   6365       case EXTERNAL_FLOAT_ELEMENTS:
   6366       case EXTERNAL_DOUBLE_ELEMENTS:
   6367         // Ignore getters and setters on pixel and external array
   6368         // elements.
   6369         return isolate->heap()->undefined_value();
   6370       case DICTIONARY_ELEMENTS:
   6371         break;
   6372       case NON_STRICT_ARGUMENTS_ELEMENTS:
   6373         UNIMPLEMENTED();
   6374         break;
   6375     }
   6376 
   6377     MaybeObject* maybe_ok =
   6378         SetElementCallback(index, info, info->property_attributes());
   6379     if (maybe_ok->IsFailure()) return maybe_ok;
   6380   } else {
   6381     // Lookup the name.
   6382     LookupResult result(isolate);
   6383     LocalLookup(name, &result, true);
   6384     // ES5 forbids turning a property into an accessor if it's not
   6385     // configurable (that is IsDontDelete in ES3 and v8), see 8.6.1 (Table 5).
   6386     if (result.IsFound() && (result.IsReadOnly() || result.IsDontDelete())) {
   6387       return isolate->heap()->undefined_value();
   6388     }
   6389 
   6390     MaybeObject* maybe_ok =
   6391         SetPropertyCallback(name, info, info->property_attributes());
   6392     if (maybe_ok->IsFailure()) return maybe_ok;
   6393   }
   6394 
   6395   return this;
   6396 }
   6397 
   6398 
   6399 MaybeObject* JSObject::LookupAccessor(Name* name, AccessorComponent component) {
   6400   Heap* heap = GetHeap();
   6401 
   6402   // Make sure that the top context does not change when doing callbacks or
   6403   // interceptor calls.
   6404   AssertNoContextChange ncc;
   6405 
   6406   // Check access rights if needed.
   6407   if (IsAccessCheckNeeded() &&
   6408       !heap->isolate()->MayNamedAccess(this, name, v8::ACCESS_HAS)) {
   6409     heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
   6410     RETURN_IF_SCHEDULED_EXCEPTION(heap->isolate());
   6411     return heap->undefined_value();
   6412   }
   6413 
   6414   // Make the lookup and include prototypes.
   6415   uint32_t index = 0;
   6416   if (name->AsArrayIndex(&index)) {
   6417     for (Object* obj = this;
   6418          obj != heap->null_value();
   6419          obj = JSReceiver::cast(obj)->GetPrototype()) {
   6420       if (obj->IsJSObject() && JSObject::cast(obj)->HasDictionaryElements()) {
   6421         JSObject* js_object = JSObject::cast(obj);
   6422         SeededNumberDictionary* dictionary = js_object->element_dictionary();
   6423         int entry = dictionary->FindEntry(index);
   6424         if (entry != SeededNumberDictionary::kNotFound) {
   6425           Object* element = dictionary->ValueAt(entry);
   6426           if (dictionary->DetailsAt(entry).type() == CALLBACKS &&
   6427               element->IsAccessorPair()) {
   6428             return AccessorPair::cast(element)->GetComponent(component);
   6429           }
   6430         }
   6431       }
   6432     }
   6433   } else {
   6434     for (Object* obj = this;
   6435          obj != heap->null_value();
   6436          obj = JSReceiver::cast(obj)->GetPrototype()) {
   6437       LookupResult result(heap->isolate());
   6438       JSReceiver::cast(obj)->LocalLookup(name, &result);
   6439       if (result.IsFound()) {
   6440         if (result.IsReadOnly()) return heap->undefined_value();
   6441         if (result.IsPropertyCallbacks()) {
   6442           Object* obj = result.GetCallbackObject();
   6443           if (obj->IsAccessorPair()) {
   6444             return AccessorPair::cast(obj)->GetComponent(component);
   6445           }
   6446         }
   6447       }
   6448     }
   6449   }
   6450   return heap->undefined_value();
   6451 }
   6452 
   6453 
   6454 Object* JSObject::SlowReverseLookup(Object* value) {
   6455   if (HasFastProperties()) {
   6456     int number_of_own_descriptors = map()->NumberOfOwnDescriptors();
   6457     DescriptorArray* descs = map()->instance_descriptors();
   6458     for (int i = 0; i < number_of_own_descriptors; i++) {
   6459       if (descs->GetType(i) == FIELD) {
   6460         Object* property = RawFastPropertyAt(descs->GetFieldIndex(i));
   6461         if (FLAG_track_double_fields &&
   6462             descs->GetDetails(i).representation().IsDouble()) {
   6463           ASSERT(property->IsHeapNumber());
   6464           if (value->IsNumber() && property->Number() == value->Number()) {
   6465             return descs->GetKey(i);
   6466           }
   6467         } else if (property == value) {
   6468           return descs->GetKey(i);
   6469         }
   6470       } else if (descs->GetType(i) == CONSTANT) {
   6471         if (descs->GetConstant(i) == value) {
   6472           return descs->GetKey(i);
   6473         }
   6474       }
   6475     }
   6476     return GetHeap()->undefined_value();
   6477   } else {
   6478     return property_dictionary()->SlowReverseLookup(value);
   6479   }
   6480 }
   6481 
   6482 
   6483 MaybeObject* Map::RawCopy(int instance_size) {
   6484   Map* result;
   6485   MaybeObject* maybe_result =
   6486       GetHeap()->AllocateMap(instance_type(), instance_size);
   6487   if (!maybe_result->To(&result)) return maybe_result;
   6488 
   6489   result->set_prototype(prototype());
   6490   result->set_constructor(constructor());
   6491   result->set_bit_field(bit_field());
   6492   result->set_bit_field2(bit_field2());
   6493   int new_bit_field3 = bit_field3();
   6494   new_bit_field3 = OwnsDescriptors::update(new_bit_field3, true);
   6495   new_bit_field3 = NumberOfOwnDescriptorsBits::update(new_bit_field3, 0);
   6496   new_bit_field3 = EnumLengthBits::update(new_bit_field3, kInvalidEnumCache);
   6497   new_bit_field3 = Deprecated::update(new_bit_field3, false);
   6498   new_bit_field3 = IsUnstable::update(new_bit_field3, false);
   6499   result->set_bit_field3(new_bit_field3);
   6500   return result;
   6501 }
   6502 
   6503 
   6504 MaybeObject* Map::CopyNormalized(PropertyNormalizationMode mode,
   6505                                  NormalizedMapSharingMode sharing) {
   6506   int new_instance_size = instance_size();
   6507   if (mode == CLEAR_INOBJECT_PROPERTIES) {
   6508     new_instance_size -= inobject_properties() * kPointerSize;
   6509   }
   6510 
   6511   Map* result;
   6512   MaybeObject* maybe_result = RawCopy(new_instance_size);
   6513   if (!maybe_result->To(&result)) return maybe_result;
   6514 
   6515   if (mode != CLEAR_INOBJECT_PROPERTIES) {
   6516     result->set_inobject_properties(inobject_properties());
   6517   }
   6518 
   6519   result->set_is_shared(sharing == SHARED_NORMALIZED_MAP);
   6520   result->set_dictionary_map(true);
   6521   result->set_migration_target(false);
   6522 
   6523 #ifdef VERIFY_HEAP
   6524   if (FLAG_verify_heap && result->is_shared()) {
   6525     result->SharedMapVerify();
   6526   }
   6527 #endif
   6528 
   6529   return result;
   6530 }
   6531 
   6532 
   6533 Handle<Map> Map::CopyDropDescriptors(Handle<Map> map) {
   6534   CALL_HEAP_FUNCTION(map->GetIsolate(), map->CopyDropDescriptors(), Map);
   6535 }
   6536 
   6537 
   6538 MaybeObject* Map::CopyDropDescriptors() {
   6539   Map* result;
   6540   MaybeObject* maybe_result = RawCopy(instance_size());
   6541   if (!maybe_result->To(&result)) return maybe_result;
   6542 
   6543   // Please note instance_type and instance_size are set when allocated.
   6544   result->set_inobject_properties(inobject_properties());
   6545   result->set_unused_property_fields(unused_property_fields());
   6546 
   6547   result->set_pre_allocated_property_fields(pre_allocated_property_fields());
   6548   result->set_is_shared(false);
   6549   result->ClearCodeCache(GetHeap());
   6550   NotifyLeafMapLayoutChange();
   6551   return result;
   6552 }
   6553 
   6554 
   6555 MaybeObject* Map::ShareDescriptor(DescriptorArray* descriptors,
   6556                                   Descriptor* descriptor) {
   6557   // Sanity check. This path is only to be taken if the map owns its descriptor
   6558   // array, implying that its NumberOfOwnDescriptors equals the number of
   6559   // descriptors in the descriptor array.
   6560   ASSERT(NumberOfOwnDescriptors() ==
   6561          instance_descriptors()->number_of_descriptors());
   6562   Map* result;
   6563   MaybeObject* maybe_result = CopyDropDescriptors();
   6564   if (!maybe_result->To(&result)) return maybe_result;
   6565 
   6566   Name* name = descriptor->GetKey();
   6567 
   6568   TransitionArray* transitions;
   6569   MaybeObject* maybe_transitions =
   6570       AddTransition(name, result, SIMPLE_TRANSITION);
   6571   if (!maybe_transitions->To(&transitions)) return maybe_transitions;
   6572 
   6573   int old_size = descriptors->number_of_descriptors();
   6574 
   6575   DescriptorArray* new_descriptors;
   6576 
   6577   if (descriptors->NumberOfSlackDescriptors() > 0) {
   6578     new_descriptors = descriptors;
   6579     new_descriptors->Append(descriptor);
   6580   } else {
   6581     // Descriptor arrays grow by 50%.
   6582     MaybeObject* maybe_descriptors = DescriptorArray::Allocate(
   6583         old_size, old_size < 4 ? 1 : old_size / 2);
   6584     if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
   6585 
   6586     DescriptorArray::WhitenessWitness witness(new_descriptors);
   6587 
   6588     // Copy the descriptors, inserting a descriptor.
   6589     for (int i = 0; i < old_size; ++i) {
   6590       new_descriptors->CopyFrom(i, descriptors, i, witness);
   6591     }
   6592 
   6593     new_descriptors->Append(descriptor, witness);
   6594 
   6595     if (old_size > 0) {
   6596       // If the source descriptors had an enum cache we copy it. This ensures
   6597       // that the maps to which we push the new descriptor array back can rely
   6598       // on a cache always being available once it is set. If the map has more
   6599       // enumerated descriptors than available in the original cache, the cache
   6600       // will be lazily replaced by the extended cache when needed.
   6601       if (descriptors->HasEnumCache()) {
   6602         new_descriptors->CopyEnumCacheFrom(descriptors);
   6603       }
   6604 
   6605       Map* map;
   6606       // Replace descriptors by new_descriptors in all maps that share it.
   6607       for (Object* current = GetBackPointer();
   6608            !current->IsUndefined();
   6609            current = map->GetBackPointer()) {
   6610         map = Map::cast(current);
   6611         if (map->instance_descriptors() != descriptors) break;
   6612         map->set_instance_descriptors(new_descriptors);
   6613       }
   6614 
   6615       set_instance_descriptors(new_descriptors);
   6616     }
   6617   }
   6618 
   6619   result->SetBackPointer(this);
   6620   result->InitializeDescriptors(new_descriptors);
   6621   ASSERT(result->NumberOfOwnDescriptors() == NumberOfOwnDescriptors() + 1);
   6622 
   6623   set_transitions(transitions);
   6624   set_owns_descriptors(false);
   6625 
   6626   return result;
   6627 }
   6628 
   6629 
   6630 MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors,
   6631                                          TransitionFlag flag,
   6632                                          Name* name,
   6633                                          SimpleTransitionFlag simple_flag) {
   6634   ASSERT(descriptors->IsSortedNoDuplicates());
   6635 
   6636   Map* result;
   6637   MaybeObject* maybe_result = CopyDropDescriptors();
   6638   if (!maybe_result->To(&result)) return maybe_result;
   6639 
   6640   result->InitializeDescriptors(descriptors);
   6641 
   6642   if (flag == INSERT_TRANSITION && CanHaveMoreTransitions()) {
   6643     TransitionArray* transitions;
   6644     MaybeObject* maybe_transitions = AddTransition(name, result, simple_flag);
   6645     if (!maybe_transitions->To(&transitions)) return maybe_transitions;
   6646     set_transitions(transitions);
   6647     result->SetBackPointer(this);
   6648   } else if (flag != OMIT_TRANSITION_KEEP_REPRESENTATIONS) {
   6649     descriptors->InitializeRepresentations(Representation::Tagged());
   6650   }
   6651 
   6652   return result;
   6653 }
   6654 
   6655 
   6656 // Since this method is used to rewrite an existing transition tree, it can
   6657 // always insert transitions without checking.
   6658 MaybeObject* Map::CopyInstallDescriptors(int new_descriptor,
   6659                                          DescriptorArray* descriptors) {
   6660   ASSERT(descriptors->IsSortedNoDuplicates());
   6661 
   6662   Map* result;
   6663   MaybeObject* maybe_result = CopyDropDescriptors();
   6664   if (!maybe_result->To(&result)) return maybe_result;
   6665 
   6666   result->InitializeDescriptors(descriptors);
   6667   result->SetNumberOfOwnDescriptors(new_descriptor + 1);
   6668 
   6669   int unused_property_fields = this->unused_property_fields();
   6670   if (descriptors->GetDetails(new_descriptor).type() == FIELD) {
   6671     unused_property_fields = this->unused_property_fields() - 1;
   6672     if (unused_property_fields < 0) {
   6673       unused_property_fields += JSObject::kFieldsAdded;
   6674     }
   6675   }
   6676 
   6677   result->set_unused_property_fields(unused_property_fields);
   6678   result->set_owns_descriptors(false);
   6679 
   6680   Name* name = descriptors->GetKey(new_descriptor);
   6681   TransitionArray* transitions;
   6682   MaybeObject* maybe_transitions =
   6683       AddTransition(name, result, SIMPLE_TRANSITION);
   6684   if (!maybe_transitions->To(&transitions)) return maybe_transitions;
   6685 
   6686   set_transitions(transitions);
   6687   result->SetBackPointer(this);
   6688 
   6689   return result;
   6690 }
   6691 
   6692 
   6693 MaybeObject* Map::CopyAsElementsKind(ElementsKind kind, TransitionFlag flag) {
   6694   if (flag == INSERT_TRANSITION) {
   6695     ASSERT(!HasElementsTransition() ||
   6696         ((elements_transition_map()->elements_kind() == DICTIONARY_ELEMENTS ||
   6697           IsExternalArrayElementsKind(
   6698               elements_transition_map()->elements_kind())) &&
   6699          (kind == DICTIONARY_ELEMENTS ||
   6700           IsExternalArrayElementsKind(kind))));
   6701     ASSERT(!IsFastElementsKind(kind) ||
   6702            IsMoreGeneralElementsKindTransition(elements_kind(), kind));
   6703     ASSERT(kind != elements_kind());
   6704   }
   6705 
   6706   bool insert_transition =
   6707       flag == INSERT_TRANSITION && !HasElementsTransition();
   6708 
   6709   if (insert_transition && owns_descriptors()) {
   6710     // In case the map owned its own descriptors, share the descriptors and
   6711     // transfer ownership to the new map.
   6712     Map* new_map;
   6713     MaybeObject* maybe_new_map = CopyDropDescriptors();
   6714     if (!maybe_new_map->To(&new_map)) return maybe_new_map;
   6715 
   6716     MaybeObject* added_elements = set_elements_transition_map(new_map);
   6717     if (added_elements->IsFailure()) return added_elements;
   6718 
   6719     new_map->set_elements_kind(kind);
   6720     new_map->InitializeDescriptors(instance_descriptors());
   6721     new_map->SetBackPointer(this);
   6722     set_owns_descriptors(false);
   6723     return new_map;
   6724   }
   6725 
   6726   // In case the map did not own its own descriptors, a split is forced by
   6727   // copying the map; creating a new descriptor array cell.
   6728   // Create a new free-floating map only if we are not allowed to store it.
   6729   Map* new_map;
   6730   MaybeObject* maybe_new_map = Copy();
   6731   if (!maybe_new_map->To(&new_map)) return maybe_new_map;
   6732 
   6733   new_map->set_elements_kind(kind);
   6734 
   6735   if (insert_transition) {
   6736     MaybeObject* added_elements = set_elements_transition_map(new_map);
   6737     if (added_elements->IsFailure()) return added_elements;
   6738     new_map->SetBackPointer(this);
   6739   }
   6740 
   6741   return new_map;
   6742 }
   6743 
   6744 
   6745 MaybeObject* Map::CopyForObserved() {
   6746   ASSERT(!is_observed());
   6747 
   6748   // In case the map owned its own descriptors, share the descriptors and
   6749   // transfer ownership to the new map.
   6750   Map* new_map;
   6751   MaybeObject* maybe_new_map;
   6752   if (owns_descriptors()) {
   6753     maybe_new_map = CopyDropDescriptors();
   6754   } else {
   6755     maybe_new_map = Copy();
   6756   }
   6757   if (!maybe_new_map->To(&new_map)) return maybe_new_map;
   6758 
   6759   TransitionArray* transitions;
   6760   MaybeObject* maybe_transitions = AddTransition(GetHeap()->observed_symbol(),
   6761                                                  new_map,
   6762                                                  FULL_TRANSITION);
   6763   if (!maybe_transitions->To(&transitions)) return maybe_transitions;
   6764   set_transitions(transitions);
   6765 
   6766   new_map->set_is_observed(true);
   6767 
   6768   if (owns_descriptors()) {
   6769     new_map->InitializeDescriptors(instance_descriptors());
   6770     set_owns_descriptors(false);
   6771   }
   6772 
   6773   new_map->SetBackPointer(this);
   6774   return new_map;
   6775 }
   6776 
   6777 
   6778 MaybeObject* Map::CopyWithPreallocatedFieldDescriptors() {
   6779   if (pre_allocated_property_fields() == 0) return CopyDropDescriptors();
   6780 
   6781   // If the map has pre-allocated properties always start out with a descriptor
   6782   // array describing these properties.
   6783   ASSERT(constructor()->IsJSFunction());
   6784   JSFunction* ctor = JSFunction::cast(constructor());
   6785   Map* map = ctor->initial_map();
   6786   DescriptorArray* descriptors = map->instance_descriptors();
   6787 
   6788   int number_of_own_descriptors = map->NumberOfOwnDescriptors();
   6789   DescriptorArray* new_descriptors;
   6790   MaybeObject* maybe_descriptors =
   6791       descriptors->CopyUpTo(number_of_own_descriptors);
   6792   if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
   6793 
   6794   return CopyReplaceDescriptors(new_descriptors, OMIT_TRANSITION);
   6795 }
   6796 
   6797 
   6798 Handle<Map> Map::Copy(Handle<Map> map) {
   6799   CALL_HEAP_FUNCTION(map->GetIsolate(), map->Copy(), Map);
   6800 }
   6801 
   6802 
   6803 MaybeObject* Map::Copy() {
   6804   DescriptorArray* descriptors = instance_descriptors();
   6805   DescriptorArray* new_descriptors;
   6806   int number_of_own_descriptors = NumberOfOwnDescriptors();
   6807   MaybeObject* maybe_descriptors =
   6808       descriptors->CopyUpTo(number_of_own_descriptors);
   6809   if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
   6810 
   6811   return CopyReplaceDescriptors(new_descriptors, OMIT_TRANSITION);
   6812 }
   6813 
   6814 
   6815 MaybeObject* Map::CopyAddDescriptor(Descriptor* descriptor,
   6816                                     TransitionFlag flag) {
   6817   DescriptorArray* descriptors = instance_descriptors();
   6818 
   6819   // Ensure the key is unique.
   6820   MaybeObject* maybe_failure = descriptor->KeyToUniqueName();
   6821   if (maybe_failure->IsFailure()) return maybe_failure;
   6822 
   6823   int old_size = NumberOfOwnDescriptors();
   6824   int new_size = old_size + 1;
   6825 
   6826   if (flag == INSERT_TRANSITION &&
   6827       owns_descriptors() &&
   6828       CanHaveMoreTransitions()) {
   6829     return ShareDescriptor(descriptors, descriptor);
   6830   }
   6831 
   6832   DescriptorArray* new_descriptors;
   6833   MaybeObject* maybe_descriptors = DescriptorArray::Allocate(old_size, 1);
   6834   if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
   6835 
   6836   DescriptorArray::WhitenessWitness witness(new_descriptors);
   6837 
   6838   // Copy the descriptors, inserting a descriptor.
   6839   for (int i = 0; i < old_size; ++i) {
   6840     new_descriptors->CopyFrom(i, descriptors, i, witness);
   6841   }
   6842 
   6843   if (old_size != descriptors->number_of_descriptors()) {
   6844     new_descriptors->SetNumberOfDescriptors(new_size);
   6845     new_descriptors->Set(old_size, descriptor, witness);
   6846     new_descriptors->Sort();
   6847   } else {
   6848     new_descriptors->Append(descriptor, witness);
   6849   }
   6850 
   6851   Name* key = descriptor->GetKey();
   6852   return CopyReplaceDescriptors(new_descriptors, flag, key, SIMPLE_TRANSITION);
   6853 }
   6854 
   6855 
   6856 MaybeObject* Map::CopyInsertDescriptor(Descriptor* descriptor,
   6857                                        TransitionFlag flag) {
   6858   DescriptorArray* old_descriptors = instance_descriptors();
   6859 
   6860   // Ensure the key is unique.
   6861   MaybeObject* maybe_result = descriptor->KeyToUniqueName();
   6862   if (maybe_result->IsFailure()) return maybe_result;
   6863 
   6864   // We replace the key if it is already present.
   6865   int index = old_descriptors->SearchWithCache(descriptor->GetKey(), this);
   6866   if (index != DescriptorArray::kNotFound) {
   6867     return CopyReplaceDescriptor(old_descriptors, descriptor, index, flag);
   6868   }
   6869   return CopyAddDescriptor(descriptor, flag);
   6870 }
   6871 
   6872 
   6873 MaybeObject* DescriptorArray::CopyUpToAddAttributes(
   6874     int enumeration_index, PropertyAttributes attributes) {
   6875   if (enumeration_index == 0) return GetHeap()->empty_descriptor_array();
   6876 
   6877   int size = enumeration_index;
   6878 
   6879   DescriptorArray* descriptors;
   6880   MaybeObject* maybe_descriptors = Allocate(size);
   6881   if (!maybe_descriptors->To(&descriptors)) return maybe_descriptors;
   6882   DescriptorArray::WhitenessWitness witness(descriptors);
   6883 
   6884   if (attributes != NONE) {
   6885     for (int i = 0; i < size; ++i) {
   6886       Object* value = GetValue(i);
   6887       PropertyDetails details = GetDetails(i);
   6888       int mask = DONT_DELETE | DONT_ENUM;
   6889       // READ_ONLY is an invalid attribute for JS setters/getters.
   6890       if (details.type() != CALLBACKS || !value->IsAccessorPair()) {
   6891         mask |= READ_ONLY;
   6892       }
   6893       details = details.CopyAddAttributes(
   6894           static_cast<PropertyAttributes>(attributes & mask));
   6895       Descriptor desc(GetKey(i), value, details);
   6896       descriptors->Set(i, &desc, witness);
   6897     }
   6898   } else {
   6899     for (int i = 0; i < size; ++i) {
   6900       descriptors->CopyFrom(i, this, i, witness);
   6901     }
   6902   }
   6903 
   6904   if (number_of_descriptors() != enumeration_index) descriptors->Sort();
   6905 
   6906   return descriptors;
   6907 }
   6908 
   6909 
   6910 MaybeObject* Map::CopyReplaceDescriptor(DescriptorArray* descriptors,
   6911                                         Descriptor* descriptor,
   6912                                         int insertion_index,
   6913                                         TransitionFlag flag) {
   6914   // Ensure the key is unique.
   6915   MaybeObject* maybe_failure = descriptor->KeyToUniqueName();
   6916   if (maybe_failure->IsFailure()) return maybe_failure;
   6917 
   6918   Name* key = descriptor->GetKey();
   6919   ASSERT(key == descriptors->GetKey(insertion_index));
   6920 
   6921   int new_size = NumberOfOwnDescriptors();
   6922   ASSERT(0 <= insertion_index && insertion_index < new_size);
   6923 
   6924   ASSERT_LT(insertion_index, new_size);
   6925 
   6926   DescriptorArray* new_descriptors;
   6927   MaybeObject* maybe_descriptors = DescriptorArray::Allocate(new_size);
   6928   if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
   6929   DescriptorArray::WhitenessWitness witness(new_descriptors);
   6930 
   6931   for (int i = 0; i < new_size; ++i) {
   6932     if (i == insertion_index) {
   6933       new_descriptors->Set(i, descriptor, witness);
   6934     } else {
   6935       new_descriptors->CopyFrom(i, descriptors, i, witness);
   6936     }
   6937   }
   6938 
   6939   // Re-sort if descriptors were removed.
   6940   if (new_size != descriptors->length()) new_descriptors->Sort();
   6941 
   6942   SimpleTransitionFlag simple_flag =
   6943       (insertion_index == descriptors->number_of_descriptors() - 1)
   6944       ? SIMPLE_TRANSITION
   6945       : FULL_TRANSITION;
   6946   return CopyReplaceDescriptors(new_descriptors, flag, key, simple_flag);
   6947 }
   6948 
   6949 
   6950 void Map::UpdateCodeCache(Handle<Map> map,
   6951                           Handle<Name> name,
   6952                           Handle<Code> code) {
   6953   Isolate* isolate = map->GetIsolate();
   6954   CALL_HEAP_FUNCTION_VOID(isolate,
   6955                           map->UpdateCodeCache(*name, *code));
   6956 }
   6957 
   6958 
   6959 MaybeObject* Map::UpdateCodeCache(Name* name, Code* code) {
   6960   ASSERT(!is_shared() || code->allowed_in_shared_map_code_cache());
   6961 
   6962   // Allocate the code cache if not present.
   6963   if (code_cache()->IsFixedArray()) {
   6964     Object* result;
   6965     { MaybeObject* maybe_result = GetHeap()->AllocateCodeCache();
   6966       if (!maybe_result->ToObject(&result)) return maybe_result;
   6967     }
   6968     set_code_cache(result);
   6969   }
   6970 
   6971   // Update the code cache.
   6972   return CodeCache::cast(code_cache())->Update(name, code);
   6973 }
   6974 
   6975 
   6976 Object* Map::FindInCodeCache(Name* name, Code::Flags flags) {
   6977   // Do a lookup if a code cache exists.
   6978   if (!code_cache()->IsFixedArray()) {
   6979     return CodeCache::cast(code_cache())->Lookup(name, flags);
   6980   } else {
   6981     return GetHeap()->undefined_value();
   6982   }
   6983 }
   6984 
   6985 
   6986 int Map::IndexInCodeCache(Object* name, Code* code) {
   6987   // Get the internal index if a code cache exists.
   6988   if (!code_cache()->IsFixedArray()) {
   6989     return CodeCache::cast(code_cache())->GetIndex(name, code);
   6990   }
   6991   return -1;
   6992 }
   6993 
   6994 
   6995 void Map::RemoveFromCodeCache(Name* name, Code* code, int index) {
   6996   // No GC is supposed to happen between a call to IndexInCodeCache and
   6997   // RemoveFromCodeCache so the code cache must be there.
   6998   ASSERT(!code_cache()->IsFixedArray());
   6999   CodeCache::cast(code_cache())->RemoveByIndex(name, code, index);
   7000 }
   7001 
   7002 
   7003 // An iterator over all map transitions in an descriptor array, reusing the map
   7004 // field of the contens array while it is running.
   7005 class IntrusiveMapTransitionIterator {
   7006  public:
   7007   explicit IntrusiveMapTransitionIterator(TransitionArray* transition_array)
   7008       : transition_array_(transition_array) { }
   7009 
   7010   void Start() {
   7011     ASSERT(!IsIterating());
   7012     *TransitionArrayHeader() = Smi::FromInt(0);
   7013   }
   7014 
   7015   bool IsIterating() {
   7016     return (*TransitionArrayHeader())->IsSmi();
   7017   }
   7018 
   7019   Map* Next() {
   7020     ASSERT(IsIterating());
   7021     int index = Smi::cast(*TransitionArrayHeader())->value();
   7022     int number_of_transitions = transition_array_->number_of_transitions();
   7023     while (index < number_of_transitions) {
   7024       *TransitionArrayHeader() = Smi::FromInt(index + 1);
   7025       return transition_array_->GetTarget(index);
   7026     }
   7027 
   7028     *TransitionArrayHeader() = transition_array_->GetHeap()->fixed_array_map();
   7029     return NULL;
   7030   }
   7031 
   7032  private:
   7033   Object** TransitionArrayHeader() {
   7034     return HeapObject::RawField(transition_array_, TransitionArray::kMapOffset);
   7035   }
   7036 
   7037   TransitionArray* transition_array_;
   7038 };
   7039 
   7040 
   7041 // An iterator over all prototype transitions, reusing the map field of the
   7042 // underlying array while it is running.
   7043 class IntrusivePrototypeTransitionIterator {
   7044  public:
   7045   explicit IntrusivePrototypeTransitionIterator(HeapObject* proto_trans)
   7046       : proto_trans_(proto_trans) { }
   7047 
   7048   void Start() {
   7049     ASSERT(!IsIterating());
   7050     *Header() = Smi::FromInt(0);
   7051   }
   7052 
   7053   bool IsIterating() {
   7054     return (*Header())->IsSmi();
   7055   }
   7056 
   7057   Map* Next() {
   7058     ASSERT(IsIterating());
   7059     int transitionNumber = Smi::cast(*Header())->value();
   7060     if (transitionNumber < NumberOfTransitions()) {
   7061       *Header() = Smi::FromInt(transitionNumber + 1);
   7062       return GetTransition(transitionNumber);
   7063     }
   7064     *Header() = proto_trans_->GetHeap()->fixed_array_map();
   7065     return NULL;
   7066   }
   7067 
   7068  private:
   7069   Object** Header() {
   7070     return HeapObject::RawField(proto_trans_, FixedArray::kMapOffset);
   7071   }
   7072 
   7073   int NumberOfTransitions() {
   7074     FixedArray* proto_trans = reinterpret_cast<FixedArray*>(proto_trans_);
   7075     Object* num = proto_trans->get(Map::kProtoTransitionNumberOfEntriesOffset);
   7076     return Smi::cast(num)->value();
   7077   }
   7078 
   7079   Map* GetTransition(int transitionNumber) {
   7080     FixedArray* proto_trans = reinterpret_cast<FixedArray*>(proto_trans_);
   7081     return Map::cast(proto_trans->get(IndexFor(transitionNumber)));
   7082   }
   7083 
   7084   int IndexFor(int transitionNumber) {
   7085     return Map::kProtoTransitionHeaderSize +
   7086         Map::kProtoTransitionMapOffset +
   7087         transitionNumber * Map::kProtoTransitionElementsPerEntry;
   7088   }
   7089 
   7090   HeapObject* proto_trans_;
   7091 };
   7092 
   7093 
   7094 // To traverse the transition tree iteratively, we have to store two kinds of
   7095 // information in a map: The parent map in the traversal and which children of a
   7096 // node have already been visited. To do this without additional memory, we
   7097 // temporarily reuse two maps with known values:
   7098 //
   7099 //  (1) The map of the map temporarily holds the parent, and is restored to the
   7100 //      meta map afterwards.
   7101 //
   7102 //  (2) The info which children have already been visited depends on which part
   7103 //      of the map we currently iterate:
   7104 //
   7105 //    (a) If we currently follow normal map transitions, we temporarily store
   7106 //        the current index in the map of the FixedArray of the desciptor
   7107 //        array's contents, and restore it to the fixed array map afterwards.
   7108 //        Note that a single descriptor can have 0, 1, or 2 transitions.
   7109 //
   7110 //    (b) If we currently follow prototype transitions, we temporarily store
   7111 //        the current index in the map of the FixedArray holding the prototype
   7112 //        transitions, and restore it to the fixed array map afterwards.
   7113 //
   7114 // Note that the child iterator is just a concatenation of two iterators: One
   7115 // iterating over map transitions and one iterating over prototype transisitons.
   7116 class TraversableMap : public Map {
   7117  public:
   7118   // Record the parent in the traversal within this map. Note that this destroys
   7119   // this map's map!
   7120   void SetParent(TraversableMap* parent) { set_map_no_write_barrier(parent); }
   7121 
   7122   // Reset the current map's map, returning the parent previously stored in it.
   7123   TraversableMap* GetAndResetParent() {
   7124     TraversableMap* old_parent = static_cast<TraversableMap*>(map());
   7125     set_map_no_write_barrier(GetHeap()->meta_map());
   7126     return old_parent;
   7127   }
   7128 
   7129   // Start iterating over this map's children, possibly destroying a FixedArray
   7130   // map (see explanation above).
   7131   void ChildIteratorStart() {
   7132     if (HasTransitionArray()) {
   7133       if (HasPrototypeTransitions()) {
   7134         IntrusivePrototypeTransitionIterator(GetPrototypeTransitions()).Start();
   7135       }
   7136 
   7137       IntrusiveMapTransitionIterator(transitions()).Start();
   7138     }
   7139   }
   7140 
   7141   // If we have an unvisited child map, return that one and advance. If we have
   7142   // none, return NULL and reset any destroyed FixedArray maps.
   7143   TraversableMap* ChildIteratorNext() {
   7144     TransitionArray* transition_array = unchecked_transition_array();
   7145     if (!transition_array->map()->IsSmi() &&
   7146         !transition_array->IsTransitionArray()) {
   7147       return NULL;
   7148     }
   7149 
   7150     if (transition_array->HasPrototypeTransitions()) {
   7151       HeapObject* proto_transitions =
   7152           transition_array->UncheckedPrototypeTransitions();
   7153       IntrusivePrototypeTransitionIterator proto_iterator(proto_transitions);
   7154       if (proto_iterator.IsIterating()) {
   7155         Map* next = proto_iterator.Next();
   7156         if (next != NULL) return static_cast<TraversableMap*>(next);
   7157       }
   7158     }
   7159 
   7160     IntrusiveMapTransitionIterator transition_iterator(transition_array);
   7161     if (transition_iterator.IsIterating()) {
   7162       Map* next = transition_iterator.Next();
   7163       if (next != NULL) return static_cast<TraversableMap*>(next);
   7164     }
   7165 
   7166     return NULL;
   7167   }
   7168 };
   7169 
   7170 
   7171 // Traverse the transition tree in postorder without using the C++ stack by
   7172 // doing pointer reversal.
   7173 void Map::TraverseTransitionTree(TraverseCallback callback, void* data) {
   7174   TraversableMap* current = static_cast<TraversableMap*>(this);
   7175   current->ChildIteratorStart();
   7176   while (true) {
   7177     TraversableMap* child = current->ChildIteratorNext();
   7178     if (child != NULL) {
   7179       child->ChildIteratorStart();
   7180       child->SetParent(current);
   7181       current = child;
   7182     } else {
   7183       TraversableMap* parent = current->GetAndResetParent();
   7184       callback(current, data);
   7185       if (current == this) break;
   7186       current = parent;
   7187     }
   7188   }
   7189 }
   7190 
   7191 
   7192 MaybeObject* CodeCache::Update(Name* name, Code* code) {
   7193   // The number of monomorphic stubs for normal load/store/call IC's can grow to
   7194   // a large number and therefore they need to go into a hash table. They are
   7195   // used to load global properties from cells.
   7196   if (code->type() == Code::NORMAL) {
   7197     // Make sure that a hash table is allocated for the normal load code cache.
   7198     if (normal_type_cache()->IsUndefined()) {
   7199       Object* result;
   7200       { MaybeObject* maybe_result =
   7201             CodeCacheHashTable::Allocate(GetHeap(),
   7202                                          CodeCacheHashTable::kInitialSize);
   7203         if (!maybe_result->ToObject(&result)) return maybe_result;
   7204       }
   7205       set_normal_type_cache(result);
   7206     }
   7207     return UpdateNormalTypeCache(name, code);
   7208   } else {
   7209     ASSERT(default_cache()->IsFixedArray());
   7210     return UpdateDefaultCache(name, code);
   7211   }
   7212 }
   7213 
   7214 
   7215 MaybeObject* CodeCache::UpdateDefaultCache(Name* name, Code* code) {
   7216   // When updating the default code cache we disregard the type encoded in the
   7217   // flags. This allows call constant stubs to overwrite call field
   7218   // stubs, etc.
   7219   Code::Flags flags = Code::RemoveTypeFromFlags(code->flags());
   7220 
   7221   // First check whether we can update existing code cache without
   7222   // extending it.
   7223   FixedArray* cache = default_cache();
   7224   int length = cache->length();
   7225   int deleted_index = -1;
   7226   for (int i = 0; i < length; i += kCodeCacheEntrySize) {
   7227     Object* key = cache->get(i);
   7228     if (key->IsNull()) {
   7229       if (deleted_index < 0) deleted_index = i;
   7230       continue;
   7231     }
   7232     if (key->IsUndefined()) {
   7233       if (deleted_index >= 0) i = deleted_index;
   7234       cache->set(i + kCodeCacheEntryNameOffset, name);
   7235       cache->set(i + kCodeCacheEntryCodeOffset, code);
   7236       return this;
   7237     }
   7238     if (name->Equals(Name::cast(key))) {
   7239       Code::Flags found =
   7240           Code::cast(cache->get(i + kCodeCacheEntryCodeOffset))->flags();
   7241       if (Code::RemoveTypeFromFlags(found) == flags) {
   7242         cache->set(i + kCodeCacheEntryCodeOffset, code);
   7243         return this;
   7244       }
   7245     }
   7246   }
   7247 
   7248   // Reached the end of the code cache.  If there were deleted
   7249   // elements, reuse the space for the first of them.
   7250   if (deleted_index >= 0) {
   7251     cache->set(deleted_index + kCodeCacheEntryNameOffset, name);
   7252     cache->set(deleted_index + kCodeCacheEntryCodeOffset, code);
   7253     return this;
   7254   }
   7255 
   7256   // Extend the code cache with some new entries (at least one). Must be a
   7257   // multiple of the entry size.
   7258   int new_length = length + ((length >> 1)) + kCodeCacheEntrySize;
   7259   new_length = new_length - new_length % kCodeCacheEntrySize;
   7260   ASSERT((new_length % kCodeCacheEntrySize) == 0);
   7261   Object* result;
   7262   { MaybeObject* maybe_result = cache->CopySize(new_length);
   7263     if (!maybe_result->ToObject(&result)) return maybe_result;
   7264   }
   7265 
   7266   // Add the (name, code) pair to the new cache.
   7267   cache = FixedArray::cast(result);
   7268   cache->set(length + kCodeCacheEntryNameOffset, name);
   7269   cache->set(length + kCodeCacheEntryCodeOffset, code);
   7270   set_default_cache(cache);
   7271   return this;
   7272 }
   7273 
   7274 
   7275 MaybeObject* CodeCache::UpdateNormalTypeCache(Name* name, Code* code) {
   7276   // Adding a new entry can cause a new cache to be allocated.
   7277   CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
   7278   Object* new_cache;
   7279   { MaybeObject* maybe_new_cache = cache->Put(name, code);
   7280     if (!maybe_new_cache->ToObject(&new_cache)) return maybe_new_cache;
   7281   }
   7282   set_normal_type_cache(new_cache);
   7283   return this;
   7284 }
   7285 
   7286 
   7287 Object* CodeCache::Lookup(Name* name, Code::Flags flags) {
   7288   if (Code::ExtractTypeFromFlags(flags) == Code::NORMAL) {
   7289     return LookupNormalTypeCache(name, flags);
   7290   } else {
   7291     return LookupDefaultCache(name, flags);
   7292   }
   7293 }
   7294 
   7295 
   7296 Object* CodeCache::LookupDefaultCache(Name* name, Code::Flags flags) {
   7297   FixedArray* cache = default_cache();
   7298   int length = cache->length();
   7299   for (int i = 0; i < length; i += kCodeCacheEntrySize) {
   7300     Object* key = cache->get(i + kCodeCacheEntryNameOffset);
   7301     // Skip deleted elements.
   7302     if (key->IsNull()) continue;
   7303     if (key->IsUndefined()) return key;
   7304     if (name->Equals(Name::cast(key))) {
   7305       Code* code = Code::cast(cache->get(i + kCodeCacheEntryCodeOffset));
   7306       if (code->flags() == flags) {
   7307         return code;
   7308       }
   7309     }
   7310   }
   7311   return GetHeap()->undefined_value();
   7312 }
   7313 
   7314 
   7315 Object* CodeCache::LookupNormalTypeCache(Name* name, Code::Flags flags) {
   7316   if (!normal_type_cache()->IsUndefined()) {
   7317     CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
   7318     return cache->Lookup(name, flags);
   7319   } else {
   7320     return GetHeap()->undefined_value();
   7321   }
   7322 }
   7323 
   7324 
   7325 int CodeCache::GetIndex(Object* name, Code* code) {
   7326   if (code->type() == Code::NORMAL) {
   7327     if (normal_type_cache()->IsUndefined()) return -1;
   7328     CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
   7329     return cache->GetIndex(Name::cast(name), code->flags());
   7330   }
   7331 
   7332   FixedArray* array = default_cache();
   7333   int len = array->length();
   7334   for (int i = 0; i < len; i += kCodeCacheEntrySize) {
   7335     if (array->get(i + kCodeCacheEntryCodeOffset) == code) return i + 1;
   7336   }
   7337   return -1;
   7338 }
   7339 
   7340 
   7341 void CodeCache::RemoveByIndex(Object* name, Code* code, int index) {
   7342   if (code->type() == Code::NORMAL) {
   7343     ASSERT(!normal_type_cache()->IsUndefined());
   7344     CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache());
   7345     ASSERT(cache->GetIndex(Name::cast(name), code->flags()) == index);
   7346     cache->RemoveByIndex(index);
   7347   } else {
   7348     FixedArray* array = default_cache();
   7349     ASSERT(array->length() >= index && array->get(index)->IsCode());
   7350     // Use null instead of undefined for deleted elements to distinguish
   7351     // deleted elements from unused elements.  This distinction is used
   7352     // when looking up in the cache and when updating the cache.
   7353     ASSERT_EQ(1, kCodeCacheEntryCodeOffset - kCodeCacheEntryNameOffset);
   7354     array->set_null(index - 1);  // Name.
   7355     array->set_null(index);  // Code.
   7356   }
   7357 }
   7358 
   7359 
   7360 // The key in the code cache hash table consists of the property name and the
   7361 // code object. The actual match is on the name and the code flags. If a key
   7362 // is created using the flags and not a code object it can only be used for
   7363 // lookup not to create a new entry.
   7364 class CodeCacheHashTableKey : public HashTableKey {
   7365  public:
   7366   CodeCacheHashTableKey(Name* name, Code::Flags flags)
   7367       : name_(name), flags_(flags), code_(NULL) { }
   7368 
   7369   CodeCacheHashTableKey(Name* name, Code* code)
   7370       : name_(name),
   7371         flags_(code->flags()),
   7372         code_(code) { }
   7373 
   7374 
   7375   bool IsMatch(Object* other) {
   7376     if (!other->IsFixedArray()) return false;
   7377     FixedArray* pair = FixedArray::cast(other);
   7378     Name* name = Name::cast(pair->get(0));
   7379     Code::Flags flags = Code::cast(pair->get(1))->flags();
   7380     if (flags != flags_) {
   7381       return false;
   7382     }
   7383     return name_->Equals(name);
   7384   }
   7385 
   7386   static uint32_t NameFlagsHashHelper(Name* name, Code::Flags flags) {
   7387     return name->Hash() ^ flags;
   7388   }
   7389 
   7390   uint32_t Hash() { return NameFlagsHashHelper(name_, flags_); }
   7391 
   7392   uint32_t HashForObject(Object* obj) {
   7393     FixedArray* pair = FixedArray::cast(obj);
   7394     Name* name = Name::cast(pair->get(0));
   7395     Code* code = Code::cast(pair->get(1));
   7396     return NameFlagsHashHelper(name, code->flags());
   7397   }
   7398 
   7399   MUST_USE_RESULT MaybeObject* AsObject(Heap* heap) {
   7400     ASSERT(code_ != NULL);
   7401     Object* obj;
   7402     { MaybeObject* maybe_obj = heap->AllocateFixedArray(2);
   7403       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   7404     }
   7405     FixedArray* pair = FixedArray::cast(obj);
   7406     pair->set(0, name_);
   7407     pair->set(1, code_);
   7408     return pair;
   7409   }
   7410 
   7411  private:
   7412   Name* name_;
   7413   Code::Flags flags_;
   7414   // TODO(jkummerow): We should be able to get by without this.
   7415   Code* code_;
   7416 };
   7417 
   7418 
   7419 Object* CodeCacheHashTable::Lookup(Name* name, Code::Flags flags) {
   7420   CodeCacheHashTableKey key(name, flags);
   7421   int entry = FindEntry(&key);
   7422   if (entry == kNotFound) return GetHeap()->undefined_value();
   7423   return get(EntryToIndex(entry) + 1);
   7424 }
   7425 
   7426 
   7427 MaybeObject* CodeCacheHashTable::Put(Name* name, Code* code) {
   7428   CodeCacheHashTableKey key(name, code);
   7429   Object* obj;
   7430   { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
   7431     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   7432   }
   7433 
   7434   // Don't use |this|, as the table might have grown.
   7435   CodeCacheHashTable* cache = reinterpret_cast<CodeCacheHashTable*>(obj);
   7436 
   7437   int entry = cache->FindInsertionEntry(key.Hash());
   7438   Object* k;
   7439   { MaybeObject* maybe_k = key.AsObject(GetHeap());
   7440     if (!maybe_k->ToObject(&k)) return maybe_k;
   7441   }
   7442 
   7443   cache->set(EntryToIndex(entry), k);
   7444   cache->set(EntryToIndex(entry) + 1, code);
   7445   cache->ElementAdded();
   7446   return cache;
   7447 }
   7448 
   7449 
   7450 int CodeCacheHashTable::GetIndex(Name* name, Code::Flags flags) {
   7451   CodeCacheHashTableKey key(name, flags);
   7452   int entry = FindEntry(&key);
   7453   return (entry == kNotFound) ? -1 : entry;
   7454 }
   7455 
   7456 
   7457 void CodeCacheHashTable::RemoveByIndex(int index) {
   7458   ASSERT(index >= 0);
   7459   Heap* heap = GetHeap();
   7460   set(EntryToIndex(index), heap->the_hole_value());
   7461   set(EntryToIndex(index) + 1, heap->the_hole_value());
   7462   ElementRemoved();
   7463 }
   7464 
   7465 
   7466 void PolymorphicCodeCache::Update(Handle<PolymorphicCodeCache> cache,
   7467                                   MapHandleList* maps,
   7468                                   Code::Flags flags,
   7469                                   Handle<Code> code) {
   7470   Isolate* isolate = cache->GetIsolate();
   7471   CALL_HEAP_FUNCTION_VOID(isolate, cache->Update(maps, flags, *code));
   7472 }
   7473 
   7474 
   7475 MaybeObject* PolymorphicCodeCache::Update(MapHandleList* maps,
   7476                                           Code::Flags flags,
   7477                                           Code* code) {
   7478   // Initialize cache if necessary.
   7479   if (cache()->IsUndefined()) {
   7480     Object* result;
   7481     { MaybeObject* maybe_result =
   7482           PolymorphicCodeCacheHashTable::Allocate(
   7483               GetHeap(),
   7484               PolymorphicCodeCacheHashTable::kInitialSize);
   7485       if (!maybe_result->ToObject(&result)) return maybe_result;
   7486     }
   7487     set_cache(result);
   7488   } else {
   7489     // This entry shouldn't be contained in the cache yet.
   7490     ASSERT(PolymorphicCodeCacheHashTable::cast(cache())
   7491                ->Lookup(maps, flags)->IsUndefined());
   7492   }
   7493   PolymorphicCodeCacheHashTable* hash_table =
   7494       PolymorphicCodeCacheHashTable::cast(cache());
   7495   Object* new_cache;
   7496   { MaybeObject* maybe_new_cache = hash_table->Put(maps, flags, code);
   7497     if (!maybe_new_cache->ToObject(&new_cache)) return maybe_new_cache;
   7498   }
   7499   set_cache(new_cache);
   7500   return this;
   7501 }
   7502 
   7503 
   7504 Handle<Object> PolymorphicCodeCache::Lookup(MapHandleList* maps,
   7505                                             Code::Flags flags) {
   7506   if (!cache()->IsUndefined()) {
   7507     PolymorphicCodeCacheHashTable* hash_table =
   7508         PolymorphicCodeCacheHashTable::cast(cache());
   7509     return Handle<Object>(hash_table->Lookup(maps, flags), GetIsolate());
   7510   } else {
   7511     return GetIsolate()->factory()->undefined_value();
   7512   }
   7513 }
   7514 
   7515 
   7516 // Despite their name, object of this class are not stored in the actual
   7517 // hash table; instead they're temporarily used for lookups. It is therefore
   7518 // safe to have a weak (non-owning) pointer to a MapList as a member field.
   7519 class PolymorphicCodeCacheHashTableKey : public HashTableKey {
   7520  public:
   7521   // Callers must ensure that |maps| outlives the newly constructed object.
   7522   PolymorphicCodeCacheHashTableKey(MapHandleList* maps, int code_flags)
   7523       : maps_(maps),
   7524         code_flags_(code_flags) {}
   7525 
   7526   bool IsMatch(Object* other) {
   7527     MapHandleList other_maps(kDefaultListAllocationSize);
   7528     int other_flags;
   7529     FromObject(other, &other_flags, &other_maps);
   7530     if (code_flags_ != other_flags) return false;
   7531     if (maps_->length() != other_maps.length()) return false;
   7532     // Compare just the hashes first because it's faster.
   7533     int this_hash = MapsHashHelper(maps_, code_flags_);
   7534     int other_hash = MapsHashHelper(&other_maps, other_flags);
   7535     if (this_hash != other_hash) return false;
   7536 
   7537     // Full comparison: for each map in maps_, look for an equivalent map in
   7538     // other_maps. This implementation is slow, but probably good enough for
   7539     // now because the lists are short (<= 4 elements currently).
   7540     for (int i = 0; i < maps_->length(); ++i) {
   7541       bool match_found = false;
   7542       for (int j = 0; j < other_maps.length(); ++j) {
   7543         if (*(maps_->at(i)) == *(other_maps.at(j))) {
   7544           match_found = true;
   7545           break;
   7546         }
   7547       }
   7548       if (!match_found) return false;
   7549     }
   7550     return true;
   7551   }
   7552 
   7553   static uint32_t MapsHashHelper(MapHandleList* maps, int code_flags) {
   7554     uint32_t hash = code_flags;
   7555     for (int i = 0; i < maps->length(); ++i) {
   7556       hash ^= maps->at(i)->Hash();
   7557     }
   7558     return hash;
   7559   }
   7560 
   7561   uint32_t Hash() {
   7562     return MapsHashHelper(maps_, code_flags_);
   7563   }
   7564 
   7565   uint32_t HashForObject(Object* obj) {
   7566     MapHandleList other_maps(kDefaultListAllocationSize);
   7567     int other_flags;
   7568     FromObject(obj, &other_flags, &other_maps);
   7569     return MapsHashHelper(&other_maps, other_flags);
   7570   }
   7571 
   7572   MUST_USE_RESULT MaybeObject* AsObject(Heap* heap) {
   7573     Object* obj;
   7574     // The maps in |maps_| must be copied to a newly allocated FixedArray,
   7575     // both because the referenced MapList is short-lived, and because C++
   7576     // objects can't be stored in the heap anyway.
   7577     { MaybeObject* maybe_obj =
   7578           heap->AllocateUninitializedFixedArray(maps_->length() + 1);
   7579       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   7580     }
   7581     FixedArray* list = FixedArray::cast(obj);
   7582     list->set(0, Smi::FromInt(code_flags_));
   7583     for (int i = 0; i < maps_->length(); ++i) {
   7584       list->set(i + 1, *maps_->at(i));
   7585     }
   7586     return list;
   7587   }
   7588 
   7589  private:
   7590   static MapHandleList* FromObject(Object* obj,
   7591                                    int* code_flags,
   7592                                    MapHandleList* maps) {
   7593     FixedArray* list = FixedArray::cast(obj);
   7594     maps->Rewind(0);
   7595     *code_flags = Smi::cast(list->get(0))->value();
   7596     for (int i = 1; i < list->length(); ++i) {
   7597       maps->Add(Handle<Map>(Map::cast(list->get(i))));
   7598     }
   7599     return maps;
   7600   }
   7601 
   7602   MapHandleList* maps_;  // weak.
   7603   int code_flags_;
   7604   static const int kDefaultListAllocationSize = kMaxKeyedPolymorphism + 1;
   7605 };
   7606 
   7607 
   7608 Object* PolymorphicCodeCacheHashTable::Lookup(MapHandleList* maps,
   7609                                               int code_flags) {
   7610   PolymorphicCodeCacheHashTableKey key(maps, code_flags);
   7611   int entry = FindEntry(&key);
   7612   if (entry == kNotFound) return GetHeap()->undefined_value();
   7613   return get(EntryToIndex(entry) + 1);
   7614 }
   7615 
   7616 
   7617 MaybeObject* PolymorphicCodeCacheHashTable::Put(MapHandleList* maps,
   7618                                                 int code_flags,
   7619                                                 Code* code) {
   7620   PolymorphicCodeCacheHashTableKey key(maps, code_flags);
   7621   Object* obj;
   7622   { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
   7623     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   7624   }
   7625   PolymorphicCodeCacheHashTable* cache =
   7626       reinterpret_cast<PolymorphicCodeCacheHashTable*>(obj);
   7627   int entry = cache->FindInsertionEntry(key.Hash());
   7628   { MaybeObject* maybe_obj = key.AsObject(GetHeap());
   7629     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   7630   }
   7631   cache->set(EntryToIndex(entry), obj);
   7632   cache->set(EntryToIndex(entry) + 1, code);
   7633   cache->ElementAdded();
   7634   return cache;
   7635 }
   7636 
   7637 
   7638 MaybeObject* FixedArray::AddKeysFromJSArray(JSArray* array) {
   7639   ElementsAccessor* accessor = array->GetElementsAccessor();
   7640   MaybeObject* maybe_result =
   7641       accessor->AddElementsToFixedArray(array, array, this);
   7642   FixedArray* result;
   7643   if (!maybe_result->To<FixedArray>(&result)) return maybe_result;
   7644 #ifdef DEBUG
   7645   if (FLAG_enable_slow_asserts) {
   7646     for (int i = 0; i < result->length(); i++) {
   7647       Object* current = result->get(i);
   7648       ASSERT(current->IsNumber() || current->IsName());
   7649     }
   7650   }
   7651 #endif
   7652   return result;
   7653 }
   7654 
   7655 
   7656 MaybeObject* FixedArray::UnionOfKeys(FixedArray* other) {
   7657   ElementsAccessor* accessor = ElementsAccessor::ForArray(other);
   7658   MaybeObject* maybe_result =
   7659       accessor->AddElementsToFixedArray(NULL, NULL, this, other);
   7660   FixedArray* result;
   7661   if (!maybe_result->To(&result)) return maybe_result;
   7662 #ifdef DEBUG
   7663   if (FLAG_enable_slow_asserts) {
   7664     for (int i = 0; i < result->length(); i++) {
   7665       Object* current = result->get(i);
   7666       ASSERT(current->IsNumber() || current->IsName());
   7667     }
   7668   }
   7669 #endif
   7670   return result;
   7671 }
   7672 
   7673 
   7674 MaybeObject* FixedArray::CopySize(int new_length) {
   7675   Heap* heap = GetHeap();
   7676   if (new_length == 0) return heap->empty_fixed_array();
   7677   Object* obj;
   7678   { MaybeObject* maybe_obj = heap->AllocateFixedArray(new_length);
   7679     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   7680   }
   7681   FixedArray* result = FixedArray::cast(obj);
   7682   // Copy the content
   7683   DisallowHeapAllocation no_gc;
   7684   int len = length();
   7685   if (new_length < len) len = new_length;
   7686   // We are taking the map from the old fixed array so the map is sure to
   7687   // be an immortal immutable object.
   7688   result->set_map_no_write_barrier(map());
   7689   WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
   7690   for (int i = 0; i < len; i++) {
   7691     result->set(i, get(i), mode);
   7692   }
   7693   return result;
   7694 }
   7695 
   7696 
   7697 void FixedArray::CopyTo(int pos, FixedArray* dest, int dest_pos, int len) {
   7698   DisallowHeapAllocation no_gc;
   7699   WriteBarrierMode mode = dest->GetWriteBarrierMode(no_gc);
   7700   for (int index = 0; index < len; index++) {
   7701     dest->set(dest_pos+index, get(pos+index), mode);
   7702   }
   7703 }
   7704 
   7705 
   7706 #ifdef DEBUG
   7707 bool FixedArray::IsEqualTo(FixedArray* other) {
   7708   if (length() != other->length()) return false;
   7709   for (int i = 0 ; i < length(); ++i) {
   7710     if (get(i) != other->get(i)) return false;
   7711   }
   7712   return true;
   7713 }
   7714 #endif
   7715 
   7716 
   7717 MaybeObject* DescriptorArray::Allocate(int number_of_descriptors, int slack) {
   7718   Heap* heap = Isolate::Current()->heap();
   7719   // Do not use DescriptorArray::cast on incomplete object.
   7720   int size = number_of_descriptors + slack;
   7721   if (size == 0) return heap->empty_descriptor_array();
   7722   FixedArray* result;
   7723   // Allocate the array of keys.
   7724   MaybeObject* maybe_array = heap->AllocateFixedArray(LengthFor(size));
   7725   if (!maybe_array->To(&result)) return maybe_array;
   7726 
   7727   result->set(kDescriptorLengthIndex, Smi::FromInt(number_of_descriptors));
   7728   result->set(kEnumCacheIndex, Smi::FromInt(0));
   7729   return result;
   7730 }
   7731 
   7732 
   7733 void DescriptorArray::ClearEnumCache() {
   7734   set(kEnumCacheIndex, Smi::FromInt(0));
   7735 }
   7736 
   7737 
   7738 void DescriptorArray::SetEnumCache(FixedArray* bridge_storage,
   7739                                    FixedArray* new_cache,
   7740                                    Object* new_index_cache) {
   7741   ASSERT(bridge_storage->length() >= kEnumCacheBridgeLength);
   7742   ASSERT(new_index_cache->IsSmi() || new_index_cache->IsFixedArray());
   7743   ASSERT(!IsEmpty());
   7744   ASSERT(!HasEnumCache() || new_cache->length() > GetEnumCache()->length());
   7745   FixedArray::cast(bridge_storage)->
   7746     set(kEnumCacheBridgeCacheIndex, new_cache);
   7747   FixedArray::cast(bridge_storage)->
   7748     set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache);
   7749   set(kEnumCacheIndex, bridge_storage);
   7750 }
   7751 
   7752 
   7753 void DescriptorArray::CopyFrom(int dst_index,
   7754                                DescriptorArray* src,
   7755                                int src_index,
   7756                                const WhitenessWitness& witness) {
   7757   Object* value = src->GetValue(src_index);
   7758   PropertyDetails details = src->GetDetails(src_index);
   7759   Descriptor desc(src->GetKey(src_index), value, details);
   7760   Set(dst_index, &desc, witness);
   7761 }
   7762 
   7763 
   7764 // Generalize the |other| descriptor array by merging it into the (at least
   7765 // partly) updated |this| descriptor array.
   7766 // The method merges two descriptor array in three parts. Both descriptor arrays
   7767 // are identical up to |verbatim|. They also overlap in keys up to |valid|.
   7768 // Between |verbatim| and |valid|, the resulting descriptor type as well as the
   7769 // representation are generalized from both |this| and |other|. Beyond |valid|,
   7770 // the descriptors are copied verbatim from |other| up to |new_size|.
   7771 // In case of incompatible types, the type and representation of |other| is
   7772 // used.
   7773 MaybeObject* DescriptorArray::Merge(int verbatim,
   7774                                     int valid,
   7775                                     int new_size,
   7776                                     DescriptorArray* other) {
   7777   ASSERT(verbatim <= valid);
   7778   ASSERT(valid <= new_size);
   7779 
   7780   DescriptorArray* result;
   7781   // Allocate a new descriptor array large enough to hold the required
   7782   // descriptors, with minimally the exact same size as this descriptor array.
   7783   MaybeObject* maybe_descriptors = DescriptorArray::Allocate(
   7784       new_size, Max(new_size, other->number_of_descriptors()) - new_size);
   7785   if (!maybe_descriptors->To(&result)) return maybe_descriptors;
   7786   ASSERT(result->length() > length() ||
   7787          result->NumberOfSlackDescriptors() > 0 ||
   7788          result->number_of_descriptors() == other->number_of_descriptors());
   7789   ASSERT(result->number_of_descriptors() == new_size);
   7790 
   7791   DescriptorArray::WhitenessWitness witness(result);
   7792 
   7793   int descriptor;
   7794 
   7795   // 0 -> |verbatim|
   7796   int current_offset = 0;
   7797   for (descriptor = 0; descriptor < verbatim; descriptor++) {
   7798     if (GetDetails(descriptor).type() == FIELD) current_offset++;
   7799     result->CopyFrom(descriptor, this, descriptor, witness);
   7800   }
   7801 
   7802   // |verbatim| -> |valid|
   7803   for (; descriptor < valid; descriptor++) {
   7804     Name* key = GetKey(descriptor);
   7805     PropertyDetails details = GetDetails(descriptor);
   7806     PropertyDetails other_details = other->GetDetails(descriptor);
   7807 
   7808     if (details.type() == FIELD || other_details.type() == FIELD ||
   7809         (details.type() == CONSTANT &&
   7810          other_details.type() == CONSTANT &&
   7811          GetValue(descriptor) != other->GetValue(descriptor))) {
   7812       Representation representation =
   7813           details.representation().generalize(other_details.representation());
   7814       FieldDescriptor d(key,
   7815                         current_offset++,
   7816                         other_details.attributes(),
   7817                         representation);
   7818       result->Set(descriptor, &d, witness);
   7819     } else {
   7820       result->CopyFrom(descriptor, other, descriptor, witness);
   7821     }
   7822   }
   7823 
   7824   // |valid| -> |new_size|
   7825   for (; descriptor < new_size; descriptor++) {
   7826     PropertyDetails details = other->GetDetails(descriptor);
   7827     if (details.type() == FIELD) {
   7828       Name* key = other->GetKey(descriptor);
   7829       FieldDescriptor d(key,
   7830                         current_offset++,
   7831                         details.attributes(),
   7832                         details.representation());
   7833       result->Set(descriptor, &d, witness);
   7834     } else {
   7835       result->CopyFrom(descriptor, other, descriptor, witness);
   7836     }
   7837   }
   7838 
   7839   result->Sort();
   7840   return result;
   7841 }
   7842 
   7843 
   7844 // Checks whether a merge of |other| into |this| would return a copy of |this|.
   7845 bool DescriptorArray::IsMoreGeneralThan(int verbatim,
   7846                                         int valid,
   7847                                         int new_size,
   7848                                         DescriptorArray* other) {
   7849   ASSERT(verbatim <= valid);
   7850   ASSERT(valid <= new_size);
   7851   if (valid != new_size) return false;
   7852 
   7853   for (int descriptor = verbatim; descriptor < valid; descriptor++) {
   7854     PropertyDetails details = GetDetails(descriptor);
   7855     PropertyDetails other_details = other->GetDetails(descriptor);
   7856     if (!other_details.representation().fits_into(details.representation())) {
   7857       return false;
   7858     }
   7859     if (details.type() == CONSTANT) {
   7860       if (other_details.type() != CONSTANT) return false;
   7861       if (GetValue(descriptor) != other->GetValue(descriptor)) return false;
   7862     }
   7863   }
   7864 
   7865   return true;
   7866 }
   7867 
   7868 
   7869 // We need the whiteness witness since sort will reshuffle the entries in the
   7870 // descriptor array. If the descriptor array were to be black, the shuffling
   7871 // would move a slot that was already recorded as pointing into an evacuation
   7872 // candidate. This would result in missing updates upon evacuation.
   7873 void DescriptorArray::Sort() {
   7874   // In-place heap sort.
   7875   int len = number_of_descriptors();
   7876   // Reset sorting since the descriptor array might contain invalid pointers.
   7877   for (int i = 0; i < len; ++i) SetSortedKey(i, i);
   7878   // Bottom-up max-heap construction.
   7879   // Index of the last node with children
   7880   const int max_parent_index = (len / 2) - 1;
   7881   for (int i = max_parent_index; i >= 0; --i) {
   7882     int parent_index = i;
   7883     const uint32_t parent_hash = GetSortedKey(i)->Hash();
   7884     while (parent_index <= max_parent_index) {
   7885       int child_index = 2 * parent_index + 1;
   7886       uint32_t child_hash = GetSortedKey(child_index)->Hash();
   7887       if (child_index + 1 < len) {
   7888         uint32_t right_child_hash = GetSortedKey(child_index + 1)->Hash();
   7889         if (right_child_hash > child_hash) {
   7890           child_index++;
   7891           child_hash = right_child_hash;
   7892         }
   7893       }
   7894       if (child_hash <= parent_hash) break;
   7895       SwapSortedKeys(parent_index, child_index);
   7896       // Now element at child_index could be < its children.
   7897       parent_index = child_index;  // parent_hash remains correct.
   7898     }
   7899   }
   7900 
   7901   // Extract elements and create sorted array.
   7902   for (int i = len - 1; i > 0; --i) {
   7903     // Put max element at the back of the array.
   7904     SwapSortedKeys(0, i);
   7905     // Shift down the new top element.
   7906     int parent_index = 0;
   7907     const uint32_t parent_hash = GetSortedKey(parent_index)->Hash();
   7908     const int max_parent_index = (i / 2) - 1;
   7909     while (parent_index <= max_parent_index) {
   7910       int child_index = parent_index * 2 + 1;
   7911       uint32_t child_hash = GetSortedKey(child_index)->Hash();
   7912       if (child_index + 1 < i) {
   7913         uint32_t right_child_hash = GetSortedKey(child_index + 1)->Hash();
   7914         if (right_child_hash > child_hash) {
   7915           child_index++;
   7916           child_hash = right_child_hash;
   7917         }
   7918       }
   7919       if (child_hash <= parent_hash) break;
   7920       SwapSortedKeys(parent_index, child_index);
   7921       parent_index = child_index;
   7922     }
   7923   }
   7924   ASSERT(IsSortedNoDuplicates());
   7925 }
   7926 
   7927 
   7928 Handle<AccessorPair> AccessorPair::Copy(Handle<AccessorPair> pair) {
   7929   Handle<AccessorPair> copy = pair->GetIsolate()->factory()->NewAccessorPair();
   7930   copy->set_getter(pair->getter());
   7931   copy->set_setter(pair->setter());
   7932   return copy;
   7933 }
   7934 
   7935 
   7936 Object* AccessorPair::GetComponent(AccessorComponent component) {
   7937   Object* accessor = get(component);
   7938   return accessor->IsTheHole() ? GetHeap()->undefined_value() : accessor;
   7939 }
   7940 
   7941 
   7942 MaybeObject* DeoptimizationInputData::Allocate(int deopt_entry_count,
   7943                                                PretenureFlag pretenure) {
   7944   ASSERT(deopt_entry_count > 0);
   7945   return HEAP->AllocateFixedArray(LengthFor(deopt_entry_count),
   7946                                   pretenure);
   7947 }
   7948 
   7949 
   7950 MaybeObject* DeoptimizationOutputData::Allocate(int number_of_deopt_points,
   7951                                                 PretenureFlag pretenure) {
   7952   if (number_of_deopt_points == 0) return HEAP->empty_fixed_array();
   7953   return HEAP->AllocateFixedArray(LengthOfFixedArray(number_of_deopt_points),
   7954                                   pretenure);
   7955 }
   7956 
   7957 
   7958 #ifdef DEBUG
   7959 bool DescriptorArray::IsEqualTo(DescriptorArray* other) {
   7960   if (IsEmpty()) return other->IsEmpty();
   7961   if (other->IsEmpty()) return false;
   7962   if (length() != other->length()) return false;
   7963   for (int i = 0; i < length(); ++i) {
   7964     if (get(i) != other->get(i)) return false;
   7965   }
   7966   return true;
   7967 }
   7968 #endif
   7969 
   7970 
   7971 bool String::LooksValid() {
   7972   if (!Isolate::Current()->heap()->Contains(this)) return false;
   7973   return true;
   7974 }
   7975 
   7976 
   7977 String::FlatContent String::GetFlatContent() {
   7978   ASSERT(!AllowHeapAllocation::IsAllowed());
   7979   int length = this->length();
   7980   StringShape shape(this);
   7981   String* string = this;
   7982   int offset = 0;
   7983   if (shape.representation_tag() == kConsStringTag) {
   7984     ConsString* cons = ConsString::cast(string);
   7985     if (cons->second()->length() != 0) {
   7986       return FlatContent();
   7987     }
   7988     string = cons->first();
   7989     shape = StringShape(string);
   7990   }
   7991   if (shape.representation_tag() == kSlicedStringTag) {
   7992     SlicedString* slice = SlicedString::cast(string);
   7993     offset = slice->offset();
   7994     string = slice->parent();
   7995     shape = StringShape(string);
   7996     ASSERT(shape.representation_tag() != kConsStringTag &&
   7997            shape.representation_tag() != kSlicedStringTag);
   7998   }
   7999   if (shape.encoding_tag() == kOneByteStringTag) {
   8000     const uint8_t* start;
   8001     if (shape.representation_tag() == kSeqStringTag) {
   8002       start = SeqOneByteString::cast(string)->GetChars();
   8003     } else {
   8004       start = ExternalAsciiString::cast(string)->GetChars();
   8005     }
   8006     return FlatContent(Vector<const uint8_t>(start + offset, length));
   8007   } else {
   8008     ASSERT(shape.encoding_tag() == kTwoByteStringTag);
   8009     const uc16* start;
   8010     if (shape.representation_tag() == kSeqStringTag) {
   8011       start = SeqTwoByteString::cast(string)->GetChars();
   8012     } else {
   8013       start = ExternalTwoByteString::cast(string)->GetChars();
   8014     }
   8015     return FlatContent(Vector<const uc16>(start + offset, length));
   8016   }
   8017 }
   8018 
   8019 
   8020 SmartArrayPointer<char> String::ToCString(AllowNullsFlag allow_nulls,
   8021                                           RobustnessFlag robust_flag,
   8022                                           int offset,
   8023                                           int length,
   8024                                           int* length_return) {
   8025   if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) {
   8026     return SmartArrayPointer<char>(NULL);
   8027   }
   8028   Heap* heap = GetHeap();
   8029 
   8030   // Negative length means the to the end of the string.
   8031   if (length < 0) length = kMaxInt - offset;
   8032 
   8033   // Compute the size of the UTF-8 string. Start at the specified offset.
   8034   Access<ConsStringIteratorOp> op(
   8035       heap->isolate()->objects_string_iterator());
   8036   StringCharacterStream stream(this, op.value(), offset);
   8037   int character_position = offset;
   8038   int utf8_bytes = 0;
   8039   int last = unibrow::Utf16::kNoPreviousCharacter;
   8040   while (stream.HasMore() && character_position++ < offset + length) {
   8041     uint16_t character = stream.GetNext();
   8042     utf8_bytes += unibrow::Utf8::Length(character, last);
   8043     last = character;
   8044   }
   8045 
   8046   if (length_return) {
   8047     *length_return = utf8_bytes;
   8048   }
   8049 
   8050   char* result = NewArray<char>(utf8_bytes + 1);
   8051 
   8052   // Convert the UTF-16 string to a UTF-8 buffer. Start at the specified offset.
   8053   stream.Reset(this, offset);
   8054   character_position = offset;
   8055   int utf8_byte_position = 0;
   8056   last = unibrow::Utf16::kNoPreviousCharacter;
   8057   while (stream.HasMore() && character_position++ < offset + length) {
   8058     uint16_t character = stream.GetNext();
   8059     if (allow_nulls == DISALLOW_NULLS && character == 0) {
   8060       character = ' ';
   8061     }
   8062     utf8_byte_position +=
   8063         unibrow::Utf8::Encode(result + utf8_byte_position, character, last);
   8064     last = character;
   8065   }
   8066   result[utf8_byte_position] = 0;
   8067   return SmartArrayPointer<char>(result);
   8068 }
   8069 
   8070 
   8071 SmartArrayPointer<char> String::ToCString(AllowNullsFlag allow_nulls,
   8072                                           RobustnessFlag robust_flag,
   8073                                           int* length_return) {
   8074   return ToCString(allow_nulls, robust_flag, 0, -1, length_return);
   8075 }
   8076 
   8077 
   8078 const uc16* String::GetTwoByteData() {
   8079   return GetTwoByteData(0);
   8080 }
   8081 
   8082 
   8083 const uc16* String::GetTwoByteData(unsigned start) {
   8084   ASSERT(!IsOneByteRepresentationUnderneath());
   8085   switch (StringShape(this).representation_tag()) {
   8086     case kSeqStringTag:
   8087       return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start);
   8088     case kExternalStringTag:
   8089       return ExternalTwoByteString::cast(this)->
   8090         ExternalTwoByteStringGetData(start);
   8091     case kSlicedStringTag: {
   8092       SlicedString* slice = SlicedString::cast(this);
   8093       return slice->parent()->GetTwoByteData(start + slice->offset());
   8094     }
   8095     case kConsStringTag:
   8096       UNREACHABLE();
   8097       return NULL;
   8098   }
   8099   UNREACHABLE();
   8100   return NULL;
   8101 }
   8102 
   8103 
   8104 SmartArrayPointer<uc16> String::ToWideCString(RobustnessFlag robust_flag) {
   8105   if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) {
   8106     return SmartArrayPointer<uc16>();
   8107   }
   8108   Heap* heap = GetHeap();
   8109 
   8110   Access<ConsStringIteratorOp> op(
   8111       heap->isolate()->objects_string_iterator());
   8112   StringCharacterStream stream(this, op.value());
   8113 
   8114   uc16* result = NewArray<uc16>(length() + 1);
   8115 
   8116   int i = 0;
   8117   while (stream.HasMore()) {
   8118     uint16_t character = stream.GetNext();
   8119     result[i++] = character;
   8120   }
   8121   result[i] = 0;
   8122   return SmartArrayPointer<uc16>(result);
   8123 }
   8124 
   8125 
   8126 const uc16* SeqTwoByteString::SeqTwoByteStringGetData(unsigned start) {
   8127   return reinterpret_cast<uc16*>(
   8128       reinterpret_cast<char*>(this) - kHeapObjectTag + kHeaderSize) + start;
   8129 }
   8130 
   8131 
   8132 void Relocatable::PostGarbageCollectionProcessing() {
   8133   Isolate* isolate = Isolate::Current();
   8134   Relocatable* current = isolate->relocatable_top();
   8135   while (current != NULL) {
   8136     current->PostGarbageCollection();
   8137     current = current->prev_;
   8138   }
   8139 }
   8140 
   8141 
   8142 // Reserve space for statics needing saving and restoring.
   8143 int Relocatable::ArchiveSpacePerThread() {
   8144   return sizeof(Isolate::Current()->relocatable_top());
   8145 }
   8146 
   8147 
   8148 // Archive statics that are thread local.
   8149 char* Relocatable::ArchiveState(Isolate* isolate, char* to) {
   8150   *reinterpret_cast<Relocatable**>(to) = isolate->relocatable_top();
   8151   isolate->set_relocatable_top(NULL);
   8152   return to + ArchiveSpacePerThread();
   8153 }
   8154 
   8155 
   8156 // Restore statics that are thread local.
   8157 char* Relocatable::RestoreState(Isolate* isolate, char* from) {
   8158   isolate->set_relocatable_top(*reinterpret_cast<Relocatable**>(from));
   8159   return from + ArchiveSpacePerThread();
   8160 }
   8161 
   8162 
   8163 char* Relocatable::Iterate(ObjectVisitor* v, char* thread_storage) {
   8164   Relocatable* top = *reinterpret_cast<Relocatable**>(thread_storage);
   8165   Iterate(v, top);
   8166   return thread_storage + ArchiveSpacePerThread();
   8167 }
   8168 
   8169 
   8170 void Relocatable::Iterate(ObjectVisitor* v) {
   8171   Isolate* isolate = Isolate::Current();
   8172   Iterate(v, isolate->relocatable_top());
   8173 }
   8174 
   8175 
   8176 void Relocatable::Iterate(ObjectVisitor* v, Relocatable* top) {
   8177   Relocatable* current = top;
   8178   while (current != NULL) {
   8179     current->IterateInstance(v);
   8180     current = current->prev_;
   8181   }
   8182 }
   8183 
   8184 
   8185 FlatStringReader::FlatStringReader(Isolate* isolate, Handle<String> str)
   8186     : Relocatable(isolate),
   8187       str_(str.location()),
   8188       length_(str->length()) {
   8189   PostGarbageCollection();
   8190 }
   8191 
   8192 
   8193 FlatStringReader::FlatStringReader(Isolate* isolate, Vector<const char> input)
   8194     : Relocatable(isolate),
   8195       str_(0),
   8196       is_ascii_(true),
   8197       length_(input.length()),
   8198       start_(input.start()) { }
   8199 
   8200 
   8201 void FlatStringReader::PostGarbageCollection() {
   8202   if (str_ == NULL) return;
   8203   Handle<String> str(str_);
   8204   ASSERT(str->IsFlat());
   8205   DisallowHeapAllocation no_gc;
   8206   // This does not actually prevent the vector from being relocated later.
   8207   String::FlatContent content = str->GetFlatContent();
   8208   ASSERT(content.IsFlat());
   8209   is_ascii_ = content.IsAscii();
   8210   if (is_ascii_) {
   8211     start_ = content.ToOneByteVector().start();
   8212   } else {
   8213     start_ = content.ToUC16Vector().start();
   8214   }
   8215 }
   8216 
   8217 
   8218 String* ConsStringIteratorOp::Operate(String* string,
   8219                                       unsigned* offset_out,
   8220                                       int32_t* type_out,
   8221                                       unsigned* length_out) {
   8222   ASSERT(string->IsConsString());
   8223   ConsString* cons_string = ConsString::cast(string);
   8224   // Set up search data.
   8225   root_ = cons_string;
   8226   consumed_ = *offset_out;
   8227   // Now search.
   8228   return Search(offset_out, type_out, length_out);
   8229 }
   8230 
   8231 
   8232 String* ConsStringIteratorOp::Search(unsigned* offset_out,
   8233                                      int32_t* type_out,
   8234                                      unsigned* length_out) {
   8235   ConsString* cons_string = root_;
   8236   // Reset the stack, pushing the root string.
   8237   depth_ = 1;
   8238   maximum_depth_ = 1;
   8239   frames_[0] = cons_string;
   8240   const unsigned consumed = consumed_;
   8241   unsigned offset = 0;
   8242   while (true) {
   8243     // Loop until the string is found which contains the target offset.
   8244     String* string = cons_string->first();
   8245     unsigned length = string->length();
   8246     int32_t type;
   8247     if (consumed < offset + length) {
   8248       // Target offset is in the left branch.
   8249       // Keep going if we're still in a ConString.
   8250       type = string->map()->instance_type();
   8251       if ((type & kStringRepresentationMask) == kConsStringTag) {
   8252         cons_string = ConsString::cast(string);
   8253         PushLeft(cons_string);
   8254         continue;
   8255       }
   8256       // Tell the stack we're done decending.
   8257       AdjustMaximumDepth();
   8258     } else {
   8259       // Descend right.
   8260       // Update progress through the string.
   8261       offset += length;
   8262       // Keep going if we're still in a ConString.
   8263       string = cons_string->second();
   8264       type = string->map()->instance_type();
   8265       if ((type & kStringRepresentationMask) == kConsStringTag) {
   8266         cons_string = ConsString::cast(string);
   8267         PushRight(cons_string);
   8268         // TODO(dcarney) Add back root optimization.
   8269         continue;
   8270       }
   8271       // Need this to be updated for the current string.
   8272       length = string->length();
   8273       // Account for the possibility of an empty right leaf.
   8274       // This happens only if we have asked for an offset outside the string.
   8275       if (length == 0) {
   8276         // Reset depth so future operations will return null immediately.
   8277         Reset();
   8278         return NULL;
   8279       }
   8280       // Tell the stack we're done decending.
   8281       AdjustMaximumDepth();
   8282       // Pop stack so next iteration is in correct place.
   8283       Pop();
   8284     }
   8285     ASSERT(length != 0);
   8286     // Adjust return values and exit.
   8287     consumed_ = offset + length;
   8288     *offset_out = consumed - offset;
   8289     *type_out = type;
   8290     *length_out = length;
   8291     return string;
   8292   }
   8293   UNREACHABLE();
   8294   return NULL;
   8295 }
   8296 
   8297 
   8298 String* ConsStringIteratorOp::NextLeaf(bool* blew_stack,
   8299                                        int32_t* type_out,
   8300                                        unsigned* length_out) {
   8301   while (true) {
   8302     // Tree traversal complete.
   8303     if (depth_ == 0) {
   8304       *blew_stack = false;
   8305       return NULL;
   8306     }
   8307     // We've lost track of higher nodes.
   8308     if (maximum_depth_ - depth_ == kStackSize) {
   8309       *blew_stack = true;
   8310       return NULL;
   8311     }
   8312     // Go right.
   8313     ConsString* cons_string = frames_[OffsetForDepth(depth_ - 1)];
   8314     String* string = cons_string->second();
   8315     int32_t type = string->map()->instance_type();
   8316     if ((type & kStringRepresentationMask) != kConsStringTag) {
   8317       // Pop stack so next iteration is in correct place.
   8318       Pop();
   8319       unsigned length = static_cast<unsigned>(string->length());
   8320       // Could be a flattened ConsString.
   8321       if (length == 0) continue;
   8322       *length_out = length;
   8323       *type_out = type;
   8324       consumed_ += length;
   8325       return string;
   8326     }
   8327     cons_string = ConsString::cast(string);
   8328     // TODO(dcarney) Add back root optimization.
   8329     PushRight(cons_string);
   8330     // Need to traverse all the way left.
   8331     while (true) {
   8332       // Continue left.
   8333       string = cons_string->first();
   8334       type = string->map()->instance_type();
   8335       if ((type & kStringRepresentationMask) != kConsStringTag) {
   8336         AdjustMaximumDepth();
   8337         unsigned length = static_cast<unsigned>(string->length());
   8338         ASSERT(length != 0);
   8339         *length_out = length;
   8340         *type_out = type;
   8341         consumed_ += length;
   8342         return string;
   8343       }
   8344       cons_string = ConsString::cast(string);
   8345       PushLeft(cons_string);
   8346     }
   8347   }
   8348   UNREACHABLE();
   8349   return NULL;
   8350 }
   8351 
   8352 
   8353 uint16_t ConsString::ConsStringGet(int index) {
   8354   ASSERT(index >= 0 && index < this->length());
   8355 
   8356   // Check for a flattened cons string
   8357   if (second()->length() == 0) {
   8358     String* left = first();
   8359     return left->Get(index);
   8360   }
   8361 
   8362   String* string = String::cast(this);
   8363 
   8364   while (true) {
   8365     if (StringShape(string).IsCons()) {
   8366       ConsString* cons_string = ConsString::cast(string);
   8367       String* left = cons_string->first();
   8368       if (left->length() > index) {
   8369         string = left;
   8370       } else {
   8371         index -= left->length();
   8372         string = cons_string->second();
   8373       }
   8374     } else {
   8375       return string->Get(index);
   8376     }
   8377   }
   8378 
   8379   UNREACHABLE();
   8380   return 0;
   8381 }
   8382 
   8383 
   8384 uint16_t SlicedString::SlicedStringGet(int index) {
   8385   return parent()->Get(offset() + index);
   8386 }
   8387 
   8388 
   8389 template <typename sinkchar>
   8390 void String::WriteToFlat(String* src,
   8391                          sinkchar* sink,
   8392                          int f,
   8393                          int t) {
   8394   String* source = src;
   8395   int from = f;
   8396   int to = t;
   8397   while (true) {
   8398     ASSERT(0 <= from && from <= to && to <= source->length());
   8399     switch (StringShape(source).full_representation_tag()) {
   8400       case kOneByteStringTag | kExternalStringTag: {
   8401         CopyChars(sink,
   8402                   ExternalAsciiString::cast(source)->GetChars() + from,
   8403                   to - from);
   8404         return;
   8405       }
   8406       case kTwoByteStringTag | kExternalStringTag: {
   8407         const uc16* data =
   8408             ExternalTwoByteString::cast(source)->GetChars();
   8409         CopyChars(sink,
   8410                   data + from,
   8411                   to - from);
   8412         return;
   8413       }
   8414       case kOneByteStringTag | kSeqStringTag: {
   8415         CopyChars(sink,
   8416                   SeqOneByteString::cast(source)->GetChars() + from,
   8417                   to - from);
   8418         return;
   8419       }
   8420       case kTwoByteStringTag | kSeqStringTag: {
   8421         CopyChars(sink,
   8422                   SeqTwoByteString::cast(source)->GetChars() + from,
   8423                   to - from);
   8424         return;
   8425       }
   8426       case kOneByteStringTag | kConsStringTag:
   8427       case kTwoByteStringTag | kConsStringTag: {
   8428         ConsString* cons_string = ConsString::cast(source);
   8429         String* first = cons_string->first();
   8430         int boundary = first->length();
   8431         if (to - boundary >= boundary - from) {
   8432           // Right hand side is longer.  Recurse over left.
   8433           if (from < boundary) {
   8434             WriteToFlat(first, sink, from, boundary);
   8435             sink += boundary - from;
   8436             from = 0;
   8437           } else {
   8438             from -= boundary;
   8439           }
   8440           to -= boundary;
   8441           source = cons_string->second();
   8442         } else {
   8443           // Left hand side is longer.  Recurse over right.
   8444           if (to > boundary) {
   8445             String* second = cons_string->second();
   8446             // When repeatedly appending to a string, we get a cons string that
   8447             // is unbalanced to the left, a list, essentially.  We inline the
   8448             // common case of sequential ascii right child.
   8449             if (to - boundary == 1) {
   8450               sink[boundary - from] = static_cast<sinkchar>(second->Get(0));
   8451             } else if (second->IsSeqOneByteString()) {
   8452               CopyChars(sink + boundary - from,
   8453                         SeqOneByteString::cast(second)->GetChars(),
   8454                         to - boundary);
   8455             } else {
   8456               WriteToFlat(second,
   8457                           sink + boundary - from,
   8458                           0,
   8459                           to - boundary);
   8460             }
   8461             to = boundary;
   8462           }
   8463           source = first;
   8464         }
   8465         break;
   8466       }
   8467       case kOneByteStringTag | kSlicedStringTag:
   8468       case kTwoByteStringTag | kSlicedStringTag: {
   8469         SlicedString* slice = SlicedString::cast(