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(source);
   8470         unsigned offset = slice->offset();
   8471         WriteToFlat(slice->parent(), sink, from + offset, to + offset);
   8472         return;
   8473       }
   8474     }
   8475   }
   8476 }
   8477 
   8478 
   8479 // Compares the contents of two strings by reading and comparing
   8480 // int-sized blocks of characters.
   8481 template <typename Char>
   8482 static inline bool CompareRawStringContents(const Char* const a,
   8483                                             const Char* const b,
   8484                                             int length) {
   8485   int i = 0;
   8486 #ifndef V8_HOST_CAN_READ_UNALIGNED
   8487   // If this architecture isn't comfortable reading unaligned ints
   8488   // then we have to check that the strings are aligned before
   8489   // comparing them blockwise.
   8490   const int kAlignmentMask = sizeof(uint32_t) - 1;  // NOLINT
   8491   uint32_t pa_addr = reinterpret_cast<uint32_t>(a);
   8492   uint32_t pb_addr = reinterpret_cast<uint32_t>(b);
   8493   if (((pa_addr & kAlignmentMask) | (pb_addr & kAlignmentMask)) == 0) {
   8494 #endif
   8495     const int kStepSize = sizeof(int) / sizeof(Char);  // NOLINT
   8496     int endpoint = length - kStepSize;
   8497     // Compare blocks until we reach near the end of the string.
   8498     for (; i <= endpoint; i += kStepSize) {
   8499       uint32_t wa = *reinterpret_cast<const uint32_t*>(a + i);
   8500       uint32_t wb = *reinterpret_cast<const uint32_t*>(b + i);
   8501       if (wa != wb) {
   8502         return false;
   8503       }
   8504     }
   8505 #ifndef V8_HOST_CAN_READ_UNALIGNED
   8506   }
   8507 #endif
   8508   // Compare the remaining characters that didn't fit into a block.
   8509   for (; i < length; i++) {
   8510     if (a[i] != b[i]) {
   8511       return false;
   8512     }
   8513   }
   8514   return true;
   8515 }
   8516 
   8517 
   8518 template<typename Chars1, typename Chars2>
   8519 class RawStringComparator : public AllStatic {
   8520  public:
   8521   static inline bool compare(const Chars1* a, const Chars2* b, int len) {
   8522     ASSERT(sizeof(Chars1) != sizeof(Chars2));
   8523     for (int i = 0; i < len; i++) {
   8524       if (a[i] != b[i]) {
   8525         return false;
   8526       }
   8527     }
   8528     return true;
   8529   }
   8530 };
   8531 
   8532 
   8533 template<>
   8534 class RawStringComparator<uint16_t, uint16_t> {
   8535  public:
   8536   static inline bool compare(const uint16_t* a, const uint16_t* b, int len) {
   8537     return CompareRawStringContents(a, b, len);
   8538   }
   8539 };
   8540 
   8541 
   8542 template<>
   8543 class RawStringComparator<uint8_t, uint8_t> {
   8544  public:
   8545   static inline bool compare(const uint8_t* a, const uint8_t* b, int len) {
   8546     return CompareRawStringContents(a, b, len);
   8547   }
   8548 };
   8549 
   8550 
   8551 class StringComparator {
   8552   class State {
   8553    public:
   8554     explicit inline State(ConsStringIteratorOp* op)
   8555       : op_(op), is_one_byte_(true), length_(0), buffer8_(NULL) {}
   8556 
   8557     inline void Init(String* string, unsigned len) {
   8558       op_->Reset();
   8559       int32_t type = string->map()->instance_type();
   8560       String::Visit(string, 0, *this, *op_, type, len);
   8561     }
   8562 
   8563     inline void VisitOneByteString(const uint8_t* chars, unsigned length) {
   8564       is_one_byte_ = true;
   8565       buffer8_ = chars;
   8566       length_ = length;
   8567     }
   8568 
   8569     inline void VisitTwoByteString(const uint16_t* chars, unsigned length) {
   8570       is_one_byte_ = false;
   8571       buffer16_ = chars;
   8572       length_ = length;
   8573     }
   8574 
   8575     void Advance(unsigned consumed) {
   8576       ASSERT(consumed <= length_);
   8577       // Still in buffer.
   8578       if (length_ != consumed) {
   8579         if (is_one_byte_) {
   8580           buffer8_ += consumed;
   8581         } else {
   8582           buffer16_ += consumed;
   8583         }
   8584         length_ -= consumed;
   8585         return;
   8586       }
   8587       // Advance state.
   8588       ASSERT(op_->HasMore());
   8589       int32_t type = 0;
   8590       unsigned length = 0;
   8591       String* next = op_->ContinueOperation(&type, &length);
   8592       ASSERT(next != NULL);
   8593       ConsStringNullOp null_op;
   8594       String::Visit(next, 0, *this, null_op, type, length);
   8595     }
   8596 
   8597     ConsStringIteratorOp* const op_;
   8598     bool is_one_byte_;
   8599     unsigned length_;
   8600     union {
   8601       const uint8_t* buffer8_;
   8602       const uint16_t* buffer16_;
   8603     };
   8604 
   8605    private:
   8606     DISALLOW_IMPLICIT_CONSTRUCTORS(State);
   8607   };
   8608 
   8609  public:
   8610   inline StringComparator(ConsStringIteratorOp* op_1,
   8611                           ConsStringIteratorOp* op_2)
   8612     : state_1_(op_1),
   8613       state_2_(op_2) {
   8614   }
   8615 
   8616   template<typename Chars1, typename Chars2>
   8617   static inline bool Equals(State* state_1, State* state_2, unsigned to_check) {
   8618     const Chars1* a = reinterpret_cast<const Chars1*>(state_1->buffer8_);
   8619     const Chars2* b = reinterpret_cast<const Chars2*>(state_2->buffer8_);
   8620     return RawStringComparator<Chars1, Chars2>::compare(a, b, to_check);
   8621   }
   8622 
   8623   bool Equals(unsigned length, String* string_1, String* string_2) {
   8624     ASSERT(length != 0);
   8625     state_1_.Init(string_1, length);
   8626     state_2_.Init(string_2, length);
   8627     while (true) {
   8628       unsigned to_check = Min(state_1_.length_, state_2_.length_);
   8629       ASSERT(to_check > 0 && to_check <= length);
   8630       bool is_equal;
   8631       if (state_1_.is_one_byte_) {
   8632         if (state_2_.is_one_byte_) {
   8633           is_equal = Equals<uint8_t, uint8_t>(&state_1_, &state_2_, to_check);
   8634         } else {
   8635           is_equal = Equals<uint8_t, uint16_t>(&state_1_, &state_2_, to_check);
   8636         }
   8637       } else {
   8638         if (state_2_.is_one_byte_) {
   8639           is_equal = Equals<uint16_t, uint8_t>(&state_1_, &state_2_, to_check);
   8640         } else {
   8641           is_equal = Equals<uint16_t, uint16_t>(&state_1_, &state_2_, to_check);
   8642         }
   8643       }
   8644       // Looping done.
   8645       if (!is_equal) return false;
   8646       length -= to_check;
   8647       // Exit condition. Strings are equal.
   8648       if (length == 0) return true;
   8649       state_1_.Advance(to_check);
   8650       state_2_.Advance(to_check);
   8651     }
   8652   }
   8653 
   8654  private:
   8655   State state_1_;
   8656   State state_2_;
   8657   DISALLOW_IMPLICIT_CONSTRUCTORS(StringComparator);
   8658 };
   8659 
   8660 
   8661 bool String::SlowEquals(String* other) {
   8662   // Fast check: negative check with lengths.
   8663   int len = length();
   8664   if (len != other->length()) return false;
   8665   if (len == 0) return true;
   8666 
   8667   // Fast check: if hash code is computed for both strings
   8668   // a fast negative check can be performed.
   8669   if (HasHashCode() && other->HasHashCode()) {
   8670 #ifdef DEBUG
   8671     if (FLAG_enable_slow_asserts) {
   8672       if (Hash() != other->Hash()) {
   8673         bool found_difference = false;
   8674         for (int i = 0; i < len; i++) {
   8675           if (Get(i) != other->Get(i)) {
   8676             found_difference = true;
   8677             break;
   8678           }
   8679         }
   8680         ASSERT(found_difference);
   8681       }
   8682     }
   8683 #endif
   8684     if (Hash() != other->Hash()) return false;
   8685   }
   8686 
   8687   // We know the strings are both non-empty. Compare the first chars
   8688   // before we try to flatten the strings.
   8689   if (this->Get(0) != other->Get(0)) return false;
   8690 
   8691   String* lhs = this->TryFlattenGetString();
   8692   String* rhs = other->TryFlattenGetString();
   8693 
   8694   // TODO(dcarney): Compare all types of flat strings with a Visitor.
   8695   if (StringShape(lhs).IsSequentialAscii() &&
   8696       StringShape(rhs).IsSequentialAscii()) {
   8697     const uint8_t* str1 = SeqOneByteString::cast(lhs)->GetChars();
   8698     const uint8_t* str2 = SeqOneByteString::cast(rhs)->GetChars();
   8699     return CompareRawStringContents(str1, str2, len);
   8700   }
   8701 
   8702   Isolate* isolate = GetIsolate();
   8703   StringComparator comparator(isolate->objects_string_compare_iterator_a(),
   8704                               isolate->objects_string_compare_iterator_b());
   8705 
   8706   return comparator.Equals(static_cast<unsigned>(len), lhs, rhs);
   8707 }
   8708 
   8709 
   8710 bool String::MarkAsUndetectable() {
   8711   if (StringShape(this).IsInternalized()) return false;
   8712 
   8713   Map* map = this->map();
   8714   Heap* heap = GetHeap();
   8715   if (map == heap->string_map()) {
   8716     this->set_map(heap->undetectable_string_map());
   8717     return true;
   8718   } else if (map == heap->ascii_string_map()) {
   8719     this->set_map(heap->undetectable_ascii_string_map());
   8720     return true;
   8721   }
   8722   // Rest cannot be marked as undetectable
   8723   return false;
   8724 }
   8725 
   8726 
   8727 bool String::IsUtf8EqualTo(Vector<const char> str, bool allow_prefix_match) {
   8728   int slen = length();
   8729   // Can't check exact length equality, but we can check bounds.
   8730   int str_len = str.length();
   8731   if (!allow_prefix_match &&
   8732       (str_len < slen ||
   8733           str_len > slen*static_cast<int>(unibrow::Utf8::kMaxEncodedSize))) {
   8734     return false;
   8735   }
   8736   int i;
   8737   unsigned remaining_in_str = static_cast<unsigned>(str_len);
   8738   const uint8_t* utf8_data = reinterpret_cast<const uint8_t*>(str.start());
   8739   for (i = 0; i < slen && remaining_in_str > 0; i++) {
   8740     unsigned cursor = 0;
   8741     uint32_t r = unibrow::Utf8::ValueOf(utf8_data, remaining_in_str, &cursor);
   8742     ASSERT(cursor > 0 && cursor <= remaining_in_str);
   8743     if (r > unibrow::Utf16::kMaxNonSurrogateCharCode) {
   8744       if (i > slen - 1) return false;
   8745       if (Get(i++) != unibrow::Utf16::LeadSurrogate(r)) return false;
   8746       if (Get(i) != unibrow::Utf16::TrailSurrogate(r)) return false;
   8747     } else {
   8748       if (Get(i) != r) return false;
   8749     }
   8750     utf8_data += cursor;
   8751     remaining_in_str -= cursor;
   8752   }
   8753   return (allow_prefix_match || i == slen) && remaining_in_str == 0;
   8754 }
   8755 
   8756 
   8757 bool String::IsOneByteEqualTo(Vector<const uint8_t> str) {
   8758   int slen = length();
   8759   if (str.length() != slen) return false;
   8760   DisallowHeapAllocation no_gc;
   8761   FlatContent content = GetFlatContent();
   8762   if (content.IsAscii()) {
   8763     return CompareChars(content.ToOneByteVector().start(),
   8764                         str.start(), slen) == 0;
   8765   }
   8766   for (int i = 0; i < slen; i++) {
   8767     if (Get(i) != static_cast<uint16_t>(str[i])) return false;
   8768   }
   8769   return true;
   8770 }
   8771 
   8772 
   8773 bool String::IsTwoByteEqualTo(Vector<const uc16> str) {
   8774   int slen = length();
   8775   if (str.length() != slen) return false;
   8776   DisallowHeapAllocation no_gc;
   8777   FlatContent content = GetFlatContent();
   8778   if (content.IsTwoByte()) {
   8779     return CompareChars(content.ToUC16Vector().start(), str.start(), slen) == 0;
   8780   }
   8781   for (int i = 0; i < slen; i++) {
   8782     if (Get(i) != str[i]) return false;
   8783   }
   8784   return true;
   8785 }
   8786 
   8787 
   8788 class IteratingStringHasher: public StringHasher {
   8789  public:
   8790   static inline uint32_t Hash(String* string, uint32_t seed) {
   8791     const unsigned len = static_cast<unsigned>(string->length());
   8792     IteratingStringHasher hasher(len, seed);
   8793     if (hasher.has_trivial_hash()) {
   8794       return hasher.GetHashField();
   8795     }
   8796     int32_t type = string->map()->instance_type();
   8797     ConsStringNullOp null_op;
   8798     String::Visit(string, 0, hasher, null_op, type, len);
   8799     // Flat strings terminate immediately.
   8800     if (hasher.consumed_ == len) {
   8801       ASSERT(!string->IsConsString());
   8802       return hasher.GetHashField();
   8803     }
   8804     ASSERT(string->IsConsString());
   8805     // This is a ConsString, iterate across it.
   8806     ConsStringIteratorOp op;
   8807     unsigned offset = 0;
   8808     unsigned leaf_length = len;
   8809     string = op.Operate(string, &offset, &type, &leaf_length);
   8810     while (true) {
   8811       ASSERT(hasher.consumed_ < len);
   8812       String::Visit(string, 0, hasher, null_op, type, leaf_length);
   8813       if (hasher.consumed_ == len) break;
   8814       string = op.ContinueOperation(&type, &leaf_length);
   8815       // This should be taken care of by the length check.
   8816       ASSERT(string != NULL);
   8817     }
   8818     return hasher.GetHashField();
   8819   }
   8820   inline void VisitOneByteString(const uint8_t* chars, unsigned length) {
   8821     AddCharacters(chars, static_cast<int>(length));
   8822     consumed_ += length;
   8823   }
   8824   inline void VisitTwoByteString(const uint16_t* chars, unsigned length) {
   8825     AddCharacters(chars, static_cast<int>(length));
   8826     consumed_ += length;
   8827   }
   8828 
   8829  private:
   8830   inline IteratingStringHasher(int len, uint32_t seed)
   8831     : StringHasher(len, seed),
   8832       consumed_(0) {}
   8833   unsigned consumed_;
   8834   DISALLOW_COPY_AND_ASSIGN(IteratingStringHasher);
   8835 };
   8836 
   8837 
   8838 uint32_t String::ComputeAndSetHash() {
   8839   // Should only be called if hash code has not yet been computed.
   8840   ASSERT(!HasHashCode());
   8841 
   8842   // Store the hash code in the object.
   8843   uint32_t field = IteratingStringHasher::Hash(this, GetHeap()->HashSeed());
   8844   set_hash_field(field);
   8845 
   8846   // Check the hash code is there.
   8847   ASSERT(HasHashCode());
   8848   uint32_t result = field >> kHashShift;
   8849   ASSERT(result != 0);  // Ensure that the hash value of 0 is never computed.
   8850   return result;
   8851 }
   8852 
   8853 
   8854 bool String::ComputeArrayIndex(uint32_t* index) {
   8855   int length = this->length();
   8856   if (length == 0 || length > kMaxArrayIndexSize) return false;
   8857   ConsStringIteratorOp op;
   8858   StringCharacterStream stream(this, &op);
   8859   uint16_t ch = stream.GetNext();
   8860 
   8861   // If the string begins with a '0' character, it must only consist
   8862   // of it to be a legal array index.
   8863   if (ch == '0') {
   8864     *index = 0;
   8865     return length == 1;
   8866   }
   8867 
   8868   // Convert string to uint32 array index; character by character.
   8869   int d = ch - '0';
   8870   if (d < 0 || d > 9) return false;
   8871   uint32_t result = d;
   8872   while (stream.HasMore()) {
   8873     d = stream.GetNext() - '0';
   8874     if (d < 0 || d > 9) return false;
   8875     // Check that the new result is below the 32 bit limit.
   8876     if (result > 429496729U - ((d > 5) ? 1 : 0)) return false;
   8877     result = (result * 10) + d;
   8878   }
   8879 
   8880   *index = result;
   8881   return true;
   8882 }
   8883 
   8884 
   8885 bool String::SlowAsArrayIndex(uint32_t* index) {
   8886   if (length() <= kMaxCachedArrayIndexLength) {
   8887     Hash();  // force computation of hash code
   8888     uint32_t field = hash_field();
   8889     if ((field & kIsNotArrayIndexMask) != 0) return false;
   8890     // Isolate the array index form the full hash field.
   8891     *index = (kArrayIndexHashMask & field) >> kHashShift;
   8892     return true;
   8893   } else {
   8894     return ComputeArrayIndex(index);
   8895   }
   8896 }
   8897 
   8898 
   8899 Handle<String> SeqString::Truncate(Handle<SeqString> string, int new_length) {
   8900   int new_size, old_size;
   8901   int old_length = string->length();
   8902   if (old_length <= new_length) return string;
   8903 
   8904   if (string->IsSeqOneByteString()) {
   8905     old_size = SeqOneByteString::SizeFor(old_length);
   8906     new_size = SeqOneByteString::SizeFor(new_length);
   8907   } else {
   8908     ASSERT(string->IsSeqTwoByteString());
   8909     old_size = SeqTwoByteString::SizeFor(old_length);
   8910     new_size = SeqTwoByteString::SizeFor(new_length);
   8911   }
   8912 
   8913   int delta = old_size - new_size;
   8914   string->set_length(new_length);
   8915 
   8916   Address start_of_string = string->address();
   8917   ASSERT_OBJECT_ALIGNED(start_of_string);
   8918   ASSERT_OBJECT_ALIGNED(start_of_string + new_size);
   8919 
   8920   Heap* heap = string->GetHeap();
   8921   NewSpace* newspace = heap->new_space();
   8922   if (newspace->Contains(start_of_string) &&
   8923       newspace->top() == start_of_string + old_size) {
   8924     // Last allocated object in new space.  Simply lower allocation top.
   8925     *(newspace->allocation_top_address()) = start_of_string + new_size;
   8926   } else {
   8927     // Sizes are pointer size aligned, so that we can use filler objects
   8928     // that are a multiple of pointer size.
   8929     heap->CreateFillerObjectAt(start_of_string + new_size, delta);
   8930   }
   8931   if (Marking::IsBlack(Marking::MarkBitFrom(start_of_string))) {
   8932     MemoryChunk::IncrementLiveBytesFromMutator(start_of_string, -delta);
   8933   }
   8934 
   8935 
   8936   if (new_length == 0) return heap->isolate()->factory()->empty_string();
   8937   return string;
   8938 }
   8939 
   8940 
   8941 AllocationMemento* AllocationMemento::FindForJSObject(JSObject* object) {
   8942   // Currently, AllocationMemento objects are only allocated immediately
   8943   // after JSArrays in NewSpace, and detecting whether a JSArray has one
   8944   // involves carefully checking the object immediately after the JSArray
   8945   // (if there is one) to see if it's an AllocationMemento.
   8946   if (FLAG_track_allocation_sites && object->GetHeap()->InNewSpace(object)) {
   8947     Address ptr_end = (reinterpret_cast<Address>(object) - kHeapObjectTag) +
   8948         object->Size();
   8949     if ((ptr_end + AllocationMemento::kSize) <=
   8950         object->GetHeap()->NewSpaceTop()) {
   8951       // There is room in newspace for allocation info. Do we have some?
   8952       Map** possible_allocation_memento_map =
   8953           reinterpret_cast<Map**>(ptr_end);
   8954       if (*possible_allocation_memento_map ==
   8955           object->GetHeap()->allocation_memento_map()) {
   8956         AllocationMemento* memento = AllocationMemento::cast(
   8957             reinterpret_cast<Object*>(ptr_end + 1));
   8958         return memento;
   8959       }
   8960     }
   8961   }
   8962   return NULL;
   8963 }
   8964 
   8965 
   8966 uint32_t StringHasher::MakeArrayIndexHash(uint32_t value, int length) {
   8967   // For array indexes mix the length into the hash as an array index could
   8968   // be zero.
   8969   ASSERT(length > 0);
   8970   ASSERT(length <= String::kMaxArrayIndexSize);
   8971   ASSERT(TenToThe(String::kMaxCachedArrayIndexLength) <
   8972          (1 << String::kArrayIndexValueBits));
   8973 
   8974   value <<= String::kHashShift;
   8975   value |= length << String::kArrayIndexHashLengthShift;
   8976 
   8977   ASSERT((value & String::kIsNotArrayIndexMask) == 0);
   8978   ASSERT((length > String::kMaxCachedArrayIndexLength) ||
   8979          (value & String::kContainsCachedArrayIndexMask) == 0);
   8980   return value;
   8981 }
   8982 
   8983 
   8984 uint32_t StringHasher::GetHashField() {
   8985   if (length_ <= String::kMaxHashCalcLength) {
   8986     if (is_array_index_) {
   8987       return MakeArrayIndexHash(array_index_, length_);
   8988     }
   8989     return (GetHashCore(raw_running_hash_) << String::kHashShift) |
   8990            String::kIsNotArrayIndexMask;
   8991   } else {
   8992     return (length_ << String::kHashShift) | String::kIsNotArrayIndexMask;
   8993   }
   8994 }
   8995 
   8996 
   8997 uint32_t StringHasher::ComputeUtf8Hash(Vector<const char> chars,
   8998                                        uint32_t seed,
   8999                                        int* utf16_length_out) {
   9000   int vector_length = chars.length();
   9001   // Handle some edge cases
   9002   if (vector_length <= 1) {
   9003     ASSERT(vector_length == 0 ||
   9004            static_cast<uint8_t>(chars.start()[0]) <=
   9005                unibrow::Utf8::kMaxOneByteChar);
   9006     *utf16_length_out = vector_length;
   9007     return HashSequentialString(chars.start(), vector_length, seed);
   9008   }
   9009   // Start with a fake length which won't affect computation.
   9010   // It will be updated later.
   9011   StringHasher hasher(String::kMaxArrayIndexSize, seed);
   9012   unsigned remaining = static_cast<unsigned>(vector_length);
   9013   const uint8_t* stream = reinterpret_cast<const uint8_t*>(chars.start());
   9014   int utf16_length = 0;
   9015   bool is_index = true;
   9016   ASSERT(hasher.is_array_index_);
   9017   while (remaining > 0) {
   9018     unsigned consumed = 0;
   9019     uint32_t c = unibrow::Utf8::ValueOf(stream, remaining, &consumed);
   9020     ASSERT(consumed > 0 && consumed <= remaining);
   9021     stream += consumed;
   9022     remaining -= consumed;
   9023     bool is_two_characters = c > unibrow::Utf16::kMaxNonSurrogateCharCode;
   9024     utf16_length += is_two_characters ? 2 : 1;
   9025     // No need to keep hashing. But we do need to calculate utf16_length.
   9026     if (utf16_length > String::kMaxHashCalcLength) continue;
   9027     if (is_two_characters) {
   9028       uint16_t c1 = unibrow::Utf16::LeadSurrogate(c);
   9029       uint16_t c2 = unibrow::Utf16::TrailSurrogate(c);
   9030       hasher.AddCharacter(c1);
   9031       hasher.AddCharacter(c2);
   9032       if (is_index) is_index = hasher.UpdateIndex(c1);
   9033       if (is_index) is_index = hasher.UpdateIndex(c2);
   9034     } else {
   9035       hasher.AddCharacter(c);
   9036       if (is_index) is_index = hasher.UpdateIndex(c);
   9037     }
   9038   }
   9039   *utf16_length_out = static_cast<int>(utf16_length);
   9040   // Must set length here so that hash computation is correct.
   9041   hasher.length_ = utf16_length;
   9042   return hasher.GetHashField();
   9043 }
   9044 
   9045 
   9046 MaybeObject* String::SubString(int start, int end, PretenureFlag pretenure) {
   9047   Heap* heap = GetHeap();
   9048   if (start == 0 && end == length()) return this;
   9049   MaybeObject* result = heap->AllocateSubString(this, start, end, pretenure);
   9050   return result;
   9051 }
   9052 
   9053 
   9054 void String::PrintOn(FILE* file) {
   9055   int length = this->length();
   9056   for (int i = 0; i < length; i++) {
   9057     PrintF(file, "%c", Get(i));
   9058   }
   9059 }
   9060 
   9061 
   9062 static void TrimEnumCache(Heap* heap, Map* map, DescriptorArray* descriptors) {
   9063   int live_enum = map->EnumLength();
   9064   if (live_enum == Map::kInvalidEnumCache) {
   9065     live_enum = map->NumberOfDescribedProperties(OWN_DESCRIPTORS, DONT_ENUM);
   9066   }
   9067   if (live_enum == 0) return descriptors->ClearEnumCache();
   9068 
   9069   FixedArray* enum_cache = descriptors->GetEnumCache();
   9070 
   9071   int to_trim = enum_cache->length() - live_enum;
   9072   if (to_trim <= 0) return;
   9073   RightTrimFixedArray<FROM_GC>(heap, descriptors->GetEnumCache(), to_trim);
   9074 
   9075   if (!descriptors->HasEnumIndicesCache()) return;
   9076   FixedArray* enum_indices_cache = descriptors->GetEnumIndicesCache();
   9077   RightTrimFixedArray<FROM_GC>(heap, enum_indices_cache, to_trim);
   9078 }
   9079 
   9080 
   9081 static void TrimDescriptorArray(Heap* heap,
   9082                                 Map* map,
   9083                                 DescriptorArray* descriptors,
   9084                                 int number_of_own_descriptors) {
   9085   int number_of_descriptors = descriptors->number_of_descriptors_storage();
   9086   int to_trim = number_of_descriptors - number_of_own_descriptors;
   9087   if (to_trim == 0) return;
   9088 
   9089   RightTrimFixedArray<FROM_GC>(
   9090       heap, descriptors, to_trim * DescriptorArray::kDescriptorSize);
   9091   descriptors->SetNumberOfDescriptors(number_of_own_descriptors);
   9092 
   9093   if (descriptors->HasEnumCache()) TrimEnumCache(heap, map, descriptors);
   9094   descriptors->Sort();
   9095 }
   9096 
   9097 
   9098 // Clear a possible back pointer in case the transition leads to a dead map.
   9099 // Return true in case a back pointer has been cleared and false otherwise.
   9100 static bool ClearBackPointer(Heap* heap, Map* target) {
   9101   if (Marking::MarkBitFrom(target).Get()) return false;
   9102   target->SetBackPointer(heap->undefined_value(), SKIP_WRITE_BARRIER);
   9103   return true;
   9104 }
   9105 
   9106 
   9107 // TODO(mstarzinger): This method should be moved into MarkCompactCollector,
   9108 // because it cannot be called from outside the GC and we already have methods
   9109 // depending on the transitions layout in the GC anyways.
   9110 void Map::ClearNonLiveTransitions(Heap* heap) {
   9111   // If there are no transitions to be cleared, return.
   9112   // TODO(verwaest) Should be an assert, otherwise back pointers are not
   9113   // properly cleared.
   9114   if (!HasTransitionArray()) return;
   9115 
   9116   TransitionArray* t = transitions();
   9117   MarkCompactCollector* collector = heap->mark_compact_collector();
   9118 
   9119   int transition_index = 0;
   9120 
   9121   DescriptorArray* descriptors = instance_descriptors();
   9122   bool descriptors_owner_died = false;
   9123 
   9124   // Compact all live descriptors to the left.
   9125   for (int i = 0; i < t->number_of_transitions(); ++i) {
   9126     Map* target = t->GetTarget(i);
   9127     if (ClearBackPointer(heap, target)) {
   9128       if (target->instance_descriptors() == descriptors) {
   9129         descriptors_owner_died = true;
   9130       }
   9131     } else {
   9132       if (i != transition_index) {
   9133         Name* key = t->GetKey(i);
   9134         t->SetKey(transition_index, key);
   9135         Object** key_slot = t->GetKeySlot(transition_index);
   9136         collector->RecordSlot(key_slot, key_slot, key);
   9137         // Target slots do not need to be recorded since maps are not compacted.
   9138         t->SetTarget(transition_index, t->GetTarget(i));
   9139       }
   9140       transition_index++;
   9141     }
   9142   }
   9143 
   9144   // If there are no transitions to be cleared, return.
   9145   // TODO(verwaest) Should be an assert, otherwise back pointers are not
   9146   // properly cleared.
   9147   if (transition_index == t->number_of_transitions()) return;
   9148 
   9149   int number_of_own_descriptors = NumberOfOwnDescriptors();
   9150 
   9151   if (descriptors_owner_died) {
   9152     if (number_of_own_descriptors > 0) {
   9153       TrimDescriptorArray(heap, this, descriptors, number_of_own_descriptors);
   9154       ASSERT(descriptors->number_of_descriptors() == number_of_own_descriptors);
   9155     } else {
   9156       ASSERT(descriptors == GetHeap()->empty_descriptor_array());
   9157     }
   9158   }
   9159 
   9160   int trim = t->number_of_transitions() - transition_index;
   9161   if (trim > 0) {
   9162     RightTrimFixedArray<FROM_GC>(heap, t, t->IsSimpleTransition()
   9163         ? trim : trim * TransitionArray::kTransitionSize);
   9164   }
   9165 }
   9166 
   9167 
   9168 int Map::Hash() {
   9169   // For performance reasons we only hash the 3 most variable fields of a map:
   9170   // constructor, prototype and bit_field2.
   9171 
   9172   // Shift away the tag.
   9173   int hash = (static_cast<uint32_t>(
   9174         reinterpret_cast<uintptr_t>(constructor())) >> 2);
   9175 
   9176   // XOR-ing the prototype and constructor directly yields too many zero bits
   9177   // when the two pointers are close (which is fairly common).
   9178   // To avoid this we shift the prototype 4 bits relatively to the constructor.
   9179   hash ^= (static_cast<uint32_t>(
   9180         reinterpret_cast<uintptr_t>(prototype())) << 2);
   9181 
   9182   return hash ^ (hash >> 16) ^ bit_field2();
   9183 }
   9184 
   9185 
   9186 static bool CheckEquivalent(Map* first, Map* second) {
   9187   return
   9188     first->constructor() == second->constructor() &&
   9189     first->prototype() == second->prototype() &&
   9190     first->instance_type() == second->instance_type() &&
   9191     first->bit_field() == second->bit_field() &&
   9192     first->bit_field2() == second->bit_field2() &&
   9193     first->is_observed() == second->is_observed() &&
   9194     first->function_with_prototype() == second->function_with_prototype();
   9195 }
   9196 
   9197 
   9198 bool Map::EquivalentToForTransition(Map* other) {
   9199   return CheckEquivalent(this, other);
   9200 }
   9201 
   9202 
   9203 bool Map::EquivalentToForNormalization(Map* other,
   9204                                        PropertyNormalizationMode mode) {
   9205   int properties = mode == CLEAR_INOBJECT_PROPERTIES
   9206       ? 0 : other->inobject_properties();
   9207   return CheckEquivalent(this, other) && inobject_properties() == properties;
   9208 }
   9209 
   9210 
   9211 void JSFunction::JSFunctionIterateBody(int object_size, ObjectVisitor* v) {
   9212   // Iterate over all fields in the body but take care in dealing with
   9213   // the code entry.
   9214   IteratePointers(v, kPropertiesOffset, kCodeEntryOffset);
   9215   v->VisitCodeEntry(this->address() + kCodeEntryOffset);
   9216   IteratePointers(v, kCodeEntryOffset + kPointerSize, object_size);
   9217 }
   9218 
   9219 
   9220 void JSFunction::MarkForLazyRecompilation() {
   9221   ASSERT(is_compiled() || GetIsolate()->DebuggerHasBreakPoints());
   9222   ASSERT(!IsOptimized());
   9223   ASSERT(shared()->allows_lazy_compilation() ||
   9224          code()->optimizable());
   9225   ASSERT(!shared()->is_generator());
   9226   set_code_no_write_barrier(
   9227       GetIsolate()->builtins()->builtin(Builtins::kLazyRecompile));
   9228   // No write barrier required, since the builtin is part of the root set.
   9229 }
   9230 
   9231 
   9232 void JSFunction::MarkForParallelRecompilation() {
   9233   ASSERT(is_compiled() || GetIsolate()->DebuggerHasBreakPoints());
   9234   ASSERT(!IsOptimized());
   9235   ASSERT(shared()->allows_lazy_compilation() || code()->optimizable());
   9236   ASSERT(!shared()->is_generator());
   9237   ASSERT(FLAG_parallel_recompilation);
   9238   if (FLAG_trace_parallel_recompilation) {
   9239     PrintF("  ** Marking ");
   9240     PrintName();
   9241     PrintF(" for parallel recompilation.\n");
   9242   }
   9243   set_code_no_write_barrier(
   9244       GetIsolate()->builtins()->builtin(Builtins::kParallelRecompile));
   9245   // No write barrier required, since the builtin is part of the root set.
   9246 }
   9247 
   9248 
   9249 void JSFunction::MarkForInstallingRecompiledCode() {
   9250   // The debugger could have switched the builtin to lazy compile.
   9251   // In that case, simply carry on.  It will be dealt with later.
   9252   ASSERT(!IsOptimized());
   9253   ASSERT(shared()->allows_lazy_compilation() || code()->optimizable());
   9254   ASSERT(FLAG_parallel_recompilation);
   9255   set_code_no_write_barrier(
   9256       GetIsolate()->builtins()->builtin(Builtins::kInstallRecompiledCode));
   9257   // No write barrier required, since the builtin is part of the root set.
   9258 }
   9259 
   9260 
   9261 void JSFunction::MarkInRecompileQueue() {
   9262   // We can only arrive here via the parallel-recompilation builtin.  If
   9263   // break points were set, the code would point to the lazy-compile builtin.
   9264   ASSERT(!GetIsolate()->DebuggerHasBreakPoints());
   9265   ASSERT(IsMarkedForParallelRecompilation() && !IsOptimized());
   9266   ASSERT(shared()->allows_lazy_compilation() || code()->optimizable());
   9267   ASSERT(FLAG_parallel_recompilation);
   9268   if (FLAG_trace_parallel_recompilation) {
   9269     PrintF("  ** Queueing ");
   9270     PrintName();
   9271     PrintF(" for parallel recompilation.\n");
   9272   }
   9273   set_code_no_write_barrier(
   9274       GetIsolate()->builtins()->builtin(Builtins::kInRecompileQueue));
   9275   // No write barrier required, since the builtin is part of the root set.
   9276 }
   9277 
   9278 
   9279 static bool CompileLazyHelper(CompilationInfo* info,
   9280                               ClearExceptionFlag flag) {
   9281   // Compile the source information to a code object.
   9282   ASSERT(info->IsOptimizing() || !info->shared_info()->is_compiled());
   9283   ASSERT(!info->isolate()->has_pending_exception());
   9284   bool result = Compiler::CompileLazy(info);
   9285   ASSERT(result != Isolate::Current()->has_pending_exception());
   9286   if (!result && flag == CLEAR_EXCEPTION) {
   9287     info->isolate()->clear_pending_exception();
   9288   }
   9289   return result;
   9290 }
   9291 
   9292 
   9293 bool SharedFunctionInfo::CompileLazy(Handle<SharedFunctionInfo> shared,
   9294                                      ClearExceptionFlag flag) {
   9295   ASSERT(shared->allows_lazy_compilation_without_context());
   9296   CompilationInfoWithZone info(shared);
   9297   return CompileLazyHelper(&info, flag);
   9298 }
   9299 
   9300 
   9301 void SharedFunctionInfo::AddToOptimizedCodeMap(
   9302     Handle<SharedFunctionInfo> shared,
   9303     Handle<Context> native_context,
   9304     Handle<Code> code,
   9305     Handle<FixedArray> literals) {
   9306   CALL_HEAP_FUNCTION_VOID(
   9307       shared->GetIsolate(),
   9308       shared->AddToOptimizedCodeMap(*native_context, *code, *literals));
   9309 }
   9310 
   9311 
   9312 MaybeObject* SharedFunctionInfo::AddToOptimizedCodeMap(Context* native_context,
   9313                                                        Code* code,
   9314                                                        FixedArray* literals) {
   9315   ASSERT(code->kind() == Code::OPTIMIZED_FUNCTION);
   9316   ASSERT(native_context->IsNativeContext());
   9317   STATIC_ASSERT(kEntryLength == 3);
   9318   Heap* heap = GetHeap();
   9319   FixedArray* new_code_map;
   9320   Object* value = optimized_code_map();
   9321   if (value->IsSmi()) {
   9322     // No optimized code map.
   9323     ASSERT_EQ(0, Smi::cast(value)->value());
   9324     // Crate 3 entries per context {context, code, literals}.
   9325     MaybeObject* maybe = heap->AllocateFixedArray(kInitialLength);
   9326     if (!maybe->To(&new_code_map)) return maybe;
   9327     new_code_map->set(kEntriesStart + 0, native_context);
   9328     new_code_map->set(kEntriesStart + 1, code);
   9329     new_code_map->set(kEntriesStart + 2, literals);
   9330   } else {
   9331     // Copy old map and append one new entry.
   9332     FixedArray* old_code_map = FixedArray::cast(value);
   9333     ASSERT_EQ(-1, SearchOptimizedCodeMap(native_context));
   9334     int old_length = old_code_map->length();
   9335     int new_length = old_length + kEntryLength;
   9336     MaybeObject* maybe = old_code_map->CopySize(new_length);
   9337     if (!maybe->To(&new_code_map)) return maybe;
   9338     new_code_map->set(old_length + 0, native_context);
   9339     new_code_map->set(old_length + 1, code);
   9340     new_code_map->set(old_length + 2, literals);
   9341     // Zap the old map for the sake of the heap verifier.
   9342     if (Heap::ShouldZapGarbage()) {
   9343       Object** data = old_code_map->data_start();
   9344       MemsetPointer(data, heap->the_hole_value(), old_length);
   9345     }
   9346   }
   9347 #ifdef DEBUG
   9348   for (int i = kEntriesStart; i < new_code_map->length(); i += kEntryLength) {
   9349     ASSERT(new_code_map->get(i)->IsNativeContext());
   9350     ASSERT(new_code_map->get(i + 1)->IsCode());
   9351     ASSERT(Code::cast(new_code_map->get(i + 1))->kind() ==
   9352            Code::OPTIMIZED_FUNCTION);
   9353     ASSERT(new_code_map->get(i + 2)->IsFixedArray());
   9354   }
   9355 #endif
   9356   set_optimized_code_map(new_code_map);
   9357   return new_code_map;
   9358 }
   9359 
   9360 
   9361 void SharedFunctionInfo::InstallFromOptimizedCodeMap(JSFunction* function,
   9362                                                      int index) {
   9363   ASSERT(index > kEntriesStart);
   9364   FixedArray* code_map = FixedArray::cast(optimized_code_map());
   9365   if (!bound()) {
   9366     FixedArray* cached_literals = FixedArray::cast(code_map->get(index + 1));
   9367     ASSERT(cached_literals != NULL);
   9368     function->set_literals(cached_literals);
   9369   }
   9370   Code* code = Code::cast(code_map->get(index));
   9371   ASSERT(code != NULL);
   9372   ASSERT(function->context()->native_context() == code_map->get(index - 1));
   9373   function->ReplaceCode(code);
   9374 }
   9375 
   9376 
   9377 void SharedFunctionInfo::ClearOptimizedCodeMap() {
   9378   FixedArray* code_map = FixedArray::cast(optimized_code_map());
   9379 
   9380   // If the next map link slot is already used then the function was
   9381   // enqueued with code flushing and we remove it now.
   9382   if (!code_map->get(kNextMapIndex)->IsUndefined()) {
   9383     CodeFlusher* flusher = GetHeap()->mark_compact_collector()->code_flusher();
   9384     flusher->EvictOptimizedCodeMap(this);
   9385   }
   9386 
   9387   ASSERT(code_map->get(kNextMapIndex)->IsUndefined());
   9388   set_optimized_code_map(Smi::FromInt(0));
   9389 }
   9390 
   9391 
   9392 void SharedFunctionInfo::EvictFromOptimizedCodeMap(Code* optimized_code,
   9393                                                    const char* reason) {
   9394   if (optimized_code_map()->IsSmi()) return;
   9395 
   9396   int i;
   9397   bool removed_entry = false;
   9398   FixedArray* code_map = FixedArray::cast(optimized_code_map());
   9399   for (i = kEntriesStart; i < code_map->length(); i += kEntryLength) {
   9400     ASSERT(code_map->get(i)->IsNativeContext());
   9401     if (Code::cast(code_map->get(i + 1)) == optimized_code) {
   9402       if (FLAG_trace_opt) {
   9403         PrintF("[evicting entry from optimizing code map (%s) for ", reason);
   9404         ShortPrint();
   9405         PrintF("]\n");
   9406       }
   9407       removed_entry = true;
   9408       break;
   9409     }
   9410   }
   9411   while (i < (code_map->length() - kEntryLength)) {
   9412     code_map->set(i, code_map->get(i + kEntryLength));
   9413     code_map->set(i + 1, code_map->get(i + 1 + kEntryLength));
   9414     code_map->set(i + 2, code_map->get(i + 2 + kEntryLength));
   9415     i += kEntryLength;
   9416   }
   9417   if (removed_entry) {
   9418     // Always trim even when array is cleared because of heap verifier.
   9419     RightTrimFixedArray<FROM_MUTATOR>(GetHeap(), code_map, kEntryLength);
   9420     if (code_map->length() == kEntriesStart) {
   9421       ClearOptimizedCodeMap();
   9422     }
   9423   }
   9424 }
   9425 
   9426 
   9427 void SharedFunctionInfo::TrimOptimizedCodeMap(int shrink_by) {
   9428   FixedArray* code_map = FixedArray::cast(optimized_code_map());
   9429   ASSERT(shrink_by % kEntryLength == 0);
   9430   ASSERT(shrink_by <= code_map->length() - kEntriesStart);
   9431   // Always trim even when array is cleared because of heap verifier.
   9432   RightTrimFixedArray<FROM_GC>(GetHeap(), code_map, shrink_by);
   9433   if (code_map->length() == kEntriesStart) {
   9434     ClearOptimizedCodeMap();
   9435   }
   9436 }
   9437 
   9438 
   9439 bool JSFunction::CompileLazy(Handle<JSFunction> function,
   9440                              ClearExceptionFlag flag) {
   9441   bool result = true;
   9442   if (function->shared()->is_compiled()) {
   9443     function->ReplaceCode(function->shared()->code());
   9444   } else {
   9445     ASSERT(function->shared()->allows_lazy_compilation());
   9446     CompilationInfoWithZone info(function);
   9447     result = CompileLazyHelper(&info, flag);
   9448     ASSERT(!result || function->is_compiled());
   9449   }
   9450   return result;
   9451 }
   9452 
   9453 
   9454 bool JSFunction::CompileOptimized(Handle<JSFunction> function,
   9455                                   BailoutId osr_ast_id,
   9456                                   ClearExceptionFlag flag) {
   9457   CompilationInfoWithZone info(function);
   9458   info.SetOptimizing(osr_ast_id);
   9459   return CompileLazyHelper(&info, flag);
   9460 }
   9461 
   9462 
   9463 bool JSFunction::EnsureCompiled(Handle<JSFunction> function,
   9464                                 ClearExceptionFlag flag) {
   9465   return function->is_compiled() || CompileLazy(function, flag);
   9466 }
   9467 
   9468 
   9469 bool JSFunction::IsInlineable() {
   9470   if (IsBuiltin()) return false;
   9471   SharedFunctionInfo* shared_info = shared();
   9472   // Check that the function has a script associated with it.
   9473   if (!shared_info->script()->IsScript()) return false;
   9474   if (shared_info->optimization_disabled()) return false;
   9475   Code* code = shared_info->code();
   9476   if (code->kind() == Code::OPTIMIZED_FUNCTION) return true;
   9477   // If we never ran this (unlikely) then lets try to optimize it.
   9478   if (code->kind() != Code::FUNCTION) return true;
   9479   return code->optimizable();
   9480 }
   9481 
   9482 
   9483 void JSObject::OptimizeAsPrototype(Handle<JSObject> object) {
   9484   CALL_HEAP_FUNCTION_VOID(object->GetIsolate(), object->OptimizeAsPrototype());
   9485 }
   9486 
   9487 
   9488 MaybeObject* JSObject::OptimizeAsPrototype() {
   9489   if (IsGlobalObject()) return this;
   9490 
   9491   // Make sure prototypes are fast objects and their maps have the bit set
   9492   // so they remain fast.
   9493   if (!HasFastProperties()) {
   9494     MaybeObject* new_proto = TransformToFastProperties(0);
   9495     if (new_proto->IsFailure()) return new_proto;
   9496     ASSERT(new_proto == this);
   9497   }
   9498   return this;
   9499 }
   9500 
   9501 
   9502 static MUST_USE_RESULT MaybeObject* CacheInitialJSArrayMaps(
   9503     Context* native_context, Map* initial_map) {
   9504   // Replace all of the cached initial array maps in the native context with
   9505   // the appropriate transitioned elements kind maps.
   9506   Heap* heap = native_context->GetHeap();
   9507   MaybeObject* maybe_maps =
   9508       heap->AllocateFixedArrayWithHoles(kElementsKindCount, TENURED);
   9509   FixedArray* maps;
   9510   if (!maybe_maps->To(&maps)) return maybe_maps;
   9511 
   9512   Map* current_map = initial_map;
   9513   ElementsKind kind = current_map->elements_kind();
   9514   ASSERT(kind == GetInitialFastElementsKind());
   9515   maps->set(kind, current_map);
   9516   for (int i = GetSequenceIndexFromFastElementsKind(kind) + 1;
   9517        i < kFastElementsKindCount; ++i) {
   9518     Map* new_map;
   9519     ElementsKind next_kind = GetFastElementsKindFromSequenceIndex(i);
   9520     if (current_map->HasElementsTransition()) {
   9521       new_map = current_map->elements_transition_map();
   9522       ASSERT(new_map->elements_kind() == next_kind);
   9523     } else {
   9524       MaybeObject* maybe_new_map =
   9525           current_map->CopyAsElementsKind(next_kind, INSERT_TRANSITION);
   9526       if (!maybe_new_map->To(&new_map)) return maybe_new_map;
   9527     }
   9528     maps->set(next_kind, new_map);
   9529     current_map = new_map;
   9530   }
   9531   native_context->set_js_array_maps(maps);
   9532   return initial_map;
   9533 }
   9534 
   9535 
   9536 Handle<Object> CacheInitialJSArrayMaps(Handle<Context> native_context,
   9537                                        Handle<Map> initial_map) {
   9538   CALL_HEAP_FUNCTION(native_context->GetIsolate(),
   9539                      CacheInitialJSArrayMaps(*native_context, *initial_map),
   9540                      Object);
   9541 }
   9542 
   9543 
   9544 void JSFunction::SetInstancePrototype(Handle<JSFunction> function,
   9545                                       Handle<Object> value) {
   9546   ASSERT(value->IsJSReceiver());
   9547 
   9548   // First some logic for the map of the prototype to make sure it is in fast
   9549   // mode.
   9550   if (value->IsJSObject()) {
   9551     JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(value));
   9552   }
   9553 
   9554   // Now some logic for the maps of the objects that are created by using this
   9555   // function as a constructor.
   9556   if (function->has_initial_map()) {
   9557     // If the function has allocated the initial map replace it with a
   9558     // copy containing the new prototype.  Also complete any in-object
   9559     // slack tracking that is in progress at this point because it is
   9560     // still tracking the old copy.
   9561     if (function->shared()->IsInobjectSlackTrackingInProgress()) {
   9562       function->shared()->CompleteInobjectSlackTracking();
   9563     }
   9564     Handle<Map> new_map = Map::Copy(handle(function->initial_map()));
   9565     new_map->set_prototype(*value);
   9566 
   9567     // If the function is used as the global Array function, cache the
   9568     // initial map (and transitioned versions) in the native context.
   9569     Context* native_context = function->context()->native_context();
   9570     Object* array_function = native_context->get(Context::ARRAY_FUNCTION_INDEX);
   9571     if (array_function->IsJSFunction() &&
   9572         *function == JSFunction::cast(array_function)) {
   9573       CacheInitialJSArrayMaps(handle(native_context), new_map);
   9574     }
   9575 
   9576     function->set_initial_map(*new_map);
   9577   } else {
   9578     // Put the value in the initial map field until an initial map is
   9579     // needed.  At that point, a new initial map is created and the
   9580     // prototype is put into the initial map where it belongs.
   9581     function->set_prototype_or_initial_map(*value);
   9582   }
   9583   function->GetHeap()->ClearInstanceofCache();
   9584 }
   9585 
   9586 
   9587 void JSFunction::SetPrototype(Handle<JSFunction> function,
   9588                               Handle<Object> value) {
   9589   ASSERT(function->should_have_prototype());
   9590   Handle<Object> construct_prototype = value;
   9591 
   9592   // If the value is not a JSReceiver, store the value in the map's
   9593   // constructor field so it can be accessed.  Also, set the prototype
   9594   // used for constructing objects to the original object prototype.
   9595   // See ECMA-262 13.2.2.
   9596   if (!value->IsJSReceiver()) {
   9597     // Copy the map so this does not affect unrelated functions.
   9598     // Remove map transitions because they point to maps with a
   9599     // different prototype.
   9600     Handle<Map> new_map = Map::Copy(handle(function->map()));
   9601 
   9602     function->set_map(*new_map);
   9603     new_map->set_constructor(*value);
   9604     new_map->set_non_instance_prototype(true);
   9605     Isolate* isolate = new_map->GetIsolate();
   9606     construct_prototype = handle(
   9607         isolate->context()->native_context()->initial_object_prototype(),
   9608         isolate);
   9609   } else {
   9610     function->map()->set_non_instance_prototype(false);
   9611   }
   9612 
   9613   return SetInstancePrototype(function, construct_prototype);
   9614 }
   9615 
   9616 
   9617 void JSFunction::RemovePrototype() {
   9618   Context* native_context = context()->native_context();
   9619   Map* no_prototype_map = shared()->is_classic_mode()
   9620       ? native_context->function_without_prototype_map()
   9621       : native_context->strict_mode_function_without_prototype_map();
   9622 
   9623   if (map() == no_prototype_map) return;
   9624 
   9625   ASSERT(map() == (shared()->is_classic_mode()
   9626                    ? native_context->function_map()
   9627                    : native_context->strict_mode_function_map()));
   9628 
   9629   set_map(no_prototype_map);
   9630   set_prototype_or_initial_map(no_prototype_map->GetHeap()->the_hole_value());
   9631 }
   9632 
   9633 
   9634 void JSFunction::SetInstanceClassName(String* name) {
   9635   shared()->set_instance_class_name(name);
   9636 }
   9637 
   9638 
   9639 void JSFunction::PrintName(FILE* out) {
   9640   SmartArrayPointer<char> name = shared()->DebugName()->ToCString();
   9641   PrintF(out, "%s", *name);
   9642 }
   9643 
   9644 
   9645 Context* JSFunction::NativeContextFromLiterals(FixedArray* literals) {
   9646   return Context::cast(literals->get(JSFunction::kLiteralNativeContextIndex));
   9647 }
   9648 
   9649 
   9650 bool JSFunction::PassesHydrogenFilter() {
   9651   String* name = shared()->DebugName();
   9652   // The filter string is a pattern that matches functions in this way:
   9653   //   "*"      all; the default
   9654   //   "-"      all but the top-level function
   9655   //   "-name"  all but the function "name"
   9656   //   ""       only the top-level function
   9657   //   "name"   only the function "name"
   9658   //   "name*"  only functions starting with "name"
   9659   if (*FLAG_hydrogen_filter != '*') {
   9660     Vector<const char> filter = CStrVector(FLAG_hydrogen_filter);
   9661     if (filter.length() == 0) return name->length() == 0;
   9662     if (filter[0] != '-' && name->IsUtf8EqualTo(filter)) return true;
   9663     if (filter[0] == '-' &&
   9664         !name->IsUtf8EqualTo(filter.SubVector(1, filter.length()))) {
   9665       return true;
   9666     }
   9667     if (filter[filter.length() - 1] == '*' &&
   9668         name->IsUtf8EqualTo(filter.SubVector(0, filter.length() - 1), true)) {
   9669       return true;
   9670     }
   9671     return false;
   9672   }
   9673 
   9674   return true;
   9675 }
   9676 
   9677 
   9678 MaybeObject* Oddball::Initialize(const char* to_string,
   9679                                  Object* to_number,
   9680                                  byte kind) {
   9681   String* internalized_to_string;
   9682   { MaybeObject* maybe_string =
   9683       Isolate::Current()->heap()->InternalizeUtf8String(
   9684           CStrVector(to_string));
   9685     if (!maybe_string->To(&internalized_to_string)) return maybe_string;
   9686   }
   9687   set_to_string(internalized_to_string);
   9688   set_to_number(to_number);
   9689   set_kind(kind);
   9690   return this;
   9691 }
   9692 
   9693 
   9694 String* SharedFunctionInfo::DebugName() {
   9695   Object* n = name();
   9696   if (!n->IsString() || String::cast(n)->length() == 0) return inferred_name();
   9697   return String::cast(n);
   9698 }
   9699 
   9700 
   9701 bool SharedFunctionInfo::HasSourceCode() {
   9702   return !script()->IsUndefined() &&
   9703          !reinterpret_cast<Script*>(script())->source()->IsUndefined();
   9704 }
   9705 
   9706 
   9707 Handle<Object> SharedFunctionInfo::GetSourceCode() {
   9708   if (!HasSourceCode()) return GetIsolate()->factory()->undefined_value();
   9709   Handle<String> source(String::cast(Script::cast(script())->source()));
   9710   return SubString(source, start_position(), end_position());
   9711 }
   9712 
   9713 
   9714 int SharedFunctionInfo::SourceSize() {
   9715   return end_position() - start_position();
   9716 }
   9717 
   9718 
   9719 int SharedFunctionInfo::CalculateInstanceSize() {
   9720   int instance_size =
   9721       JSObject::kHeaderSize +
   9722       expected_nof_properties() * kPointerSize;
   9723   if (instance_size > JSObject::kMaxInstanceSize) {
   9724     instance_size = JSObject::kMaxInstanceSize;
   9725   }
   9726   return instance_size;
   9727 }
   9728 
   9729 
   9730 int SharedFunctionInfo::CalculateInObjectProperties() {
   9731   return (CalculateInstanceSize() - JSObject::kHeaderSize) / kPointerSize;
   9732 }
   9733 
   9734 
   9735 // Support function for printing the source code to a StringStream
   9736 // without any allocation in the heap.
   9737 void SharedFunctionInfo::SourceCodePrint(StringStream* accumulator,
   9738                                          int max_length) {
   9739   // For some native functions there is no source.
   9740   if (!HasSourceCode()) {
   9741     accumulator->Add("<No Source>");
   9742     return;
   9743   }
   9744 
   9745   // Get the source for the script which this function came from.
   9746   // Don't use String::cast because we don't want more assertion errors while
   9747   // we are already creating a stack dump.
   9748   String* script_source =
   9749       reinterpret_cast<String*>(Script::cast(script())->source());
   9750 
   9751   if (!script_source->LooksValid()) {
   9752     accumulator->Add("<Invalid Source>");
   9753     return;
   9754   }
   9755 
   9756   if (!is_toplevel()) {
   9757     accumulator->Add("function ");
   9758     Object* name = this->name();
   9759     if (name->IsString() && String::cast(name)->length() > 0) {
   9760       accumulator->PrintName(name);
   9761     }
   9762   }
   9763 
   9764   int len = end_position() - start_position();
   9765   if (len <= max_length || max_length < 0) {
   9766     accumulator->Put(script_source, start_position(), end_position());
   9767   } else {
   9768     accumulator->Put(script_source,
   9769                      start_position(),
   9770                      start_position() + max_length);
   9771     accumulator->Add("...\n");
   9772   }
   9773 }
   9774 
   9775 
   9776 static bool IsCodeEquivalent(Code* code, Code* recompiled) {
   9777   if (code->instruction_size() != recompiled->instruction_size()) return false;
   9778   ByteArray* code_relocation = code->relocation_info();
   9779   ByteArray* recompiled_relocation = recompiled->relocation_info();
   9780   int length = code_relocation->length();
   9781   if (length != recompiled_relocation->length()) return false;
   9782   int compare = memcmp(code_relocation->GetDataStartAddress(),
   9783                        recompiled_relocation->GetDataStartAddress(),
   9784                        length);
   9785   return compare == 0;
   9786 }
   9787 
   9788 
   9789 void SharedFunctionInfo::EnableDeoptimizationSupport(Code* recompiled) {
   9790   ASSERT(!has_deoptimization_support());
   9791   DisallowHeapAllocation no_allocation;
   9792   Code* code = this->code();
   9793   if (IsCodeEquivalent(code, recompiled)) {
   9794     // Copy the deoptimization data from the recompiled code.
   9795     code->set_deoptimization_data(recompiled->deoptimization_data());
   9796     code->set_has_deoptimization_support(true);
   9797   } else {
   9798     // TODO(3025757): In case the recompiled isn't equivalent to the
   9799     // old code, we have to replace it. We should try to avoid this
   9800     // altogether because it flushes valuable type feedback by
   9801     // effectively resetting all IC state.
   9802     ReplaceCode(recompiled);
   9803   }
   9804   ASSERT(has_deoptimization_support());
   9805 }
   9806 
   9807 
   9808 void SharedFunctionInfo::DisableOptimization(BailoutReason reason) {
   9809   // Disable optimization for the shared function info and mark the
   9810   // code as non-optimizable. The marker on the shared function info
   9811   // is there because we flush non-optimized code thereby loosing the
   9812   // non-optimizable information for the code. When the code is
   9813   // regenerated and set on the shared function info it is marked as
   9814   // non-optimizable if optimization is disabled for the shared
   9815   // function info.
   9816   set_optimization_disabled(true);
   9817   // Code should be the lazy compilation stub or else unoptimized.  If the
   9818   // latter, disable optimization for the code too.
   9819   ASSERT(code()->kind() == Code::FUNCTION || code()->kind() == Code::BUILTIN);
   9820   if (code()->kind() == Code::FUNCTION) {
   9821     code()->set_optimizable(false);
   9822   }
   9823   if (FLAG_trace_opt) {
   9824     PrintF("[disabled optimization for ");
   9825     ShortPrint();
   9826     PrintF(", reason: %s]\n", GetBailoutReason(reason));
   9827   }
   9828 }
   9829 
   9830 
   9831 bool SharedFunctionInfo::VerifyBailoutId(BailoutId id) {
   9832   ASSERT(!id.IsNone());
   9833   Code* unoptimized = code();
   9834   DeoptimizationOutputData* data =
   9835       DeoptimizationOutputData::cast(unoptimized->deoptimization_data());
   9836   unsigned ignore = Deoptimizer::GetOutputInfo(data, id, this);
   9837   USE(ignore);
   9838   return true;  // Return true if there was no ASSERT.
   9839 }
   9840 
   9841 
   9842 void SharedFunctionInfo::StartInobjectSlackTracking(Map* map) {
   9843   ASSERT(!IsInobjectSlackTrackingInProgress());
   9844 
   9845   if (!FLAG_clever_optimizations) return;
   9846 
   9847   // Only initiate the tracking the first time.
   9848   if (live_objects_may_exist()) return;
   9849   set_live_objects_may_exist(true);
   9850 
   9851   // No tracking during the snapshot construction phase.
   9852   if (Serializer::enabled()) return;
   9853 
   9854   if (map->unused_property_fields() == 0) return;
   9855 
   9856   // Nonzero counter is a leftover from the previous attempt interrupted
   9857   // by GC, keep it.
   9858   if (construction_count() == 0) {
   9859     set_construction_count(kGenerousAllocationCount);
   9860   }
   9861   set_initial_map(map);
   9862   Builtins* builtins = map->GetHeap()->isolate()->builtins();
   9863   ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubGeneric),
   9864             construct_stub());
   9865   set_construct_stub(builtins->builtin(Builtins::kJSConstructStubCountdown));
   9866 }
   9867 
   9868 
   9869 // Called from GC, hence reinterpret_cast and unchecked accessors.
   9870 void SharedFunctionInfo::DetachInitialMap() {
   9871   Map* map = reinterpret_cast<Map*>(initial_map());
   9872 
   9873   // Make the map remember to restore the link if it survives the GC.
   9874   map->set_bit_field2(
   9875       map->bit_field2() | (1 << Map::kAttachedToSharedFunctionInfo));
   9876 
   9877   // Undo state changes made by StartInobjectTracking (except the
   9878   // construction_count). This way if the initial map does not survive the GC
   9879   // then StartInobjectTracking will be called again the next time the
   9880   // constructor is called. The countdown will continue and (possibly after
   9881   // several more GCs) CompleteInobjectSlackTracking will eventually be called.
   9882   Heap* heap = map->GetHeap();
   9883   set_initial_map(heap->undefined_value());
   9884   Builtins* builtins = heap->isolate()->builtins();
   9885   ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubCountdown),
   9886             *RawField(this, kConstructStubOffset));
   9887   set_construct_stub(builtins->builtin(Builtins::kJSConstructStubGeneric));
   9888   // It is safe to clear the flag: it will be set again if the map is live.
   9889   set_live_objects_may_exist(false);
   9890 }
   9891 
   9892 
   9893 // Called from GC, hence reinterpret_cast and unchecked accessors.
   9894 void SharedFunctionInfo::AttachInitialMap(Map* map) {
   9895   map->set_bit_field2(
   9896       map->bit_field2() & ~(1 << Map::kAttachedToSharedFunctionInfo));
   9897 
   9898   // Resume inobject slack tracking.
   9899   set_initial_map(map);
   9900   Builtins* builtins = map->GetHeap()->isolate()->builtins();
   9901   ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubGeneric),
   9902             *RawField(this, kConstructStubOffset));
   9903   set_construct_stub(builtins->builtin(Builtins::kJSConstructStubCountdown));
   9904   // The map survived the gc, so there may be objects referencing it.
   9905   set_live_objects_may_exist(true);
   9906 }
   9907 
   9908 
   9909 void SharedFunctionInfo::ResetForNewContext(int new_ic_age) {
   9910   code()->ClearInlineCaches();
   9911   set_ic_age(new_ic_age);
   9912   if (code()->kind() == Code::FUNCTION) {
   9913     code()->set_profiler_ticks(0);
   9914     if (optimization_disabled() &&
   9915         opt_count() >= FLAG_max_opt_count) {
   9916       // Re-enable optimizations if they were disabled due to opt_count limit.
   9917       set_optimization_disabled(false);
   9918       code()->set_optimizable(true);
   9919     }
   9920     set_opt_count(0);
   9921     set_deopt_count(0);
   9922   }
   9923 }
   9924 
   9925 
   9926 static void GetMinInobjectSlack(Map* map, void* data) {
   9927   int slack = map->unused_property_fields();
   9928   if (*reinterpret_cast<int*>(data) > slack) {
   9929     *reinterpret_cast<int*>(data) = slack;
   9930   }
   9931 }
   9932 
   9933 
   9934 static void ShrinkInstanceSize(Map* map, void* data) {
   9935   int slack = *reinterpret_cast<int*>(data);
   9936   map->set_inobject_properties(map->inobject_properties() - slack);
   9937   map->set_unused_property_fields(map->unused_property_fields() - slack);
   9938   map->set_instance_size(map->instance_size() - slack * kPointerSize);
   9939 
   9940   // Visitor id might depend on the instance size, recalculate it.
   9941   map->set_visitor_id(StaticVisitorBase::GetVisitorId(map));
   9942 }
   9943 
   9944 
   9945 void SharedFunctionInfo::CompleteInobjectSlackTracking() {
   9946   ASSERT(live_objects_may_exist() && IsInobjectSlackTrackingInProgress());
   9947   Map* map = Map::cast(initial_map());
   9948 
   9949   Heap* heap = map->GetHeap();
   9950   set_initial_map(heap->undefined_value());
   9951   Builtins* builtins = heap->isolate()->builtins();
   9952   ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubCountdown),
   9953             construct_stub());
   9954   set_construct_stub(builtins->builtin(Builtins::kJSConstructStubGeneric));
   9955 
   9956   int slack = map->unused_property_fields();
   9957   map->TraverseTransitionTree(&GetMinInobjectSlack, &slack);
   9958   if (slack != 0) {
   9959     // Resize the initial map and all maps in its transition tree.
   9960     map->TraverseTransitionTree(&ShrinkInstanceSize, &slack);
   9961 
   9962     // Give the correct expected_nof_properties to initial maps created later.
   9963     ASSERT(expected_nof_properties() >= slack);
   9964     set_expected_nof_properties(expected_nof_properties() - slack);
   9965   }
   9966 }
   9967 
   9968 
   9969 int SharedFunctionInfo::SearchOptimizedCodeMap(Context* native_context) {
   9970   ASSERT(native_context->IsNativeContext());
   9971   if (!FLAG_cache_optimized_code) return -1;
   9972   Object* value = optimized_code_map();
   9973   if (!value->IsSmi()) {
   9974     FixedArray* optimized_code_map = FixedArray::cast(value);
   9975     int length = optimized_code_map->length();
   9976     for (int i = kEntriesStart; i < length; i += kEntryLength) {
   9977       if (optimized_code_map->get(i) == native_context) {
   9978         return i + 1;
   9979       }
   9980     }
   9981     if (FLAG_trace_opt) {
   9982       PrintF("[didn't find optimized code in optimized code map for ");
   9983       ShortPrint();
   9984       PrintF("]\n");
   9985     }
   9986   }
   9987   return -1;
   9988 }
   9989 
   9990 
   9991 #define DECLARE_TAG(ignore1, name, ignore2) name,
   9992 const char* const VisitorSynchronization::kTags[
   9993     VisitorSynchronization::kNumberOfSyncTags] = {
   9994   VISITOR_SYNCHRONIZATION_TAGS_LIST(DECLARE_TAG)
   9995 };
   9996 #undef DECLARE_TAG
   9997 
   9998 
   9999 #define DECLARE_TAG(ignore1, ignore2, name) name,
   10000 const char* const VisitorSynchronization::kTagNames[
   10001     VisitorSynchronization::kNumberOfSyncTags] = {
   10002   VISITOR_SYNCHRONIZATION_TAGS_LIST(DECLARE_TAG)
   10003 };
   10004 #undef DECLARE_TAG
   10005 
   10006 
   10007 void ObjectVisitor::VisitCodeTarget(RelocInfo* rinfo) {
   10008   ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode()));
   10009   Object* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
   10010   Object* old_target = target;
   10011   VisitPointer(&target);
   10012   CHECK_EQ(target, old_target);  // VisitPointer doesn't change Code* *target.
   10013 }
   10014 
   10015 
   10016 void ObjectVisitor::VisitCodeAgeSequence(RelocInfo* rinfo) {
   10017   ASSERT(RelocInfo::IsCodeAgeSequence(rinfo->rmode()));
   10018   Object* stub = rinfo->code_age_stub();
   10019   if (stub) {
   10020     VisitPointer(&stub);
   10021   }
   10022 }
   10023 
   10024 
   10025 void ObjectVisitor::VisitCodeEntry(Address entry_address) {
   10026   Object* code = Code::GetObjectFromEntryAddress(entry_address);
   10027   Object* old_code = code;
   10028   VisitPointer(&code);
   10029   if (code != old_code) {
   10030     Memory::Address_at(entry_address) = reinterpret_cast<Code*>(code)->entry();
   10031   }
   10032 }
   10033 
   10034 
   10035 void ObjectVisitor::VisitCell(RelocInfo* rinfo) {
   10036   ASSERT(rinfo->rmode() == RelocInfo::CELL);
   10037   Object* cell = rinfo->target_cell();
   10038   Object* old_cell = cell;
   10039   VisitPointer(&cell);
   10040   if (cell != old_cell) {
   10041     rinfo->set_target_cell(reinterpret_cast<Cell*>(cell));
   10042   }
   10043 }
   10044 
   10045 
   10046 void ObjectVisitor::VisitDebugTarget(RelocInfo* rinfo) {
   10047   ASSERT((RelocInfo::IsJSReturn(rinfo->rmode()) &&
   10048           rinfo->IsPatchedReturnSequence()) ||
   10049          (RelocInfo::IsDebugBreakSlot(rinfo->rmode()) &&
   10050           rinfo->IsPatchedDebugBreakSlotSequence()));
   10051   Object* target = Code::GetCodeFromTargetAddress(rinfo->call_address());
   10052   Object* old_target = target;
   10053   VisitPointer(&target);
   10054   CHECK_EQ(target, old_target);  // VisitPointer doesn't change Code* *target.
   10055 }
   10056 
   10057 
   10058 void ObjectVisitor::VisitEmbeddedPointer(RelocInfo* rinfo) {
   10059   ASSERT(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT);
   10060   VisitPointer(rinfo->target_object_address());
   10061 }
   10062 
   10063 
   10064 void ObjectVisitor::VisitExternalReference(RelocInfo* rinfo) {
   10065   Address* p = rinfo->target_reference_address();
   10066   VisitExternalReferences(p, p + 1);
   10067 }
   10068 
   10069 
   10070 void Code::InvalidateRelocation() {
   10071   set_relocation_info(GetHeap()->empty_byte_array());
   10072 }
   10073 
   10074 
   10075 void Code::Relocate(intptr_t delta) {
   10076   for (RelocIterator it(this, RelocInfo::kApplyMask); !it.done(); it.next()) {
   10077     it.rinfo()->apply(delta);
   10078   }
   10079   CPU::FlushICache(instruction_start(), instruction_size());
   10080 }
   10081 
   10082 
   10083 void Code::CopyFrom(const CodeDesc& desc) {
   10084   ASSERT(Marking::Color(this) == Marking::WHITE_OBJECT);
   10085 
   10086   // copy code
   10087   CopyBytes(instruction_start(), desc.buffer,
   10088             static_cast<size_t>(desc.instr_size));
   10089 
   10090   // copy reloc info
   10091   CopyBytes(relocation_start(),
   10092             desc.buffer + desc.buffer_size - desc.reloc_size,
   10093             static_cast<size_t>(desc.reloc_size));
   10094 
   10095   // unbox handles and relocate
   10096   intptr_t delta = instruction_start() - desc.buffer;
   10097   int mode_mask = RelocInfo::kCodeTargetMask |
   10098                   RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
   10099                   RelocInfo::ModeMask(RelocInfo::CELL) |
   10100                   RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY) |
   10101                   RelocInfo::kApplyMask;
   10102   // Needed to find target_object and runtime_entry on X64
   10103   Assembler* origin = desc.origin;
   10104   AllowDeferredHandleDereference embedding_raw_address;
   10105   for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
   10106     RelocInfo::Mode mode = it.rinfo()->rmode();
   10107     if (mode == RelocInfo::EMBEDDED_OBJECT) {
   10108       Handle<Object> p = it.rinfo()->target_object_handle(origin);
   10109       it.rinfo()->set_target_object(*p, SKIP_WRITE_BARRIER);
   10110     } else if (mode == RelocInfo::CELL) {
   10111       Handle<Cell> cell  = it.rinfo()->target_cell_handle();
   10112       it.rinfo()->set_target_cell(*cell, SKIP_WRITE_BARRIER);
   10113     } else if (RelocInfo::IsCodeTarget(mode)) {
   10114       // rewrite code handles in inline cache targets to direct
   10115       // pointers to the first instruction in the code object
   10116       Handle<Object> p = it.rinfo()->target_object_handle(origin);
   10117       Code* code = Code::cast(*p);
   10118       it.rinfo()->set_target_address(code->instruction_start(),
   10119                                      SKIP_WRITE_BARRIER);
   10120     } else if (RelocInfo::IsRuntimeEntry(mode)) {
   10121       Address p = it.rinfo()->target_runtime_entry(origin);
   10122       it.rinfo()->set_target_runtime_entry(p, SKIP_WRITE_BARRIER);
   10123     } else {
   10124       it.rinfo()->apply(delta);
   10125     }
   10126   }
   10127   CPU::FlushICache(instruction_start(), instruction_size());
   10128 }
   10129 
   10130 
   10131 // Locate the source position which is closest to the address in the code. This
   10132 // is using the source position information embedded in the relocation info.
   10133 // The position returned is relative to the beginning of the script where the
   10134 // source for this function is found.
   10135 int Code::SourcePosition(Address pc) {
   10136   int distance = kMaxInt;
   10137   int position = RelocInfo::kNoPosition;  // Initially no position found.
   10138   // Run through all the relocation info to find the best matching source
   10139   // position. All the code needs to be considered as the sequence of the
   10140   // instructions in the code does not necessarily follow the same order as the
   10141   // source.
   10142   RelocIterator it(this, RelocInfo::kPositionMask);
   10143   while (!it.done()) {
   10144     // Only look at positions after the current pc.
   10145     if (it.rinfo()->pc() < pc) {
   10146       // Get position and distance.
   10147 
   10148       int dist = static_cast<int>(pc - it.rinfo()->pc());
   10149       int pos = static_cast<int>(it.rinfo()->data());
   10150       // If this position is closer than the current candidate or if it has the
   10151       // same distance as the current candidate and the position is higher then
   10152       // this position is the new candidate.
   10153       if ((dist < distance) ||
   10154           (dist == distance && pos > position)) {
   10155         position = pos;
   10156         distance = dist;
   10157       }
   10158     }
   10159     it.next();
   10160   }
   10161   return position;
   10162 }
   10163 
   10164 
   10165 // Same as Code::SourcePosition above except it only looks for statement
   10166 // positions.
   10167 int Code::SourceStatementPosition(Address pc) {
   10168   // First find the position as close as possible using all position
   10169   // information.
   10170   int position = SourcePosition(pc);
   10171   // Now find the closest statement position before the position.
   10172   int statement_position = 0;
   10173   RelocIterator it(this, RelocInfo::kPositionMask);
   10174   while (!it.done()) {
   10175     if (RelocInfo::IsStatementPosition(it.rinfo()->rmode())) {
   10176       int p = static_cast<int>(it.rinfo()->data());
   10177       if (statement_position < p && p <= position) {
   10178         statement_position = p;
   10179       }
   10180     }
   10181     it.next();
   10182   }
   10183   return statement_position;
   10184 }
   10185 
   10186 
   10187 SafepointEntry Code::GetSafepointEntry(Address pc) {
   10188   SafepointTable table(this);
   10189   return table.FindEntry(pc);
   10190 }
   10191 
   10192 
   10193 Object* Code::FindNthObject(int n, Map* match_map) {
   10194   ASSERT(is_inline_cache_stub());
   10195   DisallowHeapAllocation no_allocation;
   10196   int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
   10197   for (RelocIterator it(this, mask); !it.done(); it.next()) {
   10198     RelocInfo* info = it.rinfo();
   10199     Object* object = info->target_object();
   10200     if (object->IsHeapObject()) {
   10201       if (HeapObject::cast(object)->map() == match_map) {
   10202         if (--n == 0) return object;
   10203       }
   10204     }
   10205   }
   10206   return NULL;
   10207 }
   10208 
   10209 
   10210 Map* Code::FindFirstMap() {
   10211   Object* result = FindNthObject(1, GetHeap()->meta_map());
   10212   return (result != NULL) ? Map::cast(result) : NULL;
   10213 }
   10214 
   10215 
   10216 void Code::ReplaceNthObject(int n,
   10217                             Map* match_map,
   10218                             Object* replace_with) {
   10219   ASSERT(is_inline_cache_stub());
   10220   DisallowHeapAllocation no_allocation;
   10221   int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
   10222   for (RelocIterator it(this, mask); !it.done(); it.next()) {
   10223     RelocInfo* info = it.rinfo();
   10224     Object* object = info->target_object();
   10225     if (object->IsHeapObject()) {
   10226       if (HeapObject::cast(object)->map() == match_map) {
   10227         if (--n == 0) {
   10228           info->set_target_object(replace_with);
   10229           return;
   10230         }
   10231       }
   10232     }
   10233   }
   10234   UNREACHABLE();
   10235 }
   10236 
   10237 
   10238 void Code::FindAllMaps(MapHandleList* maps) {
   10239   ASSERT(is_inline_cache_stub());
   10240   DisallowHeapAllocation no_allocation;
   10241   int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
   10242   for (RelocIterator it(this, mask); !it.done(); it.next()) {
   10243     RelocInfo* info = it.rinfo();
   10244     Object* object = info->target_object();
   10245     if (object->IsMap()) maps->Add(Handle<Map>(Map::cast(object)));
   10246   }
   10247 }
   10248 
   10249 
   10250 void Code::ReplaceFirstMap(Map* replace_with) {
   10251   ReplaceNthObject(1, GetHeap()->meta_map(), replace_with);
   10252 }
   10253 
   10254 
   10255 Code* Code::FindFirstCode() {
   10256   ASSERT(is_inline_cache_stub());
   10257   DisallowHeapAllocation no_allocation;
   10258   int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET);
   10259   for (RelocIterator it(this, mask); !it.done(); it.next()) {
   10260     RelocInfo* info = it.rinfo();
   10261     return Code::GetCodeFromTargetAddress(info->target_address());
   10262   }
   10263   return NULL;
   10264 }
   10265 
   10266 
   10267 void Code::FindAllCode(CodeHandleList* code_list, int length) {
   10268   ASSERT(is_inline_cache_stub());
   10269   DisallowHeapAllocation no_allocation;
   10270   int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET);
   10271   int i = 0;
   10272   for (RelocIterator it(this, mask); !it.done(); it.next()) {
   10273     if (i++ == length) return;
   10274     RelocInfo* info = it.rinfo();
   10275     Code* code = Code::GetCodeFromTargetAddress(info->target_address());
   10276     ASSERT(code->kind() == Code::STUB);
   10277     code_list->Add(Handle<Code>(code));
   10278   }
   10279   UNREACHABLE();
   10280 }
   10281 
   10282 
   10283 Name* Code::FindFirstName() {
   10284   ASSERT(is_inline_cache_stub());
   10285   DisallowHeapAllocation no_allocation;
   10286   int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
   10287   for (RelocIterator it(this, mask); !it.done(); it.next()) {
   10288     RelocInfo* info = it.rinfo();
   10289     Object* object = info->target_object();
   10290     if (object->IsName()) return Name::cast(object);
   10291   }
   10292   return NULL;
   10293 }
   10294 
   10295 
   10296 void Code::ReplaceNthCell(int n, Cell* replace_with) {
   10297   ASSERT(is_inline_cache_stub());
   10298   DisallowHeapAllocation no_allocation;
   10299   int mask = RelocInfo::ModeMask(RelocInfo::CELL);
   10300   for (RelocIterator it(this, mask); !it.done(); it.next()) {
   10301     RelocInfo* info = it.rinfo();
   10302     if (--n == 0) {
   10303       info->set_target_cell(replace_with);
   10304       return;
   10305     }
   10306   }
   10307   UNREACHABLE();
   10308 }
   10309 
   10310 
   10311 void Code::ClearInlineCaches() {
   10312   int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
   10313              RelocInfo::ModeMask(RelocInfo::CONSTRUCT_CALL) |
   10314              RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID) |
   10315              RelocInfo::ModeMask(RelocInfo::CODE_TARGET_CONTEXT);
   10316   for (RelocIterator it(this, mask); !it.done(); it.next()) {
   10317     RelocInfo* info = it.rinfo();
   10318     Code* target(Code::GetCodeFromTargetAddress(info->target_address()));
   10319     if (target->is_inline_cache_stub()) {
   10320       IC::Clear(info->pc());
   10321     }
   10322   }
   10323 }
   10324 
   10325 
   10326 void Code::ClearTypeFeedbackCells(Heap* heap) {
   10327   if (kind() != FUNCTION) return;
   10328   Object* raw_info = type_feedback_info();
   10329   if (raw_info->IsTypeFeedbackInfo()) {
   10330     TypeFeedbackCells* type_feedback_cells =
   10331         TypeFeedbackInfo::cast(raw_info)->type_feedback_cells();
   10332     for (int i = 0; i < type_feedback_cells->CellCount(); i++) {
   10333       Cell* cell = type_feedback_cells->GetCell(i);
   10334       // Don't clear AllocationSites
   10335       Object* value = cell->value();
   10336       if (value == NULL || !value->IsAllocationSite()) {
   10337         cell->set_value(TypeFeedbackCells::RawUninitializedSentinel(heap));
   10338       }
   10339     }
   10340   }
   10341 }
   10342 
   10343 
   10344 bool Code::allowed_in_shared_map_code_cache() {
   10345   return is_keyed_load_stub() || is_keyed_store_stub() ||
   10346       (is_compare_ic_stub() &&
   10347        ICCompareStub::CompareState(stub_info()) == CompareIC::KNOWN_OBJECT);
   10348 }
   10349 
   10350 
   10351 void Code::MakeCodeAgeSequenceYoung(byte* sequence) {
   10352   PatchPlatformCodeAge(sequence, kNoAge, NO_MARKING_PARITY);
   10353 }
   10354 
   10355 
   10356 void Code::MakeOlder(MarkingParity current_parity) {
   10357   byte* sequence = FindCodeAgeSequence();
   10358   if (sequence != NULL) {
   10359     Age age;
   10360     MarkingParity code_parity;
   10361     GetCodeAgeAndParity(sequence, &age, &code_parity);
   10362     if (age != kLastCodeAge && code_parity != current_parity) {
   10363       PatchPlatformCodeAge(sequence, static_cast<Age>(age + 1),
   10364                            current_parity);
   10365     }
   10366   }
   10367 }
   10368 
   10369 
   10370 bool Code::IsOld() {
   10371   byte* sequence = FindCodeAgeSequence();
   10372   if (sequence == NULL) return false;
   10373   Age age;
   10374   MarkingParity parity;
   10375   GetCodeAgeAndParity(sequence, &age, &parity);
   10376   return age >= kSexagenarianCodeAge;
   10377 }
   10378 
   10379 
   10380 byte* Code::FindCodeAgeSequence() {
   10381   return FLAG_age_code &&
   10382       prologue_offset() != kPrologueOffsetNotSet &&
   10383       (kind() == OPTIMIZED_FUNCTION ||
   10384        (kind() == FUNCTION && !has_debug_break_slots()))
   10385       ? instruction_start() + prologue_offset()
   10386       : NULL;
   10387 }
   10388 
   10389 
   10390 int Code::GetAge() {
   10391   byte* sequence = FindCodeAgeSequence();
   10392   if (sequence == NULL) {
   10393     return Code::kNoAge;
   10394   }
   10395   Age age;
   10396   MarkingParity parity;
   10397   GetCodeAgeAndParity(sequence, &age, &parity);
   10398   return age;
   10399 }
   10400 
   10401 
   10402 void Code::GetCodeAgeAndParity(Code* code, Age* age,
   10403                                MarkingParity* parity) {
   10404   Isolate* isolate = Isolate::Current();
   10405   Builtins* builtins = isolate->builtins();
   10406   Code* stub = NULL;
   10407 #define HANDLE_CODE_AGE(AGE)                                            \
   10408   stub = *builtins->Make##AGE##CodeYoungAgainEvenMarking();             \
   10409   if (code == stub) {                                                   \
   10410     *age = k##AGE##CodeAge;                                             \
   10411     *parity = EVEN_MARKING_PARITY;                                      \
   10412     return;                                                             \
   10413   }                                                                     \
   10414   stub = *builtins->Make##AGE##CodeYoungAgainOddMarking();              \
   10415   if (code == stub) {                                                   \
   10416     *age = k##AGE##CodeAge;                                             \
   10417     *parity = ODD_MARKING_PARITY;                                       \
   10418     return;                                                             \
   10419   }
   10420   CODE_AGE_LIST(HANDLE_CODE_AGE)
   10421 #undef HANDLE_CODE_AGE
   10422   UNREACHABLE();
   10423 }
   10424 
   10425 
   10426 Code* Code::GetCodeAgeStub(Age age, MarkingParity parity) {
   10427   Isolate* isolate = Isolate::Current();
   10428   Builtins* builtins = isolate->builtins();
   10429   switch (age) {
   10430 #define HANDLE_CODE_AGE(AGE)                                            \
   10431     case k##AGE##CodeAge: {                                             \
   10432       Code* stub = parity == EVEN_MARKING_PARITY                        \
   10433           ? *builtins->Make##AGE##CodeYoungAgainEvenMarking()           \
   10434           : *builtins->Make##AGE##CodeYoungAgainOddMarking();           \
   10435       return stub;                                                      \
   10436     }
   10437     CODE_AGE_LIST(HANDLE_CODE_AGE)
   10438 #undef HANDLE_CODE_AGE
   10439     default:
   10440       UNREACHABLE();
   10441       break;
   10442   }
   10443   return NULL;
   10444 }
   10445 
   10446 
   10447 void Code::PrintDeoptLocation(int bailout_id) {
   10448   const char* last_comment = NULL;
   10449   int mask = RelocInfo::ModeMask(RelocInfo::COMMENT)
   10450       | RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY);
   10451   for (RelocIterator it(this, mask); !it.done(); it.next()) {
   10452     RelocInfo* info = it.rinfo();
   10453     if (info->rmode() == RelocInfo::COMMENT) {
   10454       last_comment = reinterpret_cast<const char*>(info->data());
   10455     } else if (last_comment != NULL) {
   10456       if ((bailout_id == Deoptimizer::GetDeoptimizationId(
   10457               GetIsolate(), info->target_address(), Deoptimizer::EAGER)) ||
   10458           (bailout_id == Deoptimizer::GetDeoptimizationId(
   10459               GetIsolate(), info->target_address(), Deoptimizer::SOFT))) {
   10460         CHECK(RelocInfo::IsRuntimeEntry(info->rmode()));
   10461         PrintF("            %s\n", last_comment);
   10462         return;
   10463       }
   10464     }
   10465   }
   10466 }
   10467 
   10468 
   10469 bool Code::CanDeoptAt(Address pc) {
   10470   DeoptimizationInputData* deopt_data =
   10471       DeoptimizationInputData::cast(deoptimization_data());
   10472   Address code_start_address = instruction_start();
   10473   for (int i = 0; i < deopt_data->DeoptCount(); i++) {
   10474     if (deopt_data->Pc(i)->value() == -1) continue;
   10475     Address address = code_start_address + deopt_data->Pc(i)->value();
   10476     if (address == pc) return true;
   10477   }
   10478   return false;
   10479 }
   10480 
   10481 
   10482 // Identify kind of code.
   10483 const char* Code::Kind2String(Kind kind) {
   10484   switch (kind) {
   10485 #define CASE(name) case name: return #name;
   10486     CODE_KIND_LIST(CASE)
   10487 #undef CASE
   10488     case NUMBER_OF_KINDS: break;
   10489   }
   10490   UNREACHABLE();
   10491   return NULL;
   10492 }
   10493 
   10494 
   10495 #ifdef ENABLE_DISASSEMBLER
   10496 
   10497 void DeoptimizationInputData::DeoptimizationInputDataPrint(FILE* out) {
   10498   disasm::NameConverter converter;
   10499   int deopt_count = DeoptCount();
   10500   PrintF(out, "Deoptimization Input Data (deopt points = %d)\n", deopt_count);
   10501   if (0 == deopt_count) return;
   10502 
   10503   PrintF(out, "%6s  %6s  %6s %6s %12s\n", "index", "ast id", "argc", "pc",
   10504          FLAG_print_code_verbose ? "commands" : "");
   10505   for (int i = 0; i < deopt_count; i++) {
   10506     PrintF(out, "%6d  %6d  %6d %6d",
   10507            i,
   10508            AstId(i).ToInt(),
   10509            ArgumentsStackHeight(i)->value(),
   10510            Pc(i)->value());
   10511 
   10512     if (!FLAG_print_code_verbose) {
   10513       PrintF(out, "\n");
   10514       continue;
   10515     }
   10516     // Print details of the frame translation.
   10517     int translation_index = TranslationIndex(i)->value();
   10518     TranslationIterator iterator(TranslationByteArray(), translation_index);
   10519     Translation::Opcode opcode =
   10520         static_cast<Translation::Opcode>(iterator.Next());
   10521     ASSERT(Translation::BEGIN == opcode);
   10522     int frame_count = iterator.Next();
   10523     int jsframe_count = iterator.Next();
   10524     PrintF(out, "  %s {frame count=%d, js frame count=%d}\n",
   10525            Translation::StringFor(opcode),
   10526            frame_count,
   10527            jsframe_count);
   10528 
   10529     while (iterator.HasNext() &&
   10530            Translation::BEGIN !=
   10531            (opcode = static_cast<Translation::Opcode>(iterator.Next()))) {
   10532       PrintF(out, "%24s    %s ", "", Translation::StringFor(opcode));
   10533 
   10534       switch (opcode) {
   10535         case Translation::BEGIN:
   10536           UNREACHABLE();
   10537           break;
   10538 
   10539         case Translation::JS_FRAME: {
   10540           int ast_id = iterator.Next();
   10541           int function_id = iterator.Next();
   10542           unsigned height = iterator.Next();
   10543           PrintF(out, "{ast_id=%d, function=", ast_id);
   10544           if (function_id != Translation::kSelfLiteralId) {
   10545             Object* function = LiteralArray()->get(function_id);
   10546             JSFunction::cast(function)->PrintName(out);
   10547           } else {
   10548             PrintF(out, "<self>");
   10549           }
   10550           PrintF(out, ", height=%u}", height);
   10551           break;
   10552         }
   10553 
   10554         case Translation::COMPILED_STUB_FRAME: {
   10555           Code::Kind stub_kind = static_cast<Code::Kind>(iterator.Next());
   10556           PrintF(out, "{kind=%d}", stub_kind);
   10557           break;
   10558         }
   10559 
   10560         case Translation::ARGUMENTS_ADAPTOR_FRAME:
   10561         case Translation::CONSTRUCT_STUB_FRAME: {
   10562           int function_id = iterator.Next();
   10563           JSFunction* function =
   10564               JSFunction::cast(LiteralArray()->get(function_id));
   10565           unsigned height = iterator.Next();
   10566           PrintF(out, "{function=");
   10567           function->PrintName(out);
   10568           PrintF(out, ", height=%u}", height);
   10569           break;
   10570         }
   10571 
   10572         case Translation::GETTER_STUB_FRAME:
   10573         case Translation::SETTER_STUB_FRAME: {
   10574           int function_id = iterator.Next();
   10575           JSFunction* function =
   10576               JSFunction::cast(LiteralArray()->get(function_id));
   10577           PrintF(out, "{function=");
   10578           function->PrintName(out);
   10579           PrintF(out, "}");
   10580           break;
   10581         }
   10582 
   10583         case Translation::REGISTER: {
   10584           int reg_code = iterator.Next();
   10585             PrintF(out, "{input=%s}", converter.NameOfCPURegister(reg_code));
   10586           break;
   10587         }
   10588 
   10589         case Translation::INT32_REGISTER: {
   10590           int reg_code = iterator.Next();
   10591           PrintF(out, "{input=%s}", converter.NameOfCPURegister(reg_code));
   10592           break;
   10593         }
   10594 
   10595         case Translation::UINT32_REGISTER: {
   10596           int reg_code = iterator.Next();
   10597           PrintF(out, "{input=%s (unsigned)}",
   10598                  converter.NameOfCPURegister(reg_code));
   10599           break;
   10600         }
   10601 
   10602         case Translation::DOUBLE_REGISTER: {
   10603           int reg_code = iterator.Next();
   10604           PrintF(out, "{input=%s}",
   10605                  DoubleRegister::AllocationIndexToString(reg_code));
   10606           break;
   10607         }
   10608 
   10609         case Translation::STACK_SLOT: {
   10610           int input_slot_index = iterator.Next();
   10611           PrintF(out, "{input=%d}", input_slot_index);
   10612           break;
   10613         }
   10614 
   10615         case Translation::INT32_STACK_SLOT: {
   10616           int input_slot_index = iterator.Next();
   10617           PrintF(out, "{input=%d}", input_slot_index);
   10618           break;
   10619         }
   10620 
   10621         case Translation::UINT32_STACK_SLOT: {
   10622           int input_slot_index = iterator.Next();
   10623           PrintF(out, "{input=%d (unsigned)}", input_slot_index);
   10624           break;
   10625         }
   10626 
   10627         case Translation::DOUBLE_STACK_SLOT: {
   10628           int input_slot_index = iterator.Next();
   10629           PrintF(out, "{input=%d}", input_slot_index);
   10630           break;
   10631         }
   10632 
   10633         case Translation::LITERAL: {
   10634           unsigned literal_index = iterator.Next();
   10635           PrintF(out, "{literal_id=%u}", literal_index);
   10636           break;
   10637         }
   10638 
   10639         case Translation::DUPLICATED_OBJECT: {
   10640           int object_index = iterator.Next();
   10641           PrintF(out, "{object_index=%d}", object_index);
   10642           break;
   10643         }
   10644 
   10645         case Translation::ARGUMENTS_OBJECT:
   10646         case Translation::CAPTURED_OBJECT: {
   10647           int args_length = iterator.Next();
   10648           PrintF(out, "{length=%d}", args_length);
   10649           break;
   10650         }
   10651       }
   10652       PrintF(out, "\n");
   10653     }
   10654   }
   10655 }
   10656 
   10657 
   10658 void DeoptimizationOutputData::DeoptimizationOutputDataPrint(FILE* out) {
   10659   PrintF(out, "Deoptimization Output Data (deopt points = %d)\n",
   10660          this->DeoptPoints());
   10661   if (this->DeoptPoints() == 0) return;
   10662 
   10663   PrintF("%6s  %8s  %s\n", "ast id", "pc", "state");
   10664   for (int i = 0; i < this->DeoptPoints(); i++) {
   10665     int pc_and_state = this->PcAndState(i)->value();
   10666     PrintF("%6d  %8d  %s\n",
   10667            this->AstId(i).ToInt(),
   10668            FullCodeGenerator::PcField::decode(pc_and_state),
   10669            FullCodeGenerator::State2String(
   10670                FullCodeGenerator::StateField::decode(pc_and_state)));
   10671   }
   10672 }
   10673 
   10674 
   10675 const char* Code::ICState2String(InlineCacheState state) {
   10676   switch (state) {
   10677     case UNINITIALIZED: return "UNINITIALIZED";
   10678     case PREMONOMORPHIC: return "PREMONOMORPHIC";
   10679     case MONOMORPHIC: return "MONOMORPHIC";
   10680     case MONOMORPHIC_PROTOTYPE_FAILURE: return "MONOMORPHIC_PROTOTYPE_FAILURE";
   10681     case POLYMORPHIC: return "POLYMORPHIC";
   10682     case MEGAMORPHIC: return "MEGAMORPHIC";
   10683     case GENERIC: return "GENERIC";
   10684     case DEBUG_STUB: return "DEBUG_STUB";
   10685   }
   10686   UNREACHABLE();
   10687   return NULL;
   10688 }
   10689 
   10690 
   10691 const char* Code::StubType2String(StubType type) {
   10692   switch (type) {
   10693     case NORMAL: return "NORMAL";
   10694     case FIELD: return "FIELD";
   10695     case CONSTANT: return "CONSTANT";
   10696     case CALLBACKS: return "CALLBACKS";
   10697     case INTERCEPTOR: return "INTERCEPTOR";
   10698     case MAP_TRANSITION: return "MAP_TRANSITION";
   10699     case NONEXISTENT: return "NONEXISTENT";
   10700   }
   10701   UNREACHABLE();  // keep the compiler happy
   10702   return NULL;
   10703 }
   10704 
   10705 
   10706 void Code::PrintExtraICState(FILE* out, Kind kind, ExtraICState extra) {
   10707   PrintF(out, "extra_ic_state = ");
   10708   const char* name = NULL;
   10709   switch (kind) {
   10710     case CALL_IC:
   10711       if (extra == STRING_INDEX_OUT_OF_BOUNDS) {
   10712         name = "STRING_INDEX_OUT_OF_BOUNDS";
   10713       }
   10714       break;
   10715     case STORE_IC:
   10716     case KEYED_STORE_IC:
   10717       if (extra == kStrictMode) {
   10718         name = "STRICT";
   10719       }
   10720       break;
   10721     default:
   10722       break;
   10723   }
   10724   if (name != NULL) {
   10725     PrintF(out, "%s\n", name);
   10726   } else {
   10727     PrintF(out, "%d\n", extra);
   10728   }
   10729 }
   10730 
   10731 
   10732 void Code::Disassemble(const char* name, FILE* out) {
   10733   PrintF(out, "kind = %s\n", Kind2String(kind()));
   10734   if (is_inline_cache_stub()) {
   10735     PrintF(out, "ic_state = %s\n", ICState2String(ic_state()));
   10736     PrintExtraICState(out, kind(), needs_extended_extra_ic_state(kind()) ?
   10737         extended_extra_ic_state() : extra_ic_state());
   10738     if (ic_state() == MONOMORPHIC) {
   10739       PrintF(out, "type = %s\n", StubType2String(type()));
   10740     }
   10741     if (is_call_stub() || is_keyed_call_stub()) {
   10742       PrintF(out, "argc = %d\n", arguments_count());
   10743     }
   10744     if (is_compare_ic_stub()) {
   10745       ASSERT(major_key() == CodeStub::CompareIC);
   10746       CompareIC::State left_state, right_state, handler_state;
   10747       Token::Value op;
   10748       ICCompareStub::DecodeMinorKey(stub_info(), &left_state, &right_state,
   10749                                     &handler_state, &op);
   10750       PrintF(out, "compare_state = %s*%s -> %s\n",
   10751              CompareIC::GetStateName(left_state),
   10752              CompareIC::GetStateName(right_state),
   10753              CompareIC::GetStateName(handler_state));
   10754       PrintF(out, "compare_operation = %s\n", Token::Name(op));
   10755     }
   10756   }
   10757   if ((name != NULL) && (name[0] != '\0')) {
   10758     PrintF(out, "name = %s\n", name);
   10759   }
   10760   if (kind() == OPTIMIZED_FUNCTION) {
   10761     PrintF(out, "stack_slots = %d\n", stack_slots());
   10762   }
   10763 
   10764   PrintF(out, "Instructions (size = %d)\n", instruction_size());
   10765   Disassembler::Decode(out, this);
   10766   PrintF(out, "\n");
   10767 
   10768   if (kind() == FUNCTION) {
   10769     DeoptimizationOutputData* data =
   10770         DeoptimizationOutputData::cast(this->deoptimization_data());
   10771     data->DeoptimizationOutputDataPrint(out);
   10772   } else if (kind() == OPTIMIZED_FUNCTION) {
   10773     DeoptimizationInputData* data =
   10774         DeoptimizationInputData::cast(this->deoptimization_data());
   10775     data->DeoptimizationInputDataPrint(out);
   10776   }
   10777   PrintF("\n");
   10778 
   10779   if (is_crankshafted()) {
   10780     SafepointTable table(this);
   10781     PrintF(out, "Safepoints (size = %u)\n", table.size());
   10782     for (unsigned i = 0; i < table.length(); i++) {
   10783       unsigned pc_offset = table.GetPcOffset(i);
   10784       PrintF(out, "%p  %4d  ", (instruction_start() + pc_offset), pc_offset);
   10785       table.PrintEntry(i);
   10786       PrintF(out, " (sp -> fp)");
   10787       SafepointEntry entry = table.GetEntry(i);
   10788       if (entry.deoptimization_index() != Safepoint::kNoDeoptimizationIndex) {
   10789         PrintF(out, "  %6d", entry.deoptimization_index());
   10790       } else {
   10791         PrintF(out, "  <none>");
   10792       }
   10793       if (entry.argument_count() > 0) {
   10794         PrintF(out, " argc: %d", entry.argument_count());
   10795       }
   10796       PrintF(out, "\n");
   10797     }
   10798     PrintF(out, "\n");
   10799   } else if (kind() == FUNCTION) {
   10800     unsigned offset = back_edge_table_offset();
   10801     // If there is no back edge table, the "table start" will be at or after
   10802     // (due to alignment) the end of the instruction stream.
   10803     if (static_cast<int>(offset) < instruction_size()) {
   10804       FullCodeGenerator::BackEdgeTableIterator back_edges(this);
   10805 
   10806       PrintF(out, "Back edges (size = %u)\n", back_edges.table_length());
   10807       PrintF(out, "ast_id  pc_offset  loop_depth\n");
   10808 
   10809       for ( ; !back_edges.Done(); back_edges.Next()) {
   10810         PrintF(out, "%6d  %9u  %10u\n", back_edges.ast_id().ToInt(),
   10811                                         back_edges.pc_offset(),
   10812                                         back_edges.loop_depth());
   10813       }
   10814 
   10815       PrintF(out, "\n");
   10816     }
   10817 #ifdef OBJECT_PRINT
   10818     if (!type_feedback_info()->IsUndefined()) {
   10819       TypeFeedbackInfo::cast(type_feedback_info())->TypeFeedbackInfoPrint(out);
   10820       PrintF(out, "\n");
   10821     }
   10822 #endif
   10823   }
   10824 
   10825   PrintF("RelocInfo (size = %d)\n", relocation_size());
   10826   for (RelocIterator it(this); !it.done(); it.next()) {
   10827     it.rinfo()->Print(GetIsolate(), out);
   10828   }
   10829   PrintF(out, "\n");
   10830 }
   10831 #endif  // ENABLE_DISASSEMBLER
   10832 
   10833 
   10834 MaybeObject* JSObject::SetFastElementsCapacityAndLength(
   10835     int capacity,
   10836     int length,
   10837     SetFastElementsCapacitySmiMode smi_mode) {
   10838   Heap* heap = GetHeap();
   10839   // We should never end in here with a pixel or external array.
   10840   ASSERT(!HasExternalArrayElements());
   10841   ASSERT(!map()->is_observed());
   10842 
   10843   // Allocate a new fast elements backing store.
   10844   FixedArray* new_elements;
   10845   MaybeObject* maybe = heap->AllocateUninitializedFixedArray(capacity);
   10846   if (!maybe->To(&new_elements)) return maybe;
   10847 
   10848   ElementsKind elements_kind = GetElementsKind();
   10849   ElementsKind new_elements_kind;
   10850   // The resized array has FAST_*_SMI_ELEMENTS if the capacity mode forces it,
   10851   // or if it's allowed and the old elements array contained only SMIs.
   10852   bool has_fast_smi_elements =
   10853       (smi_mode == kForceSmiElements) ||
   10854       ((smi_mode == kAllowSmiElements) && HasFastSmiElements());
   10855   if (has_fast_smi_elements) {
   10856     if (IsHoleyElementsKind(elements_kind)) {
   10857       new_elements_kind = FAST_HOLEY_SMI_ELEMENTS;
   10858     } else {
   10859       new_elements_kind = FAST_SMI_ELEMENTS;
   10860     }
   10861   } else {
   10862     if (IsHoleyElementsKind(elements_kind)) {
   10863       new_elements_kind = FAST_HOLEY_ELEMENTS;
   10864     } else {
   10865       new_elements_kind = FAST_ELEMENTS;
   10866     }
   10867   }
   10868   FixedArrayBase* old_elements = elements();
   10869   ElementsAccessor* accessor = ElementsAccessor::ForKind(new_elements_kind);
   10870   MaybeObject* maybe_obj =
   10871       accessor->CopyElements(this, new_elements, elements_kind);
   10872   if (maybe_obj->IsFailure()) return maybe_obj;
   10873 
   10874   if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) {
   10875     Map* new_map = map();
   10876     if (new_elements_kind != elements_kind) {
   10877       MaybeObject* maybe =
   10878           GetElementsTransitionMap(GetIsolate(), new_elements_kind);
   10879       if (!maybe->To(&new_map)) return maybe;
   10880     }
   10881     ValidateElements();
   10882     set_map_and_elements(new_map, new_elements);
   10883   } else {
   10884     FixedArray* parameter_map = FixedArray::cast(old_elements);
   10885     parameter_map->set(1, new_elements);
   10886   }
   10887 
   10888   if (FLAG_trace_elements_transitions) {
   10889     PrintElementsTransition(stdout, elements_kind, old_elements,
   10890                             GetElementsKind(), new_elements);
   10891   }
   10892 
   10893   if (IsJSArray()) {
   10894     JSArray::cast(this)->set_length(Smi::FromInt(length));
   10895   }
   10896   return new_elements;
   10897 }
   10898 
   10899 
   10900 MaybeObject* JSObject::SetFastDoubleElementsCapacityAndLength(
   10901     int capacity,
   10902     int length) {
   10903   Heap* heap = GetHeap();
   10904   // We should never end in here with a pixel or external array.
   10905   ASSERT(!HasExternalArrayElements());
   10906   ASSERT(!map()->is_observed());
   10907 
   10908   FixedArrayBase* elems;
   10909   { MaybeObject* maybe_obj =
   10910         heap->AllocateUninitializedFixedDoubleArray(capacity);
   10911     if (!maybe_obj->To(&elems)) return maybe_obj;
   10912   }
   10913 
   10914   ElementsKind elements_kind = GetElementsKind();
   10915   ElementsKind new_elements_kind = elements_kind;
   10916   if (IsHoleyElementsKind(elements_kind)) {
   10917     new_elements_kind = FAST_HOLEY_DOUBLE_ELEMENTS;
   10918   } else {
   10919     new_elements_kind = FAST_DOUBLE_ELEMENTS;
   10920   }
   10921 
   10922   Map* new_map;
   10923   { MaybeObject* maybe_obj =
   10924         GetElementsTransitionMap(heap->isolate(), new_elements_kind);
   10925     if (!maybe_obj->To(&new_map)) return maybe_obj;
   10926   }
   10927 
   10928   FixedArrayBase* old_elements = elements();
   10929   ElementsAccessor* accessor = ElementsAccessor::ForKind(FAST_DOUBLE_ELEMENTS);
   10930   { MaybeObject* maybe_obj =
   10931         accessor->CopyElements(this, elems, elements_kind);
   10932     if (maybe_obj->IsFailure()) return maybe_obj;
   10933   }
   10934   if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) {
   10935     ValidateElements();
   10936     set_map_and_elements(new_map, elems);
   10937   } else {
   10938     FixedArray* parameter_map = FixedArray::cast(old_elements);
   10939     parameter_map->set(1, elems);
   10940   }
   10941 
   10942   if (FLAG_trace_elements_transitions) {
   10943     PrintElementsTransition(stdout, elements_kind, old_elements,
   10944                             GetElementsKind(), elems);
   10945   }
   10946 
   10947   if (IsJSArray()) {
   10948     JSArray::cast(this)->set_length(Smi::FromInt(length));
   10949   }
   10950 
   10951   return this;
   10952 }
   10953 
   10954 
   10955 MaybeObject* JSArray::Initialize(int capacity, int length) {
   10956   ASSERT(capacity >= 0);
   10957   return GetHeap()->AllocateJSArrayStorage(this, length, capacity,
   10958                                            INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE);
   10959 }
   10960 
   10961 
   10962 void JSArray::Expand(int required_size) {
   10963   GetIsolate()->factory()->SetElementsCapacityAndLength(
   10964       Handle<JSArray>(this), required_size, required_size);
   10965 }
   10966 
   10967 
   10968 // Returns false if the passed-in index is marked non-configurable,
   10969 // which will cause the ES5 truncation operation to halt, and thus
   10970 // no further old values need be collected.
   10971 static bool GetOldValue(Isolate* isolate,
   10972                         Handle<JSObject> object,
   10973                         uint32_t index,
   10974                         List<Handle<Object> >* old_values,
   10975                         List<uint32_t>* indices) {
   10976   PropertyAttributes attributes = object->GetLocalElementAttribute(index);
   10977   ASSERT(attributes != ABSENT);
   10978   if (attributes == DONT_DELETE) return false;
   10979   old_values->Add(object->GetLocalElementAccessorPair(index) == NULL
   10980       ? Object::GetElement(object, index)
   10981       : Handle<Object>::cast(isolate->factory()->the_hole_value()));
   10982   indices->Add(index);
   10983   return true;
   10984 }
   10985 
   10986 static void EnqueueSpliceRecord(Handle<JSArray> object,
   10987                                 uint32_t index,
   10988                                 Handle<JSArray> deleted,
   10989                                 uint32_t add_count) {
   10990   Isolate* isolate = object->GetIsolate();
   10991   HandleScope scope(isolate);
   10992   Handle<Object> index_object = isolate->factory()->NewNumberFromUint(index);
   10993   Handle<Object> add_count_object =
   10994       isolate->factory()->NewNumberFromUint(add_count);
   10995 
   10996   Handle<Object> args[] =
   10997       { object, index_object, deleted, add_count_object };
   10998 
   10999   bool threw;
   11000   Execution::Call(Handle<JSFunction>(isolate->observers_enqueue_splice()),
   11001                   isolate->factory()->undefined_value(), ARRAY_SIZE(args), args,
   11002                   &threw);
   11003   ASSERT(!threw);
   11004 }
   11005 
   11006 
   11007 static void BeginPerformSplice(Handle<JSArray> object) {
   11008   Isolate* isolate = object->GetIsolate();
   11009   HandleScope scope(isolate);
   11010   Handle<Object> args[] = { object };
   11011 
   11012   bool threw;
   11013   Execution::Call(Handle<JSFunction>(isolate->observers_begin_perform_splice()),
   11014                   isolate->factory()->undefined_value(), ARRAY_SIZE(args), args,
   11015                   &threw);
   11016   ASSERT(!threw);
   11017 }
   11018 
   11019 
   11020 static void EndPerformSplice(Handle<JSArray> object) {
   11021   Isolate* isolate = object->GetIsolate();
   11022   HandleScope scope(isolate);
   11023   Handle<Object> args[] = { object };
   11024 
   11025   bool threw;
   11026   Execution::Call(Handle<JSFunction>(isolate->observers_end_perform_splice()),
   11027                   isolate->factory()->undefined_value(), ARRAY_SIZE(args), args,
   11028                   &threw);
   11029   ASSERT(!threw);
   11030 }
   11031 
   11032 
   11033 MaybeObject* JSArray::SetElementsLength(Object* len) {
   11034   // We should never end in here with a pixel or external array.
   11035   ASSERT(AllowsSetElementsLength());
   11036   if (!(FLAG_harmony_observation && map()->is_observed()))
   11037     return GetElementsAccessor()->SetLength(this, len);
   11038 
   11039   Isolate* isolate = GetIsolate();
   11040   HandleScope scope(isolate);
   11041   Handle<JSArray> self(this);
   11042   List<uint32_t> indices;
   11043   List<Handle<Object> > old_values;
   11044   Handle<Object> old_length_handle(self->length(), isolate);
   11045   Handle<Object> new_length_handle(len, isolate);
   11046   uint32_t old_length = 0;
   11047   CHECK(old_length_handle->ToArrayIndex(&old_length));
   11048   uint32_t new_length = 0;
   11049   if (!new_length_handle->ToArrayIndex(&new_length))
   11050     return Failure::InternalError();
   11051 
   11052   // Observed arrays should always be in dictionary mode;
   11053   // if they were in fast mode, the below is slower than necessary
   11054   // as it iterates over the array backing store multiple times.
   11055   ASSERT(self->HasDictionaryElements());
   11056   static const PropertyAttributes kNoAttrFilter = NONE;
   11057   int num_elements = self->NumberOfLocalElements(kNoAttrFilter);
   11058   if (num_elements > 0) {
   11059     if (old_length == static_cast<uint32_t>(num_elements)) {
   11060       // Simple case for arrays without holes.
   11061       for (uint32_t i = old_length - 1; i + 1 > new_length; --i) {
   11062         if (!GetOldValue(isolate, self, i, &old_values, &indices)) break;
   11063       }
   11064     } else {
   11065       // For sparse arrays, only iterate over existing elements.
   11066       Handle<FixedArray> keys = isolate->factory()->NewFixedArray(num_elements);
   11067       self->GetLocalElementKeys(*keys, kNoAttrFilter);
   11068       while (num_elements-- > 0) {
   11069         uint32_t index = NumberToUint32(keys->get(num_elements));
   11070         if (index < new_length) break;
   11071         if (!GetOldValue(isolate, self, index, &old_values, &indices)) break;
   11072       }
   11073     }
   11074   }
   11075 
   11076   MaybeObject* result =
   11077       self->GetElementsAccessor()->SetLength(*self, *new_length_handle);
   11078   Handle<Object> hresult;
   11079   if (!result->ToHandle(&hresult, isolate)) return result;
   11080 
   11081   CHECK(self->length()->ToArrayIndex(&new_length));
   11082   if (old_length == new_length) return *hresult;
   11083 
   11084   BeginPerformSplice(self);
   11085 
   11086   for (int i = 0; i < indices.length(); ++i) {
   11087     JSObject::EnqueueChangeRecord(
   11088         self, "deleted", isolate->factory()->Uint32ToString(indices[i]),
   11089         old_values[i]);
   11090   }
   11091   JSObject::EnqueueChangeRecord(
   11092       self, "updated", isolate->factory()->length_string(),
   11093       old_length_handle);
   11094 
   11095   EndPerformSplice(self);
   11096 
   11097   uint32_t index = Min(old_length, new_length);
   11098   uint32_t add_count = new_length > old_length ? new_length - old_length : 0;
   11099   uint32_t delete_count = new_length < old_length ? old_length - new_length : 0;
   11100   Handle<JSArray> deleted = isolate->factory()->NewJSArray(0);
   11101   if (delete_count > 0) {
   11102     for (int i = indices.length() - 1; i >= 0; i--) {
   11103       JSObject::SetElement(deleted, indices[i] - index, old_values[i], NONE,
   11104                            kNonStrictMode);
   11105     }
   11106 
   11107     SetProperty(deleted, isolate->factory()->length_string(),
   11108                 isolate->factory()->NewNumberFromUint(delete_count),
   11109                 NONE, kNonStrictMode);
   11110   }
   11111 
   11112   EnqueueSpliceRecord(self, index, deleted, add_count);
   11113 
   11114   return *hresult;
   11115 }
   11116 
   11117 
   11118 Handle<Map> Map::GetPrototypeTransition(Handle<Map> map,
   11119                                         Handle<Object> prototype) {
   11120   FixedArray* cache = map->GetPrototypeTransitions();
   11121   int number_of_transitions = map->NumberOfProtoTransitions();
   11122   const int proto_offset =
   11123       kProtoTransitionHeaderSize + kProtoTransitionPrototypeOffset;
   11124   const int map_offset = kProtoTransitionHeaderSize + kProtoTransitionMapOffset;
   11125   const int step = kProtoTransitionElementsPerEntry;
   11126   for (int i = 0; i < number_of_transitions; i++) {
   11127     if (cache->get(proto_offset + i * step) == *prototype) {
   11128       Object* result = cache->get(map_offset + i * step);
   11129       return Handle<Map>(Map::cast(result));
   11130     }
   11131   }
   11132   return Handle<Map>();
   11133 }
   11134 
   11135 
   11136 Handle<Map> Map::PutPrototypeTransition(Handle<Map> map,
   11137                                         Handle<Object> prototype,
   11138                                         Handle<Map> target_map) {
   11139   ASSERT(target_map->IsMap());
   11140   ASSERT(HeapObject::cast(*prototype)->map()->IsMap());
   11141   // Don't cache prototype transition if this map is shared.
   11142   if (map->is_shared() || !FLAG_cache_prototype_transitions) return map;
   11143 
   11144   const int step = kProtoTransitionElementsPerEntry;
   11145   const int header = kProtoTransitionHeaderSize;
   11146 
   11147   Handle<FixedArray> cache(map->GetPrototypeTransitions());
   11148   int capacity = (cache->length() - header) / step;
   11149   int transitions = map->NumberOfProtoTransitions() + 1;
   11150 
   11151   if (transitions > capacity) {
   11152     if (capacity > kMaxCachedPrototypeTransitions) return map;
   11153 
   11154     // Grow array by factor 2 over and above what we need.
   11155     Factory* factory = map->GetIsolate()->factory();
   11156     cache = factory->CopySizeFixedArray(cache, transitions * 2 * step + header);
   11157 
   11158     CALL_AND_RETRY_OR_DIE(map->GetIsolate(),
   11159                           map->SetPrototypeTransitions(*cache),
   11160                           break,
   11161                           return Handle<Map>());
   11162   }
   11163 
   11164   // Reload number of transitions as GC might shrink them.
   11165   int last = map->NumberOfProtoTransitions();
   11166   int entry = header + last * step;
   11167 
   11168   cache->set(entry + kProtoTransitionPrototypeOffset, *prototype);
   11169   cache->set(entry + kProtoTransitionMapOffset, *target_map);
   11170   map->SetNumberOfProtoTransitions(transitions);
   11171 
   11172   return map;
   11173 }
   11174 
   11175 
   11176 void Map::ZapTransitions() {
   11177   TransitionArray* transition_array = transitions();
   11178   // TODO(mstarzinger): Temporarily use a slower version instead of the faster
   11179   // MemsetPointer to investigate a crasher. Switch back to MemsetPointer.
   11180   Object** data = transition_array->data_start();
   11181   Object* the_hole = GetHeap()->the_hole_value();
   11182   int length = transition_array->length();
   11183   for (int i = 0; i < length; i++) {
   11184     data[i] = the_hole;
   11185   }
   11186 }
   11187 
   11188 
   11189 void Map::ZapPrototypeTransitions() {
   11190   FixedArray* proto_transitions = GetPrototypeTransitions();
   11191   MemsetPointer(proto_transitions->data_start(),
   11192                 GetHeap()->the_hole_value(),
   11193                 proto_transitions->length());
   11194 }
   11195 
   11196 
   11197 void Map::AddDependentCompilationInfo(DependentCode::DependencyGroup group,
   11198                                       CompilationInfo* info) {
   11199   Handle<DependentCode> dep(dependent_code());
   11200   Handle<DependentCode> codes =
   11201       DependentCode::Insert(dep, group, info->object_wrapper());
   11202   if (*codes != dependent_code()) set_dependent_code(*codes);
   11203   info->dependencies(group)->Add(Handle<HeapObject>(this), info->zone());
   11204 }
   11205 
   11206 
   11207 void Map::AddDependentCode(DependentCode::DependencyGroup group,
   11208                            Handle<Code> code) {
   11209   Handle<DependentCode> codes = DependentCode::Insert(
   11210       Handle<DependentCode>(dependent_code()), group, code);
   11211   if (*codes != dependent_code()) set_dependent_code(*codes);
   11212 }
   11213 
   11214 
   11215 DependentCode::GroupStartIndexes::GroupStartIndexes(DependentCode* entries) {
   11216   Recompute(entries);
   11217 }
   11218 
   11219 
   11220 void DependentCode::GroupStartIndexes::Recompute(DependentCode* entries) {
   11221   start_indexes_[0] = 0;
   11222   for (int g = 1; g <= kGroupCount; g++) {
   11223     int count = entries->number_of_entries(static_cast<DependencyGroup>(g - 1));
   11224     start_indexes_[g] = start_indexes_[g - 1] + count;
   11225   }
   11226 }
   11227 
   11228 
   11229 DependentCode* DependentCode::ForObject(Handle<HeapObject> object,
   11230                                         DependencyGroup group) {
   11231   AllowDeferredHandleDereference dependencies_are_safe;
   11232   if (group == DependentCode::kPropertyCellChangedGroup) {
   11233     return Handle<PropertyCell>::cast(object)->dependent_code();
   11234   }
   11235   return Handle<Map>::cast(object)->dependent_code();
   11236 }
   11237 
   11238 
   11239 Handle<DependentCode> DependentCode::Insert(Handle<DependentCode> entries,
   11240                                             DependencyGroup group,
   11241                                             Handle<Object> object) {
   11242   GroupStartIndexes starts(*entries);
   11243   int start = starts.at(group);
   11244   int end = starts.at(group + 1);
   11245   int number_of_entries = starts.number_of_entries();
   11246   if (start < end && entries->object_at(end - 1) == *object) {
   11247     // Do not append the compilation info if it is already in the array.
   11248     // It is sufficient to just check only the last element because
   11249     // we process embedded maps of an optimized code in one batch.
   11250     return entries;
   11251   }
   11252   if (entries->length() < kCodesStartIndex + number_of_entries + 1) {
   11253     Factory* factory = entries->GetIsolate()->factory();
   11254     int capacity = kCodesStartIndex + number_of_entries + 1;
   11255     if (capacity > 5) capacity = capacity * 5 / 4;
   11256     Handle<DependentCode> new_entries = Handle<DependentCode>::cast(
   11257         factory->CopySizeFixedArray(entries, capacity));
   11258     // The number of codes can change after GC.
   11259     starts.Recompute(*entries);
   11260     start = starts.at(group);
   11261     end = starts.at(group + 1);
   11262     number_of_entries = starts.number_of_entries();
   11263     for (int i = 0; i < number_of_entries; i++) {
   11264       entries->clear_at(i);
   11265     }
   11266     // If the old fixed array was empty, we need to reset counters of the
   11267     // new array.
   11268     if (number_of_entries == 0) {
   11269       for (int g = 0; g < kGroupCount; g++) {
   11270         new_entries->set_number_of_entries(static_cast<DependencyGroup>(g), 0);
   11271       }
   11272     }
   11273     entries = new_entries;
   11274   }
   11275   entries->ExtendGroup(group);
   11276   entries->set_object_at(end, *object);
   11277   entries->set_number_of_entries(group, end + 1 - start);
   11278   return entries;
   11279 }
   11280 
   11281 
   11282 void DependentCode::UpdateToFinishedCode(DependencyGroup group,
   11283                                          CompilationInfo* info,
   11284                                          Code* code) {
   11285   DisallowHeapAllocation no_gc;
   11286   AllowDeferredHandleDereference get_object_wrapper;
   11287   Foreign* info_wrapper = *info->object_wrapper();
   11288   GroupStartIndexes starts(this);
   11289   int start = starts.at(group);
   11290   int end = starts.at(group + 1);
   11291   for (int i = start; i < end; i++) {
   11292     if (object_at(i) == info_wrapper) {
   11293       set_object_at(i, code);
   11294       break;
   11295     }
   11296   }
   11297 
   11298 #ifdef DEBUG
   11299   for (int i = start; i < end; i++) {
   11300     ASSERT(is_code_at(i) || compilation_info_at(i) != info);
   11301   }
   11302 #endif
   11303 }
   11304 
   11305 
   11306 void DependentCode::RemoveCompilationInfo(DependentCode::DependencyGroup group,
   11307                                           CompilationInfo* info) {
   11308   DisallowHeapAllocation no_allocation;
   11309   AllowDeferredHandleDereference get_object_wrapper;
   11310   Foreign* info_wrapper = *info->object_wrapper();
   11311   GroupStartIndexes starts(this);
   11312   int start = starts.at(group);
   11313   int end = starts.at(group + 1);
   11314   // Find compilation info wrapper.
   11315   int info_pos = -1;
   11316   for (int i = start; i < end; i++) {
   11317     if (object_at(i) == info_wrapper) {
   11318       info_pos = i;
   11319       break;
   11320     }
   11321   }
   11322   if (info_pos == -1) return;  // Not found.
   11323   int gap = info_pos;
   11324   // Use the last of each group to fill the gap in the previous group.
   11325   for (int i = group; i < kGroupCount; i++) {
   11326     int last_of_group = starts.at(i + 1) - 1;
   11327     ASSERT(last_of_group >= gap);
   11328     if (last_of_group == gap) continue;
   11329     copy(last_of_group, gap);
   11330     gap = last_of_group;
   11331   }
   11332   ASSERT(gap == starts.number_of_entries() - 1);
   11333   clear_at(gap);  // Clear last gap.
   11334   set_number_of_entries(group, end - start - 1);
   11335 
   11336 #ifdef DEBUG
   11337   for (int i = start; i < end - 1; i++) {
   11338     ASSERT(is_code_at(i) || compilation_info_at(i) != info);
   11339   }
   11340 #endif
   11341 }
   11342 
   11343 
   11344 bool DependentCode::Contains(DependencyGroup group, Code* code) {
   11345   GroupStartIndexes starts(this);
   11346   int number_of_entries = starts.number_of_entries();
   11347   for (int i = 0; i < number_of_entries; i++) {
   11348     if (object_at(i) == code) return true;
   11349   }
   11350   return false;
   11351 }
   11352 
   11353 
   11354 void DependentCode::DeoptimizeDependentCodeGroup(
   11355     Isolate* isolate,
   11356     DependentCode::DependencyGroup group) {
   11357   ASSERT(AllowCodeDependencyChange::IsAllowed());
   11358   DisallowHeapAllocation no_allocation_scope;
   11359   DependentCode::GroupStartIndexes starts(this);
   11360   int start = starts.at(group);
   11361   int end = starts.at(group + 1);
   11362   int code_entries = starts.number_of_entries();
   11363   if (start == end) return;
   11364 
   11365   // Collect all the code to deoptimize.
   11366   Zone zone(isolate);
   11367   ZoneList<Code*> codes(end - start, &zone);
   11368   for (int i = start; i < end; i++) {
   11369     if (is_code_at(i)) {
   11370       Code* code = code_at(i);
   11371       if (!code->marked_for_deoptimization()) codes.Add(code, &zone);
   11372     } else {
   11373       CompilationInfo* info = compilation_info_at(i);
   11374       info->AbortDueToDependencyChange();
   11375     }
   11376   }
   11377   // Compact the array by moving all subsequent groups to fill in the new holes.
   11378   for (int src = end, dst = start; src < code_entries; src++, dst++) {
   11379     copy(src, dst);
   11380   }
   11381   // Now the holes are at the end of the array, zap them for heap-verifier.
   11382   int removed = end - start;
   11383   for (int i = code_entries - removed; i < code_entries; i++) {
   11384     clear_at(i);
   11385   }
   11386   set_number_of_entries(group, 0);
   11387   Deoptimizer::DeoptimizeCodeList(isolate, &codes);
   11388 }
   11389 
   11390 
   11391 Handle<Object> JSObject::SetPrototype(Handle<JSObject> object,
   11392                                       Handle<Object> value,
   11393                                       bool skip_hidden_prototypes) {
   11394 #ifdef DEBUG
   11395   int size = object->Size();
   11396 #endif
   11397 
   11398   Isolate* isolate = object->GetIsolate();
   11399   Heap* heap = isolate->heap();
   11400   // Silently ignore the change if value is not a JSObject or null.
   11401   // SpiderMonkey behaves this way.
   11402   if (!value->IsJSReceiver() && !value->IsNull()) return value;
   11403 
   11404   // From 8.6.2 Object Internal Methods
   11405   // ...
   11406   // In addition, if [[Extensible]] is false the value of the [[Class]] and
   11407   // [[Prototype]] internal properties of the object may not be modified.
   11408   // ...
   11409   // Implementation specific extensions that modify [[Class]], [[Prototype]]
   11410   // or [[Extensible]] must not violate the invariants defined in the preceding
   11411   // paragraph.
   11412   if (!object->map()->is_extensible()) {
   11413     Handle<Object> args[] = { object };
   11414     Handle<Object> error = isolate->factory()->NewTypeError(
   11415         "non_extensible_proto", HandleVector(args, ARRAY_SIZE(args)));
   11416     isolate->Throw(*error);
   11417     return Handle<Object>();
   11418   }
   11419 
   11420   // Before we can set the prototype we need to be sure
   11421   // prototype cycles are prevented.
   11422   // It is sufficient to validate that the receiver is not in the new prototype
   11423   // chain.
   11424   for (Object* pt = *value;
   11425        pt != heap->null_value();
   11426        pt = pt->GetPrototype(isolate)) {
   11427     if (JSReceiver::cast(pt) == *object) {
   11428       // Cycle detected.
   11429       Handle<Object> error = isolate->factory()->NewError(
   11430           "cyclic_proto", HandleVector<Object>(NULL, 0));
   11431       isolate->Throw(*error);
   11432       return Handle<Object>();
   11433     }
   11434   }
   11435 
   11436   Handle<JSObject> real_receiver = object;
   11437 
   11438   if (skip_hidden_prototypes) {
   11439     // Find the first object in the chain whose prototype object is not
   11440     // hidden and set the new prototype on that object.
   11441     Object* current_proto = real_receiver->GetPrototype();
   11442     while (current_proto->IsJSObject() &&
   11443           JSObject::cast(current_proto)->map()->is_hidden_prototype()) {
   11444       real_receiver = handle(JSObject::cast(current_proto), isolate);
   11445       current_proto = current_proto->GetPrototype(isolate);
   11446     }
   11447   }
   11448 
   11449   // Set the new prototype of the object.
   11450   Handle<Map> map(real_receiver->map());
   11451 
   11452   // Nothing to do if prototype is already set.
   11453   if (map->prototype() == *value) return value;
   11454 
   11455   if (value->IsJSObject()) {
   11456     JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(value));
   11457   }
   11458 
   11459   Handle<Map> new_map = Map::GetPrototypeTransition(map, value);
   11460   if (new_map.is_null()) {
   11461     new_map = Map::Copy(map);
   11462     Map::PutPrototypeTransition(map, value, new_map);
   11463     new_map->set_prototype(*value);
   11464   }
   11465   ASSERT(new_map->prototype() == *value);
   11466   real_receiver->set_map(*new_map);
   11467 
   11468   heap->ClearInstanceofCache();
   11469   ASSERT(size == object->Size());
   11470   return value;
   11471 }
   11472 
   11473 
   11474 MaybeObject* JSObject::EnsureCanContainElements(Arguments* args,
   11475                                                 uint32_t first_arg,
   11476                                                 uint32_t arg_count,
   11477                                                 EnsureElementsMode mode) {
   11478   // Elements in |Arguments| are ordered backwards (because they're on the
   11479   // stack), but the method that's called here iterates over them in forward
   11480   // direction.
   11481   return EnsureCanContainElements(
   11482       args->arguments() - first_arg - (arg_count - 1),
   11483       arg_count, mode);
   11484 }
   11485 
   11486 
   11487 PropertyType JSObject::GetLocalPropertyType(Name* name) {
   11488   uint32_t index = 0;
   11489   if (name->AsArrayIndex(&index)) {
   11490     return GetLocalElementType(index);
   11491   }
   11492   LookupResult lookup(GetIsolate());
   11493   LocalLookup(name, &lookup, true);
   11494   return lookup.type();
   11495 }
   11496 
   11497 
   11498 PropertyType JSObject::GetLocalElementType(uint32_t index) {
   11499   return GetElementsAccessor()->GetType(this, this, index);
   11500 }
   11501 
   11502 
   11503 AccessorPair* JSObject::GetLocalPropertyAccessorPair(Name* name) {
   11504   uint32_t index = 0;
   11505   if (name->AsArrayIndex(&index)) {
   11506     return GetLocalElementAccessorPair(index);
   11507   }
   11508 
   11509   LookupResult lookup(GetIsolate());
   11510   LocalLookupRealNamedProperty(name, &lookup);
   11511 
   11512   if (lookup.IsPropertyCallbacks() &&
   11513       lookup.GetCallbackObject()->IsAccessorPair()) {
   11514     return AccessorPair::cast(lookup.GetCallbackObject());
   11515   }
   11516   return NULL;
   11517 }
   11518 
   11519 
   11520 AccessorPair* JSObject::GetLocalElementAccessorPair(uint32_t index) {
   11521   if (IsJSGlobalProxy()) {
   11522     Object* proto = GetPrototype();
   11523     if (proto->IsNull()) return NULL;
   11524     ASSERT(proto->IsJSGlobalObject());
   11525     return JSObject::cast(proto)->GetLocalElementAccessorPair(index);
   11526   }
   11527 
   11528   // Check for lookup interceptor.
   11529   if (HasIndexedInterceptor()) return NULL;
   11530 
   11531   return GetElementsAccessor()->GetAccessorPair(this, this, index);
   11532 }
   11533 
   11534 
   11535 MaybeObject* JSObject::SetElementWithInterceptor(uint32_t index,
   11536                                                  Object* value,
   11537                                                  PropertyAttributes attributes,
   11538                                                  StrictModeFlag strict_mode,
   11539                                                  bool check_prototype,
   11540                                                  SetPropertyMode set_mode) {
   11541   Isolate* isolate = GetIsolate();
   11542   // Make sure that the top context does not change when doing
   11543   // callbacks or interceptor calls.
   11544   AssertNoContextChange ncc;
   11545   HandleScope scope(isolate);
   11546   Handle<InterceptorInfo> interceptor(GetIndexedInterceptor());
   11547   Handle<JSObject> this_handle(this);
   11548   Handle<Object> value_handle(value, isolate);
   11549   if (!interceptor->setter()->IsUndefined()) {
   11550     v8::IndexedPropertySetter setter =
   11551         v8::ToCData<v8::IndexedPropertySetter>(interceptor->setter());
   11552     LOG(isolate,
   11553         ApiIndexedPropertyAccess("interceptor-indexed-set", this, index));
   11554     PropertyCallbackArguments args(isolate, interceptor->data(), this, this);
   11555     v8::Handle<v8::Value> result =
   11556         args.Call(setter, index, v8::Utils::ToLocal(value_handle));
   11557     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   11558     if (!result.IsEmpty()) return *value_handle;
   11559   }
   11560   MaybeObject* raw_result =
   11561       this_handle->SetElementWithoutInterceptor(index,
   11562                                                 *value_handle,
   11563                                                 attributes,
   11564                                                 strict_mode,
   11565                                                 check_prototype,
   11566                                                 set_mode);
   11567   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   11568   return raw_result;
   11569 }
   11570 
   11571 
   11572 MaybeObject* JSObject::GetElementWithCallback(Object* receiver,
   11573                                               Object* structure,
   11574                                               uint32_t index,
   11575                                               Object* holder) {
   11576   Isolate* isolate = GetIsolate();
   11577   ASSERT(!structure->IsForeign());
   11578 
   11579   // api style callbacks.
   11580   if (structure->IsExecutableAccessorInfo()) {
   11581     Handle<ExecutableAccessorInfo> data(
   11582         ExecutableAccessorInfo::cast(structure));
   11583     Object* fun_obj = data->getter();
   11584     v8::AccessorGetter call_fun = v8::ToCData<v8::AccessorGetter>(fun_obj);
   11585     if (call_fun == NULL) return isolate->heap()->undefined_value();
   11586     HandleScope scope(isolate);
   11587     Handle<JSObject> self(JSObject::cast(receiver));
   11588     Handle<JSObject> holder_handle(JSObject::cast(holder));
   11589     Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
   11590     Handle<String> key = isolate->factory()->NumberToString(number);
   11591     LOG(isolate, ApiNamedPropertyAccess("load", *self, *key));
   11592     PropertyCallbackArguments
   11593         args(isolate, data->data(), *self, *holder_handle);
   11594     v8::Handle<v8::Value> result = args.Call(call_fun, v8::Utils::ToLocal(key));
   11595     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   11596     if (result.IsEmpty()) return isolate->heap()->undefined_value();
   11597     Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
   11598     result_internal->VerifyApiCallResultType();
   11599     return *result_internal;
   11600   }
   11601 
   11602   // __defineGetter__ callback
   11603   if (structure->IsAccessorPair()) {
   11604     Object* getter = AccessorPair::cast(structure)->getter();
   11605     if (getter->IsSpecFunction()) {
   11606       // TODO(rossberg): nicer would be to cast to some JSCallable here...
   11607       return GetPropertyWithDefinedGetter(receiver, JSReceiver::cast(getter));
   11608     }
   11609     // Getter is not a function.
   11610     return isolate->heap()->undefined_value();
   11611   }
   11612 
   11613   if (structure->IsDeclaredAccessorInfo()) {
   11614     return GetDeclaredAccessorProperty(receiver,
   11615                                        DeclaredAccessorInfo::cast(structure),
   11616                                        isolate);
   11617   }
   11618 
   11619   UNREACHABLE();
   11620   return NULL;
   11621 }
   11622 
   11623 
   11624 MaybeObject* JSObject::SetElementWithCallback(Object* structure,
   11625                                               uint32_t index,
   11626                                               Object* value,
   11627                                               JSObject* holder,
   11628                                               StrictModeFlag strict_mode) {
   11629   Isolate* isolate = GetIsolate();
   11630   HandleScope scope(isolate);
   11631 
   11632   // We should never get here to initialize a const with the hole
   11633   // value since a const declaration would conflict with the setter.
   11634   ASSERT(!value->IsTheHole());
   11635   Handle<Object> value_handle(value, isolate);
   11636 
   11637   // To accommodate both the old and the new api we switch on the
   11638   // data structure used to store the callbacks.  Eventually foreign
   11639   // callbacks should be phased out.
   11640   ASSERT(!structure->IsForeign());
   11641 
   11642   if (structure->IsExecutableAccessorInfo()) {
   11643     // api style callbacks
   11644     Handle<JSObject> self(this);
   11645     Handle<JSObject> holder_handle(JSObject::cast(holder));
   11646     Handle<ExecutableAccessorInfo> data(
   11647         ExecutableAccessorInfo::cast(structure));
   11648     Object* call_obj = data->setter();
   11649     v8::AccessorSetter call_fun = v8::ToCData<v8::AccessorSetter>(call_obj);
   11650     if (call_fun == NULL) return value;
   11651     Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
   11652     Handle<String> key(isolate->factory()->NumberToString(number));
   11653     LOG(isolate, ApiNamedPropertyAccess("store", *self, *key));
   11654     PropertyCallbackArguments
   11655         args(isolate, data->data(), *self, *holder_handle);
   11656     args.Call(call_fun,
   11657               v8::Utils::ToLocal(key),
   11658               v8::Utils::ToLocal(value_handle));
   11659     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   11660     return *value_handle;
   11661   }
   11662 
   11663   if (structure->IsAccessorPair()) {
   11664     Handle<Object> setter(AccessorPair::cast(structure)->setter(), isolate);
   11665     if (setter->IsSpecFunction()) {
   11666       // TODO(rossberg): nicer would be to cast to some JSCallable here...
   11667       return SetPropertyWithDefinedSetter(JSReceiver::cast(*setter), value);
   11668     } else {
   11669       if (strict_mode == kNonStrictMode) {
   11670         return value;
   11671       }
   11672       Handle<Object> holder_handle(holder, isolate);
   11673       Handle<Object> key(isolate->factory()->NewNumberFromUint(index));
   11674       Handle<Object> args[2] = { key, holder_handle };
   11675       return isolate->Throw(
   11676           *isolate->factory()->NewTypeError("no_setter_in_callback",
   11677                                             HandleVector(args, 2)));
   11678     }
   11679   }
   11680 
   11681   // TODO(dcarney): Handle correctly.
   11682   if (structure->IsDeclaredAccessorInfo()) return value;
   11683 
   11684   UNREACHABLE();
   11685   return NULL;
   11686 }
   11687 
   11688 
   11689 bool JSObject::HasFastArgumentsElements() {
   11690   Heap* heap = GetHeap();
   11691   if (!elements()->IsFixedArray()) return false;
   11692   FixedArray* elements = FixedArray::cast(this->elements());
   11693   if (elements->map() != heap->non_strict_arguments_elements_map()) {
   11694     return false;
   11695   }
   11696   FixedArray* arguments = FixedArray::cast(elements->get(1));
   11697   return !arguments->IsDictionary();
   11698 }
   11699 
   11700 
   11701 bool JSObject::HasDictionaryArgumentsElements() {
   11702   Heap* heap = GetHeap();
   11703   if (!elements()->IsFixedArray()) return false;
   11704   FixedArray* elements = FixedArray::cast(this->elements());
   11705   if (elements->map() != heap->non_strict_arguments_elements_map()) {
   11706     return false;
   11707   }
   11708   FixedArray* arguments = FixedArray::cast(elements->get(1));
   11709   return arguments->IsDictionary();
   11710 }
   11711 
   11712 
   11713 // Adding n elements in fast case is O(n*n).
   11714 // Note: revisit design to have dual undefined values to capture absent
   11715 // elements.
   11716 MaybeObject* JSObject::SetFastElement(uint32_t index,
   11717                                       Object* value,
   11718                                       StrictModeFlag strict_mode,
   11719                                       bool check_prototype) {
   11720   ASSERT(HasFastSmiOrObjectElements() ||
   11721          HasFastArgumentsElements());
   11722 
   11723   // Array optimizations rely on the prototype lookups of Array objects always
   11724   // returning undefined. If there is a store to the initial prototype object,
   11725   // make sure all of these optimizations are invalidated.
   11726   Isolate* isolate(GetIsolate());
   11727   if (isolate->is_initial_object_prototype(this) ||
   11728       isolate->is_initial_array_prototype(this)) {
   11729     HandleScope scope(GetIsolate());
   11730     map()->dependent_code()->DeoptimizeDependentCodeGroup(
   11731         GetIsolate(),
   11732         DependentCode::kElementsCantBeAddedGroup);
   11733   }
   11734 
   11735   FixedArray* backing_store = FixedArray::cast(elements());
   11736   if (backing_store->map() == GetHeap()->non_strict_arguments_elements_map()) {
   11737     backing_store = FixedArray::cast(backing_store->get(1));
   11738   } else {
   11739     MaybeObject* maybe = EnsureWritableFastElements();
   11740     if (!maybe->To(&backing_store)) return maybe;
   11741   }
   11742   uint32_t capacity = static_cast<uint32_t>(backing_store->length());
   11743 
   11744   if (check_prototype &&
   11745       (index >= capacity || backing_store->get(index)->IsTheHole())) {
   11746     bool found;
   11747     MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index,
   11748                                                                    value,
   11749                                                                    &found,
   11750                                                                    strict_mode);
   11751     if (found) return result;
   11752   }
   11753 
   11754   uint32_t new_capacity = capacity;
   11755   // Check if the length property of this object needs to be updated.
   11756   uint32_t array_length = 0;
   11757   bool must_update_array_length = false;
   11758   bool introduces_holes = true;
   11759   if (IsJSArray()) {
   11760     CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length));
   11761     introduces_holes = index > array_length;
   11762     if (index >= array_length) {
   11763       must_update_array_length = true;
   11764       array_length = index + 1;
   11765     }
   11766   } else {
   11767     introduces_holes = index >= capacity;
   11768   }
   11769 
   11770   // If the array is growing, and it's not growth by a single element at the
   11771   // end, make sure that the ElementsKind is HOLEY.
   11772   ElementsKind elements_kind = GetElementsKind();
   11773   if (introduces_holes &&
   11774       IsFastElementsKind(elements_kind) &&
   11775       !IsFastHoleyElementsKind(elements_kind)) {
   11776     ElementsKind transitioned_kind = GetHoleyElementsKind(elements_kind);
   11777     MaybeObject* maybe = TransitionElementsKind(transitioned_kind);
   11778     if (maybe->IsFailure()) return maybe;
   11779   }
   11780 
   11781   // Check if the capacity of the backing store needs to be increased, or if
   11782   // a transition to slow elements is necessary.
   11783   if (index >= capacity) {
   11784     bool convert_to_slow = true;
   11785     if ((index - capacity) < kMaxGap) {
   11786       new_capacity = NewElementsCapacity(index + 1);
   11787       ASSERT(new_capacity > index);
   11788       if (!ShouldConvertToSlowElements(new_capacity)) {
   11789         convert_to_slow = false;
   11790       }
   11791     }
   11792     if (convert_to_slow) {
   11793       MaybeObject* result = NormalizeElements();
   11794       if (result->IsFailure()) return result;
   11795       return SetDictionaryElement(index, value, NONE, strict_mode,
   11796                                   check_prototype);
   11797     }
   11798   }
   11799   // Convert to fast double elements if appropriate.
   11800   if (HasFastSmiElements() && !value->IsSmi() && value->IsNumber()) {
   11801     // Consider fixing the boilerplate as well if we have one.
   11802     ElementsKind to_kind = IsHoleyElementsKind(elements_kind)
   11803         ? FAST_HOLEY_DOUBLE_ELEMENTS
   11804         : FAST_DOUBLE_ELEMENTS;
   11805 
   11806     MaybeObject* maybe_failure = UpdateAllocationSite(to_kind);
   11807     if (maybe_failure->IsFailure()) return maybe_failure;
   11808 
   11809     MaybeObject* maybe =
   11810         SetFastDoubleElementsCapacityAndLength(new_capacity, array_length);
   11811     if (maybe->IsFailure()) return maybe;
   11812     FixedDoubleArray::cast(elements())->set(index, value->Number());
   11813     ValidateElements();
   11814     return value;
   11815   }
   11816   // Change elements kind from Smi-only to generic FAST if necessary.
   11817   if (HasFastSmiElements() && !value->IsSmi()) {
   11818     Map* new_map;
   11819     ElementsKind kind = HasFastHoleyElements()
   11820         ? FAST_HOLEY_ELEMENTS
   11821         : FAST_ELEMENTS;
   11822 
   11823     MaybeObject* maybe_failure = UpdateAllocationSite(kind);
   11824     if (maybe_failure->IsFailure()) return maybe_failure;
   11825 
   11826     MaybeObject* maybe_new_map = GetElementsTransitionMap(GetIsolate(),
   11827                                                           kind);
   11828     if (!maybe_new_map->To(&new_map)) return maybe_new_map;
   11829 
   11830     set_map(new_map);
   11831   }
   11832   // Increase backing store capacity if that's been decided previously.
   11833   if (new_capacity != capacity) {
   11834     FixedArray* new_elements;
   11835     SetFastElementsCapacitySmiMode smi_mode =
   11836         value->IsSmi() && HasFastSmiElements()
   11837             ? kAllowSmiElements
   11838             : kDontAllowSmiElements;
   11839     { MaybeObject* maybe =
   11840           SetFastElementsCapacityAndLength(new_capacity,
   11841                                            array_length,
   11842                                            smi_mode);
   11843       if (!maybe->To(&new_elements)) return maybe;
   11844     }
   11845     new_elements->set(index, value);
   11846     ValidateElements();
   11847     return value;
   11848   }
   11849 
   11850   // Finally, set the new element and length.
   11851   ASSERT(elements()->IsFixedArray());
   11852   backing_store->set(index, value);
   11853   if (must_update_array_length) {
   11854     JSArray::cast(this)->set_length(Smi::FromInt(array_length));
   11855   }
   11856   return value;
   11857 }
   11858 
   11859 
   11860 MaybeObject* JSObject::SetDictionaryElement(uint32_t index,
   11861                                             Object* value_raw,
   11862                                             PropertyAttributes attributes,
   11863                                             StrictModeFlag strict_mode,
   11864                                             bool check_prototype,
   11865                                             SetPropertyMode set_mode) {
   11866   ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements());
   11867   Isolate* isolate = GetIsolate();
   11868   Heap* heap = isolate->heap();
   11869   Handle<JSObject> self(this);
   11870   Handle<Object> value(value_raw, isolate);
   11871 
   11872   // Insert element in the dictionary.
   11873   Handle<FixedArray> elements(FixedArray::cast(this->elements()));
   11874   bool is_arguments =
   11875       (elements->map() == heap->non_strict_arguments_elements_map());
   11876   Handle<SeededNumberDictionary> dictionary(is_arguments
   11877     ? SeededNumberDictionary::cast(elements->get(1))
   11878     : SeededNumberDictionary::cast(*elements));
   11879 
   11880   int entry = dictionary->FindEntry(index);
   11881   if (entry != SeededNumberDictionary::kNotFound) {
   11882     Object* element = dictionary->ValueAt(entry);
   11883     PropertyDetails details = dictionary->DetailsAt(entry);
   11884     if (details.type() == CALLBACKS && set_mode == SET_PROPERTY) {
   11885       return SetElementWithCallback(element, index, *value, this, strict_mode);
   11886     } else {
   11887       dictionary->UpdateMaxNumberKey(index);
   11888       // If a value has not been initialized we allow writing to it even if it
   11889       // is read-only (a declared const that has not been initialized).  If a
   11890       // value is being defined we skip attribute checks completely.
   11891       if (set_mode == DEFINE_PROPERTY) {
   11892         details = PropertyDetails(
   11893             attributes, NORMAL, details.dictionary_index());
   11894         dictionary->DetailsAtPut(entry, details);
   11895       } else if (details.IsReadOnly() && !element->IsTheHole()) {
   11896         if (strict_mode == kNonStrictMode) {
   11897           return isolate->heap()->undefined_value();
   11898         } else {
   11899           Handle<Object> holder(this, isolate);
   11900           Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
   11901           Handle<Object> args[2] = { number, holder };
   11902           Handle<Object> error =
   11903               isolate->factory()->NewTypeError("strict_read_only_property",
   11904                                                HandleVector(args, 2));
   11905           return isolate->Throw(*error);
   11906         }
   11907       }
   11908       // Elements of the arguments object in slow mode might be slow aliases.
   11909       if (is_arguments && element->IsAliasedArgumentsEntry()) {
   11910         AliasedArgumentsEntry* entry = AliasedArgumentsEntry::cast(element);
   11911         Context* context = Context::cast(elements->get(0));
   11912         int context_index = entry->aliased_context_slot();
   11913         ASSERT(!context->get(context_index)->IsTheHole());
   11914         context->set(context_index, *value);
   11915         // For elements that are still writable we keep slow aliasing.
   11916         if (!details.IsReadOnly()) value = handle(element, isolate);
   11917       }
   11918       dictionary->ValueAtPut(entry, *value);
   11919     }
   11920   } else {
   11921     // Index not already used. Look for an accessor in the prototype chain.
   11922     // Can cause GC!
   11923     if (check_prototype) {
   11924       bool found;
   11925       MaybeObject* result = SetElementWithCallbackSetterInPrototypes(
   11926           index, *value, &found, strict_mode);
   11927       if (found) return result;
   11928     }
   11929     // When we set the is_extensible flag to false we always force the
   11930     // element into dictionary mode (and force them to stay there).
   11931     if (!self->map()->is_extensible()) {
   11932       if (strict_mode == kNonStrictMode) {
   11933         return isolate->heap()->undefined_value();
   11934       } else {
   11935         Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
   11936         Handle<String> name = isolate->factory()->NumberToString(number);
   11937         Handle<Object> args[1] = { name };
   11938         Handle<Object> error =
   11939             isolate->factory()->NewTypeError("object_not_extensible",
   11940                                              HandleVector(args, 1));
   11941         return isolate->Throw(*error);
   11942       }
   11943     }
   11944     FixedArrayBase* new_dictionary;
   11945     PropertyDetails details = PropertyDetails(attributes, NORMAL, 0);
   11946     MaybeObject* maybe = dictionary->AddNumberEntry(index, *value, details);
   11947     if (!maybe->To(&new_dictionary)) return maybe;
   11948     if (*dictionary != SeededNumberDictionary::cast(new_dictionary)) {
   11949       if (is_arguments) {
   11950         elements->set(1, new_dictionary);
   11951       } else {
   11952         self->set_elements(new_dictionary);
   11953       }
   11954       dictionary =
   11955           handle(SeededNumberDictionary::cast(new_dictionary), isolate);
   11956     }
   11957   }
   11958 
   11959   // Update the array length if this JSObject is an array.
   11960   if (self->IsJSArray()) {
   11961     MaybeObject* result =
   11962         JSArray::cast(*self)->JSArrayUpdateLengthFromIndex(index, *value);
   11963     if (result->IsFailure()) return result;
   11964   }
   11965 
   11966   // Attempt to put this object back in fast case.
   11967   if (self->ShouldConvertToFastElements()) {
   11968     uint32_t new_length = 0;
   11969     if (self->IsJSArray()) {
   11970       CHECK(JSArray::cast(*self)->length()->ToArrayIndex(&new_length));
   11971     } else {
   11972       new_length = dictionary->max_number_key() + 1;
   11973     }
   11974     SetFastElementsCapacitySmiMode smi_mode = FLAG_smi_only_arrays
   11975         ? kAllowSmiElements
   11976         : kDontAllowSmiElements;
   11977     bool has_smi_only_elements = false;
   11978     bool should_convert_to_fast_double_elements =
   11979         self->ShouldConvertToFastDoubleElements(&has_smi_only_elements);
   11980     if (has_smi_only_elements) {
   11981       smi_mode = kForceSmiElements;
   11982     }
   11983     MaybeObject* result = should_convert_to_fast_double_elements
   11984         ? self->SetFastDoubleElementsCapacityAndLength(new_length, new_length)
   11985         : self->SetFastElementsCapacityAndLength(
   11986             new_length, new_length, smi_mode);
   11987     self->ValidateElements();
   11988     if (result->IsFailure()) return result;
   11989 #ifdef DEBUG
   11990     if (FLAG_trace_normalization) {
   11991       PrintF("Object elements are fast case again:\n");
   11992       Print();
   11993     }
   11994 #endif
   11995   }
   11996   return *value;
   11997 }
   11998 
   11999 
   12000 MUST_USE_RESULT MaybeObject* JSObject::SetFastDoubleElement(
   12001     uint32_t index,
   12002     Object* value,
   12003     StrictModeFlag strict_mode,
   12004     bool check_prototype) {
   12005   ASSERT(HasFastDoubleElements());
   12006 
   12007   FixedArrayBase* base_elms = FixedArrayBase::cast(elements());
   12008   uint32_t elms_length = static_cast<uint32_t>(base_elms->length());
   12009 
   12010   // If storing to an element that isn't in the array, pass the store request
   12011   // up the prototype chain before storing in the receiver's elements.
   12012   if (check_prototype &&
   12013       (index >= elms_length ||
   12014        FixedDoubleArray::cast(base_elms)->is_the_hole(index))) {
   12015     bool found;
   12016     MaybeObject* result = SetElementWithCallbackSetterInPrototypes(index,
   12017                                                                    value,
   12018                                                                    &found,
   12019                                                                    strict_mode);
   12020     if (found) return result;
   12021   }
   12022 
   12023   // If the value object is not a heap number, switch to fast elements and try
   12024   // again.
   12025   bool value_is_smi = value->IsSmi();
   12026   bool introduces_holes = true;
   12027   uint32_t length = elms_length;
   12028   if (IsJSArray()) {
   12029     CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length));
   12030     introduces_holes = index > length;
   12031   } else {
   12032     introduces_holes = index >= elms_length;
   12033   }
   12034 
   12035   if (!value->IsNumber()) {
   12036     MaybeObject* maybe_obj = SetFastElementsCapacityAndLength(
   12037         elms_length,
   12038         length,
   12039         kDontAllowSmiElements);
   12040     if (maybe_obj->IsFailure()) return maybe_obj;
   12041     maybe_obj = SetFastElement(index, value, strict_mode, check_prototype);
   12042     if (maybe_obj->IsFailure()) return maybe_obj;
   12043     ValidateElements();
   12044     return maybe_obj;
   12045   }
   12046 
   12047   double double_value = value_is_smi
   12048       ? static_cast<double>(Smi::cast(value)->value())
   12049       : HeapNumber::cast(value)->value();
   12050 
   12051   // If the array is growing, and it's not growth by a single element at the
   12052   // end, make sure that the ElementsKind is HOLEY.
   12053   ElementsKind elements_kind = GetElementsKind();
   12054   if (introduces_holes && !IsFastHoleyElementsKind(elements_kind)) {
   12055     ElementsKind transitioned_kind = GetHoleyElementsKind(elements_kind);
   12056     MaybeObject* maybe = TransitionElementsKind(transitioned_kind);
   12057     if (maybe->IsFailure()) return maybe;
   12058   }
   12059 
   12060   // Check whether there is extra space in the fixed array.
   12061   if (index < elms_length) {
   12062     FixedDoubleArray* elms = FixedDoubleArray::cast(elements());
   12063     elms->set(index, double_value);
   12064     if (IsJSArray()) {
   12065       // Update the length of the array if needed.
   12066       uint32_t array_length = 0;
   12067       CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length));
   12068       if (index >= array_length) {
   12069         JSArray::cast(this)->set_length(Smi::FromInt(index + 1));
   12070       }
   12071     }
   12072     return value;
   12073   }
   12074 
   12075   // Allow gap in fast case.
   12076   if ((index - elms_length) < kMaxGap) {
   12077     // Try allocating extra space.
   12078     int new_capacity = NewElementsCapacity(index+1);
   12079     if (!ShouldConvertToSlowElements(new_capacity)) {
   12080       ASSERT(static_cast<uint32_t>(new_capacity) > index);
   12081       MaybeObject* maybe_obj =
   12082           SetFastDoubleElementsCapacityAndLength(new_capacity, index + 1);
   12083       if (maybe_obj->IsFailure()) return maybe_obj;
   12084       FixedDoubleArray::cast(elements())->set(index, double_value);
   12085       ValidateElements();
   12086       return value;
   12087     }
   12088   }
   12089 
   12090   // Otherwise default to slow case.
   12091   ASSERT(HasFastDoubleElements());
   12092   ASSERT(map()->has_fast_double_elements());
   12093   ASSERT(elements()->IsFixedDoubleArray());
   12094   Object* obj;
   12095   { MaybeObject* maybe_obj = NormalizeElements();
   12096     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   12097   }
   12098   ASSERT(HasDictionaryElements());
   12099   return SetElement(index, value, NONE, strict_mode, check_prototype);
   12100 }
   12101 
   12102 
   12103 MaybeObject* JSReceiver::SetElement(uint32_t index,
   12104                                     Object* value,
   12105                                     PropertyAttributes attributes,
   12106                                     StrictModeFlag strict_mode,
   12107                                     bool check_proto) {
   12108   if (IsJSProxy()) {
   12109     return JSProxy::cast(this)->SetElementWithHandler(
   12110         this, index, value, strict_mode);
   12111   } else {
   12112     return JSObject::cast(this)->SetElement(
   12113         index, value, attributes, strict_mode, check_proto);
   12114   }
   12115 }
   12116 
   12117 
   12118 Handle<Object> JSObject::SetOwnElement(Handle<JSObject> object,
   12119                                        uint32_t index,
   12120                                        Handle<Object> value,
   12121                                        StrictModeFlag strict_mode) {
   12122   ASSERT(!object->HasExternalArrayElements());
   12123   CALL_HEAP_FUNCTION(
   12124       object->GetIsolate(),
   12125       object->SetElement(index, *value, NONE, strict_mode, false),
   12126       Object);
   12127 }
   12128 
   12129 
   12130 Handle<Object> JSObject::SetElement(Handle<JSObject> object,
   12131                                     uint32_t index,
   12132                                     Handle<Object> value,
   12133                                     PropertyAttributes attr,
   12134                                     StrictModeFlag strict_mode,
   12135                                     SetPropertyMode set_mode) {
   12136   if (object->HasExternalArrayElements()) {
   12137     if (!value->IsNumber() && !value->IsUndefined()) {
   12138       bool has_exception;
   12139       Handle<Object> number = Execution::ToNumber(value, &has_exception);
   12140       if (has_exception) return Handle<Object>();
   12141       value = number;
   12142     }
   12143   }
   12144   CALL_HEAP_FUNCTION(
   12145       object->GetIsolate(),
   12146       object->SetElement(index, *value, attr, strict_mode, true, set_mode),
   12147       Object);
   12148 }
   12149 
   12150 
   12151 MaybeObject* JSObject::SetElement(uint32_t index,
   12152                                   Object* value_raw,
   12153                                   PropertyAttributes attributes,
   12154                                   StrictModeFlag strict_mode,
   12155                                   bool check_prototype,
   12156                                   SetPropertyMode set_mode) {
   12157   Isolate* isolate = GetIsolate();
   12158 
   12159   // Check access rights if needed.
   12160   if (IsAccessCheckNeeded()) {
   12161     if (!isolate->MayIndexedAccess(this, index, v8::ACCESS_SET)) {
   12162       isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET);
   12163       RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   12164       return value_raw;
   12165     }
   12166   }
   12167 
   12168   if (IsJSGlobalProxy()) {
   12169     Object* proto = GetPrototype();
   12170     if (proto->IsNull()) return value_raw;
   12171     ASSERT(proto->IsJSGlobalObject());
   12172     return JSObject::cast(proto)->SetElement(index,
   12173                                              value_raw,
   12174                                              attributes,
   12175                                              strict_mode,
   12176                                              check_prototype,
   12177                                              set_mode);
   12178   }
   12179 
   12180   // Don't allow element properties to be redefined for external arrays.
   12181   if (HasExternalArrayElements() && set_mode == DEFINE_PROPERTY) {
   12182     Handle<Object> number = isolate->factory()->NewNumberFromUint(index);
   12183     Handle<Object> args[] = { handle(this, isolate), number };
   12184     Handle<Object> error = isolate->factory()->NewTypeError(
   12185         "redef_external_array_element", HandleVector(args, ARRAY_SIZE(args)));
   12186     return isolate->Throw(*error);
   12187   }
   12188 
   12189   // Normalize the elements to enable attributes on the property.
   12190   if ((attributes & (DONT_DELETE | DONT_ENUM | READ_ONLY)) != 0) {
   12191     SeededNumberDictionary* dictionary;
   12192     MaybeObject* maybe_object = NormalizeElements();
   12193     if (!maybe_object->To(&dictionary)) return maybe_object;
   12194     // Make sure that we never go back to fast case.
   12195     dictionary->set_requires_slow_elements();
   12196   }
   12197 
   12198   if (!(FLAG_harmony_observation && map()->is_observed())) {
   12199     return HasIndexedInterceptor()
   12200       ? SetElementWithInterceptor(
   12201           index, value_raw, attributes, strict_mode, check_prototype, set_mode)
   12202       : SetElementWithoutInterceptor(
   12203           index, value_raw, attributes, strict_mode, check_prototype, set_mode);
   12204   }
   12205 
   12206   // From here on, everything has to be handlified.
   12207   Handle<JSObject> self(this);
   12208   Handle<Object> value(value_raw, isolate);
   12209   PropertyAttributes old_attributes = self->GetLocalElementAttribute(index);
   12210   Handle<Object> old_value = isolate->factory()->the_hole_value();
   12211   Handle<Object> old_length_handle;
   12212   Handle<Object> new_length_handle;
   12213 
   12214   if (old_attributes != ABSENT) {
   12215     if (self->GetLocalElementAccessorPair(index) == NULL)
   12216       old_value = Object::GetElement(self, index);
   12217   } else if (self->IsJSArray()) {
   12218     // Store old array length in case adding an element grows the array.
   12219     old_length_handle = handle(Handle<JSArray>::cast(self)->length(), isolate);
   12220   }
   12221 
   12222   // Check for lookup interceptor
   12223   MaybeObject* result = self->HasIndexedInterceptor()
   12224     ? self->SetElementWithInterceptor(
   12225         index, *value, attributes, strict_mode, check_prototype, set_mode)
   12226     : self->SetElementWithoutInterceptor(
   12227         index, *value, attributes, strict_mode, check_prototype, set_mode);
   12228 
   12229   Handle<Object> hresult;
   12230   if (!result->ToHandle(&hresult, isolate)) return result;
   12231 
   12232   Handle<String> name = isolate->factory()->Uint32ToString(index);
   12233   PropertyAttributes new_attributes = self->GetLocalElementAttribute(index);
   12234   if (old_attributes == ABSENT) {
   12235     if (self->IsJSArray() &&
   12236         !old_length_handle->SameValue(Handle<JSArray>::cast(self)->length())) {
   12237       new_length_handle = handle(Handle<JSArray>::cast(self)->length(),
   12238                                  isolate);
   12239       uint32_t old_length = 0;
   12240       uint32_t new_length = 0;
   12241       CHECK(old_length_handle->ToArrayIndex(&old_length));
   12242       CHECK(new_length_handle->ToArrayIndex(&new_length));
   12243 
   12244       BeginPerformSplice(Handle<JSArray>::cast(self));
   12245       EnqueueChangeRecord(self, "new", name, old_value);
   12246       EnqueueChangeRecord(self, "updated", isolate->factory()->length_string(),
   12247                           old_length_handle);
   12248       EndPerformSplice(Handle<JSArray>::cast(self));
   12249       Handle<JSArray> deleted = isolate->factory()->NewJSArray(0);
   12250       EnqueueSpliceRecord(Handle<JSArray>::cast(self), old_length, deleted,
   12251                           new_length - old_length);
   12252     } else {
   12253       EnqueueChangeRecord(self, "new", name, old_value);
   12254     }
   12255   } else if (old_value->IsTheHole()) {
   12256     EnqueueChangeRecord(self, "reconfigured", name, old_value);
   12257   } else {
   12258     Handle<Object> new_value = Object::GetElement(self, index);
   12259     bool value_changed = !old_value->SameValue(*new_value);
   12260     if (old_attributes != new_attributes) {
   12261       if (!value_changed) old_value = isolate->factory()->the_hole_value();
   12262       EnqueueChangeRecord(self, "reconfigured", name, old_value);
   12263     } else if (value_changed) {
   12264       EnqueueChangeRecord(self, "updated", name, old_value);
   12265     }
   12266   }
   12267 
   12268   return *hresult;
   12269 }
   12270 
   12271 
   12272 MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index,
   12273                                                     Object* value,
   12274                                                     PropertyAttributes attr,
   12275                                                     StrictModeFlag strict_mode,
   12276                                                     bool check_prototype,
   12277                                                     SetPropertyMode set_mode) {
   12278   ASSERT(HasDictionaryElements() ||
   12279          HasDictionaryArgumentsElements() ||
   12280          (attr & (DONT_DELETE | DONT_ENUM | READ_ONLY)) == 0);
   12281   Isolate* isolate = GetIsolate();
   12282   if (FLAG_trace_external_array_abuse &&
   12283       IsExternalArrayElementsKind(GetElementsKind())) {
   12284     CheckArrayAbuse(this, "external elements write", index);
   12285   }
   12286   if (FLAG_trace_js_array_abuse &&
   12287       !IsExternalArrayElementsKind(GetElementsKind())) {
   12288     if (IsJSArray()) {
   12289       CheckArrayAbuse(this, "elements write", index, true);
   12290     }
   12291   }
   12292   switch (GetElementsKind()) {
   12293     case FAST_SMI_ELEMENTS:
   12294     case FAST_ELEMENTS:
   12295     case FAST_HOLEY_SMI_ELEMENTS:
   12296     case FAST_HOLEY_ELEMENTS:
   12297       return SetFastElement(index, value, strict_mode, check_prototype);
   12298     case FAST_DOUBLE_ELEMENTS:
   12299     case FAST_HOLEY_DOUBLE_ELEMENTS:
   12300       return SetFastDoubleElement(index, value, strict_mode, check_prototype);
   12301     case EXTERNAL_PIXEL_ELEMENTS: {
   12302       ExternalPixelArray* pixels = ExternalPixelArray::cast(elements());
   12303       return pixels->SetValue(index, value);
   12304     }
   12305     case EXTERNAL_BYTE_ELEMENTS: {
   12306       ExternalByteArray* array = ExternalByteArray::cast(elements());
   12307       return array->SetValue(index, value);
   12308     }
   12309     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: {
   12310       ExternalUnsignedByteArray* array =
   12311           ExternalUnsignedByteArray::cast(elements());
   12312       return array->SetValue(index, value);
   12313     }
   12314     case EXTERNAL_SHORT_ELEMENTS: {
   12315       ExternalShortArray* array = ExternalShortArray::cast(elements());
   12316       return array->SetValue(index, value);
   12317     }
   12318     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: {
   12319       ExternalUnsignedShortArray* array =
   12320           ExternalUnsignedShortArray::cast(elements());
   12321       return array->SetValue(index, value);
   12322     }
   12323     case EXTERNAL_INT_ELEMENTS: {
   12324       ExternalIntArray* array = ExternalIntArray::cast(elements());
   12325       return array->SetValue(index, value);
   12326     }
   12327     case EXTERNAL_UNSIGNED_INT_ELEMENTS: {
   12328       ExternalUnsignedIntArray* array =
   12329           ExternalUnsignedIntArray::cast(elements());
   12330       return array->SetValue(index, value);
   12331     }
   12332     case EXTERNAL_FLOAT_ELEMENTS: {
   12333       ExternalFloatArray* array = ExternalFloatArray::cast(elements());
   12334       return array->SetValue(index, value);
   12335     }
   12336     case EXTERNAL_DOUBLE_ELEMENTS: {
   12337       ExternalDoubleArray* array = ExternalDoubleArray::cast(elements());
   12338       return array->SetValue(index, value);
   12339     }
   12340     case DICTIONARY_ELEMENTS:
   12341       return SetDictionaryElement(index, value, attr, strict_mode,
   12342                                   check_prototype, set_mode);
   12343     case NON_STRICT_ARGUMENTS_ELEMENTS: {
   12344       FixedArray* parameter_map = FixedArray::cast(elements());
   12345       uint32_t length = parameter_map->length();
   12346       Object* probe =
   12347           (index < length - 2) ? parameter_map->get(index + 2) : NULL;
   12348       if (probe != NULL && !probe->IsTheHole()) {
   12349         Context* context = Context::cast(parameter_map->get(0));
   12350         int context_index = Smi::cast(probe)->value();
   12351         ASSERT(!context->get(context_index)->IsTheHole());
   12352         context->set(context_index, value);
   12353         // Redefining attributes of an aliased element destroys fast aliasing.
   12354         if (set_mode == SET_PROPERTY || attr == NONE) return value;
   12355         parameter_map->set_the_hole(index + 2);
   12356         // For elements that are still writable we re-establish slow aliasing.
   12357         if ((attr & READ_ONLY) == 0) {
   12358           MaybeObject* maybe_entry =
   12359               isolate->heap()->AllocateAliasedArgumentsEntry(context_index);
   12360           if (!maybe_entry->ToObject(&value)) return maybe_entry;
   12361         }
   12362       }
   12363       FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
   12364       if (arguments->IsDictionary()) {
   12365         return SetDictionaryElement(index, value, attr, strict_mode,
   12366                                     check_prototype, set_mode);
   12367       } else {
   12368         return SetFastElement(index, value, strict_mode, check_prototype);
   12369       }
   12370     }
   12371   }
   12372   // All possible cases have been handled above. Add a return to avoid the
   12373   // complaints from the compiler.
   12374   UNREACHABLE();
   12375   return isolate->heap()->null_value();
   12376 }
   12377 
   12378 
   12379 Handle<Object> JSObject::TransitionElementsKind(Handle<JSObject> object,
   12380                                                 ElementsKind to_kind) {
   12381   CALL_HEAP_FUNCTION(object->GetIsolate(),
   12382                      object->TransitionElementsKind(to_kind),
   12383                      Object);
   12384 }
   12385 
   12386 
   12387 MaybeObject* JSObject::UpdateAllocationSite(ElementsKind to_kind) {
   12388   if (!FLAG_track_allocation_sites || !IsJSArray()) {
   12389     return this;
   12390   }
   12391 
   12392   AllocationMemento* memento = AllocationMemento::FindForJSObject(this);
   12393   if (memento == NULL || !memento->IsValid()) {
   12394     return this;
   12395   }
   12396 
   12397   // Walk through to the Allocation Site
   12398   AllocationSite* site = memento->GetAllocationSite();
   12399   if (site->IsLiteralSite()) {
   12400     JSArray* transition_info = JSArray::cast(site->transition_info());
   12401     ElementsKind kind = transition_info->GetElementsKind();
   12402     // if kind is holey ensure that to_kind is as well.
   12403     if (IsHoleyElementsKind(kind)) {
   12404       to_kind = GetHoleyElementsKind(to_kind);
   12405     }
   12406     if (AllocationSite::GetMode(kind, to_kind) == TRACK_ALLOCATION_SITE) {
   12407       // If the array is huge, it's not likely to be defined in a local
   12408       // function, so we shouldn't make new instances of it very often.
   12409       uint32_t length = 0;
   12410       CHECK(transition_info->length()->ToArrayIndex(&length));
   12411       if (length <= AllocationSite::kMaximumArrayBytesToPretransition) {
   12412         if (FLAG_trace_track_allocation_sites) {
   12413           PrintF(
   12414               "AllocationSite: JSArray %p boilerplate updated %s->%s\n",
   12415               reinterpret_cast<void*>(this),
   12416               ElementsKindToString(kind),
   12417               ElementsKindToString(to_kind));
   12418         }
   12419         return transition_info->TransitionElementsKind(to_kind);
   12420       }
   12421     }
   12422   } else {
   12423     ElementsKind kind = site->GetElementsKind();
   12424     // if kind is holey ensure that to_kind is as well.
   12425     if (IsHoleyElementsKind(kind)) {
   12426       to_kind = GetHoleyElementsKind(to_kind);
   12427     }
   12428     if (AllocationSite::GetMode(kind, to_kind) == TRACK_ALLOCATION_SITE) {
   12429       if (FLAG_trace_track_allocation_sites) {
   12430         PrintF("AllocationSite: JSArray %p site updated %s->%s\n",
   12431                reinterpret_cast<void*>(this),
   12432                ElementsKindToString(kind),
   12433                ElementsKindToString(to_kind));
   12434       }
   12435       site->set_transition_info(Smi::FromInt(to_kind));
   12436     }
   12437   }
   12438   return this;
   12439 }
   12440 
   12441 
   12442 MaybeObject* JSObject::TransitionElementsKind(ElementsKind to_kind) {
   12443   ASSERT(!map()->is_observed());
   12444   ElementsKind from_kind = map()->elements_kind();
   12445 
   12446   if (IsFastHoleyElementsKind(from_kind)) {
   12447     to_kind = GetHoleyElementsKind(to_kind);
   12448   }
   12449 
   12450   if (from_kind == to_kind) return this;
   12451 
   12452   MaybeObject* maybe_failure = UpdateAllocationSite(to_kind);
   12453   if (maybe_failure->IsFailure()) return maybe_failure;
   12454 
   12455   Isolate* isolate = GetIsolate();
   12456   if (elements() == isolate->heap()->empty_fixed_array() ||
   12457       (IsFastSmiOrObjectElementsKind(from_kind) &&
   12458        IsFastSmiOrObjectElementsKind(to_kind)) ||
   12459       (from_kind == FAST_DOUBLE_ELEMENTS &&
   12460        to_kind == FAST_HOLEY_DOUBLE_ELEMENTS)) {
   12461     ASSERT(from_kind != TERMINAL_FAST_ELEMENTS_KIND);
   12462     // No change is needed to the elements() buffer, the transition
   12463     // only requires a map change.
   12464     MaybeObject* maybe_new_map = GetElementsTransitionMap(isolate, to_kind);
   12465     Map* new_map;
   12466     if (!maybe_new_map->To(&new_map)) return maybe_new_map;
   12467     set_map(new_map);
   12468     if (FLAG_trace_elements_transitions) {
   12469       FixedArrayBase* elms = FixedArrayBase::cast(elements());
   12470       PrintElementsTransition(stdout, from_kind, elms, to_kind, elms);
   12471     }
   12472     return this;
   12473   }
   12474 
   12475   FixedArrayBase* elms = FixedArrayBase::cast(elements());
   12476   uint32_t capacity = static_cast<uint32_t>(elms->length());
   12477   uint32_t length = capacity;
   12478 
   12479   if (IsJSArray()) {
   12480     Object* raw_length = JSArray::cast(this)->length();
   12481     if (raw_length->IsUndefined()) {
   12482       // If length is undefined, then JSArray is being initialized and has no
   12483       // elements, assume a length of zero.
   12484       length = 0;
   12485     } else {
   12486       CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length));
   12487     }
   12488   }
   12489 
   12490   if (IsFastSmiElementsKind(from_kind) &&
   12491       IsFastDoubleElementsKind(to_kind)) {
   12492     MaybeObject* maybe_result =
   12493         SetFastDoubleElementsCapacityAndLength(capacity, length);
   12494     if (maybe_result->IsFailure()) return maybe_result;
   12495     ValidateElements();
   12496     return this;
   12497   }
   12498 
   12499   if (IsFastDoubleElementsKind(from_kind) &&
   12500       IsFastObjectElementsKind(to_kind)) {
   12501     MaybeObject* maybe_result = SetFastElementsCapacityAndLength(
   12502         capacity, length, kDontAllowSmiElements);
   12503     if (maybe_result->IsFailure()) return maybe_result;
   12504     ValidateElements();
   12505     return this;
   12506   }
   12507 
   12508   // This method should never be called for any other case than the ones
   12509   // handled above.
   12510   UNREACHABLE();
   12511   return GetIsolate()->heap()->null_value();
   12512 }
   12513 
   12514 
   12515 // static
   12516 bool Map::IsValidElementsTransition(ElementsKind from_kind,
   12517                                     ElementsKind to_kind) {
   12518   // Transitions can't go backwards.
   12519   if (!IsMoreGeneralElementsKindTransition(from_kind, to_kind)) {
   12520     return false;
   12521   }
   12522 
   12523   // Transitions from HOLEY -> PACKED are not allowed.
   12524   return !IsFastHoleyElementsKind(from_kind) ||
   12525       IsFastHoleyElementsKind(to_kind);
   12526 }
   12527 
   12528 
   12529 MaybeObject* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index,
   12530                                                    Object* value) {
   12531   uint32_t old_len = 0;
   12532   CHECK(length()->ToArrayIndex(&old_len));
   12533   // Check to see if we need to update the length. For now, we make
   12534   // sure that the length stays within 32-bits (unsigned).
   12535   if (index >= old_len && index != 0xffffffff) {
   12536     Object* len;
   12537     { MaybeObject* maybe_len =
   12538           GetHeap()->NumberFromDouble(static_cast<double>(index) + 1);
   12539       if (!maybe_len->ToObject(&len)) return maybe_len;
   12540     }
   12541     set_length(len);
   12542   }
   12543   return value;
   12544 }
   12545 
   12546 
   12547 MaybeObject* JSObject::GetElementWithInterceptor(Object* receiver,
   12548                                                  uint32_t index) {
   12549   Isolate* isolate = GetIsolate();
   12550   // Make sure that the top context does not change when doing
   12551   // callbacks or interceptor calls.
   12552   AssertNoContextChange ncc;
   12553   HandleScope scope(isolate);
   12554   Handle<InterceptorInfo> interceptor(GetIndexedInterceptor(), isolate);
   12555   Handle<Object> this_handle(receiver, isolate);
   12556   Handle<JSObject> holder_handle(this, isolate);
   12557   if (!interceptor->getter()->IsUndefined()) {
   12558     v8::IndexedPropertyGetter getter =
   12559         v8::ToCData<v8::IndexedPropertyGetter>(interceptor->getter());
   12560     LOG(isolate,
   12561         ApiIndexedPropertyAccess("interceptor-indexed-get", this, index));
   12562     PropertyCallbackArguments
   12563         args(isolate, interceptor->data(), receiver, this);
   12564     v8::Handle<v8::Value> result = args.Call(getter, index);
   12565     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   12566     if (!result.IsEmpty()) {
   12567       Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
   12568       result_internal->VerifyApiCallResultType();
   12569       return *result_internal;
   12570     }
   12571   }
   12572 
   12573   Heap* heap = holder_handle->GetHeap();
   12574   ElementsAccessor* handler = holder_handle->GetElementsAccessor();
   12575   MaybeObject* raw_result = handler->Get(*this_handle,
   12576                                          *holder_handle,
   12577                                          index);
   12578   if (raw_result != heap->the_hole_value()) return raw_result;
   12579 
   12580   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   12581 
   12582   Object* pt = holder_handle->GetPrototype();
   12583   if (pt == heap->null_value()) return heap->undefined_value();
   12584   return pt->GetElementWithReceiver(*this_handle, index);
   12585 }
   12586 
   12587 
   12588 bool JSObject::HasDenseElements() {
   12589   int capacity = 0;
   12590   int used = 0;
   12591   GetElementsCapacityAndUsage(&capacity, &used);
   12592   return (capacity == 0) || (used > (capacity / 2));
   12593 }
   12594 
   12595 
   12596 void JSObject::GetElementsCapacityAndUsage(int* capacity, int* used) {
   12597   *capacity = 0;
   12598   *used = 0;
   12599 
   12600   FixedArrayBase* backing_store_base = FixedArrayBase::cast(elements());
   12601   FixedArray* backing_store = NULL;
   12602   switch (GetElementsKind()) {
   12603     case NON_STRICT_ARGUMENTS_ELEMENTS:
   12604       backing_store_base =
   12605           FixedArray::cast(FixedArray::cast(backing_store_base)->get(1));
   12606       backing_store = FixedArray::cast(backing_store_base);
   12607       if (backing_store->IsDictionary()) {
   12608         SeededNumberDictionary* dictionary =
   12609             SeededNumberDictionary::cast(backing_store);
   12610         *capacity = dictionary->Capacity();
   12611         *used = dictionary->NumberOfElements();
   12612         break;
   12613       }
   12614       // Fall through.
   12615     case FAST_SMI_ELEMENTS:
   12616     case FAST_ELEMENTS:
   12617       if (IsJSArray()) {
   12618         *capacity = backing_store_base->length();
   12619         *used = Smi::cast(JSArray::cast(this)->length())->value();
   12620         break;
   12621       }
   12622       // Fall through if packing is not guaranteed.
   12623     case FAST_HOLEY_SMI_ELEMENTS:
   12624     case FAST_HOLEY_ELEMENTS:
   12625       backing_store = FixedArray::cast(backing_store_base);
   12626       *capacity = backing_store->length();
   12627       for (int i = 0; i < *capacity; ++i) {
   12628         if (!backing_store->get(i)->IsTheHole()) ++(*used);
   12629       }
   12630       break;
   12631     case DICTIONARY_ELEMENTS: {
   12632       SeededNumberDictionary* dictionary =
   12633           SeededNumberDictionary::cast(FixedArray::cast(elements()));
   12634       *capacity = dictionary->Capacity();
   12635       *used = dictionary->NumberOfElements();
   12636       break;
   12637     }
   12638     case FAST_DOUBLE_ELEMENTS:
   12639       if (IsJSArray()) {
   12640         *capacity = backing_store_base->length();
   12641         *used = Smi::cast(JSArray::cast(this)->length())->value();
   12642         break;
   12643       }
   12644       // Fall through if packing is not guaranteed.
   12645     case FAST_HOLEY_DOUBLE_ELEMENTS: {
   12646       FixedDoubleArray* elms = FixedDoubleArray::cast(elements());
   12647       *capacity = elms->length();
   12648       for (int i = 0; i < *capacity; i++) {
   12649         if (!elms->is_the_hole(i)) ++(*used);
   12650       }
   12651       break;
   12652     }
   12653     case EXTERNAL_BYTE_ELEMENTS:
   12654     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
   12655     case EXTERNAL_SHORT_ELEMENTS:
   12656     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
   12657     case EXTERNAL_INT_ELEMENTS:
   12658     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
   12659     case EXTERNAL_FLOAT_ELEMENTS:
   12660     case EXTERNAL_DOUBLE_ELEMENTS:
   12661     case EXTERNAL_PIXEL_ELEMENTS:
   12662       // External arrays are considered 100% used.
   12663       ExternalArray* external_array = ExternalArray::cast(elements());
   12664       *capacity = external_array->length();
   12665       *used = external_array->length();
   12666       break;
   12667   }
   12668 }
   12669 
   12670 
   12671 bool JSObject::ShouldConvertToSlowElements(int new_capacity) {
   12672   STATIC_ASSERT(kMaxUncheckedOldFastElementsLength <=
   12673                 kMaxUncheckedFastElementsLength);
   12674   if (new_capacity <= kMaxUncheckedOldFastElementsLength ||
   12675       (new_capacity <= kMaxUncheckedFastElementsLength &&
   12676        GetHeap()->InNewSpace(this))) {
   12677     return false;
   12678   }
   12679   // If the fast-case backing storage takes up roughly three times as
   12680   // much space (in machine words) as a dictionary backing storage
   12681   // would, the object should have slow elements.
   12682   int old_capacity = 0;
   12683   int used_elements = 0;
   12684   GetElementsCapacityAndUsage(&old_capacity, &used_elements);
   12685   int dictionary_size = SeededNumberDictionary::ComputeCapacity(used_elements) *
   12686       SeededNumberDictionary::kEntrySize;
   12687   return 3 * dictionary_size <= new_capacity;
   12688 }
   12689 
   12690 
   12691 bool JSObject::ShouldConvertToFastElements() {
   12692   ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements());
   12693   // If the elements are sparse, we should not go back to fast case.
   12694   if (!HasDenseElements()) return false;
   12695   // An object requiring access checks is never allowed to have fast
   12696   // elements.  If it had fast elements we would skip security checks.
   12697   if (IsAccessCheckNeeded()) return false;
   12698   // Observed objects may not go to fast mode because they rely on map checks,
   12699   // and for fast element accesses we sometimes check element kinds only.
   12700   if (FLAG_harmony_observation && map()->is_observed()) return false;
   12701 
   12702   FixedArray* elements = FixedArray::cast(this->elements());
   12703   SeededNumberDictionary* dictionary = NULL;
   12704   if (elements->map() == GetHeap()->non_strict_arguments_elements_map()) {
   12705     dictionary = SeededNumberDictionary::cast(elements->get(1));
   12706   } else {
   12707     dictionary = SeededNumberDictionary::cast(elements);
   12708   }
   12709   // If an element has been added at a very high index in the elements
   12710   // dictionary, we cannot go back to fast case.
   12711   if (dictionary->requires_slow_elements()) return false;
   12712   // If the dictionary backing storage takes up roughly half as much
   12713   // space (in machine words) as a fast-case backing storage would,
   12714   // the object should have fast elements.
   12715   uint32_t array_size = 0;
   12716   if (IsJSArray()) {
   12717     CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_size));
   12718   } else {
   12719     array_size = dictionary->max_number_key();
   12720   }
   12721   uint32_t dictionary_size = static_cast<uint32_t>(dictionary->Capacity()) *
   12722       SeededNumberDictionary::kEntrySize;
   12723   return 2 * dictionary_size >= array_size;
   12724 }
   12725 
   12726 
   12727 bool JSObject::ShouldConvertToFastDoubleElements(
   12728     bool* has_smi_only_elements) {
   12729   *has_smi_only_elements = false;
   12730   if (FLAG_unbox_double_arrays) {
   12731     ASSERT(HasDictionaryElements());
   12732     SeededNumberDictionary* dictionary =
   12733         SeededNumberDictionary::cast(elements());
   12734     bool found_double = false;
   12735     for (int i = 0; i < dictionary->Capacity(); i++) {
   12736       Object* key = dictionary->KeyAt(i);
   12737       if (key->IsNumber()) {
   12738         Object* value = dictionary->ValueAt(i);
   12739         if (!value->IsNumber()) return false;
   12740         if (!value->IsSmi()) {
   12741           found_double = true;
   12742         }
   12743       }
   12744     }
   12745     *has_smi_only_elements = !found_double;
   12746     return found_double;
   12747   } else {
   12748     return false;
   12749   }
   12750 }
   12751 
   12752 
   12753 // Certain compilers request function template instantiation when they
   12754 // see the definition of the other template functions in the
   12755 // class. This requires us to have the template functions put
   12756 // together, so even though this function belongs in objects-debug.cc,
   12757 // we keep it here instead to satisfy certain compilers.
   12758 #ifdef OBJECT_PRINT
   12759 template<typename Shape, typename Key>
   12760 void Dictionary<Shape, Key>::Print(FILE* out) {
   12761   int capacity = HashTable<Shape, Key>::Capacity();
   12762   for (int i = 0; i < capacity; i++) {
   12763     Object* k = HashTable<Shape, Key>::KeyAt(i);
   12764     if (HashTable<Shape, Key>::IsKey(k)) {
   12765       PrintF(out, " ");
   12766       if (k->IsString()) {
   12767         String::cast(k)->StringPrint(out);
   12768       } else {
   12769         k->ShortPrint(out);
   12770       }
   12771       PrintF(out, ": ");
   12772       ValueAt(i)->ShortPrint(out);
   12773       PrintF(out, "\n");
   12774     }
   12775   }
   12776 }
   12777 #endif
   12778 
   12779 
   12780 template<typename Shape, typename Key>
   12781 void Dictionary<Shape, Key>::CopyValuesTo(FixedArray* elements) {
   12782   int pos = 0;
   12783   int capacity = HashTable<Shape, Key>::Capacity();
   12784   DisallowHeapAllocation no_gc;
   12785   WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc);
   12786   for (int i = 0; i < capacity; i++) {
   12787     Object* k =  Dictionary<Shape, Key>::KeyAt(i);
   12788     if (Dictionary<Shape, Key>::IsKey(k)) {
   12789       elements->set(pos++, ValueAt(i), mode);
   12790     }
   12791   }
   12792   ASSERT(pos == elements->length());
   12793 }
   12794 
   12795 
   12796 InterceptorInfo* JSObject::GetNamedInterceptor() {
   12797   ASSERT(map()->has_named_interceptor());
   12798   JSFunction* constructor = JSFunction::cast(map()->constructor());
   12799   ASSERT(constructor->shared()->IsApiFunction());
   12800   Object* result =
   12801       constructor->shared()->get_api_func_data()->named_property_handler();
   12802   return InterceptorInfo::cast(result);
   12803 }
   12804 
   12805 
   12806 InterceptorInfo* JSObject::GetIndexedInterceptor() {
   12807   ASSERT(map()->has_indexed_interceptor());
   12808   JSFunction* constructor = JSFunction::cast(map()->constructor());
   12809   ASSERT(constructor->shared()->IsApiFunction());
   12810   Object* result =
   12811       constructor->shared()->get_api_func_data()->indexed_property_handler();
   12812   return InterceptorInfo::cast(result);
   12813 }
   12814 
   12815 
   12816 MaybeObject* JSObject::GetPropertyPostInterceptor(
   12817     Object* receiver,
   12818     Name* name,
   12819     PropertyAttributes* attributes) {
   12820   // Check local property in holder, ignore interceptor.
   12821   LookupResult result(GetIsolate());
   12822   LocalLookupRealNamedProperty(name, &result);
   12823   if (result.IsFound()) {
   12824     return GetProperty(receiver, &result, name, attributes);
   12825   }
   12826   // Continue searching via the prototype chain.
   12827   Object* pt = GetPrototype();
   12828   *attributes = ABSENT;
   12829   if (pt->IsNull()) return GetHeap()->undefined_value();
   12830   return pt->GetPropertyWithReceiver(receiver, name, attributes);
   12831 }
   12832 
   12833 
   12834 MaybeObject* JSObject::GetLocalPropertyPostInterceptor(
   12835     Object* receiver,
   12836     Name* name,
   12837     PropertyAttributes* attributes) {
   12838   // Check local property in holder, ignore interceptor.
   12839   LookupResult result(GetIsolate());
   12840   LocalLookupRealNamedProperty(name, &result);
   12841   if (result.IsFound()) {
   12842     return GetProperty(receiver, &result, name, attributes);
   12843   }
   12844   return GetHeap()->undefined_value();
   12845 }
   12846 
   12847 
   12848 MaybeObject* JSObject::GetPropertyWithInterceptor(
   12849     Object* receiver,
   12850     Name* name,
   12851     PropertyAttributes* attributes) {
   12852   // TODO(rossberg): Support symbols in the API.
   12853   if (name->IsSymbol()) return GetHeap()->undefined_value();
   12854 
   12855   Isolate* isolate = GetIsolate();
   12856   InterceptorInfo* interceptor = GetNamedInterceptor();
   12857   HandleScope scope(isolate);
   12858   Handle<Object> receiver_handle(receiver, isolate);
   12859   Handle<JSObject> holder_handle(this);
   12860   Handle<String> name_handle(String::cast(name));
   12861 
   12862   if (!interceptor->getter()->IsUndefined()) {
   12863     v8::NamedPropertyGetter getter =
   12864         v8::ToCData<v8::NamedPropertyGetter>(interceptor->getter());
   12865     LOG(isolate,
   12866         ApiNamedPropertyAccess("interceptor-named-get", *holder_handle, name));
   12867     PropertyCallbackArguments
   12868         args(isolate, interceptor->data(), receiver, this);
   12869     v8::Handle<v8::Value> result =
   12870         args.Call(getter, v8::Utils::ToLocal(name_handle));
   12871     RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   12872     if (!result.IsEmpty()) {
   12873       *attributes = NONE;
   12874       Handle<Object> result_internal = v8::Utils::OpenHandle(*result);
   12875       result_internal->VerifyApiCallResultType();
   12876       return *result_internal;
   12877     }
   12878   }
   12879 
   12880   MaybeObject* result = holder_handle->GetPropertyPostInterceptor(
   12881       *receiver_handle,
   12882       *name_handle,
   12883       attributes);
   12884   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   12885   return result;
   12886 }
   12887 
   12888 
   12889 bool JSObject::HasRealNamedProperty(Isolate* isolate, Name* key) {
   12890   // Check access rights if needed.
   12891   if (IsAccessCheckNeeded()) {
   12892     if (!isolate->MayNamedAccess(this, key, v8::ACCESS_HAS)) {
   12893       isolate->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
   12894       return false;
   12895     }
   12896   }
   12897 
   12898   LookupResult result(isolate);
   12899   LocalLookupRealNamedProperty(key, &result);
   12900   return result.IsFound() && !result.IsInterceptor();
   12901 }
   12902 
   12903 
   12904 bool JSObject::HasRealElementProperty(Isolate* isolate, uint32_t index) {
   12905   // Check access rights if needed.
   12906   if (IsAccessCheckNeeded()) {
   12907     if (!isolate->MayIndexedAccess(this, index, v8::ACCESS_HAS)) {
   12908       isolate->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
   12909       return false;
   12910     }
   12911   }
   12912 
   12913   if (IsJSGlobalProxy()) {
   12914     Object* proto = GetPrototype();
   12915     if (proto->IsNull()) return false;
   12916     ASSERT(proto->IsJSGlobalObject());
   12917     return JSObject::cast(proto)->HasRealElementProperty(isolate, index);
   12918   }
   12919 
   12920   return GetElementAttributeWithoutInterceptor(this, index, false) != ABSENT;
   12921 }
   12922 
   12923 
   12924 bool JSObject::HasRealNamedCallbackProperty(Isolate* isolate, Name* key) {
   12925   // Check access rights if needed.
   12926   if (IsAccessCheckNeeded()) {
   12927     if (!isolate->MayNamedAccess(this, key, v8::ACCESS_HAS)) {
   12928       isolate->ReportFailedAccessCheck(this, v8::ACCESS_HAS);
   12929       return false;
   12930     }
   12931   }
   12932 
   12933   LookupResult result(isolate);
   12934   LocalLookupRealNamedProperty(key, &result);
   12935   return result.IsPropertyCallbacks();
   12936 }
   12937 
   12938 
   12939 int JSObject::NumberOfLocalProperties(PropertyAttributes filter) {
   12940   if (HasFastProperties()) {
   12941     Map* map = this->map();
   12942     if (filter == NONE) return map->NumberOfOwnDescriptors();
   12943     if (filter & DONT_ENUM) {
   12944       int result = map->EnumLength();
   12945       if (result != Map::kInvalidEnumCache) return result;
   12946     }
   12947     return map->NumberOfDescribedProperties(OWN_DESCRIPTORS, filter);
   12948   }
   12949   return property_dictionary()->NumberOfElementsFilterAttributes(filter);
   12950 }
   12951 
   12952 
   12953 void FixedArray::SwapPairs(FixedArray* numbers, int i, int j) {
   12954   Object* temp = get(i);
   12955   set(i, get(j));
   12956   set(j, temp);
   12957   if (this != numbers) {
   12958     temp = numbers->get(i);
   12959     numbers->set(i, Smi::cast(numbers->get(j)));
   12960     numbers->set(j, Smi::cast(temp));
   12961   }
   12962 }
   12963 
   12964 
   12965 static void InsertionSortPairs(FixedArray* content,
   12966                                FixedArray* numbers,
   12967                                int len) {
   12968   for (int i = 1; i < len; i++) {
   12969     int j = i;
   12970     while (j > 0 &&
   12971            (NumberToUint32(numbers->get(j - 1)) >
   12972             NumberToUint32(numbers->get(j)))) {
   12973       content->SwapPairs(numbers, j - 1, j);
   12974       j--;
   12975     }
   12976   }
   12977 }
   12978 
   12979 
   12980 void HeapSortPairs(FixedArray* content, FixedArray* numbers, int len) {
   12981   // In-place heap sort.
   12982   ASSERT(content->length() == numbers->length());
   12983 
   12984   // Bottom-up max-heap construction.
   12985   for (int i = 1; i < len; ++i) {
   12986     int child_index = i;
   12987     while (child_index > 0) {
   12988       int parent_index = ((child_index + 1) >> 1) - 1;
   12989       uint32_t parent_value = NumberToUint32(numbers->get(parent_index));
   12990       uint32_t child_value = NumberToUint32(numbers->get(child_index));
   12991       if (parent_value < child_value) {
   12992         content->SwapPairs(numbers, parent_index, child_index);
   12993       } else {
   12994         break;
   12995       }
   12996       child_index = parent_index;
   12997     }
   12998   }
   12999 
   13000   // Extract elements and create sorted array.
   13001   for (int i = len - 1; i > 0; --i) {
   13002     // Put max element at the back of the array.
   13003     content->SwapPairs(numbers, 0, i);
   13004     // Sift down the new top element.
   13005     int parent_index = 0;
   13006     while (true) {
   13007       int child_index = ((parent_index + 1) << 1) - 1;
   13008       if (child_index >= i) break;
   13009       uint32_t child1_value = NumberToUint32(numbers->get(child_index));
   13010       uint32_t child2_value = NumberToUint32(numbers->get(child_index + 1));
   13011       uint32_t parent_value = NumberToUint32(numbers->get(parent_index));
   13012       if (child_index + 1 >= i || child1_value > child2_value) {
   13013         if (parent_value > child1_value) break;
   13014         content->SwapPairs(numbers, parent_index, child_index);
   13015         parent_index = child_index;
   13016       } else {
   13017         if (parent_value > child2_value) break;
   13018         content->SwapPairs(numbers, parent_index, child_index + 1);
   13019         parent_index = child_index + 1;
   13020       }
   13021     }
   13022   }
   13023 }
   13024 
   13025 
   13026 // Sort this array and the numbers as pairs wrt. the (distinct) numbers.
   13027 void FixedArray::SortPairs(FixedArray* numbers, uint32_t len) {
   13028   ASSERT(this->length() == numbers->length());
   13029   // For small arrays, simply use insertion sort.
   13030   if (len <= 10) {
   13031     InsertionSortPairs(this, numbers, len);
   13032     return;
   13033   }
   13034   // Check the range of indices.
   13035   uint32_t min_index = NumberToUint32(numbers->get(0));
   13036   uint32_t max_index = min_index;
   13037   uint32_t i;
   13038   for (i = 1; i < len; i++) {
   13039     if (NumberToUint32(numbers->get(i)) < min_index) {
   13040       min_index = NumberToUint32(numbers->get(i));
   13041     } else if (NumberToUint32(numbers->get(i)) > max_index) {
   13042       max_index = NumberToUint32(numbers->get(i));
   13043     }
   13044   }
   13045   if (max_index - min_index + 1 == len) {
   13046     // Indices form a contiguous range, unless there are duplicates.
   13047     // Do an in-place linear time sort assuming distinct numbers, but
   13048     // avoid hanging in case they are not.
   13049     for (i = 0; i < len; i++) {
   13050       uint32_t p;
   13051       uint32_t j = 0;
   13052       // While the current element at i is not at its correct position p,
   13053       // swap the elements at these two positions.
   13054       while ((p = NumberToUint32(numbers->get(i)) - min_index) != i &&
   13055              j++ < len) {
   13056         SwapPairs(numbers, i, p);
   13057       }
   13058     }
   13059   } else {
   13060     HeapSortPairs(this, numbers, len);
   13061     return;
   13062   }
   13063 }
   13064 
   13065 
   13066 // Fill in the names of local properties into the supplied storage. The main
   13067 // purpose of this function is to provide reflection information for the object
   13068 // mirrors.
   13069 void JSObject::GetLocalPropertyNames(
   13070     FixedArray* storage, int index, PropertyAttributes filter) {
   13071   ASSERT(storage->length() >= (NumberOfLocalProperties(filter) - index));
   13072   if (HasFastProperties()) {
   13073     int real_size = map()->NumberOfOwnDescriptors();
   13074     DescriptorArray* descs = map()->instance_descriptors();
   13075     for (int i = 0; i < real_size; i++) {
   13076       if ((descs->GetDetails(i).attributes() & filter) == 0 &&
   13077           ((filter & SYMBOLIC) == 0 || !descs->GetKey(i)->IsSymbol())) {
   13078         storage->set(index++, descs->GetKey(i));
   13079       }
   13080     }
   13081   } else {
   13082     property_dictionary()->CopyKeysTo(storage,
   13083                                       index,
   13084                                       filter,
   13085                                       NameDictionary::UNSORTED);
   13086   }
   13087 }
   13088 
   13089 
   13090 int JSObject::NumberOfLocalElements(PropertyAttributes filter) {
   13091   return GetLocalElementKeys(NULL, filter);
   13092 }
   13093 
   13094 
   13095 int JSObject::NumberOfEnumElements() {
   13096   // Fast case for objects with no elements.
   13097   if (!IsJSValue() && HasFastObjectElements()) {
   13098     uint32_t length = IsJSArray() ?
   13099         static_cast<uint32_t>(
   13100             Smi::cast(JSArray::cast(this)->length())->value()) :
   13101         static_cast<uint32_t>(FixedArray::cast(elements())->length());
   13102     if (length == 0) return 0;
   13103   }
   13104   // Compute the number of enumerable elements.
   13105   return NumberOfLocalElements(static_cast<PropertyAttributes>(DONT_ENUM));
   13106 }
   13107 
   13108 
   13109 int JSObject::GetLocalElementKeys(FixedArray* storage,
   13110                                   PropertyAttributes filter) {
   13111   int counter = 0;
   13112   switch (GetElementsKind()) {
   13113     case FAST_SMI_ELEMENTS:
   13114     case FAST_ELEMENTS:
   13115     case FAST_HOLEY_SMI_ELEMENTS:
   13116     case FAST_HOLEY_ELEMENTS: {
   13117       int length = IsJSArray() ?
   13118           Smi::cast(JSArray::cast(this)->length())->value() :
   13119           FixedArray::cast(elements())->length();
   13120       for (int i = 0; i < length; i++) {
   13121         if (!FixedArray::cast(elements())->get(i)->IsTheHole()) {
   13122           if (storage != NULL) {
   13123             storage->set(counter, Smi::FromInt(i));
   13124           }
   13125           counter++;
   13126         }
   13127       }
   13128       ASSERT(!storage || storage->length() >= counter);
   13129       break;
   13130     }
   13131     case FAST_DOUBLE_ELEMENTS:
   13132     case FAST_HOLEY_DOUBLE_ELEMENTS: {
   13133       int length = IsJSArray() ?
   13134           Smi::cast(JSArray::cast(this)->length())->value() :
   13135           FixedDoubleArray::cast(elements())->length();
   13136       for (int i = 0; i < length; i++) {
   13137         if (!FixedDoubleArray::cast(elements())->is_the_hole(i)) {
   13138           if (storage != NULL) {
   13139             storage->set(counter, Smi::FromInt(i));
   13140           }
   13141           counter++;
   13142         }
   13143       }
   13144       ASSERT(!storage || storage->length() >= counter);
   13145       break;
   13146     }
   13147     case EXTERNAL_PIXEL_ELEMENTS: {
   13148       int length = ExternalPixelArray::cast(elements())->length();
   13149       while (counter < length) {
   13150         if (storage != NULL) {
   13151           storage->set(counter, Smi::FromInt(counter));
   13152         }
   13153         counter++;
   13154       }
   13155       ASSERT(!storage || storage->length() >= counter);
   13156       break;
   13157     }
   13158     case EXTERNAL_BYTE_ELEMENTS:
   13159     case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
   13160     case EXTERNAL_SHORT_ELEMENTS:
   13161     case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
   13162     case EXTERNAL_INT_ELEMENTS:
   13163     case EXTERNAL_UNSIGNED_INT_ELEMENTS:
   13164     case EXTERNAL_FLOAT_ELEMENTS:
   13165     case EXTERNAL_DOUBLE_ELEMENTS: {
   13166       int length = ExternalArray::cast(elements())->length();
   13167       while (counter < length) {
   13168         if (storage != NULL) {
   13169           storage->set(counter, Smi::FromInt(counter));
   13170         }
   13171         counter++;
   13172       }
   13173       ASSERT(!storage || storage->length() >= counter);
   13174       break;
   13175     }
   13176     case DICTIONARY_ELEMENTS: {
   13177       if (storage != NULL) {
   13178         element_dictionary()->CopyKeysTo(storage,
   13179                                          filter,
   13180                                          SeededNumberDictionary::SORTED);
   13181       }
   13182       counter += element_dictionary()->NumberOfElementsFilterAttributes(filter);
   13183       break;
   13184     }
   13185     case NON_STRICT_ARGUMENTS_ELEMENTS: {
   13186       FixedArray* parameter_map = FixedArray::cast(elements());
   13187       int mapped_length = parameter_map->length() - 2;
   13188       FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
   13189       if (arguments->IsDictionary()) {
   13190         // Copy the keys from arguments first, because Dictionary::CopyKeysTo
   13191         // will insert in storage starting at index 0.
   13192         SeededNumberDictionary* dictionary =
   13193             SeededNumberDictionary::cast(arguments);
   13194         if (storage != NULL) {
   13195           dictionary->CopyKeysTo(
   13196               storage, filter, SeededNumberDictionary::UNSORTED);
   13197         }
   13198         counter += dictionary->NumberOfElementsFilterAttributes(filter);
   13199         for (int i = 0; i < mapped_length; ++i) {
   13200           if (!parameter_map->get(i + 2)->IsTheHole()) {
   13201             if (storage != NULL) storage->set(counter, Smi::FromInt(i));
   13202             ++counter;
   13203           }
   13204         }
   13205         if (storage != NULL) storage->SortPairs(storage, counter);
   13206 
   13207       } else {
   13208         int backing_length = arguments->length();
   13209         int i = 0;
   13210         for (; i < mapped_length; ++i) {
   13211           if (!parameter_map->get(i + 2)->IsTheHole()) {
   13212             if (storage != NULL) storage->set(counter, Smi::FromInt(i));
   13213             ++counter;
   13214           } else if (i < backing_length && !arguments->get(i)->IsTheHole()) {
   13215             if (storage != NULL) storage->set(counter, Smi::FromInt(i));
   13216             ++counter;
   13217           }
   13218         }
   13219         for (; i < backing_length; ++i) {
   13220           if (storage != NULL) storage->set(counter, Smi::FromInt(i));
   13221           ++counter;
   13222         }
   13223       }
   13224       break;
   13225     }
   13226   }
   13227 
   13228   if (this->IsJSValue()) {
   13229     Object* val = JSValue::cast(this)->value();
   13230     if (val->IsString()) {
   13231       String* str = String::cast(val);
   13232       if (storage) {
   13233         for (int i = 0; i < str->length(); i++) {
   13234           storage->set(counter + i, Smi::FromInt(i));
   13235         }
   13236       }
   13237       counter += str->length();
   13238     }
   13239   }
   13240   ASSERT(!storage || storage->length() == counter);
   13241   return counter;
   13242 }
   13243 
   13244 
   13245 int JSObject::GetEnumElementKeys(FixedArray* storage) {
   13246   return GetLocalElementKeys(storage,
   13247                              static_cast<PropertyAttributes>(DONT_ENUM));
   13248 }
   13249 
   13250 
   13251 // StringKey simply carries a string object as key.
   13252 class StringKey : public HashTableKey {
   13253  public:
   13254   explicit StringKey(String* string) :
   13255       string_(string),
   13256       hash_(HashForObject(string)) { }
   13257 
   13258   bool IsMatch(Object* string) {
   13259     // We know that all entries in a hash table had their hash keys created.
   13260     // Use that knowledge to have fast failure.
   13261     if (hash_ != HashForObject(string)) {
   13262       return false;
   13263     }
   13264     return string_->Equals(String::cast(string));
   13265   }
   13266 
   13267   uint32_t Hash() { return hash_; }
   13268 
   13269   uint32_t HashForObject(Object* other) { return String::cast(other)->Hash(); }
   13270 
   13271   Object* AsObject(Heap* heap) { return string_; }
   13272 
   13273   String* string_;
   13274   uint32_t hash_;
   13275 };
   13276 
   13277 
   13278 // StringSharedKeys are used as keys in the eval cache.
   13279 class StringSharedKey : public HashTableKey {
   13280  public:
   13281   StringSharedKey(String* source,
   13282                   SharedFunctionInfo* shared,
   13283                   LanguageMode language_mode,
   13284                   int scope_position)
   13285       : source_(source),
   13286         shared_(shared),
   13287         language_mode_(language_mode),
   13288         scope_position_(scope_position) { }
   13289 
   13290   bool IsMatch(Object* other) {
   13291     if (!other->IsFixedArray()) return false;
   13292     FixedArray* other_array = FixedArray::cast(other);
   13293     SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0));
   13294     if (shared != shared_) return false;
   13295     int language_unchecked = Smi::cast(other_array->get(2))->value();
   13296     ASSERT(language_unchecked == CLASSIC_MODE ||
   13297            language_unchecked == STRICT_MODE ||
   13298            language_unchecked == EXTENDED_MODE);
   13299     LanguageMode language_mode = static_cast<LanguageMode>(language_unchecked);
   13300     if (language_mode != language_mode_) return false;
   13301     int scope_position = Smi::cast(other_array->get(3))->value();
   13302     if (scope_position != scope_position_) return false;
   13303     String* source = String::cast(other_array->get(1));
   13304     return source->Equals(source_);
   13305   }
   13306 
   13307   static uint32_t StringSharedHashHelper(String* source,
   13308                                          SharedFunctionInfo* shared,
   13309                                          LanguageMode language_mode,
   13310                                          int scope_position) {
   13311     uint32_t hash = source->Hash();
   13312     if (shared->HasSourceCode()) {
   13313       // Instead of using the SharedFunctionInfo pointer in the hash
   13314       // code computation, we use a combination of the hash of the
   13315       // script source code and the start position of the calling scope.
   13316       // We do this to ensure that the cache entries can survive garbage
   13317       // collection.
   13318       Script* script = Script::cast(shared->script());
   13319       hash ^= String::cast(script->source())->Hash();
   13320       if (language_mode == STRICT_MODE) hash ^= 0x8000;
   13321       if (language_mode == EXTENDED_MODE) hash ^= 0x0080;
   13322       hash += scope_position;
   13323     }
   13324     return hash;
   13325   }
   13326 
   13327   uint32_t Hash() {
   13328     return StringSharedHashHelper(
   13329         source_, shared_, language_mode_, scope_position_);
   13330   }
   13331 
   13332   uint32_t HashForObject(Object* obj) {
   13333     FixedArray* other_array = FixedArray::cast(obj);
   13334     SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0));
   13335     String* source = String::cast(other_array->get(1));
   13336     int language_unchecked = Smi::cast(other_array->get(2))->value();
   13337     ASSERT(language_unchecked == CLASSIC_MODE ||
   13338            language_unchecked == STRICT_MODE ||
   13339            language_unchecked == EXTENDED_MODE);
   13340     LanguageMode language_mode = static_cast<LanguageMode>(language_unchecked);
   13341     int scope_position = Smi::cast(other_array->get(3))->value();
   13342     return StringSharedHashHelper(
   13343         source, shared, language_mode, scope_position);
   13344   }
   13345 
   13346   MUST_USE_RESULT MaybeObject* AsObject(Heap* heap) {
   13347     Object* obj;
   13348     { MaybeObject* maybe_obj = heap->AllocateFixedArray(4);
   13349       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   13350     }
   13351     FixedArray* other_array = FixedArray::cast(obj);
   13352     other_array->set(0, shared_);
   13353     other_array->set(1, source_);
   13354     other_array->set(2, Smi::FromInt(language_mode_));
   13355     other_array->set(3, Smi::FromInt(scope_position_));
   13356     return other_array;
   13357   }
   13358 
   13359  private:
   13360   String* source_;
   13361   SharedFunctionInfo* shared_;
   13362   LanguageMode language_mode_;
   13363   int scope_position_;
   13364 };
   13365 
   13366 
   13367 // RegExpKey carries the source and flags of a regular expression as key.
   13368 class RegExpKey : public HashTableKey {
   13369  public:
   13370   RegExpKey(String* string, JSRegExp::Flags flags)
   13371       : string_(string),
   13372         flags_(Smi::FromInt(flags.value())) { }
   13373 
   13374   // Rather than storing the key in the hash table, a pointer to the
   13375   // stored value is stored where the key should be.  IsMatch then
   13376   // compares the search key to the found object, rather than comparing
   13377   // a key to a key.
   13378   bool IsMatch(Object* obj) {
   13379     FixedArray* val = FixedArray::cast(obj);
   13380     return string_->Equals(String::cast(val->get(JSRegExp::kSourceIndex)))
   13381         && (flags_ == val->get(JSRegExp::kFlagsIndex));
   13382   }
   13383 
   13384   uint32_t Hash() { return RegExpHash(string_, flags_); }
   13385 
   13386   Object* AsObject(Heap* heap) {
   13387     // Plain hash maps, which is where regexp keys are used, don't
   13388     // use this function.
   13389     UNREACHABLE();
   13390     return NULL;
   13391   }
   13392 
   13393   uint32_t HashForObject(Object* obj) {
   13394     FixedArray* val = FixedArray::cast(obj);
   13395     return RegExpHash(String::cast(val->get(JSRegExp::kSourceIndex)),
   13396                       Smi::cast(val->get(JSRegExp::kFlagsIndex)));
   13397   }
   13398 
   13399   static uint32_t RegExpHash(String* string, Smi* flags) {
   13400     return string->Hash() + flags->value();
   13401   }
   13402 
   13403   String* string_;
   13404   Smi* flags_;
   13405 };
   13406 
   13407 
   13408 // Utf8StringKey carries a vector of chars as key.
   13409 class Utf8StringKey : public HashTableKey {
   13410  public:
   13411   explicit Utf8StringKey(Vector<const char> string, uint32_t seed)
   13412       : string_(string), hash_field_(0), seed_(seed) { }
   13413 
   13414   bool IsMatch(Object* string) {
   13415     return String::cast(string)->IsUtf8EqualTo(string_);
   13416   }
   13417 
   13418   uint32_t Hash() {
   13419     if (hash_field_ != 0) return hash_field_ >> String::kHashShift;
   13420     hash_field_ = StringHasher::ComputeUtf8Hash(string_, seed_, &chars_);
   13421     uint32_t result = hash_field_ >> String::kHashShift;
   13422     ASSERT(result != 0);  // Ensure that the hash value of 0 is never computed.
   13423     return result;
   13424   }
   13425 
   13426   uint32_t HashForObject(Object* other) {
   13427     return String::cast(other)->Hash();
   13428   }
   13429 
   13430   MaybeObject* AsObject(Heap* heap) {
   13431     if (hash_field_ == 0) Hash();
   13432     return heap->AllocateInternalizedStringFromUtf8(string_,
   13433                                                     chars_,
   13434                                                     hash_field_);
   13435   }
   13436 
   13437   Vector<const char> string_;
   13438   uint32_t hash_field_;
   13439   int chars_;  // Caches the number of characters when computing the hash code.
   13440   uint32_t seed_;
   13441 };
   13442 
   13443 
   13444 template <typename Char>
   13445 class SequentialStringKey : public HashTableKey {
   13446  public:
   13447   explicit SequentialStringKey(Vector<const Char> string, uint32_t seed)
   13448       : string_(string), hash_field_(0), seed_(seed) { }
   13449 
   13450   uint32_t Hash() {
   13451     hash_field_ = StringHasher::HashSequentialString<Char>(string_.start(),
   13452                                                            string_.length(),
   13453                                                            seed_);
   13454 
   13455     uint32_t result = hash_field_ >> String::kHashShift;
   13456     ASSERT(result != 0);  // Ensure that the hash value of 0 is never computed.
   13457     return result;
   13458   }
   13459 
   13460 
   13461   uint32_t HashForObject(Object* other) {
   13462     return String::cast(other)->Hash();
   13463   }
   13464 
   13465   Vector<const Char> string_;
   13466   uint32_t hash_field_;
   13467   uint32_t seed_;
   13468 };
   13469 
   13470 
   13471 
   13472 class OneByteStringKey : public SequentialStringKey<uint8_t> {
   13473  public:
   13474   OneByteStringKey(Vector<const uint8_t> str, uint32_t seed)
   13475       : SequentialStringKey<uint8_t>(str, seed) { }
   13476 
   13477   bool IsMatch(Object* string) {
   13478     return String::cast(string)->IsOneByteEqualTo(string_);
   13479   }
   13480 
   13481   MaybeObject* AsObject(Heap* heap) {
   13482     if (hash_field_ == 0) Hash();
   13483     return heap->AllocateOneByteInternalizedString(string_, hash_field_);
   13484   }
   13485 };
   13486 
   13487 
   13488 class SubStringOneByteStringKey : public HashTableKey {
   13489  public:
   13490   explicit SubStringOneByteStringKey(Handle<SeqOneByteString> string,
   13491                                      int from,
   13492                                      int length)
   13493       : string_(string), from_(from), length_(length) { }
   13494 
   13495   uint32_t Hash() {
   13496     ASSERT(length_ >= 0);
   13497     ASSERT(from_ + length_ <= string_->length());
   13498     uint8_t* chars = string_->GetChars() + from_;
   13499     hash_field_ = StringHasher::HashSequentialString(
   13500         chars, length_, string_->GetHeap()->HashSeed());
   13501     uint32_t result = hash_field_ >> String::kHashShift;
   13502     ASSERT(result != 0);  // Ensure that the hash value of 0 is never computed.
   13503     return result;
   13504   }
   13505 
   13506 
   13507   uint32_t HashForObject(Object* other) {
   13508     return String::cast(other)->Hash();
   13509   }
   13510 
   13511   bool IsMatch(Object* string) {
   13512     Vector<const uint8_t> chars(string_->GetChars() + from_, length_);
   13513     return String::cast(string)->IsOneByteEqualTo(chars);
   13514   }
   13515 
   13516   MaybeObject* AsObject(Heap* heap) {
   13517     if (hash_field_ == 0) Hash();
   13518     Vector<const uint8_t> chars(string_->GetChars() + from_, length_);
   13519     return heap->AllocateOneByteInternalizedString(chars, hash_field_);
   13520   }
   13521 
   13522  private:
   13523   Handle<SeqOneByteString> string_;
   13524   int from_;
   13525   int length_;
   13526   uint32_t hash_field_;
   13527 };
   13528 
   13529 
   13530 class TwoByteStringKey : public SequentialStringKey<uc16> {
   13531  public:
   13532   explicit TwoByteStringKey(Vector<const uc16> str, uint32_t seed)
   13533       : SequentialStringKey<uc16>(str, seed) { }
   13534 
   13535   bool IsMatch(Object* string) {
   13536     return String::cast(string)->IsTwoByteEqualTo(string_);
   13537   }
   13538 
   13539   MaybeObject* AsObject(Heap* heap) {
   13540     if (hash_field_ == 0) Hash();
   13541     return heap->AllocateTwoByteInternalizedString(string_, hash_field_);
   13542   }
   13543 };
   13544 
   13545 
   13546 // InternalizedStringKey carries a string/internalized-string object as key.
   13547 class InternalizedStringKey : public HashTableKey {
   13548  public:
   13549   explicit InternalizedStringKey(String* string)
   13550       : string_(string) { }
   13551 
   13552   bool IsMatch(Object* string) {
   13553     return String::cast(string)->Equals(string_);
   13554   }
   13555 
   13556   uint32_t Hash() { return string_->Hash(); }
   13557 
   13558   uint32_t HashForObject(Object* other) {
   13559     return String::cast(other)->Hash();
   13560   }
   13561 
   13562   MaybeObject* AsObject(Heap* heap) {
   13563     // Attempt to flatten the string, so that internalized strings will most
   13564     // often be flat strings.
   13565     string_ = string_->TryFlattenGetString();
   13566     // Internalize the string if possible.
   13567     Map* map = heap->InternalizedStringMapForString(string_);
   13568     if (map != NULL) {
   13569       string_->set_map_no_write_barrier(map);
   13570       ASSERT(string_->IsInternalizedString());
   13571       return string_;
   13572     }
   13573     // Otherwise allocate a new internalized string.
   13574     return heap->AllocateInternalizedStringImpl(
   13575         string_, string_->length(), string_->hash_field());
   13576   }
   13577 
   13578   static uint32_t StringHash(Object* obj) {
   13579     return String::cast(obj)->Hash();
   13580   }
   13581 
   13582   String* string_;
   13583 };
   13584 
   13585 
   13586 template<typename Shape, typename Key>
   13587 void HashTable<Shape, Key>::IteratePrefix(ObjectVisitor* v) {
   13588   IteratePointers(v, 0, kElementsStartOffset);
   13589 }
   13590 
   13591 
   13592 template<typename Shape, typename Key>
   13593 void HashTable<Shape, Key>::IterateElements(ObjectVisitor* v) {
   13594   IteratePointers(v,
   13595                   kElementsStartOffset,
   13596                   kHeaderSize + length() * kPointerSize);
   13597 }
   13598 
   13599 
   13600 template<typename Shape, typename Key>
   13601 MaybeObject* HashTable<Shape, Key>::Allocate(Heap* heap,
   13602                                              int at_least_space_for,
   13603                                              MinimumCapacity capacity_option,
   13604                                              PretenureFlag pretenure) {
   13605   ASSERT(!capacity_option || IS_POWER_OF_TWO(at_least_space_for));
   13606   int capacity = (capacity_option == USE_CUSTOM_MINIMUM_CAPACITY)
   13607                      ? at_least_space_for
   13608                      : ComputeCapacity(at_least_space_for);
   13609   if (capacity > HashTable::kMaxCapacity) {
   13610     return Failure::OutOfMemoryException(0x10);
   13611   }
   13612 
   13613   Object* obj;
   13614   { MaybeObject* maybe_obj =
   13615         heap-> AllocateHashTable(EntryToIndex(capacity), pretenure);
   13616     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   13617   }
   13618   HashTable::cast(obj)->SetNumberOfElements(0);
   13619   HashTable::cast(obj)->SetNumberOfDeletedElements(0);
   13620   HashTable::cast(obj)->SetCapacity(capacity);
   13621   return obj;
   13622 }
   13623 
   13624 
   13625 // Find entry for key otherwise return kNotFound.
   13626 int NameDictionary::FindEntry(Name* key) {
   13627   if (!key->IsUniqueName()) {
   13628     return HashTable<NameDictionaryShape, Name*>::FindEntry(key);
   13629   }
   13630 
   13631   // Optimized for unique names. Knowledge of the key type allows:
   13632   // 1. Move the check if the key is unique out of the loop.
   13633   // 2. Avoid comparing hash codes in unique-to-unique comparison.
   13634   // 3. Detect a case when a dictionary key is not unique but the key is.
   13635   //    In case of positive result the dictionary key may be replaced by the
   13636   //    internalized string with minimal performance penalty. It gives a chance
   13637   //    to perform further lookups in code stubs (and significant performance
   13638   //    boost a certain style of code).
   13639 
   13640   // EnsureCapacity will guarantee the hash table is never full.
   13641   uint32_t capacity = Capacity();
   13642   uint32_t entry = FirstProbe(key->Hash(), capacity);
   13643   uint32_t count = 1;
   13644 
   13645   while (true) {
   13646     int index = EntryToIndex(entry);
   13647     Object* element = get(index);
   13648     if (element->IsUndefined()) break;  // Empty entry.
   13649     if (key == element) return entry;
   13650     if (!element->IsUniqueName() &&
   13651         !element->IsTheHole() &&
   13652         Name::cast(element)->Equals(key)) {
   13653       // Replace a key that is a non-internalized string by the equivalent
   13654       // internalized string for faster further lookups.
   13655       set(index, key);
   13656       return entry;
   13657     }
   13658     ASSERT(element->IsTheHole() || !Name::cast(element)->Equals(key));
   13659     entry = NextProbe(entry, count++, capacity);
   13660   }
   13661   return kNotFound;
   13662 }
   13663 
   13664 
   13665 template<typename Shape, typename Key>
   13666 MaybeObject* HashTable<Shape, Key>::Rehash(HashTable* new_table, Key key) {
   13667   ASSERT(NumberOfElements() < new_table->Capacity());
   13668 
   13669   DisallowHeapAllocation no_gc;
   13670   WriteBarrierMode mode = new_table->GetWriteBarrierMode(no_gc);
   13671 
   13672   // Copy prefix to new array.
   13673   for (int i = kPrefixStartIndex;
   13674        i < kPrefixStartIndex + Shape::kPrefixSize;
   13675        i++) {
   13676     new_table->set(i, get(i), mode);
   13677   }
   13678 
   13679   // Rehash the elements.
   13680   int capacity = Capacity();
   13681   for (int i = 0; i < capacity; i++) {
   13682     uint32_t from_index = EntryToIndex(i);
   13683     Object* k = get(from_index);
   13684     if (IsKey(k)) {
   13685       uint32_t hash = HashTable<Shape, Key>::HashForObject(key, k);
   13686       uint32_t insertion_index =
   13687           EntryToIndex(new_table->FindInsertionEntry(hash));
   13688       for (int j = 0; j < Shape::kEntrySize; j++) {
   13689         new_table->set(insertion_index + j, get(from_index + j), mode);
   13690       }
   13691     }
   13692   }
   13693   new_table->SetNumberOfElements(NumberOfElements());
   13694   new_table->SetNumberOfDeletedElements(0);
   13695   return new_table;
   13696 }
   13697 
   13698 
   13699 template<typename Shape, typename Key>
   13700 MaybeObject* HashTable<Shape, Key>::EnsureCapacity(int n, Key key) {
   13701   int capacity = Capacity();
   13702   int nof = NumberOfElements() + n;
   13703   int nod = NumberOfDeletedElements();
   13704   // Return if:
   13705   //   50% is still free after adding n elements and
   13706   //   at most 50% of the free elements are deleted elements.
   13707   if (nod <= (capacity - nof) >> 1) {
   13708     int needed_free = nof >> 1;
   13709     if (nof + needed_free <= capacity) return this;
   13710   }
   13711 
   13712   const int kMinCapacityForPretenure = 256;
   13713   bool pretenure =
   13714       (capacity > kMinCapacityForPretenure) && !GetHeap()->InNewSpace(this);
   13715   Object* obj;
   13716   { MaybeObject* maybe_obj =
   13717         Allocate(GetHeap(),
   13718                  nof * 2,
   13719                  USE_DEFAULT_MINIMUM_CAPACITY,
   13720                  pretenure ? TENURED : NOT_TENURED);
   13721     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   13722   }
   13723 
   13724   return Rehash(HashTable::cast(obj), key);
   13725 }
   13726 
   13727 
   13728 template<typename Shape, typename Key>
   13729 MaybeObject* HashTable<Shape, Key>::Shrink(Key key) {
   13730   int capacity = Capacity();
   13731   int nof = NumberOfElements();
   13732 
   13733   // Shrink to fit the number of elements if only a quarter of the
   13734   // capacity is filled with elements.
   13735   if (nof > (capacity >> 2)) return this;
   13736   // Allocate a new dictionary with room for at least the current
   13737   // number of elements. The allocation method will make sure that
   13738   // there is extra room in the dictionary for additions. Don't go
   13739   // lower than room for 16 elements.
   13740   int at_least_room_for = nof;
   13741   if (at_least_room_for < 16) return this;
   13742 
   13743   const int kMinCapacityForPretenure = 256;
   13744   bool pretenure =
   13745       (at_least_room_for > kMinCapacityForPretenure) &&
   13746       !GetHeap()->InNewSpace(this);
   13747   Object* obj;
   13748   { MaybeObject* maybe_obj =
   13749         Allocate(GetHeap(),
   13750                  at_least_room_for,
   13751                  USE_DEFAULT_MINIMUM_CAPACITY,
   13752                  pretenure ? TENURED : NOT_TENURED);
   13753     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   13754   }
   13755 
   13756   return Rehash(HashTable::cast(obj), key);
   13757 }
   13758 
   13759 
   13760 template<typename Shape, typename Key>
   13761 uint32_t HashTable<Shape, Key>::FindInsertionEntry(uint32_t hash) {
   13762   uint32_t capacity = Capacity();
   13763   uint32_t entry = FirstProbe(hash, capacity);
   13764   uint32_t count = 1;
   13765   // EnsureCapacity will guarantee the hash table is never full.
   13766   while (true) {
   13767     Object* element = KeyAt(entry);
   13768     if (element->IsUndefined() || element->IsTheHole()) break;
   13769     entry = NextProbe(entry, count++, capacity);
   13770   }
   13771   return entry;
   13772 }
   13773 
   13774 
   13775 // Force instantiation of template instances class.
   13776 // Please note this list is compiler dependent.
   13777 
   13778 template class HashTable<StringTableShape, HashTableKey*>;
   13779 
   13780 template class HashTable<CompilationCacheShape, HashTableKey*>;
   13781 
   13782 template class HashTable<MapCacheShape, HashTableKey*>;
   13783 
   13784 template class HashTable<ObjectHashTableShape<1>, Object*>;
   13785 
   13786 template class HashTable<ObjectHashTableShape<2>, Object*>;
   13787 
   13788 template class Dictionary<NameDictionaryShape, Name*>;
   13789 
   13790 template class Dictionary<SeededNumberDictionaryShape, uint32_t>;
   13791 
   13792 template class Dictionary<UnseededNumberDictionaryShape, uint32_t>;
   13793 
   13794 template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>::
   13795     Allocate(Heap* heap, int at_least_space_for, PretenureFlag pretenure);
   13796 
   13797 template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>::
   13798     Allocate(Heap* heap, int at_least_space_for, PretenureFlag pretenure);
   13799 
   13800 template MaybeObject* Dictionary<NameDictionaryShape, Name*>::
   13801     Allocate(Heap* heap, int n, PretenureFlag pretenure);
   13802 
   13803 template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>::AtPut(
   13804     uint32_t, Object*);
   13805 
   13806 template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>::
   13807     AtPut(uint32_t, Object*);
   13808 
   13809 template Object* Dictionary<SeededNumberDictionaryShape, uint32_t>::
   13810     SlowReverseLookup(Object* value);
   13811 
   13812 template Object* Dictionary<UnseededNumberDictionaryShape, uint32_t>::
   13813     SlowReverseLookup(Object* value);
   13814 
   13815 template Object* Dictionary<NameDictionaryShape, Name*>::SlowReverseLookup(
   13816     Object*);
   13817 
   13818 template void Dictionary<SeededNumberDictionaryShape, uint32_t>::CopyKeysTo(
   13819     FixedArray*,
   13820     PropertyAttributes,
   13821     Dictionary<SeededNumberDictionaryShape, uint32_t>::SortMode);
   13822 
   13823 template Object* Dictionary<NameDictionaryShape, Name*>::DeleteProperty(
   13824     int, JSObject::DeleteMode);
   13825 
   13826 template Object* Dictionary<SeededNumberDictionaryShape, uint32_t>::
   13827     DeleteProperty(int, JSObject::DeleteMode);
   13828 
   13829 template MaybeObject* Dictionary<NameDictionaryShape, Name*>::Shrink(Name* n);
   13830 
   13831 template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>::Shrink(
   13832     uint32_t);
   13833 
   13834 template void Dictionary<NameDictionaryShape, Name*>::CopyKeysTo(
   13835     FixedArray*,
   13836     int,
   13837     PropertyAttributes,
   13838     Dictionary<NameDictionaryShape, Name*>::SortMode);
   13839 
   13840 template int
   13841 Dictionary<NameDictionaryShape, Name*>::NumberOfElementsFilterAttributes(
   13842     PropertyAttributes);
   13843 
   13844 template MaybeObject* Dictionary<NameDictionaryShape, Name*>::Add(
   13845     Name*, Object*, PropertyDetails);
   13846 
   13847 template MaybeObject*
   13848 Dictionary<NameDictionaryShape, Name*>::GenerateNewEnumerationIndices();
   13849 
   13850 template int
   13851 Dictionary<SeededNumberDictionaryShape, uint32_t>::
   13852     NumberOfElementsFilterAttributes(PropertyAttributes);
   13853 
   13854 template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>::Add(
   13855     uint32_t, Object*, PropertyDetails);
   13856 
   13857 template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>::Add(
   13858     uint32_t, Object*, PropertyDetails);
   13859 
   13860 template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>::
   13861     EnsureCapacity(int, uint32_t);
   13862 
   13863 template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>::
   13864     EnsureCapacity(int, uint32_t);
   13865 
   13866 template MaybeObject* Dictionary<NameDictionaryShape, Name*>::
   13867     EnsureCapacity(int, Name*);
   13868 
   13869 template MaybeObject* Dictionary<SeededNumberDictionaryShape, uint32_t>::
   13870     AddEntry(uint32_t, Object*, PropertyDetails, uint32_t);
   13871 
   13872 template MaybeObject* Dictionary<UnseededNumberDictionaryShape, uint32_t>::
   13873     AddEntry(uint32_t, Object*, PropertyDetails, uint32_t);
   13874 
   13875 template MaybeObject* Dictionary<NameDictionaryShape, Name*>::AddEntry(
   13876     Name*, Object*, PropertyDetails, uint32_t);
   13877 
   13878 template
   13879 int Dictionary<SeededNumberDictionaryShape, uint32_t>::NumberOfEnumElements();
   13880 
   13881 template
   13882 int Dictionary<NameDictionaryShape, Name*>::NumberOfEnumElements();
   13883 
   13884 template
   13885 int HashTable<SeededNumberDictionaryShape, uint32_t>::FindEntry(uint32_t);
   13886 
   13887 
   13888 // Collates undefined and unexisting elements below limit from position
   13889 // zero of the elements. The object stays in Dictionary mode.
   13890 MaybeObject* JSObject::PrepareSlowElementsForSort(uint32_t limit) {
   13891   ASSERT(HasDictionaryElements());
   13892   // Must stay in dictionary mode, either because of requires_slow_elements,
   13893   // or because we are not going to sort (and therefore compact) all of the
   13894   // elements.
   13895   SeededNumberDictionary* dict = element_dictionary();
   13896   HeapNumber* result_double = NULL;
   13897   if (limit > static_cast<uint32_t>(Smi::kMaxValue)) {
   13898     // Allocate space for result before we start mutating the object.
   13899     Object* new_double;
   13900     { MaybeObject* maybe_new_double = GetHeap()->AllocateHeapNumber(0.0);
   13901       if (!maybe_new_double->ToObject(&new_double)) return maybe_new_double;
   13902     }
   13903     result_double = HeapNumber::cast(new_double);
   13904   }
   13905 
   13906   Object* obj;
   13907   { MaybeObject* maybe_obj =
   13908         SeededNumberDictionary::Allocate(GetHeap(), dict->NumberOfElements());
   13909     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   13910   }
   13911   SeededNumberDictionary* new_dict = SeededNumberDictionary::cast(obj);
   13912 
   13913   DisallowHeapAllocation no_alloc;
   13914 
   13915   uint32_t pos = 0;
   13916   uint32_t undefs = 0;
   13917   int capacity = dict->Capacity();
   13918   for (int i = 0; i < capacity; i++) {
   13919     Object* k = dict->KeyAt(i);
   13920     if (dict->IsKey(k)) {
   13921       ASSERT(k->IsNumber());
   13922       ASSERT(!k->IsSmi() || Smi::cast(k)->value() >= 0);
   13923       ASSERT(!k->IsHeapNumber() || HeapNumber::cast(k)->value() >= 0);
   13924       ASSERT(!k->IsHeapNumber() || HeapNumber::cast(k)->value() <= kMaxUInt32);
   13925       Object* value = dict->ValueAt(i);
   13926       PropertyDetails details = dict->DetailsAt(i);
   13927       if (details.type() == CALLBACKS || details.IsReadOnly()) {
   13928         // Bail out and do the sorting of undefineds and array holes in JS.
   13929         // Also bail out if the element is not supposed to be moved.
   13930         return Smi::FromInt(-1);
   13931       }
   13932       uint32_t key = NumberToUint32(k);
   13933       // In the following we assert that adding the entry to the new dictionary
   13934       // does not cause GC.  This is the case because we made sure to allocate
   13935       // the dictionary big enough above, so it need not grow.
   13936       if (key < limit) {
   13937         if (value->IsUndefined()) {
   13938           undefs++;
   13939         } else {
   13940           if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
   13941             // Adding an entry with the key beyond smi-range requires
   13942             // allocation. Bailout.
   13943             return Smi::FromInt(-1);
   13944           }
   13945           new_dict->AddNumberEntry(pos, value, details)->ToObjectUnchecked();
   13946           pos++;
   13947         }
   13948       } else {
   13949         if (key > static_cast<uint32_t>(Smi::kMaxValue)) {
   13950           // Adding an entry with the key beyond smi-range requires
   13951           // allocation. Bailout.
   13952           return Smi::FromInt(-1);
   13953         }
   13954         new_dict->AddNumberEntry(key, value, details)->ToObjectUnchecked();
   13955       }
   13956     }
   13957   }
   13958 
   13959   uint32_t result = pos;
   13960   PropertyDetails no_details = PropertyDetails(NONE, NORMAL, 0);
   13961   Heap* heap = GetHeap();
   13962   while (undefs > 0) {
   13963     if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
   13964       // Adding an entry with the key beyond smi-range requires
   13965       // allocation. Bailout.
   13966       return Smi::FromInt(-1);
   13967     }
   13968     new_dict->AddNumberEntry(pos, heap->undefined_value(), no_details)->
   13969         ToObjectUnchecked();
   13970     pos++;
   13971     undefs--;
   13972   }
   13973 
   13974   set_elements(new_dict);
   13975 
   13976   if (result <= static_cast<uint32_t>(Smi::kMaxValue)) {
   13977     return Smi::FromInt(static_cast<int>(result));
   13978   }
   13979 
   13980   ASSERT_NE(NULL, result_double);
   13981   result_double->set_value(static_cast<double>(result));
   13982   return result_double;
   13983 }
   13984 
   13985 
   13986 // Collects all defined (non-hole) and non-undefined (array) elements at
   13987 // the start of the elements array.
   13988 // If the object is in dictionary mode, it is converted to fast elements
   13989 // mode.
   13990 MaybeObject* JSObject::PrepareElementsForSort(uint32_t limit) {
   13991   Heap* heap = GetHeap();
   13992 
   13993   ASSERT(!map()->is_observed());
   13994   if (HasDictionaryElements()) {
   13995     // Convert to fast elements containing only the existing properties.
   13996     // Ordering is irrelevant, since we are going to sort anyway.
   13997     SeededNumberDictionary* dict = element_dictionary();
   13998     if (IsJSArray() || dict->requires_slow_elements() ||
   13999         dict->max_number_key() >= limit) {
   14000       return PrepareSlowElementsForSort(limit);
   14001     }
   14002     // Convert to fast elements.
   14003 
   14004     Object* obj;
   14005     MaybeObject* maybe_obj = GetElementsTransitionMap(GetIsolate(),
   14006                                                       FAST_HOLEY_ELEMENTS);
   14007     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   14008     Map* new_map = Map::cast(obj);
   14009 
   14010     PretenureFlag tenure = heap->InNewSpace(this) ? NOT_TENURED: TENURED;
   14011     Object* new_array;
   14012     { MaybeObject* maybe_new_array =
   14013           heap->AllocateFixedArray(dict->NumberOfElements(), tenure);
   14014       if (!maybe_new_array->ToObject(&new_array)) return maybe_new_array;
   14015     }
   14016     FixedArray* fast_elements = FixedArray::cast(new_array);
   14017     dict->CopyValuesTo(fast_elements);
   14018     ValidateElements();
   14019 
   14020     set_map_and_elements(new_map, fast_elements);
   14021   } else if (HasExternalArrayElements()) {
   14022     // External arrays cannot have holes or undefined elements.
   14023     return Smi::FromInt(ExternalArray::cast(elements())->length());
   14024   } else if (!HasFastDoubleElements()) {
   14025     Object* obj;
   14026     { MaybeObject* maybe_obj = EnsureWritableFastElements();
   14027       if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   14028     }
   14029   }
   14030   ASSERT(HasFastSmiOrObjectElements() || HasFastDoubleElements());
   14031 
   14032   // Collect holes at the end, undefined before that and the rest at the
   14033   // start, and return the number of non-hole, non-undefined values.
   14034 
   14035   FixedArrayBase* elements_base = FixedArrayBase::cast(this->elements());
   14036   uint32_t elements_length = static_cast<uint32_t>(elements_base->length());
   14037   if (limit > elements_length) {
   14038     limit = elements_length ;
   14039   }
   14040   if (limit == 0) {
   14041     return Smi::FromInt(0);
   14042   }
   14043 
   14044   HeapNumber* result_double = NULL;
   14045   if (limit > static_cast<uint32_t>(Smi::kMaxValue)) {
   14046     // Pessimistically allocate space for return value before
   14047     // we start mutating the array.
   14048     Object* new_double;
   14049     { MaybeObject* maybe_new_double = heap->AllocateHeapNumber(0.0);
   14050       if (!maybe_new_double->ToObject(&new_double)) return maybe_new_double;
   14051     }
   14052     result_double = HeapNumber::cast(new_double);
   14053   }
   14054 
   14055   uint32_t result = 0;
   14056   if (elements_base->map() == heap->fixed_double_array_map()) {
   14057     FixedDoubleArray* elements = FixedDoubleArray::cast(elements_base);
   14058     // Split elements into defined and the_hole, in that order.
   14059     unsigned int holes = limit;
   14060     // Assume most arrays contain no holes and undefined values, so minimize the
   14061     // number of stores of non-undefined, non-the-hole values.
   14062     for (unsigned int i = 0; i < holes; i++) {
   14063       if (elements->is_the_hole(i)) {
   14064         holes--;
   14065       } else {
   14066         continue;
   14067       }
   14068       // Position i needs to be filled.
   14069       while (holes > i) {
   14070         if (elements->is_the_hole(holes)) {
   14071           holes--;
   14072         } else {
   14073           elements->set(i, elements->get_scalar(holes));
   14074           break;
   14075         }
   14076       }
   14077     }
   14078     result = holes;
   14079     while (holes < limit) {
   14080       elements->set_the_hole(holes);
   14081       holes++;
   14082     }
   14083   } else {
   14084     FixedArray* elements = FixedArray::cast(elements_base);
   14085     DisallowHeapAllocation no_gc;
   14086 
   14087     // Split elements into defined, undefined and the_hole, in that order.  Only
   14088     // count locations for undefined and the hole, and fill them afterwards.
   14089     WriteBarrierMode write_barrier = elements->GetWriteBarrierMode(no_gc);
   14090     unsigned int undefs = limit;
   14091     unsigned int holes = limit;
   14092     // Assume most arrays contain no holes and undefined values, so minimize the
   14093     // number of stores of non-undefined, non-the-hole values.
   14094     for (unsigned int i = 0; i < undefs; i++) {
   14095       Object* current = elements->get(i);
   14096       if (current->IsTheHole()) {
   14097         holes--;
   14098         undefs--;
   14099       } else if (current->IsUndefined()) {
   14100         undefs--;
   14101       } else {
   14102         continue;
   14103       }
   14104       // Position i needs to be filled.
   14105       while (undefs > i) {
   14106         current = elements->get(undefs);
   14107         if (current->IsTheHole()) {
   14108           holes--;
   14109           undefs--;
   14110         } else if (current->IsUndefined()) {
   14111           undefs--;
   14112         } else {
   14113           elements->set(i, current, write_barrier);
   14114           break;
   14115         }
   14116       }
   14117     }
   14118     result = undefs;
   14119     while (undefs < holes) {
   14120       elements->set_undefined(undefs);
   14121       undefs++;
   14122     }
   14123     while (holes < limit) {
   14124       elements->set_the_hole(holes);
   14125       holes++;
   14126     }
   14127   }
   14128 
   14129   if (result <= static_cast<uint32_t>(Smi::kMaxValue)) {
   14130     return Smi::FromInt(static_cast<int>(result));
   14131   }
   14132   ASSERT_NE(NULL, result_double);
   14133   result_double->set_value(static_cast<double>(result));
   14134   return result_double;
   14135 }
   14136 
   14137 
   14138 ExternalArrayType JSTypedArray::type() {
   14139   switch (elements()->map()->instance_type()) {
   14140     case EXTERNAL_BYTE_ARRAY_TYPE:
   14141       return kExternalByteArray;
   14142     case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
   14143       return kExternalUnsignedByteArray;
   14144     case EXTERNAL_SHORT_ARRAY_TYPE:
   14145       return kExternalShortArray;
   14146     case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
   14147       return kExternalUnsignedShortArray;
   14148     case EXTERNAL_INT_ARRAY_TYPE:
   14149       return kExternalIntArray;
   14150     case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
   14151       return kExternalUnsignedIntArray;
   14152     case EXTERNAL_FLOAT_ARRAY_TYPE:
   14153       return kExternalFloatArray;
   14154     case EXTERNAL_DOUBLE_ARRAY_TYPE:
   14155       return kExternalDoubleArray;
   14156     case EXTERNAL_PIXEL_ARRAY_TYPE:
   14157       return kExternalPixelArray;
   14158     default:
   14159       return static_cast<ExternalArrayType>(-1);
   14160   }
   14161 }
   14162 
   14163 
   14164 size_t JSTypedArray::element_size() {
   14165   switch (elements()->map()->instance_type()) {
   14166     case EXTERNAL_BYTE_ARRAY_TYPE:
   14167       return 1;
   14168     case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
   14169       return 1;
   14170     case EXTERNAL_SHORT_ARRAY_TYPE:
   14171       return 2;
   14172     case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
   14173       return 2;
   14174     case EXTERNAL_INT_ARRAY_TYPE:
   14175       return 4;
   14176     case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
   14177       return 4;
   14178     case EXTERNAL_FLOAT_ARRAY_TYPE:
   14179       return 4;
   14180     case EXTERNAL_DOUBLE_ARRAY_TYPE:
   14181       return 8;
   14182     case EXTERNAL_PIXEL_ARRAY_TYPE:
   14183       return 1;
   14184     default:
   14185       UNREACHABLE();
   14186       return 0;
   14187   }
   14188 }
   14189 
   14190 
   14191 Object* ExternalPixelArray::SetValue(uint32_t index, Object* value) {
   14192   uint8_t clamped_value = 0;
   14193   if (index < static_cast<uint32_t>(length())) {
   14194     if (value->IsSmi()) {
   14195       int int_value = Smi::cast(value)->value();
   14196       if (int_value < 0) {
   14197         clamped_value = 0;
   14198       } else if (int_value > 255) {
   14199         clamped_value = 255;
   14200       } else {
   14201         clamped_value = static_cast<uint8_t>(int_value);
   14202       }
   14203     } else if (value->IsHeapNumber()) {
   14204       double double_value = HeapNumber::cast(value)->value();
   14205       if (!(double_value > 0)) {
   14206         // NaN and less than zero clamp to zero.
   14207         clamped_value = 0;
   14208       } else if (double_value > 255) {
   14209         // Greater than 255 clamp to 255.
   14210         clamped_value = 255;
   14211       } else {
   14212         // Other doubles are rounded to the nearest integer.
   14213         clamped_value = static_cast<uint8_t>(lrint(double_value));
   14214       }
   14215     } else {
   14216       // Clamp undefined to zero (default). All other types have been
   14217       // converted to a number type further up in the call chain.
   14218       ASSERT(value->IsUndefined());
   14219     }
   14220     set(index, clamped_value);
   14221   }
   14222   return Smi::FromInt(clamped_value);
   14223 }
   14224 
   14225 
   14226 template<typename ExternalArrayClass, typename ValueType>
   14227 static MaybeObject* ExternalArrayIntSetter(Heap* heap,
   14228                                            ExternalArrayClass* receiver,
   14229                                            uint32_t index,
   14230                                            Object* value) {
   14231   ValueType cast_value = 0;
   14232   if (index < static_cast<uint32_t>(receiver->length())) {
   14233     if (value->IsSmi()) {
   14234       int int_value = Smi::cast(value)->value();
   14235       cast_value = static_cast<ValueType>(int_value);
   14236     } else if (value->IsHeapNumber()) {
   14237       double double_value = HeapNumber::cast(value)->value();
   14238       cast_value = static_cast<ValueType>(DoubleToInt32(double_value));
   14239     } else {
   14240       // Clamp undefined to zero (default). All other types have been
   14241       // converted to a number type further up in the call chain.
   14242       ASSERT(value->IsUndefined());
   14243     }
   14244     receiver->set(index, cast_value);
   14245   }
   14246   return heap->NumberFromInt32(cast_value);
   14247 }
   14248 
   14249 
   14250 MaybeObject* ExternalByteArray::SetValue(uint32_t index, Object* value) {
   14251   return ExternalArrayIntSetter<ExternalByteArray, int8_t>
   14252       (GetHeap(), this, index, value);
   14253 }
   14254 
   14255 
   14256 MaybeObject* ExternalUnsignedByteArray::SetValue(uint32_t index,
   14257                                                  Object* value) {
   14258   return ExternalArrayIntSetter<ExternalUnsignedByteArray, uint8_t>
   14259       (GetHeap(), this, index, value);
   14260 }
   14261 
   14262 
   14263 MaybeObject* ExternalShortArray::SetValue(uint32_t index,
   14264                                           Object* value) {
   14265   return ExternalArrayIntSetter<ExternalShortArray, int16_t>
   14266       (GetHeap(), this, index, value);
   14267 }
   14268 
   14269 
   14270 MaybeObject* ExternalUnsignedShortArray::SetValue(uint32_t index,
   14271                                                   Object* value) {
   14272   return ExternalArrayIntSetter<ExternalUnsignedShortArray, uint16_t>
   14273       (GetHeap(), this, index, value);
   14274 }
   14275 
   14276 
   14277 MaybeObject* ExternalIntArray::SetValue(uint32_t index, Object* value) {
   14278   return ExternalArrayIntSetter<ExternalIntArray, int32_t>
   14279       (GetHeap(), this, index, value);
   14280 }
   14281 
   14282 
   14283 MaybeObject* ExternalUnsignedIntArray::SetValue(uint32_t index, Object* value) {
   14284   uint32_t cast_value = 0;
   14285   Heap* heap = GetHeap();
   14286   if (index < static_cast<uint32_t>(length())) {
   14287     if (value->IsSmi()) {
   14288       int int_value = Smi::cast(value)->value();
   14289       cast_value = static_cast<uint32_t>(int_value);
   14290     } else if (value->IsHeapNumber()) {
   14291       double double_value = HeapNumber::cast(value)->value();
   14292       cast_value = static_cast<uint32_t>(DoubleToUint32(double_value));
   14293     } else {
   14294       // Clamp undefined to zero (default). All other types have been
   14295       // converted to a number type further up in the call chain.
   14296       ASSERT(value->IsUndefined());
   14297     }
   14298     set(index, cast_value);
   14299   }
   14300   return heap->NumberFromUint32(cast_value);
   14301 }
   14302 
   14303 
   14304 MaybeObject* ExternalFloatArray::SetValue(uint32_t index, Object* value) {
   14305   float cast_value = static_cast<float>(OS::nan_value());
   14306   Heap* heap = GetHeap();
   14307   if (index < static_cast<uint32_t>(length())) {
   14308     if (value->IsSmi()) {
   14309       int int_value = Smi::cast(value)->value();
   14310       cast_value = static_cast<float>(int_value);
   14311     } else if (value->IsHeapNumber()) {
   14312       double double_value = HeapNumber::cast(value)->value();
   14313       cast_value = static_cast<float>(double_value);
   14314     } else {
   14315       // Clamp undefined to NaN (default). All other types have been
   14316       // converted to a number type further up in the call chain.
   14317       ASSERT(value->IsUndefined());
   14318     }
   14319     set(index, cast_value);
   14320   }
   14321   return heap->AllocateHeapNumber(cast_value);
   14322 }
   14323 
   14324 
   14325 MaybeObject* ExternalDoubleArray::SetValue(uint32_t index, Object* value) {
   14326   double double_value = OS::nan_value();
   14327   Heap* heap = GetHeap();
   14328   if (index < static_cast<uint32_t>(length())) {
   14329     if (value->IsSmi()) {
   14330       int int_value = Smi::cast(value)->value();
   14331       double_value = static_cast<double>(int_value);
   14332     } else if (value->IsHeapNumber()) {
   14333       double_value = HeapNumber::cast(value)->value();
   14334     } else {
   14335       // Clamp undefined to NaN (default). All other types have been
   14336       // converted to a number type further up in the call chain.
   14337       ASSERT(value->IsUndefined());
   14338     }
   14339     set(index, double_value);
   14340   }
   14341   return heap->AllocateHeapNumber(double_value);
   14342 }
   14343 
   14344 
   14345 PropertyCell* GlobalObject::GetPropertyCell(LookupResult* result) {
   14346   ASSERT(!HasFastProperties());
   14347   Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry());
   14348   return PropertyCell::cast(value);
   14349 }
   14350 
   14351 
   14352 // TODO(mstarzinger): Temporary wrapper until handlified.
   14353 static Handle<NameDictionary> NameDictionaryAdd(Handle<NameDictionary> dict,
   14354                                                 Handle<Name> name,
   14355                                                 Handle<Object> value,
   14356                                                 PropertyDetails details) {
   14357   CALL_HEAP_FUNCTION(dict->GetIsolate(),
   14358                      dict->Add(*name, *value, details),
   14359                      NameDictionary);
   14360 }
   14361 
   14362 
   14363 Handle<PropertyCell> GlobalObject::EnsurePropertyCell(
   14364     Handle<GlobalObject> global,
   14365     Handle<Name> name) {
   14366   ASSERT(!global->HasFastProperties());
   14367   int entry = global->property_dictionary()->FindEntry(*name);
   14368   if (entry == NameDictionary::kNotFound) {
   14369     Isolate* isolate = global->GetIsolate();
   14370     Handle<PropertyCell> cell = isolate->factory()->NewPropertyCell(
   14371         isolate->factory()->the_hole_value());
   14372     PropertyDetails details(NONE, NORMAL, 0);
   14373     details = details.AsDeleted();
   14374     Handle<NameDictionary> dictionary = NameDictionaryAdd(
   14375         handle(global->property_dictionary()), name, cell, details);
   14376     global->set_properties(*dictionary);
   14377     return cell;
   14378   } else {
   14379     Object* value = global->property_dictionary()->ValueAt(entry);
   14380     ASSERT(value->IsPropertyCell());
   14381     return handle(PropertyCell::cast(value));
   14382   }
   14383 }
   14384 
   14385 
   14386 MaybeObject* StringTable::LookupString(String* string, Object** s) {
   14387   InternalizedStringKey key(string);
   14388   return LookupKey(&key, s);
   14389 }
   14390 
   14391 
   14392 // This class is used for looking up two character strings in the string table.
   14393 // If we don't have a hit we don't want to waste much time so we unroll the
   14394 // string hash calculation loop here for speed.  Doesn't work if the two
   14395 // characters form a decimal integer, since such strings have a different hash
   14396 // algorithm.
   14397 class TwoCharHashTableKey : public HashTableKey {
   14398  public:
   14399   TwoCharHashTableKey(uint16_t c1, uint16_t c2, uint32_t seed)
   14400     : c1_(c1), c2_(c2) {
   14401     // Char 1.
   14402     uint32_t hash = seed;
   14403     hash += c1;
   14404     hash += hash << 10;
   14405     hash ^= hash >> 6;
   14406     // Char 2.
   14407     hash += c2;
   14408     hash += hash << 10;
   14409     hash ^= hash >> 6;
   14410     // GetHash.
   14411     hash += hash << 3;
   14412     hash ^= hash >> 11;
   14413     hash += hash << 15;
   14414     if ((hash & String::kHashBitMask) == 0) hash = StringHasher::kZeroHash;
   14415     hash_ = hash;
   14416 #ifdef DEBUG
   14417     // If this assert fails then we failed to reproduce the two-character
   14418     // version of the string hashing algorithm above.  One reason could be
   14419     // that we were passed two digits as characters, since the hash
   14420     // algorithm is different in that case.
   14421     uint16_t chars[2] = {c1, c2};
   14422     uint32_t check_hash = StringHasher::HashSequentialString(chars, 2, seed);
   14423     hash = (hash << String::kHashShift) | String::kIsNotArrayIndexMask;
   14424     ASSERT_EQ(static_cast<int32_t>(hash), static_cast<int32_t>(check_hash));
   14425 #endif
   14426   }
   14427 
   14428   bool IsMatch(Object* o) {
   14429     if (!o->IsString()) return false;
   14430     String* other = String::cast(o);
   14431     if (other->length() != 2) return false;
   14432     if (other->Get(0) != c1_) return false;
   14433     return other->Get(1) == c2_;
   14434   }
   14435 
   14436   uint32_t Hash() { return hash_; }
   14437   uint32_t HashForObject(Object* key) {
   14438     if (!key->IsString()) return 0;
   14439     return String::cast(key)->Hash();
   14440   }
   14441 
   14442   Object* AsObject(Heap* heap) {
   14443     // The TwoCharHashTableKey is only used for looking in the string
   14444     // table, not for adding to it.
   14445     UNREACHABLE();
   14446     return NULL;
   14447   }
   14448 
   14449  private:
   14450   uint16_t c1_;
   14451   uint16_t c2_;
   14452   uint32_t hash_;
   14453 };
   14454 
   14455 
   14456 bool StringTable::LookupStringIfExists(String* string, String** result) {
   14457   InternalizedStringKey key(string);
   14458   int entry = FindEntry(&key);
   14459   if (entry == kNotFound) {
   14460     return false;
   14461   } else {
   14462     *result = String::cast(KeyAt(entry));
   14463     ASSERT(StringShape(*result).IsInternalized());
   14464     return true;
   14465   }
   14466 }
   14467 
   14468 
   14469 bool StringTable::LookupTwoCharsStringIfExists(uint16_t c1,
   14470                                                uint16_t c2,
   14471                                                String** result) {
   14472   TwoCharHashTableKey key(c1, c2, GetHeap()->HashSeed());
   14473   int entry = FindEntry(&key);
   14474   if (entry == kNotFound) {
   14475     return false;
   14476   } else {
   14477     *result = String::cast(KeyAt(entry));
   14478     ASSERT(StringShape(*result).IsInternalized());
   14479     return true;
   14480   }
   14481 }
   14482 
   14483 
   14484 MaybeObject* StringTable::LookupUtf8String(Vector<const char> str,
   14485                                            Object** s) {
   14486   Utf8StringKey key(str, GetHeap()->HashSeed());
   14487   return LookupKey(&key, s);
   14488 }
   14489 
   14490 
   14491 MaybeObject* StringTable::LookupOneByteString(Vector<const uint8_t> str,
   14492                                               Object** s) {
   14493   OneByteStringKey key(str, GetHeap()->HashSeed());
   14494   return LookupKey(&key, s);
   14495 }
   14496 
   14497 
   14498 MaybeObject* StringTable::LookupSubStringOneByteString(
   14499     Handle<SeqOneByteString> str,
   14500     int from,
   14501     int length,
   14502     Object** s) {
   14503   SubStringOneByteStringKey key(str, from, length);
   14504   return LookupKey(&key, s);
   14505 }
   14506 
   14507 
   14508 MaybeObject* StringTable::LookupTwoByteString(Vector<const uc16> str,
   14509                                               Object** s) {
   14510   TwoByteStringKey key(str, GetHeap()->HashSeed());
   14511   return LookupKey(&key, s);
   14512 }
   14513 
   14514 
   14515 MaybeObject* StringTable::LookupKey(HashTableKey* key, Object** s) {
   14516   int entry = FindEntry(key);
   14517 
   14518   // String already in table.
   14519   if (entry != kNotFound) {
   14520     *s = KeyAt(entry);
   14521     return this;
   14522   }
   14523 
   14524   // Adding new string. Grow table if needed.
   14525   Object* obj;
   14526   { MaybeObject* maybe_obj = EnsureCapacity(1, key);
   14527     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   14528   }
   14529 
   14530   // Create string object.
   14531   Object* string;
   14532   { MaybeObject* maybe_string = key->AsObject(GetHeap());
   14533     if (!maybe_string->ToObject(&string)) return maybe_string;
   14534   }
   14535 
   14536   // If the string table grew as part of EnsureCapacity, obj is not
   14537   // the current string table and therefore we cannot use
   14538   // StringTable::cast here.
   14539   StringTable* table = reinterpret_cast<StringTable*>(obj);
   14540 
   14541   // Add the new string and return it along with the string table.
   14542   entry = table->FindInsertionEntry(key->Hash());
   14543   table->set(EntryToIndex(entry), string);
   14544   table->ElementAdded();
   14545   *s = string;
   14546   return table;
   14547 }
   14548 
   14549 
   14550 // The key for the script compilation cache is dependent on the mode flags,
   14551 // because they change the global language mode and thus binding behaviour.
   14552 // If flags change at some point, we must ensure that we do not hit the cache
   14553 // for code compiled with different settings.
   14554 static LanguageMode CurrentGlobalLanguageMode() {
   14555   return FLAG_use_strict
   14556       ? (FLAG_harmony_scoping ? EXTENDED_MODE : STRICT_MODE)
   14557       : CLASSIC_MODE;
   14558 }
   14559 
   14560 
   14561 Object* CompilationCacheTable::Lookup(String* src, Context* context) {
   14562   SharedFunctionInfo* shared = context->closure()->shared();
   14563   StringSharedKey key(src,
   14564                       shared,
   14565                       CurrentGlobalLanguageMode(),
   14566                       RelocInfo::kNoPosition);
   14567   int entry = FindEntry(&key);
   14568   if (entry == kNotFound) return GetHeap()->undefined_value();
   14569   return get(EntryToIndex(entry) + 1);
   14570 }
   14571 
   14572 
   14573 Object* CompilationCacheTable::LookupEval(String* src,
   14574                                           Context* context,
   14575                                           LanguageMode language_mode,
   14576                                           int scope_position) {
   14577   StringSharedKey key(src,
   14578                       context->closure()->shared(),
   14579                       language_mode,
   14580                       scope_position);
   14581   int entry = FindEntry(&key);
   14582   if (entry == kNotFound) return GetHeap()->undefined_value();
   14583   return get(EntryToIndex(entry) + 1);
   14584 }
   14585 
   14586 
   14587 Object* CompilationCacheTable::LookupRegExp(String* src,
   14588                                             JSRegExp::Flags flags) {
   14589   RegExpKey key(src, flags);
   14590   int entry = FindEntry(&key);
   14591   if (entry == kNotFound) return GetHeap()->undefined_value();
   14592   return get(EntryToIndex(entry) + 1);
   14593 }
   14594 
   14595 
   14596 MaybeObject* CompilationCacheTable::Put(String* src,
   14597                                         Context* context,
   14598                                         Object* value) {
   14599   SharedFunctionInfo* shared = context->closure()->shared();
   14600   StringSharedKey key(src,
   14601                       shared,
   14602                       CurrentGlobalLanguageMode(),
   14603                       RelocInfo::kNoPosition);
   14604   CompilationCacheTable* cache;
   14605   MaybeObject* maybe_cache = EnsureCapacity(1, &key);
   14606   if (!maybe_cache->To(&cache)) return maybe_cache;
   14607 
   14608   Object* k;
   14609   MaybeObject* maybe_k = key.AsObject(GetHeap());
   14610   if (!maybe_k->To(&k)) return maybe_k;
   14611 
   14612   int entry = cache->FindInsertionEntry(key.Hash());
   14613   cache->set(EntryToIndex(entry), k);
   14614   cache->set(EntryToIndex(entry) + 1, value);
   14615   cache->ElementAdded();
   14616   return cache;
   14617 }
   14618 
   14619 
   14620 MaybeObject* CompilationCacheTable::PutEval(String* src,
   14621                                             Context* context,
   14622                                             SharedFunctionInfo* value,
   14623                                             int scope_position) {
   14624   StringSharedKey key(src,
   14625                       context->closure()->shared(),
   14626                       value->language_mode(),
   14627                       scope_position);
   14628   Object* obj;
   14629   { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
   14630     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   14631   }
   14632 
   14633   CompilationCacheTable* cache =
   14634       reinterpret_cast<CompilationCacheTable*>(obj);
   14635   int entry = cache->FindInsertionEntry(key.Hash());
   14636 
   14637   Object* k;
   14638   { MaybeObject* maybe_k = key.AsObject(GetHeap());
   14639     if (!maybe_k->ToObject(&k)) return maybe_k;
   14640   }
   14641 
   14642   cache->set(EntryToIndex(entry), k);
   14643   cache->set(EntryToIndex(entry) + 1, value);
   14644   cache->ElementAdded();
   14645   return cache;
   14646 }
   14647 
   14648 
   14649 MaybeObject* CompilationCacheTable::PutRegExp(String* src,
   14650                                               JSRegExp::Flags flags,
   14651                                               FixedArray* value) {
   14652   RegExpKey key(src, flags);
   14653   Object* obj;
   14654   { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
   14655     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   14656   }
   14657 
   14658   CompilationCacheTable* cache =
   14659       reinterpret_cast<CompilationCacheTable*>(obj);
   14660   int entry = cache->FindInsertionEntry(key.Hash());
   14661   // We store the value in the key slot, and compare the search key
   14662   // to the stored value with a custon IsMatch function during lookups.
   14663   cache->set(EntryToIndex(entry), value);
   14664   cache->set(EntryToIndex(entry) + 1, value);
   14665   cache->ElementAdded();
   14666   return cache;
   14667 }
   14668 
   14669 
   14670 void CompilationCacheTable::Remove(Object* value) {
   14671   Object* the_hole_value = GetHeap()->the_hole_value();
   14672   for (int entry = 0, size = Capacity(); entry < size; entry++) {
   14673     int entry_index = EntryToIndex(entry);
   14674     int value_index = entry_index + 1;
   14675     if (get(value_index) == value) {
   14676       NoWriteBarrierSet(this, entry_index, the_hole_value);
   14677       NoWriteBarrierSet(this, value_index, the_hole_value);
   14678       ElementRemoved();
   14679     }
   14680   }
   14681   return;
   14682 }
   14683 
   14684 
   14685 // StringsKey used for HashTable where key is array of internalized strings.
   14686 class StringsKey : public HashTableKey {
   14687  public:
   14688   explicit StringsKey(FixedArray* strings) : strings_(strings) { }
   14689 
   14690   bool IsMatch(Object* strings) {
   14691     FixedArray* o = FixedArray::cast(strings);
   14692     int len = strings_->length();
   14693     if (o->length() != len) return false;
   14694     for (int i = 0; i < len; i++) {
   14695       if (o->get(i) != strings_->get(i)) return false;
   14696     }
   14697     return true;
   14698   }
   14699 
   14700   uint32_t Hash() { return HashForObject(strings_); }
   14701 
   14702   uint32_t HashForObject(Object* obj) {
   14703     FixedArray* strings = FixedArray::cast(obj);
   14704     int len = strings->length();
   14705     uint32_t hash = 0;
   14706     for (int i = 0; i < len; i++) {
   14707       hash ^= String::cast(strings->get(i))->Hash();
   14708     }
   14709     return hash;
   14710   }
   14711 
   14712   Object* AsObject(Heap* heap) { return strings_; }
   14713 
   14714  private:
   14715   FixedArray* strings_;
   14716 };
   14717 
   14718 
   14719 Object* MapCache::Lookup(FixedArray* array) {
   14720   StringsKey key(array);
   14721   int entry = FindEntry(&key);
   14722   if (entry == kNotFound) return GetHeap()->undefined_value();
   14723   return get(EntryToIndex(entry) + 1);
   14724 }
   14725 
   14726 
   14727 MaybeObject* MapCache::Put(FixedArray* array, Map* value) {
   14728   StringsKey key(array);
   14729   Object* obj;
   14730   { MaybeObject* maybe_obj = EnsureCapacity(1, &key);
   14731     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   14732   }
   14733 
   14734   MapCache* cache = reinterpret_cast<MapCache*>(obj);
   14735   int entry = cache->FindInsertionEntry(key.Hash());
   14736   cache->set(EntryToIndex(entry), array);
   14737   cache->set(EntryToIndex(entry) + 1, value);
   14738   cache->ElementAdded();
   14739   return cache;
   14740 }
   14741 
   14742 
   14743 template<typename Shape, typename Key>
   14744 MaybeObject* Dictionary<Shape, Key>::Allocate(Heap* heap,
   14745                                               int at_least_space_for,
   14746                                               PretenureFlag pretenure) {
   14747   Object* obj;
   14748   { MaybeObject* maybe_obj =
   14749       HashTable<Shape, Key>::Allocate(
   14750           heap,
   14751           at_least_space_for,
   14752           HashTable<Shape, Key>::USE_DEFAULT_MINIMUM_CAPACITY,
   14753           pretenure);
   14754     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   14755   }
   14756   // Initialize the next enumeration index.
   14757   Dictionary<Shape, Key>::cast(obj)->
   14758       SetNextEnumerationIndex(PropertyDetails::kInitialIndex);
   14759   return obj;
   14760 }
   14761 
   14762 
   14763 void NameDictionary::DoGenerateNewEnumerationIndices(
   14764     Handle<NameDictionary> dictionary) {
   14765   CALL_HEAP_FUNCTION_VOID(dictionary->GetIsolate(),
   14766                           dictionary->GenerateNewEnumerationIndices());
   14767 }
   14768 
   14769 template<typename Shape, typename Key>
   14770 MaybeObject* Dictionary<Shape, Key>::GenerateNewEnumerationIndices() {
   14771   Heap* heap = Dictionary<Shape, Key>::GetHeap();
   14772   int length = HashTable<Shape, Key>::NumberOfElements();
   14773 
   14774   // Allocate and initialize iteration order array.
   14775   Object* obj;
   14776   { MaybeObject* maybe_obj = heap->AllocateFixedArray(length);
   14777     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   14778   }
   14779   FixedArray* iteration_order = FixedArray::cast(obj);
   14780   for (int i = 0; i < length; i++) {
   14781     iteration_order->set(i, Smi::FromInt(i));
   14782   }
   14783 
   14784   // Allocate array with enumeration order.
   14785   { MaybeObject* maybe_obj = heap->AllocateFixedArray(length);
   14786     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   14787   }
   14788   FixedArray* enumeration_order = FixedArray::cast(obj);
   14789 
   14790   // Fill the enumeration order array with property details.
   14791   int capacity = HashTable<Shape, Key>::Capacity();
   14792   int pos = 0;
   14793   for (int i = 0; i < capacity; i++) {
   14794     if (Dictionary<Shape, Key>::IsKey(Dictionary<Shape, Key>::KeyAt(i))) {
   14795       int index = DetailsAt(i).dictionary_index();
   14796       enumeration_order->set(pos++, Smi::FromInt(index));
   14797     }
   14798   }
   14799 
   14800   // Sort the arrays wrt. enumeration order.
   14801   iteration_order->SortPairs(enumeration_order, enumeration_order->length());
   14802 
   14803   // Overwrite the enumeration_order with the enumeration indices.
   14804   for (int i = 0; i < length; i++) {
   14805     int index = Smi::cast(iteration_order->get(i))->value();
   14806     int enum_index = PropertyDetails::kInitialIndex + i;
   14807     enumeration_order->set(index, Smi::FromInt(enum_index));
   14808   }
   14809 
   14810   // Update the dictionary with new indices.
   14811   capacity = HashTable<Shape, Key>::Capacity();
   14812   pos = 0;
   14813   for (int i = 0; i < capacity; i++) {
   14814     if (Dictionary<Shape, Key>::IsKey(Dictionary<Shape, Key>::KeyAt(i))) {
   14815       int enum_index = Smi::cast(enumeration_order->get(pos++))->value();
   14816       PropertyDetails details = DetailsAt(i);
   14817       PropertyDetails new_details = PropertyDetails(
   14818           details.attributes(), details.type(), enum_index);
   14819       DetailsAtPut(i, new_details);
   14820     }
   14821   }
   14822 
   14823   // Set the next enumeration index.
   14824   SetNextEnumerationIndex(PropertyDetails::kInitialIndex+length);
   14825   return this;
   14826 }
   14827 
   14828 template<typename Shape, typename Key>
   14829 MaybeObject* Dictionary<Shape, Key>::EnsureCapacity(int n, Key key) {
   14830   // Check whether there are enough enumeration indices to add n elements.
   14831   if (Shape::kIsEnumerable &&
   14832       !PropertyDetails::IsValidIndex(NextEnumerationIndex() + n)) {
   14833     // If not, we generate new indices for the properties.
   14834     Object* result;
   14835     { MaybeObject* maybe_result = GenerateNewEnumerationIndices();
   14836       if (!maybe_result->ToObject(&result)) return maybe_result;
   14837     }
   14838   }
   14839   return HashTable<Shape, Key>::EnsureCapacity(n, key);
   14840 }
   14841 
   14842 
   14843 template<typename Shape, typename Key>
   14844 Object* Dictionary<Shape, Key>::DeleteProperty(int entry,
   14845                                                JSReceiver::DeleteMode mode) {
   14846   Heap* heap = Dictionary<Shape, Key>::GetHeap();
   14847   PropertyDetails details = DetailsAt(entry);
   14848   // Ignore attributes if forcing a deletion.
   14849   if (details.IsDontDelete() && mode != JSReceiver::FORCE_DELETION) {
   14850     return heap->false_value();
   14851   }
   14852   SetEntry(entry, heap->the_hole_value(), heap->the_hole_value());
   14853   HashTable<Shape, Key>::ElementRemoved();
   14854   return heap->true_value();
   14855 }
   14856 
   14857 
   14858 template<typename Shape, typename Key>
   14859 MaybeObject* Dictionary<Shape, Key>::Shrink(Key key) {
   14860   return HashTable<Shape, Key>::Shrink(key);
   14861 }
   14862 
   14863 
   14864 template<typename Shape, typename Key>
   14865 MaybeObject* Dictionary<Shape, Key>::AtPut(Key key, Object* value) {
   14866   int entry = this->FindEntry(key);
   14867 
   14868   // If the entry is present set the value;
   14869   if (entry != Dictionary<Shape, Key>::kNotFound) {
   14870     ValueAtPut(entry, value);
   14871     return this;
   14872   }
   14873 
   14874   // Check whether the dictionary should be extended.
   14875   Object* obj;
   14876   { MaybeObject* maybe_obj = EnsureCapacity(1, key);
   14877     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   14878   }
   14879 
   14880   Object* k;
   14881   { MaybeObject* maybe_k = Shape::AsObject(this->GetHeap(), key);
   14882     if (!maybe_k->ToObject(&k)) return maybe_k;
   14883   }
   14884   PropertyDetails details = PropertyDetails(NONE, NORMAL, 0);
   14885 
   14886   return Dictionary<Shape, Key>::cast(obj)->AddEntry(key, value, details,
   14887       Dictionary<Shape, Key>::Hash(key));
   14888 }
   14889 
   14890 
   14891 template<typename Shape, typename Key>
   14892 MaybeObject* Dictionary<Shape, Key>::Add(Key key,
   14893                                          Object* value,
   14894                                          PropertyDetails details) {
   14895   // Valdate key is absent.
   14896   SLOW_ASSERT((this->FindEntry(key) == Dictionary<Shape, Key>::kNotFound));
   14897   // Check whether the dictionary should be extended.
   14898   Object* obj;
   14899   { MaybeObject* maybe_obj = EnsureCapacity(1, key);
   14900     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   14901   }
   14902 
   14903   return Dictionary<Shape, Key>::cast(obj)->AddEntry(key, value, details,
   14904       Dictionary<Shape, Key>::Hash(key));
   14905 }
   14906 
   14907 
   14908 // Add a key, value pair to the dictionary.
   14909 template<typename Shape, typename Key>
   14910 MaybeObject* Dictionary<Shape, Key>::AddEntry(Key key,
   14911                                               Object* value,
   14912                                               PropertyDetails details,
   14913                                               uint32_t hash) {
   14914   // Compute the key object.
   14915   Object* k;
   14916   { MaybeObject* maybe_k = Shape::AsObject(this->GetHeap(), key);
   14917     if (!maybe_k->ToObject(&k)) return maybe_k;
   14918   }
   14919 
   14920   uint32_t entry = Dictionary<Shape, Key>::FindInsertionEntry(hash);
   14921   // Insert element at empty or deleted entry
   14922   if (!details.IsDeleted() &&
   14923       details.dictionary_index() == 0 &&
   14924       Shape::kIsEnumerable) {
   14925     // Assign an enumeration index to the property and update
   14926     // SetNextEnumerationIndex.
   14927     int index = NextEnumerationIndex();
   14928     details = PropertyDetails(details.attributes(), details.type(), index);
   14929     SetNextEnumerationIndex(index + 1);
   14930   }
   14931   SetEntry(entry, k, value, details);
   14932   ASSERT((Dictionary<Shape, Key>::KeyAt(entry)->IsNumber() ||
   14933           Dictionary<Shape, Key>::KeyAt(entry)->IsName()));
   14934   HashTable<Shape, Key>::ElementAdded();
   14935   return this;
   14936 }
   14937 
   14938 
   14939 void SeededNumberDictionary::UpdateMaxNumberKey(uint32_t key) {
   14940   // If the dictionary requires slow elements an element has already
   14941   // been added at a high index.
   14942   if (requires_slow_elements()) return;
   14943   // Check if this index is high enough that we should require slow
   14944   // elements.
   14945   if (key > kRequiresSlowElementsLimit) {
   14946     set_requires_slow_elements();
   14947     return;
   14948   }
   14949   // Update max key value.
   14950   Object* max_index_object = get(kMaxNumberKeyIndex);
   14951   if (!max_index_object->IsSmi() || max_number_key() < key) {
   14952     FixedArray::set(kMaxNumberKeyIndex,
   14953                     Smi::FromInt(key << kRequiresSlowElementsTagSize));
   14954   }
   14955 }
   14956 
   14957 
   14958 MaybeObject* SeededNumberDictionary::AddNumberEntry(uint32_t key,
   14959                                                     Object* value,
   14960                                                     PropertyDetails details) {
   14961   UpdateMaxNumberKey(key);
   14962   SLOW_ASSERT(this->FindEntry(key) == kNotFound);
   14963   return Add(key, value, details);
   14964 }
   14965 
   14966 
   14967 MaybeObject* UnseededNumberDictionary::AddNumberEntry(uint32_t key,
   14968                                                       Object* value) {
   14969   SLOW_ASSERT(this->FindEntry(key) == kNotFound);
   14970   return Add(key, value, PropertyDetails(NONE, NORMAL, 0));
   14971 }
   14972 
   14973 
   14974 MaybeObject* SeededNumberDictionary::AtNumberPut(uint32_t key, Object* value) {
   14975   UpdateMaxNumberKey(key);
   14976   return AtPut(key, value);
   14977 }
   14978 
   14979 
   14980 MaybeObject* UnseededNumberDictionary::AtNumberPut(uint32_t key,
   14981                                                    Object* value) {
   14982   return AtPut(key, value);
   14983 }
   14984 
   14985 
   14986 Handle<SeededNumberDictionary> SeededNumberDictionary::Set(
   14987     Handle<SeededNumberDictionary> dictionary,
   14988     uint32_t index,
   14989     Handle<Object> value,
   14990     PropertyDetails details) {
   14991   CALL_HEAP_FUNCTION(dictionary->GetIsolate(),
   14992                      dictionary->Set(index, *value, details),
   14993                      SeededNumberDictionary);
   14994 }
   14995 
   14996 
   14997 Handle<UnseededNumberDictionary> UnseededNumberDictionary::Set(
   14998     Handle<UnseededNumberDictionary> dictionary,
   14999     uint32_t index,
   15000     Handle<Object> value) {
   15001   CALL_HEAP_FUNCTION(dictionary->GetIsolate(),
   15002                      dictionary->Set(index, *value),
   15003                      UnseededNumberDictionary);
   15004 }
   15005 
   15006 
   15007 MaybeObject* SeededNumberDictionary::Set(uint32_t key,
   15008                                          Object* value,
   15009                                          PropertyDetails details) {
   15010   int entry = FindEntry(key);
   15011   if (entry == kNotFound) return AddNumberEntry(key, value, details);
   15012   // Preserve enumeration index.
   15013   details = PropertyDetails(details.attributes(),
   15014                             details.type(),
   15015                             DetailsAt(entry).dictionary_index());
   15016   MaybeObject* maybe_object_key =
   15017       SeededNumberDictionaryShape::AsObject(GetHeap(), key);
   15018   Object* object_key;
   15019   if (!maybe_object_key->ToObject(&object_key)) return maybe_object_key;
   15020   SetEntry(entry, object_key, value, details);
   15021   return this;
   15022 }
   15023 
   15024 
   15025 MaybeObject* UnseededNumberDictionary::Set(uint32_t key,
   15026                                            Object* value) {
   15027   int entry = FindEntry(key);
   15028   if (entry == kNotFound) return AddNumberEntry(key, value);
   15029   MaybeObject* maybe_object_key =
   15030       UnseededNumberDictionaryShape::AsObject(GetHeap(), key);
   15031   Object* object_key;
   15032   if (!maybe_object_key->ToObject(&object_key)) return maybe_object_key;
   15033   SetEntry(entry, object_key, value);
   15034   return this;
   15035 }
   15036 
   15037 
   15038 
   15039 template<typename Shape, typename Key>
   15040 int Dictionary<Shape, Key>::NumberOfElementsFilterAttributes(
   15041     PropertyAttributes filter) {
   15042   int capacity = HashTable<Shape, Key>::Capacity();
   15043   int result = 0;
   15044   for (int i = 0; i < capacity; i++) {
   15045     Object* k = HashTable<Shape, Key>::KeyAt(i);
   15046     if (HashTable<Shape, Key>::IsKey(k) &&
   15047         ((filter & SYMBOLIC) == 0 || !k->IsSymbol())) {
   15048       PropertyDetails details = DetailsAt(i);
   15049       if (details.IsDeleted()) continue;
   15050       PropertyAttributes attr = details.attributes();
   15051       if ((attr & filter) == 0) result++;
   15052     }
   15053   }
   15054   return result;
   15055 }
   15056 
   15057 
   15058 template<typename Shape, typename Key>
   15059 int Dictionary<Shape, Key>::NumberOfEnumElements() {
   15060   return NumberOfElementsFilterAttributes(
   15061       static_cast<PropertyAttributes>(DONT_ENUM));
   15062 }
   15063 
   15064 
   15065 template<typename Shape, typename Key>
   15066 void Dictionary<Shape, Key>::CopyKeysTo(
   15067     FixedArray* storage,
   15068     PropertyAttributes filter,
   15069     typename Dictionary<Shape, Key>::SortMode sort_mode) {
   15070   ASSERT(storage->length() >= NumberOfEnumElements());
   15071   int capacity = HashTable<Shape, Key>::Capacity();
   15072   int index = 0;
   15073   for (int i = 0; i < capacity; i++) {
   15074      Object* k = HashTable<Shape, Key>::KeyAt(i);
   15075      if (HashTable<Shape, Key>::IsKey(k)) {
   15076        PropertyDetails details = DetailsAt(i);
   15077        if (details.IsDeleted()) continue;
   15078        PropertyAttributes attr = details.attributes();
   15079        if ((attr & filter) == 0) storage->set(index++, k);
   15080      }
   15081   }
   15082   if (sort_mode == Dictionary<Shape, Key>::SORTED) {
   15083     storage->SortPairs(storage, index);
   15084   }
   15085   ASSERT(storage->length() >= index);
   15086 }
   15087 
   15088 
   15089 FixedArray* NameDictionary::CopyEnumKeysTo(FixedArray* storage) {
   15090   int length = storage->length();
   15091   ASSERT(length >= NumberOfEnumElements());
   15092   Heap* heap = GetHeap();
   15093   Object* undefined_value = heap->undefined_value();
   15094   int capacity = Capacity();
   15095   int properties = 0;
   15096 
   15097   // Fill in the enumeration array by assigning enumerable keys at their
   15098   // enumeration index. This will leave holes in the array if there are keys
   15099   // that are deleted or not enumerable.
   15100   for (int i = 0; i < capacity; i++) {
   15101      Object* k = KeyAt(i);
   15102      if (IsKey(k) && !k->IsSymbol()) {
   15103        PropertyDetails details = DetailsAt(i);
   15104        if (details.IsDeleted() || details.IsDontEnum()) continue;
   15105        properties++;
   15106        storage->set(details.dictionary_index() - 1, k);
   15107        if (properties == length) break;
   15108      }
   15109   }
   15110 
   15111   // There are holes in the enumeration array if less properties were assigned
   15112   // than the length of the array. If so, crunch all the existing properties
   15113   // together by shifting them to the left (maintaining the enumeration order),
   15114   // and trimming of the right side of the array.
   15115   if (properties < length) {
   15116     if (properties == 0) return heap->empty_fixed_array();
   15117     properties = 0;
   15118     for (int i = 0; i < length; ++i) {
   15119       Object* value = storage->get(i);
   15120       if (value != undefined_value) {
   15121         storage->set(properties, value);
   15122         ++properties;
   15123       }
   15124     }
   15125     RightTrimFixedArray<FROM_MUTATOR>(heap, storage, length - properties);
   15126   }
   15127   return storage;
   15128 }
   15129 
   15130 
   15131 template<typename Shape, typename Key>
   15132 void Dictionary<Shape, Key>::CopyKeysTo(
   15133     FixedArray* storage,
   15134     int index,
   15135     PropertyAttributes filter,
   15136     typename Dictionary<Shape, Key>::SortMode sort_mode) {
   15137   ASSERT(storage->length() >= NumberOfElementsFilterAttributes(
   15138       static_cast<PropertyAttributes>(NONE)));
   15139   int capacity = HashTable<Shape, Key>::Capacity();
   15140   for (int i = 0; i < capacity; i++) {
   15141     Object* k = HashTable<Shape, Key>::KeyAt(i);
   15142     if (HashTable<Shape, Key>::IsKey(k)) {
   15143       PropertyDetails details = DetailsAt(i);
   15144       if (details.IsDeleted()) continue;
   15145       PropertyAttributes attr = details.attributes();
   15146       if ((attr & filter) == 0) storage->set(index++, k);
   15147     }
   15148   }
   15149   if (sort_mode == Dictionary<Shape, Key>::SORTED) {
   15150     storage->SortPairs(storage, index);
   15151   }
   15152   ASSERT(storage->length() >= index);
   15153 }
   15154 
   15155 
   15156 // Backwards lookup (slow).
   15157 template<typename Shape, typename Key>
   15158 Object* Dictionary<Shape, Key>::SlowReverseLookup(Object* value) {
   15159   int capacity = HashTable<Shape, Key>::Capacity();
   15160   for (int i = 0; i < capacity; i++) {
   15161     Object* k =  HashTable<Shape, Key>::KeyAt(i);
   15162     if (Dictionary<Shape, Key>::IsKey(k)) {
   15163       Object* e = ValueAt(i);
   15164       if (e->IsPropertyCell()) {
   15165         e = PropertyCell::cast(e)->value();
   15166       }
   15167       if (e == value) return k;
   15168     }
   15169   }
   15170   Heap* heap = Dictionary<Shape, Key>::GetHeap();
   15171   return heap->undefined_value();
   15172 }
   15173 
   15174 
   15175 MaybeObject* NameDictionary::TransformPropertiesToFastFor(
   15176     JSObject* obj, int unused_property_fields) {
   15177   // Make sure we preserve dictionary representation if there are too many
   15178   // descriptors.
   15179   int number_of_elements = NumberOfElements();
   15180   if (number_of_elements > DescriptorArray::kMaxNumberOfDescriptors) return obj;
   15181 
   15182   if (number_of_elements != NextEnumerationIndex()) {
   15183     MaybeObject* maybe_result = GenerateNewEnumerationIndices();
   15184     if (maybe_result->IsFailure()) return maybe_result;
   15185   }
   15186 
   15187   int instance_descriptor_length = 0;
   15188   int number_of_fields = 0;
   15189 
   15190   Heap* heap = GetHeap();
   15191 
   15192   // Compute the length of the instance descriptor.
   15193   int capacity = Capacity();
   15194   for (int i = 0; i < capacity; i++) {
   15195     Object* k = KeyAt(i);
   15196     if (IsKey(k)) {
   15197       Object* value = ValueAt(i);
   15198       PropertyType type = DetailsAt(i).type();
   15199       ASSERT(type != FIELD);
   15200       instance_descriptor_length++;
   15201       if (type == NORMAL && !value->IsJSFunction()) {
   15202         number_of_fields += 1;
   15203       }
   15204     }
   15205   }
   15206 
   15207   int inobject_props = obj->map()->inobject_properties();
   15208 
   15209   // Allocate new map.
   15210   Map* new_map;
   15211   MaybeObject* maybe_new_map = obj->map()->CopyDropDescriptors();
   15212   if (!maybe_new_map->To(&new_map)) return maybe_new_map;
   15213   new_map->set_dictionary_map(false);
   15214 
   15215   if (instance_descriptor_length == 0) {
   15216     ASSERT_LE(unused_property_fields, inobject_props);
   15217     // Transform the object.
   15218     new_map->set_unused_property_fields(inobject_props);
   15219     obj->set_map(new_map);
   15220     obj->set_properties(heap->empty_fixed_array());
   15221     // Check that it really works.
   15222     ASSERT(obj->HasFastProperties());
   15223     return obj;
   15224   }
   15225 
   15226   // Allocate the instance descriptor.
   15227   DescriptorArray* descriptors;
   15228   MaybeObject* maybe_descriptors =
   15229       DescriptorArray::Allocate(instance_descriptor_length);
   15230   if (!maybe_descriptors->To(&descriptors)) {
   15231     return maybe_descriptors;
   15232   }
   15233 
   15234   DescriptorArray::WhitenessWitness witness(descriptors);
   15235 
   15236   int number_of_allocated_fields =
   15237       number_of_fields + unused_property_fields - inobject_props;
   15238   if (number_of_allocated_fields < 0) {
   15239     // There is enough inobject space for all fields (including unused).
   15240     number_of_allocated_fields = 0;
   15241     unused_property_fields = inobject_props - number_of_fields;
   15242   }
   15243 
   15244   // Allocate the fixed array for the fields.
   15245   FixedArray* fields;
   15246   MaybeObject* maybe_fields =
   15247       heap->AllocateFixedArray(number_of_allocated_fields);
   15248   if (!maybe_fields->To(&fields)) return maybe_fields;
   15249 
   15250   // Fill in the instance descriptor and the fields.
   15251   int current_offset = 0;
   15252   for (int i = 0; i < capacity; i++) {
   15253     Object* k = KeyAt(i);
   15254     if (IsKey(k)) {
   15255       Object* value = ValueAt(i);
   15256       Name* key;
   15257       if (k->IsSymbol()) {
   15258         key = Symbol::cast(k);
   15259       } else {
   15260         // Ensure the key is a unique name before writing into the
   15261         // instance descriptor.
   15262         MaybeObject* maybe_key = heap->InternalizeString(String::cast(k));
   15263         if (!maybe_key->To(&key)) return maybe_key;
   15264       }
   15265 
   15266       PropertyDetails details = DetailsAt(i);
   15267       int enumeration_index = details.dictionary_index();
   15268       PropertyType type = details.type();
   15269 
   15270       if (value->IsJSFunction()) {
   15271         ConstantDescriptor d(key, value, details.attributes());
   15272         descriptors->Set(enumeration_index - 1, &d, witness);
   15273       } else if (type == NORMAL) {
   15274         if (current_offset < inobject_props) {
   15275           obj->InObjectPropertyAtPut(current_offset,
   15276                                      value,
   15277                                      UPDATE_WRITE_BARRIER);
   15278         } else {
   15279           int offset = current_offset - inobject_props;
   15280           fields->set(offset, value);
   15281         }
   15282         FieldDescriptor d(key,
   15283                           current_offset++,
   15284                           details.attributes(),
   15285                           // TODO(verwaest): value->OptimalRepresentation();
   15286                           Representation::Tagged());
   15287         descriptors->Set(enumeration_index - 1, &d, witness);
   15288       } else if (type == CALLBACKS) {
   15289         CallbacksDescriptor d(key,
   15290                               value,
   15291                               details.attributes());
   15292         descriptors->Set(enumeration_index - 1, &d, witness);
   15293       } else {
   15294         UNREACHABLE();
   15295       }
   15296     }
   15297   }
   15298   ASSERT(current_offset == number_of_fields);
   15299 
   15300   descriptors->Sort();
   15301 
   15302   new_map->InitializeDescriptors(descriptors);
   15303   new_map->set_unused_property_fields(unused_property_fields);
   15304 
   15305   // Transform the object.
   15306   obj->set_map(new_map);
   15307 
   15308   obj->set_properties(fields);
   15309   ASSERT(obj->IsJSObject());
   15310 
   15311   // Check that it really works.
   15312   ASSERT(obj->HasFastProperties());
   15313 
   15314   return obj;
   15315 }
   15316 
   15317 
   15318 bool ObjectHashSet::Contains(Object* key) {
   15319   ASSERT(IsKey(key));
   15320 
   15321   // If the object does not have an identity hash, it was never used as a key.
   15322   { MaybeObject* maybe_hash = key->GetHash(OMIT_CREATION);
   15323     if (maybe_hash->ToObjectUnchecked()->IsUndefined()) return false;
   15324   }
   15325   return (FindEntry(key) != kNotFound);
   15326 }
   15327 
   15328 
   15329 MaybeObject* ObjectHashSet::Add(Object* key) {
   15330   ASSERT(IsKey(key));
   15331 
   15332   // Make sure the key object has an identity hash code.
   15333   int hash;
   15334   { MaybeObject* maybe_hash = key->GetHash(ALLOW_CREATION);
   15335     if (maybe_hash->IsFailure()) return maybe_hash;
   15336     hash = Smi::cast(maybe_hash->ToObjectUnchecked())->value();
   15337   }
   15338   int entry = FindEntry(key);
   15339 
   15340   // Check whether key is already present.
   15341   if (entry != kNotFound) return this;
   15342 
   15343   // Check whether the hash set should be extended and add entry.
   15344   Object* obj;
   15345   { MaybeObject* maybe_obj = EnsureCapacity(1, key);
   15346     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   15347   }
   15348   ObjectHashSet* table = ObjectHashSet::cast(obj);
   15349   entry = table->FindInsertionEntry(hash);
   15350   table->set(EntryToIndex(entry), key);
   15351   table->ElementAdded();
   15352   return table;
   15353 }
   15354 
   15355 
   15356 MaybeObject* ObjectHashSet::Remove(Object* key) {
   15357   ASSERT(IsKey(key));
   15358 
   15359   // If the object does not have an identity hash, it was never used as a key.
   15360   { MaybeObject* maybe_hash = key->GetHash(OMIT_CREATION);
   15361     if (maybe_hash->ToObjectUnchecked()->IsUndefined()) return this;
   15362   }
   15363   int entry = FindEntry(key);
   15364 
   15365   // Check whether key is actually present.
   15366   if (entry == kNotFound) return this;
   15367 
   15368   // Remove entry and try to shrink this hash set.
   15369   set_the_hole(EntryToIndex(entry));
   15370   ElementRemoved();
   15371   return Shrink(key);
   15372 }
   15373 
   15374 
   15375 Object* ObjectHashTable::Lookup(Object* key) {
   15376   ASSERT(IsKey(key));
   15377 
   15378   // If the object does not have an identity hash, it was never used as a key.
   15379   { MaybeObject* maybe_hash = key->GetHash(OMIT_CREATION);
   15380     if (maybe_hash->ToObjectUnchecked()->IsUndefined()) {
   15381       return GetHeap()->the_hole_value();
   15382     }
   15383   }
   15384   int entry = FindEntry(key);
   15385   if (entry == kNotFound) return GetHeap()->the_hole_value();
   15386   return get(EntryToIndex(entry) + 1);
   15387 }
   15388 
   15389 
   15390 MaybeObject* ObjectHashTable::Put(Object* key, Object* value) {
   15391   ASSERT(IsKey(key));
   15392 
   15393   // Make sure the key object has an identity hash code.
   15394   int hash;
   15395   { MaybeObject* maybe_hash = key->GetHash(ALLOW_CREATION);
   15396     if (maybe_hash->IsFailure()) return maybe_hash;
   15397     hash = Smi::cast(maybe_hash->ToObjectUnchecked())->value();
   15398   }
   15399   int entry = FindEntry(key);
   15400 
   15401   // Check whether to perform removal operation.
   15402   if (value->IsTheHole()) {
   15403     if (entry == kNotFound) return this;
   15404     RemoveEntry(entry);
   15405     return Shrink(key);
   15406   }
   15407 
   15408   // Key is already in table, just overwrite value.
   15409   if (entry != kNotFound) {
   15410     set(EntryToIndex(entry) + 1, value);
   15411     return this;
   15412   }
   15413 
   15414   // Check whether the hash table should be extended.
   15415   Object* obj;
   15416   { MaybeObject* maybe_obj = EnsureCapacity(1, key);
   15417     if (!maybe_obj->ToObject(&obj)) return maybe_obj;
   15418   }
   15419   ObjectHashTable* table = ObjectHashTable::cast(obj);
   15420   table->AddEntry(table->FindInsertionEntry(hash), key, value);
   15421   return table;
   15422 }
   15423 
   15424 
   15425 void ObjectHashTable::AddEntry(int entry, Object* key, Object* value) {
   15426   set(EntryToIndex(entry), key);
   15427   set(EntryToIndex(entry) + 1, value);
   15428   ElementAdded();
   15429 }
   15430 
   15431 
   15432 void ObjectHashTable::RemoveEntry(int entry) {
   15433   set_the_hole(EntryToIndex(entry));
   15434   set_the_hole(EntryToIndex(entry) + 1);
   15435   ElementRemoved();
   15436 }
   15437 
   15438 
   15439 DeclaredAccessorDescriptorIterator::DeclaredAccessorDescriptorIterator(
   15440     DeclaredAccessorDescriptor* descriptor)
   15441     : array_(descriptor->serialized_data()->GetDataStartAddress()),
   15442       length_(descriptor->serialized_data()->length()),
   15443       offset_(0) {
   15444 }
   15445 
   15446 
   15447 const DeclaredAccessorDescriptorData*
   15448   DeclaredAccessorDescriptorIterator::Next() {
   15449   ASSERT(offset_ < length_);
   15450   uint8_t* ptr = &array_[offset_];
   15451   ASSERT(reinterpret_cast<uintptr_t>(ptr) % sizeof(uintptr_t) == 0);
   15452   const DeclaredAccessorDescriptorData* data =
   15453       reinterpret_cast<const DeclaredAccessorDescriptorData*>(ptr);
   15454   offset_ += sizeof(*data);
   15455   ASSERT(offset_ <= length_);
   15456   return data;
   15457 }
   15458 
   15459 
   15460 Handle<DeclaredAccessorDescriptor> DeclaredAccessorDescriptor::Create(
   15461     Isolate* isolate,
   15462     const DeclaredAccessorDescriptorData& descriptor,
   15463     Handle<DeclaredAccessorDescriptor> previous) {
   15464   int previous_length =
   15465       previous.is_null() ? 0 : previous->serialized_data()->length();
   15466   int length = sizeof(descriptor) + previous_length;
   15467   Handle<ByteArray> serialized_descriptor =
   15468       isolate->factory()->NewByteArray(length);
   15469   Handle<DeclaredAccessorDescriptor> value =
   15470       isolate->factory()->NewDeclaredAccessorDescriptor();
   15471   value->set_serialized_data(*serialized_descriptor);
   15472   // Copy in the data.
   15473   {
   15474     DisallowHeapAllocation no_allocation;
   15475     uint8_t* array = serialized_descriptor->GetDataStartAddress();
   15476     if (previous_length != 0) {
   15477       uint8_t* previous_array =
   15478           previous->serialized_data()->GetDataStartAddress();
   15479       OS::MemCopy(array, previous_array, previous_length);
   15480       array += previous_length;
   15481     }
   15482     ASSERT(reinterpret_cast<uintptr_t>(array) % sizeof(uintptr_t) == 0);
   15483     DeclaredAccessorDescriptorData* data =
   15484         reinterpret_cast<DeclaredAccessorDescriptorData*>(array);
   15485     *data = descriptor;
   15486   }
   15487   return value;
   15488 }
   15489 
   15490 
   15491 #ifdef ENABLE_DEBUGGER_SUPPORT
   15492 // Check if there is a break point at this code position.
   15493 bool DebugInfo::HasBreakPoint(int code_position) {
   15494   // Get the break point info object for this code position.
   15495   Object* break_point_info = GetBreakPointInfo(code_position);
   15496 
   15497   // If there is no break point info object or no break points in the break
   15498   // point info object there is no break point at this code position.
   15499   if (break_point_info->IsUndefined()) return false;
   15500   return BreakPointInfo::cast(break_point_info)->GetBreakPointCount() > 0;
   15501 }
   15502 
   15503 
   15504 // Get the break point info object for this code position.
   15505 Object* DebugInfo::GetBreakPointInfo(int code_position) {
   15506   // Find the index of the break point info object for this code position.
   15507   int index = GetBreakPointInfoIndex(code_position);
   15508 
   15509   // Return the break point info object if any.
   15510   if (index == kNoBreakPointInfo) return GetHeap()->undefined_value();
   15511   return BreakPointInfo::cast(break_points()->get(index));
   15512 }
   15513 
   15514 
   15515 // Clear a break point at the specified code position.
   15516 void DebugInfo::ClearBreakPoint(Handle<DebugInfo> debug_info,
   15517                                 int code_position,
   15518                                 Handle<Object> break_point_object) {
   15519   Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_position),
   15520                                   Isolate::Current());
   15521   if (break_point_info->IsUndefined()) return;
   15522   BreakPointInfo::ClearBreakPoint(
   15523       Handle<BreakPointInfo>::cast(break_point_info),
   15524       break_point_object);
   15525 }
   15526 
   15527 
   15528 void DebugInfo::SetBreakPoint(Handle<DebugInfo> debug_info,
   15529                               int code_position,
   15530                               int source_position,
   15531                               int statement_position,
   15532                               Handle<Object> break_point_object) {
   15533   Isolate* isolate = Isolate::Current();
   15534   Handle<Object> break_point_info(debug_info->GetBreakPointInfo(code_position),
   15535                                   isolate);
   15536   if (!break_point_info->IsUndefined()) {
   15537     BreakPointInfo::SetBreakPoint(
   15538         Handle<BreakPointInfo>::cast(break_point_info),
   15539         break_point_object);
   15540     return;
   15541   }
   15542 
   15543   // Adding a new break point for a code position which did not have any
   15544   // break points before. Try to find a free slot.
   15545   int index = kNoBreakPointInfo;
   15546   for (int i = 0; i < debug_info->break_points()->length(); i++) {
   15547     if (debug_info->break_points()->get(i)->IsUndefined()) {
   15548       index = i;
   15549       break;
   15550     }
   15551   }
   15552   if (index == kNoBreakPointInfo) {
   15553     // No free slot - extend break point info array.
   15554     Handle<FixedArray> old_break_points =
   15555         Handle<FixedArray>(FixedArray::cast(debug_info->break_points()));
   15556     Handle<FixedArray> new_break_points =
   15557         isolate->factory()->NewFixedArray(
   15558             old_break_points->length() +
   15559             Debug::kEstimatedNofBreakPointsInFunction);
   15560 
   15561     debug_info->set_break_points(*new_break_points);
   15562     for (int i = 0; i < old_break_points->length(); i++) {
   15563       new_break_points->set(i, old_break_points->get(i));
   15564     }
   15565     index = old_break_points->length();
   15566   }
   15567   ASSERT(index != kNoBreakPointInfo);
   15568 
   15569   // Allocate new BreakPointInfo object and set the break point.
   15570   Handle<BreakPointInfo> new_break_point_info = Handle<BreakPointInfo>::cast(
   15571       isolate->factory()->NewStruct(BREAK_POINT_INFO_TYPE));
   15572   new_break_point_info->set_code_position(Smi::FromInt(code_position));
   15573   new_break_point_info->set_source_position(Smi::FromInt(source_position));
   15574   new_break_point_info->
   15575       set_statement_position(Smi::FromInt(statement_position));
   15576   new_break_point_info->set_break_point_objects(
   15577       isolate->heap()->undefined_value());
   15578   BreakPointInfo::SetBreakPoint(new_break_point_info, break_point_object);
   15579   debug_info->break_points()->set(index, *new_break_point_info);
   15580 }
   15581 
   15582 
   15583 // Get the break point objects for a code position.
   15584 Object* DebugInfo::GetBreakPointObjects(int code_position) {
   15585   Object* break_point_info = GetBreakPointInfo(code_position);
   15586   if (break_point_info->IsUndefined()) {
   15587     return GetHeap()->undefined_value();
   15588   }
   15589   return BreakPointInfo::cast(break_point_info)->break_point_objects();
   15590 }
   15591 
   15592 
   15593 // Get the total number of break points.
   15594 int DebugInfo::GetBreakPointCount() {
   15595   if (break_points()->IsUndefined()) return 0;
   15596   int count = 0;
   15597   for (int i = 0; i < break_points()->length(); i++) {
   15598     if (!break_points()->get(i)->IsUndefined()) {
   15599       BreakPointInfo* break_point_info =
   15600           BreakPointInfo::cast(break_points()->get(i));
   15601       count += break_point_info->GetBreakPointCount();
   15602     }
   15603   }
   15604   return count;
   15605 }
   15606 
   15607 
   15608 Object* DebugInfo::FindBreakPointInfo(Handle<DebugInfo> debug_info,
   15609                                       Handle<Object> break_point_object) {
   15610   Heap* heap = debug_info->GetHeap();
   15611   if (debug_info->break_points()->IsUndefined()) return heap->undefined_value();
   15612   for (int i = 0; i < debug_info->break_points()->length(); i++) {
   15613     if (!debug_info->break_points()->get(i)->IsUndefined()) {
   15614       Handle<BreakPointInfo> break_point_info =
   15615           Handle<BreakPointInfo>(BreakPointInfo::cast(
   15616               debug_info->break_points()->get(i)));
   15617       if (BreakPointInfo::HasBreakPointObject(break_point_info,
   15618                                               break_point_object)) {
   15619         return *break_point_info;
   15620       }
   15621     }
   15622   }
   15623   return heap->undefined_value();
   15624 }
   15625 
   15626 
   15627 // Find the index of the break point info object for the specified code
   15628 // position.
   15629 int DebugInfo::GetBreakPointInfoIndex(int code_position) {
   15630   if (break_points()->IsUndefined()) return kNoBreakPointInfo;
   15631   for (int i = 0; i < break_points()->length(); i++) {
   15632     if (!break_points()->get(i)->IsUndefined()) {
   15633       BreakPointInfo* break_point_info =
   15634           BreakPointInfo::cast(break_points()->get(i));
   15635       if (break_point_info->code_position()->value() == code_position) {
   15636         return i;
   15637       }
   15638     }
   15639   }
   15640   return kNoBreakPointInfo;
   15641 }
   15642 
   15643 
   15644 // Remove the specified break point object.
   15645 void BreakPointInfo::ClearBreakPoint(Handle<BreakPointInfo> break_point_info,
   15646                                      Handle<Object> break_point_object) {
   15647   Isolate* isolate = Isolate::Current();
   15648   // If there are no break points just ignore.
   15649   if (break_point_info->break_point_objects()->IsUndefined()) return;
   15650   // If there is a single break point clear it if it is the same.
   15651   if (!break_point_info->break_point_objects()->IsFixedArray()) {
   15652     if (break_point_info->break_point_objects() == *break_point_object) {
   15653       break_point_info->set_break_point_objects(
   15654           isolate->heap()->undefined_value());
   15655     }
   15656     return;
   15657   }
   15658   // If there are multiple break points shrink the array
   15659   ASSERT(break_point_info->break_point_objects()->IsFixedArray());
   15660   Handle<FixedArray> old_array =
   15661       Handle<FixedArray>(
   15662           FixedArray::cast(break_point_info->break_point_objects()));
   15663   Handle<FixedArray> new_array =
   15664       isolate->factory()->NewFixedArray(old_array->length() - 1);
   15665   int found_count = 0;
   15666   for (int i = 0; i < old_array->length(); i++) {
   15667     if (old_array->get(i) == *break_point_object) {
   15668       ASSERT(found_count == 0);
   15669       found_count++;
   15670     } else {
   15671       new_array->set(i - found_count, old_array->get(i));
   15672     }
   15673   }
   15674   // If the break point was found in the list change it.
   15675   if (found_count > 0) break_point_info->set_break_point_objects(*new_array);
   15676 }
   15677 
   15678 
   15679 // Add the specified break point object.
   15680 void BreakPointInfo::SetBreakPoint(Handle<BreakPointInfo> break_point_info,
   15681                                    Handle<Object> break_point_object) {
   15682   Isolate* isolate = break_point_info->GetIsolate();
   15683 
   15684   // If there was no break point objects before just set it.
   15685   if (break_point_info->break_point_objects()->IsUndefined()) {
   15686     break_point_info->set_break_point_objects(*break_point_object);
   15687     return;
   15688   }
   15689   // If the break point object is the same as before just ignore.
   15690   if (break_point_info->break_point_objects() == *break_point_object) return;
   15691   // If there was one break point object before replace with array.
   15692   if (!break_point_info->break_point_objects()->IsFixedArray()) {
   15693     Handle<FixedArray> array = isolate->factory()->NewFixedArray(2);
   15694     array->set(0, break_point_info->break_point_objects());
   15695     array->set(1, *break_point_object);
   15696     break_point_info->set_break_point_objects(*array);
   15697     return;
   15698   }
   15699   // If there was more than one break point before extend array.
   15700   Handle<FixedArray> old_array =
   15701       Handle<FixedArray>(
   15702           FixedArray::cast(break_point_info->break_point_objects()));
   15703   Handle<FixedArray> new_array =
   15704       isolate->factory()->NewFixedArray(old_array->length() + 1);
   15705   for (int i = 0; i < old_array->length(); i++) {
   15706     // If the break point was there before just ignore.
   15707     if (old_array->get(i) == *break_point_object) return;
   15708     new_array->set(i, old_array->get(i));
   15709   }
   15710   // Add the new break point.
   15711   new_array->set(old_array->length(), *break_point_object);
   15712   break_point_info->set_break_point_objects(*new_array);
   15713 }
   15714 
   15715 
   15716 bool BreakPointInfo::HasBreakPointObject(
   15717     Handle<BreakPointInfo> break_point_info,
   15718     Handle<Object> break_point_object) {
   15719   // No break point.
   15720   if (break_point_info->break_point_objects()->IsUndefined()) return false;
   15721   // Single break point.
   15722   if (!break_point_info->break_point_objects()->IsFixedArray()) {
   15723     return break_point_info->break_point_objects() == *break_point_object;
   15724   }
   15725   // Multiple break points.
   15726   FixedArray* array = FixedArray::cast(break_point_info->break_point_objects());
   15727   for (int i = 0; i < array->length(); i++) {
   15728     if (array->get(i) == *break_point_object) {
   15729       return true;
   15730     }
   15731   }
   15732   return false;
   15733 }
   15734 
   15735 
   15736 // Get the number of break points.
   15737 int BreakPointInfo::GetBreakPointCount() {
   15738   // No break point.
   15739   if (break_point_objects()->IsUndefined()) return 0;
   15740   // Single break point.
   15741   if (!break_point_objects()->IsFixedArray()) return 1;
   15742   // Multiple break points.
   15743   return FixedArray::cast(break_point_objects())->length();
   15744 }
   15745 #endif  // ENABLE_DEBUGGER_SUPPORT
   15746 
   15747 
   15748 Object* JSDate::GetField(Object* object, Smi* index) {
   15749   return JSDate::cast(object)->DoGetField(
   15750       static_cast<FieldIndex>(index->value()));
   15751 }
   15752 
   15753 
   15754 Object* JSDate::DoGetField(FieldIndex index) {
   15755   ASSERT(index != kDateValue);
   15756 
   15757   DateCache* date_cache = GetIsolate()->date_cache();
   15758 
   15759   if (index < kFirstUncachedField) {
   15760     Object* stamp = cache_stamp();
   15761     if (stamp != date_cache->stamp() && stamp->IsSmi()) {
   15762       // Since the stamp is not NaN, the value is also not NaN.
   15763       int64_t local_time_ms =
   15764           date_cache->ToLocal(static_cast<int64_t>(value()->Number()));
   15765       SetLocalFields(local_time_ms, date_cache);
   15766     }
   15767     switch (index) {
   15768       case kYear: return year();
   15769       case kMonth: return month();
   15770       case kDay: return day();
   15771       case kWeekday: return weekday();
   15772       case kHour: return hour();
   15773       case kMinute: return min();
   15774       case kSecond: return sec();
   15775       default: UNREACHABLE();
   15776     }
   15777   }
   15778 
   15779   if (index >= kFirstUTCField) {
   15780     return GetUTCField(index, value()->Number(), date_cache);
   15781   }
   15782 
   15783   double time = value()->Number();
   15784   if (std::isnan(time)) return GetIsolate()->heap()->nan_value();
   15785 
   15786   int64_t local_time_ms = date_cache->ToLocal(static_cast<int64_t>(time));
   15787   int days = DateCache::DaysFromTime(local_time_ms);
   15788 
   15789   if (index == kDays) return Smi::FromInt(days);
   15790 
   15791   int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days);
   15792   if (index == kMillisecond) return Smi::FromInt(time_in_day_ms % 1000);
   15793   ASSERT(index == kTimeInDay);
   15794   return Smi::FromInt(time_in_day_ms);
   15795 }
   15796 
   15797 
   15798 Object* JSDate::GetUTCField(FieldIndex index,
   15799                             double value,
   15800                             DateCache* date_cache) {
   15801   ASSERT(index >= kFirstUTCField);
   15802 
   15803   if (std::isnan(value)) return GetIsolate()->heap()->nan_value();
   15804 
   15805   int64_t time_ms = static_cast<int64_t>(value);
   15806 
   15807   if (index == kTimezoneOffset) {
   15808     return Smi::FromInt(date_cache->TimezoneOffset(time_ms));
   15809   }
   15810 
   15811   int days = DateCache::DaysFromTime(time_ms);
   15812 
   15813   if (index == kWeekdayUTC) return Smi::FromInt(date_cache->Weekday(days));
   15814 
   15815   if (index <= kDayUTC) {
   15816     int year, month, day;
   15817     date_cache->YearMonthDayFromDays(days, &year, &month, &day);
   15818     if (index == kYearUTC) return Smi::FromInt(year);
   15819     if (index == kMonthUTC) return Smi::FromInt(month);
   15820     ASSERT(index == kDayUTC);
   15821     return Smi::FromInt(day);
   15822   }
   15823 
   15824   int time_in_day_ms = DateCache::TimeInDay(time_ms, days);
   15825   switch (index) {
   15826     case kHourUTC: return Smi::FromInt(time_in_day_ms / (60 * 60 * 1000));
   15827     case kMinuteUTC: return Smi::FromInt((time_in_day_ms / (60 * 1000)) % 60);
   15828     case kSecondUTC: return Smi::FromInt((time_in_day_ms / 1000) % 60);
   15829     case kMillisecondUTC: return Smi::FromInt(time_in_day_ms % 1000);
   15830     case kDaysUTC: return Smi::FromInt(days);
   15831     case kTimeInDayUTC: return Smi::FromInt(time_in_day_ms);
   15832     default: UNREACHABLE();
   15833   }
   15834 
   15835   UNREACHABLE();
   15836   return NULL;
   15837 }
   15838 
   15839 
   15840 void JSDate::SetValue(Object* value, bool is_value_nan) {
   15841   set_value(value);
   15842   if (is_value_nan) {
   15843     HeapNumber* nan = GetIsolate()->heap()->nan_value();
   15844     set_cache_stamp(nan, SKIP_WRITE_BARRIER);
   15845     set_year(nan, SKIP_WRITE_BARRIER);
   15846     set_month(nan, SKIP_WRITE_BARRIER);
   15847     set_day(nan, SKIP_WRITE_BARRIER);
   15848     set_hour(nan, SKIP_WRITE_BARRIER);
   15849     set_min(nan, SKIP_WRITE_BARRIER);
   15850     set_sec(nan, SKIP_WRITE_BARRIER);
   15851     set_weekday(nan, SKIP_WRITE_BARRIER);
   15852   } else {
   15853     set_cache_stamp(Smi::FromInt(DateCache::kInvalidStamp), SKIP_WRITE_BARRIER);
   15854   }
   15855 }
   15856 
   15857 
   15858 void JSDate::SetLocalFields(int64_t local_time_ms, DateCache* date_cache) {
   15859   int days = DateCache::DaysFromTime(local_time_ms);
   15860   int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days);
   15861   int year, month, day;
   15862   date_cache->YearMonthDayFromDays(days, &year, &month, &day);
   15863   int weekday = date_cache->Weekday(days);
   15864   int hour = time_in_day_ms / (60 * 60 * 1000);
   15865   int min = (time_in_day_ms / (60 * 1000)) % 60;
   15866   int sec = (time_in_day_ms / 1000) % 60;
   15867   set_cache_stamp(date_cache->stamp());
   15868   set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
   15869   set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
   15870   set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
   15871   set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
   15872   set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER);
   15873   set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
   15874   set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
   15875 }
   15876 
   15877 
   15878 void JSArrayBuffer::Neuter() {
   15879   ASSERT(is_external());
   15880   set_backing_store(NULL);
   15881   set_byte_length(Smi::FromInt(0));
   15882 }
   15883 
   15884 
   15885 void JSArrayBufferView::NeuterView() {
   15886   set_byte_offset(Smi::FromInt(0));
   15887   set_byte_length(Smi::FromInt(0));
   15888 }
   15889 
   15890 
   15891 void JSDataView::Neuter() {
   15892   NeuterView();
   15893 }
   15894 
   15895 
   15896 void JSTypedArray::Neuter() {
   15897   NeuterView();
   15898   set_length(Smi::FromInt(0));
   15899   set_elements(GetHeap()->EmptyExternalArrayForMap(map()));
   15900 }
   15901 
   15902 
   15903 Type* PropertyCell::type() {
   15904   return static_cast<Type*>(type_raw());
   15905 }
   15906 
   15907 
   15908 void PropertyCell::set_type(Type* type, WriteBarrierMode ignored) {
   15909   ASSERT(IsPropertyCell());
   15910   set_type_raw(type, ignored);
   15911 }
   15912 
   15913 
   15914 Type* PropertyCell::UpdateType(Handle<PropertyCell> cell,
   15915                                Handle<Object> value) {
   15916   Isolate* isolate = cell->GetIsolate();
   15917   Handle<Type> old_type(cell->type(), isolate);
   15918   // TODO(2803): Do not track ConsString as constant because they cannot be
   15919   // embedded into code.
   15920   Handle<Type> new_type(value->IsConsString() || value->IsTheHole()
   15921                         ? Type::Any()
   15922                         : Type::Constant(value, isolate), isolate);
   15923 
   15924   if (new_type->Is(old_type)) {
   15925     return *old_type;
   15926   }
   15927 
   15928   cell->dependent_code()->DeoptimizeDependentCodeGroup(
   15929       isolate, DependentCode::kPropertyCellChangedGroup);
   15930 
   15931   if (old_type->Is(Type::None()) || old_type->Is(Type::Undefined())) {
   15932     return *new_type;
   15933   }
   15934 
   15935   return Type::Any();
   15936 }
   15937 
   15938 
   15939 MaybeObject* PropertyCell::SetValueInferType(Object* value,
   15940                                              WriteBarrierMode ignored) {
   15941   set_value(value, ignored);
   15942   if (!Type::Any()->Is(type())) {
   15943     IdempotentPointerToHandleCodeTrampoline trampoline(GetIsolate());
   15944     MaybeObject* maybe_type = trampoline.CallWithReturnValue(
   15945         &PropertyCell::UpdateType,
   15946         Handle<PropertyCell>(this),
   15947         Handle<Object>(value, GetIsolate()));
   15948     Type* new_type = NULL;
   15949     if (!maybe_type->To(&new_type)) return maybe_type;
   15950     set_type(new_type);
   15951   }
   15952   return value;
   15953 }
   15954 
   15955 
   15956 void PropertyCell::AddDependentCompilationInfo(CompilationInfo* info) {
   15957   Handle<DependentCode> dep(dependent_code());
   15958   Handle<DependentCode> codes =
   15959       DependentCode::Insert(dep, DependentCode::kPropertyCellChangedGroup,
   15960                             info->object_wrapper());
   15961   if (*codes != dependent_code()) set_dependent_code(*codes);
   15962   info->dependencies(DependentCode::kPropertyCellChangedGroup)->Add(
   15963       Handle<HeapObject>(this), info->zone());
   15964 }
   15965 
   15966 
   15967 void PropertyCell::AddDependentCode(Handle<Code> code) {
   15968   Handle<DependentCode> codes = DependentCode::Insert(
   15969       Handle<DependentCode>(dependent_code()),
   15970       DependentCode::kPropertyCellChangedGroup, code);
   15971   if (*codes != dependent_code()) set_dependent_code(*codes);
   15972 }
   15973 
   15974 
   15975 const char* GetBailoutReason(BailoutReason reason) {
   15976   ASSERT(reason < kLastErrorMessage);
   15977 #define ERROR_MESSAGES_TEXTS(C, T) T,
   15978   static const char* error_messages_[] = {
   15979       ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS)
   15980   };
   15981 #undef ERROR_MESSAGES_TEXTS
   15982   return error_messages_[reason];
   15983 }
   15984 
   15985 
   15986 } }  // namespace v8::internal
   15987