| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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_ARM64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM64. |
| 6 #if defined(TARGET_ARCH_ARM64) | 6 #if defined(TARGET_ARCH_ARM64) |
| 7 | 7 |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
| (...skipping 592 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 603 case kTypedDataUint16ArrayCid: | 603 case kTypedDataUint16ArrayCid: |
| 604 locs->set_in(2, Location::WritableRegister()); | 604 locs->set_in(2, Location::WritableRegister()); |
| 605 break; | 605 break; |
| 606 case kTypedDataInt32ArrayCid: | 606 case kTypedDataInt32ArrayCid: |
| 607 case kTypedDataUint32ArrayCid: | 607 case kTypedDataUint32ArrayCid: |
| 608 // Mints are stored in Q registers. For smis, use a writable register | 608 // Mints are stored in Q registers. For smis, use a writable register |
| 609 // because the value must be untagged before storing. | 609 // because the value must be untagged before storing. |
| 610 if (value()->IsSmiValue()) { | 610 if (value()->IsSmiValue()) { |
| 611 locs->set_in(2, Location::WritableRegister()); | 611 locs->set_in(2, Location::WritableRegister()); |
| 612 } else { | 612 } else { |
| 613 // TODO(zra): Implement when we add fpu loads and stores. | 613 // TODO(zra): Implement when we add simd loads and stores. |
| 614 UNIMPLEMENTED(); | 614 UNIMPLEMENTED(); |
| 615 } | 615 } |
| 616 break; | 616 break; |
| 617 case kTypedDataFloat32ArrayCid: | 617 case kTypedDataFloat32ArrayCid: |
| 618 // TODO(zra): Implement when we add float store. |
| 619 UNIMPLEMENTED(); |
| 620 break; |
| 618 case kTypedDataFloat64ArrayCid: // TODO(srdjan): Support Float64 constants. | 621 case kTypedDataFloat64ArrayCid: // TODO(srdjan): Support Float64 constants. |
| 622 locs->set_in(2, Location::RequiresFpuRegister()); |
| 623 break; |
| 619 case kTypedDataInt32x4ArrayCid: | 624 case kTypedDataInt32x4ArrayCid: |
| 620 case kTypedDataFloat32x4ArrayCid: | 625 case kTypedDataFloat32x4ArrayCid: |
| 621 case kTypedDataFloat64x2ArrayCid: | 626 case kTypedDataFloat64x2ArrayCid: |
| 622 // TODO(zra): Implement when we add fpu loads and stores. | 627 // TODO(zra): Implement when we add simd loads and stores. |
| 623 UNIMPLEMENTED(); | 628 UNIMPLEMENTED(); |
| 624 break; | 629 break; |
| 625 default: | 630 default: |
| 626 UNREACHABLE(); | 631 UNREACHABLE(); |
| 627 return NULL; | 632 return NULL; |
| 628 } | 633 } |
| 629 return locs; | 634 return locs; |
| 630 } | 635 } |
| 631 | 636 |
| 632 | 637 |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 735 break; | 740 break; |
| 736 } | 741 } |
| 737 case kTypedDataInt32ArrayCid: | 742 case kTypedDataInt32ArrayCid: |
| 738 case kTypedDataUint32ArrayCid: { | 743 case kTypedDataUint32ArrayCid: { |
| 739 if (value()->IsSmiValue()) { | 744 if (value()->IsSmiValue()) { |
| 740 ASSERT(RequiredInputRepresentation(2) == kTagged); | 745 ASSERT(RequiredInputRepresentation(2) == kTagged); |
| 741 Register value = locs()->in(2).reg(); | 746 Register value = locs()->in(2).reg(); |
| 742 __ SmiUntag(value); | 747 __ SmiUntag(value); |
| 743 __ str(value, element_address); | 748 __ str(value, element_address); |
| 744 } else { | 749 } else { |
| 745 // TODO(zra): Implement when we add fpu loads and stores. | 750 // TODO(zra): Implement when we add simd loads and stores. |
| 746 UNIMPLEMENTED(); | 751 UNIMPLEMENTED(); |
| 747 } | 752 } |
| 748 break; | 753 break; |
| 749 } | 754 } |
| 750 case kTypedDataFloat32ArrayCid: | 755 case kTypedDataFloat32ArrayCid: |
| 751 case kTypedDataFloat64ArrayCid: | 756 // TODO(zra): Implement when we add float store. |
| 757 UNIMPLEMENTED(); |
| 758 break; |
| 759 case kTypedDataFloat64ArrayCid: { |
| 760 VRegister in2 = locs()->in(2).fpu_reg(); |
| 761 __ add(index.reg(), index.reg(), Operand(array)); |
| 762 __ StoreDFieldToOffset(in2, index.reg(), 0); |
| 763 break; |
| 764 } |
| 752 case kTypedDataFloat64x2ArrayCid: | 765 case kTypedDataFloat64x2ArrayCid: |
| 753 case kTypedDataInt32x4ArrayCid: | 766 case kTypedDataInt32x4ArrayCid: |
| 754 case kTypedDataFloat32x4ArrayCid: { | 767 case kTypedDataFloat32x4ArrayCid: { |
| 755 // TODO(zra): Implement when we add fpu loads and stores. | 768 // TODO(zra): Implement when we add simd loads and stores. |
| 756 UNIMPLEMENTED(); | 769 UNIMPLEMENTED(); |
| 757 break; | 770 break; |
| 758 } | 771 } |
| 759 default: | 772 default: |
| 760 UNREACHABLE(); | 773 UNREACHABLE(); |
| 761 } | 774 } |
| 762 } | 775 } |
| 763 | 776 |
| 764 | 777 |
| 765 static void LoadValueCid(FlowGraphCompiler* compiler, | 778 static void LoadValueCid(FlowGraphCompiler* compiler, |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 886 __ CompareImmediate(TMP, 0, PP); | 899 __ CompareImmediate(TMP, 0, PP); |
| 887 __ b(&skip_length_check, LT); | 900 __ b(&skip_length_check, LT); |
| 888 __ CompareImmediate(value_cid_reg, kNullCid, PP); | 901 __ CompareImmediate(value_cid_reg, kNullCid, PP); |
| 889 __ b(&no_fixed_length, EQ); | 902 __ b(&no_fixed_length, EQ); |
| 890 // Check for typed data array. | 903 // Check for typed data array. |
| 891 __ CompareImmediate(value_cid_reg, kTypedDataInt32x4ArrayCid, PP); | 904 __ CompareImmediate(value_cid_reg, kTypedDataInt32x4ArrayCid, PP); |
| 892 __ b(&no_fixed_length, GT); | 905 __ b(&no_fixed_length, GT); |
| 893 __ CompareImmediate(value_cid_reg, kTypedDataInt8ArrayCid, PP); | 906 __ CompareImmediate(value_cid_reg, kTypedDataInt8ArrayCid, PP); |
| 894 // Could still be a regular array. | 907 // Could still be a regular array. |
| 895 __ b(&check_array, LT); | 908 __ b(&check_array, LT); |
| 896 __ LoadFromOffset(temp_reg, value_reg, TypedData::length_offset()); | 909 __ LoadFieldFromOffset( |
| 910 temp_reg, value_reg, TypedData::length_offset()); |
| 897 __ ldr(TMP, field_length_operand); | 911 __ ldr(TMP, field_length_operand); |
| 898 __ CompareRegisters(temp_reg, TMP); | 912 __ CompareRegisters(temp_reg, TMP); |
| 899 __ b(&length_compared); | 913 __ b(&length_compared); |
| 900 // Check for regular array. | 914 // Check for regular array. |
| 901 __ Bind(&check_array); | 915 __ Bind(&check_array); |
| 902 __ CompareImmediate(value_cid_reg, kImmutableArrayCid, PP); | 916 __ CompareImmediate(value_cid_reg, kImmutableArrayCid, PP); |
| 903 __ b(&no_fixed_length, GT); | 917 __ b(&no_fixed_length, GT); |
| 904 __ CompareImmediate(value_cid_reg, kArrayCid, PP); | 918 __ CompareImmediate(value_cid_reg, kArrayCid, PP); |
| 905 __ b(&no_fixed_length, LT); | 919 __ b(&no_fixed_length, LT); |
| 906 __ LoadFieldFromOffset(temp_reg, value_reg, Array::length_offset()); | 920 __ LoadFieldFromOffset(temp_reg, value_reg, Array::length_offset()); |
| (...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1135 const intptr_t kNumTemps = 0; | 1149 const intptr_t kNumTemps = 0; |
| 1136 LocationSummary* summary = | 1150 LocationSummary* summary = |
| 1137 new LocationSummary(kNumInputs, kNumTemps, | 1151 new LocationSummary(kNumInputs, kNumTemps, |
| 1138 !field().IsNull() && | 1152 !field().IsNull() && |
| 1139 ((field().guarded_cid() == kIllegalCid) || is_initialization_) | 1153 ((field().guarded_cid() == kIllegalCid) || is_initialization_) |
| 1140 ? LocationSummary::kCallOnSlowPath | 1154 ? LocationSummary::kCallOnSlowPath |
| 1141 : LocationSummary::kNoCall); | 1155 : LocationSummary::kNoCall); |
| 1142 | 1156 |
| 1143 summary->set_in(0, Location::RequiresRegister()); | 1157 summary->set_in(0, Location::RequiresRegister()); |
| 1144 if (IsUnboxedStore() && opt) { | 1158 if (IsUnboxedStore() && opt) { |
| 1145 // TODO(zra): Implement when we add fpu loads and stores. | 1159 summary->set_in(1, Location::RequiresFpuRegister()); |
| 1146 UNIMPLEMENTED(); | 1160 summary->AddTemp(Location::RequiresRegister()); |
| 1161 summary->AddTemp(Location::RequiresRegister()); |
| 1147 } else if (IsPotentialUnboxedStore()) { | 1162 } else if (IsPotentialUnboxedStore()) { |
| 1148 summary->set_in(1, ShouldEmitStoreBarrier() | 1163 summary->set_in(1, ShouldEmitStoreBarrier() |
| 1149 ? Location::WritableRegister() | 1164 ? Location::WritableRegister() |
| 1150 : Location::RequiresRegister()); | 1165 : Location::RequiresRegister()); |
| 1151 summary->AddTemp(Location::RequiresRegister()); | 1166 summary->AddTemp(Location::RequiresRegister()); |
| 1152 summary->AddTemp(Location::RequiresRegister()); | 1167 summary->AddTemp(Location::RequiresRegister()); |
| 1168 summary->AddTemp(opt ? Location::RequiresFpuRegister() |
| 1169 : Location::FpuRegisterLocation(V1)); |
| 1153 } else { | 1170 } else { |
| 1154 summary->set_in(1, ShouldEmitStoreBarrier() | 1171 summary->set_in(1, ShouldEmitStoreBarrier() |
| 1155 ? Location::WritableRegister() | 1172 ? Location::WritableRegister() |
| 1156 : Location::RegisterOrConstant(value())); | 1173 : Location::RegisterOrConstant(value())); |
| 1157 } | 1174 } |
| 1158 return summary; | 1175 return summary; |
| 1159 } | 1176 } |
| 1160 | 1177 |
| 1161 | 1178 |
| 1162 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1179 void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1163 Label skip_store; | 1180 Label skip_store; |
| 1164 | 1181 |
| 1165 Register instance_reg = locs()->in(0).reg(); | 1182 Register instance_reg = locs()->in(0).reg(); |
| 1166 | 1183 |
| 1167 if (IsUnboxedStore() && compiler->is_optimizing()) { | 1184 if (IsUnboxedStore() && compiler->is_optimizing()) { |
| 1168 UNIMPLEMENTED(); | 1185 const VRegister value = locs()->in(1).fpu_reg(); |
| 1186 const Register temp = locs()->temp(0).reg(); |
| 1187 const Register temp2 = locs()->temp(1).reg(); |
| 1188 const intptr_t cid = field().UnboxedFieldCid(); |
| 1189 |
| 1190 if (is_initialization_) { |
| 1191 const Class* cls = NULL; |
| 1192 switch (cid) { |
| 1193 case kDoubleCid: |
| 1194 cls = &compiler->double_class(); |
| 1195 break; |
| 1196 // TODO(zra): Implement these when we add fpu loads and stores. |
| 1197 case kFloat32x4Cid: |
| 1198 case kFloat64x2Cid: |
| 1199 UNIMPLEMENTED(); |
| 1200 break; |
| 1201 default: |
| 1202 UNREACHABLE(); |
| 1203 } |
| 1204 |
| 1205 StoreInstanceFieldSlowPath* slow_path = |
| 1206 new StoreInstanceFieldSlowPath(this, *cls); |
| 1207 compiler->AddSlowPathCode(slow_path); |
| 1208 |
| 1209 __ TryAllocate(*cls, |
| 1210 slow_path->entry_label(), |
| 1211 temp, |
| 1212 temp2, |
| 1213 PP); |
| 1214 __ Bind(slow_path->exit_label()); |
| 1215 __ mov(temp2, temp); |
| 1216 __ StoreIntoObject(instance_reg, |
| 1217 FieldAddress(instance_reg, offset_in_bytes_), |
| 1218 temp2); |
| 1219 } else { |
| 1220 __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes_); |
| 1221 } |
| 1222 switch (cid) { |
| 1223 case kDoubleCid: |
| 1224 __ Comment("UnboxedDoubleStoreInstanceFieldInstr"); |
| 1225 __ StoreDFieldToOffset(value, temp, Double::value_offset()); |
| 1226 break; |
| 1227 case kFloat32x4Cid: |
| 1228 case kFloat64x2Cid: |
| 1229 UNIMPLEMENTED(); |
| 1230 break; |
| 1231 default: |
| 1232 UNREACHABLE(); |
| 1233 } |
| 1234 |
| 1235 return; |
| 1169 } | 1236 } |
| 1170 | 1237 |
| 1171 if (IsPotentialUnboxedStore()) { | 1238 if (IsPotentialUnboxedStore()) { |
| 1239 const Register value_reg = locs()->in(1).reg(); |
| 1172 const Register temp = locs()->temp(0).reg(); | 1240 const Register temp = locs()->temp(0).reg(); |
| 1173 const Register temp2 = locs()->temp(1).reg(); | 1241 const Register temp2 = locs()->temp(1).reg(); |
| 1242 const VRegister fpu_temp = locs()->temp(2).fpu_reg(); |
| 1174 | 1243 |
| 1175 Label store_pointer; | 1244 Label store_pointer; |
| 1176 Label store_double; | 1245 Label store_double; |
| 1177 Label store_float32x4; | 1246 Label store_float32x4; |
| 1178 Label store_float64x2; | 1247 Label store_float64x2; |
| 1179 | 1248 |
| 1180 __ LoadObject(temp, Field::ZoneHandle(field().raw()), PP); | 1249 __ LoadObject(temp, Field::ZoneHandle(field().raw()), PP); |
| 1181 | 1250 |
| 1182 __ LoadFieldFromOffset(temp2, temp, Field::is_nullable_offset()); | 1251 __ LoadFieldFromOffset(temp2, temp, Field::is_nullable_offset()); |
| 1183 __ CompareImmediate(temp2, kNullCid, PP); | 1252 __ CompareImmediate(temp2, kNullCid, PP); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1201 __ b(&store_float64x2, EQ); | 1270 __ b(&store_float64x2, EQ); |
| 1202 | 1271 |
| 1203 // Fall through. | 1272 // Fall through. |
| 1204 __ b(&store_pointer); | 1273 __ b(&store_pointer); |
| 1205 | 1274 |
| 1206 if (!compiler->is_optimizing()) { | 1275 if (!compiler->is_optimizing()) { |
| 1207 locs()->live_registers()->Add(locs()->in(0)); | 1276 locs()->live_registers()->Add(locs()->in(0)); |
| 1208 locs()->live_registers()->Add(locs()->in(1)); | 1277 locs()->live_registers()->Add(locs()->in(1)); |
| 1209 } | 1278 } |
| 1210 | 1279 |
| 1211 // TODO(zra): Implement these when we add fpu loads and stores. | |
| 1212 { | 1280 { |
| 1213 __ Bind(&store_double); | 1281 __ Bind(&store_double); |
| 1214 __ hlt(0); // Unimplemented. | 1282 Label copy_double; |
| 1283 StoreInstanceFieldSlowPath* slow_path = |
| 1284 new StoreInstanceFieldSlowPath(this, compiler->double_class()); |
| 1285 compiler->AddSlowPathCode(slow_path); |
| 1286 |
| 1287 __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes_); |
| 1288 __ CompareObject(temp, Object::null_object(), PP); |
| 1289 __ b(©_double, NE); |
| 1290 |
| 1291 __ TryAllocate(compiler->double_class(), |
| 1292 slow_path->entry_label(), |
| 1293 temp, |
| 1294 temp2, |
| 1295 PP); |
| 1296 __ Bind(slow_path->exit_label()); |
| 1297 __ mov(temp2, temp); |
| 1298 __ StoreIntoObject(instance_reg, |
| 1299 FieldAddress(instance_reg, offset_in_bytes_), |
| 1300 temp2); |
| 1301 __ Bind(©_double); |
| 1302 __ LoadDFieldFromOffset(fpu_temp, value_reg, Double::value_offset()); |
| 1303 __ StoreDFieldToOffset(fpu_temp, temp, Double::value_offset()); |
| 1304 __ b(&skip_store); |
| 1215 } | 1305 } |
| 1216 | 1306 |
| 1307 // TODO(zra): Implement these when we add simd loads and stores. |
| 1217 { | 1308 { |
| 1218 __ Bind(&store_float32x4); | 1309 __ Bind(&store_float32x4); |
| 1219 __ hlt(0); // Unimplemented. | 1310 __ hlt(0); // Unimplemented. |
| 1220 } | 1311 } |
| 1221 | 1312 |
| 1222 { | 1313 { |
| 1223 __ Bind(&store_float64x2); | 1314 __ Bind(&store_float64x2); |
| 1224 __ hlt(0); // Unimplemented. | 1315 __ hlt(0); // Unimplemented. |
| 1225 } | 1316 } |
| 1226 | 1317 |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1324 ASSERT(locs()->in(kElementTypePos).reg() == R1); | 1415 ASSERT(locs()->in(kElementTypePos).reg() == R1); |
| 1325 ASSERT(locs()->in(kLengthPos).reg() == R2); | 1416 ASSERT(locs()->in(kLengthPos).reg() == R2); |
| 1326 compiler->GenerateCall(token_pos(), | 1417 compiler->GenerateCall(token_pos(), |
| 1327 &StubCode::AllocateArrayLabel(), | 1418 &StubCode::AllocateArrayLabel(), |
| 1328 PcDescriptors::kOther, | 1419 PcDescriptors::kOther, |
| 1329 locs()); | 1420 locs()); |
| 1330 ASSERT(locs()->out(0).reg() == R0); | 1421 ASSERT(locs()->out(0).reg() == R0); |
| 1331 } | 1422 } |
| 1332 | 1423 |
| 1333 | 1424 |
| 1425 class BoxDoubleSlowPath : public SlowPathCode { |
| 1426 public: |
| 1427 explicit BoxDoubleSlowPath(Instruction* instruction) |
| 1428 : instruction_(instruction) { } |
| 1429 |
| 1430 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1431 __ Comment("BoxDoubleSlowPath"); |
| 1432 __ Bind(entry_label()); |
| 1433 const Class& double_class = compiler->double_class(); |
| 1434 const Code& stub = |
| 1435 Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
| 1436 const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
| 1437 |
| 1438 LocationSummary* locs = instruction_->locs(); |
| 1439 locs->live_registers()->Remove(locs->out(0)); |
| 1440 |
| 1441 compiler->SaveLiveRegisters(locs); |
| 1442 compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. |
| 1443 &label, |
| 1444 PcDescriptors::kOther, |
| 1445 locs); |
| 1446 __ mov(locs->out(0).reg(), R0); |
| 1447 compiler->RestoreLiveRegisters(locs); |
| 1448 |
| 1449 __ b(exit_label()); |
| 1450 } |
| 1451 |
| 1452 private: |
| 1453 Instruction* instruction_; |
| 1454 }; |
| 1455 |
| 1456 |
| 1334 LocationSummary* LoadFieldInstr::MakeLocationSummary(bool opt) const { | 1457 LocationSummary* LoadFieldInstr::MakeLocationSummary(bool opt) const { |
| 1335 const intptr_t kNumInputs = 1; | 1458 const intptr_t kNumInputs = 1; |
| 1336 const intptr_t kNumTemps = 0; | 1459 const intptr_t kNumTemps = 0; |
| 1337 LocationSummary* locs = | 1460 LocationSummary* locs = |
| 1338 new LocationSummary( | 1461 new LocationSummary( |
| 1339 kNumInputs, kNumTemps, | 1462 kNumInputs, kNumTemps, |
| 1340 (opt && !IsPotentialUnboxedLoad()) | 1463 (opt && !IsPotentialUnboxedLoad()) |
| 1341 ? LocationSummary::kNoCall | 1464 ? LocationSummary::kNoCall |
| 1342 : LocationSummary::kCallOnSlowPath); | 1465 : LocationSummary::kCallOnSlowPath); |
| 1343 | 1466 |
| 1344 locs->set_in(0, Location::RequiresRegister()); | 1467 locs->set_in(0, Location::RequiresRegister()); |
| 1345 | 1468 |
| 1346 if (IsUnboxedLoad() && opt) { | 1469 if (IsUnboxedLoad() && opt) { |
| 1347 // TODO(zra): Implement when we add fpu loads and stores. | 1470 locs->AddTemp(Location::RequiresRegister()); |
| 1348 UNIMPLEMENTED(); | |
| 1349 } else if (IsPotentialUnboxedLoad()) { | 1471 } else if (IsPotentialUnboxedLoad()) { |
| 1472 locs->AddTemp(opt ? Location::RequiresFpuRegister() |
| 1473 : Location::FpuRegisterLocation(V1)); |
| 1350 locs->AddTemp(Location::RequiresRegister()); | 1474 locs->AddTemp(Location::RequiresRegister()); |
| 1351 } | 1475 } |
| 1352 locs->set_out(0, Location::RequiresRegister()); | 1476 locs->set_out(0, Location::RequiresRegister()); |
| 1353 return locs; | 1477 return locs; |
| 1354 } | 1478 } |
| 1355 | 1479 |
| 1356 | 1480 |
| 1357 void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1481 void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1358 Register instance_reg = locs()->in(0).reg(); | 1482 Register instance_reg = locs()->in(0).reg(); |
| 1359 if (IsUnboxedLoad() && compiler->is_optimizing()) { | 1483 if (IsUnboxedLoad() && compiler->is_optimizing()) { |
| 1360 UNIMPLEMENTED(); | 1484 const VRegister result = locs()->out(0).fpu_reg(); |
| 1485 const Register temp = locs()->temp(0).reg(); |
| 1486 __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes()); |
| 1487 const intptr_t cid = field()->UnboxedFieldCid(); |
| 1488 switch (cid) { |
| 1489 case kDoubleCid: |
| 1490 __ Comment("UnboxedDoubleLoadFieldInstr"); |
| 1491 __ LoadDFieldFromOffset(result, temp, Double::value_offset()); |
| 1492 break; |
| 1493 case kFloat32x4Cid: |
| 1494 case kFloat64x2Cid: |
| 1495 UNIMPLEMENTED(); |
| 1496 break; |
| 1497 default: |
| 1498 UNREACHABLE(); |
| 1499 } |
| 1500 return; |
| 1361 } | 1501 } |
| 1362 | 1502 |
| 1363 Label done; | 1503 Label done; |
| 1364 Register result_reg = locs()->out(0).reg(); | 1504 Register result_reg = locs()->out(0).reg(); |
| 1365 if (IsPotentialUnboxedLoad()) { | 1505 if (IsPotentialUnboxedLoad()) { |
| 1366 const Register temp = locs()->temp(0).reg(); | 1506 const Register temp = locs()->temp(1).reg(); |
| 1507 const VRegister value = locs()->temp(0).fpu_reg(); |
| 1367 | 1508 |
| 1368 Label load_pointer; | 1509 Label load_pointer; |
| 1369 Label load_double; | 1510 Label load_double; |
| 1370 Label load_float32x4; | 1511 Label load_float32x4; |
| 1371 Label load_float64x2; | 1512 Label load_float64x2; |
| 1372 | 1513 |
| 1373 __ LoadObject(result_reg, Field::ZoneHandle(field()->raw()), PP); | 1514 __ LoadObject(result_reg, Field::ZoneHandle(field()->raw()), PP); |
| 1374 | 1515 |
| 1375 FieldAddress field_cid_operand(result_reg, Field::guarded_cid_offset()); | 1516 FieldAddress field_cid_operand(result_reg, Field::guarded_cid_offset()); |
| 1376 FieldAddress field_nullability_operand(result_reg, | 1517 FieldAddress field_nullability_operand(result_reg, |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1392 __ CompareImmediate(temp, kFloat64x2Cid, PP); | 1533 __ CompareImmediate(temp, kFloat64x2Cid, PP); |
| 1393 __ b(&load_float64x2, EQ); | 1534 __ b(&load_float64x2, EQ); |
| 1394 | 1535 |
| 1395 // Fall through. | 1536 // Fall through. |
| 1396 __ b(&load_pointer); | 1537 __ b(&load_pointer); |
| 1397 | 1538 |
| 1398 if (!compiler->is_optimizing()) { | 1539 if (!compiler->is_optimizing()) { |
| 1399 locs()->live_registers()->Add(locs()->in(0)); | 1540 locs()->live_registers()->Add(locs()->in(0)); |
| 1400 } | 1541 } |
| 1401 | 1542 |
| 1402 // TODO(zra): Implement these when we add fpu loads and stores. | |
| 1403 { | 1543 { |
| 1404 __ Bind(&load_double); | 1544 __ Bind(&load_double); |
| 1405 __ hlt(0); // Unimplemented. | 1545 BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this); |
| 1546 compiler->AddSlowPathCode(slow_path); |
| 1547 |
| 1548 __ TryAllocate(compiler->double_class(), |
| 1549 slow_path->entry_label(), |
| 1550 result_reg, |
| 1551 temp, |
| 1552 PP); |
| 1553 __ Bind(slow_path->exit_label()); |
| 1554 __ LoadFieldFromOffset(temp, instance_reg, offset_in_bytes()); |
| 1555 __ LoadDFieldFromOffset(value, temp, Double::value_offset()); |
| 1556 __ StoreDFieldToOffset(value, result_reg, Double::value_offset()); |
| 1557 __ b(&done); |
| 1406 } | 1558 } |
| 1407 | 1559 |
| 1560 // TODO(zra): Implement these when we add simd loads and stores. |
| 1408 { | 1561 { |
| 1409 __ Bind(&load_float32x4); | 1562 __ Bind(&load_float32x4); |
| 1410 __ hlt(0); // Unimplemented. | 1563 __ hlt(0); // Unimplemented. |
| 1411 } | 1564 } |
| 1412 | 1565 |
| 1413 { | 1566 { |
| 1414 __ Bind(&load_float64x2); | 1567 __ Bind(&load_float64x2); |
| 1415 __ hlt(0); // Unimplemented. | 1568 __ hlt(0); // Unimplemented. |
| 1416 } | 1569 } |
| 1417 | 1570 |
| 1418 __ Bind(&load_pointer); | 1571 __ Bind(&load_pointer); |
| 1419 } | 1572 } |
| 1420 __ LoadFromOffset( | 1573 __ LoadFieldFromOffset(result_reg, instance_reg, offset_in_bytes()); |
| 1421 result_reg, instance_reg, offset_in_bytes() - kHeapObjectTag); | |
| 1422 __ Bind(&done); | 1574 __ Bind(&done); |
| 1423 } | 1575 } |
| 1424 | 1576 |
| 1425 | 1577 |
| 1426 LocationSummary* InstantiateTypeInstr::MakeLocationSummary(bool opt) const { | 1578 LocationSummary* InstantiateTypeInstr::MakeLocationSummary(bool opt) const { |
| 1427 UNIMPLEMENTED(); | 1579 UNIMPLEMENTED(); |
| 1428 return NULL; | 1580 return NULL; |
| 1429 } | 1581 } |
| 1430 | 1582 |
| 1431 | 1583 |
| (...skipping 1205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2637 compiler->GenerateCall(token_pos(), | 2789 compiler->GenerateCall(token_pos(), |
| 2638 &label, | 2790 &label, |
| 2639 PcDescriptors::kOther, | 2791 PcDescriptors::kOther, |
| 2640 locs()); | 2792 locs()); |
| 2641 __ Drop(ArgumentCount()); // Discard arguments. | 2793 __ Drop(ArgumentCount()); // Discard arguments. |
| 2642 } | 2794 } |
| 2643 | 2795 |
| 2644 } // namespace dart | 2796 } // namespace dart |
| 2645 | 2797 |
| 2646 #endif // defined TARGET_ARCH_ARM64 | 2798 #endif // defined TARGET_ARCH_ARM64 |
| OLD | NEW |