Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: src/ic/x64/ic-x64.cc

Issue 483683005: Move IC code into a subdir and move ic-compilation related code from stub-cache into ic-compiler (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Fix BUILD.gn Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ic/x64/ic-compiler-x64.cc ('k') | src/ic/x64/stub-cache-x64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 #include "src/v8.h" 5 #include "src/v8.h"
6 6
7 #if V8_TARGET_ARCH_X64 7 #if V8_TARGET_ARCH_X64
8 8
9 #include "src/codegen.h" 9 #include "src/codegen.h"
10 #include "src/ic-inl.h" 10 #include "src/ic/ic.h"
11 #include "src/runtime.h" 11 #include "src/ic/stub-cache.h"
12 #include "src/stub-cache.h"
13 12
14 namespace v8 { 13 namespace v8 {
15 namespace internal { 14 namespace internal {
16 15
17 // ---------------------------------------------------------------------------- 16 // ----------------------------------------------------------------------------
18 // Static IC stub generators. 17 // Static IC stub generators.
19 // 18 //
20 19
21 #define __ ACCESS_MASM(masm) 20 #define __ ACCESS_MASM(masm)
22 21
23 22
24 static void GenerateGlobalInstanceTypeCheck(MacroAssembler* masm, 23 static void GenerateGlobalInstanceTypeCheck(MacroAssembler* masm, Register type,
25 Register type,
26 Label* global_object) { 24 Label* global_object) {
27 // Register usage: 25 // Register usage:
28 // type: holds the receiver instance type on entry. 26 // type: holds the receiver instance type on entry.
29 __ cmpb(type, Immediate(JS_GLOBAL_OBJECT_TYPE)); 27 __ cmpb(type, Immediate(JS_GLOBAL_OBJECT_TYPE));
30 __ j(equal, global_object); 28 __ j(equal, global_object);
31 __ cmpb(type, Immediate(JS_BUILTINS_OBJECT_TYPE)); 29 __ cmpb(type, Immediate(JS_BUILTINS_OBJECT_TYPE));
32 __ j(equal, global_object); 30 __ j(equal, global_object);
33 __ cmpb(type, Immediate(JS_GLOBAL_PROXY_TYPE)); 31 __ cmpb(type, Immediate(JS_GLOBAL_PROXY_TYPE));
34 __ j(equal, global_object); 32 __ j(equal, global_object);
35 } 33 }
36 34
37 35
38 // Helper function used to load a property from a dictionary backing storage. 36 // Helper function used to load a property from a dictionary backing storage.
39 // This function may return false negatives, so miss_label 37 // This function may return false negatives, so miss_label
40 // must always call a backup property load that is complete. 38 // must always call a backup property load that is complete.
41 // This function is safe to call if name is not an internalized string, 39 // This function is safe to call if name is not an internalized string,
42 // and will jump to the miss_label in that case. 40 // and will jump to the miss_label in that case.
43 // The generated code assumes that the receiver has slow properties, 41 // The generated code assumes that the receiver has slow properties,
44 // is not a global object and does not have interceptors. 42 // is not a global object and does not have interceptors.
45 static void GenerateDictionaryLoad(MacroAssembler* masm, 43 static void GenerateDictionaryLoad(MacroAssembler* masm, Label* miss_label,
46 Label* miss_label, 44 Register elements, Register name,
47 Register elements, 45 Register r0, Register r1, Register result) {
48 Register name,
49 Register r0,
50 Register r1,
51 Register result) {
52 // Register use: 46 // Register use:
53 // 47 //
54 // elements - holds the property dictionary on entry and is unchanged. 48 // elements - holds the property dictionary on entry and is unchanged.
55 // 49 //
56 // name - holds the name of the property on entry and is unchanged. 50 // name - holds the name of the property on entry and is unchanged.
57 // 51 //
58 // r0 - used to hold the capacity of the property dictionary. 52 // r0 - used to hold the capacity of the property dictionary.
59 // 53 //
60 // r1 - used to hold the index into the property dictionary. 54 // r1 - used to hold the index into the property dictionary.
61 // 55 //
62 // result - holds the result on exit if the load succeeded. 56 // result - holds the result on exit if the load succeeded.
63 57
64 Label done; 58 Label done;
65 59
66 // Probe the dictionary. 60 // Probe the dictionary.
67 NameDictionaryLookupStub::GeneratePositiveLookup(masm, 61 NameDictionaryLookupStub::GeneratePositiveLookup(masm, miss_label, &done,
68 miss_label, 62 elements, name, r0, r1);
69 &done,
70 elements,
71 name,
72 r0,
73 r1);
74 63
75 // If probing finds an entry in the dictionary, r1 contains the 64 // If probing finds an entry in the dictionary, r1 contains the
76 // index into the dictionary. Check that the value is a normal 65 // index into the dictionary. Check that the value is a normal
77 // property. 66 // property.
78 __ bind(&done); 67 __ bind(&done);
79 const int kElementsStartOffset = 68 const int kElementsStartOffset =
80 NameDictionary::kHeaderSize + 69 NameDictionary::kHeaderSize +
81 NameDictionary::kElementsStartIndex * kPointerSize; 70 NameDictionary::kElementsStartIndex * kPointerSize;
82 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; 71 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
83 __ Test(Operand(elements, r1, times_pointer_size, 72 __ Test(Operand(elements, r1, times_pointer_size,
84 kDetailsOffset - kHeapObjectTag), 73 kDetailsOffset - kHeapObjectTag),
85 Smi::FromInt(PropertyDetails::TypeField::kMask)); 74 Smi::FromInt(PropertyDetails::TypeField::kMask));
86 __ j(not_zero, miss_label); 75 __ j(not_zero, miss_label);
87 76
88 // Get the value at the masked, scaled index. 77 // Get the value at the masked, scaled index.
89 const int kValueOffset = kElementsStartOffset + kPointerSize; 78 const int kValueOffset = kElementsStartOffset + kPointerSize;
90 __ movp(result, 79 __ movp(result, Operand(elements, r1, times_pointer_size,
91 Operand(elements, r1, times_pointer_size, 80 kValueOffset - kHeapObjectTag));
92 kValueOffset - kHeapObjectTag));
93 } 81 }
94 82
95 83
96 // Helper function used to store a property to a dictionary backing 84 // Helper function used to store a property to a dictionary backing
97 // storage. This function may fail to store a property even though it 85 // storage. This function may fail to store a property even though it
98 // is in the dictionary, so code at miss_label must always call a 86 // is in the dictionary, so code at miss_label must always call a
99 // backup property store that is complete. This function is safe to 87 // backup property store that is complete. This function is safe to
100 // call if name is not an internalized string, and will jump to the miss_label 88 // call if name is not an internalized string, and will jump to the miss_label
101 // in that case. The generated code assumes that the receiver has slow 89 // in that case. The generated code assumes that the receiver has slow
102 // properties, is not a global object and does not have interceptors. 90 // properties, is not a global object and does not have interceptors.
103 static void GenerateDictionaryStore(MacroAssembler* masm, 91 static void GenerateDictionaryStore(MacroAssembler* masm, Label* miss_label,
104 Label* miss_label, 92 Register elements, Register name,
105 Register elements, 93 Register value, Register scratch0,
106 Register name,
107 Register value,
108 Register scratch0,
109 Register scratch1) { 94 Register scratch1) {
110 // Register use: 95 // Register use:
111 // 96 //
112 // elements - holds the property dictionary on entry and is clobbered. 97 // elements - holds the property dictionary on entry and is clobbered.
113 // 98 //
114 // name - holds the name of the property on entry and is unchanged. 99 // name - holds the name of the property on entry and is unchanged.
115 // 100 //
116 // value - holds the value to store and is unchanged. 101 // value - holds the value to store and is unchanged.
117 // 102 //
118 // scratch0 - used during the positive dictionary lookup and is clobbered. 103 // scratch0 - used during the positive dictionary lookup and is clobbered.
119 // 104 //
120 // scratch1 - used for index into the property dictionary and is clobbered. 105 // scratch1 - used for index into the property dictionary and is clobbered.
121 Label done; 106 Label done;
122 107
123 // Probe the dictionary. 108 // Probe the dictionary.
124 NameDictionaryLookupStub::GeneratePositiveLookup(masm, 109 NameDictionaryLookupStub::GeneratePositiveLookup(
125 miss_label, 110 masm, miss_label, &done, elements, name, scratch0, scratch1);
126 &done,
127 elements,
128 name,
129 scratch0,
130 scratch1);
131 111
132 // If probing finds an entry in the dictionary, scratch0 contains the 112 // If probing finds an entry in the dictionary, scratch0 contains the
133 // index into the dictionary. Check that the value is a normal 113 // index into the dictionary. Check that the value is a normal
134 // property that is not read only. 114 // property that is not read only.
135 __ bind(&done); 115 __ bind(&done);
136 const int kElementsStartOffset = 116 const int kElementsStartOffset =
137 NameDictionary::kHeaderSize + 117 NameDictionary::kHeaderSize +
138 NameDictionary::kElementsStartIndex * kPointerSize; 118 NameDictionary::kElementsStartIndex * kPointerSize;
139 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; 119 const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
140 const int kTypeAndReadOnlyMask = 120 const int kTypeAndReadOnlyMask =
141 (PropertyDetails::TypeField::kMask | 121 (PropertyDetails::TypeField::kMask |
142 PropertyDetails::AttributesField::encode(READ_ONLY)) << kSmiTagSize; 122 PropertyDetails::AttributesField::encode(READ_ONLY))
143 __ Test(Operand(elements, 123 << kSmiTagSize;
144 scratch1, 124 __ Test(Operand(elements, scratch1, times_pointer_size,
145 times_pointer_size,
146 kDetailsOffset - kHeapObjectTag), 125 kDetailsOffset - kHeapObjectTag),
147 Smi::FromInt(kTypeAndReadOnlyMask)); 126 Smi::FromInt(kTypeAndReadOnlyMask));
148 __ j(not_zero, miss_label); 127 __ j(not_zero, miss_label);
149 128
150 // Store the value at the masked, scaled index. 129 // Store the value at the masked, scaled index.
151 const int kValueOffset = kElementsStartOffset + kPointerSize; 130 const int kValueOffset = kElementsStartOffset + kPointerSize;
152 __ leap(scratch1, Operand(elements, 131 __ leap(scratch1, Operand(elements, scratch1, times_pointer_size,
153 scratch1, 132 kValueOffset - kHeapObjectTag));
154 times_pointer_size,
155 kValueOffset - kHeapObjectTag));
156 __ movp(Operand(scratch1, 0), value); 133 __ movp(Operand(scratch1, 0), value);
157 134
158 // Update write barrier. Make sure not to clobber the value. 135 // Update write barrier. Make sure not to clobber the value.
159 __ movp(scratch0, value); 136 __ movp(scratch0, value);
160 __ RecordWrite(elements, scratch1, scratch0, kDontSaveFPRegs); 137 __ RecordWrite(elements, scratch1, scratch0, kDontSaveFPRegs);
161 } 138 }
162 139
163 140
164 // Checks the receiver for special cases (value type, slow case bits). 141 // Checks the receiver for special cases (value type, slow case bits).
165 // Falls through for regular JS object. 142 // Falls through for regular JS object.
166 static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm, 143 static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm,
167 Register receiver, 144 Register receiver, Register map,
168 Register map, 145 int interceptor_bit, Label* slow) {
169 int interceptor_bit,
170 Label* slow) {
171 // Register use: 146 // Register use:
172 // receiver - holds the receiver and is unchanged. 147 // receiver - holds the receiver and is unchanged.
173 // Scratch registers: 148 // Scratch registers:
174 // map - used to hold the map of the receiver. 149 // map - used to hold the map of the receiver.
175 150
176 // Check that the object isn't a smi. 151 // Check that the object isn't a smi.
177 __ JumpIfSmi(receiver, slow); 152 __ JumpIfSmi(receiver, slow);
178 153
179 // Check that the object is some kind of JS object EXCEPT JS Value type. 154 // Check that the object is some kind of JS object EXCEPT JS Value type.
180 // In the case that the object is a value-wrapper object, 155 // In the case that the object is a value-wrapper object,
181 // we enter the runtime system to make sure that indexing 156 // we enter the runtime system to make sure that indexing
182 // into string objects work as intended. 157 // into string objects work as intended.
183 DCHECK(JS_OBJECT_TYPE > JS_VALUE_TYPE); 158 DCHECK(JS_OBJECT_TYPE > JS_VALUE_TYPE);
184 __ CmpObjectType(receiver, JS_OBJECT_TYPE, map); 159 __ CmpObjectType(receiver, JS_OBJECT_TYPE, map);
185 __ j(below, slow); 160 __ j(below, slow);
186 161
187 // Check bit field. 162 // Check bit field.
188 __ testb(FieldOperand(map, Map::kBitFieldOffset), 163 __ testb(
189 Immediate((1 << Map::kIsAccessCheckNeeded) | 164 FieldOperand(map, Map::kBitFieldOffset),
190 (1 << interceptor_bit))); 165 Immediate((1 << Map::kIsAccessCheckNeeded) | (1 << interceptor_bit)));
191 __ j(not_zero, slow); 166 __ j(not_zero, slow);
192 } 167 }
193 168
194 169
195 // Loads an indexed element from a fast case array. 170 // Loads an indexed element from a fast case array.
196 // If not_fast_array is NULL, doesn't perform the elements map check. 171 // If not_fast_array is NULL, doesn't perform the elements map check.
197 static void GenerateFastArrayLoad(MacroAssembler* masm, 172 static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver,
198 Register receiver, 173 Register key, Register elements,
199 Register key, 174 Register scratch, Register result,
200 Register elements, 175 Label* not_fast_array, Label* out_of_range) {
201 Register scratch,
202 Register result,
203 Label* not_fast_array,
204 Label* out_of_range) {
205 // Register use: 176 // Register use:
206 // 177 //
207 // receiver - holds the receiver on entry. 178 // receiver - holds the receiver on entry.
208 // Unchanged unless 'result' is the same register. 179 // Unchanged unless 'result' is the same register.
209 // 180 //
210 // key - holds the smi key on entry. 181 // key - holds the smi key on entry.
211 // Unchanged unless 'result' is the same register. 182 // Unchanged unless 'result' is the same register.
212 // 183 //
213 // elements - holds the elements of the receiver on exit. 184 // elements - holds the elements of the receiver on exit.
214 // 185 //
(...skipping 14 matching lines...) Expand all
229 __ j(not_equal, not_fast_array); 200 __ j(not_equal, not_fast_array);
230 } else { 201 } else {
231 __ AssertFastElements(elements); 202 __ AssertFastElements(elements);
232 } 203 }
233 // Check that the key (index) is within bounds. 204 // Check that the key (index) is within bounds.
234 __ SmiCompare(key, FieldOperand(elements, FixedArray::kLengthOffset)); 205 __ SmiCompare(key, FieldOperand(elements, FixedArray::kLengthOffset));
235 // Unsigned comparison rejects negative indices. 206 // Unsigned comparison rejects negative indices.
236 __ j(above_equal, out_of_range); 207 __ j(above_equal, out_of_range);
237 // Fast case: Do the load. 208 // Fast case: Do the load.
238 SmiIndex index = masm->SmiToIndex(scratch, key, kPointerSizeLog2); 209 SmiIndex index = masm->SmiToIndex(scratch, key, kPointerSizeLog2);
239 __ movp(scratch, FieldOperand(elements, 210 __ movp(scratch, FieldOperand(elements, index.reg, index.scale,
240 index.reg,
241 index.scale,
242 FixedArray::kHeaderSize)); 211 FixedArray::kHeaderSize));
243 __ CompareRoot(scratch, Heap::kTheHoleValueRootIndex); 212 __ CompareRoot(scratch, Heap::kTheHoleValueRootIndex);
244 // In case the loaded value is the_hole we have to consult GetProperty 213 // In case the loaded value is the_hole we have to consult GetProperty
245 // to ensure the prototype chain is searched. 214 // to ensure the prototype chain is searched.
246 __ j(equal, out_of_range); 215 __ j(equal, out_of_range);
247 if (!result.is(scratch)) { 216 if (!result.is(scratch)) {
248 __ movp(result, scratch); 217 __ movp(result, scratch);
249 } 218 }
250 } 219 }
251 220
252 221
253 // Checks whether a key is an array index string or a unique name. 222 // Checks whether a key is an array index string or a unique name.
254 // Falls through if the key is a unique name. 223 // Falls through if the key is a unique name.
255 static void GenerateKeyNameCheck(MacroAssembler* masm, 224 static void GenerateKeyNameCheck(MacroAssembler* masm, Register key,
256 Register key, 225 Register map, Register hash,
257 Register map, 226 Label* index_string, Label* not_unique) {
258 Register hash,
259 Label* index_string,
260 Label* not_unique) {
261 // Register use: 227 // Register use:
262 // key - holds the key and is unchanged. Assumed to be non-smi. 228 // key - holds the key and is unchanged. Assumed to be non-smi.
263 // Scratch registers: 229 // Scratch registers:
264 // map - used to hold the map of the key. 230 // map - used to hold the map of the key.
265 // hash - used to hold the hash of the key. 231 // hash - used to hold the hash of the key.
266 Label unique; 232 Label unique;
267 __ CmpObjectType(key, LAST_UNIQUE_NAME_TYPE, map); 233 __ CmpObjectType(key, LAST_UNIQUE_NAME_TYPE, map);
268 __ j(above, not_unique); 234 __ j(above, not_unique);
269 STATIC_ASSERT(LAST_UNIQUE_NAME_TYPE == FIRST_NONSTRING_TYPE); 235 STATIC_ASSERT(LAST_UNIQUE_NAME_TYPE == FIRST_NONSTRING_TYPE);
270 __ j(equal, &unique); 236 __ j(equal, &unique);
271 237
272 // Is the string an array index, with cached numeric value? 238 // Is the string an array index, with cached numeric value?
273 __ movl(hash, FieldOperand(key, Name::kHashFieldOffset)); 239 __ movl(hash, FieldOperand(key, Name::kHashFieldOffset));
274 __ testl(hash, Immediate(Name::kContainsCachedArrayIndexMask)); 240 __ testl(hash, Immediate(Name::kContainsCachedArrayIndexMask));
275 __ j(zero, index_string); // The value in hash is used at jump target. 241 __ j(zero, index_string); // The value in hash is used at jump target.
276 242
277 // Is the string internalized? We already know it's a string so a single 243 // Is the string internalized? We already know it's a string so a single
278 // bit test is enough. 244 // bit test is enough.
279 STATIC_ASSERT(kNotInternalizedTag != 0); 245 STATIC_ASSERT(kNotInternalizedTag != 0);
280 __ testb(FieldOperand(map, Map::kInstanceTypeOffset), 246 __ testb(FieldOperand(map, Map::kInstanceTypeOffset),
281 Immediate(kIsNotInternalizedMask)); 247 Immediate(kIsNotInternalizedMask));
282 __ j(not_zero, not_unique); 248 __ j(not_zero, not_unique);
283 249
284 __ bind(&unique); 250 __ bind(&unique);
285 } 251 }
286 252
287 253
288
289 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { 254 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
290 // The return address is on the stack. 255 // The return address is on the stack.
291 Label slow, check_name, index_smi, index_name, property_array_property; 256 Label slow, check_name, index_smi, index_name, property_array_property;
292 Label probe_dictionary, check_number_dictionary; 257 Label probe_dictionary, check_number_dictionary;
293 258
294 Register receiver = ReceiverRegister(); 259 Register receiver = ReceiverRegister();
295 Register key = NameRegister(); 260 Register key = NameRegister();
296 DCHECK(receiver.is(rdx)); 261 DCHECK(receiver.is(rdx));
297 DCHECK(key.is(rcx)); 262 DCHECK(key.is(rcx));
298 263
299 // Check that the key is a smi. 264 // Check that the key is a smi.
300 __ JumpIfNotSmi(key, &check_name); 265 __ JumpIfNotSmi(key, &check_name);
301 __ bind(&index_smi); 266 __ bind(&index_smi);
302 // Now the key is known to be a smi. This place is also jumped to from below 267 // Now the key is known to be a smi. This place is also jumped to from below
303 // where a numeric string is converted to a smi. 268 // where a numeric string is converted to a smi.
304 269
305 GenerateKeyedLoadReceiverCheck( 270 GenerateKeyedLoadReceiverCheck(masm, receiver, rax,
306 masm, receiver, rax, Map::kHasIndexedInterceptor, &slow); 271 Map::kHasIndexedInterceptor, &slow);
307 272
308 // Check the receiver's map to see if it has fast elements. 273 // Check the receiver's map to see if it has fast elements.
309 __ CheckFastElements(rax, &check_number_dictionary); 274 __ CheckFastElements(rax, &check_number_dictionary);
310 275
311 GenerateFastArrayLoad(masm, 276 GenerateFastArrayLoad(masm, receiver, key, rax, rbx, rax, NULL, &slow);
312 receiver,
313 key,
314 rax,
315 rbx,
316 rax,
317 NULL,
318 &slow);
319 Counters* counters = masm->isolate()->counters(); 277 Counters* counters = masm->isolate()->counters();
320 __ IncrementCounter(counters->keyed_load_generic_smi(), 1); 278 __ IncrementCounter(counters->keyed_load_generic_smi(), 1);
321 __ ret(0); 279 __ ret(0);
322 280
323 __ bind(&check_number_dictionary); 281 __ bind(&check_number_dictionary);
324 __ SmiToInteger32(rbx, key); 282 __ SmiToInteger32(rbx, key);
325 __ movp(rax, FieldOperand(receiver, JSObject::kElementsOffset)); 283 __ movp(rax, FieldOperand(receiver, JSObject::kElementsOffset));
326 284
327 // Check whether the elements is a number dictionary. 285 // Check whether the elements is a number dictionary.
328 // rbx: key as untagged int32 286 // rbx: key as untagged int32
329 // rax: elements 287 // rax: elements
330 __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset), 288 __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
331 Heap::kHashTableMapRootIndex); 289 Heap::kHashTableMapRootIndex);
332 __ j(not_equal, &slow); 290 __ j(not_equal, &slow);
333 __ LoadFromNumberDictionary(&slow, rax, key, rbx, r9, rdi, rax); 291 __ LoadFromNumberDictionary(&slow, rax, key, rbx, r9, rdi, rax);
334 __ ret(0); 292 __ ret(0);
335 293
336 __ bind(&slow); 294 __ bind(&slow);
337 // Slow case: Jump to runtime. 295 // Slow case: Jump to runtime.
338 __ IncrementCounter(counters->keyed_load_generic_slow(), 1); 296 __ IncrementCounter(counters->keyed_load_generic_slow(), 1);
339 GenerateRuntimeGetProperty(masm); 297 GenerateRuntimeGetProperty(masm);
340 298
341 __ bind(&check_name); 299 __ bind(&check_name);
342 GenerateKeyNameCheck(masm, key, rax, rbx, &index_name, &slow); 300 GenerateKeyNameCheck(masm, key, rax, rbx, &index_name, &slow);
343 301
344 GenerateKeyedLoadReceiverCheck( 302 GenerateKeyedLoadReceiverCheck(masm, receiver, rax, Map::kHasNamedInterceptor,
345 masm, receiver, rax, Map::kHasNamedInterceptor, &slow); 303 &slow);
346 304
347 // If the receiver is a fast-case object, check the keyed lookup 305 // If the receiver is a fast-case object, check the keyed lookup
348 // cache. Otherwise probe the dictionary leaving result in key. 306 // cache. Otherwise probe the dictionary leaving result in key.
349 __ movp(rbx, FieldOperand(receiver, JSObject::kPropertiesOffset)); 307 __ movp(rbx, FieldOperand(receiver, JSObject::kPropertiesOffset));
350 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset), 308 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset),
351 Heap::kHashTableMapRootIndex); 309 Heap::kHashTableMapRootIndex);
352 __ j(equal, &probe_dictionary); 310 __ j(equal, &probe_dictionary);
353 311
354 // Load the map of the receiver, compute the keyed lookup cache hash 312 // Load the map of the receiver, compute the keyed lookup cache hash
355 // based on 32 bits of the map pointer and the string hash. 313 // based on 32 bits of the map pointer and the string hash.
356 __ movp(rbx, FieldOperand(receiver, HeapObject::kMapOffset)); 314 __ movp(rbx, FieldOperand(receiver, HeapObject::kMapOffset));
357 __ movl(rax, rbx); 315 __ movl(rax, rbx);
358 __ shrl(rax, Immediate(KeyedLookupCache::kMapHashShift)); 316 __ shrl(rax, Immediate(KeyedLookupCache::kMapHashShift));
359 __ movl(rdi, FieldOperand(key, String::kHashFieldOffset)); 317 __ movl(rdi, FieldOperand(key, String::kHashFieldOffset));
360 __ shrl(rdi, Immediate(String::kHashShift)); 318 __ shrl(rdi, Immediate(String::kHashShift));
361 __ xorp(rax, rdi); 319 __ xorp(rax, rdi);
362 int mask = (KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask); 320 int mask = (KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask);
363 __ andp(rax, Immediate(mask)); 321 __ andp(rax, Immediate(mask));
364 322
365 // Load the key (consisting of map and internalized string) from the cache and 323 // Load the key (consisting of map and internalized string) from the cache and
366 // check for match. 324 // check for match.
367 Label load_in_object_property; 325 Label load_in_object_property;
368 static const int kEntriesPerBucket = KeyedLookupCache::kEntriesPerBucket; 326 static const int kEntriesPerBucket = KeyedLookupCache::kEntriesPerBucket;
369 Label hit_on_nth_entry[kEntriesPerBucket]; 327 Label hit_on_nth_entry[kEntriesPerBucket];
370 ExternalReference cache_keys 328 ExternalReference cache_keys =
371 = ExternalReference::keyed_lookup_cache_keys(masm->isolate()); 329 ExternalReference::keyed_lookup_cache_keys(masm->isolate());
372 330
373 for (int i = 0; i < kEntriesPerBucket - 1; i++) { 331 for (int i = 0; i < kEntriesPerBucket - 1; i++) {
374 Label try_next_entry; 332 Label try_next_entry;
375 __ movp(rdi, rax); 333 __ movp(rdi, rax);
376 __ shlp(rdi, Immediate(kPointerSizeLog2 + 1)); 334 __ shlp(rdi, Immediate(kPointerSizeLog2 + 1));
377 __ LoadAddress(kScratchRegister, cache_keys); 335 __ LoadAddress(kScratchRegister, cache_keys);
378 int off = kPointerSize * i * 2; 336 int off = kPointerSize * i * 2;
379 __ cmpp(rbx, Operand(kScratchRegister, rdi, times_1, off)); 337 __ cmpp(rbx, Operand(kScratchRegister, rdi, times_1, off));
380 __ j(not_equal, &try_next_entry); 338 __ j(not_equal, &try_next_entry);
381 __ cmpp(key, Operand(kScratchRegister, rdi, times_1, off + kPointerSize)); 339 __ cmpp(key, Operand(kScratchRegister, rdi, times_1, off + kPointerSize));
382 __ j(equal, &hit_on_nth_entry[i]); 340 __ j(equal, &hit_on_nth_entry[i]);
383 __ bind(&try_next_entry); 341 __ bind(&try_next_entry);
384 } 342 }
385 343
386 int off = kPointerSize * (kEntriesPerBucket - 1) * 2; 344 int off = kPointerSize * (kEntriesPerBucket - 1) * 2;
387 __ cmpp(rbx, Operand(kScratchRegister, rdi, times_1, off)); 345 __ cmpp(rbx, Operand(kScratchRegister, rdi, times_1, off));
388 __ j(not_equal, &slow); 346 __ j(not_equal, &slow);
389 __ cmpp(key, Operand(kScratchRegister, rdi, times_1, off + kPointerSize)); 347 __ cmpp(key, Operand(kScratchRegister, rdi, times_1, off + kPointerSize));
390 __ j(not_equal, &slow); 348 __ j(not_equal, &slow);
391 349
392 // Get field offset, which is a 32-bit integer. 350 // Get field offset, which is a 32-bit integer.
393 ExternalReference cache_field_offsets 351 ExternalReference cache_field_offsets =
394 = ExternalReference::keyed_lookup_cache_field_offsets(masm->isolate()); 352 ExternalReference::keyed_lookup_cache_field_offsets(masm->isolate());
395 353
396 // Hit on nth entry. 354 // Hit on nth entry.
397 for (int i = kEntriesPerBucket - 1; i >= 0; i--) { 355 for (int i = kEntriesPerBucket - 1; i >= 0; i--) {
398 __ bind(&hit_on_nth_entry[i]); 356 __ bind(&hit_on_nth_entry[i]);
399 if (i != 0) { 357 if (i != 0) {
400 __ addl(rax, Immediate(i)); 358 __ addl(rax, Immediate(i));
401 } 359 }
402 __ LoadAddress(kScratchRegister, cache_field_offsets); 360 __ LoadAddress(kScratchRegister, cache_field_offsets);
403 __ movl(rdi, Operand(kScratchRegister, rax, times_4, 0)); 361 __ movl(rdi, Operand(kScratchRegister, rax, times_4, 0));
404 __ movzxbp(rax, FieldOperand(rbx, Map::kInObjectPropertiesOffset)); 362 __ movzxbp(rax, FieldOperand(rbx, Map::kInObjectPropertiesOffset));
405 __ subp(rdi, rax); 363 __ subp(rdi, rax);
406 __ j(above_equal, &property_array_property); 364 __ j(above_equal, &property_array_property);
407 if (i != 0) { 365 if (i != 0) {
408 __ jmp(&load_in_object_property); 366 __ jmp(&load_in_object_property);
409 } 367 }
410 } 368 }
411 369
412 // Load in-object property. 370 // Load in-object property.
413 __ bind(&load_in_object_property); 371 __ bind(&load_in_object_property);
414 __ movzxbp(rax, FieldOperand(rbx, Map::kInstanceSizeOffset)); 372 __ movzxbp(rax, FieldOperand(rbx, Map::kInstanceSizeOffset));
415 __ addp(rax, rdi); 373 __ addp(rax, rdi);
416 __ movp(rax, FieldOperand(receiver, rax, times_pointer_size, 0)); 374 __ movp(rax, FieldOperand(receiver, rax, times_pointer_size, 0));
417 __ IncrementCounter(counters->keyed_load_generic_lookup_cache(), 1); 375 __ IncrementCounter(counters->keyed_load_generic_lookup_cache(), 1);
418 __ ret(0); 376 __ ret(0);
419 377
420 // Load property array property. 378 // Load property array property.
421 __ bind(&property_array_property); 379 __ bind(&property_array_property);
422 __ movp(rax, FieldOperand(receiver, JSObject::kPropertiesOffset)); 380 __ movp(rax, FieldOperand(receiver, JSObject::kPropertiesOffset));
423 __ movp(rax, FieldOperand(rax, rdi, times_pointer_size, 381 __ movp(rax,
424 FixedArray::kHeaderSize)); 382 FieldOperand(rax, rdi, times_pointer_size, FixedArray::kHeaderSize));
425 __ IncrementCounter(counters->keyed_load_generic_lookup_cache(), 1); 383 __ IncrementCounter(counters->keyed_load_generic_lookup_cache(), 1);
426 __ ret(0); 384 __ ret(0);
427 385
428 // Do a quick inline probe of the receiver's dictionary, if it 386 // Do a quick inline probe of the receiver's dictionary, if it
429 // exists. 387 // exists.
430 __ bind(&probe_dictionary); 388 __ bind(&probe_dictionary);
431 // rbx: elements 389 // rbx: elements
432 390
433 __ movp(rax, FieldOperand(receiver, JSObject::kMapOffset)); 391 __ movp(rax, FieldOperand(receiver, JSObject::kMapOffset));
434 __ movb(rax, FieldOperand(rax, Map::kInstanceTypeOffset)); 392 __ movb(rax, FieldOperand(rax, Map::kInstanceTypeOffset));
(...skipping 12 matching lines...) Expand all
447 void KeyedLoadIC::GenerateString(MacroAssembler* masm) { 405 void KeyedLoadIC::GenerateString(MacroAssembler* masm) {
448 // Return address is on the stack. 406 // Return address is on the stack.
449 Label miss; 407 Label miss;
450 408
451 Register receiver = ReceiverRegister(); 409 Register receiver = ReceiverRegister();
452 Register index = NameRegister(); 410 Register index = NameRegister();
453 Register scratch = rbx; 411 Register scratch = rbx;
454 Register result = rax; 412 Register result = rax;
455 DCHECK(!scratch.is(receiver) && !scratch.is(index)); 413 DCHECK(!scratch.is(receiver) && !scratch.is(index));
456 414
457 StringCharAtGenerator char_at_generator(receiver, 415 StringCharAtGenerator char_at_generator(receiver, index, scratch, result,
458 index,
459 scratch,
460 result,
461 &miss, // When not a string. 416 &miss, // When not a string.
462 &miss, // When not a number. 417 &miss, // When not a number.
463 &miss, // When index out of range. 418 &miss, // When index out of range.
464 STRING_INDEX_IS_ARRAY_INDEX); 419 STRING_INDEX_IS_ARRAY_INDEX);
465 char_at_generator.GenerateFast(masm); 420 char_at_generator.GenerateFast(masm);
466 __ ret(0); 421 __ ret(0);
467 422
468 StubRuntimeCallHelper call_helper; 423 StubRuntimeCallHelper call_helper;
469 char_at_generator.GenerateSlow(masm, call_helper); 424 char_at_generator.GenerateSlow(masm, call_helper);
470 425
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
510 ExternalReference(IC_Utility(kLoadElementWithInterceptor), 465 ExternalReference(IC_Utility(kLoadElementWithInterceptor),
511 masm->isolate()), 466 masm->isolate()),
512 2, 1); 467 2, 1);
513 468
514 __ bind(&slow); 469 __ bind(&slow);
515 GenerateMiss(masm); 470 GenerateMiss(masm);
516 } 471 }
517 472
518 473
519 static void KeyedStoreGenerateGenericHelper( 474 static void KeyedStoreGenerateGenericHelper(
520 MacroAssembler* masm, 475 MacroAssembler* masm, Label* fast_object, Label* fast_double, Label* slow,
521 Label* fast_object, 476 KeyedStoreCheckMap check_map, KeyedStoreIncrementLength increment_length) {
522 Label* fast_double,
523 Label* slow,
524 KeyedStoreCheckMap check_map,
525 KeyedStoreIncrementLength increment_length) {
526 Label transition_smi_elements; 477 Label transition_smi_elements;
527 Label finish_object_store, non_double_value, transition_double_elements; 478 Label finish_object_store, non_double_value, transition_double_elements;
528 Label fast_double_without_map_check; 479 Label fast_double_without_map_check;
529 Register receiver = KeyedStoreIC::ReceiverRegister(); 480 Register receiver = KeyedStoreIC::ReceiverRegister();
530 Register key = KeyedStoreIC::NameRegister(); 481 Register key = KeyedStoreIC::NameRegister();
531 Register value = KeyedStoreIC::ValueRegister(); 482 Register value = KeyedStoreIC::ValueRegister();
532 DCHECK(receiver.is(rdx)); 483 DCHECK(receiver.is(rdx));
533 DCHECK(key.is(rcx)); 484 DCHECK(key.is(rcx));
534 DCHECK(value.is(rax)); 485 DCHECK(value.is(rax));
535 // Fast case: Do the store, could be either Object or double. 486 // Fast case: Do the store, could be either Object or double.
536 __ bind(fast_object); 487 __ bind(fast_object);
537 // rbx: receiver's elements array (a FixedArray) 488 // rbx: receiver's elements array (a FixedArray)
538 // receiver is a JSArray. 489 // receiver is a JSArray.
539 // r9: map of receiver 490 // r9: map of receiver
540 if (check_map == kCheckMap) { 491 if (check_map == kCheckMap) {
541 __ movp(rdi, FieldOperand(rbx, HeapObject::kMapOffset)); 492 __ movp(rdi, FieldOperand(rbx, HeapObject::kMapOffset));
542 __ CompareRoot(rdi, Heap::kFixedArrayMapRootIndex); 493 __ CompareRoot(rdi, Heap::kFixedArrayMapRootIndex);
543 __ j(not_equal, fast_double); 494 __ j(not_equal, fast_double);
544 } 495 }
545 496
546 // HOLECHECK: guards "A[i] = V" 497 // HOLECHECK: guards "A[i] = V"
547 // We have to go to the runtime if the current value is the hole because 498 // We have to go to the runtime if the current value is the hole because
548 // there may be a callback on the element 499 // there may be a callback on the element
549 Label holecheck_passed1; 500 Label holecheck_passed1;
550 __ movp(kScratchRegister, FieldOperand(rbx, 501 __ movp(kScratchRegister,
551 key, 502 FieldOperand(rbx, key, times_pointer_size, FixedArray::kHeaderSize));
552 times_pointer_size,
553 FixedArray::kHeaderSize));
554 __ CompareRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); 503 __ CompareRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
555 __ j(not_equal, &holecheck_passed1); 504 __ j(not_equal, &holecheck_passed1);
556 __ JumpIfDictionaryInPrototypeChain(receiver, rdi, kScratchRegister, slow); 505 __ JumpIfDictionaryInPrototypeChain(receiver, rdi, kScratchRegister, slow);
557 506
558 __ bind(&holecheck_passed1); 507 __ bind(&holecheck_passed1);
559 508
560 // Smi stores don't require further checks. 509 // Smi stores don't require further checks.
561 Label non_smi_value; 510 Label non_smi_value;
562 __ JumpIfNotSmi(value, &non_smi_value); 511 __ JumpIfNotSmi(value, &non_smi_value);
563 if (increment_length == kIncrementLength) { 512 if (increment_length == kIncrementLength) {
(...skipping 13 matching lines...) Expand all
577 526
578 __ bind(&finish_object_store); 527 __ bind(&finish_object_store);
579 if (increment_length == kIncrementLength) { 528 if (increment_length == kIncrementLength) {
580 // Add 1 to receiver->length. 529 // Add 1 to receiver->length.
581 __ leal(rdi, Operand(key, 1)); 530 __ leal(rdi, Operand(key, 1));
582 __ Integer32ToSmiField(FieldOperand(receiver, JSArray::kLengthOffset), rdi); 531 __ Integer32ToSmiField(FieldOperand(receiver, JSArray::kLengthOffset), rdi);
583 } 532 }
584 __ movp(FieldOperand(rbx, key, times_pointer_size, FixedArray::kHeaderSize), 533 __ movp(FieldOperand(rbx, key, times_pointer_size, FixedArray::kHeaderSize),
585 value); 534 value);
586 __ movp(rdx, value); // Preserve the value which is returned. 535 __ movp(rdx, value); // Preserve the value which is returned.
587 __ RecordWriteArray( 536 __ RecordWriteArray(rbx, rdx, key, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
588 rbx, rdx, key, kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); 537 OMIT_SMI_CHECK);
589 __ ret(0); 538 __ ret(0);
590 539
591 __ bind(fast_double); 540 __ bind(fast_double);
592 if (check_map == kCheckMap) { 541 if (check_map == kCheckMap) {
593 // Check for fast double array case. If this fails, call through to the 542 // Check for fast double array case. If this fails, call through to the
594 // runtime. 543 // runtime.
595 // rdi: elements array's map 544 // rdi: elements array's map
596 __ CompareRoot(rdi, Heap::kFixedDoubleArrayMapRootIndex); 545 __ CompareRoot(rdi, Heap::kFixedDoubleArrayMapRootIndex);
597 __ j(not_equal, slow); 546 __ j(not_equal, slow);
598 } 547 }
(...skipping 20 matching lines...) Expand all
619 __ movp(rbx, FieldOperand(receiver, HeapObject::kMapOffset)); 568 __ movp(rbx, FieldOperand(receiver, HeapObject::kMapOffset));
620 569
621 // Transition the array appropriately depending on the value type. 570 // Transition the array appropriately depending on the value type.
622 __ movp(r9, FieldOperand(value, HeapObject::kMapOffset)); 571 __ movp(r9, FieldOperand(value, HeapObject::kMapOffset));
623 __ CompareRoot(r9, Heap::kHeapNumberMapRootIndex); 572 __ CompareRoot(r9, Heap::kHeapNumberMapRootIndex);
624 __ j(not_equal, &non_double_value); 573 __ j(not_equal, &non_double_value);
625 574
626 // Value is a double. Transition FAST_SMI_ELEMENTS -> 575 // Value is a double. Transition FAST_SMI_ELEMENTS ->
627 // FAST_DOUBLE_ELEMENTS and complete the store. 576 // FAST_DOUBLE_ELEMENTS and complete the store.
628 __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS, 577 __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS,
629 FAST_DOUBLE_ELEMENTS, 578 FAST_DOUBLE_ELEMENTS, rbx, rdi, slow);
630 rbx, 579 AllocationSiteMode mode =
631 rdi, 580 AllocationSite::GetMode(FAST_SMI_ELEMENTS, FAST_DOUBLE_ELEMENTS);
632 slow); 581 ElementsTransitionGenerator::GenerateSmiToDouble(masm, receiver, key, value,
633 AllocationSiteMode mode = AllocationSite::GetMode(FAST_SMI_ELEMENTS, 582 rbx, mode, slow);
634 FAST_DOUBLE_ELEMENTS);
635 ElementsTransitionGenerator::GenerateSmiToDouble(
636 masm, receiver, key, value, rbx, mode, slow);
637 __ movp(rbx, FieldOperand(receiver, JSObject::kElementsOffset)); 583 __ movp(rbx, FieldOperand(receiver, JSObject::kElementsOffset));
638 __ jmp(&fast_double_without_map_check); 584 __ jmp(&fast_double_without_map_check);
639 585
640 __ bind(&non_double_value); 586 __ bind(&non_double_value);
641 // Value is not a double, FAST_SMI_ELEMENTS -> FAST_ELEMENTS 587 // Value is not a double, FAST_SMI_ELEMENTS -> FAST_ELEMENTS
642 __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS, 588 __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS, FAST_ELEMENTS, rbx,
643 FAST_ELEMENTS, 589 rdi, slow);
644 rbx,
645 rdi,
646 slow);
647 mode = AllocationSite::GetMode(FAST_SMI_ELEMENTS, FAST_ELEMENTS); 590 mode = AllocationSite::GetMode(FAST_SMI_ELEMENTS, FAST_ELEMENTS);
648 ElementsTransitionGenerator::GenerateMapChangeElementsTransition( 591 ElementsTransitionGenerator::GenerateMapChangeElementsTransition(
649 masm, receiver, key, value, rbx, mode, slow); 592 masm, receiver, key, value, rbx, mode, slow);
650 __ movp(rbx, FieldOperand(receiver, JSObject::kElementsOffset)); 593 __ movp(rbx, FieldOperand(receiver, JSObject::kElementsOffset));
651 __ jmp(&finish_object_store); 594 __ jmp(&finish_object_store);
652 595
653 __ bind(&transition_double_elements); 596 __ bind(&transition_double_elements);
654 // Elements are FAST_DOUBLE_ELEMENTS, but value is an Object that's not a 597 // Elements are FAST_DOUBLE_ELEMENTS, but value is an Object that's not a
655 // HeapNumber. Make sure that the receiver is a Array with FAST_ELEMENTS and 598 // HeapNumber. Make sure that the receiver is a Array with FAST_ELEMENTS and
656 // transition array from FAST_DOUBLE_ELEMENTS to FAST_ELEMENTS 599 // transition array from FAST_DOUBLE_ELEMENTS to FAST_ELEMENTS
657 __ movp(rbx, FieldOperand(receiver, HeapObject::kMapOffset)); 600 __ movp(rbx, FieldOperand(receiver, HeapObject::kMapOffset));
658 __ LoadTransitionedArrayMapConditional(FAST_DOUBLE_ELEMENTS, 601 __ LoadTransitionedArrayMapConditional(FAST_DOUBLE_ELEMENTS, FAST_ELEMENTS,
659 FAST_ELEMENTS, 602 rbx, rdi, slow);
660 rbx,
661 rdi,
662 slow);
663 mode = AllocationSite::GetMode(FAST_DOUBLE_ELEMENTS, FAST_ELEMENTS); 603 mode = AllocationSite::GetMode(FAST_DOUBLE_ELEMENTS, FAST_ELEMENTS);
664 ElementsTransitionGenerator::GenerateDoubleToObject( 604 ElementsTransitionGenerator::GenerateDoubleToObject(masm, receiver, key,
665 masm, receiver, key, value, rbx, mode, slow); 605 value, rbx, mode, slow);
666 __ movp(rbx, FieldOperand(receiver, JSObject::kElementsOffset)); 606 __ movp(rbx, FieldOperand(receiver, JSObject::kElementsOffset));
667 __ jmp(&finish_object_store); 607 __ jmp(&finish_object_store);
668 } 608 }
669 609
670 610
671 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm, 611 void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
672 StrictMode strict_mode) { 612 StrictMode strict_mode) {
673 // Return address is on the stack. 613 // Return address is on the stack.
674 Label slow, slow_with_tagged_index, fast_object, fast_object_grow; 614 Label slow, slow_with_tagged_index, fast_object, fast_object_grow;
675 Label fast_double, fast_double_grow; 615 Label fast_double, fast_double_grow;
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
739 // is the length is always a smi. 679 // is the length is always a smi.
740 __ bind(&array); 680 __ bind(&array);
741 // receiver is a JSArray. 681 // receiver is a JSArray.
742 __ movp(rbx, FieldOperand(receiver, JSObject::kElementsOffset)); 682 __ movp(rbx, FieldOperand(receiver, JSObject::kElementsOffset));
743 683
744 // Check the key against the length in the array, compute the 684 // Check the key against the length in the array, compute the
745 // address to store into and fall through to fast case. 685 // address to store into and fall through to fast case.
746 __ SmiCompareInteger32(FieldOperand(receiver, JSArray::kLengthOffset), key); 686 __ SmiCompareInteger32(FieldOperand(receiver, JSArray::kLengthOffset), key);
747 __ j(below_equal, &extra); 687 __ j(below_equal, &extra);
748 688
749 KeyedStoreGenerateGenericHelper(masm, &fast_object, &fast_double, 689 KeyedStoreGenerateGenericHelper(masm, &fast_object, &fast_double, &slow,
750 &slow, kCheckMap, kDontIncrementLength); 690 kCheckMap, kDontIncrementLength);
751 KeyedStoreGenerateGenericHelper(masm, &fast_object_grow, &fast_double_grow, 691 KeyedStoreGenerateGenericHelper(masm, &fast_object_grow, &fast_double_grow,
752 &slow, kDontCheckMap, kIncrementLength); 692 &slow, kDontCheckMap, kIncrementLength);
753 } 693 }
754 694
755 695
756 static Operand GenerateMappedArgumentsLookup(MacroAssembler* masm, 696 static Operand GenerateMappedArgumentsLookup(
757 Register object, 697 MacroAssembler* masm, Register object, Register key, Register scratch1,
758 Register key, 698 Register scratch2, Register scratch3, Label* unmapped_case,
759 Register scratch1, 699 Label* slow_case) {
760 Register scratch2,
761 Register scratch3,
762 Label* unmapped_case,
763 Label* slow_case) {
764 Heap* heap = masm->isolate()->heap(); 700 Heap* heap = masm->isolate()->heap();
765 701
766 // Check that the receiver is a JSObject. Because of the elements 702 // Check that the receiver is a JSObject. Because of the elements
767 // map check later, we do not need to check for interceptors or 703 // map check later, we do not need to check for interceptors or
768 // whether it requires access checks. 704 // whether it requires access checks.
769 __ JumpIfSmi(object, slow_case); 705 __ JumpIfSmi(object, slow_case);
770 // Check that the object is some kind of JSObject. 706 // Check that the object is some kind of JSObject.
771 __ CmpObjectType(object, FIRST_JS_RECEIVER_TYPE, scratch1); 707 __ CmpObjectType(object, FIRST_JS_RECEIVER_TYPE, scratch1);
772 __ j(below, slow_case); 708 __ j(below, slow_case);
773 709
774 // Check that the key is a positive smi. 710 // Check that the key is a positive smi.
775 Condition check = masm->CheckNonNegativeSmi(key); 711 Condition check = masm->CheckNonNegativeSmi(key);
776 __ j(NegateCondition(check), slow_case); 712 __ j(NegateCondition(check), slow_case);
777 713
778 // Load the elements into scratch1 and check its map. If not, jump 714 // Load the elements into scratch1 and check its map. If not, jump
779 // to the unmapped lookup with the parameter map in scratch1. 715 // to the unmapped lookup with the parameter map in scratch1.
780 Handle<Map> arguments_map(heap->sloppy_arguments_elements_map()); 716 Handle<Map> arguments_map(heap->sloppy_arguments_elements_map());
781 __ movp(scratch1, FieldOperand(object, JSObject::kElementsOffset)); 717 __ movp(scratch1, FieldOperand(object, JSObject::kElementsOffset));
782 __ CheckMap(scratch1, arguments_map, slow_case, DONT_DO_SMI_CHECK); 718 __ CheckMap(scratch1, arguments_map, slow_case, DONT_DO_SMI_CHECK);
783 719
784 // Check if element is in the range of mapped arguments. 720 // Check if element is in the range of mapped arguments.
785 __ movp(scratch2, FieldOperand(scratch1, FixedArray::kLengthOffset)); 721 __ movp(scratch2, FieldOperand(scratch1, FixedArray::kLengthOffset));
786 __ SmiSubConstant(scratch2, scratch2, Smi::FromInt(2)); 722 __ SmiSubConstant(scratch2, scratch2, Smi::FromInt(2));
787 __ cmpp(key, scratch2); 723 __ cmpp(key, scratch2);
788 __ j(greater_equal, unmapped_case); 724 __ j(greater_equal, unmapped_case);
789 725
790 // Load element index and check whether it is the hole. 726 // Load element index and check whether it is the hole.
791 const int kHeaderSize = FixedArray::kHeaderSize + 2 * kPointerSize; 727 const int kHeaderSize = FixedArray::kHeaderSize + 2 * kPointerSize;
792 __ SmiToInteger64(scratch3, key); 728 __ SmiToInteger64(scratch3, key);
793 __ movp(scratch2, FieldOperand(scratch1, 729 __ movp(scratch2,
794 scratch3, 730 FieldOperand(scratch1, scratch3, times_pointer_size, kHeaderSize));
795 times_pointer_size,
796 kHeaderSize));
797 __ CompareRoot(scratch2, Heap::kTheHoleValueRootIndex); 731 __ CompareRoot(scratch2, Heap::kTheHoleValueRootIndex);
798 __ j(equal, unmapped_case); 732 __ j(equal, unmapped_case);
799 733
800 // Load value from context and return it. We can reuse scratch1 because 734 // Load value from context and return it. We can reuse scratch1 because
801 // we do not jump to the unmapped lookup (which requires the parameter 735 // we do not jump to the unmapped lookup (which requires the parameter
802 // map in scratch1). 736 // map in scratch1).
803 __ movp(scratch1, FieldOperand(scratch1, FixedArray::kHeaderSize)); 737 __ movp(scratch1, FieldOperand(scratch1, FixedArray::kHeaderSize));
804 __ SmiToInteger64(scratch3, scratch2); 738 __ SmiToInteger64(scratch3, scratch2);
805 return FieldOperand(scratch1, 739 return FieldOperand(scratch1, scratch3, times_pointer_size,
806 scratch3,
807 times_pointer_size,
808 Context::kHeaderSize); 740 Context::kHeaderSize);
809 } 741 }
810 742
811 743
812 static Operand GenerateUnmappedArgumentsLookup(MacroAssembler* masm, 744 static Operand GenerateUnmappedArgumentsLookup(MacroAssembler* masm,
813 Register key, 745 Register key,
814 Register parameter_map, 746 Register parameter_map,
815 Register scratch, 747 Register scratch,
816 Label* slow_case) { 748 Label* slow_case) {
817 // Element is in arguments backing store, which is referenced by the 749 // Element is in arguments backing store, which is referenced by the
818 // second element of the parameter_map. The parameter_map register 750 // second element of the parameter_map. The parameter_map register
819 // must be loaded with the parameter map of the arguments object and is 751 // must be loaded with the parameter map of the arguments object and is
820 // overwritten. 752 // overwritten.
821 const int kBackingStoreOffset = FixedArray::kHeaderSize + kPointerSize; 753 const int kBackingStoreOffset = FixedArray::kHeaderSize + kPointerSize;
822 Register backing_store = parameter_map; 754 Register backing_store = parameter_map;
823 __ movp(backing_store, FieldOperand(parameter_map, kBackingStoreOffset)); 755 __ movp(backing_store, FieldOperand(parameter_map, kBackingStoreOffset));
824 Handle<Map> fixed_array_map(masm->isolate()->heap()->fixed_array_map()); 756 Handle<Map> fixed_array_map(masm->isolate()->heap()->fixed_array_map());
825 __ CheckMap(backing_store, fixed_array_map, slow_case, DONT_DO_SMI_CHECK); 757 __ CheckMap(backing_store, fixed_array_map, slow_case, DONT_DO_SMI_CHECK);
826 __ movp(scratch, FieldOperand(backing_store, FixedArray::kLengthOffset)); 758 __ movp(scratch, FieldOperand(backing_store, FixedArray::kLengthOffset));
827 __ cmpp(key, scratch); 759 __ cmpp(key, scratch);
828 __ j(greater_equal, slow_case); 760 __ j(greater_equal, slow_case);
829 __ SmiToInteger64(scratch, key); 761 __ SmiToInteger64(scratch, key);
830 return FieldOperand(backing_store, 762 return FieldOperand(backing_store, scratch, times_pointer_size,
831 scratch,
832 times_pointer_size,
833 FixedArray::kHeaderSize); 763 FixedArray::kHeaderSize);
834 } 764 }
835 765
836 766
837 void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) { 767 void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) {
838 // The return address is on the stack. 768 // The return address is on the stack.
839 Register receiver = ReceiverRegister(); 769 Register receiver = ReceiverRegister();
840 Register key = NameRegister(); 770 Register key = NameRegister();
841 DCHECK(receiver.is(rdx)); 771 DCHECK(receiver.is(rdx));
842 DCHECK(key.is(rcx)); 772 DCHECK(key.is(rcx));
843 773
844 Label slow, notin; 774 Label slow, notin;
845 Operand mapped_location = 775 Operand mapped_location = GenerateMappedArgumentsLookup(
846 GenerateMappedArgumentsLookup( 776 masm, receiver, key, rbx, rax, rdi, &notin, &slow);
847 masm, receiver, key, rbx, rax, rdi, &notin, &slow);
848 __ movp(rax, mapped_location); 777 __ movp(rax, mapped_location);
849 __ Ret(); 778 __ Ret();
850 __ bind(&notin); 779 __ bind(&notin);
851 // The unmapped lookup expects that the parameter map is in rbx. 780 // The unmapped lookup expects that the parameter map is in rbx.
852 Operand unmapped_location = 781 Operand unmapped_location =
853 GenerateUnmappedArgumentsLookup(masm, key, rbx, rax, &slow); 782 GenerateUnmappedArgumentsLookup(masm, key, rbx, rax, &slow);
854 __ CompareRoot(unmapped_location, Heap::kTheHoleValueRootIndex); 783 __ CompareRoot(unmapped_location, Heap::kTheHoleValueRootIndex);
855 __ j(equal, &slow); 784 __ j(equal, &slow);
856 __ movp(rax, unmapped_location); 785 __ movp(rax, unmapped_location);
857 __ Ret(); 786 __ Ret();
(...skipping 10 matching lines...) Expand all
868 Register value = ValueRegister(); 797 Register value = ValueRegister();
869 DCHECK(receiver.is(rdx)); 798 DCHECK(receiver.is(rdx));
870 DCHECK(name.is(rcx)); 799 DCHECK(name.is(rcx));
871 DCHECK(value.is(rax)); 800 DCHECK(value.is(rax));
872 801
873 Operand mapped_location = GenerateMappedArgumentsLookup( 802 Operand mapped_location = GenerateMappedArgumentsLookup(
874 masm, receiver, name, rbx, rdi, r8, &notin, &slow); 803 masm, receiver, name, rbx, rdi, r8, &notin, &slow);
875 __ movp(mapped_location, value); 804 __ movp(mapped_location, value);
876 __ leap(r9, mapped_location); 805 __ leap(r9, mapped_location);
877 __ movp(r8, value); 806 __ movp(r8, value);
878 __ RecordWrite(rbx, 807 __ RecordWrite(rbx, r9, r8, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
879 r9,
880 r8,
881 kDontSaveFPRegs,
882 EMIT_REMEMBERED_SET,
883 INLINE_SMI_CHECK); 808 INLINE_SMI_CHECK);
884 __ Ret(); 809 __ Ret();
885 __ bind(&notin); 810 __ bind(&notin);
886 // The unmapped lookup expects that the parameter map is in rbx. 811 // The unmapped lookup expects that the parameter map is in rbx.
887 Operand unmapped_location = 812 Operand unmapped_location =
888 GenerateUnmappedArgumentsLookup(masm, name, rbx, rdi, &slow); 813 GenerateUnmappedArgumentsLookup(masm, name, rbx, rdi, &slow);
889 __ movp(unmapped_location, value); 814 __ movp(unmapped_location, value);
890 __ leap(r9, unmapped_location); 815 __ leap(r9, unmapped_location);
891 __ movp(r8, value); 816 __ movp(r8, value);
892 __ RecordWrite(rbx, 817 __ RecordWrite(rbx, r9, r8, kDontSaveFPRegs, EMIT_REMEMBERED_SET,
893 r9,
894 r8,
895 kDontSaveFPRegs,
896 EMIT_REMEMBERED_SET,
897 INLINE_SMI_CHECK); 818 INLINE_SMI_CHECK);
898 __ Ret(); 819 __ Ret();
899 __ bind(&slow); 820 __ bind(&slow);
900 GenerateMiss(masm); 821 GenerateMiss(masm);
901 } 822 }
902 823
903 824
904 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { 825 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
905 // The return address is on the stack. 826 // The return address is on the stack.
906 Register receiver = ReceiverRegister(); 827 Register receiver = ReceiverRegister();
907 Register name = NameRegister(); 828 Register name = NameRegister();
908 DCHECK(receiver.is(rdx)); 829 DCHECK(receiver.is(rdx));
909 DCHECK(name.is(rcx)); 830 DCHECK(name.is(rcx));
910 831
911 // Probe the stub cache. 832 // Probe the stub cache.
912 Code::Flags flags = Code::RemoveTypeAndHolderFromFlags( 833 Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
913 Code::ComputeHandlerFlags(Code::LOAD_IC)); 834 Code::ComputeHandlerFlags(Code::LOAD_IC));
914 masm->isolate()->stub_cache()->GenerateProbe( 835 masm->isolate()->stub_cache()->GenerateProbe(masm, flags, receiver, name, rbx,
915 masm, flags, receiver, name, rbx, rax); 836 rax);
916 837
917 GenerateMiss(masm); 838 GenerateMiss(masm);
918 } 839 }
919 840
920 841
921 void LoadIC::GenerateNormal(MacroAssembler* masm) { 842 void LoadIC::GenerateNormal(MacroAssembler* masm) {
922 Register dictionary = rax; 843 Register dictionary = rax;
923 DCHECK(!dictionary.is(ReceiverRegister())); 844 DCHECK(!dictionary.is(ReceiverRegister()));
924 DCHECK(!dictionary.is(NameRegister())); 845 DCHECK(!dictionary.is(NameRegister()));
925 846
926 Label slow; 847 Label slow;
927 848
928 __ movp(dictionary, 849 __ movp(dictionary,
929 FieldOperand(ReceiverRegister(), JSObject::kPropertiesOffset)); 850 FieldOperand(ReceiverRegister(), JSObject::kPropertiesOffset));
930 GenerateDictionaryLoad(masm, &slow, dictionary, NameRegister(), rbx, rdi, 851 GenerateDictionaryLoad(masm, &slow, dictionary, NameRegister(), rbx, rdi,
931 rax); 852 rax);
932 __ ret(0); 853 __ ret(0);
933 854
934 // Dictionary load failed, go slow (but don't miss). 855 // Dictionary load failed, go slow (but don't miss).
935 __ bind(&slow); 856 __ bind(&slow);
936 GenerateRuntimeGetProperty(masm); 857 GenerateRuntimeGetProperty(masm);
937 } 858 }
938 859
939 860
940 // A register that isn't one of the parameters to the load ic. 861 // A register that isn't one of the parameters to the load ic.
941 static const Register LoadIC_TempRegister() { return rbx; } 862 static const Register LoadIC_TempRegister() { return rbx; }
942 863
943 864
944 static const Register KeyedLoadIC_TempRegister() { 865 static const Register KeyedLoadIC_TempRegister() { return rbx; }
945 return rbx;
946 }
947 866
948 867
949 void LoadIC::GenerateMiss(MacroAssembler* masm) { 868 void LoadIC::GenerateMiss(MacroAssembler* masm) {
950 // The return address is on the stack. 869 // The return address is on the stack.
951 870
952 Counters* counters = masm->isolate()->counters(); 871 Counters* counters = masm->isolate()->counters();
953 __ IncrementCounter(counters->load_miss(), 1); 872 __ IncrementCounter(counters->load_miss(), 1);
954 873
955 __ PopReturnAddressTo(LoadIC_TempRegister()); 874 __ PopReturnAddressTo(LoadIC_TempRegister());
956 __ Push(ReceiverRegister()); // receiver 875 __ Push(ReceiverRegister()); // receiver
957 __ Push(NameRegister()); // name 876 __ Push(NameRegister()); // name
958 __ PushReturnAddressFrom(LoadIC_TempRegister()); 877 __ PushReturnAddressFrom(LoadIC_TempRegister());
959 878
960 // Perform tail call to the entry. 879 // Perform tail call to the entry.
961 ExternalReference ref = 880 ExternalReference ref =
962 ExternalReference(IC_Utility(kLoadIC_Miss), masm->isolate()); 881 ExternalReference(IC_Utility(kLoadIC_Miss), masm->isolate());
963 __ TailCallExternalReference(ref, 2, 1); 882 __ TailCallExternalReference(ref, 2, 1);
964 } 883 }
965 884
966 885
967 void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { 886 void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
968 // The return address is on the stack. 887 // The return address is on the stack.
969 888
970 __ PopReturnAddressTo(LoadIC_TempRegister()); 889 __ PopReturnAddressTo(LoadIC_TempRegister());
971 __ Push(ReceiverRegister()); // receiver 890 __ Push(ReceiverRegister()); // receiver
972 __ Push(NameRegister()); // name 891 __ Push(NameRegister()); // name
973 __ PushReturnAddressFrom(LoadIC_TempRegister()); 892 __ PushReturnAddressFrom(LoadIC_TempRegister());
974 893
975 // Perform tail call to the entry. 894 // Perform tail call to the entry.
976 __ TailCallRuntime(Runtime::kGetProperty, 2, 1); 895 __ TailCallRuntime(Runtime::kGetProperty, 2, 1);
977 } 896 }
978 897
979 898
980 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { 899 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
981 // The return address is on the stack. 900 // The return address is on the stack.
982 Counters* counters = masm->isolate()->counters(); 901 Counters* counters = masm->isolate()->counters();
983 __ IncrementCounter(counters->keyed_load_miss(), 1); 902 __ IncrementCounter(counters->keyed_load_miss(), 1);
984 903
985 __ PopReturnAddressTo(KeyedLoadIC_TempRegister()); 904 __ PopReturnAddressTo(KeyedLoadIC_TempRegister());
986 __ Push(ReceiverRegister()); // receiver 905 __ Push(ReceiverRegister()); // receiver
987 __ Push(NameRegister()); // name 906 __ Push(NameRegister()); // name
988 __ PushReturnAddressFrom(KeyedLoadIC_TempRegister()); 907 __ PushReturnAddressFrom(KeyedLoadIC_TempRegister());
989 908
990 // Perform tail call to the entry. 909 // Perform tail call to the entry.
991 ExternalReference ref = 910 ExternalReference ref =
992 ExternalReference(IC_Utility(kKeyedLoadIC_Miss), masm->isolate()); 911 ExternalReference(IC_Utility(kKeyedLoadIC_Miss), masm->isolate());
993 __ TailCallExternalReference(ref, 2, 1); 912 __ TailCallExternalReference(ref, 2, 1);
994 } 913 }
995 914
996 915
997 // IC register specifications 916 // IC register specifications
(...skipping 11 matching lines...) Expand all
1009 DCHECK(FLAG_vector_ics); 928 DCHECK(FLAG_vector_ics);
1010 return rbx; 929 return rbx;
1011 } 930 }
1012 931
1013 932
1014 const Register StoreIC::ReceiverRegister() { return rdx; } 933 const Register StoreIC::ReceiverRegister() { return rdx; }
1015 const Register StoreIC::NameRegister() { return rcx; } 934 const Register StoreIC::NameRegister() { return rcx; }
1016 const Register StoreIC::ValueRegister() { return rax; } 935 const Register StoreIC::ValueRegister() { return rax; }
1017 936
1018 937
1019 const Register KeyedStoreIC::MapRegister() { 938 const Register KeyedStoreIC::MapRegister() { return rbx; }
1020 return rbx;
1021 }
1022 939
1023 940
1024 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { 941 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
1025 // The return address is on the stack. 942 // The return address is on the stack.
1026 943
1027 __ PopReturnAddressTo(KeyedLoadIC_TempRegister()); 944 __ PopReturnAddressTo(KeyedLoadIC_TempRegister());
1028 __ Push(ReceiverRegister()); // receiver 945 __ Push(ReceiverRegister()); // receiver
1029 __ Push(NameRegister()); // name 946 __ Push(NameRegister()); // name
1030 __ PushReturnAddressFrom(KeyedLoadIC_TempRegister()); 947 __ PushReturnAddressFrom(KeyedLoadIC_TempRegister());
1031 948
1032 // Perform tail call to the entry. 949 // Perform tail call to the entry.
1033 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); 950 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
1034 } 951 }
1035 952
1036 953
1037 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) { 954 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) {
1038 // The return address is on the stack. 955 // The return address is on the stack.
1039 956
1040 // Get the receiver from the stack and probe the stub cache. 957 // Get the receiver from the stack and probe the stub cache.
1041 Code::Flags flags = Code::RemoveTypeAndHolderFromFlags( 958 Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
1042 Code::ComputeHandlerFlags(Code::STORE_IC)); 959 Code::ComputeHandlerFlags(Code::STORE_IC));
1043 masm->isolate()->stub_cache()->GenerateProbe( 960 masm->isolate()->stub_cache()->GenerateProbe(masm, flags, ReceiverRegister(),
1044 masm, flags, ReceiverRegister(), NameRegister(), rbx, no_reg); 961 NameRegister(), rbx, no_reg);
1045 962
1046 // Cache miss: Jump to runtime. 963 // Cache miss: Jump to runtime.
1047 GenerateMiss(masm); 964 GenerateMiss(masm);
1048 } 965 }
1049 966
1050 967
1051 static void StoreIC_PushArgs(MacroAssembler* masm) { 968 static void StoreIC_PushArgs(MacroAssembler* masm) {
1052 Register receiver = StoreIC::ReceiverRegister(); 969 Register receiver = StoreIC::ReceiverRegister();
1053 Register name = StoreIC::NameRegister(); 970 Register name = StoreIC::NameRegister();
1054 Register value = StoreIC::ValueRegister(); 971 Register value = StoreIC::ValueRegister();
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
1115 void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm, 1032 void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm,
1116 StrictMode strict_mode) { 1033 StrictMode strict_mode) {
1117 // Return address is on the stack. 1034 // Return address is on the stack.
1118 DCHECK(!rbx.is(ReceiverRegister()) && !rbx.is(NameRegister()) && 1035 DCHECK(!rbx.is(ReceiverRegister()) && !rbx.is(NameRegister()) &&
1119 !rbx.is(ValueRegister())); 1036 !rbx.is(ValueRegister()));
1120 1037
1121 __ PopReturnAddressTo(rbx); 1038 __ PopReturnAddressTo(rbx);
1122 __ Push(ReceiverRegister()); 1039 __ Push(ReceiverRegister());
1123 __ Push(NameRegister()); 1040 __ Push(NameRegister());
1124 __ Push(ValueRegister()); 1041 __ Push(ValueRegister());
1125 __ Push(Smi::FromInt(strict_mode)); // Strict mode. 1042 __ Push(Smi::FromInt(strict_mode)); // Strict mode.
1126 __ PushReturnAddressFrom(rbx); 1043 __ PushReturnAddressFrom(rbx);
1127 1044
1128 // Do tail-call to runtime routine. 1045 // Do tail-call to runtime routine.
1129 __ TailCallRuntime(Runtime::kSetProperty, 4, 1); 1046 __ TailCallRuntime(Runtime::kSetProperty, 4, 1);
1130 } 1047 }
1131 1048
1132 1049
1133 void StoreIC::GenerateSlow(MacroAssembler* masm) { 1050 void StoreIC::GenerateSlow(MacroAssembler* masm) {
1134 // Return address is on the stack. 1051 // Return address is on the stack.
1135 StoreIC_PushArgs(masm); 1052 StoreIC_PushArgs(masm);
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
1205 if (*test_instruction_address != Assembler::kTestAlByte) { 1122 if (*test_instruction_address != Assembler::kTestAlByte) {
1206 DCHECK(*test_instruction_address == Assembler::kNopByte); 1123 DCHECK(*test_instruction_address == Assembler::kNopByte);
1207 return; 1124 return;
1208 } 1125 }
1209 1126
1210 Address delta_address = test_instruction_address + 1; 1127 Address delta_address = test_instruction_address + 1;
1211 // The delta to the start of the map check instruction and the 1128 // The delta to the start of the map check instruction and the
1212 // condition code uses at the patched jump. 1129 // condition code uses at the patched jump.
1213 uint8_t delta = *reinterpret_cast<uint8_t*>(delta_address); 1130 uint8_t delta = *reinterpret_cast<uint8_t*>(delta_address);
1214 if (FLAG_trace_ic) { 1131 if (FLAG_trace_ic) {
1215 PrintF("[ patching ic at %p, test=%p, delta=%d\n", 1132 PrintF("[ patching ic at %p, test=%p, delta=%d\n", address,
1216 address, test_instruction_address, delta); 1133 test_instruction_address, delta);
1217 } 1134 }
1218 1135
1219 // Patch with a short conditional jump. Enabling means switching from a short 1136 // Patch with a short conditional jump. Enabling means switching from a short
1220 // jump-if-carry/not-carry to jump-if-zero/not-zero, whereas disabling is the 1137 // jump-if-carry/not-carry to jump-if-zero/not-zero, whereas disabling is the
1221 // reverse operation of that. 1138 // reverse operation of that.
1222 Address jmp_address = test_instruction_address - delta; 1139 Address jmp_address = test_instruction_address - delta;
1223 DCHECK((check == ENABLE_INLINED_SMI_CHECK) 1140 DCHECK((check == ENABLE_INLINED_SMI_CHECK)
1224 ? (*jmp_address == Assembler::kJncShortOpcode || 1141 ? (*jmp_address == Assembler::kJncShortOpcode ||
1225 *jmp_address == Assembler::kJcShortOpcode) 1142 *jmp_address == Assembler::kJcShortOpcode)
1226 : (*jmp_address == Assembler::kJnzShortOpcode || 1143 : (*jmp_address == Assembler::kJnzShortOpcode ||
1227 *jmp_address == Assembler::kJzShortOpcode)); 1144 *jmp_address == Assembler::kJzShortOpcode));
1228 Condition cc = (check == ENABLE_INLINED_SMI_CHECK) 1145 Condition cc =
1229 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) 1146 (check == ENABLE_INLINED_SMI_CHECK)
1230 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); 1147 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero)
1148 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry);
1231 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); 1149 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc);
1232 } 1150 }
1233 1151 }
1234 1152 } // namespace v8::internal
1235 } } // namespace v8::internal
1236 1153
1237 #endif // V8_TARGET_ARCH_X64 1154 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/ic/x64/ic-compiler-x64.cc ('k') | src/ic/x64/stub-cache-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698