| 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 #include "vm/globals.h" // Needed here to get TARGET_ARCH_MIPS. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_MIPS. |
| 6 #if defined(TARGET_ARCH_MIPS) | 6 #if defined(TARGET_ARCH_MIPS) |
| 7 | 7 |
| 8 #include "vm/intrinsifier.h" | 8 #include "vm/intrinsifier.h" |
| 9 | 9 |
| 10 #include "vm/assembler.h" | 10 #include "vm/assembler.h" |
| 11 #include "vm/flow_graph_compiler.h" | 11 #include "vm/flow_graph_compiler.h" |
| 12 #include "vm/object.h" | 12 #include "vm/object.h" |
| 13 #include "vm/object_store.h" | 13 #include "vm/object_store.h" |
| 14 #include "vm/symbols.h" | 14 #include "vm/symbols.h" |
| 15 | 15 |
| 16 namespace dart { | 16 namespace dart { |
| 17 | 17 |
| 18 DECLARE_FLAG(bool, enable_type_checks); | 18 DECLARE_FLAG(bool, enable_type_checks); |
| 19 | 19 |
| 20 #define __ assembler-> | 20 #define __ assembler-> |
| 21 | 21 |
| 22 | 22 |
| 23 void Intrinsifier::ObjectArrayLength(Assembler* assembler) { | 23 intptr_t Intrinsifier::ParameterSlotFromSp() { return -1; } |
| 24 __ lw(V0, Address(SP, 0 * kWordSize)); | |
| 25 __ Ret(); | |
| 26 __ delay_slot()->lw(V0, FieldAddress(V0, Array::length_offset())); | |
| 27 } | |
| 28 | |
| 29 | |
| 30 void Intrinsifier::ImmutableArrayLength(Assembler* assembler) { | |
| 31 ObjectArrayLength(assembler); | |
| 32 } | |
| 33 | |
| 34 | |
| 35 void Intrinsifier::ObjectArrayGetIndexed(Assembler* assembler) { | |
| 36 Label fall_through; | |
| 37 | |
| 38 __ lw(T0, Address(SP, + 0 * kWordSize)); // Index | |
| 39 | |
| 40 __ andi(CMPRES1, T0, Immediate(kSmiTagMask)); | |
| 41 __ bne(CMPRES1, ZR, &fall_through); // Index is not an smi, fall through | |
| 42 __ delay_slot()->lw(T1, Address(SP, + 1 * kWordSize)); // Array | |
| 43 | |
| 44 // Range check. | |
| 45 __ lw(T2, FieldAddress(T1, Array::length_offset())); | |
| 46 __ BranchUnsignedGreaterEqual(T0, T2, &fall_through); | |
| 47 | |
| 48 ASSERT(kSmiTagShift == 1); | |
| 49 // array element at T1 + T0*2 + Array::data_offset - 1 | |
| 50 __ sll(T2, T0, 1); | |
| 51 __ addu(T2, T1, T2); | |
| 52 __ Ret(); | |
| 53 __ delay_slot()->lw(V0, FieldAddress(T2, Array::data_offset())); | |
| 54 __ Bind(&fall_through); | |
| 55 } | |
| 56 | |
| 57 | |
| 58 void Intrinsifier::ImmutableArrayGetIndexed(Assembler* assembler) { | |
| 59 ObjectArrayGetIndexed(assembler); | |
| 60 } | |
| 61 | 24 |
| 62 | 25 |
| 63 static intptr_t ComputeObjectArrayTypeArgumentsOffset() { | 26 static intptr_t ComputeObjectArrayTypeArgumentsOffset() { |
| 64 const Library& core_lib = Library::Handle(Library::CoreLibrary()); | 27 const Library& core_lib = Library::Handle(Library::CoreLibrary()); |
| 65 const Class& cls = Class::Handle( | 28 const Class& cls = Class::Handle( |
| 66 core_lib.LookupClassAllowPrivate(Symbols::_List())); | 29 core_lib.LookupClassAllowPrivate(Symbols::_List())); |
| 67 ASSERT(!cls.IsNull()); | 30 ASSERT(!cls.IsNull()); |
| 68 ASSERT(cls.NumTypeArguments() == 1); | 31 ASSERT(cls.NumTypeArguments() == 1); |
| 69 const intptr_t field_offset = cls.type_arguments_field_offset(); | 32 const intptr_t field_offset = cls.type_arguments_field_offset(); |
| 70 ASSERT(field_offset != Class::kNoTypeArguments); | 33 ASSERT(field_offset != Class::kNoTypeArguments); |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 162 T1); | 125 T1); |
| 163 // Set the length field in the growable array object to 0. | 126 // Set the length field in the growable array object to 0. |
| 164 __ Ret(); // Returns the newly allocated object in V0. | 127 __ Ret(); // Returns the newly allocated object in V0. |
| 165 __ delay_slot()->sw(ZR, | 128 __ delay_slot()->sw(ZR, |
| 166 FieldAddress(V0, GrowableObjectArray::length_offset())); | 129 FieldAddress(V0, GrowableObjectArray::length_offset())); |
| 167 | 130 |
| 168 __ Bind(&fall_through); | 131 __ Bind(&fall_through); |
| 169 } | 132 } |
| 170 | 133 |
| 171 | 134 |
| 172 void Intrinsifier::GrowableArrayLength(Assembler* assembler) { | |
| 173 __ lw(V0, Address(SP, 0 * kWordSize)); | |
| 174 __ Ret(); | |
| 175 __ delay_slot()->lw(V0, | |
| 176 FieldAddress(V0, GrowableObjectArray::length_offset())); | |
| 177 } | |
| 178 | |
| 179 | |
| 180 void Intrinsifier::GrowableArrayCapacity(Assembler* assembler) { | |
| 181 __ lw(V0, Address(SP, 0 * kWordSize)); | |
| 182 __ lw(V0, FieldAddress(V0, GrowableObjectArray::data_offset())); | |
| 183 __ Ret(); | |
| 184 __ delay_slot()->lw(V0, FieldAddress(V0, Array::length_offset())); | |
| 185 } | |
| 186 | |
| 187 | |
| 188 void Intrinsifier::GrowableArrayGetIndexed(Assembler* assembler) { | 135 void Intrinsifier::GrowableArrayGetIndexed(Assembler* assembler) { |
| 189 Label fall_through; | 136 Label fall_through; |
| 190 | 137 |
| 191 __ lw(T0, Address(SP, 0 * kWordSize)); // Index | 138 __ lw(T0, Address(SP, 0 * kWordSize)); // Index |
| 192 | 139 |
| 193 __ andi(CMPRES1, T0, Immediate(kSmiTagMask)); | 140 __ andi(CMPRES1, T0, Immediate(kSmiTagMask)); |
| 194 __ bne(CMPRES1, ZR, &fall_through); // Index is not an smi, fall through | 141 __ bne(CMPRES1, ZR, &fall_through); // Index is not an smi, fall through |
| 195 __ delay_slot()->lw(T1, Address(SP, 1 * kWordSize)); // Array | 142 __ delay_slot()->lw(T1, Address(SP, 1 * kWordSize)); // Array |
| 196 | 143 |
| 197 // Range check. | 144 // Range check. |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 391 __ BranchUnsignedGreaterEqual(T2, T1, &done); \ | 338 __ BranchUnsignedGreaterEqual(T2, T1, &done); \ |
| 392 __ sw(ZR, Address(T2, 0)); \ | 339 __ sw(ZR, Address(T2, 0)); \ |
| 393 __ b(&init_loop); \ | 340 __ b(&init_loop); \ |
| 394 __ delay_slot()->addiu(T2, T2, Immediate(kWordSize)); \ | 341 __ delay_slot()->addiu(T2, T2, Immediate(kWordSize)); \ |
| 395 __ Bind(&done); \ | 342 __ Bind(&done); \ |
| 396 \ | 343 \ |
| 397 __ Ret(); \ | 344 __ Ret(); \ |
| 398 __ Bind(&fall_through); \ | 345 __ Bind(&fall_through); \ |
| 399 | 346 |
| 400 | 347 |
| 401 // Gets the length of a TypedData. | |
| 402 void Intrinsifier::TypedDataLength(Assembler* assembler) { | |
| 403 __ lw(T0, Address(SP, 0 * kWordSize)); | |
| 404 __ Ret(); | |
| 405 __ delay_slot()->lw(V0, FieldAddress(T0, TypedData::length_offset())); | |
| 406 } | |
| 407 | |
| 408 | |
| 409 void Intrinsifier::Uint8ArrayGetIndexed(Assembler* assembler) { | |
| 410 Label fall_through; | |
| 411 | |
| 412 __ lw(T0, Address(SP, + 0 * kWordSize)); // Index. | |
| 413 | |
| 414 __ andi(CMPRES1, T0, Immediate(kSmiTagMask)); | |
| 415 __ bne(CMPRES1, ZR, &fall_through); // Index is not an smi, fall through. | |
| 416 __ delay_slot()->lw(T1, Address(SP, + 1 * kWordSize)); // Array. | |
| 417 | |
| 418 // Range check. | |
| 419 __ lw(T2, FieldAddress(T1, TypedData::length_offset())); | |
| 420 __ BranchUnsignedGreaterEqual(T0, T2, &fall_through); | |
| 421 | |
| 422 __ SmiUntag(T0); | |
| 423 __ addu(T1, T1, T0); | |
| 424 __ lbu(V0, FieldAddress(T1, TypedData::data_offset())); | |
| 425 __ Ret(); | |
| 426 __ delay_slot()->SmiTag(V0); | |
| 427 | |
| 428 __ Bind(&fall_through); | |
| 429 } | |
| 430 | |
| 431 | |
| 432 void Intrinsifier::ExternalUint8ArrayGetIndexed(Assembler* assembler) { | |
| 433 Label fall_through; | |
| 434 | |
| 435 __ lw(T0, Address(SP, + 0 * kWordSize)); // Index. | |
| 436 | |
| 437 __ andi(CMPRES1, T0, Immediate(kSmiTagMask)); | |
| 438 __ bne(CMPRES1, ZR, &fall_through); // Index is not an smi, fall through. | |
| 439 __ delay_slot()->lw(T1, Address(SP, + 1 * kWordSize)); // Array. | |
| 440 | |
| 441 // Range check. | |
| 442 __ lw(T2, FieldAddress(T1, TypedData::length_offset())); | |
| 443 __ BranchUnsignedGreaterEqual(T0, T2, &fall_through); | |
| 444 | |
| 445 __ lw(T1, FieldAddress(T1, ExternalTypedData::data_offset())); | |
| 446 __ SmiUntag(T0); | |
| 447 __ addu(T1, T1, T0); | |
| 448 __ lbu(V0, Address(T1, 0)); | |
| 449 __ Ret(); | |
| 450 __ delay_slot()->SmiTag(V0); | |
| 451 | |
| 452 __ Bind(&fall_through); | |
| 453 } | |
| 454 | |
| 455 | |
| 456 void Intrinsifier::Float64ArrayGetIndexed(Assembler* assembler) { | |
| 457 Label fall_through; | |
| 458 | |
| 459 __ lw(T0, Address(SP, + 0 * kWordSize)); // Index. | |
| 460 | |
| 461 __ andi(CMPRES1, T0, Immediate(kSmiTagMask)); | |
| 462 __ bne(CMPRES1, ZR, &fall_through); // Index is not an smi, fall through. | |
| 463 __ delay_slot()->lw(T1, Address(SP, + 1 * kWordSize)); // Array. | |
| 464 | |
| 465 // Range check. | |
| 466 __ lw(T2, FieldAddress(T1, TypedData::length_offset())); | |
| 467 __ BranchUnsignedGreaterEqual(T0, T2, &fall_through); | |
| 468 | |
| 469 Address element_address = | |
| 470 __ ElementAddressForRegIndex(true, // Load. | |
| 471 false, // Not external. | |
| 472 kTypedDataFloat64ArrayCid, // Cid. | |
| 473 8, // Index scale. | |
| 474 T1, // Array. | |
| 475 T0); // Index. | |
| 476 | |
| 477 __ LoadDFromOffset(D0, element_address.base(), element_address.offset()); | |
| 478 | |
| 479 const Class& double_class = Class::Handle( | |
| 480 Isolate::Current()->object_store()->double_class()); | |
| 481 __ TryAllocate(double_class, | |
| 482 &fall_through, | |
| 483 V0, // Result register. | |
| 484 T1); | |
| 485 __ StoreDToOffset(D0, V0, Double::value_offset() - kHeapObjectTag); | |
| 486 __ Ret(); | |
| 487 __ Bind(&fall_through); | |
| 488 } | |
| 489 | |
| 490 | |
| 491 void Intrinsifier::Float64ArraySetIndexed(Assembler* assembler) { | |
| 492 Label fall_through; | |
| 493 | |
| 494 __ lw(T0, Address(SP, + 1 * kWordSize)); // Index. | |
| 495 | |
| 496 __ andi(CMPRES1, T0, Immediate(kSmiTagMask)); | |
| 497 __ bne(CMPRES1, ZR, &fall_through); // Index is not an smi, fall through. | |
| 498 __ delay_slot()->lw(T1, Address(SP, + 2 * kWordSize)); // Array. | |
| 499 | |
| 500 // Range check. | |
| 501 __ lw(T2, FieldAddress(T1, TypedData::length_offset())); | |
| 502 __ BranchUnsignedGreaterEqual(T0, T2, &fall_through); | |
| 503 | |
| 504 __ lw(T2, Address(SP, + 0 * kWordSize)); // Value. | |
| 505 __ andi(CMPRES1, T2, Immediate(kSmiTagMask)); | |
| 506 __ beq(CMPRES1, ZR, &fall_through); // Value is a Smi. Fall through. | |
| 507 | |
| 508 __ LoadClassId(T3, T2); | |
| 509 __ BranchNotEqual(T3, kDoubleCid, &fall_through); // Not a Double. | |
| 510 | |
| 511 __ LoadDFromOffset(D0, T2, Double::value_offset() - kHeapObjectTag); | |
| 512 | |
| 513 Address element_address = | |
| 514 __ ElementAddressForRegIndex(false, // Store. | |
| 515 false, // Not external. | |
| 516 kTypedDataFloat64ArrayCid, // Cid. | |
| 517 8, // Index scale. | |
| 518 T1, // Array. | |
| 519 T0); // Index. | |
| 520 __ StoreDToOffset(D0, element_address.base(), element_address.offset()); | |
| 521 __ Ret(); | |
| 522 __ Bind(&fall_through); | |
| 523 } | |
| 524 | |
| 525 | |
| 526 static int GetScaleFactor(intptr_t size) { | 348 static int GetScaleFactor(intptr_t size) { |
| 527 switch (size) { | 349 switch (size) { |
| 528 case 1: return 0; | 350 case 1: return 0; |
| 529 case 2: return 1; | 351 case 2: return 1; |
| 530 case 4: return 2; | 352 case 4: return 2; |
| 531 case 8: return 3; | 353 case 8: return 3; |
| 532 case 16: return 4; | 354 case 16: return 4; |
| 533 } | 355 } |
| 534 UNREACHABLE(); | 356 UNREACHABLE(); |
| 535 return -1; | 357 return -1; |
| (...skipping 862 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1398 void Intrinsifier::String_getHashCode(Assembler* assembler) { | 1220 void Intrinsifier::String_getHashCode(Assembler* assembler) { |
| 1399 Label fall_through; | 1221 Label fall_through; |
| 1400 __ lw(T0, Address(SP, 0 * kWordSize)); | 1222 __ lw(T0, Address(SP, 0 * kWordSize)); |
| 1401 __ lw(V0, FieldAddress(T0, String::hash_offset())); | 1223 __ lw(V0, FieldAddress(T0, String::hash_offset())); |
| 1402 __ beq(V0, ZR, &fall_through); | 1224 __ beq(V0, ZR, &fall_through); |
| 1403 __ Ret(); | 1225 __ Ret(); |
| 1404 __ Bind(&fall_through); // Hash not yet computed. | 1226 __ Bind(&fall_through); // Hash not yet computed. |
| 1405 } | 1227 } |
| 1406 | 1228 |
| 1407 | 1229 |
| 1408 void Intrinsifier::StringBaseLength(Assembler* assembler) { | |
| 1409 __ lw(T0, Address(SP, 0 * kWordSize)); | |
| 1410 __ Ret(); | |
| 1411 __ delay_slot()->lw(V0, FieldAddress(T0, String::length_offset())); | |
| 1412 } | |
| 1413 | |
| 1414 | |
| 1415 void Intrinsifier::StringBaseCodeUnitAt(Assembler* assembler) { | 1230 void Intrinsifier::StringBaseCodeUnitAt(Assembler* assembler) { |
| 1416 Label fall_through, try_two_byte_string; | 1231 Label fall_through, try_two_byte_string; |
| 1417 | 1232 |
| 1418 __ lw(T1, Address(SP, 0 * kWordSize)); // Index. | 1233 __ lw(T1, Address(SP, 0 * kWordSize)); // Index. |
| 1419 __ lw(T0, Address(SP, 1 * kWordSize)); // String. | 1234 __ lw(T0, Address(SP, 1 * kWordSize)); // String. |
| 1420 | 1235 |
| 1421 // Checks. | 1236 // Checks. |
| 1422 __ andi(CMPRES1, T1, Immediate(kSmiTagMask)); | 1237 __ andi(CMPRES1, T1, Immediate(kSmiTagMask)); |
| 1423 __ bne(T1, ZR, &fall_through); // Index is not a Smi. | 1238 __ bne(T1, ZR, &fall_through); // Index is not a Smi. |
| 1424 __ lw(T2, FieldAddress(T0, String::length_offset())); // Range check. | 1239 __ lw(T2, FieldAddress(T0, String::length_offset())); // Range check. |
| (...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1833 Isolate* isolate = Isolate::Current(); | 1648 Isolate* isolate = Isolate::Current(); |
| 1834 __ LoadImmediate(V0, reinterpret_cast<uword>(isolate)); | 1649 __ LoadImmediate(V0, reinterpret_cast<uword>(isolate)); |
| 1835 // Set return value. | 1650 // Set return value. |
| 1836 __ Ret(); | 1651 __ Ret(); |
| 1837 __ delay_slot()->lw(V0, Address(V0, Isolate::current_tag_offset())); | 1652 __ delay_slot()->lw(V0, Address(V0, Isolate::current_tag_offset())); |
| 1838 } | 1653 } |
| 1839 | 1654 |
| 1840 } // namespace dart | 1655 } // namespace dart |
| 1841 | 1656 |
| 1842 #endif // defined TARGET_ARCH_MIPS | 1657 #endif // defined TARGET_ARCH_MIPS |
| OLD | NEW |