Index: src/builtins.cc |
diff --git a/src/builtins.cc b/src/builtins.cc |
index d14953028e693c9a22ca4299fc0169ff2d9501bd..70edff136683d6b477bdf0be15d2cafba47fc39c 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; |
@@ -345,8 +363,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; |
@@ -358,7 +380,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. |
@@ -389,14 +410,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. |
@@ -419,18 +443,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()) { |
@@ -450,11 +474,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(); |
@@ -468,8 +494,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; |
@@ -502,11 +526,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(); |
@@ -557,8 +583,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); |
@@ -572,11 +596,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(); |
@@ -626,8 +652,6 @@ BUILTIN(ArraySplice) { |
if (result->IsFailure()) return result; |
FixedArray* result_elms = FixedArray::cast(result); |
- FixedArray* elms = FixedArray::cast(array->elements()); |
- |
AssertNoAllocation no_gc; |
// Fill newly created array. |
CopyElements(&no_gc, result_elms, 0, elms, actualStart, actualDeleteCount); |