Add Array.concat builtin for the most common case.
authorantonm@chromium.org <antonm@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 15 Mar 2010 10:52:38 +0000 (10:52 +0000)
committerantonm@chromium.org <antonm@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 15 Mar 2010 10:52:38 +0000 (10:52 +0000)
Review URL: http://codereview.chromium.org/954001

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4129 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/array.js
src/builtins.cc
src/builtins.h
src/runtime.cc
src/v8-counters.h

index 86784a323a91ead7cd59592af52711996877b58b..a29015a5ef8233634734d9f8fc4ea6e7a0034e33 100644 (file)
@@ -1133,7 +1133,7 @@ function SetupArray() {
     "join", getFunction("join", ArrayJoin),
     "pop", getFunction("pop", ArrayPop),
     "push", getFunction("push", ArrayPush, 1),
-    "concat", getFunction("concat", ArrayConcat),
+    "concat", getFunction("concat", ArrayConcat, 1),
     "reverse", getFunction("reverse", ArrayReverse),
     "shift", getFunction("shift", ArrayShift),
     "unshift", getFunction("unshift", ArrayUnshift, 1),
index e59dbcf29d2168080c95e4cac648ab033d3a8ee9..4166b7121d269c5d38091cccf1b753425f306b00 100644 (file)
@@ -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;
+}
+
+
 // -----------------------------------------------------------------------------
 //
 
index 595e9a4b8b52f3df36669e1ae4d4da648c8100b4..1378c5455c6049cd78f216add18de5b26559da4a 100644 (file)
@@ -52,6 +52,7 @@ enum BuiltinExtraArguments {
   V(ArrayUnshift, NO_EXTRA_ARGUMENTS)                               \
   V(ArraySlice, NO_EXTRA_ARGUMENTS)                                 \
   V(ArraySplice, NO_EXTRA_ARGUMENTS)                                \
+  V(ArrayConcat, NO_EXTRA_ARGUMENTS)                                \
                                                                     \
   V(HandleApiCall, NEEDS_CALLED_FUNCTION)                           \
   V(FastHandleApiCall, NO_EXTRA_ARGUMENTS)                          \
index 61534d3571dcb8111a66c4ae45d618d130f58d39..72f7cf4b266b95cfc835118669885f2c63d86e2c 100644 (file)
@@ -1297,6 +1297,7 @@ static Object* Runtime_SpecialArrayFunctions(Arguments args) {
   InstallBuiltin(holder, "unshift", Builtins::ArrayUnshift);
   InstallBuiltin(holder, "slice", Builtins::ArraySlice);
   InstallBuiltin(holder, "splice", Builtins::ArraySplice);
+  InstallBuiltin(holder, "concat", Builtins::ArrayConcat);
 
   return *holder;
 }
index b595cd4922c2739b6b537c68a33507891d97f955..c1400ae4047f1b091c32d549a03499581cc740eb 100644 (file)
@@ -151,6 +151,8 @@ namespace internal {
   SC(constructed_objects_stub, V8.ConstructedObjectsStub)             \
   SC(array_function_runtime, V8.ArrayFunctionRuntime)                 \
   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(enum_cache_hits, V8.EnumCacheHits)                               \
   SC(enum_cache_misses, V8.EnumCacheMisses)                           \