Revision: 22595
Author: [email protected]
Date: Thu Jul 24 12:08:23 2014 UTC
Log: Keep new arrays allocated with 'new Array(N)' in fast mode
Also explicit length setting with a.length = N should remain in fast mode.
[email protected]
Review URL: https://codereview.chromium.org/397593008
http://code.google.com/p/v8/source/detail?r=22595
Modified:
/branches/bleeding_edge/src/elements.cc
/branches/bleeding_edge/src/objects.cc
/branches/bleeding_edge/src/runtime.cc
/branches/bleeding_edge/src/runtime.h
/branches/bleeding_edge/test/fuzz-natives/base.js
/branches/bleeding_edge/test/mjsunit/allocation-site-info.js
/branches/bleeding_edge/test/mjsunit/apply.js
/branches/bleeding_edge/test/mjsunit/array-constructor-feedback.js
/branches/bleeding_edge/test/mjsunit/array-feedback.js
/branches/bleeding_edge/test/mjsunit/array-splice.js
/branches/bleeding_edge/test/mjsunit/array-unshift.js
/branches/bleeding_edge/test/mjsunit/elements-kind.js
/branches/bleeding_edge/test/mjsunit/es7/object-observe.js
/branches/bleeding_edge/test/mjsunit/polymorph-arrays.js
/branches/bleeding_edge/test/mjsunit/regress/regress-2790.js
/branches/bleeding_edge/tools/generate-runtime-tests.py
=======================================
--- /branches/bleeding_edge/src/elements.cc Fri Jun 13 12:12:42 2014 UTC
+++ /branches/bleeding_edge/src/elements.cc Thu Jul 24 12:08:23 2014 UTC
@@ -897,8 +897,7 @@
typedef typename KindTraits::BackingStore BackingStore;
- // Adjusts the length of the fast backing store or returns the new
length or
- // undefined in case conversion to a slow backing store should be
performed.
+ // Adjusts the length of the fast backing store..
static Handle<Object> SetLengthWithoutNormalize(
Handle<FixedArrayBase> backing_store,
Handle<JSArray> array,
@@ -950,15 +949,10 @@
// Check whether the backing store should be expanded.
uint32_t min = JSObject::NewElementsCapacity(old_capacity);
uint32_t new_capacity = length > min ? length : min;
- if (!array->ShouldConvertToSlowElements(new_capacity)) {
- FastElementsAccessorSubclass::
- SetFastElementsCapacityAndLength(array, new_capacity, length);
- JSObject::ValidateElements(array);
- return length_object;
- }
-
- // Request conversion to slow elements.
- return isolate->factory()->undefined_value();
+ FastElementsAccessorSubclass::SetFastElementsCapacityAndLength(
+ array, new_capacity, length);
+ JSObject::ValidateElements(array);
+ return length_object;
}
static Handle<Object> DeleteCommon(Handle<JSObject> obj,
=======================================
--- /branches/bleeding_edge/src/objects.cc Thu Jul 24 11:33:46 2014 UTC
+++ /branches/bleeding_edge/src/objects.cc Thu Jul 24 12:08:23 2014 UTC
@@ -11720,6 +11720,17 @@
MaybeHandle<Object> JSArray::SetElementsLength(
Handle<JSArray> array,
Handle<Object> new_length_handle) {
+ if (array->HasFastElements()) {
+ // If the new array won't fit in a some non-trivial fraction of the
max old
+ // space size, then force it to go dictionary mode.
+ int max_fast_array_size = static_cast<int>(
+ (array->GetHeap()->MaxOldGenerationSize() / kDoubleSize) / 4);
+ if (new_length_handle->IsNumber() &&
+ NumberToInt32(*new_length_handle) >= max_fast_array_size) {
+ NormalizeElements(array);
+ }
+ }
+
// We should never end in here with a pixel or external array.
ASSERT(array->AllowsSetElementsLength());
if (!array->map()->is_observed()) {
=======================================
--- /branches/bleeding_edge/src/runtime.cc Wed Jul 23 07:33:47 2014 UTC
+++ /branches/bleeding_edge/src/runtime.cc Thu Jul 24 12:08:23 2014 UTC
@@ -10576,7 +10576,30 @@
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSObject, array, 0);
CONVERT_NUMBER_CHECKED(uint32_t, length, Uint32, args[1]);
- if (array->elements()->IsDictionary()) {
+
+ ElementsKind kind = array->GetElementsKind();
+ bool estimate_keys_as_length = IsFastPackedElementsKind(kind);
+ if (IsHoleyElementsKind(kind)) {
+ ElementsAccessor* accessor = array->GetElementsAccessor();
+ // If more than 10% of the array is holes, then calculate the key set,
it's
+ // much faster than using the runtime to walk the prototype chain in
the
+ // hole case.
+ int holes = 0;
+ int length = array->elements()->length();
+ for (int i = 0; i < length; ++i) {
+ if (!accessor->HasElement(array, array, i)) {
+ ++holes;
+ }
+ }
+ estimate_keys_as_length = holes < static_cast<int>(length / 10);
+ }
+
+ if (estimate_keys_as_length) {
+ RUNTIME_ASSERT(array->HasFastSmiOrObjectElements() ||
+ array->HasFastDoubleElements());
+ uint32_t actual_length =
static_cast<uint32_t>(array->elements()->length());
+ return *isolate->factory()->NewNumberFromUint(Min(actual_length,
length));
+ } else {
Handle<FixedArray> keys = isolate->factory()->empty_fixed_array();
for (PrototypeIterator iter(isolate, array,
PrototypeIterator::START_AT_RECEIVER);
@@ -10603,11 +10626,6 @@
if (NumberToUint32(keys->get(i)) >= length) keys->set_undefined(i);
}
return *isolate->factory()->NewJSArrayWithElements(keys);
- } else {
- RUNTIME_ASSERT(array->HasFastSmiOrObjectElements() ||
- array->HasFastDoubleElements());
- uint32_t actual_length =
static_cast<uint32_t>(array->elements()->length());
- return *isolate->factory()->NewNumberFromUint(Min(actual_length,
length));
}
}
@@ -14929,6 +14947,15 @@
Handle<AllocationSite>::null(),
caller_args);
}
+
+
+RUNTIME_FUNCTION(Runtime_NormalizeElements) {
+ HandleScope scope(isolate);
+ ASSERT(args.length() == 1);
+ CONVERT_ARG_HANDLE_CHECKED(JSObject, array, 0);
+ JSObject::NormalizeElements(array);
+ return *array;
+}
RUNTIME_FUNCTION(Runtime_MaxSmi) {
=======================================
--- /branches/bleeding_edge/src/runtime.h Wed Jul 23 07:33:47 2014 UTC
+++ /branches/bleeding_edge/src/runtime.h Thu Jul 24 12:08:23 2014 UTC
@@ -440,6 +440,7 @@
/* Arrays */ \
F(ArrayConstructor, -1, 1) \
F(InternalArrayConstructor, -1, 1) \
+ F(NormalizeElements, 1, 1) \
\
/* Literals */ \
F(MaterializeRegExpLiteral, 4, 1) \
=======================================
--- /branches/bleeding_edge/test/fuzz-natives/base.js Wed May 7 12:31:26
2014 UTC
+++ /branches/bleeding_edge/test/fuzz-natives/base.js Thu Jul 24 12:08:23
2014 UTC
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Flags: --allow-natives-syntax
+
// TODO(jkummerow): There are many ways to improve these tests, e.g.:
// - more variance in randomized inputs
// - better time complexity management
@@ -15,7 +17,9 @@
result.push(17);
result.push(-31);
result.push(new Array(100));
- result.push(new Array(100003));
+ var a = %NormalizeElements([]);
+ a.length = 100003;
+ result.push(a);
result.push(Number.MIN_VALUE);
result.push("whoops");
result.push("x");
=======================================
--- /branches/bleeding_edge/test/mjsunit/allocation-site-info.js Fri Jul 18
07:17:21 2014 UTC
+++ /branches/bleeding_edge/test/mjsunit/allocation-site-info.js Thu Jul 24
12:08:23 2014 UTC
@@ -297,10 +297,6 @@
assertKind(elements_kind.fast_double, obj);
obj = newarraycase_onearg(0, 5);
assertKind(elements_kind.fast_double, obj);
-// Now pass a length that forces the dictionary path.
-obj = newarraycase_onearg(100000, 5);
-assertKind(elements_kind.dictionary, obj);
-assertTrue(obj.length == 100000);
// Verify that cross context calls work
var realmA = Realm.current();
=======================================
--- /branches/bleeding_edge/test/mjsunit/apply.js Wed Oct 19 13:56:18 2011
UTC
+++ /branches/bleeding_edge/test/mjsunit/apply.js Thu Jul 24 12:08:23 2014
UTC
@@ -25,6 +25,8 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// Flags: --allow-natives-syntax
+
function f0() {
return this;
}
@@ -114,7 +116,8 @@
for (var j = 1; j < 0x40000000; j <<= 1) {
try {
- var a = new Array(j);
+ var a = %NormalizeElements([]);
+ a.length = j;
a[j - 1] = 42;
assertEquals(42 + j, al.apply(345, a));
} catch (e) {
@@ -122,7 +125,8 @@
for (; j < 0x40000000; j <<= 1) {
var caught = false;
try {
- a = new Array(j);
+ a = %NormalizeElements([]);
+ a.length = j;
a[j - 1] = 42;
al.apply(345, a);
assertUnreachable("Apply of array with length " + a.length +
=======================================
--- /branches/bleeding_edge/test/mjsunit/array-constructor-feedback.js Fri
Jul 18 07:17:21 2014 UTC
+++ /branches/bleeding_edge/test/mjsunit/array-constructor-feedback.js Thu
Jul 24 12:08:23 2014 UTC
@@ -130,8 +130,7 @@
a = bar(10);
assertKind(elements_kind.fast, a);
assertOptimized(bar);
- a = bar(100000);
- assertKind(elements_kind.dictionary, a);
+ bar(100000);
assertOptimized(bar);
// If the argument isn't a smi, things should still work.
=======================================
--- /branches/bleeding_edge/test/mjsunit/array-feedback.js Fri Jul 18
07:17:21 2014 UTC
+++ /branches/bleeding_edge/test/mjsunit/array-feedback.js Thu Jul 24
12:08:23 2014 UTC
@@ -92,7 +92,7 @@
assertKind(elements_kind.fast, b);
a = create1(100000);
- assertKind(elements_kind.dictionary, a);
+ assertKind(elements_kind.fast_smi_only, a);
function create3(arg1, arg2, arg3) {
return Array(arg1, arg2, arg3);
=======================================
--- /branches/bleeding_edge/test/mjsunit/array-splice.js Fri Mar 22
15:08:30 2013 UTC
+++ /branches/bleeding_edge/test/mjsunit/array-splice.js Thu Jul 24
12:08:23 2014 UTC
@@ -25,6 +25,8 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// Flags: --allow-natives-syntax
+
// Check that splicing array of holes keeps it as array of holes
(function() {
for (var i = 0; i < 7; i++) {
@@ -357,7 +359,9 @@
(function() {
for (var i = 0; i < 7; i++) {
try {
- new Array(Math.pow(2, 32) - 3).splice(-1, 0, 1, 2, 3, 4, 5);
+ var a = %NormalizeElements([]);
+ a.length = Math.pow(2, 32) - 3;
+ a.splice(-1, 0, 1, 2, 3, 4, 5);
throw 'Should have thrown RangeError';
} catch (e) {
assertTrue(e instanceof RangeError);
@@ -365,7 +369,8 @@
// Check smi boundary
var bigNum = (1 << 30) - 3;
- var array = new Array(bigNum);
+ var array = %NormalizeElements([]);
+ array.length = bigNum;
array.splice(-1, 0, 1, 2, 3, 4, 5, 6, 7);
assertEquals(bigNum + 7, array.length);
}
=======================================
--- /branches/bleeding_edge/test/mjsunit/array-unshift.js Fri Mar 22
18:04:32 2013 UTC
+++ /branches/bleeding_edge/test/mjsunit/array-unshift.js Thu Jul 24
12:08:23 2014 UTC
@@ -194,7 +194,9 @@
(function() {
for (var i = 0; i < 7; i++) {
try {
- new Array(Math.pow(2, 32) - 3).unshift(1, 2, 3, 4, 5);
+ var a1 = [];
+ a1[Math.pow(2, 32) - 3 - 1] = 0;
+ a1.unshift(1, 2, 3, 4, 5);
throw 'Should have thrown RangeError';
} catch (e) {
assertTrue(e instanceof RangeError);
@@ -202,7 +204,9 @@
// Check smi boundary
var bigNum = (1 << 30) - 3;
- assertEquals(bigNum + 7, new Array(bigNum).unshift(1, 2, 3, 4, 5, 6,
7));
+ var a2 = [];
+ a2[bigNum - 1] = 0;
+ assertEquals(bigNum + 7, a2.unshift(1, 2, 3, 4, 5, 6, 7));
}
})();
=======================================
--- /branches/bleeding_edge/test/mjsunit/elements-kind.js Fri Jul 18
07:17:21 2014 UTC
+++ /branches/bleeding_edge/test/mjsunit/elements-kind.js Thu Jul 24
12:08:23 2014 UTC
@@ -145,7 +145,9 @@
}
assertKind(elements_kind.fast, you);
- assertKind(elements_kind.dictionary, new Array(0xDECAF));
+ var temp = [];
+ temp[0xDECAF] = 0;
+ assertKind(elements_kind.dictionary, temp);
var fast_double_array = new Array(0xDECAF);
for (var i = 0; i < 0xDECAF; i++) fast_double_array[i] = i / 2;
=======================================
--- /branches/bleeding_edge/test/mjsunit/es7/object-observe.js Mon Jul 7
16:18:15 2014 UTC
+++ /branches/bleeding_edge/test/mjsunit/es7/object-observe.js Thu Jul 24
12:08:23 2014 UTC
@@ -1234,8 +1234,9 @@
// Updating length on large (slow) array
reset();
-var slow_arr = new Array(1000000000);
+var slow_arr = %NormalizeElements([]);
slow_arr[500000000] = 'hello';
+slow_arr.length = 1000000000;
Object.observe(slow_arr, observer.callback);
var spliceRecords;
function slowSpliceCallback(records) {
=======================================
--- /branches/bleeding_edge/test/mjsunit/polymorph-arrays.js Fri Jul 8
10:59:20 2011 UTC
+++ /branches/bleeding_edge/test/mjsunit/polymorph-arrays.js Thu Jul 24
12:08:23 2014 UTC
@@ -37,7 +37,7 @@
a[i] = i;
}
a[5000000] = 256;
- assertTrue(%HasDictionaryElements(a));
+ return %NormalizeElements(a);
}
function testPolymorphicLoads() {
@@ -49,7 +49,7 @@
var object_array = new Object;
var sparse_object_array = new Object;
var js_array = new Array(10);
- var sparse_js_array = new Array(5000001);
+ var sparse_js_array = %NormalizeElements([]);
init_array(object_array);
init_array(js_array);
@@ -67,7 +67,7 @@
var object_array = new Object;
var sparse_object_array = new Object;
var js_array = new Array(10);
- var sparse_js_array = new Array(5000001);
+ var sparse_js_array = %NormalizeElements([]);
init_array(object_array);
init_array(js_array);
@@ -114,7 +114,8 @@
var object_array = new Object;
var sparse_object_array = new Object;
var js_array = new Array(10);
- var sparse_js_array = new Array(5000001);
+ var sparse_js_array = [];
+ sparse_js_array.length = 5000001;
init_array(object_array);
init_array(js_array);
@@ -132,7 +133,8 @@
var object_array = new Object;
var sparse_object_array = new Object;
var js_array = new Array(10);
- var sparse_js_array = new Array(5000001);
+ var sparse_js_array = %NormalizeElements([]);
+ sparse_js_array.length = 5000001;
init_array(object_array);
init_array(js_array);
=======================================
--- /branches/bleeding_edge/test/mjsunit/regress/regress-2790.js Tue Nov 26
10:43:44 2013 UTC
+++ /branches/bleeding_edge/test/mjsunit/regress/regress-2790.js Thu Jul 24
12:08:23 2014 UTC
@@ -26,6 +26,6 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Test that we can create arrays of any size.
-for (var i = 1000; i < 1000000; i += 197) {
+for (var i = 1000; i < 1000000; i += 19703) {
new Array(i);
}
=======================================
--- /branches/bleeding_edge/tools/generate-runtime-tests.py Thu Jul 24
10:43:41 2014 UTC
+++ /branches/bleeding_edge/tools/generate-runtime-tests.py Thu Jul 24
12:08:23 2014 UTC
@@ -47,7 +47,7 @@
# that the parser doesn't bit-rot. Change the values as needed when you
add,
# remove or change runtime functions, but make sure we don't lose our
ability
# to parse them!
-EXPECTED_FUNCTION_COUNT = 420
+EXPECTED_FUNCTION_COUNT = 421
EXPECTED_FUZZABLE_COUNT = 335
EXPECTED_CCTEST_COUNT = 8
EXPECTED_UNKNOWN_COUNT = 4
@@ -124,6 +124,7 @@
# Arrays
"ArrayConstructor",
"InternalArrayConstructor",
+ "NormalizeElements",
# Literals
"MaterializeRegExpLiteral",
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.