Use map of prototype in Map::Hash.
Instead of using addresses of prototype and constructor (which can be movedby GC) when computing the hash of a Map, we use the addresses of the prototype map (which won't be compacted). The prototype map is in a 1:1 relation with the prototype. In addition the prototype points to the constructor in most cases. Bug: v8:11519 Change-Id: Ibc47e5870955d7721509be07fae7719a93da9a26 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2739646 Commit-Queue: Patrick Thier <pthier@chromium.org> Auto-Submit: Patrick Thier <pthier@chromium.org> Reviewed-by: Toon Verwaest <verwaest@chromium.org> Cr-Commit-Position: refs/heads/master@{#73286}
This commit is contained in:
parent
03a73545af
commit
ae8823217d
@ -2372,20 +2372,17 @@ Handle<Map> Map::CopyReplaceDescriptor(Isolate* isolate, Handle<Map> map,
|
||||
}
|
||||
|
||||
int Map::Hash() {
|
||||
// For performance reasons we only hash the 3 most variable fields of a map:
|
||||
// constructor, prototype and bit_field2. For predictability reasons we
|
||||
// use objects' offsets in respective pages for hashing instead of raw
|
||||
// addresses.
|
||||
// For performance reasons we only hash the 2 most variable fields of a map:
|
||||
// prototype map and bit_field2. For predictability reasons we use objects'
|
||||
// offsets in respective pages for hashing instead of raw addresses. We use
|
||||
// the map of the prototype because the prototype itself could be compacted,
|
||||
// whereas the map will not be moved.
|
||||
// NOTE: If we want to compact maps, this hash function won't work as intended
|
||||
// anymore.
|
||||
|
||||
// Shift away the tag.
|
||||
int hash = ObjectAddressForHashing(GetConstructor().ptr()) >> 2;
|
||||
|
||||
// XOR-ing the prototype and constructor directly yields too many zero bits
|
||||
// when the two pointers are close (which is fairly common).
|
||||
// To avoid this we shift the prototype bits relatively to the constructor.
|
||||
hash ^= ObjectAddressForHashing(prototype().ptr()) << (32 - kPageSizeBits);
|
||||
|
||||
return hash ^ (hash >> 16) ^ bit_field2();
|
||||
int hash = ObjectAddressForHashing(prototype().map().ptr()) >> 2;
|
||||
return hash ^ bit_field2();
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
25
test/mjsunit/regress/regress-11519.js
Normal file
25
test/mjsunit/regress/regress-11519.js
Normal file
@ -0,0 +1,25 @@
|
||||
// Copyright 2021 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --allow-natives-syntax --gc-interval=500 --stress-compaction
|
||||
|
||||
function bar(a) {
|
||||
return Object.defineProperty(a, 'x', {get() { return 1; }});
|
||||
}
|
||||
|
||||
function foo() {
|
||||
return {};
|
||||
}
|
||||
|
||||
%NeverOptimizeFunction(bar);
|
||||
%PrepareFunctionForOptimization(foo);
|
||||
const o = foo(); // Keep a reference so the GC doesn't kill the map.
|
||||
%SimulateNewspaceFull();
|
||||
bar(o);
|
||||
const a = bar(foo());
|
||||
%SimulateNewspaceFull();
|
||||
%OptimizeFunctionOnNextCall(foo);
|
||||
const b = bar(foo());
|
||||
|
||||
assertTrue(%HaveSameMap(a, b));
|
Loading…
Reference in New Issue
Block a user