Permalink
Browse files

Land number collision fix for v8 3.6 by Erik Corry

- If V8 snapshots are enabled then the hash is only randomized at build time.

---
backport @10366, @10367 and @10402 to 3.6

Add seed to hash of numeric keyed properties.

Minor cleanups of numeric seeded hashing patch.

Split NumberDictionary into a randomly seeded and an unseeded version.
We don't want to randomize the stub cache.

Review URL: http://codereview.chromium.org/9190001/
  • Loading branch information...
indutny committed Jan 17, 2012
1 parent 534df2f commit 16953329413831b32f4c3b2255aeacec874ed69d
@@ -5363,7 +5363,7 @@ void StringHelper::GenerateHashInit(MacroAssembler* masm,
Register hash,
Register character) {
// hash = character + (character << 10);
__ LoadRoot(hash, Heap::kStringHashSeedRootIndex);
__ LoadRoot(hash, Heap::kHashSeedRootIndex);
// Untag smi seed and add the character.
__ add(hash, character, Operand(hash, LSR, kSmiTagSize));
// hash += hash << 10;
@@ -1337,6 +1337,34 @@ void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
}
void MacroAssembler::GetNumberHash(Register t0, Register scratch) {
// First of all we assign the hash seed to scratch.
LoadRoot(scratch, Heap::kHashSeedRootIndex);
SmiUntag(scratch);
// Xor original key with a seed.
eor(t0, t0, Operand(scratch));
// Compute the hash code from the untagged key. This must be kept in sync
// with ComputeIntegerHash in utils.h.
//
// hash = ~hash + (hash << 15);
mvn(scratch, Operand(t0));
add(t0, scratch, Operand(t0, LSL, 15));
// hash = hash ^ (hash >> 12);
eor(t0, t0, Operand(t0, LSR, 12));
// hash = hash + (hash << 2);
add(t0, t0, Operand(t0, LSL, 2));
// hash = hash ^ (hash >> 4);
eor(t0, t0, Operand(t0, LSR, 4));
// hash = hash * 2057;
mov(scratch, Operand(2057));
mul(t0, t0, scratch);
// hash = hash ^ (hash >> 16);
eor(t0, t0, Operand(t0, LSR, 16));
}
void MacroAssembler::LoadFromNumberDictionary(Label* miss,
Register elements,
Register key,
@@ -1366,26 +1394,10 @@ void MacroAssembler::LoadFromNumberDictionary(Label* miss,
// t2 - used for the index into the dictionary.
Label done;
// Compute the hash code from the untagged key. This must be kept in sync
// with ComputeIntegerHash in utils.h.
//
// hash = ~hash + (hash << 15);
mvn(t1, Operand(t0));
add(t0, t1, Operand(t0, LSL, 15));
// hash = hash ^ (hash >> 12);
eor(t0, t0, Operand(t0, LSR, 12));
// hash = hash + (hash << 2);
add(t0, t0, Operand(t0, LSL, 2));
// hash = hash ^ (hash >> 4);
eor(t0, t0, Operand(t0, LSR, 4));
// hash = hash * 2057;
mov(t1, Operand(2057));
mul(t0, t0, t1);
// hash = hash ^ (hash >> 16);
eor(t0, t0, Operand(t0, LSR, 16));
GetNumberHash(t0, t1);
// Compute the capacity mask.
ldr(t1, FieldMemOperand(elements, NumberDictionary::kCapacityOffset));
ldr(t1, FieldMemOperand(elements, SeededNumberDictionary::kCapacityOffset));
mov(t1, Operand(t1, ASR, kSmiTagSize)); // convert smi to int
sub(t1, t1, Operand(1));
@@ -1396,17 +1408,17 @@ void MacroAssembler::LoadFromNumberDictionary(Label* miss,
mov(t2, t0);
// Compute the masked index: (hash + i + i * i) & mask.
if (i > 0) {
add(t2, t2, Operand(NumberDictionary::GetProbeOffset(i)));
add(t2, t2, Operand(SeededNumberDictionary::GetProbeOffset(i)));
}
and_(t2, t2, Operand(t1));
// Scale the index by multiplying by the element size.
ASSERT(NumberDictionary::kEntrySize == 3);
ASSERT(SeededNumberDictionary::kEntrySize == 3);
add(t2, t2, Operand(t2, LSL, 1)); // t2 = t2 * 3
// Check if the key is identical to the name.
add(t2, elements, Operand(t2, LSL, kPointerSizeLog2));
ldr(ip, FieldMemOperand(t2, NumberDictionary::kElementsStartOffset));
ldr(ip, FieldMemOperand(t2, SeededNumberDictionary::kElementsStartOffset));
cmp(key, Operand(ip));
if (i != kProbes - 1) {
b(eq, &done);
@@ -1419,14 +1431,14 @@ void MacroAssembler::LoadFromNumberDictionary(Label* miss,
// Check that the value is a normal property.
// t2: elements + (index * kPointerSize)
const int kDetailsOffset =
NumberDictionary::kElementsStartOffset + 2 * kPointerSize;
SeededNumberDictionary::kElementsStartOffset + 2 * kPointerSize;
ldr(t1, FieldMemOperand(t2, kDetailsOffset));
tst(t1, Operand(Smi::FromInt(PropertyDetails::TypeField::kMask)));
b(ne, miss);
// Get the value at the masked, scaled index and return.
const int kValueOffset =
NumberDictionary::kElementsStartOffset + kPointerSize;
SeededNumberDictionary::kElementsStartOffset + kPointerSize;
ldr(result, FieldMemOperand(t2, kValueOffset));
}
@@ -441,6 +441,7 @@ class MacroAssembler: public Assembler {
Register scratch,
Label* miss);
void GetNumberHash(Register t0, Register scratch);
void LoadFromNumberDictionary(Label* miss,
Register elements,
@@ -40,7 +40,7 @@ namespace internal {
bool CodeStub::FindCodeInCache(Code** code_out) {
Heap* heap = Isolate::Current()->heap();
int index = heap->code_stubs()->FindEntry(GetKey());
if (index != NumberDictionary::kNotFound) {
if (index != UnseededNumberDictionary::kNotFound) {
*code_out = Code::cast(heap->code_stubs()->ValueAt(index));
return true;
}
@@ -121,9 +121,9 @@ Handle<Code> CodeStub::GetCode() {
FinishCode(*new_object);
// Update the dictionary and the root in Heap.
Handle<NumberDictionary> dict =
Handle<UnseededNumberDictionary> dict =
factory->DictionaryAtNumberPut(
Handle<NumberDictionary>(heap->code_stubs()),
Handle<UnseededNumberDictionary>(heap->code_stubs()),
GetKey(),
new_object);
heap->public_set_code_stubs(*dict);
@@ -165,7 +165,7 @@ MaybeObject* CodeStub::TryGetCode() {
MaybeObject* maybe_new_object =
heap->code_stubs()->AtNumberPut(GetKey(), code);
if (maybe_new_object->ToObject(&new_object)) {
heap->public_set_code_stubs(NumberDictionary::cast(new_object));
heap->public_set_code_stubs(UnseededNumberDictionary::cast(new_object));
}
}
View
@@ -178,7 +178,9 @@ class ScriptCache : private HashMap {
private:
// Calculate the hash value from the key (script id).
static uint32_t Hash(int key) { return ComputeIntegerHash(key); }
static uint32_t Hash(int key) {
return ComputeIntegerHash(key, v8::internal::kZeroHashSeed);
}
// Scripts match if their keys (script id) match.
static bool ScriptMatch(void* key1, void* key2) { return key1 == key2; }
View
@@ -392,7 +392,7 @@ class PixelElementsAccessor
class DictionaryElementsAccessor
: public ElementsAccessorBase<DictionaryElementsAccessor,
NumberDictionary> {
SeededNumberDictionary> {
public:
static MaybeObject* DeleteCommon(JSObject* obj,
uint32_t key,
@@ -405,9 +405,10 @@ class DictionaryElementsAccessor
if (is_arguments) {
backing_store = FixedArray::cast(backing_store->get(1));
}
NumberDictionary* dictionary = NumberDictionary::cast(backing_store);
SeededNumberDictionary* dictionary =
SeededNumberDictionary::cast(backing_store);
int entry = dictionary->FindEntry(key);
if (entry != NumberDictionary::kNotFound) {
if (entry != SeededNumberDictionary::kNotFound) {
Object* result = dictionary->DeleteProperty(entry, mode);
if (result == heap->true_value()) {
MaybeObject* maybe_elements = dictionary->Shrink(key);
@@ -440,20 +441,20 @@ class DictionaryElementsAccessor
protected:
friend class ElementsAccessorBase<DictionaryElementsAccessor,
NumberDictionary>;
SeededNumberDictionary>;
virtual MaybeObject* Delete(JSObject* obj,
uint32_t key,
JSReceiver::DeleteMode mode) {
return DeleteCommon(obj, key, mode);
}
static MaybeObject* Get(NumberDictionary* backing_store,
static MaybeObject* Get(SeededNumberDictionary* backing_store,
uint32_t key,
JSObject* obj,
Object* receiver) {
int entry = backing_store->FindEntry(key);
if (entry != NumberDictionary::kNotFound) {
if (entry != SeededNumberDictionary::kNotFound) {
Object* element = backing_store->ValueAt(entry);
PropertyDetails details = backing_store->DetailsAt(entry);
if (details.type() == CALLBACKS) {
@@ -468,7 +469,7 @@ class DictionaryElementsAccessor
return obj->GetHeap()->the_hole_value();
}
static uint32_t GetKeyForIndex(NumberDictionary* dict,
static uint32_t GetKeyForIndex(SeededNumberDictionary* dict,
uint32_t index) {
Object* key = dict->KeyAt(index);
return Smi::cast(key)->value();
View
@@ -77,11 +77,21 @@ Handle<StringDictionary> Factory::NewStringDictionary(int at_least_space_for) {
}
Handle<NumberDictionary> Factory::NewNumberDictionary(int at_least_space_for) {
Handle<SeededNumberDictionary> Factory::NewSeededNumberDictionary(
int at_least_space_for) {
ASSERT(0 <= at_least_space_for);
CALL_HEAP_FUNCTION(isolate(),
NumberDictionary::Allocate(at_least_space_for),
NumberDictionary);
SeededNumberDictionary::Allocate(at_least_space_for),
SeededNumberDictionary);
}
Handle<UnseededNumberDictionary> Factory::NewUnseededNumberDictionary(
int at_least_space_for) {
ASSERT(0 <= at_least_space_for);
CALL_HEAP_FUNCTION(isolate(),
UnseededNumberDictionary::Allocate(at_least_space_for),
UnseededNumberDictionary);
}
@@ -990,13 +1000,23 @@ Handle<String> Factory::NumberToString(Handle<Object> number) {
}
Handle<NumberDictionary> Factory::DictionaryAtNumberPut(
Handle<NumberDictionary> dictionary,
Handle<SeededNumberDictionary> Factory::DictionaryAtNumberPut(
Handle<SeededNumberDictionary> dictionary,
uint32_t key,
Handle<Object> value) {
CALL_HEAP_FUNCTION(isolate(),
dictionary->AtNumberPut(key, *value),
SeededNumberDictionary);
}
Handle<UnseededNumberDictionary> Factory::DictionaryAtNumberPut(
Handle<UnseededNumberDictionary> dictionary,
uint32_t key,
Handle<Object> value) {
CALL_HEAP_FUNCTION(isolate(),
dictionary->AtNumberPut(key, *value),
NumberDictionary);
UnseededNumberDictionary);
}
View
@@ -54,7 +54,11 @@ class Factory {
int size,
PretenureFlag pretenure = NOT_TENURED);
Handle<NumberDictionary> NewNumberDictionary(int at_least_space_for);
Handle<SeededNumberDictionary> NewSeededNumberDictionary(
int at_least_space_for);
Handle<UnseededNumberDictionary> NewUnseededNumberDictionary(
int at_least_space_for);
Handle<StringDictionary> NewStringDictionary(int at_least_space_for);
@@ -412,8 +416,13 @@ class Factory {
Handle<Object> stack_trace,
Handle<Object> stack_frames);
Handle<NumberDictionary> DictionaryAtNumberPut(
Handle<NumberDictionary>,
Handle<SeededNumberDictionary> DictionaryAtNumberPut(
Handle<SeededNumberDictionary>,
uint32_t key,
Handle<Object> value);
Handle<UnseededNumberDictionary> DictionaryAtNumberPut(
Handle<UnseededNumberDictionary>,
uint32_t key,
Handle<Object> value);
@@ -319,13 +319,13 @@ DEFINE_bool(trace_exception, false,
"print stack trace when throwing exceptions")
DEFINE_bool(preallocate_message_memory, false,
"preallocate some memory to build stack traces.")
DEFINE_bool(randomize_string_hashes,
DEFINE_bool(randomize_hashes,
true,
"randomize string hashes to avoid predictable hash collisions "
"randomize hashes to avoid predictable hash collisions "
"(with snapshots this option cannot override the baked-in seed)")
DEFINE_int(string_hash_seed,
DEFINE_int(hash_seed,
0,
"Fixed seed to use to string hashing (0 means random)"
"Fixed seed to use to hash property keys (0 means random)"
"(with snapshots this option cannot override the baked-in seed)")
// v8.cc
View
@@ -1187,7 +1187,8 @@ PcToCodeCache::PcToCodeCacheEntry* PcToCodeCache::GetCacheEntry(Address pc) {
isolate_->counters()->pc_to_code()->Increment();
ASSERT(IsPowerOf2(kPcToCodeCacheSize));
uint32_t hash = ComputeIntegerHash(
static_cast<uint32_t>(reinterpret_cast<uintptr_t>(pc)));
static_cast<uint32_t>(reinterpret_cast<uintptr_t>(pc)),
v8::internal::kZeroHashSeed);
uint32_t index = hash & (kPcToCodeCacheSize - 1);
PcToCodeCacheEntry* entry = cache(index);
if (entry->pc == pc) {
View
@@ -214,10 +214,10 @@ void NormalizeProperties(Handle<JSObject> object,
}
Handle<NumberDictionary> NormalizeElements(Handle<JSObject> object) {
Handle<SeededNumberDictionary> NormalizeElements(Handle<JSObject> object) {
CALL_HEAP_FUNCTION(object->GetIsolate(),
object->NormalizeElements(),
NumberDictionary);
SeededNumberDictionary);
}
@@ -229,14 +229,14 @@ void TransformToFastProperties(Handle<JSObject> object,
}
Handle<NumberDictionary> NumberDictionarySet(
Handle<NumberDictionary> dictionary,
Handle<SeededNumberDictionary> SeededNumberDictionarySet(
Handle<SeededNumberDictionary> dictionary,
uint32_t index,
Handle<Object> value,
PropertyDetails details) {
CALL_HEAP_FUNCTION(dictionary->GetIsolate(),
dictionary->Set(index, *value, details),
NumberDictionary);
SeededNumberDictionary);
}
View
@@ -170,11 +170,11 @@ class HandleScope {
void NormalizeProperties(Handle<JSObject> object,
PropertyNormalizationMode mode,
int expected_additional_properties);
Handle<NumberDictionary> NormalizeElements(Handle<JSObject> object);
Handle<SeededNumberDictionary> NormalizeElements(Handle<JSObject> object);
void TransformToFastProperties(Handle<JSObject> object,
int unused_property_fields);
MUST_USE_RESULT Handle<NumberDictionary> NumberDictionarySet(
Handle<NumberDictionary> dictionary,
MUST_USE_RESULT Handle<SeededNumberDictionary> SeededNumberDictionarySet(
Handle<SeededNumberDictionary> dictionary,
uint32_t index,
Handle<Object> value,
PropertyDetails details);
Oops, something went wrong.

0 comments on commit 1695332

Please sign in to comment.