[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:
adamk 2016-10-07 15:29:02 -07:00 committed by Commit bot
parent 3b6c7f04a9
commit 2d4871c143
8 changed files with 50 additions and 58 deletions

View File

@ -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;
}

View File

@ -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));

View File

@ -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);

View File

@ -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);

View File

@ -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.

View File

@ -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)

View File

@ -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) {}

View File

@ -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 };