Index: src/builtins.cc |
diff --git a/src/builtins.cc b/src/builtins.cc |
index a833119e853aabc9593735ecc5c7af83f72fcd5f..21381f15d5cb578e49c2594d4cfec3749e366471 100644 |
--- a/src/builtins.cc |
+++ b/src/builtins.cc |
@@ -515,10 +515,10 @@ BUILTIN(ArrayShift) { |
Object* elms_obj; |
{ MaybeObject* maybe_elms_obj = |
EnsureJSArrayWithWritableFastElements(receiver); |
+ if (maybe_elms_obj == NULL) return CallJsBuiltin("ArrayShift", args); |
if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj; |
} |
- if (elms_obj == NULL || |
- !IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) { |
+ if (!IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) { |
return CallJsBuiltin("ArrayShift", args); |
} |
FixedArray* elms = FixedArray::cast(elms_obj); |
@@ -557,10 +557,10 @@ BUILTIN(ArrayUnshift) { |
Object* elms_obj; |
{ MaybeObject* maybe_elms_obj = |
EnsureJSArrayWithWritableFastElements(receiver); |
+ if (maybe_elms_obj == NULL) return CallJsBuiltin("ArrayUnshift", args); |
if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj; |
} |
- if (elms_obj == NULL || |
- !IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) { |
+ if (!IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) { |
return CallJsBuiltin("ArrayUnshift", args); |
} |
FixedArray* elms = FixedArray::cast(elms_obj); |
@@ -611,21 +611,46 @@ BUILTIN(ArrayUnshift) { |
BUILTIN(ArraySlice) { |
Object* receiver = *args.receiver(); |
- Object* elms_obj; |
+ FixedArray* elms; |
+ int len = -1; |
{ MaybeObject* maybe_elms_obj = |
EnsureJSArrayWithWritableFastElements(receiver); |
- if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj; |
- } |
- if (elms_obj == NULL || |
- !IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) { |
- return CallJsBuiltin("ArraySlice", args); |
- } |
- FixedArray* elms = FixedArray::cast(elms_obj); |
- JSArray* array = JSArray::cast(receiver); |
- ASSERT(array->HasFastElements()); |
- |
- int len = Smi::cast(array->length())->value(); |
+ Object* elms_obj; |
+ if (maybe_elms_obj != NULL && maybe_elms_obj->ToObject(&elms_obj)) { |
+ if (!IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) { |
+ return CallJsBuiltin("ArraySlice", args); |
+ } |
+ elms = FixedArray::cast(elms_obj); |
+ JSArray* array = JSArray::cast(receiver); |
+ ASSERT(array->HasFastElements()); |
+ len = Smi::cast(array->length())->value(); |
+ } else { |
+ // Array.slice(arguments, ...) is quite a common idiom (notably more |
+ // than 50% of invocations in Web apps). Treat it in C++ as well. |
+ Map* arguments_map = |
+ Top::context()->global_context()->arguments_boilerplate()->map(); |
+ |
+ bool is_arguments_object_with_fast_elements = |
+ receiver->IsJSObject() |
+ && JSObject::cast(receiver)->map() == arguments_map |
+ && JSObject::cast(receiver)->HasFastElements(); |
+ if (!is_arguments_object_with_fast_elements) { |
+ return CallJsBuiltin("ArraySlice", args); |
+ } |
+ elms = FixedArray::cast(JSObject::cast(receiver)->elements()); |
+ len = elms->length(); |
+#ifdef DEBUG |
+ // Arguments object by construction should have no holes, check it. |
+ if (FLAG_enable_slow_asserts) { |
+ for (int i = 0; i < len; i++) { |
+ ASSERT(elms->get(i) != Heap::the_hole_value()); |
+ } |
+ } |
+#endif |
+ } |
+ } |
+ ASSERT(len >= 0); |
int n_arguments = args.length() - 1; |
// Note carefully choosen defaults---if argument is missing, |
@@ -693,10 +718,10 @@ BUILTIN(ArraySplice) { |
Object* elms_obj; |
{ MaybeObject* maybe_elms_obj = |
EnsureJSArrayWithWritableFastElements(receiver); |
+ if (maybe_elms_obj == NULL) return CallJsBuiltin("ArraySplice", args); |
if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj; |
} |
- if (elms_obj == NULL || |
- !IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) { |
+ if (!IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) { |
return CallJsBuiltin("ArraySplice", args); |
} |
FixedArray* elms = FixedArray::cast(elms_obj); |