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.
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;
}
}
+// 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) {