From 97300c5c38f775bdec197909e4140ce649c5713a Mon Sep 17 00:00:00 2001 From: Toon Verwaest Date: Fri, 24 Mar 2017 13:37:51 +0100 Subject: [PATCH] [runtime] Immediately set the array-index hash in Uint32ToString and convert to string in ForInPrepare This speeds up for/in over arrays. E.g.,: function f(a) { for (let i in a) { if (a[i] != a[i]) print(false); } } var a = new Array(10000000); a.fill(1); f(a); runs 3x faster after the change. BUG=chromium:703226 Change-Id: Iabc5e931d985a03f89440cd702b2feb3eb9f5c18 Reviewed-on: https://chromium-review.googlesource.com/459538 Reviewed-by: Camillo Bruni Commit-Queue: Toon Verwaest Cr-Commit-Position: refs/heads/master@{#44108} --- src/builtins/builtins-forin-gen.cc | 22 ++++++---------------- src/factory.h | 9 ++++++++- src/objects.cc | 9 +++++++-- src/runtime/runtime-forin.cc | 2 +- 4 files changed, 22 insertions(+), 20 deletions(-) diff --git a/src/builtins/builtins-forin-gen.cc b/src/builtins/builtins-forin-gen.cc index ad3f4d6e17..0f428b68c0 100644 --- a/src/builtins/builtins-forin-gen.cc +++ b/src/builtins/builtins-forin-gen.cc @@ -21,28 +21,18 @@ typedef compiler::Node Node; Node* ForInBuiltinsAssembler::ForInFilter(Node* key, Node* object, Node* context) { - Label return_undefined(this, Label::kDeferred), return_to_name(this), - end(this); + CSA_ASSERT(this, IsName(key)); - Variable var_result(this, MachineRepresentation::kTagged); + Variable var_result(this, MachineRepresentation::kTagged, key); Node* has_property = HasProperty(object, key, context, Runtime::kForInHasProperty); - Branch(WordEqual(has_property, BooleanConstant(true)), &return_to_name, - &return_undefined); + Label end(this); + GotoIf(WordEqual(has_property, BooleanConstant(true)), &end); - Bind(&return_to_name); - { - var_result.Bind(ToName(context, key)); - Goto(&end); - } - - Bind(&return_undefined); - { - var_result.Bind(UndefinedConstant()); - Goto(&end); - } + var_result.Bind(UndefinedConstant()); + Goto(&end); Bind(&end); return var_result.value(); diff --git a/src/factory.h b/src/factory.h index 2038bf2d10..ced247df4e 100644 --- a/src/factory.h +++ b/src/factory.h @@ -671,7 +671,14 @@ class V8_EXPORT_PRIVATE Factory final { bool check_number_string_cache = true); Handle Uint32ToString(uint32_t value) { - return NumberToString(NewNumberFromUint(value)); + Handle result = NumberToString(NewNumberFromUint(value)); + + if (result->length() <= String::kMaxArrayIndexSize) { + uint32_t field = + StringHasher::MakeArrayIndexHash(value, result->length()); + result->set_hash_field(field); + } + return result; } Handle InstallMembers(Handle function); diff --git a/src/objects.cc b/src/objects.cc index 942bbb5ce1..ba5f6f61b0 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -18549,8 +18549,13 @@ Handle OrderedHashSet::ConvertToKeysArray( for (int i = 0; i < length; i++) { int index = kHashTableStartIndex + nof_buckets + (i * kEntrySize); Object* key = table->get(index); - if (convert == GetKeysConversion::kConvertToString && key->IsNumber()) { - key = *isolate->factory()->NumberToString(handle(key, isolate)); + if (convert == GetKeysConversion::kConvertToString) { + uint32_t index_value; + if (key->ToArrayIndex(&index_value)) { + key = *isolate->factory()->Uint32ToString(index_value); + } else { + CHECK(key->IsName()); + } } result->set(i, key); } diff --git a/src/runtime/runtime-forin.cc b/src/runtime/runtime-forin.cc index 9a7c539865..08f6d86819 100644 --- a/src/runtime/runtime-forin.cc +++ b/src/runtime/runtime-forin.cc @@ -31,7 +31,7 @@ MaybeHandle Enumerate(Handle receiver) { if (!accumulator.is_receiver_simple_enum()) { Handle keys; ASSIGN_RETURN_ON_EXCEPTION( - isolate, keys, accumulator.GetKeys(GetKeysConversion::kKeepNumbers), + isolate, keys, accumulator.GetKeys(GetKeysConversion::kConvertToString), HeapObject); // Test again, since cache may have been built by GetKeys() calls above. if (!accumulator.is_receiver_simple_enum()) return keys;