[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 <cbruni@chromium.org> Commit-Queue: Toon Verwaest <verwaest@chromium.org> Cr-Commit-Position: refs/heads/master@{#44108}
This commit is contained in:
parent
9a3b029b6c
commit
97300c5c38
@ -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();
|
||||
|
@ -671,7 +671,14 @@ class V8_EXPORT_PRIVATE Factory final {
|
||||
bool check_number_string_cache = true);
|
||||
|
||||
Handle<String> Uint32ToString(uint32_t value) {
|
||||
return NumberToString(NewNumberFromUint(value));
|
||||
Handle<String> 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<JSFunction> InstallMembers(Handle<JSFunction> function);
|
||||
|
@ -18549,8 +18549,13 @@ Handle<FixedArray> 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);
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ MaybeHandle<HeapObject> Enumerate(Handle<JSReceiver> receiver) {
|
||||
if (!accumulator.is_receiver_simple_enum()) {
|
||||
Handle<FixedArray> 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;
|
||||
|
Loading…
Reference in New Issue
Block a user