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

Side by Side Diff: runtime/vm/intrinsifier_ia32.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_arm.cc ('k') | runtime/vm/intrinsifier_mips.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 (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 // The intrinsic code below is executed before a method has built its frame. 5 // The intrinsic code below is executed before a method has built its frame.
6 // The return address is on the stack and the arguments below it. 6 // The return address is on the stack and the arguments below it.
7 // Registers EDX (arguments descriptor) and ECX (function) must be preserved. 7 // Registers EDX (arguments descriptor) and ECX (function) must be preserved.
8 // Each intrinsification method returns true if the corresponding 8 // Each intrinsification method returns true if the corresponding
9 // Dart method was intrinsified. 9 // Dart method was intrinsified.
10 10
(...skipping 10 matching lines...) Expand all
21 #include "vm/stub_code.h" 21 #include "vm/stub_code.h"
22 #include "vm/symbols.h" 22 #include "vm/symbols.h"
23 23
24 namespace dart { 24 namespace dart {
25 25
26 DECLARE_FLAG(bool, enable_type_checks); 26 DECLARE_FLAG(bool, enable_type_checks);
27 27
28 28
29 #define __ assembler-> 29 #define __ assembler->
30 30
31 bool Intrinsifier::ObjectArray_Allocate(Assembler* assembler) { 31 void Intrinsifier::ObjectArray_Allocate(Assembler* assembler) {
32 // This snippet of inlined code uses the following registers: 32 // This snippet of inlined code uses the following registers:
33 // EAX, EBX, EDI 33 // EAX, EBX, EDI
34 // and the newly allocated object is returned in EAX. 34 // and the newly allocated object is returned in EAX.
35 const intptr_t kTypeArgumentsOffset = 2 * kWordSize; 35 const intptr_t kTypeArgumentsOffset = 2 * kWordSize;
36 const intptr_t kArrayLengthOffset = 1 * kWordSize; 36 const intptr_t kArrayLengthOffset = 1 * kWordSize;
37 Label fall_through; 37 Label fall_through;
38 38
39 // Compute the size to be allocated, it is based on the array length 39 // Compute the size to be allocated, it is based on the array length
40 // and is computed as: 40 // and is computed as:
41 // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)). 41 // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)).
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
125 __ Bind(&init_loop); 125 __ Bind(&init_loop);
126 __ cmpl(EDI, EBX); 126 __ cmpl(EDI, EBX);
127 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); 127 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump);
128 __ movl(Address(EDI, 0), raw_null); 128 __ movl(Address(EDI, 0), raw_null);
129 __ addl(EDI, Immediate(kWordSize)); 129 __ addl(EDI, 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 EAX. 132 __ ret(); // returns the newly allocated object in EAX.
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 __ movl(EAX, Address(ESP, + 1 * kWordSize)); 139 __ movl(EAX, Address(ESP, + 1 * kWordSize));
141 __ movl(EAX, FieldAddress(EAX, Array::length_offset())); 140 __ movl(EAX, FieldAddress(EAX, 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 __ movl(EBX, Address(ESP, + 1 * kWordSize)); // Index. 152 __ movl(EBX, Address(ESP, + 1 * kWordSize)); // Index.
155 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Array. 153 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Array.
156 __ testl(EBX, Immediate(kSmiTagMask)); 154 __ testl(EBX, 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 __ cmpl(EBX, FieldAddress(EAX, Array::length_offset())); 157 __ cmpl(EBX, FieldAddress(EAX, 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 EBX is Smi, i.e, times 2. 160 // Note that EBX is Smi, i.e, times 2.
163 ASSERT(kSmiTagShift == 1); 161 ASSERT(kSmiTagShift == 1);
164 __ movl(EAX, FieldAddress(EAX, EBX, TIMES_2, Array::data_offset())); 162 __ movl(EAX, FieldAddress(EAX, EBX, TIMES_2, 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 static intptr_t ComputeObjectArrayTypeArgumentsOffset() { 173 static intptr_t ComputeObjectArrayTypeArgumentsOffset() {
177 const Library& core_lib = Library::Handle(Library::CoreLibrary()); 174 const Library& core_lib = Library::Handle(Library::CoreLibrary());
178 const Class& cls = Class::Handle( 175 const Class& cls = Class::Handle(
179 core_lib.LookupClassAllowPrivate(Symbols::ObjectArray(), NULL)); 176 core_lib.LookupClassAllowPrivate(Symbols::ObjectArray(), NULL));
180 ASSERT(!cls.IsNull()); 177 ASSERT(!cls.IsNull());
181 ASSERT(cls.HasTypeArguments()); 178 ASSERT(cls.HasTypeArguments());
182 ASSERT(cls.NumTypeArguments() == 1); 179 ASSERT(cls.NumTypeArguments() == 1);
183 const intptr_t field_offset = cls.type_arguments_field_offset(); 180 const intptr_t field_offset = cls.type_arguments_field_offset();
184 ASSERT(field_offset != Class::kNoTypeArguments); 181 ASSERT(field_offset != Class::kNoTypeArguments);
185 return field_offset; 182 return field_offset;
186 } 183 }
187 184
188 185
189 // Intrinsify only for Smi value and index. Non-smi values need a store buffer 186 // Intrinsify only for Smi value and index. Non-smi values need a store buffer
190 // update. Array length is always a Smi. 187 // update. Array length is always a Smi.
191 bool Intrinsifier::Array_setIndexed(Assembler* assembler) { 188 void Intrinsifier::Array_setIndexed(Assembler* assembler) {
192 Label fall_through; 189 Label fall_through;
193 if (FLAG_enable_type_checks) { 190 if (FLAG_enable_type_checks) {
194 const intptr_t type_args_field_offset = 191 const intptr_t type_args_field_offset =
195 ComputeObjectArrayTypeArgumentsOffset(); 192 ComputeObjectArrayTypeArgumentsOffset();
196 // Inline simple tests (Smi, null), fallthrough if not positive. 193 // Inline simple tests (Smi, null), fallthrough if not positive.
197 const Immediate& raw_null = 194 const Immediate& raw_null =
198 Immediate(reinterpret_cast<intptr_t>(Object::null())); 195 Immediate(reinterpret_cast<intptr_t>(Object::null()));
199 Label checked_ok; 196 Label checked_ok;
200 __ movl(EDI, Address(ESP, + 1 * kWordSize)); // Value. 197 __ movl(EDI, Address(ESP, + 1 * kWordSize)); // Value.
201 // Null value is valid for any type. 198 // Null value is valid for any type.
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
236 // Note that EBX is Smi, i.e, times 2. 233 // Note that EBX is Smi, i.e, times 2.
237 ASSERT(kSmiTagShift == 1); 234 ASSERT(kSmiTagShift == 1);
238 // Destroy ECX (ic data) as we will not continue in the function. 235 // Destroy ECX (ic data) as we will not continue in the function.
239 __ movl(ECX, Address(ESP, + 1 * kWordSize)); // Value. 236 __ movl(ECX, Address(ESP, + 1 * kWordSize)); // Value.
240 __ StoreIntoObject(EAX, 237 __ StoreIntoObject(EAX,
241 FieldAddress(EAX, EBX, TIMES_2, Array::data_offset()), 238 FieldAddress(EAX, EBX, TIMES_2, Array::data_offset()),
242 ECX); 239 ECX);
243 // Caller is responsible of preserving the value if necessary. 240 // Caller is responsible of preserving the value if necessary.
244 __ ret(); 241 __ ret();
245 __ Bind(&fall_through); 242 __ Bind(&fall_through);
246 return false;
247 } 243 }
248 244
249 245
250 // Allocate a GrowableObjectArray using the backing array specified. 246 // Allocate a GrowableObjectArray using the backing array specified.
251 // On stack: type argument (+2), data (+1), return-address (+0). 247 // On stack: type argument (+2), data (+1), return-address (+0).
252 bool Intrinsifier::GrowableArray_Allocate(Assembler* assembler) { 248 void Intrinsifier::GrowableArray_Allocate(Assembler* assembler) {
253 // This snippet of inlined code uses the following registers: 249 // This snippet of inlined code uses the following registers:
254 // EAX, EBX 250 // EAX, EBX
255 // and the newly allocated object is returned in EAX. 251 // and the newly allocated object is returned in EAX.
256 const intptr_t kTypeArgumentsOffset = 2 * kWordSize; 252 const intptr_t kTypeArgumentsOffset = 2 * kWordSize;
257 const intptr_t kArrayOffset = 1 * kWordSize; 253 const intptr_t kArrayOffset = 1 * kWordSize;
258 Label fall_through; 254 Label fall_through;
259 255
260 // Compute the size to be allocated, it is based on the array length 256 // Compute the size to be allocated, it is based on the array length
261 // and is computed as: 257 // and is computed as:
262 // RoundedAllocationSize(sizeof(RawGrowableObjectArray)) + 258 // RoundedAllocationSize(sizeof(RawGrowableObjectArray)) +
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
304 EAX, 300 EAX,
305 FieldAddress(EAX, GrowableObjectArray::type_arguments_offset()), 301 FieldAddress(EAX, GrowableObjectArray::type_arguments_offset()),
306 EBX); 302 EBX);
307 303
308 // Set the length field in the growable array object to 0. 304 // Set the length field in the growable array object to 0.
309 __ movl(FieldAddress(EAX, GrowableObjectArray::length_offset()), 305 __ movl(FieldAddress(EAX, GrowableObjectArray::length_offset()),
310 Immediate(0)); 306 Immediate(0));
311 __ ret(); // returns the newly allocated object in EAX. 307 __ ret(); // returns the newly allocated object in EAX.
312 308
313 __ Bind(&fall_through); 309 __ Bind(&fall_through);
314 return false;
315 } 310 }
316 311
317 312
318 // Get length of growable object array. 313 // Get length of growable object array.
319 // On stack: growable array (+1), return-address (+0). 314 // On stack: growable array (+1), return-address (+0).
320 bool Intrinsifier::GrowableArray_getLength(Assembler* assembler) { 315 void Intrinsifier::GrowableArray_getLength(Assembler* assembler) {
321 __ movl(EAX, Address(ESP, + 1 * kWordSize)); 316 __ movl(EAX, Address(ESP, + 1 * kWordSize));
322 __ movl(EAX, FieldAddress(EAX, GrowableObjectArray::length_offset())); 317 __ movl(EAX, FieldAddress(EAX, GrowableObjectArray::length_offset()));
323 __ ret(); 318 __ ret();
324 return true;
325 } 319 }
326 320
327 321
328 // Get capacity of growable object array. 322 // Get capacity of growable object array.
329 // On stack: growable array (+1), return-address (+0). 323 // On stack: growable array (+1), return-address (+0).
330 bool Intrinsifier::GrowableArray_getCapacity(Assembler* assembler) { 324 void Intrinsifier::GrowableArray_getCapacity(Assembler* assembler) {
331 __ movl(EAX, Address(ESP, + 1 * kWordSize)); 325 __ movl(EAX, Address(ESP, + 1 * kWordSize));
332 __ movl(EAX, FieldAddress(EAX, GrowableObjectArray::data_offset())); 326 __ movl(EAX, FieldAddress(EAX, GrowableObjectArray::data_offset()));
333 __ movl(EAX, FieldAddress(EAX, Array::length_offset())); 327 __ movl(EAX, FieldAddress(EAX, Array::length_offset()));
334 __ ret(); 328 __ ret();
335 return true;
336 } 329 }
337 330
338 331
339 // Access growable object array at specified index. 332 // Access growable object array at specified index.
340 // On stack: growable array (+2), index (+1), return-address (+0). 333 // On stack: growable array (+2), index (+1), return-address (+0).
341 bool Intrinsifier::GrowableArray_getIndexed(Assembler* assembler) { 334 void Intrinsifier::GrowableArray_getIndexed(Assembler* assembler) {
342 Label fall_through; 335 Label fall_through;
343 __ movl(EBX, Address(ESP, + 1 * kWordSize)); // Index. 336 __ movl(EBX, Address(ESP, + 1 * kWordSize)); // Index.
344 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // GrowableArray. 337 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // GrowableArray.
345 __ testl(EBX, Immediate(kSmiTagMask)); 338 __ testl(EBX, Immediate(kSmiTagMask));
346 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi index. 339 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi index.
347 // Range check using _length field. 340 // Range check using _length field.
348 __ cmpl(EBX, FieldAddress(EAX, GrowableObjectArray::length_offset())); 341 __ cmpl(EBX, FieldAddress(EAX, GrowableObjectArray::length_offset()));
349 // Runtime throws exception. 342 // Runtime throws exception.
350 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump); 343 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump);
351 __ movl(EAX, FieldAddress(EAX, GrowableObjectArray::data_offset())); // data. 344 __ movl(EAX, FieldAddress(EAX, GrowableObjectArray::data_offset())); // data.
352 345
353 // Note that EBX is Smi, i.e, times 2. 346 // Note that EBX is Smi, i.e, times 2.
354 ASSERT(kSmiTagShift == 1); 347 ASSERT(kSmiTagShift == 1);
355 __ movl(EAX, FieldAddress(EAX, EBX, TIMES_2, Array::data_offset())); 348 __ movl(EAX, FieldAddress(EAX, EBX, TIMES_2, Array::data_offset()));
356 __ ret(); 349 __ ret();
357 __ Bind(&fall_through); 350 __ Bind(&fall_through);
358 return false;
359 } 351 }
360 352
361 353
362 // Set value into growable object array at specified index. 354 // Set value into growable object array at specified index.
363 // On stack: growable array (+3), index (+2), value (+1), return-address (+0). 355 // On stack: growable array (+3), index (+2), value (+1), return-address (+0).
364 bool Intrinsifier::GrowableArray_setIndexed(Assembler* assembler) { 356 void Intrinsifier::GrowableArray_setIndexed(Assembler* assembler) {
365 if (FLAG_enable_type_checks) { 357 if (FLAG_enable_type_checks) {
366 return false; 358 return;
367 } 359 }
368 Label fall_through; 360 Label fall_through;
369 __ movl(EBX, Address(ESP, + 2 * kWordSize)); // Index. 361 __ movl(EBX, Address(ESP, + 2 * kWordSize)); // Index.
370 __ movl(EAX, Address(ESP, + 3 * kWordSize)); // GrowableArray. 362 __ movl(EAX, Address(ESP, + 3 * kWordSize)); // GrowableArray.
371 __ testl(EBX, Immediate(kSmiTagMask)); 363 __ testl(EBX, Immediate(kSmiTagMask));
372 __ j(NOT_ZERO, &fall_through); // Non-smi index. 364 __ j(NOT_ZERO, &fall_through); // Non-smi index.
373 // Range check using _length field. 365 // Range check using _length field.
374 __ cmpl(EBX, FieldAddress(EAX, GrowableObjectArray::length_offset())); 366 __ cmpl(EBX, FieldAddress(EAX, GrowableObjectArray::length_offset()));
375 // Runtime throws exception. 367 // Runtime throws exception.
376 __ j(ABOVE_EQUAL, &fall_through); 368 __ j(ABOVE_EQUAL, &fall_through);
377 __ movl(EAX, FieldAddress(EAX, GrowableObjectArray::data_offset())); // data. 369 __ movl(EAX, FieldAddress(EAX, GrowableObjectArray::data_offset())); // data.
378 __ movl(EDI, Address(ESP, + 1 * kWordSize)); // Value. 370 __ movl(EDI, Address(ESP, + 1 * kWordSize)); // Value.
379 // Note that EBX is Smi, i.e, times 2. 371 // Note that EBX is Smi, i.e, times 2.
380 ASSERT(kSmiTagShift == 1); 372 ASSERT(kSmiTagShift == 1);
381 __ StoreIntoObject(EAX, 373 __ StoreIntoObject(EAX,
382 FieldAddress(EAX, EBX, TIMES_2, Array::data_offset()), 374 FieldAddress(EAX, EBX, TIMES_2, Array::data_offset()),
383 EDI); 375 EDI);
384 __ ret(); 376 __ ret();
385 __ Bind(&fall_through); 377 __ Bind(&fall_through);
386 return false;
387 } 378 }
388 379
389 380
390 // Set length of growable object array. The length cannot 381 // Set length of growable object array. The length cannot
391 // be greater than the length of the data container. 382 // be greater than the length of the data container.
392 // On stack: growable array (+2), length (+1), return-address (+0). 383 // On stack: growable array (+2), length (+1), return-address (+0).
393 bool Intrinsifier::GrowableArray_setLength(Assembler* assembler) { 384 void Intrinsifier::GrowableArray_setLength(Assembler* assembler) {
394 Label fall_through; 385 Label fall_through;
395 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Growable array. 386 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Growable array.
396 __ movl(EBX, Address(ESP, + 1 * kWordSize)); // Length value. 387 __ movl(EBX, Address(ESP, + 1 * kWordSize)); // Length value.
397 __ testl(EBX, Immediate(kSmiTagMask)); 388 __ testl(EBX, Immediate(kSmiTagMask));
398 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi length. 389 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi length.
399 __ movl(FieldAddress(EAX, GrowableObjectArray::length_offset()), EBX); 390 __ movl(FieldAddress(EAX, GrowableObjectArray::length_offset()), EBX);
400 __ ret(); 391 __ ret();
401 __ Bind(&fall_through); 392 __ Bind(&fall_through);
402 return false;
403 } 393 }
404 394
405 395
406 // Set data of growable object array. 396 // Set data of growable object array.
407 // On stack: growable array (+2), data (+1), return-address (+0). 397 // On stack: growable array (+2), data (+1), return-address (+0).
408 bool Intrinsifier::GrowableArray_setData(Assembler* assembler) { 398 void Intrinsifier::GrowableArray_setData(Assembler* assembler) {
409 if (FLAG_enable_type_checks) { 399 if (FLAG_enable_type_checks) {
410 return false; 400 return;
411 } 401 }
412 Label fall_through; 402 Label fall_through;
413 __ movl(EBX, Address(ESP, + 1 * kWordSize)); // Data. 403 __ movl(EBX, Address(ESP, + 1 * kWordSize)); // Data.
414 // Check that data is an ObjectArray. 404 // Check that data is an ObjectArray.
415 __ testl(EBX, Immediate(kSmiTagMask)); 405 __ testl(EBX, Immediate(kSmiTagMask));
416 __ j(ZERO, &fall_through); // Data is Smi. 406 __ j(ZERO, &fall_through); // Data is Smi.
417 __ CompareClassId(EBX, kArrayCid, EAX); 407 __ CompareClassId(EBX, kArrayCid, EAX);
418 __ j(NOT_EQUAL, &fall_through); 408 __ j(NOT_EQUAL, &fall_through);
419 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Growable array. 409 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Growable array.
420 __ StoreIntoObject(EAX, 410 __ StoreIntoObject(EAX,
421 FieldAddress(EAX, GrowableObjectArray::data_offset()), 411 FieldAddress(EAX, GrowableObjectArray::data_offset()),
422 EBX); 412 EBX);
423 __ ret(); 413 __ ret();
424 __ Bind(&fall_through); 414 __ Bind(&fall_through);
425 return false;
426 } 415 }
427 416
428 417
429 // Add an element to growable array if it doesn't need to grow, otherwise 418 // Add an element to growable array if it doesn't need to grow, otherwise
430 // call into regular code. 419 // call into regular code.
431 // On stack: growable array (+2), value (+1), return-address (+0). 420 // On stack: growable array (+2), value (+1), return-address (+0).
432 bool Intrinsifier::GrowableArray_add(Assembler* assembler) { 421 void Intrinsifier::GrowableArray_add(Assembler* assembler) {
433 // In checked mode we need to type-check the incoming argument. 422 // In checked mode we need to type-check the incoming argument.
434 if (FLAG_enable_type_checks) return false; 423 if (FLAG_enable_type_checks) return;
424
435 Label fall_through; 425 Label fall_through;
436 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Array. 426 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Array.
437 __ movl(EBX, FieldAddress(EAX, GrowableObjectArray::length_offset())); 427 __ movl(EBX, FieldAddress(EAX, GrowableObjectArray::length_offset()));
438 // EBX: length. 428 // EBX: length.
439 __ movl(EDI, FieldAddress(EAX, GrowableObjectArray::data_offset())); 429 __ movl(EDI, FieldAddress(EAX, GrowableObjectArray::data_offset()));
440 // EDI: data. 430 // EDI: data.
441 // Compare length with capacity. 431 // Compare length with capacity.
442 __ cmpl(EBX, FieldAddress(EDI, Array::length_offset())); 432 __ cmpl(EBX, FieldAddress(EDI, Array::length_offset()));
443 __ j(EQUAL, &fall_through); // Must grow data. 433 __ j(EQUAL, &fall_through); // Must grow data.
444 const Immediate& value_one = 434 const Immediate& value_one =
445 Immediate(reinterpret_cast<int32_t>(Smi::New(1))); 435 Immediate(reinterpret_cast<int32_t>(Smi::New(1)));
446 // len = len + 1; 436 // len = len + 1;
447 __ addl(FieldAddress(EAX, GrowableObjectArray::length_offset()), value_one); 437 __ addl(FieldAddress(EAX, GrowableObjectArray::length_offset()), value_one);
448 __ movl(EAX, Address(ESP, + 1 * kWordSize)); // Value 438 __ movl(EAX, Address(ESP, + 1 * kWordSize)); // Value
449 ASSERT(kSmiTagShift == 1); 439 ASSERT(kSmiTagShift == 1);
450 __ StoreIntoObject(EDI, 440 __ StoreIntoObject(EDI,
451 FieldAddress(EDI, EBX, TIMES_2, Array::data_offset()), 441 FieldAddress(EDI, EBX, TIMES_2, Array::data_offset()),
452 EAX); 442 EAX);
453 const Immediate& raw_null = 443 const Immediate& raw_null =
454 Immediate(reinterpret_cast<int32_t>(Object::null())); 444 Immediate(reinterpret_cast<int32_t>(Object::null()));
455 __ movl(EAX, raw_null); 445 __ movl(EAX, raw_null);
456 __ ret(); 446 __ ret();
457 __ Bind(&fall_through); 447 __ Bind(&fall_through);
458 return false;
459 } 448 }
460 449
461 450
462 #define TYPED_ARRAY_ALLOCATION(type_name, cid, max_len, scale_factor) \ 451 #define TYPED_ARRAY_ALLOCATION(type_name, cid, max_len, scale_factor) \
463 Label fall_through; \ 452 Label fall_through; \
464 const intptr_t kArrayLengthStackOffset = 1 * kWordSize; \ 453 const intptr_t kArrayLengthStackOffset = 1 * kWordSize; \
465 __ movl(EDI, Address(ESP, kArrayLengthStackOffset)); /* Array length. */ \ 454 __ movl(EDI, Address(ESP, kArrayLengthStackOffset)); /* Array length. */ \
466 /* Check that length is a positive Smi. */ \ 455 /* Check that length is a positive Smi. */ \
467 /* EDI: requested array length argument. */ \ 456 /* EDI: requested array length argument. */ \
468 __ testl(EDI, Immediate(kSmiTagMask)); \ 457 __ testl(EDI, Immediate(kSmiTagMask)); \
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
547 __ addl(EDI, Immediate(kWordSize)); \ 536 __ addl(EDI, Immediate(kWordSize)); \
548 __ jmp(&init_loop, Assembler::kNearJump); \ 537 __ jmp(&init_loop, Assembler::kNearJump); \
549 __ Bind(&done); \ 538 __ Bind(&done); \
550 \ 539 \
551 __ ret(); \ 540 __ ret(); \
552 __ Bind(&fall_through); \ 541 __ Bind(&fall_through); \
553 542
554 543
555 544
556 // Gets the length of a TypedData. 545 // Gets the length of a TypedData.
557 bool Intrinsifier::TypedData_getLength(Assembler* assembler) { 546 void Intrinsifier::TypedData_getLength(Assembler* assembler) {
558 __ movl(EAX, Address(ESP, + 1 * kWordSize)); 547 __ movl(EAX, Address(ESP, + 1 * kWordSize));
559 __ movl(EAX, FieldAddress(EAX, TypedData::length_offset())); 548 __ movl(EAX, FieldAddress(EAX, TypedData::length_offset()));
560 __ ret(); 549 __ ret();
561 return true;
562 } 550 }
563 551
564 552
565 static ScaleFactor GetScaleFactor(intptr_t size) { 553 static ScaleFactor GetScaleFactor(intptr_t size) {
566 switch (size) { 554 switch (size) {
567 case 1: return TIMES_1; 555 case 1: return TIMES_1;
568 case 2: return TIMES_2; 556 case 2: return TIMES_2;
569 case 4: return TIMES_4; 557 case 4: return TIMES_4;
570 case 8: return TIMES_8; 558 case 8: return TIMES_8;
571 case 16: return TIMES_16; 559 case 16: return TIMES_16;
572 } 560 }
573 UNREACHABLE(); 561 UNREACHABLE();
574 return static_cast<ScaleFactor>(0); 562 return static_cast<ScaleFactor>(0);
575 }; 563 };
576 564
577 565
578 #define TYPED_DATA_ALLOCATOR(clazz) \ 566 #define TYPED_DATA_ALLOCATOR(clazz) \
579 bool Intrinsifier::TypedData_##clazz##_new(Assembler* assembler) { \ 567 void Intrinsifier::TypedData_##clazz##_new(Assembler* assembler) { \
580 intptr_t size = TypedData::ElementSizeInBytes(kTypedData##clazz##Cid); \ 568 intptr_t size = TypedData::ElementSizeInBytes(kTypedData##clazz##Cid); \
581 intptr_t max_len = TypedData::MaxElements(kTypedData##clazz##Cid); \ 569 intptr_t max_len = TypedData::MaxElements(kTypedData##clazz##Cid); \
582 ScaleFactor scale = GetScaleFactor(size); \ 570 ScaleFactor scale = GetScaleFactor(size); \
583 TYPED_ARRAY_ALLOCATION(TypedData, kTypedData##clazz##Cid, max_len, scale); \ 571 TYPED_ARRAY_ALLOCATION(TypedData, kTypedData##clazz##Cid, max_len, scale); \
584 return false; \
585 } \ 572 } \
586 bool Intrinsifier::TypedData_##clazz##_factory(Assembler* assembler) { \ 573 void Intrinsifier::TypedData_##clazz##_factory(Assembler* assembler) { \
587 intptr_t size = TypedData::ElementSizeInBytes(kTypedData##clazz##Cid); \ 574 intptr_t size = TypedData::ElementSizeInBytes(kTypedData##clazz##Cid); \
588 intptr_t max_len = TypedData::MaxElements(kTypedData##clazz##Cid); \ 575 intptr_t max_len = TypedData::MaxElements(kTypedData##clazz##Cid); \
589 ScaleFactor scale = GetScaleFactor(size); \ 576 ScaleFactor scale = GetScaleFactor(size); \
590 TYPED_ARRAY_ALLOCATION(TypedData, kTypedData##clazz##Cid, max_len, scale); \ 577 TYPED_ARRAY_ALLOCATION(TypedData, kTypedData##clazz##Cid, max_len, scale); \
591 return false; \
592 } 578 }
593 CLASS_LIST_TYPED_DATA(TYPED_DATA_ALLOCATOR) 579 CLASS_LIST_TYPED_DATA(TYPED_DATA_ALLOCATOR)
594 #undef TYPED_DATA_ALLOCATOR 580 #undef TYPED_DATA_ALLOCATOR
595 581
596 582
597 // Tests if two top most arguments are smis, jumps to label not_smi if not. 583 // Tests if two top most arguments are smis, jumps to label not_smi if not.
598 // Topmost argument is in EAX. 584 // Topmost argument is in EAX.
599 static void TestBothArgumentsSmis(Assembler* assembler, Label* not_smi) { 585 static void TestBothArgumentsSmis(Assembler* assembler, Label* not_smi) {
600 __ movl(EAX, Address(ESP, + 1 * kWordSize)); 586 __ movl(EAX, Address(ESP, + 1 * kWordSize));
601 __ movl(EBX, Address(ESP, + 2 * kWordSize)); 587 __ movl(EBX, Address(ESP, + 2 * kWordSize));
602 __ orl(EBX, EAX); 588 __ orl(EBX, EAX);
603 __ testl(EBX, Immediate(kSmiTagMask)); 589 __ testl(EBX, Immediate(kSmiTagMask));
604 __ j(NOT_ZERO, not_smi, Assembler::kNearJump); 590 __ j(NOT_ZERO, not_smi, Assembler::kNearJump);
605 } 591 }
606 592
607 593
608 bool Intrinsifier::Integer_addFromInteger(Assembler* assembler) { 594 void Intrinsifier::Integer_addFromInteger(Assembler* assembler) {
609 Label fall_through; 595 Label fall_through;
610 TestBothArgumentsSmis(assembler, &fall_through); 596 TestBothArgumentsSmis(assembler, &fall_through);
611 __ addl(EAX, Address(ESP, + 2 * kWordSize)); 597 __ addl(EAX, Address(ESP, + 2 * kWordSize));
612 __ j(OVERFLOW, &fall_through, Assembler::kNearJump); 598 __ j(OVERFLOW, &fall_through, Assembler::kNearJump);
613 // Result is in EAX. 599 // Result is in EAX.
614 __ ret(); 600 __ ret();
615 __ Bind(&fall_through); 601 __ Bind(&fall_through);
616 return false;
617 } 602 }
618 603
619 604
620 bool Intrinsifier::Integer_add(Assembler* assembler) { 605 void Intrinsifier::Integer_add(Assembler* assembler) {
621 return Integer_addFromInteger(assembler); 606 return Integer_addFromInteger(assembler);
622 } 607 }
623 608
624 609
625 bool Intrinsifier::Integer_subFromInteger(Assembler* assembler) { 610 void Intrinsifier::Integer_subFromInteger(Assembler* assembler) {
626 Label fall_through; 611 Label fall_through;
627 TestBothArgumentsSmis(assembler, &fall_through); 612 TestBothArgumentsSmis(assembler, &fall_through);
628 __ subl(EAX, Address(ESP, + 2 * kWordSize)); 613 __ subl(EAX, Address(ESP, + 2 * kWordSize));
629 __ j(OVERFLOW, &fall_through, Assembler::kNearJump); 614 __ j(OVERFLOW, &fall_through, Assembler::kNearJump);
630 // Result is in EAX. 615 // Result is in EAX.
631 __ ret(); 616 __ ret();
632 __ Bind(&fall_through); 617 __ Bind(&fall_through);
633 return false;
634 } 618 }
635 619
636 620
637 bool Intrinsifier::Integer_sub(Assembler* assembler) { 621 void Intrinsifier::Integer_sub(Assembler* assembler) {
638 Label fall_through; 622 Label fall_through;
639 TestBothArgumentsSmis(assembler, &fall_through); 623 TestBothArgumentsSmis(assembler, &fall_through);
640 __ movl(EBX, EAX); 624 __ movl(EBX, EAX);
641 __ movl(EAX, Address(ESP, + 2 * kWordSize)); 625 __ movl(EAX, Address(ESP, + 2 * kWordSize));
642 __ subl(EAX, EBX); 626 __ subl(EAX, EBX);
643 __ j(OVERFLOW, &fall_through, Assembler::kNearJump); 627 __ j(OVERFLOW, &fall_through, Assembler::kNearJump);
644 // Result is in EAX. 628 // Result is in EAX.
645 __ ret(); 629 __ ret();
646 __ Bind(&fall_through); 630 __ Bind(&fall_through);
647 return false;
648 } 631 }
649 632
650 633
651 634
652 bool Intrinsifier::Integer_mulFromInteger(Assembler* assembler) { 635 void Intrinsifier::Integer_mulFromInteger(Assembler* assembler) {
653 Label fall_through; 636 Label fall_through;
654 TestBothArgumentsSmis(assembler, &fall_through); 637 TestBothArgumentsSmis(assembler, &fall_through);
655 ASSERT(kSmiTag == 0); // Adjust code below if not the case. 638 ASSERT(kSmiTag == 0); // Adjust code below if not the case.
656 __ SmiUntag(EAX); 639 __ SmiUntag(EAX);
657 __ imull(EAX, Address(ESP, + 2 * kWordSize)); 640 __ imull(EAX, Address(ESP, + 2 * kWordSize));
658 __ j(OVERFLOW, &fall_through, Assembler::kNearJump); 641 __ j(OVERFLOW, &fall_through, Assembler::kNearJump);
659 // Result is in EAX. 642 // Result is in EAX.
660 __ ret(); 643 __ ret();
661 __ Bind(&fall_through); 644 __ Bind(&fall_through);
662 return false;
663 } 645 }
664 646
665 647
666 bool Intrinsifier::Integer_mul(Assembler* assembler) { 648 void Intrinsifier::Integer_mul(Assembler* assembler) {
667 return Integer_mulFromInteger(assembler); 649 return Integer_mulFromInteger(assembler);
668 } 650 }
669 651
670 652
671 // Optimizations: 653 // Optimizations:
672 // - result is 0 if: 654 // - result is 0 if:
673 // - left is 0 655 // - left is 0
674 // - left equals right 656 // - left equals right
675 // - result is left if 657 // - result is left if
676 // - left > 0 && left < right 658 // - left > 0 && left < right
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
708 690
709 // Implementation: 691 // Implementation:
710 // res = left % right; 692 // res = left % right;
711 // if (res < 0) { 693 // if (res < 0) {
712 // if (right < 0) { 694 // if (right < 0) {
713 // res = res - right; 695 // res = res - right;
714 // } else { 696 // } else {
715 // res = res + right; 697 // res = res + right;
716 // } 698 // }
717 // } 699 // }
718 bool Intrinsifier::Integer_moduloFromInteger(Assembler* assembler) { 700 void Intrinsifier::Integer_moduloFromInteger(Assembler* assembler) {
719 Label fall_through, subtract; 701 Label fall_through, subtract;
720 TestBothArgumentsSmis(assembler, &fall_through); 702 TestBothArgumentsSmis(assembler, &fall_through);
721 __ movl(EBX, Address(ESP, + 2 * kWordSize)); 703 __ movl(EBX, Address(ESP, + 2 * kWordSize));
722 // EAX: Tagged left (dividend). 704 // EAX: Tagged left (dividend).
723 // EBX: Tagged right (divisor). 705 // EBX: Tagged right (divisor).
724 // Check if modulo by zero -> exception thrown in main function. 706 // Check if modulo by zero -> exception thrown in main function.
725 __ cmpl(EBX, Immediate(0)); 707 __ cmpl(EBX, Immediate(0));
726 __ j(EQUAL, &fall_through, Assembler::kNearJump); 708 __ j(EQUAL, &fall_through, Assembler::kNearJump);
727 EmitRemainderOperation(assembler); 709 EmitRemainderOperation(assembler);
728 // Untagged remainder result in EDX. 710 // Untagged remainder result in EDX.
(...skipping 10 matching lines...) Expand all
739 721
740 __ Bind(&subtract); 722 __ Bind(&subtract);
741 __ subl(EAX, EBX); 723 __ subl(EAX, EBX);
742 724
743 __ Bind(&done); 725 __ Bind(&done);
744 // The remainder of two Smi-s is always a Smi, no overflow check needed. 726 // The remainder of two Smi-s is always a Smi, no overflow check needed.
745 __ SmiTag(EAX); 727 __ SmiTag(EAX);
746 __ ret(); 728 __ ret();
747 729
748 __ Bind(&fall_through); 730 __ Bind(&fall_through);
749 return false;
750 } 731 }
751 732
752 733
753 bool Intrinsifier::Integer_remainder(Assembler* assembler) { 734 void Intrinsifier::Integer_remainder(Assembler* assembler) {
754 Label fall_through; 735 Label fall_through;
755 TestBothArgumentsSmis(assembler, &fall_through); 736 TestBothArgumentsSmis(assembler, &fall_through);
756 // EAX: right argument (divisor) 737 // EAX: right argument (divisor)
757 __ movl(EBX, EAX); 738 __ movl(EBX, EAX);
758 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Left argument (dividend). 739 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Left argument (dividend).
759 // EAX: Tagged left (dividend). 740 // EAX: Tagged left (dividend).
760 // EBX: Tagged right (divisor). 741 // EBX: Tagged right (divisor).
761 // Check if modulo by zero -> exception thrown in main function. 742 // Check if modulo by zero -> exception thrown in main function.
762 __ cmpl(EBX, Immediate(0)); 743 __ cmpl(EBX, Immediate(0));
763 __ j(EQUAL, &fall_through, Assembler::kNearJump); 744 __ j(EQUAL, &fall_through, Assembler::kNearJump);
764 EmitRemainderOperation(assembler); 745 EmitRemainderOperation(assembler);
765 // Untagged remainder result in EDX. 746 // Untagged remainder result in EDX.
766 __ movl(EAX, EDX); 747 __ movl(EAX, EDX);
767 __ SmiTag(EAX); 748 __ SmiTag(EAX);
768 __ ret(); 749 __ ret();
769 750
770 __ Bind(&fall_through); 751 __ Bind(&fall_through);
771 return false;
772 } 752 }
773 753
774 754
775 bool Intrinsifier::Integer_truncDivide(Assembler* assembler) { 755 void Intrinsifier::Integer_truncDivide(Assembler* assembler) {
776 Label fall_through; 756 Label fall_through;
777 TestBothArgumentsSmis(assembler, &fall_through); 757 TestBothArgumentsSmis(assembler, &fall_through);
778 // EAX: right argument (divisor) 758 // EAX: right argument (divisor)
779 __ cmpl(EAX, Immediate(0)); 759 __ cmpl(EAX, Immediate(0));
780 __ j(EQUAL, &fall_through, Assembler::kNearJump); 760 __ j(EQUAL, &fall_through, Assembler::kNearJump);
781 __ movl(EBX, EAX); 761 __ movl(EBX, EAX);
782 __ SmiUntag(EBX); 762 __ SmiUntag(EBX);
783 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Left argument (dividend). 763 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Left argument (dividend).
784 __ SmiUntag(EAX); 764 __ SmiUntag(EAX);
785 __ pushl(EDX); // Preserve EDX in case of 'fall_through'. 765 __ pushl(EDX); // Preserve EDX in case of 'fall_through'.
786 __ cdq(); 766 __ cdq();
787 __ idivl(EBX); 767 __ idivl(EBX);
788 __ popl(EDX); 768 __ popl(EDX);
789 // Check the corner case of dividing the 'MIN_SMI' with -1, in which case we 769 // Check the corner case of dividing the 'MIN_SMI' with -1, in which case we
790 // cannot tag the result. 770 // cannot tag the result.
791 __ cmpl(EAX, Immediate(0x40000000)); 771 __ cmpl(EAX, Immediate(0x40000000));
792 __ j(EQUAL, &fall_through); 772 __ j(EQUAL, &fall_through);
793 __ SmiTag(EAX); 773 __ SmiTag(EAX);
794 __ ret(); 774 __ ret();
795 __ Bind(&fall_through); 775 __ Bind(&fall_through);
796 return false;
797 } 776 }
798 777
799 778
800 bool Intrinsifier::Integer_negate(Assembler* assembler) { 779 void Intrinsifier::Integer_negate(Assembler* assembler) {
801 Label fall_through; 780 Label fall_through;
802 __ movl(EAX, Address(ESP, + 1 * kWordSize)); 781 __ movl(EAX, Address(ESP, + 1 * kWordSize));
803 __ testl(EAX, Immediate(kSmiTagMask)); 782 __ testl(EAX, Immediate(kSmiTagMask));
804 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi value. 783 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi value.
805 __ negl(EAX); 784 __ negl(EAX);
806 __ j(OVERFLOW, &fall_through, Assembler::kNearJump); 785 __ j(OVERFLOW, &fall_through, Assembler::kNearJump);
807 // Result is in EAX. 786 // Result is in EAX.
808 __ ret(); 787 __ ret();
809 __ Bind(&fall_through); 788 __ Bind(&fall_through);
810 return false;
811 } 789 }
812 790
813 791
814 bool Intrinsifier::Integer_bitAndFromInteger(Assembler* assembler) { 792 void Intrinsifier::Integer_bitAndFromInteger(Assembler* assembler) {
815 Label fall_through; 793 Label fall_through;
816 TestBothArgumentsSmis(assembler, &fall_through); 794 TestBothArgumentsSmis(assembler, &fall_through);
817 __ movl(EBX, Address(ESP, + 2 * kWordSize)); 795 __ movl(EBX, Address(ESP, + 2 * kWordSize));
818 __ andl(EAX, EBX); 796 __ andl(EAX, EBX);
819 // Result is in EAX. 797 // Result is in EAX.
820 __ ret(); 798 __ ret();
821 __ Bind(&fall_through); 799 __ Bind(&fall_through);
822 return false;
823 } 800 }
824 801
825 802
826 bool Intrinsifier::Integer_bitAnd(Assembler* assembler) { 803 void Intrinsifier::Integer_bitAnd(Assembler* assembler) {
827 return Integer_bitAndFromInteger(assembler); 804 return Integer_bitAndFromInteger(assembler);
828 } 805 }
829 806
830 807
831 bool Intrinsifier::Integer_bitOrFromInteger(Assembler* assembler) { 808 void Intrinsifier::Integer_bitOrFromInteger(Assembler* assembler) {
832 Label fall_through; 809 Label fall_through;
833 TestBothArgumentsSmis(assembler, &fall_through); 810 TestBothArgumentsSmis(assembler, &fall_through);
834 __ movl(EBX, Address(ESP, + 2 * kWordSize)); 811 __ movl(EBX, Address(ESP, + 2 * kWordSize));
835 __ orl(EAX, EBX); 812 __ orl(EAX, EBX);
836 // Result is in EAX. 813 // Result is in EAX.
837 __ ret(); 814 __ ret();
838 __ Bind(&fall_through); 815 __ Bind(&fall_through);
839 return false;
840 } 816 }
841 817
842 818
843 bool Intrinsifier::Integer_bitOr(Assembler* assembler) { 819 void Intrinsifier::Integer_bitOr(Assembler* assembler) {
844 return Integer_bitOrFromInteger(assembler); 820 return Integer_bitOrFromInteger(assembler);
845 } 821 }
846 822
847 823
848 bool Intrinsifier::Integer_bitXorFromInteger(Assembler* assembler) { 824 void Intrinsifier::Integer_bitXorFromInteger(Assembler* assembler) {
849 Label fall_through; 825 Label fall_through;
850 TestBothArgumentsSmis(assembler, &fall_through); 826 TestBothArgumentsSmis(assembler, &fall_through);
851 __ movl(EBX, Address(ESP, + 2 * kWordSize)); 827 __ movl(EBX, Address(ESP, + 2 * kWordSize));
852 __ xorl(EAX, EBX); 828 __ xorl(EAX, EBX);
853 // Result is in EAX. 829 // Result is in EAX.
854 __ ret(); 830 __ ret();
855 __ Bind(&fall_through); 831 __ Bind(&fall_through);
856 return false;
857 } 832 }
858 833
859 834
860 bool Intrinsifier::Integer_bitXor(Assembler* assembler) { 835 void Intrinsifier::Integer_bitXor(Assembler* assembler) {
861 return Integer_bitXorFromInteger(assembler); 836 return Integer_bitXorFromInteger(assembler);
862 } 837 }
863 838
864 839
865 bool Intrinsifier::Integer_shl(Assembler* assembler) { 840 void Intrinsifier::Integer_shl(Assembler* assembler) {
866 ASSERT(kSmiTagShift == 1); 841 ASSERT(kSmiTagShift == 1);
867 ASSERT(kSmiTag == 0); 842 ASSERT(kSmiTag == 0);
868 Label fall_through, overflow; 843 Label fall_through, overflow;
869 TestBothArgumentsSmis(assembler, &fall_through); 844 TestBothArgumentsSmis(assembler, &fall_through);
870 // Shift value is in EAX. Compare with tagged Smi. 845 // Shift value is in EAX. Compare with tagged Smi.
871 __ cmpl(EAX, Immediate(Smi::RawValue(Smi::kBits))); 846 __ cmpl(EAX, Immediate(Smi::RawValue(Smi::kBits)));
872 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump); 847 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump);
873 848
874 __ SmiUntag(EAX); 849 __ SmiUntag(EAX);
875 __ movl(ECX, EAX); // Shift amount must be in ECX. 850 __ movl(ECX, EAX); // Shift amount must be in ECX.
(...skipping 26 matching lines...) Expand all
902 Isolate::Current()->object_store()->mint_class()); 877 Isolate::Current()->object_store()->mint_class());
903 __ TryAllocate(mint_class, 878 __ TryAllocate(mint_class,
904 &fall_through, 879 &fall_through,
905 Assembler::kNearJump, 880 Assembler::kNearJump,
906 EAX); // Result register. 881 EAX); // Result register.
907 // EBX and EDI are not objects but integer values. 882 // EBX and EDI are not objects but integer values.
908 __ movl(FieldAddress(EAX, Mint::value_offset()), EBX); 883 __ movl(FieldAddress(EAX, Mint::value_offset()), EBX);
909 __ movl(FieldAddress(EAX, Mint::value_offset() + kWordSize), EDI); 884 __ movl(FieldAddress(EAX, Mint::value_offset() + kWordSize), EDI);
910 __ ret(); 885 __ ret();
911 __ Bind(&fall_through); 886 __ Bind(&fall_through);
912 return false;
913 } 887 }
914 888
915 889
916 static void Push64SmiOrMint(Assembler* assembler, 890 static void Push64SmiOrMint(Assembler* assembler,
917 Register reg, 891 Register reg,
918 Register tmp, 892 Register tmp,
919 Label* not_smi_or_mint) { 893 Label* not_smi_or_mint) {
920 Label not_smi, done; 894 Label not_smi, done;
921 __ testl(reg, Immediate(kSmiTagMask)); 895 __ testl(reg, Immediate(kSmiTagMask));
922 __ j(NOT_ZERO, &not_smi, Assembler::kNearJump); 896 __ j(NOT_ZERO, &not_smi, Assembler::kNearJump);
923 __ SmiUntag(reg); 897 __ SmiUntag(reg);
924 // Sign extend to 64 bit 898 // Sign extend to 64 bit
925 __ movl(tmp, reg); 899 __ movl(tmp, reg);
926 __ sarl(tmp, Immediate(31)); 900 __ sarl(tmp, Immediate(31));
927 __ pushl(tmp); 901 __ pushl(tmp);
928 __ pushl(reg); 902 __ pushl(reg);
929 __ jmp(&done); 903 __ jmp(&done);
930 __ Bind(&not_smi); 904 __ Bind(&not_smi);
931 __ CompareClassId(reg, kMintCid, tmp); 905 __ CompareClassId(reg, kMintCid, tmp);
932 __ j(NOT_EQUAL, not_smi_or_mint); 906 __ j(NOT_EQUAL, not_smi_or_mint);
933 // Mint. 907 // Mint.
934 __ pushl(FieldAddress(reg, Mint::value_offset() + kWordSize)); 908 __ pushl(FieldAddress(reg, Mint::value_offset() + kWordSize));
935 __ pushl(FieldAddress(reg, Mint::value_offset())); 909 __ pushl(FieldAddress(reg, Mint::value_offset()));
936 __ Bind(&done); 910 __ Bind(&done);
937 } 911 }
938 912
939 913
940 static bool CompareIntegers(Assembler* assembler, Condition true_condition) { 914 static void CompareIntegers(Assembler* assembler, Condition true_condition) {
941 Label try_mint_smi, is_true, is_false, drop_two_fall_through, fall_through; 915 Label try_mint_smi, is_true, is_false, drop_two_fall_through, fall_through;
942 TestBothArgumentsSmis(assembler, &try_mint_smi); 916 TestBothArgumentsSmis(assembler, &try_mint_smi);
943 // EAX contains the right argument. 917 // EAX contains the right argument.
944 __ cmpl(Address(ESP, + 2 * kWordSize), EAX); 918 __ cmpl(Address(ESP, + 2 * kWordSize), EAX);
945 __ j(true_condition, &is_true, Assembler::kNearJump); 919 __ j(true_condition, &is_true, Assembler::kNearJump);
946 __ Bind(&is_false); 920 __ Bind(&is_false);
947 __ LoadObject(EAX, Bool::False()); 921 __ LoadObject(EAX, Bool::False());
948 __ ret(); 922 __ ret();
949 __ Bind(&is_true); 923 __ Bind(&is_true);
950 __ LoadObject(EAX, Bool::True()); 924 __ LoadObject(EAX, Bool::True());
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
986 __ j(hi_false_cond, &is_false, Assembler::kNearJump); 960 __ j(hi_false_cond, &is_false, Assembler::kNearJump);
987 __ j(hi_true_cond, &is_true, Assembler::kNearJump); 961 __ j(hi_true_cond, &is_true, Assembler::kNearJump);
988 __ cmpl(EAX, EBX); // cmpl left.LO, right.LO. 962 __ cmpl(EAX, EBX); // cmpl left.LO, right.LO.
989 __ j(lo_false_cond, &is_false, Assembler::kNearJump); 963 __ j(lo_false_cond, &is_false, Assembler::kNearJump);
990 // Else is true. 964 // Else is true.
991 __ jmp(&is_true); 965 __ jmp(&is_true);
992 966
993 __ Bind(&drop_two_fall_through); 967 __ Bind(&drop_two_fall_through);
994 __ Drop(2); 968 __ Drop(2);
995 __ Bind(&fall_through); 969 __ Bind(&fall_through);
996 return false;
997 } 970 }
998 971
999 972
1000 973
1001 bool Intrinsifier::Integer_greaterThanFromInt(Assembler* assembler) { 974 void Intrinsifier::Integer_greaterThanFromInt(Assembler* assembler) {
1002 return CompareIntegers(assembler, LESS); 975 return CompareIntegers(assembler, LESS);
1003 } 976 }
1004 977
1005 978
1006 bool Intrinsifier::Integer_lessThan(Assembler* assembler) { 979 void Intrinsifier::Integer_lessThan(Assembler* assembler) {
1007 return Integer_greaterThanFromInt(assembler); 980 return Integer_greaterThanFromInt(assembler);
1008 } 981 }
1009 982
1010 983
1011 bool Intrinsifier::Integer_greaterThan(Assembler* assembler) { 984 void Intrinsifier::Integer_greaterThan(Assembler* assembler) {
1012 return CompareIntegers(assembler, GREATER); 985 return CompareIntegers(assembler, GREATER);
1013 } 986 }
1014 987
1015 988
1016 bool Intrinsifier::Integer_lessEqualThan(Assembler* assembler) { 989 void Intrinsifier::Integer_lessEqualThan(Assembler* assembler) {
1017 return CompareIntegers(assembler, LESS_EQUAL); 990 return CompareIntegers(assembler, LESS_EQUAL);
1018 } 991 }
1019 992
1020 993
1021 bool Intrinsifier::Integer_greaterEqualThan(Assembler* assembler) { 994 void Intrinsifier::Integer_greaterEqualThan(Assembler* assembler) {
1022 return CompareIntegers(assembler, GREATER_EQUAL); 995 return CompareIntegers(assembler, GREATER_EQUAL);
1023 } 996 }
1024 997
1025 998
1026 // This is called for Smi, Mint and Bigint receivers. The right argument 999 // This is called for Smi, Mint and Bigint receivers. The right argument
1027 // can be Smi, Mint, Bigint or double. 1000 // can be Smi, Mint, Bigint or double.
1028 bool Intrinsifier::Integer_equalToInteger(Assembler* assembler) { 1001 void Intrinsifier::Integer_equalToInteger(Assembler* assembler) {
1029 Label fall_through, true_label, check_for_mint; 1002 Label fall_through, true_label, check_for_mint;
1030 // For integer receiver '===' check first. 1003 // For integer receiver '===' check first.
1031 __ movl(EAX, Address(ESP, + 1 * kWordSize)); 1004 __ movl(EAX, Address(ESP, + 1 * kWordSize));
1032 __ cmpl(EAX, Address(ESP, + 2 * kWordSize)); 1005 __ cmpl(EAX, Address(ESP, + 2 * kWordSize));
1033 __ j(EQUAL, &true_label, Assembler::kNearJump); 1006 __ j(EQUAL, &true_label, Assembler::kNearJump);
1034 __ movl(EBX, Address(ESP, + 2 * kWordSize)); 1007 __ movl(EBX, Address(ESP, + 2 * kWordSize));
1035 __ orl(EAX, EBX); 1008 __ orl(EAX, EBX);
1036 __ testl(EAX, Immediate(kSmiTagMask)); 1009 __ testl(EAX, Immediate(kSmiTagMask));
1037 __ j(NOT_ZERO, &check_for_mint, Assembler::kNearJump); 1010 __ j(NOT_ZERO, &check_for_mint, Assembler::kNearJump);
1038 // Both arguments are smi, '===' is good enough. 1011 // Both arguments are smi, '===' is good enough.
(...skipping 25 matching lines...) Expand all
1064 __ j(NOT_EQUAL, &fall_through); 1037 __ j(NOT_EQUAL, &fall_through);
1065 // Receiver is Mint, return false if right is Smi. 1038 // Receiver is Mint, return false if right is Smi.
1066 __ movl(EAX, Address(ESP, + 1 * kWordSize)); // Right argument. 1039 __ movl(EAX, Address(ESP, + 1 * kWordSize)); // Right argument.
1067 __ testl(EAX, Immediate(kSmiTagMask)); 1040 __ testl(EAX, Immediate(kSmiTagMask));
1068 __ j(NOT_ZERO, &fall_through); 1041 __ j(NOT_ZERO, &fall_through);
1069 __ LoadObject(EAX, Bool::False()); 1042 __ LoadObject(EAX, Bool::False());
1070 __ ret(); 1043 __ ret();
1071 // TODO(srdjan): Implement Mint == Mint comparison. 1044 // TODO(srdjan): Implement Mint == Mint comparison.
1072 1045
1073 __ Bind(&fall_through); 1046 __ Bind(&fall_through);
1074 return false;
1075 } 1047 }
1076 1048
1077 1049
1078 bool Intrinsifier::Integer_equal(Assembler* assembler) { 1050 void Intrinsifier::Integer_equal(Assembler* assembler) {
1079 return Integer_equalToInteger(assembler); 1051 return Integer_equalToInteger(assembler);
1080 } 1052 }
1081 1053
1082 1054
1083 bool Intrinsifier::Integer_sar(Assembler* assembler) { 1055 void Intrinsifier::Integer_sar(Assembler* assembler) {
1084 Label fall_through, shift_count_ok; 1056 Label fall_through, shift_count_ok;
1085 TestBothArgumentsSmis(assembler, &fall_through); 1057 TestBothArgumentsSmis(assembler, &fall_through);
1086 // Can destroy ECX since we are not falling through. 1058 // Can destroy ECX since we are not falling through.
1087 const Immediate& count_limit = Immediate(0x1F); 1059 const Immediate& count_limit = Immediate(0x1F);
1088 // Check that the count is not larger than what the hardware can handle. 1060 // Check that the count is not larger than what the hardware can handle.
1089 // For shifting right a Smi the result is the same for all numbers 1061 // For shifting right a Smi the result is the same for all numbers
1090 // >= count_limit. 1062 // >= count_limit.
1091 __ SmiUntag(EAX); 1063 __ SmiUntag(EAX);
1092 // Negative counts throw exception. 1064 // Negative counts throw exception.
1093 __ cmpl(EAX, Immediate(0)); 1065 __ cmpl(EAX, Immediate(0));
1094 __ j(LESS, &fall_through, Assembler::kNearJump); 1066 __ j(LESS, &fall_through, Assembler::kNearJump);
1095 __ cmpl(EAX, count_limit); 1067 __ cmpl(EAX, count_limit);
1096 __ j(LESS_EQUAL, &shift_count_ok, Assembler::kNearJump); 1068 __ j(LESS_EQUAL, &shift_count_ok, Assembler::kNearJump);
1097 __ movl(EAX, count_limit); 1069 __ movl(EAX, count_limit);
1098 __ Bind(&shift_count_ok); 1070 __ Bind(&shift_count_ok);
1099 __ movl(ECX, EAX); // Shift amount must be in ECX. 1071 __ movl(ECX, EAX); // Shift amount must be in ECX.
1100 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Value. 1072 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Value.
1101 __ SmiUntag(EAX); // Value. 1073 __ SmiUntag(EAX); // Value.
1102 __ sarl(EAX, ECX); 1074 __ sarl(EAX, ECX);
1103 __ SmiTag(EAX); 1075 __ SmiTag(EAX);
1104 __ ret(); 1076 __ ret();
1105 __ Bind(&fall_through); 1077 __ Bind(&fall_through);
1106 return false;
1107 } 1078 }
1108 1079
1109 1080
1110 // Argument is Smi (receiver). 1081 // Argument is Smi (receiver).
1111 bool Intrinsifier::Smi_bitNegate(Assembler* assembler) { 1082 void Intrinsifier::Smi_bitNegate(Assembler* assembler) {
1112 __ movl(EAX, Address(ESP, + 1 * kWordSize)); // Index. 1083 __ movl(EAX, Address(ESP, + 1 * kWordSize)); // Index.
1113 __ notl(EAX); 1084 __ notl(EAX);
1114 __ andl(EAX, Immediate(~kSmiTagMask)); // Remove inverted smi-tag. 1085 __ andl(EAX, Immediate(~kSmiTagMask)); // Remove inverted smi-tag.
1115 __ ret(); 1086 __ ret();
1116 return true;
1117 } 1087 }
1118 1088
1119 1089
1120 // Check if the last argument is a double, jump to label 'is_smi' if smi 1090 // Check if the last argument is a double, jump to label 'is_smi' if smi
1121 // (easy to convert to double), otherwise jump to label 'not_double_smi', 1091 // (easy to convert to double), otherwise jump to label 'not_double_smi',
1122 // Returns the last argument in EAX. 1092 // Returns the last argument in EAX.
1123 static void TestLastArgumentIsDouble(Assembler* assembler, 1093 static void TestLastArgumentIsDouble(Assembler* assembler,
1124 Label* is_smi, 1094 Label* is_smi,
1125 Label* not_double_smi) { 1095 Label* not_double_smi) {
1126 __ movl(EAX, Address(ESP, + 1 * kWordSize)); 1096 __ movl(EAX, Address(ESP, + 1 * kWordSize));
1127 __ testl(EAX, Immediate(kSmiTagMask)); 1097 __ testl(EAX, Immediate(kSmiTagMask));
1128 __ j(ZERO, is_smi, Assembler::kNearJump); // Jump if Smi. 1098 __ j(ZERO, is_smi, Assembler::kNearJump); // Jump if Smi.
1129 __ CompareClassId(EAX, kDoubleCid, EBX); 1099 __ CompareClassId(EAX, kDoubleCid, EBX);
1130 __ j(NOT_EQUAL, not_double_smi, Assembler::kNearJump); 1100 __ j(NOT_EQUAL, not_double_smi, Assembler::kNearJump);
1131 // Fall through if double. 1101 // Fall through if double.
1132 } 1102 }
1133 1103
1134 1104
1135 // Both arguments on stack, arg0 (left) is a double, arg1 (right) is of unknown 1105 // Both arguments on stack, arg0 (left) is a double, arg1 (right) is of unknown
1136 // type. Return true or false object in the register EAX. Any NaN argument 1106 // type. Return true or false object in the register EAX. Any NaN argument
1137 // returns false. Any non-double arg1 causes control flow to fall through to the 1107 // returns false. Any non-double arg1 causes control flow to fall through to the
1138 // slow case (compiled method body). 1108 // slow case (compiled method body).
1139 static bool CompareDoubles(Assembler* assembler, Condition true_condition) { 1109 static void CompareDoubles(Assembler* assembler, Condition true_condition) {
1140 Label fall_through, is_false, is_true, is_smi, double_op; 1110 Label fall_through, is_false, is_true, is_smi, double_op;
1141 TestLastArgumentIsDouble(assembler, &is_smi, &fall_through); 1111 TestLastArgumentIsDouble(assembler, &is_smi, &fall_through);
1142 // Both arguments are double, right operand is in EAX. 1112 // Both arguments are double, right operand is in EAX.
1143 __ movsd(XMM1, FieldAddress(EAX, Double::value_offset())); 1113 __ movsd(XMM1, FieldAddress(EAX, Double::value_offset()));
1144 __ Bind(&double_op); 1114 __ Bind(&double_op);
1145 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Left argument. 1115 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Left argument.
1146 __ movsd(XMM0, FieldAddress(EAX, Double::value_offset())); 1116 __ movsd(XMM0, FieldAddress(EAX, Double::value_offset()));
1147 __ comisd(XMM0, XMM1); 1117 __ comisd(XMM0, XMM1);
1148 __ j(PARITY_EVEN, &is_false, Assembler::kNearJump); // NaN -> false; 1118 __ j(PARITY_EVEN, &is_false, Assembler::kNearJump); // NaN -> false;
1149 __ j(true_condition, &is_true, Assembler::kNearJump); 1119 __ j(true_condition, &is_true, Assembler::kNearJump);
1150 // Fall through false. 1120 // Fall through false.
1151 __ Bind(&is_false); 1121 __ Bind(&is_false);
1152 __ LoadObject(EAX, Bool::False()); 1122 __ LoadObject(EAX, Bool::False());
1153 __ ret(); 1123 __ ret();
1154 __ Bind(&is_true); 1124 __ Bind(&is_true);
1155 __ LoadObject(EAX, Bool::True()); 1125 __ LoadObject(EAX, Bool::True());
1156 __ ret(); 1126 __ ret();
1157 __ Bind(&is_smi); 1127 __ Bind(&is_smi);
1158 __ SmiUntag(EAX); 1128 __ SmiUntag(EAX);
1159 __ cvtsi2sd(XMM1, EAX); 1129 __ cvtsi2sd(XMM1, EAX);
1160 __ jmp(&double_op); 1130 __ jmp(&double_op);
1161 __ Bind(&fall_through); 1131 __ Bind(&fall_through);
1162 return false;
1163 } 1132 }
1164 1133
1165 1134
1166 // arg0 is Double, arg1 is unknown. 1135 // arg0 is Double, arg1 is unknown.
1167 bool Intrinsifier::Double_greaterThan(Assembler* assembler) { 1136 void Intrinsifier::Double_greaterThan(Assembler* assembler) {
1168 return CompareDoubles(assembler, ABOVE); 1137 return CompareDoubles(assembler, ABOVE);
1169 } 1138 }
1170 1139
1171 1140
1172 // arg0 is Double, arg1 is unknown. 1141 // arg0 is Double, arg1 is unknown.
1173 bool Intrinsifier::Double_greaterEqualThan(Assembler* assembler) { 1142 void Intrinsifier::Double_greaterEqualThan(Assembler* assembler) {
1174 return CompareDoubles(assembler, ABOVE_EQUAL); 1143 return CompareDoubles(assembler, ABOVE_EQUAL);
1175 } 1144 }
1176 1145
1177 1146
1178 // arg0 is Double, arg1 is unknown. 1147 // arg0 is Double, arg1 is unknown.
1179 bool Intrinsifier::Double_lessThan(Assembler* assembler) { 1148 void Intrinsifier::Double_lessThan(Assembler* assembler) {
1180 return CompareDoubles(assembler, BELOW); 1149 return CompareDoubles(assembler, BELOW);
1181 } 1150 }
1182 1151
1183 1152
1184 // arg0 is Double, arg1 is unknown. 1153 // arg0 is Double, arg1 is unknown.
1185 bool Intrinsifier::Double_equal(Assembler* assembler) { 1154 void Intrinsifier::Double_equal(Assembler* assembler) {
1186 return CompareDoubles(assembler, EQUAL); 1155 return CompareDoubles(assembler, EQUAL);
1187 } 1156 }
1188 1157
1189 1158
1190 // arg0 is Double, arg1 is unknown. 1159 // arg0 is Double, arg1 is unknown.
1191 bool Intrinsifier::Double_lessEqualThan(Assembler* assembler) { 1160 void Intrinsifier::Double_lessEqualThan(Assembler* assembler) {
1192 return CompareDoubles(assembler, BELOW_EQUAL); 1161 return CompareDoubles(assembler, BELOW_EQUAL);
1193 } 1162 }
1194 1163
1195 1164
1196 // Expects left argument to be double (receiver). Right argument is unknown. 1165 // Expects left argument to be double (receiver). Right argument is unknown.
1197 // Both arguments are on stack. 1166 // Both arguments are on stack.
1198 static bool DoubleArithmeticOperations(Assembler* assembler, Token::Kind kind) { 1167 static void DoubleArithmeticOperations(Assembler* assembler, Token::Kind kind) {
1199 Label fall_through; 1168 Label fall_through;
1200 TestLastArgumentIsDouble(assembler, &fall_through, &fall_through); 1169 TestLastArgumentIsDouble(assembler, &fall_through, &fall_through);
1201 // Both arguments are double, right operand is in EAX. 1170 // Both arguments are double, right operand is in EAX.
1202 __ movsd(XMM1, FieldAddress(EAX, Double::value_offset())); 1171 __ movsd(XMM1, FieldAddress(EAX, Double::value_offset()));
1203 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Left argument. 1172 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Left argument.
1204 __ movsd(XMM0, FieldAddress(EAX, Double::value_offset())); 1173 __ movsd(XMM0, FieldAddress(EAX, Double::value_offset()));
1205 switch (kind) { 1174 switch (kind) {
1206 case Token::kADD: __ addsd(XMM0, XMM1); break; 1175 case Token::kADD: __ addsd(XMM0, XMM1); break;
1207 case Token::kSUB: __ subsd(XMM0, XMM1); break; 1176 case Token::kSUB: __ subsd(XMM0, XMM1); break;
1208 case Token::kMUL: __ mulsd(XMM0, XMM1); break; 1177 case Token::kMUL: __ mulsd(XMM0, XMM1); break;
1209 case Token::kDIV: __ divsd(XMM0, XMM1); break; 1178 case Token::kDIV: __ divsd(XMM0, XMM1); break;
1210 default: UNREACHABLE(); 1179 default: UNREACHABLE();
1211 } 1180 }
1212 const Class& double_class = Class::Handle( 1181 const Class& double_class = Class::Handle(
1213 Isolate::Current()->object_store()->double_class()); 1182 Isolate::Current()->object_store()->double_class());
1214 __ TryAllocate(double_class, 1183 __ TryAllocate(double_class,
1215 &fall_through, 1184 &fall_through,
1216 Assembler::kNearJump, 1185 Assembler::kNearJump,
1217 EAX); // Result register. 1186 EAX); // Result register.
1218 __ movsd(FieldAddress(EAX, Double::value_offset()), XMM0); 1187 __ movsd(FieldAddress(EAX, Double::value_offset()), XMM0);
1219 __ ret(); 1188 __ ret();
1220 __ Bind(&fall_through); 1189 __ Bind(&fall_through);
1221 return false;
1222 } 1190 }
1223 1191
1224 1192
1225 bool Intrinsifier::Double_add(Assembler* assembler) { 1193 void Intrinsifier::Double_add(Assembler* assembler) {
1226 return DoubleArithmeticOperations(assembler, Token::kADD); 1194 return DoubleArithmeticOperations(assembler, Token::kADD);
1227 } 1195 }
1228 1196
1229 1197
1230 bool Intrinsifier::Double_mul(Assembler* assembler) { 1198 void Intrinsifier::Double_mul(Assembler* assembler) {
1231 return DoubleArithmeticOperations(assembler, Token::kMUL); 1199 return DoubleArithmeticOperations(assembler, Token::kMUL);
1232 } 1200 }
1233 1201
1234 1202
1235 bool Intrinsifier::Double_sub(Assembler* assembler) { 1203 void Intrinsifier::Double_sub(Assembler* assembler) {
1236 return DoubleArithmeticOperations(assembler, Token::kSUB); 1204 return DoubleArithmeticOperations(assembler, Token::kSUB);
1237 } 1205 }
1238 1206
1239 1207
1240 bool Intrinsifier::Double_div(Assembler* assembler) { 1208 void Intrinsifier::Double_div(Assembler* assembler) {
1241 return DoubleArithmeticOperations(assembler, Token::kDIV); 1209 return DoubleArithmeticOperations(assembler, Token::kDIV);
1242 } 1210 }
1243 1211
1244 1212
1245 // Left is double right is integer (Bigint, Mint or Smi) 1213 // Left is double right is integer (Bigint, Mint or Smi)
1246 bool Intrinsifier::Double_mulFromInteger(Assembler* assembler) { 1214 void Intrinsifier::Double_mulFromInteger(Assembler* assembler) {
1247 Label fall_through; 1215 Label fall_through;
1248 // Only Smi-s allowed. 1216 // Only Smi-s allowed.
1249 __ movl(EAX, Address(ESP, + 1 * kWordSize)); 1217 __ movl(EAX, Address(ESP, + 1 * kWordSize));
1250 __ testl(EAX, Immediate(kSmiTagMask)); 1218 __ testl(EAX, Immediate(kSmiTagMask));
1251 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); 1219 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump);
1252 // Is Smi. 1220 // Is Smi.
1253 __ SmiUntag(EAX); 1221 __ SmiUntag(EAX);
1254 __ cvtsi2sd(XMM1, EAX); 1222 __ cvtsi2sd(XMM1, EAX);
1255 __ movl(EAX, Address(ESP, + 2 * kWordSize)); 1223 __ movl(EAX, Address(ESP, + 2 * kWordSize));
1256 __ movsd(XMM0, FieldAddress(EAX, Double::value_offset())); 1224 __ movsd(XMM0, FieldAddress(EAX, Double::value_offset()));
1257 __ mulsd(XMM0, XMM1); 1225 __ mulsd(XMM0, XMM1);
1258 const Class& double_class = Class::Handle( 1226 const Class& double_class = Class::Handle(
1259 Isolate::Current()->object_store()->double_class()); 1227 Isolate::Current()->object_store()->double_class());
1260 __ TryAllocate(double_class, 1228 __ TryAllocate(double_class,
1261 &fall_through, 1229 &fall_through,
1262 Assembler::kNearJump, 1230 Assembler::kNearJump,
1263 EAX); // Result register. 1231 EAX); // Result register.
1264 __ movsd(FieldAddress(EAX, Double::value_offset()), XMM0); 1232 __ movsd(FieldAddress(EAX, Double::value_offset()), XMM0);
1265 __ ret(); 1233 __ ret();
1266 __ Bind(&fall_through); 1234 __ Bind(&fall_through);
1267 return false;
1268 } 1235 }
1269 1236
1270 1237
1271 bool Intrinsifier::Double_fromInteger(Assembler* assembler) { 1238 void Intrinsifier::Double_fromInteger(Assembler* assembler) {
1272 Label fall_through; 1239 Label fall_through;
1273 __ movl(EAX, Address(ESP, +1 * kWordSize)); 1240 __ movl(EAX, Address(ESP, +1 * kWordSize));
1274 __ testl(EAX, Immediate(kSmiTagMask)); 1241 __ testl(EAX, Immediate(kSmiTagMask));
1275 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); 1242 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump);
1276 // Is Smi. 1243 // Is Smi.
1277 __ SmiUntag(EAX); 1244 __ SmiUntag(EAX);
1278 __ cvtsi2sd(XMM0, EAX); 1245 __ cvtsi2sd(XMM0, EAX);
1279 const Class& double_class = Class::Handle( 1246 const Class& double_class = Class::Handle(
1280 Isolate::Current()->object_store()->double_class()); 1247 Isolate::Current()->object_store()->double_class());
1281 __ TryAllocate(double_class, 1248 __ TryAllocate(double_class,
1282 &fall_through, 1249 &fall_through,
1283 Assembler::kNearJump, 1250 Assembler::kNearJump,
1284 EAX); // Result register. 1251 EAX); // Result register.
1285 __ movsd(FieldAddress(EAX, Double::value_offset()), XMM0); 1252 __ movsd(FieldAddress(EAX, Double::value_offset()), XMM0);
1286 __ ret(); 1253 __ ret();
1287 __ Bind(&fall_through); 1254 __ Bind(&fall_through);
1288 return false;
1289 } 1255 }
1290 1256
1291 1257
1292 bool Intrinsifier::Double_getIsNaN(Assembler* assembler) { 1258 void Intrinsifier::Double_getIsNaN(Assembler* assembler) {
1293 Label is_true; 1259 Label is_true;
1294 __ movl(EAX, Address(ESP, +1 * kWordSize)); 1260 __ movl(EAX, Address(ESP, +1 * kWordSize));
1295 __ movsd(XMM0, FieldAddress(EAX, Double::value_offset())); 1261 __ movsd(XMM0, FieldAddress(EAX, Double::value_offset()));
1296 __ comisd(XMM0, XMM0); 1262 __ comisd(XMM0, XMM0);
1297 __ j(PARITY_EVEN, &is_true, Assembler::kNearJump); // NaN -> true; 1263 __ j(PARITY_EVEN, &is_true, Assembler::kNearJump); // NaN -> true;
1298 __ LoadObject(EAX, Bool::False()); 1264 __ LoadObject(EAX, Bool::False());
1299 __ ret(); 1265 __ ret();
1300 __ Bind(&is_true); 1266 __ Bind(&is_true);
1301 __ LoadObject(EAX, Bool::True()); 1267 __ LoadObject(EAX, Bool::True());
1302 __ ret(); 1268 __ ret();
1303 return true; // Method is complete, no slow case.
1304 } 1269 }
1305 1270
1306 1271
1307 bool Intrinsifier::Double_getIsNegative(Assembler* assembler) { 1272 void Intrinsifier::Double_getIsNegative(Assembler* assembler) {
1308 Label is_false, is_true, is_zero; 1273 Label is_false, is_true, is_zero;
1309 __ movl(EAX, Address(ESP, +1 * kWordSize)); 1274 __ movl(EAX, Address(ESP, +1 * kWordSize));
1310 __ movsd(XMM0, FieldAddress(EAX, Double::value_offset())); 1275 __ movsd(XMM0, FieldAddress(EAX, Double::value_offset()));
1311 __ xorpd(XMM1, XMM1); // 0.0 -> XMM1. 1276 __ xorpd(XMM1, XMM1); // 0.0 -> XMM1.
1312 __ comisd(XMM0, XMM1); 1277 __ comisd(XMM0, XMM1);
1313 __ j(PARITY_EVEN, &is_false, Assembler::kNearJump); // NaN -> false. 1278 __ j(PARITY_EVEN, &is_false, Assembler::kNearJump); // NaN -> false.
1314 __ j(EQUAL, &is_zero, Assembler::kNearJump); // Check for negative zero. 1279 __ j(EQUAL, &is_zero, Assembler::kNearJump); // Check for negative zero.
1315 __ j(ABOVE_EQUAL, &is_false, Assembler::kNearJump); // >= 0 -> false. 1280 __ j(ABOVE_EQUAL, &is_false, Assembler::kNearJump); // >= 0 -> false.
1316 __ Bind(&is_true); 1281 __ Bind(&is_true);
1317 __ LoadObject(EAX, Bool::True()); 1282 __ LoadObject(EAX, Bool::True());
1318 __ ret(); 1283 __ ret();
1319 __ Bind(&is_false); 1284 __ Bind(&is_false);
1320 __ LoadObject(EAX, Bool::False()); 1285 __ LoadObject(EAX, Bool::False());
1321 __ ret(); 1286 __ ret();
1322 __ Bind(&is_zero); 1287 __ Bind(&is_zero);
1323 // Check for negative zero (get the sign bit). 1288 // Check for negative zero (get the sign bit).
1324 __ movmskpd(EAX, XMM0); 1289 __ movmskpd(EAX, XMM0);
1325 __ testl(EAX, Immediate(1)); 1290 __ testl(EAX, Immediate(1));
1326 __ j(NOT_ZERO, &is_true, Assembler::kNearJump); 1291 __ j(NOT_ZERO, &is_true, Assembler::kNearJump);
1327 __ jmp(&is_false, Assembler::kNearJump); 1292 __ jmp(&is_false, Assembler::kNearJump);
1328 return true; // Method is complete, no slow case.
1329 } 1293 }
1330 1294
1331 1295
1332 bool Intrinsifier::Double_toInt(Assembler* assembler) { 1296 void Intrinsifier::Double_toInt(Assembler* assembler) {
1333 __ movl(EAX, Address(ESP, +1 * kWordSize)); 1297 __ movl(EAX, Address(ESP, +1 * kWordSize));
1334 __ movsd(XMM0, FieldAddress(EAX, Double::value_offset())); 1298 __ movsd(XMM0, FieldAddress(EAX, Double::value_offset()));
1335 __ cvttsd2si(EAX, XMM0); 1299 __ cvttsd2si(EAX, XMM0);
1336 // Overflow is signalled with minint. 1300 // Overflow is signalled with minint.
1337 Label fall_through; 1301 Label fall_through;
1338 // Check for overflow and that it fits into Smi. 1302 // Check for overflow and that it fits into Smi.
1339 __ cmpl(EAX, Immediate(0xC0000000)); 1303 __ cmpl(EAX, Immediate(0xC0000000));
1340 __ j(NEGATIVE, &fall_through, Assembler::kNearJump); 1304 __ j(NEGATIVE, &fall_through, Assembler::kNearJump);
1341 __ SmiTag(EAX); 1305 __ SmiTag(EAX);
1342 __ ret(); 1306 __ ret();
1343 __ Bind(&fall_through); 1307 __ Bind(&fall_through);
1344 return false;
1345 } 1308 }
1346 1309
1347 1310
1348 // Argument type is not known 1311 // Argument type is not known
1349 bool Intrinsifier::Math_sqrt(Assembler* assembler) { 1312 void Intrinsifier::Math_sqrt(Assembler* assembler) {
1350 Label fall_through, is_smi, double_op; 1313 Label fall_through, is_smi, double_op;
1351 TestLastArgumentIsDouble(assembler, &is_smi, &fall_through); 1314 TestLastArgumentIsDouble(assembler, &is_smi, &fall_through);
1352 // Argument is double and is in EAX. 1315 // Argument is double and is in EAX.
1353 __ movsd(XMM1, FieldAddress(EAX, Double::value_offset())); 1316 __ movsd(XMM1, FieldAddress(EAX, Double::value_offset()));
1354 __ Bind(&double_op); 1317 __ Bind(&double_op);
1355 __ sqrtsd(XMM0, XMM1); 1318 __ sqrtsd(XMM0, XMM1);
1356 const Class& double_class = Class::Handle( 1319 const Class& double_class = Class::Handle(
1357 Isolate::Current()->object_store()->double_class()); 1320 Isolate::Current()->object_store()->double_class());
1358 __ TryAllocate(double_class, 1321 __ TryAllocate(double_class,
1359 &fall_through, 1322 &fall_through,
1360 Assembler::kNearJump, 1323 Assembler::kNearJump,
1361 EAX); // Result register. 1324 EAX); // Result register.
1362 __ movsd(FieldAddress(EAX, Double::value_offset()), XMM0); 1325 __ movsd(FieldAddress(EAX, Double::value_offset()), XMM0);
1363 __ ret(); 1326 __ ret();
1364 __ Bind(&is_smi); 1327 __ Bind(&is_smi);
1365 __ SmiUntag(EAX); 1328 __ SmiUntag(EAX);
1366 __ cvtsi2sd(XMM1, EAX); 1329 __ cvtsi2sd(XMM1, EAX);
1367 __ jmp(&double_op); 1330 __ jmp(&double_op);
1368 __ Bind(&fall_through); 1331 __ Bind(&fall_through);
1369 return false;
1370 } 1332 }
1371 1333
1372 1334
1373 enum TrigonometricFunctions { 1335 enum TrigonometricFunctions {
1374 kSine, 1336 kSine,
1375 kCosine, 1337 kCosine,
1376 }; 1338 };
1377 1339
1378 1340
1379 static void EmitTrigonometric(Assembler* assembler, 1341 static void EmitTrigonometric(Assembler* assembler,
(...skipping 27 matching lines...) Expand all
1407 __ jmp(&double_op); 1369 __ jmp(&double_op);
1408 1370
1409 __ Bind(&alloc_failed); 1371 __ Bind(&alloc_failed);
1410 __ ffree(0); 1372 __ ffree(0);
1411 __ fincstp(); 1373 __ fincstp();
1412 1374
1413 __ Bind(&fall_through); 1375 __ Bind(&fall_through);
1414 } 1376 }
1415 1377
1416 1378
1417 bool Intrinsifier::Math_sin(Assembler* assembler) { 1379 void Intrinsifier::Math_sin(Assembler* assembler) {
1418 EmitTrigonometric(assembler, kSine); 1380 EmitTrigonometric(assembler, kSine);
1419 return false; // Compile method for slow case.
1420 } 1381 }
1421 1382
1422 1383
1423 bool Intrinsifier::Math_cos(Assembler* assembler) { 1384 void Intrinsifier::Math_cos(Assembler* assembler) {
1424 EmitTrigonometric(assembler, kCosine); 1385 EmitTrigonometric(assembler, kCosine);
1425 return false; // Compile method for slow case.
1426 } 1386 }
1427 1387
1428 1388
1429 // var state = ((_A * (_state[kSTATE_LO])) + _state[kSTATE_HI]) & _MASK_64; 1389 // var state = ((_A * (_state[kSTATE_LO])) + _state[kSTATE_HI]) & _MASK_64;
1430 // _state[kSTATE_LO] = state & _MASK_32; 1390 // _state[kSTATE_LO] = state & _MASK_32;
1431 // _state[kSTATE_HI] = state >> 32; 1391 // _state[kSTATE_HI] = state >> 32;
1432 bool Intrinsifier::Random_nextState(Assembler* assembler) { 1392 void Intrinsifier::Random_nextState(Assembler* assembler) {
1433 const Library& math_lib = Library::Handle(Library::MathLibrary()); 1393 const Library& math_lib = Library::Handle(Library::MathLibrary());
1434 ASSERT(!math_lib.IsNull()); 1394 ASSERT(!math_lib.IsNull());
1435 const Class& random_class = Class::Handle( 1395 const Class& random_class = Class::Handle(
1436 math_lib.LookupClassAllowPrivate(Symbols::_Random(), NULL)); 1396 math_lib.LookupClassAllowPrivate(Symbols::_Random(), NULL));
1437 ASSERT(!random_class.IsNull()); 1397 ASSERT(!random_class.IsNull());
1438 const Field& state_field = Field::ZoneHandle( 1398 const Field& state_field = Field::ZoneHandle(
1439 random_class.LookupInstanceField(Symbols::_state())); 1399 random_class.LookupInstanceField(Symbols::_state()));
1440 ASSERT(!state_field.IsNull()); 1400 ASSERT(!state_field.IsNull());
1441 const Field& random_A_field = Field::ZoneHandle( 1401 const Field& random_A_field = Field::ZoneHandle(
1442 random_class.LookupStaticField(Symbols::_A())); 1402 random_class.LookupStaticField(Symbols::_A()));
(...skipping 18 matching lines...) Expand all
1461 EBX, 1421 EBX,
1462 1); 1422 1);
1463 __ movl(EAX, Immediate(a_int32_value)); 1423 __ movl(EAX, Immediate(a_int32_value));
1464 // 64-bit multiply EAX * value -> EDX:EAX. 1424 // 64-bit multiply EAX * value -> EDX:EAX.
1465 __ mull(addr_0); 1425 __ mull(addr_0);
1466 __ addl(EAX, addr_1); 1426 __ addl(EAX, addr_1);
1467 __ adcl(EDX, Immediate(0)); 1427 __ adcl(EDX, Immediate(0));
1468 __ movl(addr_1, EDX); 1428 __ movl(addr_1, EDX);
1469 __ movl(addr_0, EAX); 1429 __ movl(addr_0, EAX);
1470 __ ret(); 1430 __ ret();
1471 return true;
1472 } 1431 }
1473 1432
1474 1433
1475 // Identity comparison. 1434 // Identity comparison.
1476 bool Intrinsifier::Object_equal(Assembler* assembler) { 1435 void Intrinsifier::Object_equal(Assembler* assembler) {
1477 Label is_true; 1436 Label is_true;
1478 __ movl(EAX, Address(ESP, + 1 * kWordSize)); 1437 __ movl(EAX, Address(ESP, + 1 * kWordSize));
1479 __ cmpl(EAX, Address(ESP, + 2 * kWordSize)); 1438 __ cmpl(EAX, Address(ESP, + 2 * kWordSize));
1480 __ j(EQUAL, &is_true, Assembler::kNearJump); 1439 __ j(EQUAL, &is_true, Assembler::kNearJump);
1481 __ LoadObject(EAX, Bool::False()); 1440 __ LoadObject(EAX, Bool::False());
1482 __ ret(); 1441 __ ret();
1483 __ Bind(&is_true); 1442 __ Bind(&is_true);
1484 __ LoadObject(EAX, Bool::True()); 1443 __ LoadObject(EAX, Bool::True());
1485 __ ret(); 1444 __ ret();
1486 return true;
1487 } 1445 }
1488 1446
1489 1447
1490 bool Intrinsifier::String_getHashCode(Assembler* assembler) { 1448 void Intrinsifier::String_getHashCode(Assembler* assembler) {
1491 Label fall_through; 1449 Label fall_through;
1492 __ movl(EAX, Address(ESP, + 1 * kWordSize)); // String object. 1450 __ movl(EAX, Address(ESP, + 1 * kWordSize)); // String object.
1493 __ movl(EAX, FieldAddress(EAX, String::hash_offset())); 1451 __ movl(EAX, FieldAddress(EAX, String::hash_offset()));
1494 __ cmpl(EAX, Immediate(0)); 1452 __ cmpl(EAX, Immediate(0));
1495 __ j(EQUAL, &fall_through, Assembler::kNearJump); 1453 __ j(EQUAL, &fall_through, Assembler::kNearJump);
1496 __ ret(); 1454 __ ret();
1497 __ Bind(&fall_through); 1455 __ Bind(&fall_through);
1498 // Hash not yet computed. 1456 // Hash not yet computed.
1499 return false;
1500 } 1457 }
1501 1458
1502 1459
1503 bool Intrinsifier::String_getLength(Assembler* assembler) { 1460 void Intrinsifier::String_getLength(Assembler* assembler) {
1504 __ movl(EAX, Address(ESP, + 1 * kWordSize)); // String object. 1461 __ movl(EAX, Address(ESP, + 1 * kWordSize)); // String object.
1505 __ movl(EAX, FieldAddress(EAX, String::length_offset())); 1462 __ movl(EAX, FieldAddress(EAX, String::length_offset()));
1506 __ ret(); 1463 __ ret();
1507 return true;
1508 } 1464 }
1509 1465
1510 1466
1511 bool Intrinsifier::String_codeUnitAt(Assembler* assembler) { 1467 void Intrinsifier::String_codeUnitAt(Assembler* assembler) {
1512 Label fall_through, try_two_byte_string; 1468 Label fall_through, try_two_byte_string;
1513 __ movl(EBX, Address(ESP, + 1 * kWordSize)); // Index. 1469 __ movl(EBX, Address(ESP, + 1 * kWordSize)); // Index.
1514 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // String. 1470 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // String.
1515 __ testl(EBX, Immediate(kSmiTagMask)); 1471 __ testl(EBX, Immediate(kSmiTagMask));
1516 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi index. 1472 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi index.
1517 // Range check. 1473 // Range check.
1518 __ cmpl(EBX, FieldAddress(EAX, String::length_offset())); 1474 __ cmpl(EBX, FieldAddress(EAX, String::length_offset()));
1519 // Runtime throws exception. 1475 // Runtime throws exception.
1520 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump); 1476 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump);
1521 __ CompareClassId(EAX, kOneByteStringCid, EDI); 1477 __ CompareClassId(EAX, kOneByteStringCid, EDI);
1522 __ j(NOT_EQUAL, &try_two_byte_string, Assembler::kNearJump); 1478 __ j(NOT_EQUAL, &try_two_byte_string, Assembler::kNearJump);
1523 __ SmiUntag(EBX); 1479 __ SmiUntag(EBX);
1524 __ movzxb(EAX, FieldAddress(EAX, EBX, TIMES_1, OneByteString::data_offset())); 1480 __ movzxb(EAX, FieldAddress(EAX, EBX, TIMES_1, OneByteString::data_offset()));
1525 __ SmiTag(EAX); 1481 __ SmiTag(EAX);
1526 __ ret(); 1482 __ ret();
1527 1483
1528 __ Bind(&try_two_byte_string); 1484 __ Bind(&try_two_byte_string);
1529 __ CompareClassId(EAX, kTwoByteStringCid, EDI); 1485 __ CompareClassId(EAX, kTwoByteStringCid, EDI);
1530 __ j(NOT_EQUAL, &fall_through, Assembler::kNearJump); 1486 __ j(NOT_EQUAL, &fall_through, Assembler::kNearJump);
1531 ASSERT(kSmiTagShift == 1); 1487 ASSERT(kSmiTagShift == 1);
1532 __ movzxw(EAX, FieldAddress(EAX, EBX, TIMES_1, OneByteString::data_offset())); 1488 __ movzxw(EAX, FieldAddress(EAX, EBX, TIMES_1, OneByteString::data_offset()));
1533 __ SmiTag(EAX); 1489 __ SmiTag(EAX);
1534 __ ret(); 1490 __ ret();
1535 1491
1536 __ Bind(&fall_through); 1492 __ Bind(&fall_through);
1537 return false;
1538 } 1493 }
1539 1494
1540 1495
1541 bool Intrinsifier::String_getIsEmpty(Assembler* assembler) { 1496 void Intrinsifier::String_getIsEmpty(Assembler* assembler) {
1542 Label is_true; 1497 Label is_true;
1543 // Get length. 1498 // Get length.
1544 __ movl(EAX, Address(ESP, + 1 * kWordSize)); // String object. 1499 __ movl(EAX, Address(ESP, + 1 * kWordSize)); // String object.
1545 __ movl(EAX, FieldAddress(EAX, String::length_offset())); 1500 __ movl(EAX, FieldAddress(EAX, String::length_offset()));
1546 __ cmpl(EAX, Immediate(Smi::RawValue(0))); 1501 __ cmpl(EAX, Immediate(Smi::RawValue(0)));
1547 __ j(EQUAL, &is_true, Assembler::kNearJump); 1502 __ j(EQUAL, &is_true, Assembler::kNearJump);
1548 __ LoadObject(EAX, Bool::False()); 1503 __ LoadObject(EAX, Bool::False());
1549 __ ret(); 1504 __ ret();
1550 __ Bind(&is_true); 1505 __ Bind(&is_true);
1551 __ LoadObject(EAX, Bool::True()); 1506 __ LoadObject(EAX, Bool::True());
1552 __ ret(); 1507 __ ret();
1553 return false;
1554 } 1508 }
1555 1509
1556 1510
1557 bool Intrinsifier::OneByteString_getHashCode(Assembler* assembler) { 1511 void Intrinsifier::OneByteString_getHashCode(Assembler* assembler) {
1558 Label compute_hash; 1512 Label compute_hash;
1559 __ movl(EBX, Address(ESP, + 1 * kWordSize)); // OneByteString object. 1513 __ movl(EBX, Address(ESP, + 1 * kWordSize)); // OneByteString object.
1560 __ movl(EAX, FieldAddress(EBX, String::hash_offset())); 1514 __ movl(EAX, FieldAddress(EBX, String::hash_offset()));
1561 __ cmpl(EAX, Immediate(0)); 1515 __ cmpl(EAX, Immediate(0));
1562 __ j(EQUAL, &compute_hash, Assembler::kNearJump); 1516 __ j(EQUAL, &compute_hash, Assembler::kNearJump);
1563 __ ret(); 1517 __ ret();
1564 1518
1565 __ Bind(&compute_hash); 1519 __ Bind(&compute_hash);
1566 // Hash not yet computed, use algorithm of class StringHasher. 1520 // Hash not yet computed, use algorithm of class StringHasher.
1567 __ movl(ECX, FieldAddress(EBX, String::length_offset())); 1521 __ movl(ECX, FieldAddress(EBX, String::length_offset()));
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
1613 Immediate(((static_cast<intptr_t>(1) << String::kHashBits) - 1))); 1567 Immediate(((static_cast<intptr_t>(1) << String::kHashBits) - 1)));
1614 1568
1615 // return hash_ == 0 ? 1 : hash_; 1569 // return hash_ == 0 ? 1 : hash_;
1616 __ cmpl(EAX, Immediate(0)); 1570 __ cmpl(EAX, Immediate(0));
1617 __ j(NOT_EQUAL, &set_hash_code, Assembler::kNearJump); 1571 __ j(NOT_EQUAL, &set_hash_code, Assembler::kNearJump);
1618 __ incl(EAX); 1572 __ incl(EAX);
1619 __ Bind(&set_hash_code); 1573 __ Bind(&set_hash_code);
1620 __ SmiTag(EAX); 1574 __ SmiTag(EAX);
1621 __ movl(FieldAddress(EBX, String::hash_offset()), EAX); 1575 __ movl(FieldAddress(EBX, String::hash_offset()), EAX);
1622 __ ret(); 1576 __ ret();
1623 return true;
1624 } 1577 }
1625 1578
1626 1579
1627 // Allocates one-byte string of length 'end - start'. The content is not 1580 // Allocates one-byte string of length 'end - start'. The content is not
1628 // initialized. 'length-reg' contains tagged length. 1581 // initialized. 'length-reg' contains tagged length.
1629 // Returns new string as tagged pointer in EAX. 1582 // Returns new string as tagged pointer in EAX.
1630 static void TryAllocateOnebyteString(Assembler* assembler, 1583 static void TryAllocateOnebyteString(Assembler* assembler,
1631 Label* ok, 1584 Label* ok,
1632 Label* failure, 1585 Label* failure,
1633 Register length_reg) { 1586 Register length_reg) {
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
1697 __ Bind(&pop_and_fail); 1650 __ Bind(&pop_and_fail);
1698 __ popl(EDI); 1651 __ popl(EDI);
1699 __ jmp(failure); 1652 __ jmp(failure);
1700 } 1653 }
1701 1654
1702 1655
1703 // Arg0: Onebyte String 1656 // Arg0: Onebyte String
1704 // Arg1: Start index as Smi. 1657 // Arg1: Start index as Smi.
1705 // Arg2: End index as Smi. 1658 // Arg2: End index as Smi.
1706 // The indexes must be valid. 1659 // The indexes must be valid.
1707 bool Intrinsifier::OneByteString_substringUnchecked(Assembler* assembler) { 1660 void Intrinsifier::OneByteString_substringUnchecked(Assembler* assembler) {
1708 const intptr_t kStringOffset = 3 * kWordSize; 1661 const intptr_t kStringOffset = 3 * kWordSize;
1709 const intptr_t kStartIndexOffset = 2 * kWordSize; 1662 const intptr_t kStartIndexOffset = 2 * kWordSize;
1710 const intptr_t kEndIndexOffset = 1 * kWordSize; 1663 const intptr_t kEndIndexOffset = 1 * kWordSize;
1711 Label fall_through, ok; 1664 Label fall_through, ok;
1712 __ movl(EDI, Address(ESP, + kEndIndexOffset)); 1665 __ movl(EDI, Address(ESP, + kEndIndexOffset));
1713 __ subl(EDI, Address(ESP, + kStartIndexOffset)); 1666 __ subl(EDI, Address(ESP, + kStartIndexOffset));
1714 TryAllocateOnebyteString(assembler, &ok, &fall_through, EDI); 1667 TryAllocateOnebyteString(assembler, &ok, &fall_through, EDI);
1715 __ Bind(&ok); 1668 __ Bind(&ok);
1716 // EAX: new string as tagged pointer. 1669 // EAX: new string as tagged pointer.
1717 // Copy string. 1670 // Copy string.
(...skipping 16 matching lines...) Expand all
1734 __ jmp(&check, Assembler::kNearJump); 1687 __ jmp(&check, Assembler::kNearJump);
1735 __ Bind(&loop); 1688 __ Bind(&loop);
1736 __ movzxb(EBX, Address(EDI, EDX, TIMES_1, 0)); 1689 __ movzxb(EBX, Address(EDI, EDX, TIMES_1, 0));
1737 __ movb(FieldAddress(EAX, EDX, TIMES_1, OneByteString::data_offset()), BL); 1690 __ movb(FieldAddress(EAX, EDX, TIMES_1, OneByteString::data_offset()), BL);
1738 __ incl(EDX); 1691 __ incl(EDX);
1739 __ Bind(&check); 1692 __ Bind(&check);
1740 __ cmpl(EDX, ECX); 1693 __ cmpl(EDX, ECX);
1741 __ j(LESS, &loop, Assembler::kNearJump); 1694 __ j(LESS, &loop, Assembler::kNearJump);
1742 __ ret(); 1695 __ ret();
1743 __ Bind(&fall_through); 1696 __ Bind(&fall_through);
1744 return false;
1745 } 1697 }
1746 1698
1747 1699
1748 bool Intrinsifier::OneByteString_setAt(Assembler* assembler) { 1700 void Intrinsifier::OneByteString_setAt(Assembler* assembler) {
1749 __ movl(ECX, Address(ESP, + 1 * kWordSize)); // Value. 1701 __ movl(ECX, Address(ESP, + 1 * kWordSize)); // Value.
1750 __ movl(EBX, Address(ESP, + 2 * kWordSize)); // Index. 1702 __ movl(EBX, Address(ESP, + 2 * kWordSize)); // Index.
1751 __ movl(EAX, Address(ESP, + 3 * kWordSize)); // OneByteString. 1703 __ movl(EAX, Address(ESP, + 3 * kWordSize)); // OneByteString.
1752 __ SmiUntag(EBX); 1704 __ SmiUntag(EBX);
1753 __ SmiUntag(ECX); 1705 __ SmiUntag(ECX);
1754 __ movb(FieldAddress(EAX, EBX, TIMES_1, OneByteString::data_offset()), CL); 1706 __ movb(FieldAddress(EAX, EBX, TIMES_1, OneByteString::data_offset()), CL);
1755 __ ret(); 1707 __ ret();
1756 return true;
1757 } 1708 }
1758 1709
1759 1710
1760 bool Intrinsifier::OneByteString_allocate(Assembler* assembler) { 1711 void Intrinsifier::OneByteString_allocate(Assembler* assembler) {
1761 __ movl(EDI, Address(ESP, + 1 * kWordSize)); // Length. 1712 __ movl(EDI, Address(ESP, + 1 * kWordSize)); // Length.
1762 Label fall_through, ok; 1713 Label fall_through, ok;
1763 TryAllocateOnebyteString(assembler, &ok, &fall_through, EDI); 1714 TryAllocateOnebyteString(assembler, &ok, &fall_through, EDI);
1764 // EDI: Start address to copy from (untagged). 1715 // EDI: Start address to copy from (untagged).
1765 1716
1766 __ Bind(&ok); 1717 __ Bind(&ok);
1767 __ ret(); 1718 __ ret();
1768 1719
1769 __ Bind(&fall_through); 1720 __ Bind(&fall_through);
1770 return false;
1771 } 1721 }
1772 1722
1773 #undef __ 1723 #undef __
1774 } // namespace dart 1724 } // namespace dart
1775 1725
1776 #endif // defined TARGET_ARCH_IA32 1726 #endif // defined TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « runtime/vm/intrinsifier_arm.cc ('k') | runtime/vm/intrinsifier_mips.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698