Index: src/builtins.cc |
diff --git a/src/builtins.cc b/src/builtins.cc |
index c68de9ac794adc7b37fa23530fc822ca5bf70d8e..e8e7109d19d9610eac690e268503291bc1f2a989 100644 |
--- a/src/builtins.cc |
+++ b/src/builtins.cc |
@@ -419,6 +419,110 @@ BUILTIN(ArrayUnshift) { |
} |
+static Object* SlowArraySlice(Handle<Object> receiver, |
+ Object** arg0, |
+ Object** arg1 = NULL) { |
+ HandleScope handleScope; |
+ |
+ Handle<Object> slow_slice = |
+ GetProperty(Handle<JSObject>(Top::global_context()->builtins()), |
+ "ArraySlice"); |
+ ASSERT(slow_slice->IsJSFunction()); |
+ Handle<JSFunction> function(Handle<JSFunction>::cast(slow_slice)); |
+ Object** args[] = { arg0, arg1 }; |
+ bool pending_exception = false; |
+ Handle<Object> result = Execution::Call(function, |
+ receiver, |
+ arg1 == NULL ? 1 : 2, |
+ args, |
+ &pending_exception); |
+ if (pending_exception) return Failure::Exception(); |
+ return *result; |
+} |
+ |
+ |
+BUILTIN(ArraySlice) { |
+ JSArray* array = JSArray::cast(*args.receiver()); |
+ ASSERT(array->HasFastElements()); |
+ |
+ int len = Smi::cast(array->length())->value(); |
+ |
+ int n_arguments = args.length() - 1; |
+ |
+ // Note carefully choosen defaults---if argument is missing, |
+ // it's undefined which gets converted to 0 for relativeStart |
+ // and to len for relativeEnd. |
+ int relativeStart = 0; |
+ int relativeEnd = len; |
+ if (n_arguments > 0) { |
+ Object* arg1 = args[1]; |
+ if (arg1->IsSmi()) { |
+ relativeStart = Smi::cast(arg1)->value(); |
+ } else if (!arg1->IsUndefined()) { |
+ if (n_arguments > 1) { |
+ return SlowArraySlice(args.receiver(), &args[1], &args[2]); |
+ } else { |
+ return SlowArraySlice(args.receiver(), &args[1]); |
+ } |
+ } |
+ if (n_arguments > 1) { |
+ Object* arg2 = args[2]; |
+ if (arg2->IsSmi()) { |
+ relativeEnd = Smi::cast(arg2)->value(); |
+ } else if (!arg2->IsUndefined()) { |
+ return SlowArraySlice(args.receiver(), &args[1], &args[2]); |
+ } |
+ } |
+ } |
+ |
+ // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 6. |
+ int k = (relativeStart < 0) ? Max(len + relativeStart, 0) |
+ : Min(relativeStart, len); |
+ |
+ // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 8. |
+ int final = (relativeEnd < 0) ? Max(len + relativeEnd, 0) |
+ : Min(relativeEnd, len); |
+ |
+ // Calculate the length of result array. |
+ int result_len = final - k; |
+ if (result_len < 0) { |
+ result_len = 0; |
+ } |
+ |
+ JSFunction* array_function = |
+ Top::context()->global_context()->array_function(); |
+ Object* result = Heap::AllocateJSObject(array_function); |
+ if (result->IsFailure()) return result; |
+ JSArray* result_array = JSArray::cast(result); |
+ |
+ result = Heap::AllocateFixedArrayWithHoles(result_len); |
+ if (result->IsFailure()) return result; |
+ FixedArray* result_elms = FixedArray::cast(result); |
+ |
+ FixedArray* elms = FixedArray::cast(array->elements()); |
+ |
+ // Fetch the prototype. |
+ JSObject* prototype = JSObject::cast(array_function->prototype()); |
+ |
+ AssertNoAllocation no_gc; |
+ WriteBarrierMode mode = result_elms->GetWriteBarrierMode(no_gc); |
+ |
+ // Fill newly created array. |
+ for (int i = 0; i < result_len; i++) { |
+ result_elms->set(i, |
+ GetElementToMove(k + i, elms, prototype), |
+ mode); |
+ } |
+ |
+ // Set elements. |
+ result_array->set_elements(result_elms); |
+ |
+ // Set the length. |
+ result_array->set_length(Smi::FromInt(result_len)); |
+ return result_array; |
+} |
+ |
+ |
// ----------------------------------------------------------------------------- |
// |