Index: src/runtime.cc |
diff --git a/src/runtime.cc b/src/runtime.cc |
index 51ff5c0dea4d95adb72a9dfadfb047a6b4efdaba..dd58b2b70bfa70f454d123db1577182403c38029 100644 |
--- a/src/runtime.cc |
+++ b/src/runtime.cc |
@@ -876,7 +876,13 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOwnProperty) { |
ASSERT(proto->IsJSGlobalObject()); |
holder = Handle<JSObject>(JSObject::cast(proto)); |
} |
- NumberDictionary* dictionary = holder->element_dictionary(); |
+ FixedArray* elements = FixedArray::cast(holder->elements()); |
+ NumberDictionary* dictionary = NULL; |
+ if (elements->map() == heap->non_strict_arguments_elements_map()) { |
+ dictionary = NumberDictionary::cast(elements->get(1)); |
+ } else { |
+ dictionary = NumberDictionary::cast(elements); |
+ } |
int entry = dictionary->FindEntry(index); |
ASSERT(entry != NumberDictionary::kNotFound); |
PropertyDetails details = dictionary->DetailsAt(entry); |
@@ -4039,7 +4045,7 @@ MaybeObject* Runtime::SetObjectProperty(Isolate* isolate, |
Handle<String> name = Handle<String>::cast(converted); |
if (name->AsArrayIndex(&index)) { |
- return js_object->SetElement(index, *value, strict_mode); |
+ return js_object->SetElement(index, *value, strict_mode, true); |
} else { |
return js_object->SetProperty(*name, *value, attr, strict_mode); |
} |
@@ -4067,12 +4073,12 @@ MaybeObject* Runtime::ForceSetObjectProperty(Isolate* isolate, |
return *value; |
} |
- return js_object->SetElement(index, *value, kNonStrictMode); |
+ return js_object->SetElement(index, *value, kNonStrictMode, true); |
} |
if (key->IsString()) { |
if (Handle<String>::cast(key)->AsArrayIndex(&index)) { |
- return js_object->SetElement(index, *value, kNonStrictMode); |
+ return js_object->SetElement(index, *value, kNonStrictMode, true); |
} else { |
Handle<String> key_string = Handle<String>::cast(key); |
key_string->TryFlatten(); |
@@ -4089,7 +4095,7 @@ MaybeObject* Runtime::ForceSetObjectProperty(Isolate* isolate, |
Handle<String> name = Handle<String>::cast(converted); |
if (name->AsArrayIndex(&index)) { |
- return js_object->SetElement(index, *value, kNonStrictMode); |
+ return js_object->SetElement(index, *value, kNonStrictMode, true); |
} else { |
return js_object->SetLocalPropertyIgnoreAttributes(*name, *value, attr); |
} |
@@ -7343,6 +7349,103 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DateYMDFromTime) { |
RUNTIME_FUNCTION(MaybeObject*, Runtime_NewArgumentsFast) { |
+ HandleScope scope(isolate); |
+ ASSERT(args.length() == 3); |
+ |
+ Handle<JSFunction> callee = args.at<JSFunction>(0); |
+ Object** parameters = reinterpret_cast<Object**>(args[1]); |
+ const int argument_count = Smi::cast(args[2])->value(); |
+ |
+ Handle<JSObject> result = |
+ isolate->factory()->NewArgumentsObject(callee, argument_count); |
+ // Allocate the elements if needed. |
+ int parameter_count = callee->shared()->formal_parameter_count(); |
+ if (argument_count > 0) { |
+ if (parameter_count > 0) { |
+ int mapped_count = Min(argument_count, parameter_count); |
+ Handle<FixedArray> parameter_map = |
+ isolate->factory()->NewFixedArray(mapped_count + 2, NOT_TENURED); |
+ parameter_map->set_map( |
+ isolate->heap()->non_strict_arguments_elements_map()); |
+ |
+ Handle<Map> old_map(result->map()); |
+ Handle<Map> new_map = |
+ isolate->factory()->CopyMapDropTransitions(old_map); |
+ new_map->set_elements_kind(JSObject::NON_STRICT_ARGUMENTS_ELEMENTS); |
+ |
+ result->set_map(*new_map); |
+ result->set_elements(*parameter_map); |
+ |
+ // Store the context and the arguments array at the beginning of the |
+ // parameter map. |
+ Handle<Context> context(isolate->context()); |
+ Handle<FixedArray> arguments = |
+ isolate->factory()->NewFixedArray(argument_count, NOT_TENURED); |
+ parameter_map->set(0, *context); |
+ parameter_map->set(1, *arguments); |
+ |
+ // Loop over the actual parameters backwards. |
+ int index = argument_count - 1; |
+ while (index >= mapped_count) { |
+ // These go directly in the arguments array and have no |
+ // corresponding slot in the parameter map. |
+ arguments->set(index, *(parameters - index - 1)); |
+ --index; |
+ } |
+ |
+ ScopeInfo<> scope_info(callee->shared()->scope_info()); |
+ while (index >= 0) { |
+ // Detect duplicate names to the right in the parameter list. |
+ Handle<String> name = scope_info.parameter_name(index); |
+ int context_slot_count = scope_info.number_of_context_slots(); |
+ bool duplicate = false; |
+ for (int j = index + 1; j < parameter_count; ++j) { |
+ if (scope_info.parameter_name(j).is_identical_to(name)) { |
+ duplicate = true; |
+ break; |
+ } |
+ } |
+ |
+ if (duplicate) { |
+ // This goes directly in the arguments array with a hole in the |
+ // parameter map. |
+ arguments->set(index, *(parameters - index - 1)); |
+ parameter_map->set_the_hole(index + 2); |
+ } else { |
+ // The context index goes in the parameter map with a hole in the |
+ // arguments array. |
+ int context_index = -1; |
+ for (int j = Context::MIN_CONTEXT_SLOTS; |
+ j < context_slot_count; |
+ ++j) { |
+ if (scope_info.context_slot_name(j).is_identical_to(name)) { |
+ context_index = j; |
+ break; |
+ } |
+ } |
+ ASSERT(context_index >= 0); |
+ arguments->set_the_hole(index); |
+ parameter_map->set(index + 2, Smi::FromInt(context_index)); |
+ } |
+ |
+ --index; |
+ } |
+ } else { |
+ // If there is no aliasing, the arguments object elements are not |
+ // special in any way. |
+ Handle<FixedArray> elements = |
+ isolate->factory()->NewFixedArray(argument_count, NOT_TENURED); |
+ result->set_elements(*elements); |
+ for (int i = 0; i < argument_count; ++i) { |
+ elements->set(i, *(parameters - i - 1)); |
+ } |
+ } |
+ } |
+ return *result; |
+} |
+ |
+ |
+RUNTIME_FUNCTION(MaybeObject*, Runtime_NewStrictArgumentsFast) { |
NoHandleAllocation ha; |
ASSERT(args.length() == 3); |
@@ -7784,7 +7887,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileForOnStackReplacement) { |
CONVERT_ARG_CHECKED(JSFunction, function, 0); |
// We're not prepared to handle a function with arguments object. |
- ASSERT(!function->shared()->scope_info()->HasArgumentsShadow()); |
+ ASSERT(!function->shared()->uses_arguments()); |
// We have hit a back edge in an unoptimized frame for a function that was |
// selected for on-stack replacement. Find the unoptimized code object. |
@@ -8749,8 +8852,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_PushIfAbsent) { |
} |
Object* obj; |
// Strict not needed. Used for cycle detection in Array join implementation. |
- { MaybeObject* maybe_obj = array->SetFastElement(length, element, |
- kNonStrictMode); |
+ { MaybeObject* maybe_obj = |
+ array->SetFastElement(length, element, kNonStrictMode, true); |
if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
} |
return isolate->heap()->true_value(); |
@@ -10061,18 +10164,14 @@ static bool CopyContextLocalsToScopeObject( |
int context_index = serialized_scope_info->ContextSlotIndex( |
*scope_info.context_slot_name(i), NULL); |
- // Don't include the arguments shadow (.arguments) context variable. |
- if (*scope_info.context_slot_name(i) != |
- isolate->heap()->arguments_shadow_symbol()) { |
- RETURN_IF_EMPTY_HANDLE_VALUE( |
- isolate, |
- SetProperty(scope_object, |
- scope_info.context_slot_name(i), |
- Handle<Object>(context->get(context_index), isolate), |
- NONE, |
- kNonStrictMode), |
- false); |
- } |
+ RETURN_IF_EMPTY_HANDLE_VALUE( |
+ isolate, |
+ SetProperty(scope_object, |
+ scope_info.context_slot_name(i), |
+ Handle<Object>(context->get(context_index), isolate), |
+ NONE, |
+ kNonStrictMode), |
+ false); |
} |
return true; |
@@ -10167,29 +10266,6 @@ static Handle<JSObject> MaterializeClosure(Isolate* isolate, |
Handle<JSObject> closure_scope = |
isolate->factory()->NewJSObject(isolate->object_function()); |
- // Check whether the arguments shadow object exists. |
- int arguments_shadow_index = |
- shared->scope_info()->ContextSlotIndex( |
- isolate->heap()->arguments_shadow_symbol(), NULL); |
- if (arguments_shadow_index >= 0) { |
- // In this case all the arguments are available in the arguments shadow |
- // object. |
- Handle<JSObject> arguments_shadow( |
- JSObject::cast(context->get(arguments_shadow_index))); |
- for (int i = 0; i < scope_info.number_of_parameters(); ++i) { |
- // We don't expect exception-throwing getters on the arguments shadow. |
- Object* element = arguments_shadow->GetElement(i)->ToObjectUnchecked(); |
- RETURN_IF_EMPTY_HANDLE_VALUE( |
- isolate, |
- SetProperty(closure_scope, |
- scope_info.parameter_name(i), |
- Handle<Object>(element, isolate), |
- NONE, |
- kNonStrictMode), |
- Handle<JSObject>()); |
- } |
- } |
- |
// Fill all context locals to the context extension. |
if (!CopyContextLocalsToScopeObject(isolate, |
serialized_scope_info, scope_info, |