Index: src/ia32/ic-ia32.cc |
=================================================================== |
--- src/ia32/ic-ia32.cc (revision 4975) |
+++ src/ia32/ic-ia32.cc (working copy) |
@@ -61,11 +61,11 @@ |
// Generated code falls through if the receiver is a regular non-global |
// JS object with slow properties and no interceptors. |
-static void GenerateDictionaryLoadReceiverCheck(MacroAssembler* masm, |
- Register receiver, |
- Register r0, |
- Register r1, |
- Label* miss) { |
+static void GenerateStringDictionaryReceiverCheck(MacroAssembler* masm, |
+ Register receiver, |
+ Register r0, |
+ Register r1, |
+ Label* miss) { |
// Register usage: |
// receiver: holds the receiver on entry and is unchanged. |
// r0: used to hold receiver instance type. |
@@ -98,36 +98,17 @@ |
} |
-// Helper function used to load a property from a dictionary backing storage. |
-// This function may return false negatives, so miss_label |
-// must always call a backup property load that is complete. |
-// This function is safe to call if name is not a symbol, and will jump to |
-// the miss_label in that case. |
-// The generated code assumes that the receiver has slow properties, |
-// is not a global object and does not have interceptors. |
-static void GenerateDictionaryLoad(MacroAssembler* masm, |
- Label* miss_label, |
- Register elements, |
- Register name, |
- Register r0, |
- Register r1, |
- Register result) { |
- // Register use: |
- // |
- // elements - holds the property dictionary on entry and is unchanged. |
- // |
- // name - holds the name of the property on entry and is unchanged. |
- // |
- // Scratch registers: |
- // |
- // r0 - used for the index into the property dictionary |
- // |
- // r1 - used to hold the capacity of the property dictionary. |
- // |
- // result - holds the result on exit. |
- |
- Label 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 |r0|. Jump to the |miss| label |
+// otherwise. |
+static void GenerateStringDictionaryProbes(MacroAssembler* masm, |
+ Label* miss, |
+ Label* done, |
+ Register elements, |
+ Register name, |
+ Register r0, |
+ Register r1) { |
// Compute the capacity mask. |
const int kCapacityOffset = |
StringDictionary::kHeaderSize + |
@@ -160,14 +141,61 @@ |
__ cmp(name, Operand(elements, r0, times_4, |
kElementsStartOffset - kHeapObjectTag)); |
if (i != kProbes - 1) { |
- __ j(equal, &done, taken); |
+ __ j(equal, done, taken); |
} else { |
- __ j(not_equal, miss_label, not_taken); |
+ __ j(not_equal, miss, not_taken); |
} |
} |
+} |
- // Check that the value is a normal property. |
+ |
+ |
+// Helper function used to load a property from a dictionary backing |
+// storage. This function may fail to load a property even though it is |
+// in the dictionary, so code at miss_label must always call a backup |
+// property load that is complete. This function is safe to call if |
+// name is not a symbol, and will jump to the miss_label in that |
+// case. The generated code assumes that the receiver has slow |
+// properties, is not a global object and does not have interceptors. |
+static void GenerateDictionaryLoad(MacroAssembler* masm, |
+ Label* miss_label, |
+ Register elements, |
+ Register name, |
+ Register r0, |
+ Register r1, |
+ Register result) { |
+ // Register use: |
+ // |
+ // elements - holds the property dictionary on entry and is unchanged. |
+ // |
+ // name - holds the name of the property on entry and is unchanged. |
+ // |
+ // Scratch registers: |
+ // |
+ // r0 - used for the index into the property dictionary |
+ // |
+ // r1 - used to hold the capacity of the property dictionary. |
+ // |
+ // result - holds the result on exit. |
+ |
+ Label done; |
+ |
+ // Probe the dictionary. |
+ GenerateStringDictionaryProbes(masm, |
+ miss_label, |
+ &done, |
+ elements, |
+ name, |
+ r0, |
+ r1); |
+ |
+ // If probing finds an entry in the dictionary, r0 contains the |
+ // index into the dictionary. Check that the value is a normal |
+ // property. |
__ bind(&done); |
+ const int kElementsStartOffset = |
+ StringDictionary::kHeaderSize + |
+ StringDictionary::kElementsStartIndex * kPointerSize; |
const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; |
__ test(Operand(elements, r0, times_4, kDetailsOffset - kHeapObjectTag), |
Immediate(PropertyDetails::TypeField::mask() << kSmiTagSize)); |
@@ -179,6 +207,69 @@ |
} |
+// Helper function used to store a property to a dictionary backing |
+// storage. This function may fail to store a property eventhough it |
+// is in the dictionary, so code at miss_label must always call a |
+// backup property store that is complete. This function is safe to |
+// call if name is not a symbol, and will jump to the miss_label in |
+// that case. The generated code assumes that the receiver has slow |
+// properties, is not a global object and does not have interceptors. |
+static void GenerateDictionaryStore(MacroAssembler* masm, |
+ Label* miss_label, |
+ Register elements, |
+ Register name, |
+ Register value, |
+ Register r0, |
+ Register r1) { |
+ // Register use: |
+ // |
+ // elements - holds the property dictionary on entry and is clobbered. |
+ // |
+ // name - holds the name of the property on entry and is unchanged. |
+ // |
+ // value - holds the value to store and is unchanged. |
+ // |
+ // r0 - used for index into the property dictionary and is clobbered. |
+ // |
+ // r1 - used to hold the capacity of the property dictionary and is clobbered. |
+ Label done; |
+ |
+ |
+ // Probe the dictionary. |
+ GenerateStringDictionaryProbes(masm, |
+ miss_label, |
+ &done, |
+ elements, |
+ name, |
+ r0, |
+ r1); |
+ |
+ // If probing finds an entry in the dictionary, r0 contains the |
+ // index into the dictionary. Check that the value is a normal |
+ // property that is not read only. |
+ __ bind(&done); |
+ const int kElementsStartOffset = |
+ StringDictionary::kHeaderSize + |
+ StringDictionary::kElementsStartIndex * kPointerSize; |
+ const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; |
+ const int kTypeAndReadOnlyMask |
+ = (PropertyDetails::TypeField::mask() | |
+ PropertyDetails::AttributesField::encode(READ_ONLY)) << kSmiTagSize; |
+ __ test(Operand(elements, r0, times_4, kDetailsOffset - kHeapObjectTag), |
+ Immediate(kTypeAndReadOnlyMask)); |
+ __ j(not_zero, miss_label, not_taken); |
+ |
+ // Store the value at the masked, scaled index. |
+ const int kValueOffset = kElementsStartOffset + kPointerSize; |
+ __ lea(r0, Operand(elements, r0, times_4, kValueOffset - kHeapObjectTag)); |
+ __ mov(Operand(r0, 0), value); |
+ |
+ // Update write barrier. Make sure not to clobber the value. |
+ __ mov(r1, value); |
+ __ RecordWrite(elements, r0, r1); |
+} |
+ |
+ |
static void GenerateNumberDictionaryLoad(MacroAssembler* masm, |
Label* miss, |
Register elements, |
@@ -1238,7 +1329,7 @@ |
// Get the receiver of the function from the stack; 1 ~ return address. |
__ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
- GenerateDictionaryLoadReceiverCheck(masm, edx, eax, ebx, &miss); |
+ GenerateStringDictionaryReceiverCheck(masm, edx, eax, ebx, &miss); |
// eax: elements |
// Search the dictionary placing the result in edi. |
@@ -1517,7 +1608,7 @@ |
// ----------------------------------- |
Label miss; |
- GenerateDictionaryLoadReceiverCheck(masm, eax, edx, ebx, &miss); |
+ GenerateStringDictionaryReceiverCheck(masm, eax, edx, ebx, &miss); |
// edx: elements |
// Search the dictionary placing the result in eax. |
@@ -1775,6 +1866,36 @@ |
} |
+void StoreIC::GenerateNormal(MacroAssembler* masm) { |
+ // ----------- S t a t e ------------- |
+ // -- eax : value |
+ // -- ecx : name |
+ // -- edx : receiver |
+ // -- esp[0] : return address |
+ // ----------------------------------- |
+ |
+ Label miss, restore_miss; |
+ |
+ GenerateStringDictionaryReceiverCheck(masm, edx, ebx, edi, &miss); |
+ |
+ // A lot of registers are needed for storing to slow case |
+ // objects. Push and restore receiver but rely on |
+ // GenerateDictionaryStore preserving the value and name. |
+ __ push(edx); |
+ GenerateDictionaryStore(masm, &restore_miss, ebx, ecx, eax, edx, edi); |
+ __ Drop(1); |
+ __ IncrementCounter(&Counters::store_normal_hit, 1); |
+ __ ret(0); |
+ |
+ __ bind(&restore_miss); |
+ __ pop(edx); |
+ |
+ __ bind(&miss); |
+ __ IncrementCounter(&Counters::store_normal_miss, 1); |
+ GenerateMiss(masm); |
+} |
+ |
+ |
// Defined in ic.cc. |
Object* KeyedStoreIC_Miss(Arguments args); |