Index: src/builtins.cc |
diff --git a/src/builtins.cc b/src/builtins.cc |
index a8ba818c412a8985cf26a9003776454f167d3918..1e95bc201a105539b6c9cc5d2ee7a13e9b979447 100644 |
--- a/src/builtins.cc |
+++ b/src/builtins.cc |
@@ -319,6 +319,24 @@ static bool ArrayPrototypeHasNoElements() { |
} |
+static bool IsJSArrayWithFastElements(Object* receiver, |
+ FixedArray** elements) { |
+ if (!receiver->IsJSArray()) { |
+ return false; |
+ } |
+ |
+ JSArray* array = JSArray::cast(receiver); |
+ |
+ HeapObject* elms = HeapObject::cast(array->elements()); |
+ if (elms->map() != Heap::fixed_array_map()) { |
+ return false; |
+ } |
+ |
+ *elements = FixedArray::cast(elms); |
+ return true; |
+} |
+ |
+ |
static Object* CallJsBuiltin(const char* name, |
BuiltinArguments<NO_EXTRA_ARGUMENTS> args) { |
HandleScope handleScope; |
@@ -331,7 +349,7 @@ static Object* CallJsBuiltin(const char* name, |
Vector<Object**> argv(Vector<Object**>::New(args.length() - 1)); |
int n_args = args.length() - 1; |
for (int i = 0; i < n_args; i++) { |
- argv[i] = &args[i + 1]; |
+ argv[i] = args.at<Object>(i + 1).location(); |
} |
bool pending_exception = false; |
Handle<Object> result = Execution::Call(function, |
@@ -346,8 +364,12 @@ static Object* CallJsBuiltin(const char* name, |
BUILTIN(ArrayPush) { |
- JSArray* array = JSArray::cast(*args.receiver()); |
- ASSERT(array->HasFastElements()); |
+ Object* receiver = *args.receiver(); |
+ FixedArray* elms = NULL; |
+ if (!IsJSArrayWithFastElements(receiver, &elms)) { |
+ return CallJsBuiltin("ArrayPush", args); |
+ } |
+ JSArray* array = JSArray::cast(receiver); |
int len = Smi::cast(array->length())->value(); |
int to_add = args.length() - 1; |
@@ -359,7 +381,6 @@ BUILTIN(ArrayPush) { |
ASSERT(to_add <= (Smi::kMaxValue - len)); |
int new_length = len + to_add; |
- FixedArray* elms = FixedArray::cast(array->elements()); |
if (new_length > elms->length()) { |
// New backing storage is needed. |
@@ -390,14 +411,17 @@ BUILTIN(ArrayPush) { |
BUILTIN(ArrayPop) { |
- JSArray* array = JSArray::cast(*args.receiver()); |
- ASSERT(array->HasFastElements()); |
+ Object* receiver = *args.receiver(); |
+ FixedArray* elms = NULL; |
+ if (!IsJSArrayWithFastElements(receiver, &elms)) { |
+ return CallJsBuiltin("ArrayPop", args); |
+ } |
+ JSArray* array = JSArray::cast(receiver); |
int len = Smi::cast(array->length())->value(); |
if (len == 0) return Heap::undefined_value(); |
// Get top element |
- FixedArray* elms = FixedArray::cast(array->elements()); |
Object* top = elms->get(len - 1); |
// Set the length. |
@@ -420,18 +444,18 @@ BUILTIN(ArrayPop) { |
BUILTIN(ArrayShift) { |
- if (!ArrayPrototypeHasNoElements()) { |
+ Object* receiver = *args.receiver(); |
+ FixedArray* elms = NULL; |
+ if (!IsJSArrayWithFastElements(receiver, &elms) |
+ || !ArrayPrototypeHasNoElements()) { |
return CallJsBuiltin("ArrayShift", args); |
} |
- |
- JSArray* array = JSArray::cast(*args.receiver()); |
+ JSArray* array = JSArray::cast(receiver); |
ASSERT(array->HasFastElements()); |
int len = Smi::cast(array->length())->value(); |
if (len == 0) return Heap::undefined_value(); |
- FixedArray* elms = FixedArray::cast(array->elements()); |
- |
// Get first element |
Object* first = elms->get(0); |
if (first->IsTheHole()) { |
@@ -451,11 +475,13 @@ BUILTIN(ArrayShift) { |
BUILTIN(ArrayUnshift) { |
- if (!ArrayPrototypeHasNoElements()) { |
+ Object* receiver = *args.receiver(); |
+ FixedArray* elms = NULL; |
+ if (!IsJSArrayWithFastElements(receiver, &elms) |
+ || !ArrayPrototypeHasNoElements()) { |
return CallJsBuiltin("ArrayUnshift", args); |
} |
- |
- JSArray* array = JSArray::cast(*args.receiver()); |
+ JSArray* array = JSArray::cast(receiver); |
ASSERT(array->HasFastElements()); |
int len = Smi::cast(array->length())->value(); |
@@ -469,8 +495,6 @@ BUILTIN(ArrayUnshift) { |
// we should never hit this case. |
ASSERT(to_add <= (Smi::kMaxValue - len)); |
- FixedArray* elms = FixedArray::cast(array->elements()); |
- |
if (new_length > elms->length()) { |
// New backing storage is needed. |
int capacity = new_length + (new_length >> 1) + 16; |
@@ -503,11 +527,13 @@ BUILTIN(ArrayUnshift) { |
BUILTIN(ArraySlice) { |
- if (!ArrayPrototypeHasNoElements()) { |
+ Object* receiver = *args.receiver(); |
+ FixedArray* elms = NULL; |
+ if (!IsJSArrayWithFastElements(receiver, &elms) |
+ || !ArrayPrototypeHasNoElements()) { |
return CallJsBuiltin("ArraySlice", args); |
} |
- |
- JSArray* array = JSArray::cast(*args.receiver()); |
+ JSArray* array = JSArray::cast(receiver); |
ASSERT(array->HasFastElements()); |
int len = Smi::cast(array->length())->value(); |
@@ -558,8 +584,6 @@ BUILTIN(ArraySlice) { |
if (result->IsFailure()) return result; |
FixedArray* result_elms = FixedArray::cast(result); |
- FixedArray* elms = FixedArray::cast(array->elements()); |
- |
AssertNoAllocation no_gc; |
CopyElements(&no_gc, result_elms, 0, elms, k, result_len); |
@@ -573,11 +597,13 @@ BUILTIN(ArraySlice) { |
BUILTIN(ArraySplice) { |
- if (!ArrayPrototypeHasNoElements()) { |
+ Object* receiver = *args.receiver(); |
+ FixedArray* elms = NULL; |
+ if (!IsJSArrayWithFastElements(receiver, &elms) |
+ || !ArrayPrototypeHasNoElements()) { |
return CallJsBuiltin("ArraySplice", args); |
} |
- |
- JSArray* array = JSArray::cast(*args.receiver()); |
+ JSArray* array = JSArray::cast(receiver); |
ASSERT(array->HasFastElements()); |
int len = Smi::cast(array->length())->value(); |
@@ -618,8 +644,6 @@ BUILTIN(ArraySplice) { |
} |
int actual_delete_count = Min(Max(delete_count, 0), len - actual_start); |
- FixedArray* elms = FixedArray::cast(array->elements()); |
- |
JSArray* result_array = NULL; |
if (actual_delete_count == 0) { |
Object* result = AllocateEmptyJSArray(); |