| Index: src/objects.cc
|
| diff --git a/src/objects.cc b/src/objects.cc
|
| index b3a264e79831963d91b91818db9634ef4400244a..ca9e3963a8bb57f48fa1e945ac740b68b20128f1 100644
|
| --- a/src/objects.cc
|
| +++ b/src/objects.cc
|
| @@ -455,15 +455,18 @@ Handle<Object> JSProxy::SetElementWithHandler(Handle<JSProxy> proxy,
|
| StrictModeFlag strict_mode) {
|
| Isolate* isolate = proxy->GetIsolate();
|
| Handle<String> name = isolate->factory()->Uint32ToString(index);
|
| - return SetPropertyWithHandler(
|
| - proxy, receiver, name, value, NONE, strict_mode);
|
| + CALL_HEAP_FUNCTION(isolate,
|
| + proxy->SetPropertyWithHandler(
|
| + *receiver, *name, *value, NONE, strict_mode),
|
| + Object);
|
| }
|
|
|
|
|
| -bool JSProxy::HasElementWithHandler(Handle<JSProxy> proxy, uint32_t index) {
|
| - Isolate* isolate = proxy->GetIsolate();
|
| - Handle<String> name = isolate->factory()->Uint32ToString(index);
|
| - return HasPropertyWithHandler(proxy, name);
|
| +bool JSProxy::HasElementWithHandler(uint32_t index) {
|
| + String* name;
|
| + MaybeObject* maybe = GetHeap()->Uint32ToString(index);
|
| + if (!maybe->To<String>(&name)) return maybe;
|
| + return HasPropertyWithHandler(name);
|
| }
|
|
|
|
|
| @@ -1868,20 +1871,6 @@ String* JSReceiver::constructor_name() {
|
| }
|
|
|
|
|
| -Handle<Object> JSObject::AddFastPropertyUsingMap(
|
| - Handle<JSObject> object,
|
| - Handle<Map> new_map,
|
| - Handle<Name> name,
|
| - Handle<Object> value,
|
| - int field_index,
|
| - Representation representation) {
|
| - CALL_HEAP_FUNCTION(object->GetIsolate(),
|
| - object->AddFastPropertyUsingMap(
|
| - *new_map, *name, *value, field_index, representation),
|
| - Object);
|
| -}
|
| -
|
| -
|
| MaybeObject* JSObject::AddFastPropertyUsingMap(Map* new_map,
|
| Name* name,
|
| Object* value,
|
| @@ -1911,215 +1900,182 @@ MaybeObject* JSObject::AddFastPropertyUsingMap(Map* new_map,
|
| }
|
|
|
|
|
| -static MaybeObject* CopyAddFieldDescriptor(Map* map,
|
| - Name* name,
|
| - int index,
|
| - PropertyAttributes attributes,
|
| - Representation representation,
|
| - TransitionFlag flag) {
|
| - Map* new_map;
|
| - FieldDescriptor new_field_desc(name, index, attributes, representation);
|
| - MaybeObject* maybe_map = map->CopyAddDescriptor(&new_field_desc, flag);
|
| - if (!maybe_map->To(&new_map)) return maybe_map;
|
| - int unused_property_fields = map->unused_property_fields() - 1;
|
| - if (unused_property_fields < 0) {
|
| - unused_property_fields += JSObject::kFieldsAdded;
|
| - }
|
| - new_map->set_unused_property_fields(unused_property_fields);
|
| - return new_map;
|
| -}
|
| -
|
| -
|
| -static Handle<Map> CopyAddFieldDescriptor(Handle<Map> map,
|
| - Handle<Name> name,
|
| - int index,
|
| - PropertyAttributes attributes,
|
| - Representation representation,
|
| - TransitionFlag flag) {
|
| - CALL_HEAP_FUNCTION(map->GetIsolate(),
|
| - CopyAddFieldDescriptor(
|
| - *map, *name, index, attributes, representation, flag),
|
| - Map);
|
| -}
|
| -
|
| -
|
| -void JSObject::AddFastProperty(Handle<JSObject> object,
|
| - Handle<Name> name,
|
| - Handle<Object> value,
|
| - PropertyAttributes attributes,
|
| - StoreFromKeyed store_mode,
|
| - ValueType value_type,
|
| - TransitionFlag flag) {
|
| - ASSERT(!object->IsJSGlobalProxy());
|
| +MaybeObject* JSObject::AddFastProperty(Name* name,
|
| + Object* value,
|
| + PropertyAttributes attributes,
|
| + StoreFromKeyed store_mode,
|
| + ValueType value_type,
|
| + TransitionFlag flag) {
|
| + ASSERT(!IsJSGlobalProxy());
|
| ASSERT(DescriptorArray::kNotFound ==
|
| - object->map()->instance_descriptors()->Search(
|
| - *name, object->map()->NumberOfOwnDescriptors()));
|
| + map()->instance_descriptors()->Search(
|
| + name, map()->NumberOfOwnDescriptors()));
|
|
|
| // Normalize the object if the name is an actual name (not the
|
| // hidden strings) and is not a real identifier.
|
| // Normalize the object if it will have too many fast properties.
|
| - Isolate* isolate = object->GetIsolate();
|
| - if (!name->IsCacheable(isolate) ||
|
| - object->TooManyFastProperties(store_mode)) {
|
| - NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0);
|
| - AddSlowProperty(object, name, value, attributes);
|
| - return;
|
| + Isolate* isolate = GetHeap()->isolate();
|
| + if (!name->IsCacheable(isolate) || TooManyFastProperties(store_mode)) {
|
| + MaybeObject* maybe_failure =
|
| + NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
|
| + if (maybe_failure->IsFailure()) return maybe_failure;
|
| + return AddSlowProperty(name, value, attributes);
|
| }
|
|
|
| // Compute the new index for new field.
|
| - int index = object->map()->NextFreePropertyIndex();
|
| + int index = map()->NextFreePropertyIndex();
|
|
|
| // Allocate new instance descriptors with (name, index) added
|
| - if (object->IsJSContextExtensionObject()) value_type = FORCE_TAGGED;
|
| + if (IsJSContextExtensionObject()) value_type = FORCE_TAGGED;
|
| Representation representation = value->OptimalRepresentation(value_type);
|
| - Handle<Map> new_map = CopyAddFieldDescriptor(
|
| - handle(object->map()), name, index, attributes, representation, flag);
|
| -
|
| - AddFastPropertyUsingMap(object, new_map, name, value, index, representation);
|
| -}
|
|
|
| + FieldDescriptor new_field(name, index, attributes, representation);
|
|
|
| -static MaybeObject* CopyAddConstantDescriptor(Map* map,
|
| - Name* name,
|
| - Object* value,
|
| - PropertyAttributes attributes,
|
| - TransitionFlag flag) {
|
| - ConstantDescriptor new_constant_desc(name, value, attributes);
|
| - return map->CopyAddDescriptor(&new_constant_desc, flag);
|
| -}
|
| + Map* new_map;
|
| + MaybeObject* maybe_new_map = map()->CopyAddDescriptor(&new_field, flag);
|
| + if (!maybe_new_map->To(&new_map)) return maybe_new_map;
|
|
|
| + int unused_property_fields = map()->unused_property_fields() - 1;
|
| + if (unused_property_fields < 0) {
|
| + unused_property_fields += kFieldsAdded;
|
| + }
|
| + new_map->set_unused_property_fields(unused_property_fields);
|
|
|
| -static Handle<Map> CopyAddConstantDescriptor(Handle<Map> map,
|
| - Handle<Name> name,
|
| - Handle<Object> value,
|
| - PropertyAttributes attributes,
|
| - TransitionFlag flag) {
|
| - CALL_HEAP_FUNCTION(map->GetIsolate(),
|
| - CopyAddConstantDescriptor(
|
| - *map, *name, *value, attributes, flag),
|
| - Map);
|
| + return AddFastPropertyUsingMap(new_map, name, value, index, representation);
|
| }
|
|
|
|
|
| -void JSObject::AddConstantProperty(Handle<JSObject> object,
|
| - Handle<Name> name,
|
| - Handle<Object> constant,
|
| - PropertyAttributes attributes,
|
| - TransitionFlag initial_flag) {
|
| +MaybeObject* JSObject::AddConstantProperty(
|
| + Name* name,
|
| + Object* constant,
|
| + PropertyAttributes attributes,
|
| + TransitionFlag initial_flag) {
|
| + // Allocate new instance descriptors with (name, constant) added
|
| + ConstantDescriptor d(name, constant, attributes);
|
| +
|
| TransitionFlag flag =
|
| // Do not add transitions to global objects.
|
| - (object->IsGlobalObject() ||
|
| + (IsGlobalObject() ||
|
| // Don't add transitions to special properties with non-trivial
|
| // attributes.
|
| attributes != NONE)
|
| ? OMIT_TRANSITION
|
| : initial_flag;
|
|
|
| - // Allocate new instance descriptors with (name, constant) added.
|
| - Handle<Map> new_map = CopyAddConstantDescriptor(
|
| - handle(object->map()), name, constant, attributes, flag);
|
| -
|
| - object->set_map(*new_map);
|
| -}
|
| -
|
| + Map* new_map;
|
| + MaybeObject* maybe_new_map = map()->CopyAddDescriptor(&d, flag);
|
| + if (!maybe_new_map->To(&new_map)) return maybe_new_map;
|
|
|
| -// TODO(mstarzinger): Temporary wrapper until handlified.
|
| -static Handle<NameDictionary> NameDictionaryAdd(Handle<NameDictionary> dict,
|
| - Handle<Name> name,
|
| - Handle<Object> value,
|
| - PropertyDetails details) {
|
| - CALL_HEAP_FUNCTION(dict->GetIsolate(),
|
| - dict->Add(*name, *value, details),
|
| - NameDictionary);
|
| + set_map(new_map);
|
| + return constant;
|
| }
|
|
|
|
|
| -void JSObject::AddSlowProperty(Handle<JSObject> object,
|
| - Handle<Name> name,
|
| - Handle<Object> value,
|
| - PropertyAttributes attributes) {
|
| - ASSERT(!object->HasFastProperties());
|
| - Isolate* isolate = object->GetIsolate();
|
| - Handle<NameDictionary> dict(object->property_dictionary());
|
| - if (object->IsGlobalObject()) {
|
| +// Add property in slow mode
|
| +MaybeObject* JSObject::AddSlowProperty(Name* name,
|
| + Object* value,
|
| + PropertyAttributes attributes) {
|
| + ASSERT(!HasFastProperties());
|
| + NameDictionary* dict = property_dictionary();
|
| + Object* store_value = value;
|
| + if (IsGlobalObject()) {
|
| // In case name is an orphaned property reuse the cell.
|
| - int entry = dict->FindEntry(*name);
|
| + int entry = dict->FindEntry(name);
|
| if (entry != NameDictionary::kNotFound) {
|
| - Handle<PropertyCell> cell(PropertyCell::cast(dict->ValueAt(entry)));
|
| - PropertyCell::SetValueInferType(cell, value);
|
| + store_value = dict->ValueAt(entry);
|
| + MaybeObject* maybe_type =
|
| + PropertyCell::cast(store_value)->SetValueInferType(value);
|
| + if (maybe_type->IsFailure()) return maybe_type;
|
| // Assign an enumeration index to the property and update
|
| // SetNextEnumerationIndex.
|
| int index = dict->NextEnumerationIndex();
|
| PropertyDetails details = PropertyDetails(attributes, NORMAL, index);
|
| dict->SetNextEnumerationIndex(index + 1);
|
| - dict->SetEntry(entry, *name, *cell, details);
|
| - return;
|
| + dict->SetEntry(entry, name, store_value, details);
|
| + return value;
|
| + }
|
| + Heap* heap = GetHeap();
|
| + { MaybeObject* maybe_store_value =
|
| + heap->AllocatePropertyCell(value);
|
| + if (!maybe_store_value->ToObject(&store_value)) return maybe_store_value;
|
| }
|
| - Handle<PropertyCell> cell = isolate->factory()->NewPropertyCell(value);
|
| - PropertyCell::SetValueInferType(cell, value);
|
| - value = cell;
|
| + MaybeObject* maybe_type =
|
| + PropertyCell::cast(store_value)->SetValueInferType(value);
|
| + if (maybe_type->IsFailure()) return maybe_type;
|
| }
|
| PropertyDetails details = PropertyDetails(attributes, NORMAL, 0);
|
| - Handle<NameDictionary> result = NameDictionaryAdd(dict, name, value, details);
|
| - if (*dict != *result) object->set_properties(*result);
|
| + Object* result;
|
| + { MaybeObject* maybe_result = dict->Add(name, store_value, details);
|
| + if (!maybe_result->ToObject(&result)) return maybe_result;
|
| + }
|
| + if (dict != result) set_properties(NameDictionary::cast(result));
|
| + return value;
|
| }
|
|
|
|
|
| -Handle<Object> JSObject::AddProperty(Handle<JSObject> object,
|
| - Handle<Name> name,
|
| - Handle<Object> value,
|
| - PropertyAttributes attributes,
|
| - StrictModeFlag strict_mode,
|
| - JSReceiver::StoreFromKeyed store_mode,
|
| - ExtensibilityCheck extensibility_check,
|
| - ValueType value_type,
|
| - StoreMode mode,
|
| - TransitionFlag transition_flag) {
|
| - ASSERT(!object->IsJSGlobalProxy());
|
| - Isolate* isolate = object->GetIsolate();
|
| +MaybeObject* JSObject::AddProperty(Name* name,
|
| + Object* value,
|
| + PropertyAttributes attributes,
|
| + StrictModeFlag strict_mode,
|
| + JSReceiver::StoreFromKeyed store_mode,
|
| + ExtensibilityCheck extensibility_check,
|
| + ValueType value_type,
|
| + StoreMode mode,
|
| + TransitionFlag transition_flag) {
|
| + ASSERT(!IsJSGlobalProxy());
|
| + Map* map_of_this = map();
|
| + Heap* heap = GetHeap();
|
| + Isolate* isolate = heap->isolate();
|
| + MaybeObject* result;
|
| if (extensibility_check == PERFORM_EXTENSIBILITY_CHECK &&
|
| - !object->map()->is_extensible()) {
|
| + !map_of_this->is_extensible()) {
|
| if (strict_mode == kNonStrictMode) {
|
| return value;
|
| } else {
|
| - Handle<Object> args[1] = { name };
|
| - Handle<Object> error = isolate->factory()->NewTypeError(
|
| - "object_not_extensible", HandleVector(args, ARRAY_SIZE(args)));
|
| - isolate->Throw(*error);
|
| - return Handle<Object>();
|
| + Handle<Object> args[1] = {Handle<Name>(name)};
|
| + return isolate->Throw(
|
| + *isolate->factory()->NewTypeError("object_not_extensible",
|
| + HandleVector(args, 1)));
|
| }
|
| }
|
|
|
| - if (object->HasFastProperties()) {
|
| + if (HasFastProperties()) {
|
| // Ensure the descriptor array does not get too big.
|
| - if (object->map()->NumberOfOwnDescriptors() <
|
| + if (map_of_this->NumberOfOwnDescriptors() <
|
| DescriptorArray::kMaxNumberOfDescriptors) {
|
| // TODO(verwaest): Support other constants.
|
| // if (mode == ALLOW_AS_CONSTANT &&
|
| // !value->IsTheHole() &&
|
| // !value->IsConsString()) {
|
| if (value->IsJSFunction()) {
|
| - AddConstantProperty(object, name, value, attributes, transition_flag);
|
| + result = AddConstantProperty(name, value, attributes, transition_flag);
|
| } else {
|
| - AddFastProperty(object, name, value, attributes, store_mode,
|
| - value_type, transition_flag);
|
| + result = AddFastProperty(
|
| + name, value, attributes, store_mode, value_type, transition_flag);
|
| }
|
| } else {
|
| // Normalize the object to prevent very large instance descriptors.
|
| // This eliminates unwanted N^2 allocation and lookup behavior.
|
| - NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0);
|
| - AddSlowProperty(object, name, value, attributes);
|
| + Object* obj;
|
| + MaybeObject* maybe = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0);
|
| + if (!maybe->To(&obj)) return maybe;
|
| + result = AddSlowProperty(name, value, attributes);
|
| }
|
| } else {
|
| - AddSlowProperty(object, name, value, attributes);
|
| + result = AddSlowProperty(name, value, attributes);
|
| }
|
|
|
| - if (FLAG_harmony_observation && object->map()->is_observed()) {
|
| - Handle<Object> old_value = isolate->factory()->the_hole_value();
|
| - EnqueueChangeRecord(object, "new", name, old_value);
|
| + Handle<Object> hresult;
|
| + if (!result->ToHandle(&hresult, isolate)) return result;
|
| +
|
| + if (FLAG_harmony_observation && map()->is_observed()) {
|
| + EnqueueChangeRecord(handle(this, isolate),
|
| + "new",
|
| + handle(name, isolate),
|
| + handle(heap->the_hole_value(), isolate));
|
| }
|
|
|
| - return value;
|
| + return *hresult;
|
| }
|
|
|
|
|
| @@ -2159,39 +2115,37 @@ void JSObject::DeliverChangeRecords(Isolate* isolate) {
|
| }
|
|
|
|
|
| -Handle<Object> JSObject::SetPropertyPostInterceptor(
|
| - Handle<JSObject> object,
|
| - Handle<Name> name,
|
| - Handle<Object> value,
|
| +MaybeObject* JSObject::SetPropertyPostInterceptor(
|
| + Name* name,
|
| + Object* value,
|
| PropertyAttributes attributes,
|
| - StrictModeFlag strict_mode) {
|
| + StrictModeFlag strict_mode,
|
| + StoreMode mode) {
|
| // Check local property, ignore interceptor.
|
| - LookupResult result(object->GetIsolate());
|
| - object->LocalLookupRealNamedProperty(*name, &result);
|
| - if (!result.IsFound()) {
|
| - object->map()->LookupTransition(*object, *name, &result);
|
| - }
|
| + LookupResult result(GetIsolate());
|
| + LocalLookupRealNamedProperty(name, &result);
|
| + if (!result.IsFound()) map()->LookupTransition(this, name, &result);
|
| if (result.IsFound()) {
|
| // An existing property or a map transition was found. Use set property to
|
| // handle all these cases.
|
| - return SetPropertyForResult(object, &result, name, value, attributes,
|
| - strict_mode, MAY_BE_STORE_FROM_KEYED);
|
| + return SetProperty(&result, name, value, attributes, strict_mode);
|
| }
|
| bool done = false;
|
| - Handle<Object> result_object = SetPropertyViaPrototypes(
|
| - object, name, value, attributes, strict_mode, &done);
|
| + MaybeObject* result_object =
|
| + SetPropertyViaPrototypes(name, value, attributes, strict_mode, &done);
|
| if (done) return result_object;
|
| // Add a new real property.
|
| - return AddProperty(object, name, value, attributes, strict_mode);
|
| + return AddProperty(name, value, attributes, strict_mode,
|
| + MAY_BE_STORE_FROM_KEYED, PERFORM_EXTENSIBILITY_CHECK,
|
| + OPTIMAL_REPRESENTATION, mode);
|
| }
|
|
|
|
|
| -static Handle<Object> ReplaceSlowProperty(Handle<JSObject> object,
|
| - Handle<Name> name,
|
| - Handle<Object> value,
|
| - PropertyAttributes attributes) {
|
| - NameDictionary* dictionary = object->property_dictionary();
|
| - int old_index = dictionary->FindEntry(*name);
|
| +MaybeObject* JSObject::ReplaceSlowProperty(Name* name,
|
| + Object* value,
|
| + PropertyAttributes attributes) {
|
| + NameDictionary* dictionary = property_dictionary();
|
| + int old_index = dictionary->FindEntry(name);
|
| int new_enumeration_index = 0; // 0 means "Use the next available index."
|
| if (old_index != -1) {
|
| // All calls to ReplaceSlowProperty have had all transitions removed.
|
| @@ -2199,7 +2153,7 @@ static Handle<Object> ReplaceSlowProperty(Handle<JSObject> object,
|
| }
|
|
|
| PropertyDetails new_details(attributes, NORMAL, new_enumeration_index);
|
| - return JSObject::SetNormalizedProperty(object, name, value, new_details);
|
| + return SetNormalizedProperty(name, value, new_details);
|
| }
|
|
|
|
|
| @@ -2306,11 +2260,6 @@ bool Map::InstancesNeedRewriting(Map* target,
|
| }
|
|
|
|
|
| -void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map) {
|
| - CALL_HEAP_FUNCTION_VOID(object->GetIsolate(), object->MigrateToMap(*new_map));
|
| -}
|
| -
|
| -
|
| // To migrate an instance to a map:
|
| // - First check whether the instance needs to be rewritten. If not, simply
|
| // change the map.
|
| @@ -2412,14 +2361,17 @@ MaybeObject* JSObject::MigrateToMap(Map* new_map) {
|
| }
|
|
|
|
|
| -void JSObject::GeneralizeFieldRepresentation(Handle<JSObject> object,
|
| - int modify_index,
|
| - Representation new_representation,
|
| - StoreMode store_mode) {
|
| - Handle<Map> new_map = Map::GeneralizeRepresentation(
|
| - handle(object->map()), modify_index, new_representation, store_mode);
|
| - if (object->map() == *new_map) return;
|
| - return MigrateToMap(object, new_map);
|
| +MaybeObject* JSObject::GeneralizeFieldRepresentation(
|
| + int modify_index,
|
| + Representation new_representation,
|
| + StoreMode store_mode) {
|
| + Map* new_map;
|
| + MaybeObject* maybe_new_map = map()->GeneralizeRepresentation(
|
| + modify_index, new_representation, store_mode);
|
| + if (!maybe_new_map->To(&new_map)) return maybe_new_map;
|
| + if (map() == new_map) return this;
|
| +
|
| + return MigrateToMap(new_map);
|
| }
|
|
|
|
|
| @@ -2433,12 +2385,14 @@ int Map::NumberOfFields() {
|
| }
|
|
|
|
|
| -Handle<Map> Map::CopyGeneralizeAllRepresentations(Handle<Map> map,
|
| - int modify_index,
|
| - StoreMode store_mode,
|
| - PropertyAttributes attributes,
|
| - const char* reason) {
|
| - Handle<Map> new_map = Copy(map);
|
| +MaybeObject* Map::CopyGeneralizeAllRepresentations(
|
| + int modify_index,
|
| + StoreMode store_mode,
|
| + PropertyAttributes attributes,
|
| + const char* reason) {
|
| + Map* new_map;
|
| + MaybeObject* maybe_map = this->Copy();
|
| + if (!maybe_map->To(&new_map)) return maybe_map;
|
|
|
| DescriptorArray* descriptors = new_map->instance_descriptors();
|
| descriptors->InitializeRepresentations(Representation::Tagged());
|
| @@ -2460,7 +2414,7 @@ Handle<Map> Map::CopyGeneralizeAllRepresentations(Handle<Map> map,
|
| }
|
|
|
| if (FLAG_trace_generalization) {
|
| - map->PrintGeneralization(stdout, reason, modify_index,
|
| + PrintGeneralization(stdout, reason, modify_index,
|
| new_map->NumberOfOwnDescriptors(),
|
| new_map->NumberOfOwnDescriptors(),
|
| details.type() == CONSTANT && store_mode == FORCE_FIELD,
|
| @@ -2608,11 +2562,11 @@ Map* Map::FindLastMatchMap(int verbatim,
|
| // - If |updated| == |split_map|, |updated| is in the expected state. Return it.
|
| // - Otherwise, invalidate the outdated transition target from |updated|, and
|
| // replace its transition tree with a new branch for the updated descriptors.
|
| -Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map,
|
| - int modify_index,
|
| - Representation new_representation,
|
| - StoreMode store_mode) {
|
| - Handle<DescriptorArray> old_descriptors(old_map->instance_descriptors());
|
| +MaybeObject* Map::GeneralizeRepresentation(int modify_index,
|
| + Representation new_representation,
|
| + StoreMode store_mode) {
|
| + Map* old_map = this;
|
| + DescriptorArray* old_descriptors = old_map->instance_descriptors();
|
| PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
|
| Representation old_representation = old_details.representation();
|
|
|
| @@ -2628,37 +2582,37 @@ Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map,
|
| }
|
|
|
| int descriptors = old_map->NumberOfOwnDescriptors();
|
| - Handle<Map> root_map(old_map->FindRootMap());
|
| + Map* root_map = old_map->FindRootMap();
|
|
|
| // Check the state of the root map.
|
| - if (!old_map->EquivalentToForTransition(*root_map)) {
|
| - return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
|
| - old_details.attributes(), "not equivalent");
|
| + if (!old_map->EquivalentToForTransition(root_map)) {
|
| + return CopyGeneralizeAllRepresentations(
|
| + modify_index, store_mode, old_details.attributes(), "not equivalent");
|
| }
|
|
|
| int verbatim = root_map->NumberOfOwnDescriptors();
|
|
|
| if (store_mode != ALLOW_AS_CONSTANT && modify_index < verbatim) {
|
| - return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
|
| + return CopyGeneralizeAllRepresentations(
|
| + modify_index, store_mode,
|
| old_details.attributes(), "root modification");
|
| }
|
|
|
| - Map* raw_updated = root_map->FindUpdatedMap(
|
| - verbatim, descriptors, *old_descriptors);
|
| - if (raw_updated == NULL) {
|
| - return CopyGeneralizeAllRepresentations(old_map, modify_index, store_mode,
|
| - old_details.attributes(), "incompatible");
|
| + Map* updated = root_map->FindUpdatedMap(
|
| + verbatim, descriptors, old_descriptors);
|
| + if (updated == NULL) {
|
| + return CopyGeneralizeAllRepresentations(
|
| + modify_index, store_mode, old_details.attributes(), "incompatible");
|
| }
|
|
|
| - Handle<Map> updated(raw_updated);
|
| - Handle<DescriptorArray> updated_descriptors(updated->instance_descriptors());
|
| + DescriptorArray* updated_descriptors = updated->instance_descriptors();
|
|
|
| int valid = updated->NumberOfOwnDescriptors();
|
|
|
| // Directly change the map if the target map is more general. Ensure that the
|
| // target type of the modify_index is a FIELD, unless we are migrating.
|
| if (updated_descriptors->IsMoreGeneralThan(
|
| - verbatim, valid, descriptors, *old_descriptors) &&
|
| + verbatim, valid, descriptors, old_descriptors) &&
|
| (store_mode == ALLOW_AS_CONSTANT ||
|
| updated_descriptors->GetDetails(modify_index).type() == FIELD)) {
|
| Representation updated_representation =
|
| @@ -2666,9 +2620,10 @@ Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map,
|
| if (new_representation.fits_into(updated_representation)) return updated;
|
| }
|
|
|
| - Handle<DescriptorArray> new_descriptors = DescriptorArray::Merge(
|
| - updated_descriptors, verbatim, valid, descriptors, modify_index,
|
| - store_mode, old_descriptors);
|
| + DescriptorArray* new_descriptors;
|
| + MaybeObject* maybe_descriptors = updated_descriptors->Merge(
|
| + verbatim, valid, descriptors, modify_index, store_mode, old_descriptors);
|
| + if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
|
| ASSERT(store_mode == ALLOW_AS_CONSTANT ||
|
| new_descriptors->GetDetails(modify_index).type() == FIELD);
|
|
|
| @@ -2680,8 +2635,8 @@ Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map,
|
| new_descriptors->SetRepresentation(modify_index, updated_representation);
|
| }
|
|
|
| - Handle<Map> split_map(root_map->FindLastMatchMap(
|
| - verbatim, descriptors, *new_descriptors));
|
| + Map* split_map = root_map->FindLastMatchMap(
|
| + verbatim, descriptors, new_descriptors);
|
|
|
| int split_descriptors = split_map->NumberOfOwnDescriptors();
|
| // This is shadowed by |updated_descriptors| being more general than
|
| @@ -2690,20 +2645,28 @@ Handle<Map> Map::GeneralizeRepresentation(Handle<Map> old_map,
|
|
|
| int descriptor = split_descriptors;
|
| split_map->DeprecateTarget(
|
| - old_descriptors->GetKey(descriptor), *new_descriptors);
|
| + old_descriptors->GetKey(descriptor), new_descriptors);
|
|
|
| if (FLAG_trace_generalization) {
|
| - old_map->PrintGeneralization(
|
| + PrintGeneralization(
|
| stdout, "", modify_index, descriptor, descriptors,
|
| old_descriptors->GetDetails(modify_index).type() == CONSTANT &&
|
| store_mode == FORCE_FIELD,
|
| old_representation, updated_representation);
|
| }
|
|
|
| + Map* new_map = split_map;
|
| // Add missing transitions.
|
| - Handle<Map> new_map = split_map;
|
| for (; descriptor < descriptors; descriptor++) {
|
| - new_map = Map::CopyInstallDescriptors(new_map, descriptor, new_descriptors);
|
| + MaybeObject* maybe_map = new_map->CopyInstallDescriptors(
|
| + descriptor, new_descriptors);
|
| + if (!maybe_map->To(&new_map)) {
|
| + // Create a handle for the last created map to ensure it stays alive
|
| + // during GC. Its descriptor array is too large, but it will be
|
| + // overwritten during retry anyway.
|
| + Handle<Map>(new_map);
|
| + return maybe_map;
|
| + }
|
| new_map->set_migration_target(true);
|
| }
|
|
|
| @@ -2740,52 +2703,79 @@ Map* Map::CurrentMapForDeprecated() {
|
| }
|
|
|
|
|
| -Handle<Object> JSObject::SetPropertyWithInterceptor(
|
| - Handle<JSObject> object,
|
| - Handle<Name> name,
|
| - Handle<Object> value,
|
| +MaybeObject* JSObject::SetPropertyWithInterceptor(
|
| + Name* name,
|
| + Object* value,
|
| PropertyAttributes attributes,
|
| StrictModeFlag strict_mode) {
|
| // TODO(rossberg): Support symbols in the API.
|
| if (name->IsSymbol()) return value;
|
| - Isolate* isolate = object->GetIsolate();
|
| - Handle<String> name_string = Handle<String>::cast(name);
|
| - Handle<InterceptorInfo> interceptor(object->GetNamedInterceptor());
|
| + Isolate* isolate = GetIsolate();
|
| + HandleScope scope(isolate);
|
| + Handle<JSObject> this_handle(this);
|
| + Handle<String> name_handle(String::cast(name));
|
| + Handle<Object> value_handle(value, isolate);
|
| + Handle<InterceptorInfo> interceptor(GetNamedInterceptor());
|
| if (!interceptor->setter()->IsUndefined()) {
|
| - LOG(isolate,
|
| - ApiNamedPropertyAccess("interceptor-named-set", *object, *name));
|
| - PropertyCallbackArguments args(
|
| - isolate, interceptor->data(), *object, *object);
|
| + LOG(isolate, ApiNamedPropertyAccess("interceptor-named-set", this, name));
|
| + PropertyCallbackArguments args(isolate, interceptor->data(), this, this);
|
| v8::NamedPropertySetterCallback setter =
|
| v8::ToCData<v8::NamedPropertySetterCallback>(interceptor->setter());
|
| - Handle<Object> value_unhole = value->IsTheHole()
|
| - ? Handle<Object>(isolate->factory()->undefined_value()) : value;
|
| + Handle<Object> value_unhole(value->IsTheHole() ?
|
| + isolate->heap()->undefined_value() :
|
| + value,
|
| + isolate);
|
| v8::Handle<v8::Value> result = args.Call(setter,
|
| - v8::Utils::ToLocal(name_string),
|
| + v8::Utils::ToLocal(name_handle),
|
| v8::Utils::ToLocal(value_unhole));
|
| - RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
|
| - if (!result.IsEmpty()) return value;
|
| + RETURN_IF_SCHEDULED_EXCEPTION(isolate);
|
| + if (!result.IsEmpty()) return *value_handle;
|
| }
|
| - Handle<Object> result =
|
| - SetPropertyPostInterceptor(object, name, value, attributes, strict_mode);
|
| - RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
|
| - return result;
|
| + MaybeObject* raw_result =
|
| + this_handle->SetPropertyPostInterceptor(*name_handle,
|
| + *value_handle,
|
| + attributes,
|
| + strict_mode);
|
| + RETURN_IF_SCHEDULED_EXCEPTION(isolate);
|
| + return raw_result;
|
| }
|
|
|
|
|
| Handle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object,
|
| - Handle<Name> name,
|
| + Handle<Name> key,
|
| Handle<Object> value,
|
| PropertyAttributes attributes,
|
| - StrictModeFlag strict_mode,
|
| - StoreFromKeyed store_mode) {
|
| - LookupResult result(object->GetIsolate());
|
| - object->LocalLookup(*name, &result, true);
|
| + StrictModeFlag strict_mode) {
|
| + CALL_HEAP_FUNCTION(object->GetIsolate(),
|
| + object->SetProperty(*key, *value, attributes, strict_mode),
|
| + Object);
|
| +}
|
| +
|
| +
|
| +MaybeObject* JSReceiver::SetPropertyOrFail(
|
| + Handle<JSReceiver> object,
|
| + Handle<Name> key,
|
| + Handle<Object> value,
|
| + PropertyAttributes attributes,
|
| + StrictModeFlag strict_mode,
|
| + JSReceiver::StoreFromKeyed store_mode) {
|
| + CALL_HEAP_FUNCTION_PASS_EXCEPTION(
|
| + object->GetIsolate(),
|
| + object->SetProperty(*key, *value, attributes, strict_mode, store_mode));
|
| +}
|
| +
|
| +
|
| +MaybeObject* JSReceiver::SetProperty(Name* name,
|
| + Object* value,
|
| + PropertyAttributes attributes,
|
| + StrictModeFlag strict_mode,
|
| + JSReceiver::StoreFromKeyed store_mode) {
|
| + LookupResult result(GetIsolate());
|
| + LocalLookup(name, &result, true);
|
| if (!result.IsFound()) {
|
| - object->map()->LookupTransition(JSObject::cast(*object), *name, &result);
|
| + map()->LookupTransition(JSObject::cast(this), name, &result);
|
| }
|
| - return SetProperty(object, &result, name, value, attributes, strict_mode,
|
| - store_mode);
|
| + return SetProperty(&result, name, value, attributes, strict_mode, store_mode);
|
| }
|
|
|
|
|
| @@ -2940,20 +2930,21 @@ MaybeObject* JSObject::SetElementWithCallbackSetterInPrototypes(
|
| return heap->the_hole_value();
|
| }
|
|
|
| -Handle<Object> JSObject::SetPropertyViaPrototypes(Handle<JSObject> object,
|
| - Handle<Name> name,
|
| - Handle<Object> value,
|
| - PropertyAttributes attributes,
|
| - StrictModeFlag strict_mode,
|
| - bool* done) {
|
| - Isolate* isolate = object->GetIsolate();
|
| +MaybeObject* JSObject::SetPropertyViaPrototypes(
|
| + Name* name,
|
| + Object* value,
|
| + PropertyAttributes attributes,
|
| + StrictModeFlag strict_mode,
|
| + bool* done) {
|
| + Heap* heap = GetHeap();
|
| + Isolate* isolate = heap->isolate();
|
|
|
| *done = false;
|
| // We could not find a local property so let's check whether there is an
|
| // accessor that wants to handle the property, or whether the property is
|
| // read-only on the prototype chain.
|
| LookupResult result(isolate);
|
| - object->LookupRealNamedPropertyInPrototypes(*name, &result);
|
| + LookupRealNamedPropertyInPrototypes(name, &result);
|
| if (result.IsFound()) {
|
| switch (result.type()) {
|
| case NORMAL:
|
| @@ -2964,25 +2955,19 @@ Handle<Object> JSObject::SetPropertyViaPrototypes(Handle<JSObject> object,
|
| case INTERCEPTOR: {
|
| PropertyAttributes attr =
|
| result.holder()->GetPropertyAttributeWithInterceptor(
|
| - *object, *name, true);
|
| + this, name, true);
|
| *done = !!(attr & READ_ONLY);
|
| break;
|
| }
|
| case CALLBACKS: {
|
| if (!FLAG_es5_readonly && result.IsReadOnly()) break;
|
| *done = true;
|
| - CALL_HEAP_FUNCTION(isolate,
|
| - object->SetPropertyWithCallback(
|
| - result.GetCallbackObject(),
|
| - *name, *value, result.holder(), strict_mode),
|
| - Object);
|
| + return SetPropertyWithCallback(result.GetCallbackObject(),
|
| + name, value, result.holder(), strict_mode);
|
| }
|
| case HANDLER: {
|
| - CALL_HEAP_FUNCTION(isolate,
|
| - result.proxy()->SetPropertyViaPrototypesWithHandler(
|
| - *object, *name, *value, attributes, strict_mode,
|
| - done),
|
| - Object);
|
| + return result.proxy()->SetPropertyViaPrototypesWithHandler(
|
| + this, name, value, attributes, strict_mode, done);
|
| }
|
| case TRANSITION:
|
| case NONEXISTENT:
|
| @@ -2995,13 +2980,12 @@ Handle<Object> JSObject::SetPropertyViaPrototypes(Handle<JSObject> object,
|
| if (!FLAG_es5_readonly) *done = false;
|
| if (*done) {
|
| if (strict_mode == kNonStrictMode) return value;
|
| - Handle<Object> args[] = { name, object };
|
| - Handle<Object> error = isolate->factory()->NewTypeError(
|
| - "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args)));
|
| - isolate->Throw(*error);
|
| - return Handle<Object>();
|
| + Handle<Object> args[] = { Handle<Object>(name, isolate),
|
| + Handle<Object>(this, isolate)};
|
| + return isolate->Throw(*isolate->factory()->NewTypeError(
|
| + "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args))));
|
| }
|
| - return isolate->factory()->the_hole_value();
|
| + return heap->the_hole_value();
|
| }
|
|
|
|
|
| @@ -3422,31 +3406,33 @@ MaybeObject* JSObject::SetPropertyWithFailedAccessCheck(
|
| }
|
|
|
|
|
| -Handle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object,
|
| - LookupResult* result,
|
| - Handle<Name> key,
|
| - Handle<Object> value,
|
| - PropertyAttributes attributes,
|
| - StrictModeFlag strict_mode,
|
| - StoreFromKeyed store_mode) {
|
| +MaybeObject* JSReceiver::SetProperty(LookupResult* result,
|
| + Name* key,
|
| + Object* value,
|
| + PropertyAttributes attributes,
|
| + StrictModeFlag strict_mode,
|
| + JSReceiver::StoreFromKeyed store_mode) {
|
| if (result->IsHandler()) {
|
| - return JSProxy::SetPropertyWithHandler(handle(result->proxy()),
|
| - object, key, value, attributes, strict_mode);
|
| + return result->proxy()->SetPropertyWithHandler(
|
| + this, key, value, attributes, strict_mode);
|
| } else {
|
| - return JSObject::SetPropertyForResult(Handle<JSObject>::cast(object),
|
| + return JSObject::cast(this)->SetPropertyForResult(
|
| result, key, value, attributes, strict_mode, store_mode);
|
| }
|
| }
|
|
|
|
|
| -bool JSProxy::HasPropertyWithHandler(Handle<JSProxy> proxy, Handle<Name> name) {
|
| - Isolate* isolate = proxy->GetIsolate();
|
| +bool JSProxy::HasPropertyWithHandler(Name* name_raw) {
|
| + Isolate* isolate = GetIsolate();
|
| + HandleScope scope(isolate);
|
| + Handle<Object> receiver(this, isolate);
|
| + Handle<Object> name(name_raw, isolate);
|
|
|
| // TODO(rossberg): adjust once there is a story for symbols vs proxies.
|
| if (name->IsSymbol()) return false;
|
|
|
| Handle<Object> args[] = { name };
|
| - Handle<Object> result = proxy->CallTrap(
|
| + Handle<Object> result = CallTrap(
|
| "has", isolate->derived_has_trap(), ARRAY_SIZE(args), args);
|
| if (isolate->has_pending_exception()) return false;
|
|
|
| @@ -3454,22 +3440,26 @@ bool JSProxy::HasPropertyWithHandler(Handle<JSProxy> proxy, Handle<Name> name) {
|
| }
|
|
|
|
|
| -Handle<Object> JSProxy::SetPropertyWithHandler(Handle<JSProxy> proxy,
|
| - Handle<JSReceiver> receiver,
|
| - Handle<Name> name,
|
| - Handle<Object> value,
|
| - PropertyAttributes attributes,
|
| - StrictModeFlag strict_mode) {
|
| - Isolate* isolate = proxy->GetIsolate();
|
| +MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyWithHandler(
|
| + JSReceiver* receiver_raw,
|
| + Name* name_raw,
|
| + Object* value_raw,
|
| + PropertyAttributes attributes,
|
| + StrictModeFlag strict_mode) {
|
| + Isolate* isolate = GetIsolate();
|
| + HandleScope scope(isolate);
|
| + Handle<JSReceiver> receiver(receiver_raw);
|
| + Handle<Object> name(name_raw, isolate);
|
| + Handle<Object> value(value_raw, isolate);
|
|
|
| // TODO(rossberg): adjust once there is a story for symbols vs proxies.
|
| - if (name->IsSymbol()) return value;
|
| + if (name->IsSymbol()) return *value;
|
|
|
| Handle<Object> args[] = { receiver, name, value };
|
| - proxy->CallTrap("set", isolate->derived_set_trap(), ARRAY_SIZE(args), args);
|
| - if (isolate->has_pending_exception()) return Handle<Object>();
|
| + CallTrap("set", isolate->derived_set_trap(), ARRAY_SIZE(args), args);
|
| + if (isolate->has_pending_exception()) return Failure::Exception();
|
|
|
| - return value;
|
| + return *value;
|
| }
|
|
|
|
|
| @@ -3744,31 +3734,36 @@ void JSObject::AllocateStorageForMap(Handle<JSObject> object, Handle<Map> map) {
|
|
|
|
|
| void JSObject::MigrateInstance(Handle<JSObject> object) {
|
| - // Converting any field to the most specific type will cause the
|
| - // GeneralizeFieldRepresentation algorithm to create the most general existing
|
| - // transition that matches the object. This achieves what is needed.
|
| - Handle<Map> original_map(object->map());
|
| - GeneralizeFieldRepresentation(
|
| - object, 0, Representation::None(), ALLOW_AS_CONSTANT);
|
| - if (FLAG_trace_migration) {
|
| - object->PrintInstanceMigration(stdout, *original_map, object->map());
|
| - }
|
| + CALL_HEAP_FUNCTION_VOID(
|
| + object->GetIsolate(),
|
| + object->MigrateInstance());
|
| }
|
|
|
|
|
| Handle<Object> JSObject::TryMigrateInstance(Handle<JSObject> object) {
|
| - MigrateInstance(object);
|
| - return object;
|
| + CALL_HEAP_FUNCTION(
|
| + object->GetIsolate(),
|
| + object->MigrateInstance(),
|
| + Object);
|
| }
|
|
|
|
|
| -Handle<Object> JSObject::SetPropertyUsingTransition(
|
| - Handle<JSObject> object,
|
| - LookupResult* lookup,
|
| - Handle<Name> name,
|
| - Handle<Object> value,
|
| - PropertyAttributes attributes) {
|
| - Handle<Map> transition_map(lookup->GetTransitionTarget());
|
| +Handle<Map> Map::GeneralizeRepresentation(Handle<Map> map,
|
| + int modify_index,
|
| + Representation representation,
|
| + StoreMode store_mode) {
|
| + CALL_HEAP_FUNCTION(
|
| + map->GetIsolate(),
|
| + map->GeneralizeRepresentation(modify_index, representation, store_mode),
|
| + Map);
|
| +}
|
| +
|
| +
|
| +static MaybeObject* SetPropertyUsingTransition(LookupResult* lookup,
|
| + Handle<Name> name,
|
| + Handle<Object> value,
|
| + PropertyAttributes attributes) {
|
| + Map* transition_map = lookup->GetTransitionTarget();
|
| int descriptor = transition_map->LastAdded();
|
|
|
| DescriptorArray* descriptors = transition_map->instance_descriptors();
|
| @@ -3778,8 +3773,8 @@ Handle<Object> JSObject::SetPropertyUsingTransition(
|
| // AddProperty will either normalize the object, or create a new fast copy
|
| // of the map. If we get a fast copy of the map, all field representations
|
| // will be tagged since the transition is omitted.
|
| - return JSObject::AddProperty(
|
| - object, name, value, attributes, kNonStrictMode,
|
| + return lookup->holder()->AddProperty(
|
| + *name, *value, attributes, kNonStrictMode,
|
| JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED,
|
| JSReceiver::OMIT_EXTENSIBILITY_CHECK,
|
| JSObject::FORCE_TAGGED, FORCE_FIELD, OMIT_TRANSITION);
|
| @@ -3790,40 +3785,45 @@ Handle<Object> JSObject::SetPropertyUsingTransition(
|
| // (value->IsUninitialized) as constant.
|
| if (details.type() == CONSTANT &&
|
| descriptors->GetValue(descriptor) == *value) {
|
| - object->set_map(*transition_map);
|
| - return value;
|
| + lookup->holder()->set_map(transition_map);
|
| + return *value;
|
| }
|
|
|
| Representation representation = details.representation();
|
|
|
| if (!value->FitsRepresentation(representation) ||
|
| details.type() == CONSTANT) {
|
| - transition_map = Map::GeneralizeRepresentation(transition_map,
|
| + MaybeObject* maybe_map = transition_map->GeneralizeRepresentation(
|
| descriptor, value->OptimalRepresentation(), FORCE_FIELD);
|
| + if (!maybe_map->To(&transition_map)) return maybe_map;
|
| Object* back = transition_map->GetBackPointer();
|
| if (back->IsMap()) {
|
| - MigrateToMap(object, handle(Map::cast(back)));
|
| + MaybeObject* maybe_failure =
|
| + lookup->holder()->MigrateToMap(Map::cast(back));
|
| + if (maybe_failure->IsFailure()) return maybe_failure;
|
| }
|
| descriptors = transition_map->instance_descriptors();
|
| representation = descriptors->GetDetails(descriptor).representation();
|
| }
|
|
|
| int field_index = descriptors->GetFieldIndex(descriptor);
|
| - return AddFastPropertyUsingMap(
|
| - object, transition_map, name, value, field_index, representation);
|
| + return lookup->holder()->AddFastPropertyUsingMap(
|
| + transition_map, *name, *value, field_index, representation);
|
| }
|
|
|
|
|
| -static Handle<Object> SetPropertyToField(LookupResult* lookup,
|
| - Handle<Name> name,
|
| - Handle<Object> value) {
|
| +static MaybeObject* SetPropertyToField(LookupResult* lookup,
|
| + Handle<Name> name,
|
| + Handle<Object> value) {
|
| Representation representation = lookup->representation();
|
| if (!value->FitsRepresentation(representation) ||
|
| lookup->type() == CONSTANT) {
|
| - JSObject::GeneralizeFieldRepresentation(handle(lookup->holder()),
|
| - lookup->GetDescriptorIndex(),
|
| - value->OptimalRepresentation(),
|
| - FORCE_FIELD);
|
| + MaybeObject* maybe_failure =
|
| + lookup->holder()->GeneralizeFieldRepresentation(
|
| + lookup->GetDescriptorIndex(),
|
| + value->OptimalRepresentation(),
|
| + FORCE_FIELD);
|
| + if (maybe_failure->IsFailure()) return maybe_failure;
|
| DescriptorArray* desc = lookup->holder()->map()->instance_descriptors();
|
| int descriptor = lookup->GetDescriptorIndex();
|
| representation = desc->GetDetails(descriptor).representation();
|
| @@ -3833,189 +3833,199 @@ static Handle<Object> SetPropertyToField(LookupResult* lookup,
|
| HeapNumber* storage = HeapNumber::cast(lookup->holder()->RawFastPropertyAt(
|
| lookup->GetFieldIndex().field_index()));
|
| storage->set_value(value->Number());
|
| - return value;
|
| + return *value;
|
| }
|
|
|
| lookup->holder()->FastPropertyAtPut(
|
| lookup->GetFieldIndex().field_index(), *value);
|
| - return value;
|
| + return *value;
|
| }
|
|
|
|
|
| -static Handle<Object> ConvertAndSetLocalProperty(
|
| - LookupResult* lookup,
|
| - Handle<Name> name,
|
| - Handle<Object> value,
|
| - PropertyAttributes attributes) {
|
| - Handle<JSObject> object(lookup->holder());
|
| +static MaybeObject* ConvertAndSetLocalProperty(LookupResult* lookup,
|
| + Name* name,
|
| + Object* value,
|
| + PropertyAttributes attributes) {
|
| + JSObject* object = lookup->holder();
|
| if (object->TooManyFastProperties()) {
|
| - JSObject::NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0);
|
| + MaybeObject* maybe_failure = object->NormalizeProperties(
|
| + CLEAR_INOBJECT_PROPERTIES, 0);
|
| + if (maybe_failure->IsFailure()) return maybe_failure;
|
| }
|
|
|
| if (!object->HasFastProperties()) {
|
| - return ReplaceSlowProperty(object, name, value, attributes);
|
| + return object->ReplaceSlowProperty(name, value, attributes);
|
| }
|
|
|
| int descriptor_index = lookup->GetDescriptorIndex();
|
| if (lookup->GetAttributes() == attributes) {
|
| - JSObject::GeneralizeFieldRepresentation(
|
| - object, descriptor_index, Representation::Tagged(), FORCE_FIELD);
|
| + MaybeObject* maybe_failure = object->GeneralizeFieldRepresentation(
|
| + descriptor_index, Representation::Tagged(), FORCE_FIELD);
|
| + if (maybe_failure->IsFailure()) return maybe_failure;
|
| } else {
|
| - Handle<Map> old_map(object->map());
|
| - Handle<Map> new_map = Map::CopyGeneralizeAllRepresentations(old_map,
|
| + Map* map;
|
| + MaybeObject* maybe_map = object->map()->CopyGeneralizeAllRepresentations(
|
| descriptor_index, FORCE_FIELD, attributes, "attributes mismatch");
|
| - JSObject::MigrateToMap(object, new_map);
|
| + if (!maybe_map->To(&map)) return maybe_map;
|
| + MaybeObject* maybe_failure = object->MigrateToMap(map);
|
| + if (maybe_failure->IsFailure()) return maybe_failure;
|
| }
|
|
|
| DescriptorArray* descriptors = object->map()->instance_descriptors();
|
| int index = descriptors->GetDetails(descriptor_index).field_index();
|
| - object->FastPropertyAtPut(index, *value);
|
| + object->FastPropertyAtPut(index, value);
|
| return value;
|
| }
|
|
|
|
|
| -static Handle<Object> SetPropertyToFieldWithAttributes(
|
| +static MaybeObject* SetPropertyToFieldWithAttributes(
|
| LookupResult* lookup,
|
| Handle<Name> name,
|
| Handle<Object> value,
|
| PropertyAttributes attributes) {
|
| if (lookup->GetAttributes() == attributes) {
|
| - if (value->IsUninitialized()) return value;
|
| + if (value->IsUninitialized()) return *value;
|
| return SetPropertyToField(lookup, name, value);
|
| } else {
|
| - return ConvertAndSetLocalProperty(lookup, name, value, attributes);
|
| + return ConvertAndSetLocalProperty(lookup, *name, *value, attributes);
|
| }
|
| }
|
|
|
|
|
| -Handle<Object> JSObject::SetPropertyForResult(Handle<JSObject> object,
|
| - LookupResult* lookup,
|
| - Handle<Name> name,
|
| - Handle<Object> value,
|
| - PropertyAttributes attributes,
|
| - StrictModeFlag strict_mode,
|
| - StoreFromKeyed store_mode) {
|
| - Isolate* isolate = object->GetIsolate();
|
| +MaybeObject* JSObject::SetPropertyForResult(LookupResult* lookup,
|
| + Name* name_raw,
|
| + Object* value_raw,
|
| + PropertyAttributes attributes,
|
| + StrictModeFlag strict_mode,
|
| + StoreFromKeyed store_mode) {
|
| + Heap* heap = GetHeap();
|
| + Isolate* isolate = heap->isolate();
|
|
|
| // Make sure that the top context does not change when doing callbacks or
|
| // interceptor calls.
|
| - AssertNoContextChange ncc;
|
| + AssertNoContextChangeWithHandleScope ncc;
|
|
|
| // Optimization for 2-byte strings often used as keys in a decompression
|
| // dictionary. We internalize these short keys to avoid constantly
|
| // reallocating them.
|
| - if (name->IsString() && !name->IsInternalizedString() &&
|
| - Handle<String>::cast(name)->length() <= 2) {
|
| - name = isolate->factory()->InternalizeString(Handle<String>::cast(name));
|
| + if (name_raw->IsString() && !name_raw->IsInternalizedString() &&
|
| + String::cast(name_raw)->length() <= 2) {
|
| + Object* internalized_version;
|
| + { MaybeObject* maybe_string_version =
|
| + heap->InternalizeString(String::cast(name_raw));
|
| + if (maybe_string_version->ToObject(&internalized_version)) {
|
| + name_raw = String::cast(internalized_version);
|
| + }
|
| + }
|
| }
|
|
|
| // Check access rights if needed.
|
| - if (object->IsAccessCheckNeeded()) {
|
| - if (!isolate->MayNamedAccess(*object, *name, v8::ACCESS_SET)) {
|
| - CALL_HEAP_FUNCTION(
|
| - isolate,
|
| - object->SetPropertyWithFailedAccessCheck(
|
| - lookup, *name, *value, true, strict_mode),
|
| - Object);
|
| + if (IsAccessCheckNeeded()) {
|
| + if (!isolate->MayNamedAccess(this, name_raw, v8::ACCESS_SET)) {
|
| + return SetPropertyWithFailedAccessCheck(
|
| + lookup, name_raw, value_raw, true, strict_mode);
|
| }
|
| }
|
|
|
| - if (object->IsJSGlobalProxy()) {
|
| - Handle<Object> proto(object->GetPrototype(), isolate);
|
| - if (proto->IsNull()) return value;
|
| + if (IsJSGlobalProxy()) {
|
| + Object* proto = GetPrototype();
|
| + if (proto->IsNull()) return value_raw;
|
| ASSERT(proto->IsJSGlobalObject());
|
| - return SetPropertyForResult(Handle<JSObject>::cast(proto),
|
| - lookup, name, value, attributes, strict_mode, store_mode);
|
| + return JSObject::cast(proto)->SetPropertyForResult(
|
| + lookup, name_raw, value_raw, attributes, strict_mode, store_mode);
|
| }
|
|
|
| - ASSERT(!lookup->IsFound() || lookup->holder() == *object ||
|
| + ASSERT(!lookup->IsFound() || lookup->holder() == this ||
|
| lookup->holder()->map()->is_hidden_prototype());
|
|
|
| - if (!lookup->IsProperty() && !object->IsJSContextExtensionObject()) {
|
| + // From this point on everything needs to be handlified, because
|
| + // SetPropertyViaPrototypes might call back into JavaScript.
|
| + HandleScope scope(isolate);
|
| + Handle<JSObject> self(this);
|
| + Handle<Name> name(name_raw);
|
| + Handle<Object> value(value_raw, isolate);
|
| +
|
| + if (!lookup->IsProperty() && !self->IsJSContextExtensionObject()) {
|
| bool done = false;
|
| - Handle<Object> result_object = SetPropertyViaPrototypes(
|
| - object, name, value, attributes, strict_mode, &done);
|
| + MaybeObject* result_object = self->SetPropertyViaPrototypes(
|
| + *name, *value, attributes, strict_mode, &done);
|
| if (done) return result_object;
|
| }
|
|
|
| if (!lookup->IsFound()) {
|
| // Neither properties nor transitions found.
|
| - return AddProperty(
|
| - object, name, value, attributes, strict_mode, store_mode);
|
| + return self->AddProperty(
|
| + *name, *value, attributes, strict_mode, store_mode);
|
| }
|
|
|
| if (lookup->IsProperty() && lookup->IsReadOnly()) {
|
| if (strict_mode == kStrictMode) {
|
| - Handle<Object> args[] = { name, object };
|
| - Handle<Object> error = isolate->factory()->NewTypeError(
|
| - "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args)));
|
| - isolate->Throw(*error);
|
| - return Handle<Object>();
|
| + Handle<Object> args[] = { name, self };
|
| + return isolate->Throw(*isolate->factory()->NewTypeError(
|
| + "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args))));
|
| } else {
|
| - return value;
|
| + return *value;
|
| }
|
| }
|
|
|
| - Handle<Object> old_value = isolate->factory()->the_hole_value();
|
| + Handle<Object> old_value(heap->the_hole_value(), isolate);
|
| if (FLAG_harmony_observation &&
|
| - object->map()->is_observed() && lookup->IsDataProperty()) {
|
| - old_value = Object::GetProperty(object, name);
|
| + map()->is_observed() && lookup->IsDataProperty()) {
|
| + old_value = Object::GetProperty(self, name);
|
| }
|
|
|
| // This is a real property that is not read-only, or it is a
|
| // transition or null descriptor and there are no setters in the prototypes.
|
| - Handle<Object> result = value;
|
| + MaybeObject* result = *value;
|
| switch (lookup->type()) {
|
| case NORMAL:
|
| - result = SetNormalizedProperty(handle(lookup->holder()), lookup, value);
|
| + result = lookup->holder()->SetNormalizedProperty(lookup, *value);
|
| break;
|
| case FIELD:
|
| result = SetPropertyToField(lookup, name, value);
|
| break;
|
| case CONSTANT:
|
| // Only replace the constant if necessary.
|
| - if (*value == lookup->GetConstant()) return value;
|
| + if (*value == lookup->GetConstant()) return *value;
|
| result = SetPropertyToField(lookup, name, value);
|
| break;
|
| case CALLBACKS: {
|
| - Handle<Object> callback_object(lookup->GetCallbackObject(), isolate);
|
| - CALL_HEAP_FUNCTION(
|
| - isolate,
|
| - object->SetPropertyWithCallback(*callback_object, *name, *value,
|
| - lookup->holder(), strict_mode),
|
| - Object);
|
| + Object* callback_object = lookup->GetCallbackObject();
|
| + return self->SetPropertyWithCallback(
|
| + callback_object, *name, *value, lookup->holder(), strict_mode);
|
| }
|
| case INTERCEPTOR:
|
| - result = SetPropertyWithInterceptor(handle(lookup->holder()), name, value,
|
| - attributes, strict_mode);
|
| + result = lookup->holder()->SetPropertyWithInterceptor(
|
| + *name, *value, attributes, strict_mode);
|
| break;
|
| - case TRANSITION:
|
| - result = SetPropertyUsingTransition(handle(lookup->holder()), lookup,
|
| - name, value, attributes);
|
| + case TRANSITION: {
|
| + result = SetPropertyUsingTransition(lookup, name, value, attributes);
|
| break;
|
| + }
|
| case HANDLER:
|
| case NONEXISTENT:
|
| UNREACHABLE();
|
| }
|
|
|
| - RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<Object>());
|
| + Handle<Object> hresult;
|
| + if (!result->ToHandle(&hresult, isolate)) return result;
|
|
|
| - if (FLAG_harmony_observation && object->map()->is_observed()) {
|
| + if (FLAG_harmony_observation && self->map()->is_observed()) {
|
| if (lookup->IsTransition()) {
|
| - EnqueueChangeRecord(object, "new", name, old_value);
|
| + EnqueueChangeRecord(self, "new", name, old_value);
|
| } else {
|
| LookupResult new_lookup(isolate);
|
| - object->LocalLookup(*name, &new_lookup, true);
|
| + self->LocalLookup(*name, &new_lookup, true);
|
| if (new_lookup.IsDataProperty()) {
|
| - Handle<Object> new_value = Object::GetProperty(object, name);
|
| + Handle<Object> new_value = Object::GetProperty(self, name);
|
| if (!new_value->SameValue(*old_value)) {
|
| - EnqueueChangeRecord(object, "updated", name, old_value);
|
| + EnqueueChangeRecord(self, "updated", name, old_value);
|
| }
|
| }
|
| }
|
| }
|
|
|
| - return result;
|
| + return *hresult;
|
| }
|
|
|
|
|
| @@ -4053,69 +4063,91 @@ MaybeObject* JSObject::SetLocalPropertyIgnoreAttributesTrampoline(
|
| // doesn't handle function prototypes correctly.
|
| Handle<Object> JSObject::SetLocalPropertyIgnoreAttributes(
|
| Handle<JSObject> object,
|
| - Handle<Name> name,
|
| + Handle<Name> key,
|
| Handle<Object> value,
|
| PropertyAttributes attributes,
|
| ValueType value_type,
|
| StoreMode mode,
|
| ExtensibilityCheck extensibility_check) {
|
| - Isolate* isolate = object->GetIsolate();
|
| + CALL_HEAP_FUNCTION(
|
| + object->GetIsolate(),
|
| + object->SetLocalPropertyIgnoreAttributes(
|
| + *key, *value, attributes, value_type, mode, extensibility_check),
|
| + Object);
|
| +}
|
| +
|
|
|
| +MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes(
|
| + Name* name_raw,
|
| + Object* value_raw,
|
| + PropertyAttributes attributes,
|
| + ValueType value_type,
|
| + StoreMode mode,
|
| + ExtensibilityCheck extensibility_check) {
|
| // Make sure that the top context does not change when doing callbacks or
|
| // interceptor calls.
|
| - AssertNoContextChange ncc;
|
| -
|
| + AssertNoContextChangeWithHandleScope ncc;
|
| + Isolate* isolate = GetIsolate();
|
| LookupResult lookup(isolate);
|
| - object->LocalLookup(*name, &lookup, true);
|
| - if (!lookup.IsFound()) {
|
| - object->map()->LookupTransition(*object, *name, &lookup);
|
| - }
|
| -
|
| + LocalLookup(name_raw, &lookup, true);
|
| + if (!lookup.IsFound()) map()->LookupTransition(this, name_raw, &lookup);
|
| // Check access rights if needed.
|
| - if (object->IsAccessCheckNeeded()) {
|
| - if (!isolate->MayNamedAccess(*object, *name, v8::ACCESS_SET)) {
|
| - CALL_HEAP_FUNCTION(
|
| - isolate,
|
| - object->SetPropertyWithFailedAccessCheck(
|
| - &lookup, *name, *value, false, kNonStrictMode),
|
| - Object);
|
| + if (IsAccessCheckNeeded()) {
|
| + if (!isolate->MayNamedAccess(this, name_raw, v8::ACCESS_SET)) {
|
| + return SetPropertyWithFailedAccessCheck(&lookup,
|
| + name_raw,
|
| + value_raw,
|
| + false,
|
| + kNonStrictMode);
|
| }
|
| }
|
|
|
| - if (object->IsJSGlobalProxy()) {
|
| - Handle<Object> proto(object->GetPrototype(), isolate);
|
| - if (proto->IsNull()) return value;
|
| + if (IsJSGlobalProxy()) {
|
| + Object* proto = GetPrototype();
|
| + if (proto->IsNull()) return value_raw;
|
| ASSERT(proto->IsJSGlobalObject());
|
| - return SetLocalPropertyIgnoreAttributes(Handle<JSObject>::cast(proto),
|
| - name, value, attributes, value_type, mode, extensibility_check);
|
| + return JSObject::cast(proto)->SetLocalPropertyIgnoreAttributes(
|
| + name_raw,
|
| + value_raw,
|
| + attributes,
|
| + value_type,
|
| + mode,
|
| + extensibility_check);
|
| }
|
|
|
| if (lookup.IsFound() &&
|
| (lookup.type() == INTERCEPTOR || lookup.type() == CALLBACKS)) {
|
| - object->LocalLookupRealNamedProperty(*name, &lookup);
|
| + LocalLookupRealNamedProperty(name_raw, &lookup);
|
| }
|
|
|
| // Check for accessor in prototype chain removed here in clone.
|
| if (!lookup.IsFound()) {
|
| // Neither properties nor transitions found.
|
| - return AddProperty(object, name, value, attributes, kNonStrictMode,
|
| + return AddProperty(
|
| + name_raw, value_raw, attributes, kNonStrictMode,
|
| MAY_BE_STORE_FROM_KEYED, extensibility_check, value_type, mode);
|
| }
|
|
|
| - Handle<Object> old_value = isolate->factory()->the_hole_value();
|
| + // From this point on everything needs to be handlified.
|
| + HandleScope scope(isolate);
|
| + Handle<JSObject> self(this);
|
| + Handle<Name> name(name_raw);
|
| + Handle<Object> value(value_raw, isolate);
|
| +
|
| + Handle<Object> old_value(isolate->heap()->the_hole_value(), isolate);
|
| PropertyAttributes old_attributes = ABSENT;
|
| - bool is_observed = FLAG_harmony_observation && object->map()->is_observed();
|
| + bool is_observed = FLAG_harmony_observation && self->map()->is_observed();
|
| if (is_observed && lookup.IsProperty()) {
|
| if (lookup.IsDataProperty()) old_value =
|
| - Object::GetProperty(object, name);
|
| + Object::GetProperty(self, name);
|
| old_attributes = lookup.GetAttributes();
|
| }
|
|
|
| // Check of IsReadOnly removed from here in clone.
|
| - Handle<Object> result = value;
|
| + MaybeObject* result = *value;
|
| switch (lookup.type()) {
|
| case NORMAL:
|
| - result = ReplaceSlowProperty(object, name, value, attributes);
|
| + result = self->ReplaceSlowProperty(*name, *value, attributes);
|
| break;
|
| case FIELD:
|
| result = SetPropertyToFieldWithAttributes(
|
| @@ -4130,11 +4162,10 @@ Handle<Object> JSObject::SetLocalPropertyIgnoreAttributes(
|
| }
|
| break;
|
| case CALLBACKS:
|
| - result = ConvertAndSetLocalProperty(&lookup, name, value, attributes);
|
| + result = ConvertAndSetLocalProperty(&lookup, *name, *value, attributes);
|
| break;
|
| case TRANSITION:
|
| - result = SetPropertyUsingTransition(handle(lookup.holder()), &lookup,
|
| - name, value, attributes);
|
| + result = SetPropertyUsingTransition(&lookup, name, value, attributes);
|
| break;
|
| case NONEXISTENT:
|
| case HANDLER:
|
| @@ -4142,31 +4173,32 @@ Handle<Object> JSObject::SetLocalPropertyIgnoreAttributes(
|
| UNREACHABLE();
|
| }
|
|
|
| - if (result.is_null()) return result;
|
| + Handle<Object> hresult;
|
| + if (!result->ToHandle(&hresult, isolate)) return result;
|
|
|
| if (is_observed) {
|
| if (lookup.IsTransition()) {
|
| - EnqueueChangeRecord(object, "new", name, old_value);
|
| + EnqueueChangeRecord(self, "new", name, old_value);
|
| } else if (old_value->IsTheHole()) {
|
| - EnqueueChangeRecord(object, "reconfigured", name, old_value);
|
| + EnqueueChangeRecord(self, "reconfigured", name, old_value);
|
| } else {
|
| LookupResult new_lookup(isolate);
|
| - object->LocalLookup(*name, &new_lookup, true);
|
| + self->LocalLookup(*name, &new_lookup, true);
|
| bool value_changed = false;
|
| if (new_lookup.IsDataProperty()) {
|
| - Handle<Object> new_value = Object::GetProperty(object, name);
|
| + Handle<Object> new_value = Object::GetProperty(self, name);
|
| value_changed = !old_value->SameValue(*new_value);
|
| }
|
| if (new_lookup.GetAttributes() != old_attributes) {
|
| if (!value_changed) old_value = isolate->factory()->the_hole_value();
|
| - EnqueueChangeRecord(object, "reconfigured", name, old_value);
|
| + EnqueueChangeRecord(self, "reconfigured", name, old_value);
|
| } else if (value_changed) {
|
| - EnqueueChangeRecord(object, "updated", name, old_value);
|
| + EnqueueChangeRecord(self, "updated", name, old_value);
|
| }
|
| }
|
| }
|
|
|
| - return result;
|
| + return *hresult;
|
| }
|
|
|
|
|
| @@ -5120,7 +5152,7 @@ Handle<Object> JSObject::DeleteElement(Handle<JSObject> object,
|
| Handle<Object> old_value;
|
| bool should_enqueue_change_record = false;
|
| if (FLAG_harmony_observation && object->map()->is_observed()) {
|
| - should_enqueue_change_record = HasLocalElement(object, index);
|
| + should_enqueue_change_record = object->HasLocalElement(index);
|
| if (should_enqueue_change_record) {
|
| old_value = object->GetLocalElementAccessorPair(index) != NULL
|
| ? Handle<Object>::cast(factory->the_hole_value())
|
| @@ -5136,7 +5168,7 @@ Handle<Object> JSObject::DeleteElement(Handle<JSObject> object,
|
| result = AccessorDelete(object, index, mode);
|
| }
|
|
|
| - if (should_enqueue_change_record && !HasLocalElement(object, index)) {
|
| + if (should_enqueue_change_record && !object->HasLocalElement(index)) {
|
| Handle<String> name = factory->Uint32ToString(index);
|
| EnqueueChangeRecord(object, "deleted", name, old_value);
|
| }
|
| @@ -5211,7 +5243,7 @@ Handle<Object> JSObject::DeleteProperty(Handle<JSObject> object,
|
| result = DeleteNormalizedProperty(object, name, mode);
|
| }
|
|
|
| - if (is_observed && !HasLocalProperty(object, name)) {
|
| + if (is_observed && !object->HasLocalProperty(*name)) {
|
| EnqueueChangeRecord(object, "deleted", name, old_value);
|
| }
|
|
|
| @@ -5603,80 +5635,71 @@ MUST_USE_RESULT MaybeObject* JSObject::SetObserved(Isolate* isolate) {
|
| }
|
|
|
|
|
| -// TODO(mstarzinger): Temporary wrapper until handlified.
|
| -static Handle<Object> NewStorageFor(Isolate* isolate,
|
| - Handle<Object> object,
|
| - Representation representation) {
|
| - Heap* heap = isolate->heap();
|
| - CALL_HEAP_FUNCTION(isolate,
|
| - object->AllocateNewStorageFor(heap, representation),
|
| - Object);
|
| -}
|
| -
|
| -
|
| -Handle<JSObject> JSObject::Copy(Handle<JSObject> object) {
|
| - Isolate* isolate = object->GetIsolate();
|
| - CALL_HEAP_FUNCTION(isolate,
|
| - isolate->heap()->CopyJSObject(*object), JSObject);
|
| -}
|
| -
|
| -
|
| -Handle<JSObject> JSObject::DeepCopy(Handle<JSObject> object) {
|
| - Isolate* isolate = object->GetIsolate();
|
| +MUST_USE_RESULT MaybeObject* JSObject::DeepCopy(Isolate* isolate) {
|
| StackLimitCheck check(isolate);
|
| - if (check.HasOverflowed()) {
|
| - isolate->StackOverflow();
|
| - return Handle<JSObject>::null();
|
| - }
|
| + if (check.HasOverflowed()) return isolate->StackOverflow();
|
|
|
| - if (object->map()->is_deprecated()) {
|
| - MigrateInstance(object);
|
| + if (map()->is_deprecated()) {
|
| + MaybeObject* maybe_failure = MigrateInstance();
|
| + if (maybe_failure->IsFailure()) return maybe_failure;
|
| }
|
|
|
| - Handle<JSObject> copy = Copy(object);
|
| -
|
| - HandleScope scope(isolate);
|
| + Heap* heap = isolate->heap();
|
| + Object* result;
|
| + { MaybeObject* maybe_result = heap->CopyJSObject(this);
|
| + if (!maybe_result->ToObject(&result)) return maybe_result;
|
| + }
|
| + JSObject* copy = JSObject::cast(result);
|
|
|
| // Deep copy local properties.
|
| if (copy->HasFastProperties()) {
|
| - Handle<DescriptorArray> descriptors(copy->map()->instance_descriptors());
|
| + DescriptorArray* descriptors = copy->map()->instance_descriptors();
|
| int limit = copy->map()->NumberOfOwnDescriptors();
|
| for (int i = 0; i < limit; i++) {
|
| PropertyDetails details = descriptors->GetDetails(i);
|
| if (details.type() != FIELD) continue;
|
| int index = descriptors->GetFieldIndex(i);
|
| - Handle<Object> value(object->RawFastPropertyAt(index), isolate);
|
| + Object* value = RawFastPropertyAt(index);
|
| if (value->IsJSObject()) {
|
| - value = DeepCopy(Handle<JSObject>::cast(value));
|
| - RETURN_IF_EMPTY_HANDLE_VALUE(isolate, value, Handle<JSObject>());
|
| + JSObject* js_object = JSObject::cast(value);
|
| + MaybeObject* maybe_copy = js_object->DeepCopy(isolate);
|
| + if (!maybe_copy->To(&value)) return maybe_copy;
|
| } else {
|
| Representation representation = details.representation();
|
| - value = NewStorageFor(isolate, value, representation);
|
| + MaybeObject* maybe_storage =
|
| + value->AllocateNewStorageFor(heap, representation);
|
| + if (!maybe_storage->To(&value)) return maybe_storage;
|
| }
|
| - copy->FastPropertyAtPut(index, *value);
|
| + copy->FastPropertyAtPut(index, value);
|
| }
|
| } else {
|
| - Handle<FixedArray> names =
|
| - isolate->factory()->NewFixedArray(copy->NumberOfLocalProperties());
|
| - copy->GetLocalPropertyNames(*names, 0);
|
| + { MaybeObject* maybe_result =
|
| + heap->AllocateFixedArray(copy->NumberOfLocalProperties());
|
| + if (!maybe_result->ToObject(&result)) return maybe_result;
|
| + }
|
| + FixedArray* names = FixedArray::cast(result);
|
| + copy->GetLocalPropertyNames(names, 0);
|
| for (int i = 0; i < names->length(); i++) {
|
| ASSERT(names->get(i)->IsString());
|
| - Handle<String> key_string(String::cast(names->get(i)));
|
| + String* key_string = String::cast(names->get(i));
|
| PropertyAttributes attributes =
|
| - copy->GetLocalPropertyAttribute(*key_string);
|
| + copy->GetLocalPropertyAttribute(key_string);
|
| // Only deep copy fields from the object literal expression.
|
| // In particular, don't try to copy the length attribute of
|
| // an array.
|
| if (attributes != NONE) continue;
|
| - Handle<Object> value(
|
| - copy->GetProperty(*key_string, &attributes)->ToObjectUnchecked(),
|
| - isolate);
|
| + Object* value =
|
| + copy->GetProperty(key_string, &attributes)->ToObjectUnchecked();
|
| if (value->IsJSObject()) {
|
| - Handle<Object> result = DeepCopy(Handle<JSObject>::cast(value));
|
| - RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<JSObject>());
|
| - // Creating object copy for literals. No strict mode needed.
|
| - CHECK_NOT_EMPTY_HANDLE(isolate, SetProperty(
|
| - copy, key_string, result, NONE, kNonStrictMode));
|
| + JSObject* js_object = JSObject::cast(value);
|
| + { MaybeObject* maybe_result = js_object->DeepCopy(isolate);
|
| + if (!maybe_result->ToObject(&result)) return maybe_result;
|
| + }
|
| + { MaybeObject* maybe_result =
|
| + // Creating object copy for literals. No strict mode needed.
|
| + copy->SetProperty(key_string, result, NONE, kNonStrictMode);
|
| + if (!maybe_result->ToObject(&result)) return maybe_result;
|
| + }
|
| }
|
| }
|
| }
|
| @@ -5689,8 +5712,8 @@ Handle<JSObject> JSObject::DeepCopy(Handle<JSObject> object) {
|
| case FAST_ELEMENTS:
|
| case FAST_HOLEY_SMI_ELEMENTS:
|
| case FAST_HOLEY_ELEMENTS: {
|
| - Handle<FixedArray> elements(FixedArray::cast(copy->elements()));
|
| - if (elements->map() == isolate->heap()->fixed_cow_array_map()) {
|
| + FixedArray* elements = FixedArray::cast(copy->elements());
|
| + if (elements->map() == heap->fixed_cow_array_map()) {
|
| isolate->counters()->cow_arrays_created_runtime()->Increment();
|
| #ifdef DEBUG
|
| for (int i = 0; i < elements->length(); i++) {
|
| @@ -5699,31 +5722,34 @@ Handle<JSObject> JSObject::DeepCopy(Handle<JSObject> object) {
|
| #endif
|
| } else {
|
| for (int i = 0; i < elements->length(); i++) {
|
| - Handle<Object> value(elements->get(i), isolate);
|
| + Object* value = elements->get(i);
|
| ASSERT(value->IsSmi() ||
|
| value->IsTheHole() ||
|
| (IsFastObjectElementsKind(copy->GetElementsKind())));
|
| if (value->IsJSObject()) {
|
| - Handle<Object> result = DeepCopy(Handle<JSObject>::cast(value));
|
| - RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<JSObject>());
|
| - elements->set(i, *result);
|
| + JSObject* js_object = JSObject::cast(value);
|
| + { MaybeObject* maybe_result = js_object->DeepCopy(isolate);
|
| + if (!maybe_result->ToObject(&result)) return maybe_result;
|
| + }
|
| + elements->set(i, result);
|
| }
|
| }
|
| }
|
| break;
|
| }
|
| case DICTIONARY_ELEMENTS: {
|
| - Handle<SeededNumberDictionary> element_dictionary(
|
| - copy->element_dictionary());
|
| + SeededNumberDictionary* element_dictionary = copy->element_dictionary();
|
| int capacity = element_dictionary->Capacity();
|
| for (int i = 0; i < capacity; i++) {
|
| Object* k = element_dictionary->KeyAt(i);
|
| if (element_dictionary->IsKey(k)) {
|
| - Handle<Object> value(element_dictionary->ValueAt(i), isolate);
|
| + Object* value = element_dictionary->ValueAt(i);
|
| if (value->IsJSObject()) {
|
| - Handle<Object> result = DeepCopy(Handle<JSObject>::cast(value));
|
| - RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<JSObject>());
|
| - element_dictionary->ValueAtPut(i, *result);
|
| + JSObject* js_object = JSObject::cast(value);
|
| + { MaybeObject* maybe_result = js_object->DeepCopy(isolate);
|
| + if (!maybe_result->ToObject(&result)) return maybe_result;
|
| + }
|
| + element_dictionary->ValueAtPut(i, result);
|
| }
|
| }
|
| }
|
| @@ -6164,7 +6190,7 @@ void JSObject::DefineAccessor(Handle<JSObject> object,
|
| bool preexists = false;
|
| if (is_observed) {
|
| if (is_element) {
|
| - preexists = HasLocalElement(object, index);
|
| + preexists = object->HasLocalElement(index);
|
| if (preexists && object->GetLocalElementAccessorPair(index) == NULL) {
|
| old_value = Object::GetElement(isolate, object, index);
|
| }
|
| @@ -6660,15 +6686,6 @@ MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors,
|
| }
|
|
|
|
|
| -Handle<Map> Map::CopyInstallDescriptors(Handle<Map> map,
|
| - int new_descriptor,
|
| - Handle<DescriptorArray> descriptors) {
|
| - CALL_HEAP_FUNCTION(map->GetIsolate(),
|
| - map->CopyInstallDescriptors(new_descriptor, *descriptors),
|
| - Map);
|
| -}
|
| -
|
| -
|
| // Since this method is used to rewrite an existing transition tree, it can
|
| // always insert transitions without checking.
|
| MaybeObject* Map::CopyInstallDescriptors(int new_descriptor,
|
| @@ -7781,20 +7798,6 @@ void DescriptorArray::CopyFrom(int dst_index,
|
| }
|
|
|
|
|
| -Handle<DescriptorArray> DescriptorArray::Merge(Handle<DescriptorArray> desc,
|
| - int verbatim,
|
| - int valid,
|
| - int new_size,
|
| - int modify_index,
|
| - StoreMode store_mode,
|
| - Handle<DescriptorArray> other) {
|
| - CALL_HEAP_FUNCTION(desc->GetIsolate(),
|
| - desc->Merge(verbatim, valid, new_size, modify_index,
|
| - store_mode, *other),
|
| - DescriptorArray);
|
| -}
|
| -
|
| -
|
| // Generalize the |other| descriptor array by merging it into the (at least
|
| // partly) updated |this| descriptor array.
|
| // The method merges two descriptor array in three parts. Both descriptor arrays
|
| @@ -10433,8 +10436,8 @@ bool Code::allowed_in_shared_map_code_cache() {
|
| }
|
|
|
|
|
| -void Code::MakeCodeAgeSequenceYoung(byte* sequence, Isolate* isolate) {
|
| - PatchPlatformCodeAge(isolate, sequence, kNoAge, NO_MARKING_PARITY);
|
| +void Code::MakeCodeAgeSequenceYoung(byte* sequence) {
|
| + PatchPlatformCodeAge(sequence, kNoAge, NO_MARKING_PARITY);
|
| }
|
|
|
|
|
| @@ -10445,9 +10448,7 @@ void Code::MakeOlder(MarkingParity current_parity) {
|
| MarkingParity code_parity;
|
| GetCodeAgeAndParity(sequence, &age, &code_parity);
|
| if (age != kLastCodeAge && code_parity != current_parity) {
|
| - PatchPlatformCodeAge(GetIsolate(),
|
| - sequence,
|
| - static_cast<Age>(age + 1),
|
| + PatchPlatformCodeAge(sequence, static_cast<Age>(age + 1),
|
| current_parity);
|
| }
|
| }
|
| @@ -10510,7 +10511,8 @@ void Code::GetCodeAgeAndParity(Code* code, Age* age,
|
| }
|
|
|
|
|
| -Code* Code::GetCodeAgeStub(Isolate* isolate, Age age, MarkingParity parity) {
|
| +Code* Code::GetCodeAgeStub(Age age, MarkingParity parity) {
|
| + Isolate* isolate = Isolate::Current();
|
| Builtins* builtins = isolate->builtins();
|
| switch (age) {
|
| #define HANDLE_CODE_AGE(AGE) \
|
| @@ -10781,7 +10783,7 @@ const char* Code::StubType2String(StubType type) {
|
| case CONSTANT: return "CONSTANT";
|
| case CALLBACKS: return "CALLBACKS";
|
| case INTERCEPTOR: return "INTERCEPTOR";
|
| - case TRANSITION: return "TRANSITION";
|
| + case MAP_TRANSITION: return "MAP_TRANSITION";
|
| case NONEXISTENT: return "NONEXISTENT";
|
| }
|
| UNREACHABLE(); // keep the compiler happy
|
| @@ -14517,6 +14519,17 @@ PropertyCell* GlobalObject::GetPropertyCell(LookupResult* result) {
|
| }
|
|
|
|
|
| +// TODO(mstarzinger): Temporary wrapper until handlified.
|
| +static Handle<NameDictionary> NameDictionaryAdd(Handle<NameDictionary> dict,
|
| + Handle<Name> name,
|
| + Handle<Object> value,
|
| + PropertyDetails details) {
|
| + CALL_HEAP_FUNCTION(dict->GetIsolate(),
|
| + dict->Add(*name, *value, details),
|
| + NameDictionary);
|
| +}
|
| +
|
| +
|
| Handle<PropertyCell> GlobalObject::EnsurePropertyCell(
|
| Handle<GlobalObject> global,
|
| Handle<Name> name) {
|
| @@ -16095,14 +16108,6 @@ Type* PropertyCell::UpdateType(Handle<PropertyCell> cell,
|
| }
|
|
|
|
|
| -void PropertyCell::SetValueInferType(Handle<PropertyCell> cell,
|
| - Handle<Object> value,
|
| - WriteBarrierMode mode) {
|
| - CALL_HEAP_FUNCTION_VOID(cell->GetIsolate(),
|
| - cell->SetValueInferType(*value, mode));
|
| -}
|
| -
|
| -
|
| MaybeObject* PropertyCell::SetValueInferType(Object* value,
|
| WriteBarrierMode ignored) {
|
| set_value(value, ignored);
|
|
|