OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #if V8_TARGET_ARCH_X64 | 5 #if V8_TARGET_ARCH_X64 |
6 | 6 |
7 #include "src/codegen.h" | 7 #include "src/codegen.h" |
8 #include "src/ic/ic.h" | 8 #include "src/ic/ic.h" |
9 #include "src/ic/ic-compiler.h" | 9 #include "src/ic/ic-compiler.h" |
10 #include "src/ic/stub-cache.h" | 10 #include "src/ic/stub-cache.h" |
11 | 11 |
12 namespace v8 { | 12 namespace v8 { |
13 namespace internal { | 13 namespace internal { |
14 | 14 |
15 // ---------------------------------------------------------------------------- | 15 // ---------------------------------------------------------------------------- |
16 // Static IC stub generators. | 16 // Static IC stub generators. |
17 // | 17 // |
18 | 18 |
19 #define __ ACCESS_MASM(masm) | 19 #define __ ACCESS_MASM(masm) |
20 | 20 |
21 // Helper function used to load a property from a dictionary backing storage. | |
22 // This function may return false negatives, so miss_label | |
23 // must always call a backup property load that is complete. | |
24 // This function is safe to call if name is not an internalized string, | |
25 // and will jump to the miss_label in that case. | |
26 // The generated code assumes that the receiver has slow properties, | |
27 // is not a global object and does not have interceptors. | |
28 static void GenerateDictionaryLoad(MacroAssembler* masm, Label* miss_label, | |
29 Register elements, Register name, | |
30 Register r0, Register r1, Register result) { | |
31 // Register use: | |
32 // | |
33 // elements - holds the property dictionary on entry and is unchanged. | |
34 // | |
35 // name - holds the name of the property on entry and is unchanged. | |
36 // | |
37 // r0 - used to hold the capacity of the property dictionary. | |
38 // | |
39 // r1 - used to hold the index into the property dictionary. | |
40 // | |
41 // result - holds the result on exit if the load succeeded. | |
42 | |
43 Label done; | |
44 | |
45 // Probe the dictionary. | |
46 NameDictionaryLookupStub::GeneratePositiveLookup(masm, miss_label, &done, | |
47 elements, name, r0, r1); | |
48 | |
49 // If probing finds an entry in the dictionary, r1 contains the | |
50 // index into the dictionary. Check that the value is a normal | |
51 // property. | |
52 __ bind(&done); | |
53 const int kElementsStartOffset = | |
54 NameDictionary::kHeaderSize + | |
55 NameDictionary::kElementsStartIndex * kPointerSize; | |
56 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; | |
57 __ Test(Operand(elements, r1, times_pointer_size, | |
58 kDetailsOffset - kHeapObjectTag), | |
59 Smi::FromInt(PropertyDetails::TypeField::kMask)); | |
60 __ j(not_zero, miss_label); | |
61 | |
62 // Get the value at the masked, scaled index. | |
63 const int kValueOffset = kElementsStartOffset + kPointerSize; | |
64 __ movp(result, Operand(elements, r1, times_pointer_size, | |
65 kValueOffset - kHeapObjectTag)); | |
66 } | |
67 | |
68 | |
69 // Helper function used to store a property to a dictionary backing | |
70 // storage. This function may fail to store a property even though it | |
71 // is in the dictionary, so code at miss_label must always call a | |
72 // backup property store that is complete. This function is safe to | |
73 // call if name is not an internalized string, and will jump to the miss_label | |
74 // in that case. The generated code assumes that the receiver has slow | |
75 // properties, is not a global object and does not have interceptors. | |
76 static void GenerateDictionaryStore(MacroAssembler* masm, Label* miss_label, | |
77 Register elements, Register name, | |
78 Register value, Register scratch0, | |
79 Register scratch1) { | |
80 // Register use: | |
81 // | |
82 // elements - holds the property dictionary on entry and is clobbered. | |
83 // | |
84 // name - holds the name of the property on entry and is unchanged. | |
85 // | |
86 // value - holds the value to store and is unchanged. | |
87 // | |
88 // scratch0 - used during the positive dictionary lookup and is clobbered. | |
89 // | |
90 // scratch1 - used for index into the property dictionary and is clobbered. | |
91 Label done; | |
92 | |
93 // Probe the dictionary. | |
94 NameDictionaryLookupStub::GeneratePositiveLookup( | |
95 masm, miss_label, &done, elements, name, scratch0, scratch1); | |
96 | |
97 // If probing finds an entry in the dictionary, scratch0 contains the | |
98 // index into the dictionary. Check that the value is a normal | |
99 // property that is not read only. | |
100 __ bind(&done); | |
101 const int kElementsStartOffset = | |
102 NameDictionary::kHeaderSize + | |
103 NameDictionary::kElementsStartIndex * kPointerSize; | |
104 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; | |
105 const int kTypeAndReadOnlyMask = | |
106 PropertyDetails::TypeField::kMask | | |
107 PropertyDetails::AttributesField::encode(READ_ONLY); | |
108 __ Test(Operand(elements, scratch1, times_pointer_size, | |
109 kDetailsOffset - kHeapObjectTag), | |
110 Smi::FromInt(kTypeAndReadOnlyMask)); | |
111 __ j(not_zero, miss_label); | |
112 | |
113 // Store the value at the masked, scaled index. | |
114 const int kValueOffset = kElementsStartOffset + kPointerSize; | |
115 __ leap(scratch1, Operand(elements, scratch1, times_pointer_size, | |
116 kValueOffset - kHeapObjectTag)); | |
117 __ movp(Operand(scratch1, 0), value); | |
118 | |
119 // Update write barrier. Make sure not to clobber the value. | |
120 __ movp(scratch0, value); | |
121 __ RecordWrite(elements, scratch1, scratch0, kDontSaveFPRegs); | |
122 } | |
123 | |
124 void LoadIC::GenerateNormal(MacroAssembler* masm) { | |
125 Register dictionary = rax; | |
126 DCHECK(!dictionary.is(LoadDescriptor::ReceiverRegister())); | |
127 DCHECK(!dictionary.is(LoadDescriptor::NameRegister())); | |
128 | |
129 Label slow; | |
130 | |
131 __ movp(dictionary, FieldOperand(LoadDescriptor::ReceiverRegister(), | |
132 JSObject::kPropertiesOffset)); | |
133 GenerateDictionaryLoad(masm, &slow, dictionary, | |
134 LoadDescriptor::NameRegister(), rbx, rdi, rax); | |
135 __ ret(0); | |
136 | |
137 // Dictionary load failed, go slow (but don't miss). | |
138 __ bind(&slow); | |
139 LoadIC::GenerateRuntimeGetProperty(masm); | |
140 } | |
141 | |
142 void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { | |
143 // The return address is on the stack. | |
144 Register receiver = LoadDescriptor::ReceiverRegister(); | |
145 Register name = LoadDescriptor::NameRegister(); | |
146 | |
147 DCHECK(!rbx.is(receiver) && !rbx.is(name)); | |
148 | |
149 __ PopReturnAddressTo(rbx); | |
150 __ Push(receiver); | |
151 __ Push(name); | |
152 __ PushReturnAddressFrom(rbx); | |
153 | |
154 // Do tail-call to runtime routine. | |
155 __ TailCallRuntime(Runtime::kGetProperty); | |
156 } | |
157 | |
158 static void StoreIC_PushArgs(MacroAssembler* masm) { | 21 static void StoreIC_PushArgs(MacroAssembler* masm) { |
159 Register receiver = StoreWithVectorDescriptor::ReceiverRegister(); | 22 Register receiver = StoreWithVectorDescriptor::ReceiverRegister(); |
160 Register name = StoreWithVectorDescriptor::NameRegister(); | 23 Register name = StoreWithVectorDescriptor::NameRegister(); |
161 Register value = StoreWithVectorDescriptor::ValueRegister(); | 24 Register value = StoreWithVectorDescriptor::ValueRegister(); |
162 Register slot = StoreWithVectorDescriptor::SlotRegister(); | 25 Register slot = StoreWithVectorDescriptor::SlotRegister(); |
163 Register vector = StoreWithVectorDescriptor::VectorRegister(); | 26 Register vector = StoreWithVectorDescriptor::VectorRegister(); |
164 Register temp = r11; | 27 Register temp = r11; |
165 DCHECK(!AreAliased(receiver, name, value, slot, vector, temp)); | 28 DCHECK(!AreAliased(receiver, name, value, slot, vector, temp)); |
166 | 29 |
167 __ PopReturnAddressTo(temp); | 30 __ PopReturnAddressTo(temp); |
168 __ Push(value); | 31 __ Push(value); |
169 __ Push(slot); | 32 __ Push(slot); |
170 __ Push(vector); | 33 __ Push(vector); |
171 __ Push(receiver); | 34 __ Push(receiver); |
172 __ Push(name); | 35 __ Push(name); |
173 __ PushReturnAddressFrom(temp); | 36 __ PushReturnAddressFrom(temp); |
174 } | 37 } |
175 | 38 |
176 | |
177 void StoreIC::GenerateMiss(MacroAssembler* masm) { | |
178 // Return address is on the stack. | |
179 StoreIC_PushArgs(masm); | |
180 | |
181 // Perform tail call to the entry. | |
182 __ TailCallRuntime(Runtime::kStoreIC_Miss); | |
183 } | |
184 | |
185 | |
186 void StoreIC::GenerateNormal(MacroAssembler* masm) { | |
187 Register receiver = StoreDescriptor::ReceiverRegister(); | |
188 Register name = StoreDescriptor::NameRegister(); | |
189 Register value = StoreDescriptor::ValueRegister(); | |
190 Register dictionary = r11; | |
191 DCHECK(!AreAliased(dictionary, StoreWithVectorDescriptor::VectorRegister(), | |
192 StoreWithVectorDescriptor::SlotRegister())); | |
193 | |
194 Label miss; | |
195 | |
196 __ movp(dictionary, FieldOperand(receiver, JSObject::kPropertiesOffset)); | |
197 GenerateDictionaryStore(masm, &miss, dictionary, name, value, r8, r9); | |
198 Counters* counters = masm->isolate()->counters(); | |
199 __ IncrementCounter(counters->ic_store_normal_hit(), 1); | |
200 __ ret(0); | |
201 | |
202 __ bind(&miss); | |
203 __ IncrementCounter(counters->ic_store_normal_miss(), 1); | |
204 GenerateMiss(masm); | |
205 } | |
206 | |
207 | |
208 void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { | 39 void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { |
209 // Return address is on the stack. | 40 // Return address is on the stack. |
210 StoreIC_PushArgs(masm); | 41 StoreIC_PushArgs(masm); |
211 | 42 |
212 // Do tail-call to runtime routine. | 43 // Do tail-call to runtime routine. |
213 __ TailCallRuntime(Runtime::kKeyedStoreIC_Miss); | 44 __ TailCallRuntime(Runtime::kKeyedStoreIC_Miss); |
214 } | 45 } |
215 | 46 |
216 void KeyedStoreIC::GenerateSlow(MacroAssembler* masm) { | 47 void KeyedStoreIC::GenerateSlow(MacroAssembler* masm) { |
217 // Return address is on the stack. | 48 // Return address is on the stack. |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
290 Condition cc = | 121 Condition cc = |
291 (check == ENABLE_INLINED_SMI_CHECK) | 122 (check == ENABLE_INLINED_SMI_CHECK) |
292 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) | 123 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) |
293 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); | 124 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); |
294 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); | 125 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); |
295 } | 126 } |
296 } // namespace internal | 127 } // namespace internal |
297 } // namespace v8 | 128 } // namespace v8 |
298 | 129 |
299 #endif // V8_TARGET_ARCH_X64 | 130 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |