Commit 94c47602 authored by kasperl@chromium.org's avatar kasperl@chromium.org

Revert r2486, r2487, and r2488 until I get the chance to fix

the performance issue with number dictionaries.

TBR=kmillikin@chromium.org

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2490 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 5ec5dcbd
...@@ -103,20 +103,16 @@ static void GenerateDictionaryLoad(MacroAssembler* masm, ...@@ -103,20 +103,16 @@ static void GenerateDictionaryLoad(MacroAssembler* masm,
// Generate an unrolled loop that performs a few probes before // Generate an unrolled loop that performs a few probes before
// giving up. Measurements done on Gmail indicate that 2 probes // giving up. Measurements done on Gmail indicate that 2 probes
// cover ~93% of loads from dictionaries. // cover ~93% of loads from dictionaries.
static const uint32_t kProbes = static const int kProbes = 4;
HashTable<StringDictionaryShape, String*>::kNofFastProbes; for (int i = 0; i < kProbes; i++) {
static const uint32_t kShift = // Compute the masked index: (hash + i + i * i) & mask.
HashTable<StringDictionaryShape, String*>::kHashRotateShift;
for (uint32_t i = 0; i < kProbes; i++) {
// Compute the masked index.
__ ldr(t1, FieldMemOperand(r2, String::kLengthOffset)); __ ldr(t1, FieldMemOperand(r2, String::kLengthOffset));
__ mov(t1, Operand(t1, LSR, String::kHashShift)); __ mov(t1, Operand(t1, LSR, String::kHashShift));
if (i > 0) { if (i > 0) {
__ and_(t1, r3, Operand(t1, ROR, (kShift * i) % kBitsPerInt)); __ add(t1, t1, Operand(StringDictionary::GetProbeOffset(i)));
} else {
__ and_(t1, t1, Operand(r3));
} }
__ and_(t1, t1, Operand(r3));
// Scale the index by multiplying by the element size. // Scale the index by multiplying by the element size.
ASSERT(StringDictionary::kEntrySize == 3); ASSERT(StringDictionary::kEntrySize == 3);
__ add(t1, t1, Operand(t1, LSL, 1)); // t1 = t1 * 3 __ add(t1, t1, Operand(t1, LSL, 1)); // t1 = t1 * 3
......
...@@ -45,7 +45,6 @@ using ::v8::internal::PrintF; ...@@ -45,7 +45,6 @@ using ::v8::internal::PrintF;
using ::v8::internal::OS; using ::v8::internal::OS;
using ::v8::internal::ReadLine; using ::v8::internal::ReadLine;
using ::v8::internal::DeleteArray; using ::v8::internal::DeleteArray;
using ::v8::internal::RotateRight;
// This macro provides a platform independent use of sscanf. The reason for // This macro provides a platform independent use of sscanf. The reason for
// SScanF not being implemented in a platform independent was through // SScanF not being implemented in a platform independent was through
...@@ -818,12 +817,7 @@ int32_t Simulator::GetShiftRm(Instr* instr, bool* carry_out) { ...@@ -818,12 +817,7 @@ int32_t Simulator::GetShiftRm(Instr* instr, bool* carry_out) {
} }
case ROR: { case ROR: {
ASSERT(shift_amount > 0); UNIMPLEMENTED();
uint32_t uresult = static_cast<uint32_t>(result);
uresult = RotateRight(uresult, shift_amount - 1);
*carry_out = (uresult & 1) == 1;
uresult = RotateRight(uresult, 1);
result = static_cast<int32_t>(uresult);
break; break;
} }
......
...@@ -1240,16 +1240,6 @@ void Assembler::xor_(const Operand& dst, const Immediate& x) { ...@@ -1240,16 +1240,6 @@ void Assembler::xor_(const Operand& dst, const Immediate& x) {
} }
void Assembler::ror(Register dst, uint32_t count) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
EMIT(0xC1);
emit_operand(ecx, Operand(dst));
ASSERT(count < 32);
EMIT(count);
}
void Assembler::bt(const Operand& dst, Register src) { void Assembler::bt(const Operand& dst, Register src) {
EnsureSpace ensure_space(this); EnsureSpace ensure_space(this);
last_pc_ = pc_; last_pc_ = pc_;
......
...@@ -597,9 +597,6 @@ class Assembler : public Malloced { ...@@ -597,9 +597,6 @@ class Assembler : public Malloced {
void xor_(const Operand& src, Register dst); void xor_(const Operand& src, Register dst);
void xor_(const Operand& dst, const Immediate& x); void xor_(const Operand& dst, const Immediate& x);
// Rotate dist right count times, asserts count < 32.
void ror(Register dst, uint32_t count);
// Bit operations. // Bit operations.
void bt(const Operand& dst, Register src); void bt(const Operand& dst, Register src);
void bts(const Operand& dst, Register src); void bts(const Operand& dst, Register src);
......
...@@ -97,20 +97,15 @@ static void GenerateDictionaryLoad(MacroAssembler* masm, Label* miss_label, ...@@ -97,20 +97,15 @@ static void GenerateDictionaryLoad(MacroAssembler* masm, Label* miss_label,
// Generate an unrolled loop that performs a few probes before // Generate an unrolled loop that performs a few probes before
// giving up. Measurements done on Gmail indicate that 2 probes // giving up. Measurements done on Gmail indicate that 2 probes
// cover ~93% of loads from dictionaries. // cover ~93% of loads from dictionaries.
static const int kProbes = 4;
const int kElementsStartOffset = const int kElementsStartOffset =
Array::kHeaderSize + StringDictionary::kElementsStartIndex * kPointerSize; Array::kHeaderSize + StringDictionary::kElementsStartIndex * kPointerSize;
for (int i = 0; i < kProbes; i++) {
static const uint32_t kProbes = // Compute the masked index: (hash + i + i * i) & mask.
HashTable<StringDictionaryShape, String*>::kNofFastProbes;
static const uint32_t kShift =
HashTable<StringDictionaryShape, String*>::kHashRotateShift;
for (uint32_t i = 0; i < kProbes; i++) {
// Compute the masked index.
__ mov(r1, FieldOperand(name, String::kLengthOffset)); __ mov(r1, FieldOperand(name, String::kLengthOffset));
__ shr(r1, String::kHashShift); __ shr(r1, String::kHashShift);
if (i > 0) { if (i > 0) {
__ ror(r1, (kShift * i) % kBitsPerInt); __ add(Operand(r1), Immediate(StringDictionary::GetProbeOffset(i)));
} }
__ and_(r1, Operand(r2)); __ and_(r1, Operand(r2));
......
...@@ -6502,8 +6502,7 @@ template<typename Shape, typename Key> ...@@ -6502,8 +6502,7 @@ template<typename Shape, typename Key>
Object* HashTable<Shape, Key>::Allocate( Object* HashTable<Shape, Key>::Allocate(
int at_least_space_for) { int at_least_space_for) {
int capacity = RoundUpToPowerOf2(at_least_space_for); int capacity = RoundUpToPowerOf2(at_least_space_for);
static const int kMinCapacity = 16; if (capacity < 4) capacity = 4; // Guarantee min capacity.
if (capacity < kMinCapacity) capacity = kMinCapacity;
Object* obj = Heap::AllocateHashTable(EntryToIndex(capacity)); Object* obj = Heap::AllocateHashTable(EntryToIndex(capacity));
if (!obj->IsFailure()) { if (!obj->IsFailure()) {
HashTable::cast(obj)->SetNumberOfElements(0); HashTable::cast(obj)->SetNumberOfElements(0);
...@@ -6517,25 +6516,26 @@ Object* HashTable<Shape, Key>::Allocate( ...@@ -6517,25 +6516,26 @@ Object* HashTable<Shape, Key>::Allocate(
// Find entry for key otherwise return -1. // Find entry for key otherwise return -1.
template<typename Shape, typename Key> template<typename Shape, typename Key>
int HashTable<Shape, Key>::FindEntry(Key key) { int HashTable<Shape, Key>::FindEntry(Key key) {
uint32_t mask = Capacity() - 1; uint32_t nof = NumberOfElements();
if (nof == 0) return kNotFound; // Bail out if empty.
uint32_t capacity = Capacity();
uint32_t hash = Shape::Hash(key); uint32_t hash = Shape::Hash(key);
uint32_t entry = GetProbe(hash, 0, capacity);
// For the first probes rotate the hash to ensure a proper spread. Object* element = KeyAt(entry);
uint32_t h = hash; uint32_t passed_elements = 0;
for (uint32_t i = 0; i < kNofFastProbes; i++) { if (!element->IsNull()) {
int entry = h & mask; if (!element->IsUndefined() && Shape::IsMatch(key, element)) return entry;
Object* element = KeyAt(entry); if (++passed_elements == nof) return kNotFound;
if (element->IsUndefined()) return kNotFound;
if (!element->IsNull() && Shape::IsMatch(key, element)) return entry;
h = RotateRight(h, kHashRotateShift);
} }
for (uint32_t i = 1; !element->IsUndefined(); i++) {
// In this unlikely event, do a linear scan. entry = GetProbe(hash, i, capacity);
for (uint32_t i = 1; i <= mask; i++) { element = KeyAt(entry);
int entry = ++hash & mask; if (!element->IsNull()) {
Object* element = KeyAt(entry); if (!element->IsUndefined() && Shape::IsMatch(key, element)) return entry;
if (element->IsUndefined()) return kNotFound; if (++passed_elements == nof) return kNotFound;
if (!element->IsNull() && Shape::IsMatch(key, element)) return entry; }
} }
return kNotFound; return kNotFound;
} }
...@@ -6579,23 +6579,14 @@ Object* HashTable<Shape, Key>::EnsureCapacity(int n, Key key) { ...@@ -6579,23 +6579,14 @@ Object* HashTable<Shape, Key>::EnsureCapacity(int n, Key key) {
template<typename Shape, typename Key> template<typename Shape, typename Key>
uint32_t HashTable<Shape, Key>::FindInsertionEntry(uint32_t hash) { uint32_t HashTable<Shape, Key>::FindInsertionEntry(uint32_t hash) {
uint32_t mask = Capacity() - 1; uint32_t capacity = Capacity();
int entry; uint32_t entry = GetProbe(hash, 0, capacity);
Object* element; Object* element = KeyAt(entry);
// For the first probes rotate the hash to ensure a proper spread.
uint32_t h = hash;
for (uint32_t i = 0; i < kNofFastProbes; i++) {
entry = h & mask;
element = KeyAt(entry);
if (element->IsUndefined() || element->IsNull()) return entry;
h = RotateRight(h, kHashRotateShift);
}
do { for (uint32_t i = 1; !(element->IsUndefined() || element->IsNull()); i++) {
entry = ++hash & mask; entry = GetProbe(hash, i, capacity);
element = KeyAt(entry); element = KeyAt(entry);
} while (!(element->IsUndefined() || element->IsNull())); }
return entry; return entry;
} }
...@@ -6675,10 +6666,6 @@ int Dictionary<NumberDictionaryShape, uint32_t>::NumberOfEnumElements(); ...@@ -6675,10 +6666,6 @@ int Dictionary<NumberDictionaryShape, uint32_t>::NumberOfEnumElements();
template template
int Dictionary<StringDictionaryShape, String*>::NumberOfEnumElements(); int Dictionary<StringDictionaryShape, String*>::NumberOfEnumElements();
template
int HashTable<NumberDictionaryShape, uint32_t>::FindEntry(uint32_t key);
// Collates undefined and unexisting elements below limit from position // Collates undefined and unexisting elements below limit from position
// zero of the elements. The object stays in Dictionary mode. // zero of the elements. The object stays in Dictionary mode.
Object* JSObject::PrepareSlowElementsForSort(uint32_t limit) { Object* JSObject::PrepareSlowElementsForSort(uint32_t limit) {
...@@ -7034,7 +7021,7 @@ class SymbolsKey : public HashTableKey { ...@@ -7034,7 +7021,7 @@ class SymbolsKey : public HashTableKey {
uint32_t HashForObject(Object* obj) { uint32_t HashForObject(Object* obj) {
FixedArray* symbols = FixedArray::cast(obj); FixedArray* symbols = FixedArray::cast(obj);
int len = symbols->length(); int len = symbols->length();
uint32_t hash = 40617523; // In case the array is empty. uint32_t hash = 0;
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
hash ^= String::cast(symbols->get(i))->Hash(); hash ^= String::cast(symbols->get(i))->Hash();
} }
......
...@@ -2051,6 +2051,11 @@ class HashTable: public FixedArray { ...@@ -2051,6 +2051,11 @@ class HashTable: public FixedArray {
// Casting. // Casting.
static inline HashTable* cast(Object* obj); static inline HashTable* cast(Object* obj);
// Compute the probe offset (quadratic probing).
INLINE(static uint32_t GetProbeOffset(uint32_t n)) {
return (n + n * n) >> 1;
}
static const int kNumberOfElementsIndex = 0; static const int kNumberOfElementsIndex = 0;
static const int kCapacityIndex = 1; static const int kCapacityIndex = 1;
static const int kPrefixStartIndex = 2; static const int kPrefixStartIndex = 2;
...@@ -2066,9 +2071,6 @@ class HashTable: public FixedArray { ...@@ -2066,9 +2071,6 @@ class HashTable: public FixedArray {
// Find entry for key otherwise return -1. // Find entry for key otherwise return -1.
int FindEntry(Key key); int FindEntry(Key key);
static const uint32_t kNofFastProbes = 4;
static const uint32_t kHashRotateShift = 3;
protected: protected:
// Find the entry at which to insert element with the given key that // Find the entry at which to insert element with the given key that
...@@ -2094,6 +2096,13 @@ class HashTable: public FixedArray { ...@@ -2094,6 +2096,13 @@ class HashTable: public FixedArray {
fast_set(this, kCapacityIndex, Smi::FromInt(capacity)); fast_set(this, kCapacityIndex, Smi::FromInt(capacity));
} }
// Returns probe entry.
static uint32_t GetProbe(uint32_t hash, uint32_t number, uint32_t size) {
ASSERT(IsPowerOf2(size));
return (hash + GetProbeOffset(number)) & (size - 1);
}
// Ensure enough space for n additional elements. // Ensure enough space for n additional elements.
Object* EnsureCapacity(int n, Key key); Object* EnsureCapacity(int n, Key key);
}; };
......
...@@ -211,21 +211,6 @@ inline byte* DecodeUnsignedIntBackward(byte* p, unsigned int* x) { ...@@ -211,21 +211,6 @@ inline byte* DecodeUnsignedIntBackward(byte* p, unsigned int* x) {
uint32_t ComputeIntegerHash(uint32_t key); uint32_t ComputeIntegerHash(uint32_t key);
// ----------------------------------------------------------------------------
// Bitwise rotate word
inline uint32_t RotateRight(uint32_t value, uint32_t n) {
ASSERT(n < 31);
return (value >> n) | (value << (32-n));
}
inline uint32_t RotateLeft(uint32_t value, uint32_t n) {
ASSERT(n < 31);
return (value << n) | (value >> (32-n));
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// I/O support. // I/O support.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment