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

Side by Side Diff: runtime/vm/intrinsifier_x64.cc

Issue 22866025: Always generate full unoptimized code for intrinsified methods. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 3 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 | « runtime/vm/intrinsifier_mips.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64.
6 #if defined(TARGET_ARCH_X64) 6 #if defined(TARGET_ARCH_X64)
7 7
8 #include "vm/intrinsifier.h" 8 #include "vm/intrinsifier.h"
9 9
10 #include "vm/assembler.h" 10 #include "vm/assembler.h"
11 #include "vm/flow_graph_compiler.h" 11 #include "vm/flow_graph_compiler.h"
12 #include "vm/instructions.h" 12 #include "vm/instructions.h"
13 #include "vm/object_store.h" 13 #include "vm/object_store.h"
14 #include "vm/symbols.h" 14 #include "vm/symbols.h"
15 15
16 namespace dart { 16 namespace dart {
17 17
18 DECLARE_FLAG(bool, enable_type_checks); 18 DECLARE_FLAG(bool, enable_type_checks);
19 19
20 // When entering intrinsics code: 20 // When entering intrinsics code:
21 // RBX: IC Data 21 // RBX: IC Data
22 // R10: Arguments descriptor 22 // R10: Arguments descriptor
23 // TOS: Return address 23 // TOS: Return address
24 // The RBX, R10 registers can be destroyed only if there is no slow-path (i.e., 24 // The RBX, R10 registers can be destroyed only if there is no slow-path (i.e.,
25 // the methods returns true). 25 // the methods returns true).
26 26
27 #define __ assembler-> 27 #define __ assembler->
28 28
29 29
30 bool Intrinsifier::ObjectArray_Allocate(Assembler* assembler) { 30 void Intrinsifier::ObjectArray_Allocate(Assembler* assembler) {
31 // This snippet of inlined code uses the following registers: 31 // This snippet of inlined code uses the following registers:
32 // RAX, RCX, RDI, R13 32 // RAX, RCX, RDI, R13
33 // and the newly allocated object is returned in RAX. 33 // and the newly allocated object is returned in RAX.
34 const intptr_t kTypeArgumentsOffset = 2 * kWordSize; 34 const intptr_t kTypeArgumentsOffset = 2 * kWordSize;
35 const intptr_t kArrayLengthOffset = 1 * kWordSize; 35 const intptr_t kArrayLengthOffset = 1 * kWordSize;
36 Label fall_through; 36 Label fall_through;
37 37
38 // Compute the size to be allocated, it is based on the array length 38 // Compute the size to be allocated, it is based on the array length
39 // and is computed as: 39 // and is computed as:
40 // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)). 40 // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)).
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
125 __ Bind(&init_loop); 125 __ Bind(&init_loop);
126 __ cmpq(RDI, RCX); 126 __ cmpq(RDI, RCX);
127 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); 127 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump);
128 __ movq(Address(RDI, 0), raw_null); 128 __ movq(Address(RDI, 0), raw_null);
129 __ addq(RDI, Immediate(kWordSize)); 129 __ addq(RDI, Immediate(kWordSize));
130 __ jmp(&init_loop, Assembler::kNearJump); 130 __ jmp(&init_loop, Assembler::kNearJump);
131 __ Bind(&done); 131 __ Bind(&done);
132 __ ret(); // returns the newly allocated object in RAX. 132 __ ret(); // returns the newly allocated object in RAX.
133 133
134 __ Bind(&fall_through); 134 __ Bind(&fall_through);
135 return false;
136 } 135 }
137 136
138 137
139 bool Intrinsifier::Array_getLength(Assembler* assembler) { 138 void Intrinsifier::Array_getLength(Assembler* assembler) {
140 __ movq(RAX, Address(RSP, + 1 * kWordSize)); 139 __ movq(RAX, Address(RSP, + 1 * kWordSize));
141 __ movq(RAX, FieldAddress(RAX, Array::length_offset())); 140 __ movq(RAX, FieldAddress(RAX, Array::length_offset()));
142 __ ret(); 141 __ ret();
143 return true;
144 } 142 }
145 143
146 144
147 bool Intrinsifier::ImmutableArray_getLength(Assembler* assembler) { 145 void Intrinsifier::ImmutableArray_getLength(Assembler* assembler) {
148 return Array_getLength(assembler); 146 return Array_getLength(assembler);
149 } 147 }
150 148
151 149
152 bool Intrinsifier::Array_getIndexed(Assembler* assembler) { 150 void Intrinsifier::Array_getIndexed(Assembler* assembler) {
153 Label fall_through; 151 Label fall_through;
154 __ movq(RCX, Address(RSP, + 1 * kWordSize)); // Index. 152 __ movq(RCX, Address(RSP, + 1 * kWordSize)); // Index.
155 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Array. 153 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Array.
156 __ testq(RCX, Immediate(kSmiTagMask)); 154 __ testq(RCX, Immediate(kSmiTagMask));
157 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi index. 155 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi index.
158 // Range check. 156 // Range check.
159 __ cmpq(RCX, FieldAddress(RAX, Array::length_offset())); 157 __ cmpq(RCX, FieldAddress(RAX, Array::length_offset()));
160 // Runtime throws exception. 158 // Runtime throws exception.
161 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump); 159 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump);
162 // Note that RBX is Smi, i.e, times 2. 160 // Note that RBX is Smi, i.e, times 2.
163 ASSERT(kSmiTagShift == 1); 161 ASSERT(kSmiTagShift == 1);
164 __ movq(RAX, FieldAddress(RAX, RCX, TIMES_4, Array::data_offset())); 162 __ movq(RAX, FieldAddress(RAX, RCX, TIMES_4, Array::data_offset()));
165 __ ret(); 163 __ ret();
166 __ Bind(&fall_through); 164 __ Bind(&fall_through);
167 return false;
168 } 165 }
169 166
170 167
171 bool Intrinsifier::ImmutableArray_getIndexed(Assembler* assembler) { 168 void Intrinsifier::ImmutableArray_getIndexed(Assembler* assembler) {
172 return Array_getIndexed(assembler); 169 return Array_getIndexed(assembler);
173 } 170 }
174 171
175 172
176 bool Intrinsifier::Array_setIndexed(Assembler* assembler) { 173 void Intrinsifier::Array_setIndexed(Assembler* assembler) {
177 if (FLAG_enable_type_checks) { 174 if (FLAG_enable_type_checks) {
178 return false; 175 return;
179 } 176 }
180 __ movq(RDX, Address(RSP, + 1 * kWordSize)); // Value. 177 __ movq(RDX, Address(RSP, + 1 * kWordSize)); // Value.
181 __ movq(RCX, Address(RSP, + 2 * kWordSize)); // Index. 178 __ movq(RCX, Address(RSP, + 2 * kWordSize)); // Index.
182 __ movq(RAX, Address(RSP, + 3 * kWordSize)); // Array. 179 __ movq(RAX, Address(RSP, + 3 * kWordSize)); // Array.
183 Label fall_through; 180 Label fall_through;
184 __ testq(RCX, Immediate(kSmiTagMask)); 181 __ testq(RCX, Immediate(kSmiTagMask));
185 __ j(NOT_ZERO, &fall_through); 182 __ j(NOT_ZERO, &fall_through);
186 // Range check. 183 // Range check.
187 __ cmpq(RCX, FieldAddress(RAX, Array::length_offset())); 184 __ cmpq(RCX, FieldAddress(RAX, Array::length_offset()));
188 // Runtime throws exception. 185 // Runtime throws exception.
189 __ j(ABOVE_EQUAL, &fall_through); 186 __ j(ABOVE_EQUAL, &fall_through);
190 // Note that RBX is Smi, i.e, times 2. 187 // Note that RBX is Smi, i.e, times 2.
191 ASSERT(kSmiTagShift == 1); 188 ASSERT(kSmiTagShift == 1);
192 // Destroy RCX (ic data) as we will not continue in the function. 189 // Destroy RCX (ic data) as we will not continue in the function.
193 __ StoreIntoObject(RAX, 190 __ StoreIntoObject(RAX,
194 FieldAddress(RAX, RCX, TIMES_4, Array::data_offset()), 191 FieldAddress(RAX, RCX, TIMES_4, Array::data_offset()),
195 RDX); 192 RDX);
196 // Caller is responsible of preserving the value if necessary. 193 // Caller is responsible of preserving the value if necessary.
197 __ ret(); 194 __ ret();
198 __ Bind(&fall_through); 195 __ Bind(&fall_through);
199 return false;
200 } 196 }
201 197
202 198
203 // Allocate a GrowableObjectArray using the backing array specified. 199 // Allocate a GrowableObjectArray using the backing array specified.
204 // On stack: type argument (+2), data (+1), return-address (+0). 200 // On stack: type argument (+2), data (+1), return-address (+0).
205 bool Intrinsifier::GrowableArray_Allocate(Assembler* assembler) { 201 void Intrinsifier::GrowableArray_Allocate(Assembler* assembler) {
206 // This snippet of inlined code uses the following registers: 202 // This snippet of inlined code uses the following registers:
207 // RAX, RCX, R13 203 // RAX, RCX, R13
208 // and the newly allocated object is returned in RAX. 204 // and the newly allocated object is returned in RAX.
209 const intptr_t kTypeArgumentsOffset = 2 * kWordSize; 205 const intptr_t kTypeArgumentsOffset = 2 * kWordSize;
210 const intptr_t kArrayOffset = 1 * kWordSize; 206 const intptr_t kArrayOffset = 1 * kWordSize;
211 Label fall_through; 207 Label fall_through;
212 208
213 // Compute the size to be allocated, it is based on the array length 209 // Compute the size to be allocated, it is based on the array length
214 // and is computed as: 210 // and is computed as:
215 // RoundedAllocationSize(sizeof(RawGrowableObjectArray)) + 211 // RoundedAllocationSize(sizeof(RawGrowableObjectArray)) +
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
260 RAX, 256 RAX,
261 FieldAddress(RAX, GrowableObjectArray::type_arguments_offset()), 257 FieldAddress(RAX, GrowableObjectArray::type_arguments_offset()),
262 RCX); 258 RCX);
263 259
264 // Set the length field in the growable array object to 0. 260 // Set the length field in the growable array object to 0.
265 __ movq(FieldAddress(RAX, GrowableObjectArray::length_offset()), 261 __ movq(FieldAddress(RAX, GrowableObjectArray::length_offset()),
266 Immediate(0)); 262 Immediate(0));
267 __ ret(); // returns the newly allocated object in RAX. 263 __ ret(); // returns the newly allocated object in RAX.
268 264
269 __ Bind(&fall_through); 265 __ Bind(&fall_through);
270 return false;
271 } 266 }
272 267
273 268
274 // Get length of growable object array. 269 // Get length of growable object array.
275 // On stack: growable array (+1), return-address (+0). 270 // On stack: growable array (+1), return-address (+0).
276 bool Intrinsifier::GrowableArray_getLength(Assembler* assembler) { 271 void Intrinsifier::GrowableArray_getLength(Assembler* assembler) {
277 __ movq(RAX, Address(RSP, + 1 * kWordSize)); 272 __ movq(RAX, Address(RSP, + 1 * kWordSize));
278 __ movq(RAX, FieldAddress(RAX, GrowableObjectArray::length_offset())); 273 __ movq(RAX, FieldAddress(RAX, GrowableObjectArray::length_offset()));
279 __ ret(); 274 __ ret();
280 return true;
281 } 275 }
282 276
283 277
284 bool Intrinsifier::GrowableArray_getCapacity(Assembler* assembler) { 278 void Intrinsifier::GrowableArray_getCapacity(Assembler* assembler) {
285 __ movq(RAX, Address(RSP, + 1 * kWordSize)); 279 __ movq(RAX, Address(RSP, + 1 * kWordSize));
286 __ movq(RAX, FieldAddress(RAX, GrowableObjectArray::data_offset())); 280 __ movq(RAX, FieldAddress(RAX, GrowableObjectArray::data_offset()));
287 __ movq(RAX, FieldAddress(RAX, Array::length_offset())); 281 __ movq(RAX, FieldAddress(RAX, Array::length_offset()));
288 __ ret(); 282 __ ret();
289 return true;
290 } 283 }
291 284
292 285
293 // Access growable object array at specified index. 286 // Access growable object array at specified index.
294 // On stack: growable array (+2), index (+1), return-address (+0). 287 // On stack: growable array (+2), index (+1), return-address (+0).
295 bool Intrinsifier::GrowableArray_getIndexed(Assembler* assembler) { 288 void Intrinsifier::GrowableArray_getIndexed(Assembler* assembler) {
296 Label fall_through; 289 Label fall_through;
297 __ movq(RCX, Address(RSP, + 1 * kWordSize)); // Index. 290 __ movq(RCX, Address(RSP, + 1 * kWordSize)); // Index.
298 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // GrowableArray. 291 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // GrowableArray.
299 __ testq(RCX, Immediate(kSmiTagMask)); 292 __ testq(RCX, Immediate(kSmiTagMask));
300 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi index. 293 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi index.
301 // Range check using _length field. 294 // Range check using _length field.
302 __ cmpq(RCX, FieldAddress(RAX, GrowableObjectArray::length_offset())); 295 __ cmpq(RCX, FieldAddress(RAX, GrowableObjectArray::length_offset()));
303 // Runtime throws exception. 296 // Runtime throws exception.
304 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump); 297 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump);
305 __ movq(RAX, FieldAddress(RAX, GrowableObjectArray::data_offset())); // data. 298 __ movq(RAX, FieldAddress(RAX, GrowableObjectArray::data_offset())); // data.
306 299
307 // Note that RCX is Smi, i.e, times 4. 300 // Note that RCX is Smi, i.e, times 4.
308 ASSERT(kSmiTagShift == 1); 301 ASSERT(kSmiTagShift == 1);
309 __ movq(RAX, FieldAddress(RAX, RCX, TIMES_4, Array::data_offset())); 302 __ movq(RAX, FieldAddress(RAX, RCX, TIMES_4, Array::data_offset()));
310 __ ret(); 303 __ ret();
311 __ Bind(&fall_through); 304 __ Bind(&fall_through);
312 return false;
313 } 305 }
314 306
315 307
316 // Set value into growable object array at specified index. 308 // Set value into growable object array at specified index.
317 // On stack: growable array (+3), index (+2), value (+1), return-address (+0). 309 // On stack: growable array (+3), index (+2), value (+1), return-address (+0).
318 bool Intrinsifier::GrowableArray_setIndexed(Assembler* assembler) { 310 void Intrinsifier::GrowableArray_setIndexed(Assembler* assembler) {
319 if (FLAG_enable_type_checks) { 311 if (FLAG_enable_type_checks) {
320 return false; 312 return;
321 } 313 }
322 __ movq(RDX, Address(RSP, + 1 * kWordSize)); // Value. 314 __ movq(RDX, Address(RSP, + 1 * kWordSize)); // Value.
323 __ movq(RCX, Address(RSP, + 2 * kWordSize)); // Index. 315 __ movq(RCX, Address(RSP, + 2 * kWordSize)); // Index.
324 __ movq(RAX, Address(RSP, + 3 * kWordSize)); // GrowableArray. 316 __ movq(RAX, Address(RSP, + 3 * kWordSize)); // GrowableArray.
325 Label fall_through; 317 Label fall_through;
326 __ testq(RCX, Immediate(kSmiTagMask)); 318 __ testq(RCX, Immediate(kSmiTagMask));
327 __ j(NOT_ZERO, &fall_through); // Non-smi index. 319 __ j(NOT_ZERO, &fall_through); // Non-smi index.
328 // Range check using _length field. 320 // Range check using _length field.
329 __ cmpq(RCX, FieldAddress(RAX, GrowableObjectArray::length_offset())); 321 __ cmpq(RCX, FieldAddress(RAX, GrowableObjectArray::length_offset()));
330 // Runtime throws exception. 322 // Runtime throws exception.
331 __ j(ABOVE_EQUAL, &fall_through); 323 __ j(ABOVE_EQUAL, &fall_through);
332 __ movq(RAX, FieldAddress(RAX, GrowableObjectArray::data_offset())); // data. 324 __ movq(RAX, FieldAddress(RAX, GrowableObjectArray::data_offset())); // data.
333 // Note that RCX is Smi, i.e, times 4. 325 // Note that RCX is Smi, i.e, times 4.
334 ASSERT(kSmiTagShift == 1); 326 ASSERT(kSmiTagShift == 1);
335 __ StoreIntoObject(RAX, 327 __ StoreIntoObject(RAX,
336 FieldAddress(RAX, RCX, TIMES_4, Array::data_offset()), 328 FieldAddress(RAX, RCX, TIMES_4, Array::data_offset()),
337 RDX); 329 RDX);
338 __ ret(); 330 __ ret();
339 __ Bind(&fall_through); 331 __ Bind(&fall_through);
340 return false;
341 } 332 }
342 333
343 334
344 // Set length of growable object array. The length cannot 335 // Set length of growable object array. The length cannot
345 // be greater than the length of the data container. 336 // be greater than the length of the data container.
346 // On stack: growable array (+2), length (+1), return-address (+0). 337 // On stack: growable array (+2), length (+1), return-address (+0).
347 bool Intrinsifier::GrowableArray_setLength(Assembler* assembler) { 338 void Intrinsifier::GrowableArray_setLength(Assembler* assembler) {
348 Label fall_through; 339 Label fall_through;
349 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Growable array. 340 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Growable array.
350 __ movq(RCX, Address(RSP, + 1 * kWordSize)); // Length value. 341 __ movq(RCX, Address(RSP, + 1 * kWordSize)); // Length value.
351 __ testq(RCX, Immediate(kSmiTagMask)); 342 __ testq(RCX, Immediate(kSmiTagMask));
352 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi length. 343 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi length.
353 __ movq(FieldAddress(RAX, GrowableObjectArray::length_offset()), RCX); 344 __ movq(FieldAddress(RAX, GrowableObjectArray::length_offset()), RCX);
354 __ ret(); 345 __ ret();
355 __ Bind(&fall_through); 346 __ Bind(&fall_through);
356 return false;
357 } 347 }
358 348
359 349
360 // Set data of growable object array. 350 // Set data of growable object array.
361 // On stack: growable array (+2), data (+1), return-address (+0). 351 // On stack: growable array (+2), data (+1), return-address (+0).
362 bool Intrinsifier::GrowableArray_setData(Assembler* assembler) { 352 void Intrinsifier::GrowableArray_setData(Assembler* assembler) {
363 if (FLAG_enable_type_checks) { 353 if (FLAG_enable_type_checks) {
364 return false; 354 return;
365 } 355 }
366 Label fall_through; 356 Label fall_through;
367 __ movq(RBX, Address(RSP, + 1 * kWordSize)); /// Data. 357 __ movq(RBX, Address(RSP, + 1 * kWordSize)); /// Data.
368 __ testq(RBX, Immediate(kSmiTagMask)); 358 __ testq(RBX, Immediate(kSmiTagMask));
369 __ j(ZERO, &fall_through); // Data is Smi. 359 __ j(ZERO, &fall_through); // Data is Smi.
370 __ CompareClassId(RBX, kArrayCid); 360 __ CompareClassId(RBX, kArrayCid);
371 __ j(NOT_EQUAL, &fall_through); 361 __ j(NOT_EQUAL, &fall_through);
372 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Growable array. 362 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Growable array.
373 __ StoreIntoObject(RAX, 363 __ StoreIntoObject(RAX,
374 FieldAddress(RAX, GrowableObjectArray::data_offset()), 364 FieldAddress(RAX, GrowableObjectArray::data_offset()),
375 RBX); 365 RBX);
376 __ ret(); 366 __ ret();
377 __ Bind(&fall_through); 367 __ Bind(&fall_through);
378 return false;
379 } 368 }
380 369
381 370
382 // Add an element to growable array if it doesn't need to grow, otherwise 371 // Add an element to growable array if it doesn't need to grow, otherwise
383 // call into regular code. 372 // call into regular code.
384 // On stack: growable array (+2), value (+1), return-address (+0). 373 // On stack: growable array (+2), value (+1), return-address (+0).
385 bool Intrinsifier::GrowableArray_add(Assembler* assembler) { 374 void Intrinsifier::GrowableArray_add(Assembler* assembler) {
386 // In checked mode we need to check the incoming argument. 375 // In checked mode we need to check the incoming argument.
387 if (FLAG_enable_type_checks) return false; 376 if (FLAG_enable_type_checks) return;
388 Label fall_through; 377 Label fall_through;
389 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Array. 378 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Array.
390 __ movq(RCX, FieldAddress(RAX, GrowableObjectArray::length_offset())); 379 __ movq(RCX, FieldAddress(RAX, GrowableObjectArray::length_offset()));
391 // RCX: length. 380 // RCX: length.
392 __ movq(RDX, FieldAddress(RAX, GrowableObjectArray::data_offset())); 381 __ movq(RDX, FieldAddress(RAX, GrowableObjectArray::data_offset()));
393 // RDX: data. 382 // RDX: data.
394 // Compare length with capacity. 383 // Compare length with capacity.
395 __ cmpq(RCX, FieldAddress(RDX, Array::length_offset())); 384 __ cmpq(RCX, FieldAddress(RDX, Array::length_offset()));
396 __ j(EQUAL, &fall_through); // Must grow data. 385 __ j(EQUAL, &fall_through); // Must grow data.
397 const Immediate& value_one = 386 const Immediate& value_one =
398 Immediate(reinterpret_cast<int64_t>(Smi::New(1))); 387 Immediate(reinterpret_cast<int64_t>(Smi::New(1)));
399 // len = len + 1; 388 // len = len + 1;
400 __ addq(FieldAddress(RAX, GrowableObjectArray::length_offset()), value_one); 389 __ addq(FieldAddress(RAX, GrowableObjectArray::length_offset()), value_one);
401 __ movq(RAX, Address(RSP, + 1 * kWordSize)); // Value 390 __ movq(RAX, Address(RSP, + 1 * kWordSize)); // Value
402 ASSERT(kSmiTagShift == 1); 391 ASSERT(kSmiTagShift == 1);
403 __ StoreIntoObject(RDX, 392 __ StoreIntoObject(RDX,
404 FieldAddress(RDX, RCX, TIMES_4, Array::data_offset()), 393 FieldAddress(RDX, RCX, TIMES_4, Array::data_offset()),
405 RAX); 394 RAX);
406 const Immediate& raw_null = 395 const Immediate& raw_null =
407 Immediate(reinterpret_cast<int64_t>(Object::null())); 396 Immediate(reinterpret_cast<int64_t>(Object::null()));
408 __ movq(RAX, raw_null); 397 __ movq(RAX, raw_null);
409 __ ret(); 398 __ ret();
410 __ Bind(&fall_through); 399 __ Bind(&fall_through);
411 return false;
412 } 400 }
413 401
414 402
415 #define TYPED_ARRAY_ALLOCATION(type_name, cid, max_len, scale_factor) \ 403 #define TYPED_ARRAY_ALLOCATION(type_name, cid, max_len, scale_factor) \
416 Label fall_through; \ 404 Label fall_through; \
417 const intptr_t kArrayLengthStackOffset = 1 * kWordSize; \ 405 const intptr_t kArrayLengthStackOffset = 1 * kWordSize; \
418 __ movq(RDI, Address(RSP, kArrayLengthStackOffset)); /* Array length. */ \ 406 __ movq(RDI, Address(RSP, kArrayLengthStackOffset)); /* Array length. */ \
419 /* Check that length is a positive Smi. */ \ 407 /* Check that length is a positive Smi. */ \
420 /* RDI: requested array length argument. */ \ 408 /* RDI: requested array length argument. */ \
421 __ testq(RDI, Immediate(kSmiTagMask)); \ 409 __ testq(RDI, Immediate(kSmiTagMask)); \
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
504 __ movq(Address(RDI, 0), RBX); \ 492 __ movq(Address(RDI, 0), RBX); \
505 __ addq(RDI, Immediate(kWordSize)); \ 493 __ addq(RDI, Immediate(kWordSize)); \
506 __ jmp(&init_loop, Assembler::kNearJump); \ 494 __ jmp(&init_loop, Assembler::kNearJump); \
507 __ Bind(&done); \ 495 __ Bind(&done); \
508 \ 496 \
509 __ ret(); \ 497 __ ret(); \
510 __ Bind(&fall_through); \ 498 __ Bind(&fall_through); \
511 499
512 500
513 // Gets the length of a TypedData. 501 // Gets the length of a TypedData.
514 bool Intrinsifier::TypedData_getLength(Assembler* assembler) { 502 void Intrinsifier::TypedData_getLength(Assembler* assembler) {
515 __ movq(RAX, Address(RSP, + 1 * kWordSize)); 503 __ movq(RAX, Address(RSP, + 1 * kWordSize));
516 __ movq(RAX, FieldAddress(RAX, TypedData::length_offset())); 504 __ movq(RAX, FieldAddress(RAX, TypedData::length_offset()));
517 __ ret(); 505 __ ret();
518 // Generate enough code to satisfy patchability constraint.
519 intptr_t offset = __ CodeSize();
520 __ nop(JumpPattern::InstructionLength() - offset);
521 return true;
522 } 506 }
523 507
524 508
525 static ScaleFactor GetScaleFactor(intptr_t size) { 509 static ScaleFactor GetScaleFactor(intptr_t size) {
526 switch (size) { 510 switch (size) {
527 case 1: return TIMES_1; 511 case 1: return TIMES_1;
528 case 2: return TIMES_2; 512 case 2: return TIMES_2;
529 case 4: return TIMES_4; 513 case 4: return TIMES_4;
530 case 8: return TIMES_8; 514 case 8: return TIMES_8;
531 case 16: return TIMES_16; 515 case 16: return TIMES_16;
532 } 516 }
533 UNREACHABLE(); 517 UNREACHABLE();
534 return static_cast<ScaleFactor>(0); 518 return static_cast<ScaleFactor>(0);
535 }; 519 };
536 520
537 521
538 #define TYPED_DATA_ALLOCATOR(clazz) \ 522 #define TYPED_DATA_ALLOCATOR(clazz) \
539 bool Intrinsifier::TypedData_##clazz##_new(Assembler* assembler) { \ 523 void Intrinsifier::TypedData_##clazz##_new(Assembler* assembler) { \
540 intptr_t size = TypedData::ElementSizeInBytes(kTypedData##clazz##Cid); \ 524 intptr_t size = TypedData::ElementSizeInBytes(kTypedData##clazz##Cid); \
541 intptr_t max_len = TypedData::MaxElements(kTypedData##clazz##Cid); \ 525 intptr_t max_len = TypedData::MaxElements(kTypedData##clazz##Cid); \
542 ScaleFactor scale = GetScaleFactor(size); \ 526 ScaleFactor scale = GetScaleFactor(size); \
543 TYPED_ARRAY_ALLOCATION(TypedData, kTypedData##clazz##Cid, max_len, scale); \ 527 TYPED_ARRAY_ALLOCATION(TypedData, kTypedData##clazz##Cid, max_len, scale); \
544 return false; \
545 } \ 528 } \
546 bool Intrinsifier::TypedData_##clazz##_factory(Assembler* assembler) { \ 529 void Intrinsifier::TypedData_##clazz##_factory(Assembler* assembler) { \
547 intptr_t size = TypedData::ElementSizeInBytes(kTypedData##clazz##Cid); \ 530 intptr_t size = TypedData::ElementSizeInBytes(kTypedData##clazz##Cid); \
548 intptr_t max_len = TypedData::MaxElements(kTypedData##clazz##Cid); \ 531 intptr_t max_len = TypedData::MaxElements(kTypedData##clazz##Cid); \
549 ScaleFactor scale = GetScaleFactor(size); \ 532 ScaleFactor scale = GetScaleFactor(size); \
550 TYPED_ARRAY_ALLOCATION(TypedData, kTypedData##clazz##Cid, max_len, scale); \ 533 TYPED_ARRAY_ALLOCATION(TypedData, kTypedData##clazz##Cid, max_len, scale); \
551 return false; \
552 } 534 }
553 CLASS_LIST_TYPED_DATA(TYPED_DATA_ALLOCATOR) 535 CLASS_LIST_TYPED_DATA(TYPED_DATA_ALLOCATOR)
554 #undef TYPED_DATA_ALLOCATOR 536 #undef TYPED_DATA_ALLOCATOR
555 537
556 538
557 // Tests if two top most arguments are smis, jumps to label not_smi if not. 539 // Tests if two top most arguments are smis, jumps to label not_smi if not.
558 // Topmost argument is in RAX. 540 // Topmost argument is in RAX.
559 static void TestBothArgumentsSmis(Assembler* assembler, Label* not_smi) { 541 static void TestBothArgumentsSmis(Assembler* assembler, Label* not_smi) {
560 __ movq(RAX, Address(RSP, + 1 * kWordSize)); 542 __ movq(RAX, Address(RSP, + 1 * kWordSize));
561 __ movq(RCX, Address(RSP, + 2 * kWordSize)); 543 __ movq(RCX, Address(RSP, + 2 * kWordSize));
562 __ orq(RCX, RAX); 544 __ orq(RCX, RAX);
563 __ testq(RCX, Immediate(kSmiTagMask)); 545 __ testq(RCX, Immediate(kSmiTagMask));
564 __ j(NOT_ZERO, not_smi); 546 __ j(NOT_ZERO, not_smi);
565 } 547 }
566 548
567 549
568 bool Intrinsifier::Integer_addFromInteger(Assembler* assembler) { 550 void Intrinsifier::Integer_addFromInteger(Assembler* assembler) {
569 Label fall_through; 551 Label fall_through;
570 TestBothArgumentsSmis(assembler, &fall_through); 552 TestBothArgumentsSmis(assembler, &fall_through);
571 // RAX contains right argument. 553 // RAX contains right argument.
572 __ addq(RAX, Address(RSP, + 2 * kWordSize)); 554 __ addq(RAX, Address(RSP, + 2 * kWordSize));
573 __ j(OVERFLOW, &fall_through, Assembler::kNearJump); 555 __ j(OVERFLOW, &fall_through, Assembler::kNearJump);
574 // Result is in RAX. 556 // Result is in RAX.
575 __ ret(); 557 __ ret();
576 __ Bind(&fall_through); 558 __ Bind(&fall_through);
577 return false;
578 } 559 }
579 560
580 561
581 bool Intrinsifier::Integer_add(Assembler* assembler) { 562 void Intrinsifier::Integer_add(Assembler* assembler) {
582 return Integer_addFromInteger(assembler); 563 return Integer_addFromInteger(assembler);
583 } 564 }
584 565
585 566
586 bool Intrinsifier::Integer_subFromInteger(Assembler* assembler) { 567 void Intrinsifier::Integer_subFromInteger(Assembler* assembler) {
587 Label fall_through; 568 Label fall_through;
588 TestBothArgumentsSmis(assembler, &fall_through); 569 TestBothArgumentsSmis(assembler, &fall_through);
589 // RAX contains right argument, which is the actual minuend of subtraction. 570 // RAX contains right argument, which is the actual minuend of subtraction.
590 __ subq(RAX, Address(RSP, + 2 * kWordSize)); 571 __ subq(RAX, Address(RSP, + 2 * kWordSize));
591 __ j(OVERFLOW, &fall_through, Assembler::kNearJump); 572 __ j(OVERFLOW, &fall_through, Assembler::kNearJump);
592 // Result is in RAX. 573 // Result is in RAX.
593 __ ret(); 574 __ ret();
594 __ Bind(&fall_through); 575 __ Bind(&fall_through);
595 return false;
596 } 576 }
597 577
598 578
599 bool Intrinsifier::Integer_sub(Assembler* assembler) { 579 void Intrinsifier::Integer_sub(Assembler* assembler) {
600 Label fall_through; 580 Label fall_through;
601 TestBothArgumentsSmis(assembler, &fall_through); 581 TestBothArgumentsSmis(assembler, &fall_through);
602 // RAX contains right argument, which is the actual subtrahend of subtraction. 582 // RAX contains right argument, which is the actual subtrahend of subtraction.
603 __ movq(RCX, RAX); 583 __ movq(RCX, RAX);
604 __ movq(RAX, Address(RSP, + 2 * kWordSize)); 584 __ movq(RAX, Address(RSP, + 2 * kWordSize));
605 __ subq(RAX, RCX); 585 __ subq(RAX, RCX);
606 __ j(OVERFLOW, &fall_through, Assembler::kNearJump); 586 __ j(OVERFLOW, &fall_through, Assembler::kNearJump);
607 // Result is in RAX. 587 // Result is in RAX.
608 __ ret(); 588 __ ret();
609 __ Bind(&fall_through); 589 __ Bind(&fall_through);
610 return false;
611 } 590 }
612 591
613 592
614 593
615 bool Intrinsifier::Integer_mulFromInteger(Assembler* assembler) { 594 void Intrinsifier::Integer_mulFromInteger(Assembler* assembler) {
616 Label fall_through; 595 Label fall_through;
617 TestBothArgumentsSmis(assembler, &fall_through); 596 TestBothArgumentsSmis(assembler, &fall_through);
618 // RAX is the right argument. 597 // RAX is the right argument.
619 ASSERT(kSmiTag == 0); // Adjust code below if not the case. 598 ASSERT(kSmiTag == 0); // Adjust code below if not the case.
620 __ SmiUntag(RAX); 599 __ SmiUntag(RAX);
621 __ imulq(RAX, Address(RSP, + 2 * kWordSize)); 600 __ imulq(RAX, Address(RSP, + 2 * kWordSize));
622 __ j(OVERFLOW, &fall_through, Assembler::kNearJump); 601 __ j(OVERFLOW, &fall_through, Assembler::kNearJump);
623 // Result is in RAX. 602 // Result is in RAX.
624 __ ret(); 603 __ ret();
625 __ Bind(&fall_through); 604 __ Bind(&fall_through);
626 return false;
627 } 605 }
628 606
629 607
630 bool Intrinsifier::Integer_mul(Assembler* assembler) { 608 void Intrinsifier::Integer_mul(Assembler* assembler) {
631 return Integer_mulFromInteger(assembler); 609 return Integer_mulFromInteger(assembler);
632 } 610 }
633 611
634 612
635 // Optimizations: 613 // Optimizations:
636 // - result is 0 if: 614 // - result is 0 if:
637 // - left is 0 615 // - left is 0
638 // - left equals right 616 // - left equals right
639 // - result is left if 617 // - result is left if
640 // - left > 0 && left < right 618 // - left > 0 && left < right
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
696 674
697 // Implementation: 675 // Implementation:
698 // res = left % right; 676 // res = left % right;
699 // if (res < 0) { 677 // if (res < 0) {
700 // if (right < 0) { 678 // if (right < 0) {
701 // res = res - right; 679 // res = res - right;
702 // } else { 680 // } else {
703 // res = res + right; 681 // res = res + right;
704 // } 682 // }
705 // } 683 // }
706 bool Intrinsifier::Integer_moduloFromInteger(Assembler* assembler) { 684 void Intrinsifier::Integer_moduloFromInteger(Assembler* assembler) {
707 Label fall_through, negative_result; 685 Label fall_through, negative_result;
708 TestBothArgumentsSmis(assembler, &fall_through); 686 TestBothArgumentsSmis(assembler, &fall_through);
709 __ movq(RCX, Address(RSP, + 2 * kWordSize)); 687 __ movq(RCX, Address(RSP, + 2 * kWordSize));
710 // RAX: Tagged left (dividend). 688 // RAX: Tagged left (dividend).
711 // RCX: Tagged right (divisor). 689 // RCX: Tagged right (divisor).
712 __ cmpq(RCX, Immediate(0)); 690 __ cmpq(RCX, Immediate(0));
713 __ j(EQUAL, &fall_through); 691 __ j(EQUAL, &fall_through);
714 EmitRemainderOperation(assembler); 692 EmitRemainderOperation(assembler);
715 // Untagged remainder result in RAX. 693 // Untagged remainder result in RAX.
716 __ cmpq(RAX, Immediate(0)); 694 __ cmpq(RAX, Immediate(0));
(...skipping 10 matching lines...) Expand all
727 __ addq(RAX, RCX); 705 __ addq(RAX, RCX);
728 __ SmiTag(RAX); 706 __ SmiTag(RAX);
729 __ ret(); 707 __ ret();
730 708
731 __ Bind(&subtract); 709 __ Bind(&subtract);
732 __ subq(RAX, RCX); 710 __ subq(RAX, RCX);
733 __ SmiTag(RAX); 711 __ SmiTag(RAX);
734 __ ret(); 712 __ ret();
735 713
736 __ Bind(&fall_through); 714 __ Bind(&fall_through);
737 return false;
738 } 715 }
739 716
740 717
741 bool Intrinsifier::Integer_remainder(Assembler* assembler) { 718 void Intrinsifier::Integer_remainder(Assembler* assembler) {
742 Label fall_through; 719 Label fall_through;
743 TestBothArgumentsSmis(assembler, &fall_through); 720 TestBothArgumentsSmis(assembler, &fall_through);
744 // RAX: right argument (divisor) 721 // RAX: right argument (divisor)
745 __ movq(RCX, RAX); 722 __ movq(RCX, RAX);
746 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Left argument (dividend). 723 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Left argument (dividend).
747 // RAX: Tagged left (dividend). 724 // RAX: Tagged left (dividend).
748 // RCX: Tagged right (divisor). 725 // RCX: Tagged right (divisor).
749 __ cmpq(RCX, Immediate(0)); 726 __ cmpq(RCX, Immediate(0));
750 __ j(EQUAL, &fall_through); 727 __ j(EQUAL, &fall_through);
751 EmitRemainderOperation(assembler); 728 EmitRemainderOperation(assembler);
752 // Untagged remainder result in RAX. 729 // Untagged remainder result in RAX.
753 __ SmiTag(RAX); 730 __ SmiTag(RAX);
754 __ ret(); 731 __ ret();
755 __ Bind(&fall_through); 732 __ Bind(&fall_through);
756 return false;
757 } 733 }
758 734
759 735
760 bool Intrinsifier::Integer_truncDivide(Assembler* assembler) { 736 void Intrinsifier::Integer_truncDivide(Assembler* assembler) {
761 Label fall_through, not_32bit; 737 Label fall_through, not_32bit;
762 TestBothArgumentsSmis(assembler, &fall_through); 738 TestBothArgumentsSmis(assembler, &fall_through);
763 // RAX: right argument (divisor) 739 // RAX: right argument (divisor)
764 __ cmpq(RAX, Immediate(0)); 740 __ cmpq(RAX, Immediate(0));
765 __ j(EQUAL, &fall_through, Assembler::kNearJump); 741 __ j(EQUAL, &fall_through, Assembler::kNearJump);
766 __ movq(RCX, RAX); 742 __ movq(RCX, RAX);
767 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Left argument (dividend). 743 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Left argument (dividend).
768 744
769 // Check if both operands fit into 32bits as idiv with 64bit operands 745 // Check if both operands fit into 32bits as idiv with 64bit operands
770 // requires twice as many cycles and has much higher latency. We are checking 746 // requires twice as many cycles and has much higher latency. We are checking
(...skipping 23 matching lines...) Expand all
794 __ cqo(); 770 __ cqo();
795 __ idivq(RCX); 771 __ idivq(RCX);
796 __ popq(RDX); 772 __ popq(RDX);
797 // Check the corner case of dividing the 'MIN_SMI' with -1, in which case we 773 // Check the corner case of dividing the 'MIN_SMI' with -1, in which case we
798 // cannot tag the result. 774 // cannot tag the result.
799 __ cmpq(RAX, Immediate(0x4000000000000000)); 775 __ cmpq(RAX, Immediate(0x4000000000000000));
800 __ j(EQUAL, &fall_through); 776 __ j(EQUAL, &fall_through);
801 __ SmiTag(RAX); 777 __ SmiTag(RAX);
802 __ ret(); 778 __ ret();
803 __ Bind(&fall_through); 779 __ Bind(&fall_through);
804 return false;
805 } 780 }
806 781
807 782
808 bool Intrinsifier::Integer_negate(Assembler* assembler) { 783 void Intrinsifier::Integer_negate(Assembler* assembler) {
809 Label fall_through; 784 Label fall_through;
810 __ movq(RAX, Address(RSP, + 1 * kWordSize)); 785 __ movq(RAX, Address(RSP, + 1 * kWordSize));
811 __ testq(RAX, Immediate(kSmiTagMask)); 786 __ testq(RAX, Immediate(kSmiTagMask));
812 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi value. 787 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi value.
813 __ negq(RAX); 788 __ negq(RAX);
814 __ j(OVERFLOW, &fall_through, Assembler::kNearJump); 789 __ j(OVERFLOW, &fall_through, Assembler::kNearJump);
815 // Result is in RAX. 790 // Result is in RAX.
816 __ ret(); 791 __ ret();
817 __ Bind(&fall_through); 792 __ Bind(&fall_through);
818 return false;
819 } 793 }
820 794
821 795
822 bool Intrinsifier::Integer_bitAndFromInteger(Assembler* assembler) { 796 void Intrinsifier::Integer_bitAndFromInteger(Assembler* assembler) {
823 Label fall_through; 797 Label fall_through;
824 TestBothArgumentsSmis(assembler, &fall_through); 798 TestBothArgumentsSmis(assembler, &fall_through);
825 // RAX is the right argument. 799 // RAX is the right argument.
826 __ andq(RAX, Address(RSP, + 2 * kWordSize)); 800 __ andq(RAX, Address(RSP, + 2 * kWordSize));
827 // Result is in RAX. 801 // Result is in RAX.
828 __ ret(); 802 __ ret();
829 __ Bind(&fall_through); 803 __ Bind(&fall_through);
830 return false;
831 } 804 }
832 805
833 806
834 bool Intrinsifier::Integer_bitAnd(Assembler* assembler) { 807 void Intrinsifier::Integer_bitAnd(Assembler* assembler) {
835 return Integer_bitAndFromInteger(assembler); 808 return Integer_bitAndFromInteger(assembler);
836 } 809 }
837 810
838 811
839 bool Intrinsifier::Integer_bitOrFromInteger(Assembler* assembler) { 812 void Intrinsifier::Integer_bitOrFromInteger(Assembler* assembler) {
840 Label fall_through; 813 Label fall_through;
841 TestBothArgumentsSmis(assembler, &fall_through); 814 TestBothArgumentsSmis(assembler, &fall_through);
842 // RAX is the right argument. 815 // RAX is the right argument.
843 __ orq(RAX, Address(RSP, + 2 * kWordSize)); 816 __ orq(RAX, Address(RSP, + 2 * kWordSize));
844 // Result is in RAX. 817 // Result is in RAX.
845 __ ret(); 818 __ ret();
846 __ Bind(&fall_through); 819 __ Bind(&fall_through);
847 return false;
848 } 820 }
849 821
850 822
851 bool Intrinsifier::Integer_bitOr(Assembler* assembler) { 823 void Intrinsifier::Integer_bitOr(Assembler* assembler) {
852 return Integer_bitOrFromInteger(assembler); 824 return Integer_bitOrFromInteger(assembler);
853 } 825 }
854 826
855 827
856 bool Intrinsifier::Integer_bitXorFromInteger(Assembler* assembler) { 828 void Intrinsifier::Integer_bitXorFromInteger(Assembler* assembler) {
857 Label fall_through; 829 Label fall_through;
858 TestBothArgumentsSmis(assembler, &fall_through); 830 TestBothArgumentsSmis(assembler, &fall_through);
859 // RAX is the right argument. 831 // RAX is the right argument.
860 __ xorq(RAX, Address(RSP, + 2 * kWordSize)); 832 __ xorq(RAX, Address(RSP, + 2 * kWordSize));
861 // Result is in RAX. 833 // Result is in RAX.
862 __ ret(); 834 __ ret();
863 __ Bind(&fall_through); 835 __ Bind(&fall_through);
864 return false;
865 } 836 }
866 837
867 838
868 bool Intrinsifier::Integer_bitXor(Assembler* assembler) { 839 void Intrinsifier::Integer_bitXor(Assembler* assembler) {
869 return Integer_bitXorFromInteger(assembler); 840 return Integer_bitXorFromInteger(assembler);
870 } 841 }
871 842
872 843
873 bool Intrinsifier::Integer_shl(Assembler* assembler) { 844 void Intrinsifier::Integer_shl(Assembler* assembler) {
874 ASSERT(kSmiTagShift == 1); 845 ASSERT(kSmiTagShift == 1);
875 ASSERT(kSmiTag == 0); 846 ASSERT(kSmiTag == 0);
876 Label fall_through, overflow; 847 Label fall_through, overflow;
877 TestBothArgumentsSmis(assembler, &fall_through); 848 TestBothArgumentsSmis(assembler, &fall_through);
878 // Shift value is in RAX. Compare with tagged Smi. 849 // Shift value is in RAX. Compare with tagged Smi.
879 __ cmpq(RAX, Immediate(Smi::RawValue(Smi::kBits))); 850 __ cmpq(RAX, Immediate(Smi::RawValue(Smi::kBits)));
880 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump); 851 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump);
881 852
882 __ SmiUntag(RAX); 853 __ SmiUntag(RAX);
883 __ movq(RCX, RAX); // Shift amount must be in RCX. 854 __ movq(RCX, RAX); // Shift amount must be in RCX.
884 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Value. 855 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Value.
885 856
886 // Overflow test - all the shifted-out bits must be same as the sign bit. 857 // Overflow test - all the shifted-out bits must be same as the sign bit.
887 __ movq(RDI, RAX); 858 __ movq(RDI, RAX);
888 __ shlq(RAX, RCX); 859 __ shlq(RAX, RCX);
889 __ sarq(RAX, RCX); 860 __ sarq(RAX, RCX);
890 __ cmpq(RAX, RDI); 861 __ cmpq(RAX, RDI);
891 __ j(NOT_EQUAL, &overflow, Assembler::kNearJump); 862 __ j(NOT_EQUAL, &overflow, Assembler::kNearJump);
892 863
893 __ shlq(RAX, RCX); // Shift for result now we know there is no overflow. 864 __ shlq(RAX, RCX); // Shift for result now we know there is no overflow.
894 865
895 // RAX is a correctly tagged Smi. 866 // RAX is a correctly tagged Smi.
896 __ ret(); 867 __ ret();
897 868
898 __ Bind(&overflow); 869 __ Bind(&overflow);
899 // Mint is rarely used on x64 (only for integers requiring 64 bit instead of 870 // Mint is rarely used on x64 (only for integers requiring 64 bit instead of
900 // 63 bits as represented by Smi). 871 // 63 bits as represented by Smi).
901 __ Bind(&fall_through); 872 __ Bind(&fall_through);
902 return false;
903 } 873 }
904 874
905 875
906 static bool CompareIntegers(Assembler* assembler, Condition true_condition) { 876 static void CompareIntegers(Assembler* assembler, Condition true_condition) {
907 Label fall_through, true_label; 877 Label fall_through, true_label;
908 TestBothArgumentsSmis(assembler, &fall_through); 878 TestBothArgumentsSmis(assembler, &fall_through);
909 // RAX contains the right argument. 879 // RAX contains the right argument.
910 __ cmpq(Address(RSP, + 2 * kWordSize), RAX); 880 __ cmpq(Address(RSP, + 2 * kWordSize), RAX);
911 __ j(true_condition, &true_label, Assembler::kNearJump); 881 __ j(true_condition, &true_label, Assembler::kNearJump);
912 __ LoadObject(RAX, Bool::False()); 882 __ LoadObject(RAX, Bool::False());
913 __ ret(); 883 __ ret();
914 __ Bind(&true_label); 884 __ Bind(&true_label);
915 __ LoadObject(RAX, Bool::True()); 885 __ LoadObject(RAX, Bool::True());
916 __ ret(); 886 __ ret();
917 __ Bind(&fall_through); 887 __ Bind(&fall_through);
918 return false;
919 } 888 }
920 889
921 890
922 891
923 bool Intrinsifier::Integer_lessThan(Assembler* assembler) { 892 void Intrinsifier::Integer_lessThan(Assembler* assembler) {
924 return CompareIntegers(assembler, LESS); 893 return CompareIntegers(assembler, LESS);
925 } 894 }
926 895
927 896
928 bool Intrinsifier::Integer_greaterThanFromInt(Assembler* assembler) { 897 void Intrinsifier::Integer_greaterThanFromInt(Assembler* assembler) {
929 return CompareIntegers(assembler, LESS); 898 return CompareIntegers(assembler, LESS);
930 } 899 }
931 900
932 901
933 bool Intrinsifier::Integer_greaterThan(Assembler* assembler) { 902 void Intrinsifier::Integer_greaterThan(Assembler* assembler) {
934 return CompareIntegers(assembler, GREATER); 903 return CompareIntegers(assembler, GREATER);
935 } 904 }
936 905
937 906
938 bool Intrinsifier::Integer_lessEqualThan(Assembler* assembler) { 907 void Intrinsifier::Integer_lessEqualThan(Assembler* assembler) {
939 return CompareIntegers(assembler, LESS_EQUAL); 908 return CompareIntegers(assembler, LESS_EQUAL);
940 } 909 }
941 910
942 911
943 bool Intrinsifier::Integer_greaterEqualThan(Assembler* assembler) { 912 void Intrinsifier::Integer_greaterEqualThan(Assembler* assembler) {
944 return CompareIntegers(assembler, GREATER_EQUAL); 913 return CompareIntegers(assembler, GREATER_EQUAL);
945 } 914 }
946 915
947 916
948 // This is called for Smi, Mint and Bigint receivers. The right argument 917 // This is called for Smi, Mint and Bigint receivers. The right argument
949 // can be Smi, Mint, Bigint or double. 918 // can be Smi, Mint, Bigint or double.
950 bool Intrinsifier::Integer_equalToInteger(Assembler* assembler) { 919 void Intrinsifier::Integer_equalToInteger(Assembler* assembler) {
951 Label fall_through, true_label, check_for_mint; 920 Label fall_through, true_label, check_for_mint;
952 // For integer receiver '===' check first. 921 // For integer receiver '===' check first.
953 __ movq(RAX, Address(RSP, + 1 * kWordSize)); 922 __ movq(RAX, Address(RSP, + 1 * kWordSize));
954 __ movq(RCX, Address(RSP, + 2 * kWordSize)); 923 __ movq(RCX, Address(RSP, + 2 * kWordSize));
955 __ cmpq(RAX, RCX); 924 __ cmpq(RAX, RCX);
956 __ j(EQUAL, &true_label, Assembler::kNearJump); 925 __ j(EQUAL, &true_label, Assembler::kNearJump);
957 __ orq(RAX, RCX); 926 __ orq(RAX, RCX);
958 __ testq(RAX, Immediate(kSmiTagMask)); 927 __ testq(RAX, Immediate(kSmiTagMask));
959 __ j(NOT_ZERO, &check_for_mint, Assembler::kNearJump); 928 __ j(NOT_ZERO, &check_for_mint, Assembler::kNearJump);
960 // Both arguments are smi, '===' is good enough. 929 // Both arguments are smi, '===' is good enough.
(...skipping 25 matching lines...) Expand all
986 __ j(NOT_EQUAL, &fall_through); 955 __ j(NOT_EQUAL, &fall_through);
987 // Receiver is Mint, return false if right is Smi. 956 // Receiver is Mint, return false if right is Smi.
988 __ movq(RAX, Address(RSP, + 1 * kWordSize)); // Right argument. 957 __ movq(RAX, Address(RSP, + 1 * kWordSize)); // Right argument.
989 __ testq(RAX, Immediate(kSmiTagMask)); 958 __ testq(RAX, Immediate(kSmiTagMask));
990 __ j(NOT_ZERO, &fall_through); 959 __ j(NOT_ZERO, &fall_through);
991 __ LoadObject(RAX, Bool::False()); // Smi == Mint -> false. 960 __ LoadObject(RAX, Bool::False()); // Smi == Mint -> false.
992 __ ret(); 961 __ ret();
993 // TODO(srdjan): Implement Mint == Mint comparison. 962 // TODO(srdjan): Implement Mint == Mint comparison.
994 963
995 __ Bind(&fall_through); 964 __ Bind(&fall_through);
996 return false;
997 } 965 }
998 966
999 967
1000 bool Intrinsifier::Integer_equal(Assembler* assembler) { 968 void Intrinsifier::Integer_equal(Assembler* assembler) {
1001 return Integer_equalToInteger(assembler); 969 return Integer_equalToInteger(assembler);
1002 } 970 }
1003 971
1004 972
1005 bool Intrinsifier::Integer_sar(Assembler* assembler) { 973 void Intrinsifier::Integer_sar(Assembler* assembler) {
1006 Label fall_through, shift_count_ok; 974 Label fall_through, shift_count_ok;
1007 TestBothArgumentsSmis(assembler, &fall_through); 975 TestBothArgumentsSmis(assembler, &fall_through);
1008 const Immediate& count_limit = Immediate(0x3F); 976 const Immediate& count_limit = Immediate(0x3F);
1009 // Check that the count is not larger than what the hardware can handle. 977 // Check that the count is not larger than what the hardware can handle.
1010 // For shifting right a Smi the result is the same for all numbers 978 // For shifting right a Smi the result is the same for all numbers
1011 // >= count_limit. 979 // >= count_limit.
1012 __ SmiUntag(RAX); 980 __ SmiUntag(RAX);
1013 // Negative counts throw exception. 981 // Negative counts throw exception.
1014 __ cmpq(RAX, Immediate(0)); 982 __ cmpq(RAX, Immediate(0));
1015 __ j(LESS, &fall_through, Assembler::kNearJump); 983 __ j(LESS, &fall_through, Assembler::kNearJump);
1016 __ cmpq(RAX, count_limit); 984 __ cmpq(RAX, count_limit);
1017 __ j(LESS_EQUAL, &shift_count_ok, Assembler::kNearJump); 985 __ j(LESS_EQUAL, &shift_count_ok, Assembler::kNearJump);
1018 __ movq(RAX, count_limit); 986 __ movq(RAX, count_limit);
1019 __ Bind(&shift_count_ok); 987 __ Bind(&shift_count_ok);
1020 __ movq(RCX, RAX); // Shift amount must be in RCX. 988 __ movq(RCX, RAX); // Shift amount must be in RCX.
1021 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Value. 989 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Value.
1022 __ SmiUntag(RAX); // Value. 990 __ SmiUntag(RAX); // Value.
1023 __ sarq(RAX, RCX); 991 __ sarq(RAX, RCX);
1024 __ SmiTag(RAX); 992 __ SmiTag(RAX);
1025 __ ret(); 993 __ ret();
1026 __ Bind(&fall_through); 994 __ Bind(&fall_through);
1027 return false;
1028 } 995 }
1029 996
1030 997
1031 // Argument is Smi (receiver). 998 // Argument is Smi (receiver).
1032 bool Intrinsifier::Smi_bitNegate(Assembler* assembler) { 999 void Intrinsifier::Smi_bitNegate(Assembler* assembler) {
1033 __ movq(RAX, Address(RSP, + 1 * kWordSize)); // Index. 1000 __ movq(RAX, Address(RSP, + 1 * kWordSize)); // Index.
1034 __ notq(RAX); 1001 __ notq(RAX);
1035 __ andq(RAX, Immediate(~kSmiTagMask)); // Remove inverted smi-tag. 1002 __ andq(RAX, Immediate(~kSmiTagMask)); // Remove inverted smi-tag.
1036 __ ret(); 1003 __ ret();
1037 return true;
1038 } 1004 }
1039 1005
1040 1006
1041 // Check if the last argument is a double, jump to label 'is_smi' if smi 1007 // Check if the last argument is a double, jump to label 'is_smi' if smi
1042 // (easy to convert to double), otherwise jump to label 'not_double_smi', 1008 // (easy to convert to double), otherwise jump to label 'not_double_smi',
1043 // Returns the last argument in RAX. 1009 // Returns the last argument in RAX.
1044 static void TestLastArgumentIsDouble(Assembler* assembler, 1010 static void TestLastArgumentIsDouble(Assembler* assembler,
1045 Label* is_smi, 1011 Label* is_smi,
1046 Label* not_double_smi) { 1012 Label* not_double_smi) {
1047 __ movq(RAX, Address(RSP, + 1 * kWordSize)); 1013 __ movq(RAX, Address(RSP, + 1 * kWordSize));
1048 __ testq(RAX, Immediate(kSmiTagMask)); 1014 __ testq(RAX, Immediate(kSmiTagMask));
1049 __ j(ZERO, is_smi, Assembler::kNearJump); // Jump if Smi. 1015 __ j(ZERO, is_smi, Assembler::kNearJump); // Jump if Smi.
1050 __ CompareClassId(RAX, kDoubleCid); 1016 __ CompareClassId(RAX, kDoubleCid);
1051 __ j(NOT_EQUAL, not_double_smi, Assembler::kNearJump); 1017 __ j(NOT_EQUAL, not_double_smi, Assembler::kNearJump);
1052 // Fall through if double. 1018 // Fall through if double.
1053 } 1019 }
1054 1020
1055 1021
1056 // Both arguments on stack, left argument is a double, right argument is of 1022 // Both arguments on stack, left argument is a double, right argument is of
1057 // unknown type. Return true or false object in RAX. Any NaN argument 1023 // unknown type. Return true or false object in RAX. Any NaN argument
1058 // returns false. Any non-double argument causes control flow to fall through 1024 // returns false. Any non-double argument causes control flow to fall through
1059 // to the slow case (compiled method body). 1025 // to the slow case (compiled method body).
1060 static bool CompareDoubles(Assembler* assembler, Condition true_condition) { 1026 static void CompareDoubles(Assembler* assembler, Condition true_condition) {
1061 Label fall_through, is_false, is_true, is_smi, double_op; 1027 Label fall_through, is_false, is_true, is_smi, double_op;
1062 TestLastArgumentIsDouble(assembler, &is_smi, &fall_through); 1028 TestLastArgumentIsDouble(assembler, &is_smi, &fall_through);
1063 // Both arguments are double, right operand is in RAX. 1029 // Both arguments are double, right operand is in RAX.
1064 __ movsd(XMM1, FieldAddress(RAX, Double::value_offset())); 1030 __ movsd(XMM1, FieldAddress(RAX, Double::value_offset()));
1065 __ Bind(&double_op); 1031 __ Bind(&double_op);
1066 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Left argument. 1032 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Left argument.
1067 __ movsd(XMM0, FieldAddress(RAX, Double::value_offset())); 1033 __ movsd(XMM0, FieldAddress(RAX, Double::value_offset()));
1068 __ comisd(XMM0, XMM1); 1034 __ comisd(XMM0, XMM1);
1069 __ j(PARITY_EVEN, &is_false, Assembler::kNearJump); // NaN -> false; 1035 __ j(PARITY_EVEN, &is_false, Assembler::kNearJump); // NaN -> false;
1070 __ j(true_condition, &is_true, Assembler::kNearJump); 1036 __ j(true_condition, &is_true, Assembler::kNearJump);
1071 // Fall through false. 1037 // Fall through false.
1072 __ Bind(&is_false); 1038 __ Bind(&is_false);
1073 __ LoadObject(RAX, Bool::False()); 1039 __ LoadObject(RAX, Bool::False());
1074 __ ret(); 1040 __ ret();
1075 __ Bind(&is_true); 1041 __ Bind(&is_true);
1076 __ LoadObject(RAX, Bool::True()); 1042 __ LoadObject(RAX, Bool::True());
1077 __ ret(); 1043 __ ret();
1078 __ Bind(&is_smi); 1044 __ Bind(&is_smi);
1079 __ SmiUntag(RAX); 1045 __ SmiUntag(RAX);
1080 __ cvtsi2sd(XMM1, RAX); 1046 __ cvtsi2sd(XMM1, RAX);
1081 __ jmp(&double_op); 1047 __ jmp(&double_op);
1082 __ Bind(&fall_through); 1048 __ Bind(&fall_through);
1083 return false;
1084 } 1049 }
1085 1050
1086 1051
1087 bool Intrinsifier::Double_greaterThan(Assembler* assembler) { 1052 void Intrinsifier::Double_greaterThan(Assembler* assembler) {
1088 return CompareDoubles(assembler, ABOVE); 1053 return CompareDoubles(assembler, ABOVE);
1089 } 1054 }
1090 1055
1091 1056
1092 bool Intrinsifier::Double_greaterEqualThan(Assembler* assembler) { 1057 void Intrinsifier::Double_greaterEqualThan(Assembler* assembler) {
1093 return CompareDoubles(assembler, ABOVE_EQUAL); 1058 return CompareDoubles(assembler, ABOVE_EQUAL);
1094 } 1059 }
1095 1060
1096 1061
1097 bool Intrinsifier::Double_lessThan(Assembler* assembler) { 1062 void Intrinsifier::Double_lessThan(Assembler* assembler) {
1098 return CompareDoubles(assembler, BELOW); 1063 return CompareDoubles(assembler, BELOW);
1099 } 1064 }
1100 1065
1101 1066
1102 bool Intrinsifier::Double_equal(Assembler* assembler) { 1067 void Intrinsifier::Double_equal(Assembler* assembler) {
1103 return CompareDoubles(assembler, EQUAL); 1068 return CompareDoubles(assembler, EQUAL);
1104 } 1069 }
1105 1070
1106 1071
1107 bool Intrinsifier::Double_lessEqualThan(Assembler* assembler) { 1072 void Intrinsifier::Double_lessEqualThan(Assembler* assembler) {
1108 return CompareDoubles(assembler, BELOW_EQUAL); 1073 return CompareDoubles(assembler, BELOW_EQUAL);
1109 } 1074 }
1110 1075
1111 1076
1112 // Expects left argument to be double (receiver). Right argument is unknown. 1077 // Expects left argument to be double (receiver). Right argument is unknown.
1113 // Both arguments are on stack. 1078 // Both arguments are on stack.
1114 static bool DoubleArithmeticOperations(Assembler* assembler, Token::Kind kind) { 1079 static void DoubleArithmeticOperations(Assembler* assembler, Token::Kind kind) {
1115 Label fall_through; 1080 Label fall_through;
1116 TestLastArgumentIsDouble(assembler, &fall_through, &fall_through); 1081 TestLastArgumentIsDouble(assembler, &fall_through, &fall_through);
1117 // Both arguments are double, right operand is in RAX. 1082 // Both arguments are double, right operand is in RAX.
1118 __ movsd(XMM1, FieldAddress(RAX, Double::value_offset())); 1083 __ movsd(XMM1, FieldAddress(RAX, Double::value_offset()));
1119 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Left argument. 1084 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Left argument.
1120 __ movsd(XMM0, FieldAddress(RAX, Double::value_offset())); 1085 __ movsd(XMM0, FieldAddress(RAX, Double::value_offset()));
1121 switch (kind) { 1086 switch (kind) {
1122 case Token::kADD: __ addsd(XMM0, XMM1); break; 1087 case Token::kADD: __ addsd(XMM0, XMM1); break;
1123 case Token::kSUB: __ subsd(XMM0, XMM1); break; 1088 case Token::kSUB: __ subsd(XMM0, XMM1); break;
1124 case Token::kMUL: __ mulsd(XMM0, XMM1); break; 1089 case Token::kMUL: __ mulsd(XMM0, XMM1); break;
1125 case Token::kDIV: __ divsd(XMM0, XMM1); break; 1090 case Token::kDIV: __ divsd(XMM0, XMM1); break;
1126 default: UNREACHABLE(); 1091 default: UNREACHABLE();
1127 } 1092 }
1128 const Class& double_class = Class::Handle( 1093 const Class& double_class = Class::Handle(
1129 Isolate::Current()->object_store()->double_class()); 1094 Isolate::Current()->object_store()->double_class());
1130 __ TryAllocate(double_class, 1095 __ TryAllocate(double_class,
1131 &fall_through, 1096 &fall_through,
1132 Assembler::kNearJump, 1097 Assembler::kNearJump,
1133 RAX); // Result register. 1098 RAX); // Result register.
1134 __ movsd(FieldAddress(RAX, Double::value_offset()), XMM0); 1099 __ movsd(FieldAddress(RAX, Double::value_offset()), XMM0);
1135 __ ret(); 1100 __ ret();
1136 __ Bind(&fall_through); 1101 __ Bind(&fall_through);
1137 return false;
1138 } 1102 }
1139 1103
1140 1104
1141 bool Intrinsifier::Double_add(Assembler* assembler) { 1105 void Intrinsifier::Double_add(Assembler* assembler) {
1142 return DoubleArithmeticOperations(assembler, Token::kADD); 1106 return DoubleArithmeticOperations(assembler, Token::kADD);
1143 } 1107 }
1144 1108
1145 1109
1146 bool Intrinsifier::Double_mul(Assembler* assembler) { 1110 void Intrinsifier::Double_mul(Assembler* assembler) {
1147 return DoubleArithmeticOperations(assembler, Token::kMUL); 1111 return DoubleArithmeticOperations(assembler, Token::kMUL);
1148 } 1112 }
1149 1113
1150 1114
1151 bool Intrinsifier::Double_sub(Assembler* assembler) { 1115 void Intrinsifier::Double_sub(Assembler* assembler) {
1152 return DoubleArithmeticOperations(assembler, Token::kSUB); 1116 return DoubleArithmeticOperations(assembler, Token::kSUB);
1153 } 1117 }
1154 1118
1155 1119
1156 bool Intrinsifier::Double_div(Assembler* assembler) { 1120 void Intrinsifier::Double_div(Assembler* assembler) {
1157 return DoubleArithmeticOperations(assembler, Token::kDIV); 1121 return DoubleArithmeticOperations(assembler, Token::kDIV);
1158 } 1122 }
1159 1123
1160 1124
1161 bool Intrinsifier::Double_mulFromInteger(Assembler* assembler) { 1125 void Intrinsifier::Double_mulFromInteger(Assembler* assembler) {
1162 Label fall_through; 1126 Label fall_through;
1163 // Only Smi-s allowed. 1127 // Only Smi-s allowed.
1164 __ movq(RAX, Address(RSP, + 1 * kWordSize)); 1128 __ movq(RAX, Address(RSP, + 1 * kWordSize));
1165 __ testq(RAX, Immediate(kSmiTagMask)); 1129 __ testq(RAX, Immediate(kSmiTagMask));
1166 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); 1130 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump);
1167 // Is Smi. 1131 // Is Smi.
1168 __ SmiUntag(RAX); 1132 __ SmiUntag(RAX);
1169 __ cvtsi2sd(XMM1, RAX); 1133 __ cvtsi2sd(XMM1, RAX);
1170 __ movq(RAX, Address(RSP, + 2 * kWordSize)); 1134 __ movq(RAX, Address(RSP, + 2 * kWordSize));
1171 __ movsd(XMM0, FieldAddress(RAX, Double::value_offset())); 1135 __ movsd(XMM0, FieldAddress(RAX, Double::value_offset()));
1172 __ mulsd(XMM0, XMM1); 1136 __ mulsd(XMM0, XMM1);
1173 const Class& double_class = Class::Handle( 1137 const Class& double_class = Class::Handle(
1174 Isolate::Current()->object_store()->double_class()); 1138 Isolate::Current()->object_store()->double_class());
1175 __ TryAllocate(double_class, 1139 __ TryAllocate(double_class,
1176 &fall_through, 1140 &fall_through,
1177 Assembler::kNearJump, 1141 Assembler::kNearJump,
1178 RAX); // Result register. 1142 RAX); // Result register.
1179 __ movsd(FieldAddress(RAX, Double::value_offset()), XMM0); 1143 __ movsd(FieldAddress(RAX, Double::value_offset()), XMM0);
1180 __ ret(); 1144 __ ret();
1181 __ Bind(&fall_through); 1145 __ Bind(&fall_through);
1182 return false;
1183 } 1146 }
1184 1147
1185 1148
1186 // Left is double right is integer (Bigint, Mint or Smi) 1149 // Left is double right is integer (Bigint, Mint or Smi)
1187 bool Intrinsifier::Double_fromInteger(Assembler* assembler) { 1150 void Intrinsifier::Double_fromInteger(Assembler* assembler) {
1188 Label fall_through; 1151 Label fall_through;
1189 __ movq(RAX, Address(RSP, +1 * kWordSize)); 1152 __ movq(RAX, Address(RSP, +1 * kWordSize));
1190 __ testq(RAX, Immediate(kSmiTagMask)); 1153 __ testq(RAX, Immediate(kSmiTagMask));
1191 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); 1154 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump);
1192 // Is Smi. 1155 // Is Smi.
1193 __ SmiUntag(RAX); 1156 __ SmiUntag(RAX);
1194 __ cvtsi2sd(XMM0, RAX); 1157 __ cvtsi2sd(XMM0, RAX);
1195 const Class& double_class = Class::Handle( 1158 const Class& double_class = Class::Handle(
1196 Isolate::Current()->object_store()->double_class()); 1159 Isolate::Current()->object_store()->double_class());
1197 __ TryAllocate(double_class, 1160 __ TryAllocate(double_class,
1198 &fall_through, 1161 &fall_through,
1199 Assembler::kNearJump, 1162 Assembler::kNearJump,
1200 RAX); // Result register. 1163 RAX); // Result register.
1201 __ movsd(FieldAddress(RAX, Double::value_offset()), XMM0); 1164 __ movsd(FieldAddress(RAX, Double::value_offset()), XMM0);
1202 __ ret(); 1165 __ ret();
1203 __ Bind(&fall_through); 1166 __ Bind(&fall_through);
1204 return false;
1205 } 1167 }
1206 1168
1207 1169
1208 bool Intrinsifier::Double_getIsNaN(Assembler* assembler) { 1170 void Intrinsifier::Double_getIsNaN(Assembler* assembler) {
1209 Label is_true; 1171 Label is_true;
1210 __ movq(RAX, Address(RSP, +1 * kWordSize)); 1172 __ movq(RAX, Address(RSP, +1 * kWordSize));
1211 __ movsd(XMM0, FieldAddress(RAX, Double::value_offset())); 1173 __ movsd(XMM0, FieldAddress(RAX, Double::value_offset()));
1212 __ comisd(XMM0, XMM0); 1174 __ comisd(XMM0, XMM0);
1213 __ j(PARITY_EVEN, &is_true, Assembler::kNearJump); // NaN -> true; 1175 __ j(PARITY_EVEN, &is_true, Assembler::kNearJump); // NaN -> true;
1214 __ LoadObject(RAX, Bool::False()); 1176 __ LoadObject(RAX, Bool::False());
1215 __ ret(); 1177 __ ret();
1216 __ Bind(&is_true); 1178 __ Bind(&is_true);
1217 __ LoadObject(RAX, Bool::True()); 1179 __ LoadObject(RAX, Bool::True());
1218 __ ret(); 1180 __ ret();
1219 return true; // Method is complete, no slow case.
1220 } 1181 }
1221 1182
1222 1183
1223 bool Intrinsifier::Double_getIsNegative(Assembler* assembler) { 1184 void Intrinsifier::Double_getIsNegative(Assembler* assembler) {
1224 Label is_false, is_true, is_zero; 1185 Label is_false, is_true, is_zero;
1225 __ movq(RAX, Address(RSP, +1 * kWordSize)); 1186 __ movq(RAX, Address(RSP, +1 * kWordSize));
1226 __ movsd(XMM0, FieldAddress(RAX, Double::value_offset())); 1187 __ movsd(XMM0, FieldAddress(RAX, Double::value_offset()));
1227 __ xorpd(XMM1, XMM1); // 0.0 -> XMM1. 1188 __ xorpd(XMM1, XMM1); // 0.0 -> XMM1.
1228 __ comisd(XMM0, XMM1); 1189 __ comisd(XMM0, XMM1);
1229 __ j(PARITY_EVEN, &is_false, Assembler::kNearJump); // NaN -> false. 1190 __ j(PARITY_EVEN, &is_false, Assembler::kNearJump); // NaN -> false.
1230 __ j(EQUAL, &is_zero, Assembler::kNearJump); // Check for negative zero. 1191 __ j(EQUAL, &is_zero, Assembler::kNearJump); // Check for negative zero.
1231 __ j(ABOVE_EQUAL, &is_false, Assembler::kNearJump); // >= 0 -> false. 1192 __ j(ABOVE_EQUAL, &is_false, Assembler::kNearJump); // >= 0 -> false.
1232 __ Bind(&is_true); 1193 __ Bind(&is_true);
1233 __ LoadObject(RAX, Bool::True()); 1194 __ LoadObject(RAX, Bool::True());
1234 __ ret(); 1195 __ ret();
1235 __ Bind(&is_false); 1196 __ Bind(&is_false);
1236 __ LoadObject(RAX, Bool::False()); 1197 __ LoadObject(RAX, Bool::False());
1237 __ ret(); 1198 __ ret();
1238 __ Bind(&is_zero); 1199 __ Bind(&is_zero);
1239 // Check for negative zero (get the sign bit). 1200 // Check for negative zero (get the sign bit).
1240 __ movmskpd(RAX, XMM0); 1201 __ movmskpd(RAX, XMM0);
1241 __ testq(RAX, Immediate(1)); 1202 __ testq(RAX, Immediate(1));
1242 __ j(NOT_ZERO, &is_true, Assembler::kNearJump); 1203 __ j(NOT_ZERO, &is_true, Assembler::kNearJump);
1243 __ jmp(&is_false, Assembler::kNearJump); 1204 __ jmp(&is_false, Assembler::kNearJump);
1244 return true; // Method is complete, no slow case.
1245 } 1205 }
1246 1206
1247 1207
1248 enum TrigonometricFunctions { 1208 enum TrigonometricFunctions {
1249 kSine, 1209 kSine,
1250 kCosine, 1210 kCosine,
1251 }; 1211 };
1252 1212
1253 1213
1254 static void EmitTrigonometric(Assembler* assembler, 1214 static void EmitTrigonometric(Assembler* assembler,
(...skipping 27 matching lines...) Expand all
1282 __ jmp(&double_op); 1242 __ jmp(&double_op);
1283 1243
1284 __ Bind(&alloc_failed); 1244 __ Bind(&alloc_failed);
1285 __ ffree(0); 1245 __ ffree(0);
1286 __ fincstp(); 1246 __ fincstp();
1287 1247
1288 __ Bind(&fall_through); 1248 __ Bind(&fall_through);
1289 } 1249 }
1290 1250
1291 1251
1292 bool Intrinsifier::Double_toInt(Assembler* assembler) { 1252 void Intrinsifier::Double_toInt(Assembler* assembler) {
1293 __ movq(RAX, Address(RSP, +1 * kWordSize)); 1253 __ movq(RAX, Address(RSP, +1 * kWordSize));
1294 __ movsd(XMM0, FieldAddress(RAX, Double::value_offset())); 1254 __ movsd(XMM0, FieldAddress(RAX, Double::value_offset()));
1295 __ cvttsd2siq(RAX, XMM0); 1255 __ cvttsd2siq(RAX, XMM0);
1296 // Overflow is signalled with minint. 1256 // Overflow is signalled with minint.
1297 Label fall_through; 1257 Label fall_through;
1298 // Check for overflow and that it fits into Smi. 1258 // Check for overflow and that it fits into Smi.
1299 __ movq(RCX, RAX); 1259 __ movq(RCX, RAX);
1300 __ shlq(RCX, Immediate(1)); 1260 __ shlq(RCX, Immediate(1));
1301 __ j(OVERFLOW, &fall_through, Assembler::kNearJump); 1261 __ j(OVERFLOW, &fall_through, Assembler::kNearJump);
1302 __ SmiTag(RAX); 1262 __ SmiTag(RAX);
1303 __ ret(); 1263 __ ret();
1304 __ Bind(&fall_through); 1264 __ Bind(&fall_through);
1305 return false;
1306 } 1265 }
1307 1266
1308 1267
1309 bool Intrinsifier::Math_sqrt(Assembler* assembler) { 1268 void Intrinsifier::Math_sqrt(Assembler* assembler) {
1310 Label fall_through, is_smi, double_op; 1269 Label fall_through, is_smi, double_op;
1311 TestLastArgumentIsDouble(assembler, &is_smi, &fall_through); 1270 TestLastArgumentIsDouble(assembler, &is_smi, &fall_through);
1312 // Argument is double and is in RAX. 1271 // Argument is double and is in RAX.
1313 __ movsd(XMM1, FieldAddress(RAX, Double::value_offset())); 1272 __ movsd(XMM1, FieldAddress(RAX, Double::value_offset()));
1314 __ Bind(&double_op); 1273 __ Bind(&double_op);
1315 __ sqrtsd(XMM0, XMM1); 1274 __ sqrtsd(XMM0, XMM1);
1316 const Class& double_class = Class::Handle( 1275 const Class& double_class = Class::Handle(
1317 Isolate::Current()->object_store()->double_class()); 1276 Isolate::Current()->object_store()->double_class());
1318 __ TryAllocate(double_class, 1277 __ TryAllocate(double_class,
1319 &fall_through, 1278 &fall_through,
1320 Assembler::kNearJump, 1279 Assembler::kNearJump,
1321 RAX); // Result register. 1280 RAX); // Result register.
1322 __ movsd(FieldAddress(RAX, Double::value_offset()), XMM0); 1281 __ movsd(FieldAddress(RAX, Double::value_offset()), XMM0);
1323 __ ret(); 1282 __ ret();
1324 __ Bind(&is_smi); 1283 __ Bind(&is_smi);
1325 __ SmiUntag(RAX); 1284 __ SmiUntag(RAX);
1326 __ cvtsi2sd(XMM1, RAX); 1285 __ cvtsi2sd(XMM1, RAX);
1327 __ jmp(&double_op); 1286 __ jmp(&double_op);
1328 __ Bind(&fall_through); 1287 __ Bind(&fall_through);
1329 return false;
1330 } 1288 }
1331 1289
1332 1290
1333 bool Intrinsifier::Math_sin(Assembler* assembler) { 1291 void Intrinsifier::Math_sin(Assembler* assembler) {
1334 EmitTrigonometric(assembler, kSine); 1292 EmitTrigonometric(assembler, kSine);
1335 return false; // Compile method for slow case.
1336 } 1293 }
1337 1294
1338 1295
1339 bool Intrinsifier::Math_cos(Assembler* assembler) { 1296 void Intrinsifier::Math_cos(Assembler* assembler) {
1340 EmitTrigonometric(assembler, kCosine); 1297 EmitTrigonometric(assembler, kCosine);
1341 return false; // Compile method for slow case.
1342 } 1298 }
1343 1299
1344 1300
1345 // var state = ((_A * (_state[kSTATE_LO])) + _state[kSTATE_HI]) & _MASK_64; 1301 // var state = ((_A * (_state[kSTATE_LO])) + _state[kSTATE_HI]) & _MASK_64;
1346 // _state[kSTATE_LO] = state & _MASK_32; 1302 // _state[kSTATE_LO] = state & _MASK_32;
1347 // _state[kSTATE_HI] = state >> 32; 1303 // _state[kSTATE_HI] = state >> 32;
1348 bool Intrinsifier::Random_nextState(Assembler* assembler) { 1304 void Intrinsifier::Random_nextState(Assembler* assembler) {
1349 const Library& math_lib = Library::Handle(Library::MathLibrary()); 1305 const Library& math_lib = Library::Handle(Library::MathLibrary());
1350 ASSERT(!math_lib.IsNull()); 1306 ASSERT(!math_lib.IsNull());
1351 const Class& random_class = Class::Handle( 1307 const Class& random_class = Class::Handle(
1352 math_lib.LookupClassAllowPrivate(Symbols::_Random(), NULL)); 1308 math_lib.LookupClassAllowPrivate(Symbols::_Random(), NULL));
1353 ASSERT(!random_class.IsNull()); 1309 ASSERT(!random_class.IsNull());
1354 const Field& state_field = Field::ZoneHandle( 1310 const Field& state_field = Field::ZoneHandle(
1355 random_class.LookupInstanceField(Symbols::_state())); 1311 random_class.LookupInstanceField(Symbols::_state()));
1356 ASSERT(!state_field.IsNull()); 1312 ASSERT(!state_field.IsNull());
1357 const Field& random_A_field = Field::ZoneHandle( 1313 const Field& random_A_field = Field::ZoneHandle(
1358 random_class.LookupStaticField(Symbols::_A())); 1314 random_class.LookupStaticField(Symbols::_A()));
(...skipping 17 matching lines...) Expand all
1376 1332
1377 __ movq(RAX, Immediate(a_int_value)); 1333 __ movq(RAX, Immediate(a_int_value));
1378 __ movl(RCX, addr_0); 1334 __ movl(RCX, addr_0);
1379 __ imulq(RCX, RAX); 1335 __ imulq(RCX, RAX);
1380 __ movl(RDX, addr_1); 1336 __ movl(RDX, addr_1);
1381 __ addq(RDX, RCX); 1337 __ addq(RDX, RCX);
1382 __ movl(addr_0, RDX); 1338 __ movl(addr_0, RDX);
1383 __ shrq(RDX, Immediate(32)); 1339 __ shrq(RDX, Immediate(32));
1384 __ movl(addr_1, RDX); 1340 __ movl(addr_1, RDX);
1385 __ ret(); 1341 __ ret();
1386 return true;
1387 } 1342 }
1388 1343
1389 1344
1390 1345
1391 // Identity comparison. 1346 // Identity comparison.
1392 bool Intrinsifier::Object_equal(Assembler* assembler) { 1347 void Intrinsifier::Object_equal(Assembler* assembler) {
1393 Label is_true; 1348 Label is_true;
1394 __ movq(RAX, Address(RSP, + 1 * kWordSize)); 1349 __ movq(RAX, Address(RSP, + 1 * kWordSize));
1395 __ cmpq(RAX, Address(RSP, + 2 * kWordSize)); 1350 __ cmpq(RAX, Address(RSP, + 2 * kWordSize));
1396 __ j(EQUAL, &is_true, Assembler::kNearJump); 1351 __ j(EQUAL, &is_true, Assembler::kNearJump);
1397 __ LoadObject(RAX, Bool::False()); 1352 __ LoadObject(RAX, Bool::False());
1398 __ ret(); 1353 __ ret();
1399 __ Bind(&is_true); 1354 __ Bind(&is_true);
1400 __ LoadObject(RAX, Bool::True()); 1355 __ LoadObject(RAX, Bool::True());
1401 __ ret(); 1356 __ ret();
1402 return true;
1403 } 1357 }
1404 1358
1405 1359
1406 bool Intrinsifier::String_getHashCode(Assembler* assembler) { 1360 void Intrinsifier::String_getHashCode(Assembler* assembler) {
1407 Label fall_through; 1361 Label fall_through;
1408 __ movq(RAX, Address(RSP, + 1 * kWordSize)); // String object. 1362 __ movq(RAX, Address(RSP, + 1 * kWordSize)); // String object.
1409 __ movq(RAX, FieldAddress(RAX, String::hash_offset())); 1363 __ movq(RAX, FieldAddress(RAX, String::hash_offset()));
1410 __ cmpq(RAX, Immediate(0)); 1364 __ cmpq(RAX, Immediate(0));
1411 __ j(EQUAL, &fall_through, Assembler::kNearJump); 1365 __ j(EQUAL, &fall_through, Assembler::kNearJump);
1412 __ ret(); 1366 __ ret();
1413 __ Bind(&fall_through); 1367 __ Bind(&fall_through);
1414 // Hash not yet computed. 1368 // Hash not yet computed.
1415 return false;
1416 } 1369 }
1417 1370
1418 1371
1419 bool Intrinsifier::String_getLength(Assembler* assembler) { 1372 void Intrinsifier::String_getLength(Assembler* assembler) {
1420 __ movq(RAX, Address(RSP, + 1 * kWordSize)); // String object. 1373 __ movq(RAX, Address(RSP, + 1 * kWordSize)); // String object.
1421 __ movq(RAX, FieldAddress(RAX, String::length_offset())); 1374 __ movq(RAX, FieldAddress(RAX, String::length_offset()));
1422 __ ret(); 1375 __ ret();
1423 return true;
1424 } 1376 }
1425 1377
1426 1378
1427 bool Intrinsifier::String_codeUnitAt(Assembler* assembler) { 1379 void Intrinsifier::String_codeUnitAt(Assembler* assembler) {
1428 Label fall_through, try_two_byte_string; 1380 Label fall_through, try_two_byte_string;
1429 __ movq(RCX, Address(RSP, + 1 * kWordSize)); // Index. 1381 __ movq(RCX, Address(RSP, + 1 * kWordSize)); // Index.
1430 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // String. 1382 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // String.
1431 __ testq(RCX, Immediate(kSmiTagMask)); 1383 __ testq(RCX, Immediate(kSmiTagMask));
1432 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi index. 1384 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi index.
1433 // Range check. 1385 // Range check.
1434 __ cmpq(RCX, FieldAddress(RAX, String::length_offset())); 1386 __ cmpq(RCX, FieldAddress(RAX, String::length_offset()));
1435 // Runtime throws exception. 1387 // Runtime throws exception.
1436 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump); 1388 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump);
1437 __ CompareClassId(RAX, kOneByteStringCid); 1389 __ CompareClassId(RAX, kOneByteStringCid);
1438 __ j(NOT_EQUAL, &try_two_byte_string, Assembler::kNearJump); 1390 __ j(NOT_EQUAL, &try_two_byte_string, Assembler::kNearJump);
1439 __ SmiUntag(RCX); 1391 __ SmiUntag(RCX);
1440 __ movzxb(RAX, FieldAddress(RAX, RCX, TIMES_1, OneByteString::data_offset())); 1392 __ movzxb(RAX, FieldAddress(RAX, RCX, TIMES_1, OneByteString::data_offset()));
1441 __ SmiTag(RAX); 1393 __ SmiTag(RAX);
1442 __ ret(); 1394 __ ret();
1443 1395
1444 __ Bind(&try_two_byte_string); 1396 __ Bind(&try_two_byte_string);
1445 __ CompareClassId(RAX, kTwoByteStringCid); 1397 __ CompareClassId(RAX, kTwoByteStringCid);
1446 __ j(NOT_EQUAL, &fall_through, Assembler::kNearJump); 1398 __ j(NOT_EQUAL, &fall_through, Assembler::kNearJump);
1447 ASSERT(kSmiTagShift == 1); 1399 ASSERT(kSmiTagShift == 1);
1448 __ movzxw(RAX, FieldAddress(RAX, RCX, TIMES_1, OneByteString::data_offset())); 1400 __ movzxw(RAX, FieldAddress(RAX, RCX, TIMES_1, OneByteString::data_offset()));
1449 __ SmiTag(RAX); 1401 __ SmiTag(RAX);
1450 __ ret(); 1402 __ ret();
1451 1403
1452 __ Bind(&fall_through); 1404 __ Bind(&fall_through);
1453 return false;
1454 } 1405 }
1455 1406
1456 1407
1457 bool Intrinsifier::String_getIsEmpty(Assembler* assembler) { 1408 void Intrinsifier::String_getIsEmpty(Assembler* assembler) {
1458 Label is_true; 1409 Label is_true;
1459 // Get length. 1410 // Get length.
1460 __ movq(RAX, Address(RSP, + 1 * kWordSize)); // String object. 1411 __ movq(RAX, Address(RSP, + 1 * kWordSize)); // String object.
1461 __ movq(RAX, FieldAddress(RAX, String::length_offset())); 1412 __ movq(RAX, FieldAddress(RAX, String::length_offset()));
1462 __ cmpq(RAX, Immediate(Smi::RawValue(0))); 1413 __ cmpq(RAX, Immediate(Smi::RawValue(0)));
1463 __ j(EQUAL, &is_true, Assembler::kNearJump); 1414 __ j(EQUAL, &is_true, Assembler::kNearJump);
1464 __ LoadObject(RAX, Bool::False()); 1415 __ LoadObject(RAX, Bool::False());
1465 __ ret(); 1416 __ ret();
1466 __ Bind(&is_true); 1417 __ Bind(&is_true);
1467 __ LoadObject(RAX, Bool::True()); 1418 __ LoadObject(RAX, Bool::True());
1468 __ ret(); 1419 __ ret();
1469 return false;
1470 } 1420 }
1471 1421
1472 1422
1473 bool Intrinsifier::OneByteString_getHashCode(Assembler* assembler) { 1423 void Intrinsifier::OneByteString_getHashCode(Assembler* assembler) {
1474 Label compute_hash; 1424 Label compute_hash;
1475 __ movq(RBX, Address(RSP, + 1 * kWordSize)); // OneByteString object. 1425 __ movq(RBX, Address(RSP, + 1 * kWordSize)); // OneByteString object.
1476 __ movq(RAX, FieldAddress(RBX, String::hash_offset())); 1426 __ movq(RAX, FieldAddress(RBX, String::hash_offset()));
1477 __ cmpq(RAX, Immediate(0)); 1427 __ cmpq(RAX, Immediate(0));
1478 __ j(EQUAL, &compute_hash, Assembler::kNearJump); 1428 __ j(EQUAL, &compute_hash, Assembler::kNearJump);
1479 __ ret(); 1429 __ ret();
1480 1430
1481 __ Bind(&compute_hash); 1431 __ Bind(&compute_hash);
1482 // Hash not yet computed, use algorithm of class StringHasher. 1432 // Hash not yet computed, use algorithm of class StringHasher.
1483 __ movq(RCX, FieldAddress(RBX, String::length_offset())); 1433 __ movq(RCX, FieldAddress(RBX, String::length_offset()));
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
1529 Immediate(((static_cast<intptr_t>(1) << String::kHashBits) - 1))); 1479 Immediate(((static_cast<intptr_t>(1) << String::kHashBits) - 1)));
1530 1480
1531 // return hash_ == 0 ? 1 : hash_; 1481 // return hash_ == 0 ? 1 : hash_;
1532 __ cmpq(RAX, Immediate(0)); 1482 __ cmpq(RAX, Immediate(0));
1533 __ j(NOT_EQUAL, &set_hash_code, Assembler::kNearJump); 1483 __ j(NOT_EQUAL, &set_hash_code, Assembler::kNearJump);
1534 __ incq(RAX); 1484 __ incq(RAX);
1535 __ Bind(&set_hash_code); 1485 __ Bind(&set_hash_code);
1536 __ SmiTag(RAX); 1486 __ SmiTag(RAX);
1537 __ movq(FieldAddress(RBX, String::hash_offset()), RAX); 1487 __ movq(FieldAddress(RBX, String::hash_offset()), RAX);
1538 __ ret(); 1488 __ ret();
1539 return true;
1540 } 1489 }
1541 1490
1542 1491
1543 // Allocates one-byte string of length 'end - start'. The content is not 1492 // Allocates one-byte string of length 'end - start'. The content is not
1544 // initialized. 'length-reg' contains tagged length. 1493 // initialized. 'length-reg' contains tagged length.
1545 // Returns new string as tagged pointer in EAX. 1494 // Returns new string as tagged pointer in EAX.
1546 static void TryAllocateOnebyteString(Assembler* assembler, 1495 static void TryAllocateOnebyteString(Assembler* assembler,
1547 Label* ok, 1496 Label* ok,
1548 Label* failure, 1497 Label* failure,
1549 Register length_reg) { 1498 Register length_reg) {
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
1615 __ Bind(&pop_and_fail); 1564 __ Bind(&pop_and_fail);
1616 __ popq(RDI); 1565 __ popq(RDI);
1617 __ jmp(failure); 1566 __ jmp(failure);
1618 } 1567 }
1619 1568
1620 1569
1621 // Arg0: Onebyte String 1570 // Arg0: Onebyte String
1622 // Arg1: Start index as Smi. 1571 // Arg1: Start index as Smi.
1623 // Arg2: End index as Smi. 1572 // Arg2: End index as Smi.
1624 // The indexes must be valid. 1573 // The indexes must be valid.
1625 bool Intrinsifier::OneByteString_substringUnchecked(Assembler* assembler) { 1574 void Intrinsifier::OneByteString_substringUnchecked(Assembler* assembler) {
1626 const intptr_t kStringOffset = 3 * kWordSize; 1575 const intptr_t kStringOffset = 3 * kWordSize;
1627 const intptr_t kStartIndexOffset = 2 * kWordSize; 1576 const intptr_t kStartIndexOffset = 2 * kWordSize;
1628 const intptr_t kEndIndexOffset = 1 * kWordSize; 1577 const intptr_t kEndIndexOffset = 1 * kWordSize;
1629 Label fall_through, ok; 1578 Label fall_through, ok;
1630 __ movq(RDI, Address(RSP, + kEndIndexOffset)); 1579 __ movq(RDI, Address(RSP, + kEndIndexOffset));
1631 __ subq(RDI, Address(RSP, + kStartIndexOffset)); 1580 __ subq(RDI, Address(RSP, + kStartIndexOffset));
1632 TryAllocateOnebyteString(assembler, &ok, &fall_through, RDI); 1581 TryAllocateOnebyteString(assembler, &ok, &fall_through, RDI);
1633 __ Bind(&ok); 1582 __ Bind(&ok);
1634 // RAX: new string as tagged pointer. 1583 // RAX: new string as tagged pointer.
1635 // Copy string. 1584 // Copy string.
(...skipping 16 matching lines...) Expand all
1652 __ jmp(&check, Assembler::kNearJump); 1601 __ jmp(&check, Assembler::kNearJump);
1653 __ Bind(&loop); 1602 __ Bind(&loop);
1654 __ movzxb(RBX, Address(RSI, RDX, TIMES_1, 0)); 1603 __ movzxb(RBX, Address(RSI, RDX, TIMES_1, 0));
1655 __ movb(FieldAddress(RAX, RDX, TIMES_1, OneByteString::data_offset()), RBX); 1604 __ movb(FieldAddress(RAX, RDX, TIMES_1, OneByteString::data_offset()), RBX);
1656 __ incq(RDX); 1605 __ incq(RDX);
1657 __ Bind(&check); 1606 __ Bind(&check);
1658 __ cmpq(RDX, RCX); 1607 __ cmpq(RDX, RCX);
1659 __ j(LESS, &loop, Assembler::kNearJump); 1608 __ j(LESS, &loop, Assembler::kNearJump);
1660 __ ret(); 1609 __ ret();
1661 __ Bind(&fall_through); 1610 __ Bind(&fall_through);
1662 return false;
1663 } 1611 }
1664 1612
1665 1613
1666 bool Intrinsifier::OneByteString_setAt(Assembler* assembler) { 1614 void Intrinsifier::OneByteString_setAt(Assembler* assembler) {
1667 __ movq(RCX, Address(RSP, + 1 * kWordSize)); // Value. 1615 __ movq(RCX, Address(RSP, + 1 * kWordSize)); // Value.
1668 __ movq(RBX, Address(RSP, + 2 * kWordSize)); // Index. 1616 __ movq(RBX, Address(RSP, + 2 * kWordSize)); // Index.
1669 __ movq(RAX, Address(RSP, + 3 * kWordSize)); // OneByteString. 1617 __ movq(RAX, Address(RSP, + 3 * kWordSize)); // OneByteString.
1670 __ SmiUntag(RBX); 1618 __ SmiUntag(RBX);
1671 __ SmiUntag(RCX); 1619 __ SmiUntag(RCX);
1672 __ movb(FieldAddress(RAX, RBX, TIMES_1, OneByteString::data_offset()), RCX); 1620 __ movb(FieldAddress(RAX, RBX, TIMES_1, OneByteString::data_offset()), RCX);
1673 __ ret(); 1621 __ ret();
1674 return true;
1675 } 1622 }
1676 1623
1677 1624
1678 bool Intrinsifier::OneByteString_allocate(Assembler* assembler) { 1625 void Intrinsifier::OneByteString_allocate(Assembler* assembler) {
1679 __ movq(RDI, Address(RSP, + 1 * kWordSize)); // Length.v= 1626 __ movq(RDI, Address(RSP, + 1 * kWordSize)); // Length.v=
1680 Label fall_through, ok; 1627 Label fall_through, ok;
1681 TryAllocateOnebyteString(assembler, &ok, &fall_through, RDI); 1628 TryAllocateOnebyteString(assembler, &ok, &fall_through, RDI);
1682 // EDI: Start address to copy from (untagged). 1629 // EDI: Start address to copy from (untagged).
1683 1630
1684 __ Bind(&ok); 1631 __ Bind(&ok);
1685 __ ret(); 1632 __ ret();
1686 1633
1687 __ Bind(&fall_through); 1634 __ Bind(&fall_through);
1688 return false;
1689 } 1635 }
1690 1636
1691 1637
1692 #undef __ 1638 #undef __
1693 1639
1694 } // namespace dart 1640 } // namespace dart
1695 1641
1696 #endif // defined TARGET_ARCH_X64 1642 #endif // defined TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « runtime/vm/intrinsifier_mips.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698