Index: src/objects.cc |
diff --git a/src/objects.cc b/src/objects.cc |
index 17ef8dfd2308a39c87a41c76ac72e314ca9b302e..3ce84df2da3e459d89012b6ffe793c006d99e744 100644 |
--- a/src/objects.cc |
+++ b/src/objects.cc |
@@ -9568,19 +9568,31 @@ MaybeObject* JSObject::SetDictionaryElement(uint32_t index, |
// value is being defined we skip attribute checks completely. |
if (set_mode == DEFINE_PROPERTY) { |
details = PropertyDetails(attributes, NORMAL, details.index()); |
- dictionary->ValueAtPut(entry, value); |
dictionary->DetailsAtPut(entry, details); |
- } else if (!details.IsReadOnly() || element->IsTheHole()) { |
- dictionary->ValueAtPut(entry, value); |
- } else if (strict_mode == kStrictMode) { |
- Handle<Object> holder(this); |
- Handle<Object> number = isolate->factory()->NewNumberFromUint(index); |
- Handle<Object> args[2] = { number, holder }; |
- Handle<Object> error = |
- isolate->factory()->NewTypeError("strict_read_only_property", |
- HandleVector(args, 2)); |
- return isolate->Throw(*error); |
+ } else if (details.IsReadOnly() && !element->IsTheHole()) { |
+ if (strict_mode == kNonStrictMode) { |
+ return isolate->heap()->undefined_value(); |
+ } else { |
+ Handle<Object> holder(this); |
+ Handle<Object> number = isolate->factory()->NewNumberFromUint(index); |
+ Handle<Object> args[2] = { number, holder }; |
+ Handle<Object> error = |
+ isolate->factory()->NewTypeError("strict_read_only_property", |
+ HandleVector(args, 2)); |
+ return isolate->Throw(*error); |
+ } |
} |
+ // Elements of the arguments object in slow mode might be slow aliases. |
+ if (is_arguments && element->IsAliasedArgumentsEntry()) { |
+ AliasedArgumentsEntry* entry = AliasedArgumentsEntry::cast(element); |
+ Context* context = Context::cast(elements->get(0)); |
+ int context_index = entry->aliased_context_slot(); |
+ ASSERT(!context->get(context_index)->IsTheHole()); |
+ context->set(context_index, value); |
+ // For elements that are still writable we keep slow aliasing. |
+ if (!details.IsReadOnly()) value = element; |
+ } |
+ dictionary->ValueAtPut(entry, value); |
} |
} else { |
// Index not already used. Look for an accessor in the prototype chain. |
@@ -9936,17 +9948,23 @@ MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index, |
int context_index = Smi::cast(probe)->value(); |
ASSERT(!context->get(context_index)->IsTheHole()); |
context->set(context_index, value); |
- return value; |
- } else { |
- // Object is not mapped, defer to the arguments. |
- FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
- if (arguments->IsDictionary()) { |
- return SetDictionaryElement(index, value, attr, strict_mode, |
- check_prototype, set_mode); |
- } else { |
- return SetFastElement(index, value, strict_mode, check_prototype); |
+ // Redefining attributes of an aliased element destroys fast aliasing. |
+ if (set_mode == SET_PROPERTY || attr == NONE) return value; |
+ parameter_map->set_the_hole(index + 2); |
+ // For elements that are still writable we re-establish slow aliasing. |
+ if ((attr & READ_ONLY) == 0) { |
+ MaybeObject* maybe_entry = |
+ isolate->heap()->AllocateAliasedArgumentsEntry(context_index); |
+ if (!maybe_entry->ToObject(&value)) return maybe_entry; |
} |
} |
+ FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
+ if (arguments->IsDictionary()) { |
+ return SetDictionaryElement(index, value, attr, strict_mode, |
+ check_prototype, set_mode); |
+ } else { |
+ return SetFastElement(index, value, strict_mode, check_prototype); |
+ } |
} |
} |
// All possible cases have been handled above. Add a return to avoid the |