Move the contains check in array join from javascript to C++.
authorager@chromium.org <ager@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 9 Sep 2008 07:38:00 +0000 (07:38 +0000)
committerager@chromium.org <ager@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 9 Sep 2008 07:38:00 +0000 (07:38 +0000)
git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@224 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/array.js
src/runtime.cc
src/runtime.h

index b532ef1..6f229c0 100644 (file)
@@ -111,8 +111,7 @@ function Join(array, length, separator, convert) {
   if (is_array) {
     // If the array is cyclic, return the empty string for already
     // visited arrays.
-    if (Contains(visited_arrays, array)) return '';
-    visited_arrays[visited_arrays.length] = array;
+    if (!%PushIfAbsent(visited_arrays, array)) return '';
   }
 
   // Attempt to convert the elements.
@@ -702,17 +701,17 @@ function ArraySort(comparefn) {
     while (true) {
       var child_index = ((parent_index + 1) << 1) - 1;
       if (child_index >= i) break;
-      var child1_value = this[child_index]; 
+      var child1_value = this[child_index];
       var child2_value = this[child_index + 1];
       var parent_value = this[parent_index];
       if (child_index + 1 >= i || Compare(child1_value, child2_value) > 0) {
         if (Compare(parent_value, child1_value) > 0) break;
-        this[child_index] = parent_value; 
+        this[child_index] = parent_value;
         this[parent_index] = child1_value;
         parent_index = child_index;
       } else {
         if (Compare(parent_value, child2_value) > 0) break;
-        this[child_index + 1] = parent_value; 
+        this[child_index + 1] = parent_value;
         this[parent_index] = child2_value;
         parent_index = child_index + 1;
       }
index 870e8b7..88e9101 100644 (file)
@@ -3443,6 +3443,25 @@ static Object* Runtime_SetNewFunctionAttributes(Arguments args) {
 }
 
 
+// Push an array unto an array of arrays if it is not already in the
+// array.  Returns true if the element was pushed on the stack and
+// false otherwise.
+static Object* Runtime_PushIfAbsent(Arguments args) {
+  ASSERT(args.length == 2);
+  CONVERT_CHECKED(JSArray, array, args[0]);
+  CONVERT_CHECKED(JSArray, element, args[1]);
+  CHECK(array->HasFastElements());
+  int length = Smi::cast(array->length())->value();
+  FixedArray* elements = FixedArray::cast(array->elements());
+  for (int i = 0; i < length; i++) {
+    if (elements->get(i) == element) return Heap::false_value();
+  }
+  Object* obj = array->SetFastElement(length, element);
+  if (obj->IsFailure()) return obj;
+  return Heap::true_value();
+}
+
+
 // This will not allocate (flatten the string), but it may run
 // very slowly for very deeply nested ConsStrings.  For debugging use only.
 static Object* Runtime_GlobalPrint(Arguments args) {
index afb5179..fbeaed5 100644 (file)
@@ -61,6 +61,9 @@ namespace v8 { namespace internal {
   F(LazyCompile, 1) \
   F(SetNewFunctionAttributes, 1) \
   \
+  /* Array join support */ \
+  F(PushIfAbsent, 2) \
+  \
   /* ConsStrings */ \
   F(ConsStringFst, 1) \
   F(ConsStringSnd, 1) \