Commit c2dc3161 authored by antonm@chromium.org's avatar antonm@chromium.org

Add Array.concat builtin for the most common case.

Review URL: http://codereview.chromium.org/954001

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4129 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 27c737bb
...@@ -1133,7 +1133,7 @@ function SetupArray() { ...@@ -1133,7 +1133,7 @@ function SetupArray() {
"join", getFunction("join", ArrayJoin), "join", getFunction("join", ArrayJoin),
"pop", getFunction("pop", ArrayPop), "pop", getFunction("pop", ArrayPop),
"push", getFunction("push", ArrayPush, 1), "push", getFunction("push", ArrayPush, 1),
"concat", getFunction("concat", ArrayConcat), "concat", getFunction("concat", ArrayConcat, 1),
"reverse", getFunction("reverse", ArrayReverse), "reverse", getFunction("reverse", ArrayReverse),
"shift", getFunction("shift", ArrayShift), "shift", getFunction("shift", ArrayShift),
"unshift", getFunction("unshift", ArrayUnshift, 1), "unshift", getFunction("unshift", ArrayUnshift, 1),
......
...@@ -727,6 +727,63 @@ BUILTIN(ArraySplice) { ...@@ -727,6 +727,63 @@ BUILTIN(ArraySplice) {
} }
BUILTIN(ArrayConcat) {
Counters::array_concat_builtin_total.Increment();
if (args.length() != 2) {
// Fast case only for concating two arrays.
return CallJsBuiltin("ArrayConcat", args);
}
Counters::array_concat_builtin_two_args.Increment();
Object* receiver_obj = *args.receiver();
FixedArray* receiver_elms = NULL;
Object* arg_obj = args[1];
FixedArray* arg_elms = NULL;
if (!IsJSArrayWithFastElements(receiver_obj, &receiver_elms)
|| !IsJSArrayWithFastElements(arg_obj, &arg_elms)
|| !ArrayPrototypeHasNoElements()) {
return CallJsBuiltin("ArrayConcat", args);
}
JSArray* receiver_array = JSArray::cast(receiver_obj);
ASSERT(receiver_array->HasFastElements());
JSArray* arg_array = JSArray::cast(arg_obj);
ASSERT(arg_array->HasFastElements());
int receiver_len = Smi::cast(receiver_array->length())->value();
int arg_len = Smi::cast(arg_array->length())->value();
ASSERT(receiver_len <= (Smi::kMaxValue - arg_len));
int result_len = receiver_len + arg_len;
if (result_len > FixedArray::kMaxSize) {
return CallJsBuiltin("ArrayConcat", args);
}
if (result_len == 0) {
return AllocateEmptyJSArray();
}
// Allocate result.
Object* result = AllocateJSArray();
if (result->IsFailure()) return result;
JSArray* result_array = JSArray::cast(result);
result = Heap::AllocateUninitializedFixedArray(result_len);
if (result->IsFailure()) return result;
FixedArray* result_elms = FixedArray::cast(result);
// Copy data.
AssertNoAllocation no_gc;
CopyElements(&no_gc, result_elms, 0, receiver_elms, 0, receiver_len);
CopyElements(&no_gc, result_elms, receiver_len, arg_elms, 0, arg_len);
// Set the length and elements.
result_array->set_length(Smi::FromInt(result_len));
result_array->set_elements(result_elms);
return result_array;
}
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// //
......
...@@ -52,6 +52,7 @@ enum BuiltinExtraArguments { ...@@ -52,6 +52,7 @@ enum BuiltinExtraArguments {
V(ArrayUnshift, NO_EXTRA_ARGUMENTS) \ V(ArrayUnshift, NO_EXTRA_ARGUMENTS) \
V(ArraySlice, NO_EXTRA_ARGUMENTS) \ V(ArraySlice, NO_EXTRA_ARGUMENTS) \
V(ArraySplice, NO_EXTRA_ARGUMENTS) \ V(ArraySplice, NO_EXTRA_ARGUMENTS) \
V(ArrayConcat, NO_EXTRA_ARGUMENTS) \
\ \
V(HandleApiCall, NEEDS_CALLED_FUNCTION) \ V(HandleApiCall, NEEDS_CALLED_FUNCTION) \
V(FastHandleApiCall, NO_EXTRA_ARGUMENTS) \ V(FastHandleApiCall, NO_EXTRA_ARGUMENTS) \
......
...@@ -1297,6 +1297,7 @@ static Object* Runtime_SpecialArrayFunctions(Arguments args) { ...@@ -1297,6 +1297,7 @@ static Object* Runtime_SpecialArrayFunctions(Arguments args) {
InstallBuiltin(holder, "unshift", Builtins::ArrayUnshift); InstallBuiltin(holder, "unshift", Builtins::ArrayUnshift);
InstallBuiltin(holder, "slice", Builtins::ArraySlice); InstallBuiltin(holder, "slice", Builtins::ArraySlice);
InstallBuiltin(holder, "splice", Builtins::ArraySplice); InstallBuiltin(holder, "splice", Builtins::ArraySplice);
InstallBuiltin(holder, "concat", Builtins::ArrayConcat);
return *holder; return *holder;
} }
......
...@@ -151,6 +151,8 @@ namespace internal { ...@@ -151,6 +151,8 @@ namespace internal {
SC(constructed_objects_stub, V8.ConstructedObjectsStub) \ SC(constructed_objects_stub, V8.ConstructedObjectsStub) \
SC(array_function_runtime, V8.ArrayFunctionRuntime) \ SC(array_function_runtime, V8.ArrayFunctionRuntime) \
SC(array_function_native, V8.ArrayFunctionNative) \ SC(array_function_native, V8.ArrayFunctionNative) \
SC(array_concat_builtin_total, V8.ArrayConcatTotal) \
SC(array_concat_builtin_two_args, V8.ArrayConcatTwoArgs) \
SC(for_in, V8.ForIn) \ SC(for_in, V8.ForIn) \
SC(enum_cache_hits, V8.EnumCacheHits) \ SC(enum_cache_hits, V8.EnumCacheHits) \
SC(enum_cache_misses, V8.EnumCacheMisses) \ SC(enum_cache_misses, V8.EnumCacheMisses) \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment