| 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 966 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 977 return kUnboxedFloat32x4; | 977 return kUnboxedFloat32x4; |
| 978 case kTypedDataFloat64x2ArrayCid: | 978 case kTypedDataFloat64x2ArrayCid: |
| 979 return kUnboxedFloat64x2; | 979 return kUnboxedFloat64x2; |
| 980 default: | 980 default: |
| 981 UNIMPLEMENTED(); | 981 UNIMPLEMENTED(); |
| 982 return kTagged; | 982 return kTagged; |
| 983 } | 983 } |
| 984 } | 984 } |
| 985 | 985 |
| 986 | 986 |
| 987 static bool CanBeImmediateIndex(Value* value, intptr_t cid, bool is_external) { |
| 988 ConstantInstr* constant = value->definition()->AsConstant(); |
| 989 if ((constant == NULL) || !constant->value().IsSmi()) { |
| 990 return false; |
| 991 } |
| 992 const int64_t index = Smi::Cast(constant->value()).AsInt64Value(); |
| 993 const intptr_t scale = Instance::ElementSizeFor(cid); |
| 994 const int64_t offset = index * scale + |
| 995 (is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag)); |
| 996 if (!Utils::IsInt(32, offset)) { |
| 997 return false; |
| 998 } |
| 999 return Address::CanHoldOffset(static_cast<int32_t>(offset), |
| 1000 Address::Offset, |
| 1001 Address::OperandSizeFor(cid)); |
| 1002 } |
| 1003 |
| 1004 |
| 987 LocationSummary* LoadIndexedInstr::MakeLocationSummary(Isolate* isolate, | 1005 LocationSummary* LoadIndexedInstr::MakeLocationSummary(Isolate* isolate, |
| 988 bool opt) const { | 1006 bool opt) const { |
| 989 const intptr_t kNumInputs = 2; | 1007 const intptr_t kNumInputs = 2; |
| 990 const intptr_t kNumTemps = 0; | 1008 const intptr_t kNumTemps = 0; |
| 991 LocationSummary* locs = new(isolate) LocationSummary( | 1009 LocationSummary* locs = new(isolate) LocationSummary( |
| 992 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1010 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 993 locs->set_in(0, Location::RequiresRegister()); | 1011 locs->set_in(0, Location::RequiresRegister()); |
| 994 // The smi index is either untagged (element size == 1), or it is left smi | 1012 if (CanBeImmediateIndex(index(), class_id(), IsExternal())) { |
| 995 // tagged (for all element sizes > 1). | 1013 locs->set_in(1, Location::Constant(index()->BoundConstant())); |
| 996 // TODO(regis): Revisit and see if the index can be immediate. | 1014 } else { |
| 997 locs->set_in(1, Location::WritableRegister()); | 1015 locs->set_in(1, Location::RequiresRegister()); |
| 1016 } |
| 998 if ((representation() == kUnboxedDouble) || | 1017 if ((representation() == kUnboxedDouble) || |
| 999 (representation() == kUnboxedFloat32x4) || | 1018 (representation() == kUnboxedFloat32x4) || |
| 1000 (representation() == kUnboxedInt32x4) || | 1019 (representation() == kUnboxedInt32x4) || |
| 1001 (representation() == kUnboxedFloat64x2)) { | 1020 (representation() == kUnboxedFloat64x2)) { |
| 1002 locs->set_out(0, Location::RequiresFpuRegister()); | 1021 locs->set_out(0, Location::RequiresFpuRegister()); |
| 1003 } else { | 1022 } else { |
| 1004 locs->set_out(0, Location::RequiresRegister()); | 1023 locs->set_out(0, Location::RequiresRegister()); |
| 1005 } | 1024 } |
| 1006 return locs; | 1025 return locs; |
| 1007 } | 1026 } |
| 1008 | 1027 |
| 1009 | 1028 |
| 1029 static Address ElementAddressForIntIndex(bool is_external, |
| 1030 intptr_t cid, |
| 1031 intptr_t index_scale, |
| 1032 Register array, |
| 1033 intptr_t index) { |
| 1034 const int64_t offset = index * index_scale + |
| 1035 (is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag)); |
| 1036 ASSERT(Utils::IsInt(32, offset)); |
| 1037 const OperandSize size = Address::OperandSizeFor(cid); |
| 1038 ASSERT(Address::CanHoldOffset(offset, Address::Offset, size)); |
| 1039 return Address(array, static_cast<int32_t>(offset), Address::Offset, size); |
| 1040 } |
| 1041 |
| 1042 |
| 1043 static Address ElementAddressForRegIndex(Assembler* assembler, |
| 1044 bool is_load, |
| 1045 bool is_external, |
| 1046 intptr_t cid, |
| 1047 intptr_t index_scale, |
| 1048 Register array, |
| 1049 Register index) { |
| 1050 // Note that index is expected smi-tagged, (i.e, LSL 1) for all arrays. |
| 1051 const intptr_t shift = Utils::ShiftForPowerOfTwo(index_scale) - kSmiTagShift; |
| 1052 const int32_t offset = |
| 1053 is_external ? 0 : (Instance::DataOffsetFor(cid) - kHeapObjectTag); |
| 1054 ASSERT(array != TMP); |
| 1055 ASSERT(index != TMP); |
| 1056 const Register base = is_load ? TMP : index; |
| 1057 if ((offset == 0) && (shift == 0)) { |
| 1058 return Address(array, index, UXTX, Address::Unscaled); |
| 1059 } else if (shift < 0) { |
| 1060 ASSERT(shift == -1); |
| 1061 assembler->add(base, array, Operand(index, ASR, 1)); |
| 1062 } else { |
| 1063 assembler->add(base, array, Operand(index, LSL, shift)); |
| 1064 } |
| 1065 const OperandSize size = Address::OperandSizeFor(cid); |
| 1066 ASSERT(Address::CanHoldOffset(offset, Address::Offset, size)); |
| 1067 return Address(base, offset, Address::Offset, size); |
| 1068 } |
| 1069 |
| 1070 |
| 1010 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1071 void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1072 // The array register points to the backing store for external arrays. |
| 1011 const Register array = locs()->in(0).reg(); | 1073 const Register array = locs()->in(0).reg(); |
| 1012 ASSERT(locs()->in(1).IsRegister()); // TODO(regis): Revisit. | 1074 const Location index = locs()->in(1); |
| 1013 const Register index = locs()->in(1).reg(); | |
| 1014 | 1075 |
| 1015 Address element_address(kNoRegister, 0); | 1076 Address element_address = index.IsRegister() |
| 1016 | 1077 ? ElementAddressForRegIndex(compiler->assembler(), |
| 1017 // The array register points to the backing store for external arrays. | 1078 true, // Load. |
| 1018 intptr_t offset = 0; | 1079 IsExternal(), class_id(), index_scale(), |
| 1019 if (!IsExternal()) { | 1080 array, index.reg()) |
| 1020 ASSERT(this->array()->definition()->representation() == kTagged); | 1081 : ElementAddressForIntIndex(IsExternal(), class_id(), index_scale(), |
| 1021 offset = Instance::DataOffsetFor(class_id()) - kHeapObjectTag; | 1082 array, Smi::Cast(index.constant()).Value()); |
| 1022 } | 1083 // Warning: element_address may use register TMP as base. |
| 1023 | |
| 1024 // Note that index is expected smi-tagged, (i.e, times 2) for all arrays | |
| 1025 // with index scale factor > 1. E.g., for Uint8Array and OneByteString the | |
| 1026 // index is expected to be untagged before accessing. | |
| 1027 ASSERT(kSmiTagShift == 1); | |
| 1028 switch (index_scale()) { | |
| 1029 case 1: | |
| 1030 __ add(index, array, Operand(index, ASR, kSmiTagSize)); | |
| 1031 element_address = Address(index, offset); | |
| 1032 break; | |
| 1033 case 2: | |
| 1034 if (offset != 0) { | |
| 1035 __ add(index, array, Operand(index)); | |
| 1036 element_address = Address(index, offset); | |
| 1037 } else { | |
| 1038 element_address = Address(array, index, UXTX, Address::Unscaled); | |
| 1039 } | |
| 1040 break; | |
| 1041 case 4: | |
| 1042 __ add(index, array, Operand(index, LSL, 1)); | |
| 1043 element_address = Address(index, offset); | |
| 1044 break; | |
| 1045 case 8: | |
| 1046 __ add(index, array, Operand(index, LSL, 2)); | |
| 1047 element_address = Address(index, offset); | |
| 1048 break; | |
| 1049 case 16: | |
| 1050 __ add(index, array, Operand(index, LSL, 3)); | |
| 1051 element_address = Address(index, offset); | |
| 1052 break; | |
| 1053 default: | |
| 1054 UNREACHABLE(); | |
| 1055 } | |
| 1056 | 1084 |
| 1057 if ((representation() == kUnboxedDouble) || | 1085 if ((representation() == kUnboxedDouble) || |
| 1058 (representation() == kUnboxedFloat32x4) || | 1086 (representation() == kUnboxedFloat32x4) || |
| 1059 (representation() == kUnboxedInt32x4) || | 1087 (representation() == kUnboxedInt32x4) || |
| 1060 (representation() == kUnboxedFloat64x2)) { | 1088 (representation() == kUnboxedFloat64x2)) { |
| 1061 const VRegister result = locs()->out(0).fpu_reg(); | 1089 const VRegister result = locs()->out(0).fpu_reg(); |
| 1062 switch (class_id()) { | 1090 switch (class_id()) { |
| 1063 case kTypedDataFloat32ArrayCid: | 1091 case kTypedDataFloat32ArrayCid: |
| 1064 // Load single precision float. | 1092 // Load single precision float. |
| 1065 __ fldrs(result, element_address); | 1093 __ fldrs(result, element_address); |
| 1066 break; | 1094 break; |
| 1067 case kTypedDataFloat64ArrayCid: | 1095 case kTypedDataFloat64ArrayCid: |
| 1068 // Load double precision float. | 1096 // Load double precision float. |
| 1069 __ fldrd(result, element_address); | 1097 __ fldrd(result, element_address); |
| 1070 break; | 1098 break; |
| 1071 case kTypedDataFloat64x2ArrayCid: | 1099 case kTypedDataFloat64x2ArrayCid: |
| 1072 case kTypedDataInt32x4ArrayCid: | 1100 case kTypedDataInt32x4ArrayCid: |
| 1073 case kTypedDataFloat32x4ArrayCid: | 1101 case kTypedDataFloat32x4ArrayCid: |
| 1074 __ fldrq(result, element_address); | 1102 __ fldrq(result, element_address); |
| 1075 break; | 1103 break; |
| 1104 default: |
| 1105 UNREACHABLE(); |
| 1076 } | 1106 } |
| 1077 return; | 1107 return; |
| 1078 } | 1108 } |
| 1079 | 1109 |
| 1080 const Register result = locs()->out(0).reg(); | 1110 const Register result = locs()->out(0).reg(); |
| 1081 switch (class_id()) { | 1111 switch (class_id()) { |
| 1082 case kTypedDataInt8ArrayCid: | 1112 case kTypedDataInt8ArrayCid: |
| 1083 ASSERT(index_scale() == 1); | 1113 ASSERT(index_scale() == 1); |
| 1084 __ ldr(result, element_address, kByte); | 1114 __ ldr(result, element_address, kByte); |
| 1085 __ SmiTag(result); | 1115 __ SmiTag(result); |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1153 } | 1183 } |
| 1154 | 1184 |
| 1155 | 1185 |
| 1156 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Isolate* isolate, | 1186 LocationSummary* StoreIndexedInstr::MakeLocationSummary(Isolate* isolate, |
| 1157 bool opt) const { | 1187 bool opt) const { |
| 1158 const intptr_t kNumInputs = 3; | 1188 const intptr_t kNumInputs = 3; |
| 1159 const intptr_t kNumTemps = 0; | 1189 const intptr_t kNumTemps = 0; |
| 1160 LocationSummary* locs = new(isolate) LocationSummary( | 1190 LocationSummary* locs = new(isolate) LocationSummary( |
| 1161 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1191 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 1162 locs->set_in(0, Location::RequiresRegister()); | 1192 locs->set_in(0, Location::RequiresRegister()); |
| 1163 // The smi index is either untagged (element size == 1), or it is left smi | 1193 if (CanBeImmediateIndex(index(), class_id(), IsExternal())) { |
| 1164 // tagged (for all element sizes > 1). | 1194 locs->set_in(1, Location::Constant(index()->BoundConstant())); |
| 1165 // TODO(regis): Revisit and see if the index can be immediate. | 1195 } else { |
| 1166 locs->set_in(1, Location::WritableRegister()); | 1196 locs->set_in(1, Location::WritableRegister()); |
| 1197 } |
| 1167 switch (class_id()) { | 1198 switch (class_id()) { |
| 1168 case kArrayCid: | 1199 case kArrayCid: |
| 1169 locs->set_in(2, ShouldEmitStoreBarrier() | 1200 locs->set_in(2, ShouldEmitStoreBarrier() |
| 1170 ? Location::WritableRegister() | 1201 ? Location::WritableRegister() |
| 1171 : Location::RegisterOrConstant(value())); | 1202 : Location::RegisterOrConstant(value())); |
| 1172 break; | 1203 break; |
| 1173 case kExternalTypedDataUint8ArrayCid: | 1204 case kExternalTypedDataUint8ArrayCid: |
| 1174 case kExternalTypedDataUint8ClampedArrayCid: | 1205 case kExternalTypedDataUint8ClampedArrayCid: |
| 1175 case kTypedDataInt8ArrayCid: | 1206 case kTypedDataInt8ArrayCid: |
| 1176 case kTypedDataUint8ArrayCid: | 1207 case kTypedDataUint8ArrayCid: |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1195 break; | 1226 break; |
| 1196 default: | 1227 default: |
| 1197 UNREACHABLE(); | 1228 UNREACHABLE(); |
| 1198 return NULL; | 1229 return NULL; |
| 1199 } | 1230 } |
| 1200 return locs; | 1231 return locs; |
| 1201 } | 1232 } |
| 1202 | 1233 |
| 1203 | 1234 |
| 1204 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1235 void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1236 // The array register points to the backing store for external arrays. |
| 1205 const Register array = locs()->in(0).reg(); | 1237 const Register array = locs()->in(0).reg(); |
| 1206 ASSERT(locs()->in(1).IsRegister()); // TODO(regis): Revisit. | 1238 const Location index = locs()->in(1); |
| 1207 const Register index = locs()->in(1).reg(); | |
| 1208 | 1239 |
| 1209 Address element_address(kNoRegister, 0); | 1240 Address element_address = index.IsRegister() |
| 1210 | 1241 ? ElementAddressForRegIndex(compiler->assembler(), |
| 1211 // The array register points to the backing store for external arrays. | 1242 false, // Store. |
| 1212 intptr_t offset = 0; | 1243 IsExternal(), class_id(), index_scale(), |
| 1213 if (!IsExternal()) { | 1244 array, index.reg()) |
| 1214 ASSERT(this->array()->definition()->representation() == kTagged); | 1245 : ElementAddressForIntIndex(IsExternal(), class_id(), index_scale(), |
| 1215 offset = Instance::DataOffsetFor(class_id()) - kHeapObjectTag; | 1246 array, Smi::Cast(index.constant()).Value()); |
| 1216 } | |
| 1217 | |
| 1218 // Note that index is expected smi-tagged, (i.e, times 2) for all arrays | |
| 1219 // with index scale factor > 1. E.g., for Uint8Array and OneByteString the | |
| 1220 // index is expected to be untagged before accessing. | |
| 1221 ASSERT(kSmiTagShift == 1); | |
| 1222 switch (index_scale()) { | |
| 1223 case 1: { | |
| 1224 __ add(index, array, Operand(index, ASR, kSmiTagSize)); | |
| 1225 element_address = Address(index, offset); | |
| 1226 break; | |
| 1227 } | |
| 1228 case 2: { | |
| 1229 if (offset != 0) { | |
| 1230 __ add(index, array, Operand(index)); | |
| 1231 element_address = Address(index, offset); | |
| 1232 } else { | |
| 1233 element_address = Address(array, index, UXTX, Address::Unscaled); | |
| 1234 } | |
| 1235 break; | |
| 1236 } | |
| 1237 case 4: { | |
| 1238 __ add(index, array, Operand(index, LSL, 1)); | |
| 1239 element_address = Address(index, offset); | |
| 1240 break; | |
| 1241 } | |
| 1242 case 8: { | |
| 1243 __ add(index, array, Operand(index, LSL, 2)); | |
| 1244 element_address = Address(index, offset); | |
| 1245 break; | |
| 1246 } | |
| 1247 case 16: { | |
| 1248 __ add(index, array, Operand(index, LSL, 3)); | |
| 1249 element_address = Address(index, offset); | |
| 1250 break; | |
| 1251 } | |
| 1252 default: | |
| 1253 UNREACHABLE(); | |
| 1254 } | |
| 1255 | 1247 |
| 1256 switch (class_id()) { | 1248 switch (class_id()) { |
| 1257 case kArrayCid: | 1249 case kArrayCid: |
| 1258 if (ShouldEmitStoreBarrier()) { | 1250 if (ShouldEmitStoreBarrier()) { |
| 1259 const Register value = locs()->in(2).reg(); | 1251 const Register value = locs()->in(2).reg(); |
| 1260 __ StoreIntoObject(array, element_address, value); | 1252 __ StoreIntoObject(array, element_address, value); |
| 1261 } else if (locs()->in(2).IsConstant()) { | 1253 } else if (locs()->in(2).IsConstant()) { |
| 1262 const Object& constant = locs()->in(2).constant(); | 1254 const Object& constant = locs()->in(2).constant(); |
| 1263 __ StoreIntoObjectNoBarrier(array, element_address, constant); | 1255 __ StoreIntoObjectNoBarrier(array, element_address, constant); |
| 1264 } else { | 1256 } else { |
| (...skipping 4144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5409 compiler->GenerateCall(token_pos(), | 5401 compiler->GenerateCall(token_pos(), |
| 5410 &label, | 5402 &label, |
| 5411 PcDescriptors::kOther, | 5403 PcDescriptors::kOther, |
| 5412 locs()); | 5404 locs()); |
| 5413 __ Drop(ArgumentCount()); // Discard arguments. | 5405 __ Drop(ArgumentCount()); // Discard arguments. |
| 5414 } | 5406 } |
| 5415 | 5407 |
| 5416 } // namespace dart | 5408 } // namespace dart |
| 5417 | 5409 |
| 5418 #endif // defined TARGET_ARCH_ARM64 | 5410 #endif // defined TARGET_ARCH_ARM64 |
| OLD | NEW |