| Index: src/builtins.cc
|
| diff --git a/src/builtins.cc b/src/builtins.cc
|
| index 3a0393efbc593c7e3b0d2c8ed39428dddb177004..437bc1e6c1531de9e006c9d3fca766ef673d9e1b 100644
|
| --- a/src/builtins.cc
|
| +++ b/src/builtins.cc
|
| @@ -269,6 +269,7 @@ static void CopyElements(AssertNoAllocation* no_gc,
|
| int src_index,
|
| int len) {
|
| ASSERT(dst != src); // Use MoveElements instead.
|
| + ASSERT(dst->map() != Heap::fixed_cow_array_map());
|
| ASSERT(len > 0);
|
| CopyWords(dst->data_start() + dst_index,
|
| src->data_start() + src_index,
|
| @@ -286,6 +287,7 @@ static void MoveElements(AssertNoAllocation* no_gc,
|
| FixedArray* src,
|
| int src_index,
|
| int len) {
|
| + ASSERT(dst->map() != Heap::fixed_cow_array_map());
|
| memmove(dst->data_start() + dst_index,
|
| src->data_start() + src_index,
|
| len * kPointerSize);
|
| @@ -297,11 +299,13 @@ static void MoveElements(AssertNoAllocation* no_gc,
|
|
|
|
|
| static void FillWithHoles(FixedArray* dst, int from, int to) {
|
| + ASSERT(dst->map() != Heap::fixed_cow_array_map());
|
| MemsetPointer(dst->data_start() + from, Heap::the_hole_value(), to - from);
|
| }
|
|
|
|
|
| static FixedArray* LeftTrimFixedArray(FixedArray* elms, int to_trim) {
|
| + ASSERT(elms->map() != Heap::fixed_cow_array_map());
|
| // For now this trick is only applied to fixed arrays in new space.
|
| // In large object space the object's start must coincide with chunk
|
| // and thus the trick is just not applicable.
|
| @@ -348,33 +352,24 @@ static bool ArrayPrototypeHasNoElements(Context* global_context,
|
| }
|
|
|
|
|
| -static bool IsJSArrayWithFastElements(Object* receiver,
|
| - FixedArray** elements) {
|
| - if (!receiver->IsJSArray()) {
|
| - return false;
|
| - }
|
| -
|
| +static Object* EnsureJSArrayWithWritableFastElements(Object* receiver) {
|
| + if (!receiver->IsJSArray()) return NULL;
|
| JSArray* array = JSArray::cast(receiver);
|
| -
|
| HeapObject* elms = HeapObject::cast(array->elements());
|
| - if (elms->map() != Heap::fixed_array_map()) {
|
| - return false;
|
| + if (elms->map() == Heap::fixed_array_map()) return elms;
|
| + if (elms->map() == Heap::fixed_cow_array_map()) {
|
| + return array->EnsureWritableFastElements();
|
| }
|
| -
|
| - *elements = FixedArray::cast(elms);
|
| - return true;
|
| + return NULL;
|
| }
|
|
|
|
|
| -static bool IsFastElementMovingAllowed(Object* receiver,
|
| - FixedArray** elements) {
|
| - if (!IsJSArrayWithFastElements(receiver, elements)) return false;
|
| -
|
| +static bool IsJSArrayFastElementMovingAllowed(JSArray* receiver) {
|
| Context* global_context = Top::context()->global_context();
|
| JSObject* array_proto =
|
| JSObject::cast(global_context->array_function()->prototype());
|
| - if (JSArray::cast(receiver)->GetPrototype() != array_proto) return false;
|
| - return ArrayPrototypeHasNoElements(global_context, array_proto);
|
| + return receiver->GetPrototype() == array_proto &&
|
| + ArrayPrototypeHasNoElements(global_context, array_proto);
|
| }
|
|
|
|
|
| @@ -405,10 +400,10 @@ static Object* CallJsBuiltin(const char* name,
|
|
|
| BUILTIN(ArrayPush) {
|
| Object* receiver = *args.receiver();
|
| - FixedArray* elms = NULL;
|
| - if (!IsJSArrayWithFastElements(receiver, &elms)) {
|
| - return CallJsBuiltin("ArrayPush", args);
|
| - }
|
| + Object* elms_obj = EnsureJSArrayWithWritableFastElements(receiver);
|
| + if (elms_obj == NULL) return CallJsBuiltin("ArrayPush", args);
|
| + if (elms_obj->IsFailure()) return elms_obj;
|
| + FixedArray* elms = FixedArray::cast(elms_obj);
|
| JSArray* array = JSArray::cast(receiver);
|
|
|
| int len = Smi::cast(array->length())->value();
|
| @@ -454,10 +449,10 @@ BUILTIN(ArrayPush) {
|
|
|
| BUILTIN(ArrayPop) {
|
| Object* receiver = *args.receiver();
|
| - FixedArray* elms = NULL;
|
| - if (!IsJSArrayWithFastElements(receiver, &elms)) {
|
| - return CallJsBuiltin("ArrayPop", args);
|
| - }
|
| + Object* elms_obj = EnsureJSArrayWithWritableFastElements(receiver);
|
| + if (elms_obj == NULL) return CallJsBuiltin("ArrayPop", args);
|
| + if (elms_obj->IsFailure()) return elms_obj;
|
| + FixedArray* elms = FixedArray::cast(elms_obj);
|
| JSArray* array = JSArray::cast(receiver);
|
|
|
| int len = Smi::cast(array->length())->value();
|
| @@ -483,10 +478,13 @@ BUILTIN(ArrayPop) {
|
|
|
| BUILTIN(ArrayShift) {
|
| Object* receiver = *args.receiver();
|
| - FixedArray* elms = NULL;
|
| - if (!IsFastElementMovingAllowed(receiver, &elms)) {
|
| + Object* elms_obj = EnsureJSArrayWithWritableFastElements(receiver);
|
| + if (elms_obj->IsFailure()) return elms_obj;
|
| + if (elms_obj == NULL ||
|
| + !IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) {
|
| return CallJsBuiltin("ArrayShift", args);
|
| }
|
| + FixedArray* elms = FixedArray::cast(elms_obj);
|
| JSArray* array = JSArray::cast(receiver);
|
| ASSERT(array->HasFastElements());
|
|
|
| @@ -519,10 +517,13 @@ BUILTIN(ArrayShift) {
|
|
|
| BUILTIN(ArrayUnshift) {
|
| Object* receiver = *args.receiver();
|
| - FixedArray* elms = NULL;
|
| - if (!IsFastElementMovingAllowed(receiver, &elms)) {
|
| + Object* elms_obj = EnsureJSArrayWithWritableFastElements(receiver);
|
| + if (elms_obj->IsFailure()) return elms_obj;
|
| + if (elms_obj == NULL ||
|
| + !IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) {
|
| return CallJsBuiltin("ArrayUnshift", args);
|
| }
|
| + FixedArray* elms = FixedArray::cast(elms_obj);
|
| JSArray* array = JSArray::cast(receiver);
|
| ASSERT(array->HasFastElements());
|
|
|
| @@ -568,10 +569,13 @@ BUILTIN(ArrayUnshift) {
|
|
|
| BUILTIN(ArraySlice) {
|
| Object* receiver = *args.receiver();
|
| - FixedArray* elms = NULL;
|
| - if (!IsFastElementMovingAllowed(receiver, &elms)) {
|
| + Object* elms_obj = EnsureJSArrayWithWritableFastElements(receiver);
|
| + if (elms_obj->IsFailure()) return 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());
|
|
|
| @@ -637,10 +641,13 @@ BUILTIN(ArraySlice) {
|
|
|
| BUILTIN(ArraySplice) {
|
| Object* receiver = *args.receiver();
|
| - FixedArray* elms = NULL;
|
| - if (!IsFastElementMovingAllowed(receiver, &elms)) {
|
| + Object* elms_obj = EnsureJSArrayWithWritableFastElements(receiver);
|
| + if (elms_obj->IsFailure()) return elms_obj;
|
| + if (elms_obj == NULL ||
|
| + !IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) {
|
| return CallJsBuiltin("ArraySplice", args);
|
| }
|
| + FixedArray* elms = FixedArray::cast(elms_obj);
|
| JSArray* array = JSArray::cast(receiver);
|
| ASSERT(array->HasFastElements());
|
|
|
|
|