Index: src/x64/ic-x64.cc |
=================================================================== |
--- src/x64/ic-x64.cc (revision 4975) |
+++ src/x64/ic-x64.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,34 +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. |
- // |
- // r0 - used to hold the capacity of the property dictionary. |
- // |
- // r1 - used to hold the index into the property dictionary. |
- // |
- // result - holds the result on exit if the load succeeded. |
- |
- 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 |r1|. 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 + |
@@ -157,14 +140,58 @@ |
__ cmpq(name, Operand(elements, r1, times_pointer_size, |
kElementsStartOffset - kHeapObjectTag)); |
if (i != kProbes - 1) { |
- __ j(equal, &done); |
+ __ j(equal, done); |
} else { |
- __ j(not_equal, miss_label); |
+ __ j(not_equal, miss); |
} |
} |
+} |
- // Check that the value is a normal property. |
+ |
+// 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. |
+ // |
+ // r0 - used to hold the capacity of the property dictionary. |
+ // |
+ // r1 - used to hold the index into the property dictionary. |
+ // |
+ // result - holds the result on exit if the load succeeded. |
+ |
+ 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, r1, times_pointer_size, |
kDetailsOffset - kHeapObjectTag), |
@@ -179,6 +206,75 @@ |
} |
+// Helper function used to store a property to a dictionary backing |
+// storage. This function may fail to store a property even though 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 scratch0, |
+ Register scratch1) { |
+ // 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. |
+ // |
+ // scratch0 - used for index into the property dictionary and is clobbered. |
+ // |
+ // scratch1 - used to hold the capacity of the property dictionary and is |
+ // clobbered. |
+ Label done; |
+ |
+ // Probe the dictionary. |
+ GenerateStringDictionaryProbes(masm, |
+ miss_label, |
+ &done, |
+ elements, |
+ name, |
+ scratch0, |
+ scratch1); |
+ |
+ // If probing finds an entry in the dictionary, scratch0 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, |
+ scratch1, |
+ times_pointer_size, |
+ kDetailsOffset - kHeapObjectTag), |
+ Smi::FromInt(kTypeAndReadOnlyMask)); |
+ __ j(not_zero, miss_label); |
+ |
+ // Store the value at the masked, scaled index. |
+ const int kValueOffset = kElementsStartOffset + kPointerSize; |
+ __ lea(scratch1, Operand(elements, |
+ scratch1, |
+ times_pointer_size, |
+ kValueOffset - kHeapObjectTag)); |
+ __ movq(Operand(scratch1, 0), value); |
+ |
+ // Update write barrier. Make sure not to clobber the value. |
+ __ movq(scratch0, value); |
+ __ RecordWrite(elements, scratch1, scratch0); |
+} |
+ |
+ |
static void GenerateNumberDictionaryLoad(MacroAssembler* masm, |
Label* miss, |
Register elements, |
@@ -1332,7 +1428,7 @@ |
// Get the receiver of the function from the stack. |
__ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); |
- GenerateDictionaryLoadReceiverCheck(masm, rdx, rax, rbx, &miss); |
+ GenerateStringDictionaryReceiverCheck(masm, rdx, rax, rbx, &miss); |
// rax: elements |
// Search the dictionary placing the result in rdi. |
@@ -1616,7 +1712,7 @@ |
// ----------------------------------- |
Label miss; |
- GenerateDictionaryLoadReceiverCheck(masm, rax, rdx, rbx, &miss); |
+ GenerateStringDictionaryReceiverCheck(masm, rax, rdx, rbx, &miss); |
// rdx: elements |
// Search the dictionary placing the result in rax. |
@@ -1760,6 +1856,28 @@ |
} |
+void StoreIC::GenerateNormal(MacroAssembler* masm) { |
+ // ----------- S t a t e ------------- |
+ // -- rax : value |
+ // -- rcx : name |
+ // -- rdx : receiver |
+ // -- rsp[0] : return address |
+ // ----------------------------------- |
+ |
+ Label miss, restore_miss; |
+ |
+ GenerateStringDictionaryReceiverCheck(masm, rdx, rbx, rdi, &miss); |
+ |
+ GenerateDictionaryStore(masm, &miss, rbx, rcx, rax, r8, r9); |
+ __ IncrementCounter(&Counters::store_normal_hit, 1); |
+ __ ret(0); |
+ |
+ __ bind(&miss); |
+ __ IncrementCounter(&Counters::store_normal_miss, 1); |
+ GenerateMiss(masm); |
+} |
+ |
+ |
#undef __ |