[modules] Give Module an internal [hash] field
This allows us to stop using a Symbol, set as the name of the Module's SharedFunctionInfo, as our storage for a hash. As part of this, centralize the code for generating a random, non-zero hash code in one place (there were previously two copies of this code, and I needed to call it from a third file). BUG=v8:5483 TBR=jochen@chromium.org Review-Url: https://codereview.chromium.org/2395233003 Cr-Commit-Position: refs/heads/master@{#40102}
This commit is contained in:
parent
3b6c7f04a9
commit
2d4871c143
@ -1762,11 +1762,6 @@ Handle<Module> Factory::NewModule(Handle<SharedFunctionInfo> code) {
|
||||
requested_modules_length > 0 ? NewFixedArray(requested_modules_length)
|
||||
: empty_fixed_array();
|
||||
|
||||
// To make it easy to hash Modules, we set a new symbol as the name of
|
||||
// SharedFunctionInfo representing this Module.
|
||||
Handle<Symbol> name_symbol = NewSymbol();
|
||||
code->set_name(*name_symbol);
|
||||
|
||||
Handle<Module> module = Handle<Module>::cast(NewStruct(MODULE_TYPE));
|
||||
module->set_code(*code);
|
||||
module->set_embedder_data(isolate()->heap()->undefined_value());
|
||||
@ -1774,6 +1769,8 @@ Handle<Module> Factory::NewModule(Handle<SharedFunctionInfo> code) {
|
||||
module->set_flags(0);
|
||||
module->set_module_namespace(isolate()->heap()->undefined_value());
|
||||
module->set_requested_modules(*requested_modules);
|
||||
module->set_embedder_data(isolate()->heap()->undefined_value());
|
||||
module->set_hash(isolate()->GenerateIdentityHash(Smi::kMaxValue));
|
||||
return module;
|
||||
}
|
||||
|
||||
|
@ -4014,13 +4014,7 @@ AllocationResult Heap::AllocateSymbol() {
|
||||
result->set_map_no_write_barrier(symbol_map());
|
||||
|
||||
// Generate a random hash value.
|
||||
int hash;
|
||||
int attempts = 0;
|
||||
do {
|
||||
hash = isolate()->random_number_generator()->NextInt() & Name::kHashBitMask;
|
||||
attempts++;
|
||||
} while (hash == 0 && attempts < 30);
|
||||
if (hash == 0) hash = 1; // never return 0
|
||||
int hash = isolate()->GenerateIdentityHash(Name::kHashBitMask);
|
||||
|
||||
Symbol::cast(result)
|
||||
->set_hash_field(Name::kIsNotArrayIndexMask | (hash << Name::kHashShift));
|
||||
|
@ -2883,6 +2883,14 @@ base::RandomNumberGenerator* Isolate::random_number_generator() {
|
||||
return random_number_generator_;
|
||||
}
|
||||
|
||||
int Isolate::GenerateIdentityHash(uint32_t mask) {
|
||||
int hash;
|
||||
int attempts = 0;
|
||||
do {
|
||||
hash = random_number_generator()->NextInt() & mask;
|
||||
} while (hash == 0 && attempts++ < 30);
|
||||
return hash != 0 ? hash : 1;
|
||||
}
|
||||
|
||||
Object* Isolate::FindCodeObject(Address a) {
|
||||
return inner_pointer_to_code_cache()->GcSafeFindCodeForInnerPointer(a);
|
||||
|
@ -1069,6 +1069,10 @@ class Isolate {
|
||||
|
||||
base::RandomNumberGenerator* random_number_generator();
|
||||
|
||||
// Generates a random number that is non-zero when masked
|
||||
// with the provided mask.
|
||||
int GenerateIdentityHash(uint32_t mask);
|
||||
|
||||
// Given an address occupied by a live code object, return that object.
|
||||
Object* FindCodeObject(Address a);
|
||||
|
||||
|
@ -936,7 +936,7 @@ void Module::ModuleVerify() {
|
||||
requested_modules()->ObjectVerify();
|
||||
VerifySmiField(kFlagsOffset);
|
||||
embedder_data()->ObjectVerify();
|
||||
CHECK(shared()->name()->IsSymbol());
|
||||
VerifySmiField(kHashOffset);
|
||||
CHECK(module_namespace()->IsUndefined(isolate) ||
|
||||
module_namespace()->IsJSModuleNamespace());
|
||||
// TODO(neis): Check more.
|
||||
|
@ -5716,6 +5716,7 @@ ACCESSORS(Module, requested_modules, FixedArray, kRequestedModulesOffset)
|
||||
SMI_ACCESSORS(Module, flags, kFlagsOffset)
|
||||
BOOL_ACCESSORS(Module, flags, evaluated, kEvaluatedBit)
|
||||
ACCESSORS(Module, embedder_data, Object, kEmbedderDataOffset)
|
||||
SMI_ACCESSORS(Module, hash, kHashOffset)
|
||||
|
||||
SharedFunctionInfo* Module::shared() const {
|
||||
return code()->IsSharedFunctionInfo() ? SharedFunctionInfo::cast(code())
|
||||
@ -5726,8 +5727,6 @@ ModuleInfo* Module::info() const {
|
||||
return shared()->scope_info()->ModuleDescriptorInfo();
|
||||
}
|
||||
|
||||
uint32_t Module::Hash() const { return Symbol::cast(shared()->name())->Hash(); }
|
||||
|
||||
ACCESSORS(AccessorPair, getter, Object, kGetterOffset)
|
||||
ACCESSORS(AccessorPair, setter, Object, kSetterOffset)
|
||||
|
||||
|
@ -6169,27 +6169,13 @@ Handle<SeededNumberDictionary> JSObject::NormalizeElements(
|
||||
}
|
||||
|
||||
|
||||
static Smi* GenerateIdentityHash(Isolate* isolate) {
|
||||
int hash_value;
|
||||
int attempts = 0;
|
||||
do {
|
||||
// Generate a random 32-bit hash value but limit range to fit
|
||||
// within a smi.
|
||||
hash_value = isolate->random_number_generator()->NextInt() & Smi::kMaxValue;
|
||||
attempts++;
|
||||
} while (hash_value == 0 && attempts < 30);
|
||||
hash_value = hash_value != 0 ? hash_value : 1; // never return 0
|
||||
|
||||
return Smi::FromInt(hash_value);
|
||||
}
|
||||
|
||||
template <typename ProxyType>
|
||||
static Smi* GetOrCreateIdentityHashHelper(Isolate* isolate,
|
||||
Handle<ProxyType> proxy) {
|
||||
Object* maybe_hash = proxy->hash();
|
||||
if (maybe_hash->IsSmi()) return Smi::cast(maybe_hash);
|
||||
|
||||
Smi* hash = GenerateIdentityHash(isolate);
|
||||
Smi* hash = Smi::FromInt(isolate->GenerateIdentityHash(Smi::kMaxValue));
|
||||
proxy->set_hash(hash);
|
||||
return hash;
|
||||
}
|
||||
@ -6219,7 +6205,7 @@ Smi* JSObject::GetOrCreateIdentityHash(Isolate* isolate,
|
||||
if (maybe_hash->IsSmi()) return Smi::cast(maybe_hash);
|
||||
}
|
||||
|
||||
Smi* hash = GenerateIdentityHash(isolate);
|
||||
Smi* hash = Smi::FromInt(isolate->GenerateIdentityHash(Smi::kMaxValue));
|
||||
CHECK(AddDataProperty(&it, handle(hash, isolate), NONE, THROW_ON_ERROR,
|
||||
CERTAINLY_NOT_STORE_FROM_KEYED)
|
||||
.IsJust());
|
||||
@ -19587,9 +19573,10 @@ MaybeHandle<Object> JSModuleNamespace::GetExport(Handle<String> name) {
|
||||
|
||||
namespace {
|
||||
|
||||
template <typename T>
|
||||
struct HandleValueHash {
|
||||
V8_INLINE size_t operator()(Handle<T> handle) const { return handle->Hash(); }
|
||||
struct ModuleHandleHash {
|
||||
V8_INLINE size_t operator()(Handle<Module> module) const {
|
||||
return module->hash();
|
||||
}
|
||||
};
|
||||
|
||||
struct ModuleHandleEqual {
|
||||
@ -19598,6 +19585,12 @@ struct ModuleHandleEqual {
|
||||
}
|
||||
};
|
||||
|
||||
struct StringHandleHash {
|
||||
V8_INLINE size_t operator()(Handle<String> string) const {
|
||||
return string->Hash();
|
||||
}
|
||||
};
|
||||
|
||||
struct StringHandleEqual {
|
||||
V8_INLINE bool operator()(Handle<String> lhs, Handle<String> rhs) const {
|
||||
return lhs->Equals(*rhs);
|
||||
@ -19605,42 +19598,39 @@ struct StringHandleEqual {
|
||||
};
|
||||
|
||||
class UnorderedStringSet
|
||||
: public std::unordered_set<Handle<String>, HandleValueHash<String>,
|
||||
: public std::unordered_set<Handle<String>, StringHandleHash,
|
||||
StringHandleEqual,
|
||||
zone_allocator<Handle<String>>> {
|
||||
public:
|
||||
explicit UnorderedStringSet(Zone* zone)
|
||||
: std::unordered_set<Handle<String>, HandleValueHash<String>,
|
||||
StringHandleEqual, zone_allocator<Handle<String>>>(
|
||||
2 /* bucket count */, HandleValueHash<String>(),
|
||||
StringHandleEqual(), zone_allocator<Handle<String>>(zone)) {}
|
||||
: std::unordered_set<Handle<String>, StringHandleHash, StringHandleEqual,
|
||||
zone_allocator<Handle<String>>>(
|
||||
2 /* bucket count */, StringHandleHash(), StringHandleEqual(),
|
||||
zone_allocator<Handle<String>>(zone)) {}
|
||||
};
|
||||
|
||||
class UnorderedModuleSet
|
||||
: public std::unordered_set<Handle<Module>, HandleValueHash<Module>,
|
||||
: public std::unordered_set<Handle<Module>, ModuleHandleHash,
|
||||
ModuleHandleEqual,
|
||||
zone_allocator<Handle<Module>>> {
|
||||
public:
|
||||
explicit UnorderedModuleSet(Zone* zone)
|
||||
: std::unordered_set<Handle<Module>, HandleValueHash<Module>,
|
||||
ModuleHandleEqual, zone_allocator<Handle<Module>>>(
|
||||
2 /* bucket count */, HandleValueHash<Module>(),
|
||||
ModuleHandleEqual(), zone_allocator<Handle<Module>>(zone)) {}
|
||||
: std::unordered_set<Handle<Module>, ModuleHandleHash, ModuleHandleEqual,
|
||||
zone_allocator<Handle<Module>>>(
|
||||
2 /* bucket count */, ModuleHandleHash(), ModuleHandleEqual(),
|
||||
zone_allocator<Handle<Module>>(zone)) {}
|
||||
};
|
||||
|
||||
class UnorderedStringMap
|
||||
: public std::unordered_map<
|
||||
Handle<String>, Handle<Object>, HandleValueHash<String>,
|
||||
StringHandleEqual,
|
||||
Handle<String>, Handle<Object>, StringHandleHash, StringHandleEqual,
|
||||
zone_allocator<std::pair<const Handle<String>, Handle<Object>>>> {
|
||||
public:
|
||||
explicit UnorderedStringMap(Zone* zone)
|
||||
: std::unordered_map<
|
||||
Handle<String>, Handle<Object>, HandleValueHash<String>,
|
||||
StringHandleEqual,
|
||||
Handle<String>, Handle<Object>, StringHandleHash, StringHandleEqual,
|
||||
zone_allocator<std::pair<const Handle<String>, Handle<Object>>>>(
|
||||
2 /* bucket count */, HandleValueHash<String>(),
|
||||
StringHandleEqual(),
|
||||
2 /* bucket count */, StringHandleHash(), StringHandleEqual(),
|
||||
zone_allocator<std::pair<const Handle<String>, Handle<Object>>>(
|
||||
zone)) {}
|
||||
};
|
||||
@ -19649,17 +19639,16 @@ class UnorderedStringMap
|
||||
|
||||
class Module::ResolveSet
|
||||
: public std::unordered_map<
|
||||
Handle<Module>, UnorderedStringSet*, HandleValueHash<Module>,
|
||||
Handle<Module>, UnorderedStringSet*, ModuleHandleHash,
|
||||
ModuleHandleEqual, zone_allocator<std::pair<const Handle<Module>,
|
||||
UnorderedStringSet*>>> {
|
||||
public:
|
||||
explicit ResolveSet(Zone* zone)
|
||||
: std::unordered_map<Handle<Module>, UnorderedStringSet*,
|
||||
HandleValueHash<Module>, ModuleHandleEqual,
|
||||
ModuleHandleHash, ModuleHandleEqual,
|
||||
zone_allocator<std::pair<const Handle<Module>,
|
||||
UnorderedStringSet*>>>(
|
||||
2 /* bucket count */, HandleValueHash<Module>(),
|
||||
ModuleHandleEqual(),
|
||||
2 /* bucket count */, ModuleHandleHash(), ModuleHandleEqual(),
|
||||
zone_allocator<
|
||||
std::pair<const Handle<Module>, UnorderedStringSet*>>(zone)),
|
||||
zone_(zone) {}
|
||||
|
@ -7926,15 +7926,15 @@ class Module : public Struct {
|
||||
// Embedder-specified data
|
||||
DECL_ACCESSORS(embedder_data, Object)
|
||||
|
||||
// Hash for this object (a random non-zero Smi).
|
||||
DECL_INT_ACCESSORS(hash)
|
||||
|
||||
// Get the SharedFunctionInfo associated with the code.
|
||||
inline SharedFunctionInfo* shared() const;
|
||||
|
||||
// Get the ModuleInfo associated with the code.
|
||||
inline ModuleInfo* info() const;
|
||||
|
||||
// Compute a hash for this object.
|
||||
inline uint32_t Hash() const;
|
||||
|
||||
// Implementation of spec operation ModuleDeclarationInstantiation.
|
||||
// Returns false if an exception occurred during instantiation, true
|
||||
// otherwise.
|
||||
@ -7964,7 +7964,8 @@ class Module : public Struct {
|
||||
static const int kFlagsOffset = kRequestedModulesOffset + kPointerSize;
|
||||
static const int kEmbedderDataOffset = kFlagsOffset + kPointerSize;
|
||||
static const int kModuleNamespaceOffset = kEmbedderDataOffset + kPointerSize;
|
||||
static const int kSize = kModuleNamespaceOffset + kPointerSize;
|
||||
static const int kHashOffset = kModuleNamespaceOffset + kPointerSize;
|
||||
static const int kSize = kHashOffset + kPointerSize;
|
||||
|
||||
private:
|
||||
enum { kEvaluatedBit };
|
||||
|
Loading…
Reference in New Issue
Block a user