| OLD | NEW |
| 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 11 matching lines...) Expand all Loading... |
| 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 | 31 |
| 32 void Intrinsifier::ObjectArrayLength(Assembler* assembler) { | 32 intptr_t Intrinsifier::ParameterSlotFromSp() { return 0; } |
| 33 __ movl(EAX, Address(ESP, + 1 * kWordSize)); | |
| 34 __ movl(EAX, FieldAddress(EAX, Array::length_offset())); | |
| 35 __ ret(); | |
| 36 } | |
| 37 | |
| 38 | |
| 39 void Intrinsifier::ImmutableArrayLength(Assembler* assembler) { | |
| 40 ObjectArrayLength(assembler); | |
| 41 } | |
| 42 | |
| 43 | |
| 44 void Intrinsifier::ObjectArrayGetIndexed(Assembler* assembler) { | |
| 45 Label fall_through; | |
| 46 __ movl(EBX, Address(ESP, + 1 * kWordSize)); // Index. | |
| 47 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Array. | |
| 48 __ testl(EBX, Immediate(kSmiTagMask)); | |
| 49 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi index. | |
| 50 // Range check. | |
| 51 __ cmpl(EBX, FieldAddress(EAX, Array::length_offset())); | |
| 52 // Runtime throws exception. | |
| 53 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump); | |
| 54 // Note that EBX is Smi, i.e, times 2. | |
| 55 ASSERT(kSmiTagShift == 1); | |
| 56 __ movl(EAX, FieldAddress(EAX, EBX, TIMES_2, Array::data_offset())); | |
| 57 __ ret(); | |
| 58 __ Bind(&fall_through); | |
| 59 } | |
| 60 | |
| 61 | |
| 62 void Intrinsifier::ImmutableArrayGetIndexed(Assembler* assembler) { | |
| 63 ObjectArrayGetIndexed(assembler); | |
| 64 } | |
| 65 | 33 |
| 66 | 34 |
| 67 static intptr_t ComputeObjectArrayTypeArgumentsOffset() { | 35 static intptr_t ComputeObjectArrayTypeArgumentsOffset() { |
| 68 const Library& core_lib = Library::Handle(Library::CoreLibrary()); | 36 const Library& core_lib = Library::Handle(Library::CoreLibrary()); |
| 69 const Class& cls = Class::Handle( | 37 const Class& cls = Class::Handle( |
| 70 core_lib.LookupClassAllowPrivate(Symbols::_List())); | 38 core_lib.LookupClassAllowPrivate(Symbols::_List())); |
| 71 ASSERT(!cls.IsNull()); | 39 ASSERT(!cls.IsNull()); |
| 72 ASSERT(cls.NumTypeArguments() == 1); | 40 ASSERT(cls.NumTypeArguments() == 1); |
| 73 const intptr_t field_offset = cls.type_arguments_field_offset(); | 41 const intptr_t field_offset = cls.type_arguments_field_offset(); |
| 74 ASSERT(field_offset != Class::kNoTypeArguments); | 42 ASSERT(field_offset != Class::kNoTypeArguments); |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 166 | 134 |
| 167 // Set the length field in the growable array object to 0. | 135 // Set the length field in the growable array object to 0. |
| 168 __ movl(FieldAddress(EAX, GrowableObjectArray::length_offset()), | 136 __ movl(FieldAddress(EAX, GrowableObjectArray::length_offset()), |
| 169 Immediate(0)); | 137 Immediate(0)); |
| 170 __ ret(); // returns the newly allocated object in EAX. | 138 __ ret(); // returns the newly allocated object in EAX. |
| 171 | 139 |
| 172 __ Bind(&fall_through); | 140 __ Bind(&fall_through); |
| 173 } | 141 } |
| 174 | 142 |
| 175 | 143 |
| 176 // Get length of growable object array. | |
| 177 // On stack: growable array (+1), return-address (+0). | |
| 178 void Intrinsifier::GrowableArrayLength(Assembler* assembler) { | |
| 179 __ movl(EAX, Address(ESP, + 1 * kWordSize)); | |
| 180 __ movl(EAX, FieldAddress(EAX, GrowableObjectArray::length_offset())); | |
| 181 __ ret(); | |
| 182 } | |
| 183 | |
| 184 | |
| 185 // Get capacity of growable object array. | |
| 186 // On stack: growable array (+1), return-address (+0). | |
| 187 void Intrinsifier::GrowableArrayCapacity(Assembler* assembler) { | |
| 188 __ movl(EAX, Address(ESP, + 1 * kWordSize)); | |
| 189 __ movl(EAX, FieldAddress(EAX, GrowableObjectArray::data_offset())); | |
| 190 __ movl(EAX, FieldAddress(EAX, Array::length_offset())); | |
| 191 __ ret(); | |
| 192 } | |
| 193 | |
| 194 | |
| 195 // Access growable object array at specified index. | 144 // Access growable object array at specified index. |
| 196 // On stack: growable array (+2), index (+1), return-address (+0). | 145 // On stack: growable array (+2), index (+1), return-address (+0). |
| 197 void Intrinsifier::GrowableArrayGetIndexed(Assembler* assembler) { | 146 void Intrinsifier::GrowableArrayGetIndexed(Assembler* assembler) { |
| 198 Label fall_through; | 147 Label fall_through; |
| 199 __ movl(EBX, Address(ESP, + 1 * kWordSize)); // Index. | 148 __ movl(EBX, Address(ESP, + 1 * kWordSize)); // Index. |
| 200 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // GrowableArray. | 149 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // GrowableArray. |
| 201 __ testl(EBX, Immediate(kSmiTagMask)); | 150 __ testl(EBX, Immediate(kSmiTagMask)); |
| 202 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi index. | 151 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi index. |
| 203 // Range check using _length field. | 152 // Range check using _length field. |
| 204 __ cmpl(EBX, FieldAddress(EAX, GrowableObjectArray::length_offset())); | 153 __ cmpl(EBX, FieldAddress(EAX, GrowableObjectArray::length_offset())); |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 398 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); \ | 347 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); \ |
| 399 __ movl(Address(EDI, 0), ECX); \ | 348 __ movl(Address(EDI, 0), ECX); \ |
| 400 __ addl(EDI, Immediate(kWordSize)); \ | 349 __ addl(EDI, Immediate(kWordSize)); \ |
| 401 __ jmp(&init_loop, Assembler::kNearJump); \ | 350 __ jmp(&init_loop, Assembler::kNearJump); \ |
| 402 __ Bind(&done); \ | 351 __ Bind(&done); \ |
| 403 \ | 352 \ |
| 404 __ ret(); \ | 353 __ ret(); \ |
| 405 __ Bind(&fall_through); \ | 354 __ Bind(&fall_through); \ |
| 406 | 355 |
| 407 | 356 |
| 408 | |
| 409 // Gets the length of a TypedData. | |
| 410 void Intrinsifier::TypedDataLength(Assembler* assembler) { | |
| 411 __ movl(EAX, Address(ESP, + 1 * kWordSize)); | |
| 412 __ movl(EAX, FieldAddress(EAX, TypedData::length_offset())); | |
| 413 __ ret(); | |
| 414 } | |
| 415 | |
| 416 | |
| 417 void Intrinsifier::Uint8ArrayGetIndexed(Assembler* assembler) { | |
| 418 Label fall_through; | |
| 419 __ movl(EBX, Address(ESP, + 1 * kWordSize)); // Index. | |
| 420 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Array. | |
| 421 __ testl(EBX, Immediate(kSmiTagMask)); | |
| 422 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi index. | |
| 423 // Range check. | |
| 424 __ cmpl(EBX, FieldAddress(EAX, TypedData::length_offset())); | |
| 425 // Runtime throws exception. | |
| 426 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump); | |
| 427 | |
| 428 __ SmiUntag(EBX); | |
| 429 __ movzxb(EAX, FieldAddress(EAX, EBX, TIMES_1, TypedData::data_offset())); | |
| 430 __ SmiTag(EAX); | |
| 431 __ ret(); | |
| 432 __ Bind(&fall_through); | |
| 433 } | |
| 434 | |
| 435 | |
| 436 void Intrinsifier::ExternalUint8ArrayGetIndexed(Assembler* assembler) { | |
| 437 Label fall_through; | |
| 438 __ movl(EBX, Address(ESP, + 1 * kWordSize)); // Index. | |
| 439 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Array. | |
| 440 __ testl(EBX, Immediate(kSmiTagMask)); | |
| 441 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi index. | |
| 442 // Range check. | |
| 443 __ cmpl(EBX, FieldAddress(EAX, TypedData::length_offset())); | |
| 444 // Runtime throws exception. | |
| 445 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump); | |
| 446 | |
| 447 __ movl(EAX, FieldAddress(EAX, ExternalTypedData::data_offset())); | |
| 448 __ SmiUntag(EBX); | |
| 449 __ movzxb(EAX, Address(EAX, EBX, TIMES_1, 0)); | |
| 450 __ SmiTag(EAX); | |
| 451 __ ret(); | |
| 452 __ Bind(&fall_through); | |
| 453 } | |
| 454 | |
| 455 | |
| 456 void Intrinsifier::Float64ArrayGetIndexed(Assembler* assembler) { | |
| 457 Label fall_through; | |
| 458 __ movl(EBX, Address(ESP, + 1 * kWordSize)); // Index. | |
| 459 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Array. | |
| 460 __ testl(EBX, Immediate(kSmiTagMask)); | |
| 461 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi index. | |
| 462 // Range check. | |
| 463 __ cmpl(EBX, FieldAddress(EAX, TypedData::length_offset())); | |
| 464 // Runtime throws exception. | |
| 465 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump); | |
| 466 | |
| 467 Address element_address = | |
| 468 Assembler::ElementAddressForRegIndex(false, // Not external | |
| 469 kTypedDataFloat64ArrayCid, // Cid. | |
| 470 8, // Index scale. | |
| 471 EAX, // Array. | |
| 472 EBX); // Index. | |
| 473 | |
| 474 __ movsd(XMM0, element_address); | |
| 475 | |
| 476 const Class& double_class = Class::Handle( | |
| 477 Isolate::Current()->object_store()->double_class()); | |
| 478 __ TryAllocate(double_class, | |
| 479 &fall_through, | |
| 480 Assembler::kNearJump, | |
| 481 EAX, // Result register. | |
| 482 EBX); | |
| 483 __ movsd(FieldAddress(EAX, Double::value_offset()), XMM0); | |
| 484 __ ret(); | |
| 485 __ Bind(&fall_through); | |
| 486 } | |
| 487 | |
| 488 | |
| 489 void Intrinsifier::Float64ArraySetIndexed(Assembler* assembler) { | |
| 490 Label fall_through; | |
| 491 __ movl(EBX, Address(ESP, + 2 * kWordSize)); // Index. | |
| 492 __ movl(EAX, Address(ESP, + 3 * kWordSize)); // Array. | |
| 493 __ testl(EBX, Immediate(kSmiTagMask)); | |
| 494 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi index. | |
| 495 // Range check. | |
| 496 __ cmpl(EBX, FieldAddress(EAX, TypedData::length_offset())); | |
| 497 // Runtime throws exception. | |
| 498 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump); | |
| 499 | |
| 500 __ movl(ECX, Address(ESP, + 1 * kWordSize)); // Value. | |
| 501 __ testl(ECX, Immediate(kSmiTagMask)); | |
| 502 __ j(ZERO, &fall_through, Assembler::kNearJump); // Value is Smi. | |
| 503 __ LoadClassId(EDI, ECX); | |
| 504 | |
| 505 __ cmpl(EDI, Immediate(kDoubleCid)); | |
| 506 __ j(NOT_EQUAL, &fall_through, Assembler::kNearJump); // Not a Double. | |
| 507 | |
| 508 __ movsd(XMM0, FieldAddress(ECX, Double::value_offset())); | |
| 509 | |
| 510 Address element_address = | |
| 511 Assembler::ElementAddressForRegIndex(false, // Not external | |
| 512 kTypedDataFloat64ArrayCid, // Cid. | |
| 513 8, // Index scale. | |
| 514 EAX, // Array. | |
| 515 EBX); // Index. | |
| 516 | |
| 517 __ movsd(element_address, XMM0); | |
| 518 __ ret(); | |
| 519 __ Bind(&fall_through); | |
| 520 } | |
| 521 | |
| 522 | |
| 523 static ScaleFactor GetScaleFactor(intptr_t size) { | 357 static ScaleFactor GetScaleFactor(intptr_t size) { |
| 524 switch (size) { | 358 switch (size) { |
| 525 case 1: return TIMES_1; | 359 case 1: return TIMES_1; |
| 526 case 2: return TIMES_2; | 360 case 2: return TIMES_2; |
| 527 case 4: return TIMES_4; | 361 case 4: return TIMES_4; |
| 528 case 8: return TIMES_8; | 362 case 8: return TIMES_8; |
| 529 case 16: return TIMES_16; | 363 case 16: return TIMES_16; |
| 530 } | 364 } |
| 531 UNREACHABLE(); | 365 UNREACHABLE(); |
| 532 return static_cast<ScaleFactor>(0); | 366 return static_cast<ScaleFactor>(0); |
| (...skipping 827 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1360 __ movl(EAX, Address(ESP, + 1 * kWordSize)); // String object. | 1194 __ movl(EAX, Address(ESP, + 1 * kWordSize)); // String object. |
| 1361 __ movl(EAX, FieldAddress(EAX, String::hash_offset())); | 1195 __ movl(EAX, FieldAddress(EAX, String::hash_offset())); |
| 1362 __ cmpl(EAX, Immediate(0)); | 1196 __ cmpl(EAX, Immediate(0)); |
| 1363 __ j(EQUAL, &fall_through, Assembler::kNearJump); | 1197 __ j(EQUAL, &fall_through, Assembler::kNearJump); |
| 1364 __ ret(); | 1198 __ ret(); |
| 1365 __ Bind(&fall_through); | 1199 __ Bind(&fall_through); |
| 1366 // Hash not yet computed. | 1200 // Hash not yet computed. |
| 1367 } | 1201 } |
| 1368 | 1202 |
| 1369 | 1203 |
| 1370 void Intrinsifier::StringBaseLength(Assembler* assembler) { | |
| 1371 __ movl(EAX, Address(ESP, + 1 * kWordSize)); // String object. | |
| 1372 __ movl(EAX, FieldAddress(EAX, String::length_offset())); | |
| 1373 __ ret(); | |
| 1374 } | |
| 1375 | |
| 1376 | |
| 1377 void Intrinsifier::StringBaseCodeUnitAt(Assembler* assembler) { | 1204 void Intrinsifier::StringBaseCodeUnitAt(Assembler* assembler) { |
| 1378 Label fall_through, try_two_byte_string; | 1205 Label fall_through, try_two_byte_string; |
| 1379 __ movl(EBX, Address(ESP, + 1 * kWordSize)); // Index. | 1206 __ movl(EBX, Address(ESP, + 1 * kWordSize)); // Index. |
| 1380 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // String. | 1207 __ movl(EAX, Address(ESP, + 2 * kWordSize)); // String. |
| 1381 __ testl(EBX, Immediate(kSmiTagMask)); | 1208 __ testl(EBX, Immediate(kSmiTagMask)); |
| 1382 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi index. | 1209 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Non-smi index. |
| 1383 // Range check. | 1210 // Range check. |
| 1384 __ cmpl(EBX, FieldAddress(EAX, String::length_offset())); | 1211 __ cmpl(EBX, FieldAddress(EAX, String::length_offset())); |
| 1385 // Runtime throws exception. | 1212 // Runtime throws exception. |
| 1386 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump); | 1213 __ j(ABOVE_EQUAL, &fall_through, Assembler::kNearJump); |
| (...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1790 Isolate::current_tag_offset()); | 1617 Isolate::current_tag_offset()); |
| 1791 // Set return value to Isolate::current_tag_. | 1618 // Set return value to Isolate::current_tag_. |
| 1792 __ movl(EAX, current_tag_addr); | 1619 __ movl(EAX, current_tag_addr); |
| 1793 __ ret(); | 1620 __ ret(); |
| 1794 } | 1621 } |
| 1795 | 1622 |
| 1796 #undef __ | 1623 #undef __ |
| 1797 } // namespace dart | 1624 } // namespace dart |
| 1798 | 1625 |
| 1799 #endif // defined TARGET_ARCH_IA32 | 1626 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |