Chromium Code Reviews| Index: src/x64/code-stubs-x64.cc |
| diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc |
| index ec1c185620579e26087026c554cc0a2ae19b5688..9381b6900a6a07645b5212c33bc9033f5fbc0954 100644 |
| --- a/src/x64/code-stubs-x64.cc |
| +++ b/src/x64/code-stubs-x64.cc |
| @@ -996,7 +996,7 @@ void TypeRecordingBinaryOpStub::GenerateFloatingPointCode( |
| // We need tagged values in rdx and rax for the following code, |
| // not int32 in rax and rcx. |
| __ Integer32ToSmi(rax, rcx); |
| - __ Integer32ToSmi(rdx, rax); |
| + __ Integer32ToSmi(rdx, rbx); |
|
Mads Ager (chromium)
2011/05/05 11:54:56
This is fixed in Florian's commit too, right?
Vyacheslav Egorov (Chromium)
2011/05/05 12:30:16
Yep, this is accidental change.
|
| __ jmp(allocation_failure); |
| } |
| break; |
| @@ -4736,6 +4736,203 @@ void ICCompareStub::GenerateMiss(MacroAssembler* masm) { |
| } |
| +void StringDictionaryLookupStub::GenerateNegativeLookup(MacroAssembler* masm, |
| + Label* miss, |
| + Label* done, |
| + Register properties, |
| + String* name, |
| + Register r0) { |
| + // If names of slots in range from 1 to kProbes - 1 for the hash value are |
| + // not equal to the name and kProbes-th slot is not used (its name is the |
| + // undefined value), it guarantees the hash table doesn't contain the |
| + // property. It's true even if some slots represent deleted properties |
| + // (their names are the null value). |
| + for (int i = 0; i < kInlinedProbes; i++) { |
| + // r0 points to properties hash. |
| + // Compute the masked index: (hash + i + i * i) & mask. |
| + Register index = r0; |
| + // Capacity is smi 2^n. |
| + __ SmiToInteger32(index, FieldOperand(properties, kCapacityOffset)); |
| + __ decl(index); |
| + __ and_(index, |
|
Lasse Reichstein
2011/05/05 14:20:13
Use andl instead of and_, one byte shorter.
|
| + Immediate(name->Hash() + StringDictionary::GetProbeOffset(i))); |
| + |
| + // Scale the index by multiplying by the entry size. |
| + ASSERT(StringDictionary::kEntrySize == 3); |
| + __ lea(index, Operand(index, index, times_2, 0)); // index *= 3. |
|
Lasse Reichstein
2011/05/05 14:20:13
Use leal instead of lea for 32-bit operations - un
|
| + |
| + Register entity_name = r0; |
| + // Having undefined at this place means the name is not contained. |
| + ASSERT_EQ(kSmiTagSize, 1); |
| + __ movq(entity_name, Operand(properties, |
| + index, |
| + times_pointer_size, |
| + kElementsStartOffset - kHeapObjectTag)); |
| + __ Cmp(entity_name, masm->isolate()->factory()->undefined_value()); |
|
Lasse Reichstein
2011/05/05 14:20:13
We typically use CompareRoot for this.
|
| + __ j(equal, done); |
| + |
| + // Stop if found the property. |
| + __ Cmp(entity_name, Handle<String>(name)); |
| + __ j(equal, miss); |
| + |
| + // Check if the entry name is not a symbol. |
| + __ movq(entity_name, FieldOperand(entity_name, HeapObject::kMapOffset)); |
| + __ testb(FieldOperand(entity_name, Map::kInstanceTypeOffset), |
| + Immediate(kIsSymbolMask)); |
| + __ j(zero, miss); |
| + } |
| + |
| + StringDictionaryLookupStub stub(properties, |
| + r0, |
| + r0, |
| + StringDictionaryLookupStub::NEGATIVE_LOOKUP); |
| + __ Push(Handle<Object>(name)); |
| + __ push(Immediate(name->Hash())); |
| + __ CallStub(&stub); |
| + __ testq(r0, r0); |
|
Lasse Reichstein
2011/05/05 14:20:13
If the result is guaranteed to have its nonzero bi
|
| + __ j(not_zero, miss); |
| + __ jmp(done); |
| +} |
| + |
| + |
| +// Probe the string dictionary in the |elements| register. Jump to the |
| +// |done| label if a property with the given name is found leaving the |
| +// index into the dictionary in |r1|. Jump to the |miss| label |
| +// otherwise. |
| +void StringDictionaryLookupStub::GeneratePositiveLookup(MacroAssembler* masm, |
| + Label* miss, |
| + Label* done, |
| + Register elements, |
| + Register name, |
| + Register r0, |
| + Register r1) { |
| + // Assert that name contains a string. |
| + if (FLAG_debug_code) __ AbortIfNotString(name); |
| + |
| + __ SmiToInteger32(r0, FieldOperand(elements, kCapacityOffset)); |
| + __ decl(r0); |
| + |
| + for (int i = 0; i < kInlinedProbes; i++) { |
| + // Compute the masked index: (hash + i + i * i) & mask. |
| + __ movl(r1, FieldOperand(name, String::kHashFieldOffset)); |
| + __ shrl(r1, Immediate(String::kHashShift)); |
| + if (i > 0) { |
| + __ addl(r1, Immediate(StringDictionary::GetProbeOffset(i))); |
| + } |
| + __ and_(r1, r0); |
|
Lasse Reichstein
2011/05/05 14:20:13
andl
|
| + |
| + // Scale the index by multiplying by the entry size. |
| + ASSERT(StringDictionary::kEntrySize == 3); |
| + __ lea(r1, Operand(r1, r1, times_2, 0)); // r1 = r1 * 3 |
|
Lasse Reichstein
2011/05/05 14:20:13
leal
|
| + |
| + // Check if the key is identical to the name. |
| + __ cmpq(name, Operand(elements, r1, times_pointer_size, |
| + kElementsStartOffset - kHeapObjectTag)); |
| + __ j(equal, done); |
| + } |
| + |
| + StringDictionaryLookupStub stub(elements, |
| + r0, |
| + r1, |
| + POSITIVE_LOOKUP); |
| + __ push(name); |
| + __ movl(r0, FieldOperand(name, String::kHashFieldOffset)); |
| + __ shrl(r0, Immediate(String::kHashShift)); |
| + __ push(r0); |
| + __ CallStub(&stub); |
| + |
| + __ testq(r0, r0); |
|
Lasse Reichstein
2011/05/05 14:20:13
Possibly testl.
|
| + __ j(zero, miss); |
| + __ jmp(done); |
| +} |
| + |
| + |
| +void StringDictionaryLookupStub::Generate(MacroAssembler* masm) { |
| + // Stack frame on entry: |
| + // esp[0 * kPointerSize]: return address. |
|
Lasse Reichstein
2011/05/05 14:20:13
esp->rsp
|
| + // esp[1 * kPointerSize]: key's hash. |
| + // esp[2 * kPointerSize]: key. |
| + // Registers: |
| + // dictionary_: StringDictionary to probe. |
| + // result_: used as scratch. |
| + // index_: will hold an index of entry if lookup is successful. |
| + // might alias with result_. |
| + // Returns: |
| + // result_ is zero if lookup failed, non zero otherwise. |
|
Lasse Reichstein
2011/05/05 14:20:13
Document that it's nonzero when used as a double-w
|
| + |
| + Label in_dictionary, maybe_in_dictionary, not_in_dictionary; |
| + |
| + Register scratch = result_; |
| + |
| + __ SmiToInteger32(scratch, FieldOperand(dictionary_, kCapacityOffset)); |
| + __ decl(scratch); |
| + __ push(scratch); |
| + |
| + // If names of slots in range from 1 to kProbes - 1 for the hash value are |
| + // not equal to the name and kProbes-th slot is not used (its name is the |
| + // undefined value), it guarantees the hash table doesn't contain the |
| + // property. It's true even if some slots represent deleted properties |
| + // (their names are the null value). |
| + for (int i = kInlinedProbes; i < kTotalProbes; i++) { |
| + // Compute the masked index: (hash + i + i * i) & mask. |
| + __ movq(scratch, Operand(rsp, 2 * kPointerSize)); |
| + if (i > 0) { |
| + __ addl(scratch, Immediate(StringDictionary::GetProbeOffset(i))); |
| + } |
| + __ and_(scratch, Operand(rsp, 0)); |
|
Lasse Reichstein
2011/05/05 14:20:13
andl
|
| + |
| + // Scale the index by multiplying by the entry size. |
| + ASSERT(StringDictionary::kEntrySize == 3); |
| + __ lea(index_, Operand(scratch, scratch, times_2, 0)); // index *= 3. |
|
Lasse Reichstein
2011/05/05 14:20:13
leal
|
| + |
| + // Having undefined at this place means the name is not contained. |
| + __ movq(scratch, Operand(dictionary_, |
| + index_, |
| + times_pointer_size, |
| + kElementsStartOffset - kHeapObjectTag)); |
| + |
| + __ Cmp(scratch, masm->isolate()->factory()->undefined_value()); |
|
Lasse Reichstein
2011/05/05 14:20:13
CompareRoot
|
| + __ j(equal, ¬_in_dictionary); |
| + |
| + // Stop if found the property. |
| + __ cmpq(scratch, Operand(rsp, 3 * kPointerSize)); |
| + __ j(equal, &in_dictionary); |
| + |
| + if (i != kTotalProbes - 1 && mode_ == NEGATIVE_LOOKUP) { |
| + // If we hit a non symbol key during negative lookup |
| + // we have to bailout as this key might be equal to the |
| + // key we are looking for. |
| + |
| + // Check if the entry name is not a symbol. |
| + __ movq(scratch, FieldOperand(scratch, HeapObject::kMapOffset)); |
| + __ testb(FieldOperand(scratch, Map::kInstanceTypeOffset), |
| + Immediate(kIsSymbolMask)); |
| + __ j(zero, &maybe_in_dictionary); |
| + } |
| + } |
| + |
| + __ bind(&maybe_in_dictionary); |
| + // If we are doing negative lookup then probing failure should be |
| + // treated as a lookup success. For positive lookup probing failure |
| + // should be treated as lookup failure. |
| + if (mode_ == POSITIVE_LOOKUP) { |
| + __ movq(scratch, Immediate(0)); |
|
Lasse Reichstein
2011/05/05 14:20:13
__ Move(scratch, 0); // will use xor
|
| + __ Drop(1); |
| + __ ret(2 * kPointerSize); |
| + } |
| + |
| + __ bind(&in_dictionary); |
| + __ movq(scratch, Immediate(1)); |
|
Lasse Reichstein
2011/05/05 14:20:13
Consider using Move
|
| + __ Drop(1); |
| + __ ret(2 * kPointerSize); |
| + |
| + __ bind(¬_in_dictionary); |
| + __ movq(scratch, Immediate(0)); |
|
Lasse Reichstein
2011/05/05 14:20:13
Use Move.
|
| + __ Drop(1); |
| + __ ret(2 * kPointerSize); |
| +} |
| + |
| + |
| #undef __ |
| } } // namespace v8::internal |