| Index: src/objects.cc
|
| diff --git a/src/objects.cc b/src/objects.cc
|
| index 10971cfb7c53c8695f620f49129373c1f489e882..fe2b6bafdda913a2625fb6e9e04d4e49009ca16b 100644
|
| --- a/src/objects.cc
|
| +++ b/src/objects.cc
|
| @@ -1812,7 +1812,8 @@ static bool IsIdentifier(UnicodeCache* cache, Name* name) {
|
| MaybeObject* JSObject::AddFastProperty(Name* name,
|
| Object* value,
|
| PropertyAttributes attributes,
|
| - StoreFromKeyed store_mode) {
|
| + StoreFromKeyed store_mode,
|
| + ValueType value_type) {
|
| ASSERT(!IsJSGlobalProxy());
|
| ASSERT(DescriptorArray::kNotFound ==
|
| map()->instance_descriptors()->Search(
|
| @@ -1838,8 +1839,8 @@ MaybeObject* JSObject::AddFastProperty(Name* name,
|
| int index = map()->NextFreePropertyIndex();
|
|
|
| // Allocate new instance descriptors with (name, index) added
|
| - Representation representation = IsJSContextExtensionObject()
|
| - ? Representation::Tagged() : value->OptimalRepresentation();
|
| + if (IsJSContextExtensionObject()) value_type = FORCE_TAGGED;
|
| + Representation representation = value->OptimalRepresentation(value_type);
|
|
|
| FieldDescriptor new_field(name, index, attributes, representation);
|
|
|
| @@ -1956,7 +1957,8 @@ MaybeObject* JSObject::AddProperty(Name* name,
|
| PropertyAttributes attributes,
|
| StrictModeFlag strict_mode,
|
| JSReceiver::StoreFromKeyed store_mode,
|
| - ExtensibilityCheck extensibility_check) {
|
| + ExtensibilityCheck extensibility_check,
|
| + ValueType value_type) {
|
| ASSERT(!IsJSGlobalProxy());
|
| Map* map_of_this = map();
|
| Heap* heap = GetHeap();
|
| @@ -1983,7 +1985,8 @@ MaybeObject* JSObject::AddProperty(Name* name,
|
| JSFunction::cast(value),
|
| attributes);
|
| } else {
|
| - result = AddFastProperty(name, value, attributes, store_mode);
|
| + result = AddFastProperty(
|
| + name, value, attributes, store_mode, value_type);
|
| }
|
| } else {
|
| // Normalize the object to prevent very large instance descriptors.
|
| @@ -2267,7 +2270,7 @@ bool Map::InstancesNeedRewriting(Map* target,
|
| int limit = NumberOfOwnDescriptors();
|
| for (int i = 0; i < limit; i++) {
|
| if (new_desc->GetDetails(i).representation().IsDouble() &&
|
| - old_desc->GetDetails(i).representation().IsSmi()) {
|
| + !old_desc->GetDetails(i).representation().IsDouble()) {
|
| return true;
|
| }
|
| }
|
| @@ -2338,8 +2341,9 @@ MaybeObject* JSObject::MigrateToMap(Map* new_map) {
|
| ? old_descriptors->GetValue(i)
|
| : RawFastPropertyAt(old_descriptors->GetFieldIndex(i));
|
| if (FLAG_track_double_fields &&
|
| - old_details.representation().IsSmi() &&
|
| + !old_details.representation().IsDouble() &&
|
| details.representation().IsDouble()) {
|
| + if (old_details.representation().IsNone()) value = Smi::FromInt(0);
|
| // Objects must be allocated in the old object space, since the
|
| // overall number of HeapNumbers needed for the conversion might
|
| // exceed the capacity of new space, and we would fail repeatedly
|
| @@ -2392,7 +2396,7 @@ MaybeObject* JSObject::GeneralizeFieldRepresentation(
|
| MaybeObject* maybe_new_map =
|
| map()->GeneralizeRepresentation(modify_index, new_representation);
|
| if (!maybe_new_map->To(&new_map)) return maybe_new_map;
|
| - ASSERT(map() != new_map || new_map->FindRootMap()->is_deprecated());
|
| + if (map() == new_map) return this;
|
|
|
| return MigrateToMap(new_map);
|
| }
|
| @@ -2569,10 +2573,21 @@ MaybeObject* Map::GeneralizeRepresentation(int modify_index,
|
| Representation old_representation =
|
| old_descriptors->GetDetails(modify_index).representation();
|
|
|
| - if (old_representation.IsNone()) {
|
| - UNREACHABLE();
|
| + // It's fine to transition from None to anything but double without any
|
| + // modification to the object, because the default uninitialized value for
|
| + // representation None can be overwritten by both smi and tagged values.
|
| + // Doubles, however, would require a box allocation.
|
| + if (old_representation.IsNone() &&
|
| + !new_representation.IsNone() &&
|
| + !new_representation.IsDouble()) {
|
| + if (FLAG_trace_generalization) {
|
| + PrintF("initializing representation %i: %p -> %s\n",
|
| + modify_index,
|
| + static_cast<void*>(this),
|
| + new_representation.Mnemonic());
|
| + }
|
| old_descriptors->SetRepresentation(modify_index, new_representation);
|
| - return this;
|
| + return old_map;
|
| }
|
|
|
| int descriptors = old_map->NumberOfOwnDescriptors();
|
| @@ -2598,7 +2613,7 @@ MaybeObject* Map::GeneralizeRepresentation(int modify_index,
|
| updated_descriptors->GetDetails(modify_index).representation();
|
| if (new_representation.fits_into(updated_representation)) {
|
| if (FLAG_trace_generalization &&
|
| - !(modify_index == 0 && new_representation.IsSmi())) {
|
| + !(modify_index == 0 && new_representation.IsNone())) {
|
| PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
|
| PrintF("migrating to existing map %p(%s) -> %p(%s)\n",
|
| static_cast<void*>(this),
|
| @@ -2636,7 +2651,7 @@ MaybeObject* Map::GeneralizeRepresentation(int modify_index,
|
| old_descriptors->GetKey(descriptor), new_descriptors);
|
|
|
| if (FLAG_trace_generalization &&
|
| - !(modify_index == 0 && new_representation.IsSmi())) {
|
| + !(modify_index == 0 && new_representation.IsNone())) {
|
| PrintF("migrating to new map %i: %p(%s) -> %p(%s) (%i steps)\n",
|
| modify_index,
|
| static_cast<void*>(this),
|
| @@ -3928,10 +3943,12 @@ Handle<Object> JSObject::SetLocalPropertyIgnoreAttributes(
|
| Handle<JSObject> object,
|
| Handle<Name> key,
|
| Handle<Object> value,
|
| - PropertyAttributes attributes) {
|
| + PropertyAttributes attributes,
|
| + ValueType value_type) {
|
| CALL_HEAP_FUNCTION(
|
| object->GetIsolate(),
|
| - object->SetLocalPropertyIgnoreAttributes(*key, *value, attributes),
|
| + object->SetLocalPropertyIgnoreAttributes(
|
| + *key, *value, attributes, value_type),
|
| Object);
|
| }
|
|
|
| @@ -3939,7 +3956,8 @@ Handle<Object> JSObject::SetLocalPropertyIgnoreAttributes(
|
| MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes(
|
| Name* name_raw,
|
| Object* value_raw,
|
| - PropertyAttributes attributes) {
|
| + PropertyAttributes attributes,
|
| + ValueType value_type) {
|
| // Make sure that the top context does not change when doing callbacks or
|
| // interceptor calls.
|
| AssertNoContextChange ncc;
|
| @@ -3965,13 +3983,16 @@ MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes(
|
| return JSObject::cast(proto)->SetLocalPropertyIgnoreAttributes(
|
| name_raw,
|
| value_raw,
|
| - attributes);
|
| + attributes,
|
| + value_type);
|
| }
|
|
|
| // Check for accessor in prototype chain removed here in clone.
|
| if (!lookup.IsFound()) {
|
| // Neither properties nor transitions found.
|
| - return AddProperty(name_raw, value_raw, attributes, kNonStrictMode);
|
| + return AddProperty(
|
| + name_raw, value_raw, attributes, kNonStrictMode,
|
| + MAY_BE_STORE_FROM_KEYED, PERFORM_EXTENSIBILITY_CHECK, value_type);
|
| }
|
|
|
| // From this point on everything needs to be handlified.
|
| @@ -3998,9 +4019,11 @@ MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes(
|
| }
|
| case FIELD: {
|
| Representation representation = lookup.representation();
|
| - if (!value->FitsRepresentation(representation)) {
|
| + Representation value_representation =
|
| + value->OptimalRepresentation(value_type);
|
| + if (!value_representation.fits_into(representation)) {
|
| MaybeObject* maybe_failure = self->GeneralizeFieldRepresentation(
|
| - lookup.GetDescriptorIndex(), value->OptimalRepresentation());
|
| + lookup.GetDescriptorIndex(), value_representation);
|
| if (maybe_failure->IsFailure()) return maybe_failure;
|
| DescriptorArray* desc = self->map()->instance_descriptors();
|
| int descriptor = lookup.GetDescriptorIndex();
|
| @@ -4041,9 +4064,11 @@ MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes(
|
| if (details.type() == FIELD) {
|
| if (attributes == details.attributes()) {
|
| Representation representation = details.representation();
|
| - if (!value->FitsRepresentation(representation)) {
|
| + Representation value_representation =
|
| + value->OptimalRepresentation(value_type);
|
| + if (!value_representation.fits_into(representation)) {
|
| MaybeObject* maybe_map = transition_map->GeneralizeRepresentation(
|
| - descriptor, value->OptimalRepresentation());
|
| + descriptor, value_representation);
|
| if (!maybe_map->To(&transition_map)) return maybe_map;
|
| Object* back = transition_map->GetBackPointer();
|
| if (back->IsMap()) {
|
|
|