| 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);
|
|
|