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 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
281 if (!locs()->out(0).IsInvalid()) { | 281 if (!locs()->out(0).IsInvalid()) { |
282 const Register result = locs()->out(0).reg(); | 282 const Register result = locs()->out(0).reg(); |
283 __ LoadObject(result, value(), PP); | 283 __ LoadObject(result, value(), PP); |
284 } | 284 } |
285 } | 285 } |
286 | 286 |
287 | 287 |
288 LocationSummary* UnboxedConstantInstr::MakeLocationSummary(Isolate* isolate, | 288 LocationSummary* UnboxedConstantInstr::MakeLocationSummary(Isolate* isolate, |
289 bool opt) const { | 289 bool opt) const { |
290 const intptr_t kNumInputs = 0; | 290 const intptr_t kNumInputs = 0; |
| 291 const Location out = (representation_ == kUnboxedInt32) ? |
| 292 Location::RequiresRegister() : Location::RequiresFpuRegister(); |
291 return LocationSummary::Make(isolate, | 293 return LocationSummary::Make(isolate, |
292 kNumInputs, | 294 kNumInputs, |
293 Location::RequiresFpuRegister(), | 295 out, |
294 LocationSummary::kNoCall); | 296 LocationSummary::kNoCall); |
295 } | 297 } |
296 | 298 |
297 | 299 |
298 void UnboxedConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 300 void UnboxedConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
299 ASSERT(representation_ == kUnboxedDouble); | |
300 if (!locs()->out(0).IsInvalid()) { | 301 if (!locs()->out(0).IsInvalid()) { |
301 if (Utils::DoublesBitEqual(Double::Cast(value()).value(), 0.0)) { | 302 switch (representation_) { |
302 const VRegister dst = locs()->out(0).fpu_reg(); | 303 case kUnboxedDouble: |
303 __ veor(dst, dst, dst); | 304 if (Utils::DoublesBitEqual(Double::Cast(value()).value(), 0.0)) { |
304 } else { | 305 const VRegister dst = locs()->out(0).fpu_reg(); |
305 const VRegister dst = locs()->out(0).fpu_reg(); | 306 __ veor(dst, dst, dst); |
306 __ LoadDImmediate(dst, Double::Cast(value()).value(), PP); | 307 } else { |
| 308 const VRegister dst = locs()->out(0).fpu_reg(); |
| 309 __ LoadDImmediate(dst, Double::Cast(value()).value(), PP); |
| 310 } |
| 311 break; |
| 312 case kUnboxedInt32: |
| 313 __ LoadImmediate(locs()->out(0).reg(), |
| 314 static_cast<int32_t>(Smi::Cast(value()).Value()), |
| 315 PP); |
| 316 break; |
| 317 default: |
| 318 UNREACHABLE(); |
| 319 break; |
307 } | 320 } |
308 } | 321 } |
309 } | 322 } |
310 | 323 |
311 | 324 |
312 LocationSummary* AssertAssignableInstr::MakeLocationSummary(Isolate* isolate, | 325 LocationSummary* AssertAssignableInstr::MakeLocationSummary(Isolate* isolate, |
313 bool opt) const { | 326 bool opt) const { |
314 const intptr_t kNumInputs = 3; | 327 const intptr_t kNumInputs = 3; |
315 const intptr_t kNumTemps = 0; | 328 const intptr_t kNumTemps = 0; |
316 LocationSummary* summary = new(isolate) LocationSummary( | 329 LocationSummary* summary = new(isolate) LocationSummary( |
(...skipping 806 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1123 switch (class_id_) { | 1136 switch (class_id_) { |
1124 case kArrayCid: | 1137 case kArrayCid: |
1125 case kOneByteStringCid: | 1138 case kOneByteStringCid: |
1126 case kTypedDataInt8ArrayCid: | 1139 case kTypedDataInt8ArrayCid: |
1127 case kTypedDataUint8ArrayCid: | 1140 case kTypedDataUint8ArrayCid: |
1128 case kExternalTypedDataUint8ArrayCid: | 1141 case kExternalTypedDataUint8ArrayCid: |
1129 case kTypedDataUint8ClampedArrayCid: | 1142 case kTypedDataUint8ClampedArrayCid: |
1130 case kExternalTypedDataUint8ClampedArrayCid: | 1143 case kExternalTypedDataUint8ClampedArrayCid: |
1131 case kTypedDataInt16ArrayCid: | 1144 case kTypedDataInt16ArrayCid: |
1132 case kTypedDataUint16ArrayCid: | 1145 case kTypedDataUint16ArrayCid: |
| 1146 return kTagged; |
1133 case kTypedDataInt32ArrayCid: | 1147 case kTypedDataInt32ArrayCid: |
| 1148 return kUnboxedInt32; |
1134 case kTypedDataUint32ArrayCid: | 1149 case kTypedDataUint32ArrayCid: |
1135 return kTagged; | 1150 return kUnboxedUint32; |
1136 case kTypedDataFloat32ArrayCid: | 1151 case kTypedDataFloat32ArrayCid: |
1137 case kTypedDataFloat64ArrayCid: | 1152 case kTypedDataFloat64ArrayCid: |
1138 return kUnboxedDouble; | 1153 return kUnboxedDouble; |
1139 case kTypedDataFloat32x4ArrayCid: | 1154 case kTypedDataFloat32x4ArrayCid: |
1140 return kUnboxedFloat32x4; | 1155 return kUnboxedFloat32x4; |
1141 case kTypedDataInt32x4ArrayCid: | 1156 case kTypedDataInt32x4ArrayCid: |
1142 return kUnboxedInt32x4; | 1157 return kUnboxedInt32x4; |
1143 case kTypedDataFloat64x2ArrayCid: | 1158 case kTypedDataFloat64x2ArrayCid: |
1144 return kUnboxedFloat64x2; | 1159 return kUnboxedFloat64x2; |
1145 default: | 1160 default: |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1264 case kTypedDataInt16ArrayCid: | 1279 case kTypedDataInt16ArrayCid: |
1265 case kTypedDataUint16ArrayCid: { | 1280 case kTypedDataUint16ArrayCid: { |
1266 const Register value = locs()->in(2).reg(); | 1281 const Register value = locs()->in(2).reg(); |
1267 __ SmiUntag(TMP, value); | 1282 __ SmiUntag(TMP, value); |
1268 __ str(TMP, element_address, kUnsignedHalfword); | 1283 __ str(TMP, element_address, kUnsignedHalfword); |
1269 break; | 1284 break; |
1270 } | 1285 } |
1271 case kTypedDataInt32ArrayCid: | 1286 case kTypedDataInt32ArrayCid: |
1272 case kTypedDataUint32ArrayCid: { | 1287 case kTypedDataUint32ArrayCid: { |
1273 const Register value = locs()->in(2).reg(); | 1288 const Register value = locs()->in(2).reg(); |
1274 __ SmiUntag(TMP, value); | 1289 __ str(value, element_address, kUnsignedWord); |
1275 __ str(TMP, element_address, kUnsignedWord); | |
1276 break; | 1290 break; |
1277 } | 1291 } |
1278 case kTypedDataFloat32ArrayCid: { | 1292 case kTypedDataFloat32ArrayCid: { |
1279 const VRegister value_reg = locs()->in(2).fpu_reg(); | 1293 const VRegister value_reg = locs()->in(2).fpu_reg(); |
1280 __ fstrs(value_reg, element_address); | 1294 __ fstrs(value_reg, element_address); |
1281 break; | 1295 break; |
1282 } | 1296 } |
1283 case kTypedDataFloat64ArrayCid: { | 1297 case kTypedDataFloat64ArrayCid: { |
1284 const VRegister value_reg = locs()->in(2).fpu_reg(); | 1298 const VRegister value_reg = locs()->in(2).fpu_reg(); |
1285 __ fstrd(value_reg, element_address); | 1299 __ fstrd(value_reg, element_address); |
(...skipping 3864 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5150 | 5164 |
5151 | 5165 |
5152 CompileType UnaryUint32OpInstr::ComputeType() const { | 5166 CompileType UnaryUint32OpInstr::ComputeType() const { |
5153 return CompileType::FromCid(kSmiCid); | 5167 return CompileType::FromCid(kSmiCid); |
5154 } | 5168 } |
5155 | 5169 |
5156 | 5170 |
5157 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryUint32OpInstr) | 5171 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryUint32OpInstr) |
5158 DEFINE_UNIMPLEMENTED_INSTRUCTION(ShiftUint32OpInstr) | 5172 DEFINE_UNIMPLEMENTED_INSTRUCTION(ShiftUint32OpInstr) |
5159 DEFINE_UNIMPLEMENTED_INSTRUCTION(UnaryUint32OpInstr) | 5173 DEFINE_UNIMPLEMENTED_INSTRUCTION(UnaryUint32OpInstr) |
5160 DEFINE_UNIMPLEMENTED_INSTRUCTION(BoxInt32Instr) | |
5161 DEFINE_UNIMPLEMENTED_INSTRUCTION(UnboxInt32Instr) | |
5162 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryInt32OpInstr) | 5174 DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryInt32OpInstr) |
5163 DEFINE_UNIMPLEMENTED_INSTRUCTION(BoxUint32Instr) | |
5164 DEFINE_UNIMPLEMENTED_INSTRUCTION(UnboxedIntConverterInstr) | |
5165 | 5175 |
5166 | 5176 |
5167 LocationSummary* UnboxUint32Instr::MakeLocationSummary(Isolate* isolate, | 5177 LocationSummary* UnboxIntNInstr::MakeLocationSummary(Isolate* isolate, |
5168 bool opt) const { | 5178 bool opt) const { |
5169 const intptr_t kNumInputs = 1; | 5179 const intptr_t kNumInputs = 1; |
5170 const intptr_t kNumTemps = 0; | 5180 const intptr_t kNumTemps = 0; |
5171 LocationSummary* summary = new(isolate) LocationSummary( | 5181 LocationSummary* summary = new(isolate) LocationSummary( |
5172 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5182 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5173 summary->set_in(0, Location::RequiresRegister()); | 5183 summary->set_in(0, Location::RequiresRegister()); |
5174 summary->set_out(0, Location::SameAsFirstInput()); | 5184 summary->set_out(0, Location::RequiresRegister()); |
5175 return summary; | 5185 return summary; |
5176 } | 5186 } |
5177 | 5187 |
5178 | 5188 |
5179 void UnboxUint32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5189 void UnboxIntNInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5180 const intptr_t value_cid = value()->Type()->ToCid(); | 5190 const intptr_t value_cid = value()->Type()->ToCid(); |
| 5191 const Register out = locs()->out(0).reg(); |
5181 const Register value = locs()->in(0).reg(); | 5192 const Register value = locs()->in(0).reg(); |
5182 ASSERT(value == locs()->out(0).reg()); | 5193 Label* deopt = CanDeoptimize() ? |
| 5194 compiler->AddDeoptStub(deopt_id_, ICData::kDeoptUnboxInteger) : NULL; |
5183 | 5195 |
5184 if (value_cid == kSmiCid) { | 5196 if (value_cid == kSmiCid) { |
5185 __ SmiUntag(value); | 5197 __ SmiUntag(out, value); |
| 5198 } else if (value_cid == kMintCid) { |
| 5199 __ LoadFieldFromOffset(out, value, Mint::value_offset(), PP); |
5186 } else { | 5200 } else { |
5187 Label* deopt = compiler->AddDeoptStub(deopt_id_, | 5201 Label done; |
5188 ICData::kDeoptUnboxInteger); | 5202 __ SmiUntag(out, value); |
5189 __ tsti(value, kSmiTagMask); | 5203 __ TestImmediate(value, kSmiTagMask, PP); |
| 5204 __ b(&done, EQ); |
| 5205 __ CompareClassId(value, kMintCid, PP); |
5190 __ b(deopt, NE); | 5206 __ b(deopt, NE); |
5191 __ SmiUntag(value); | 5207 __ LoadFieldFromOffset(out, value, Mint::value_offset(), PP); |
| 5208 __ Bind(&done); |
| 5209 } |
| 5210 |
| 5211 // TODO(vegorov): as it is implemented right now truncating unboxing would |
| 5212 // leave "garbage" in the higher word. |
| 5213 if (!is_truncating() && (deopt != NULL)) { |
| 5214 ASSERT(representation() == kUnboxedInt32); |
| 5215 __ cmp(out, Operand(out, SXTW, 0)); |
| 5216 __ b(deopt, NE); |
5192 } | 5217 } |
5193 } | 5218 } |
5194 | 5219 |
| 5220 |
| 5221 LocationSummary* BoxIntNInstr::MakeLocationSummary(Isolate* isolate, |
| 5222 bool opt) const { |
| 5223 ASSERT((from_representation() == kUnboxedInt32) || |
| 5224 (from_representation() == kUnboxedUint32)); |
| 5225 const intptr_t kNumInputs = 1; |
| 5226 const intptr_t kNumTemps = 0; |
| 5227 LocationSummary* summary = new(isolate) LocationSummary( |
| 5228 isolate, |
| 5229 kNumInputs, |
| 5230 kNumTemps, |
| 5231 LocationSummary::kNoCall); |
| 5232 summary->set_in(0, Location::RequiresRegister()); |
| 5233 summary->set_out(0, Location::RequiresRegister()); |
| 5234 return summary; |
| 5235 } |
| 5236 |
| 5237 |
| 5238 void BoxIntNInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5239 Register value = locs()->in(0).reg(); |
| 5240 Register out = locs()->out(0).reg(); |
| 5241 ASSERT(value != out); |
| 5242 |
| 5243 ASSERT(kSmiTagSize == 1); |
| 5244 // TODO(vegorov) implement and use UBFM/SBFM for this. |
| 5245 __ Lsl(out, value, 32); |
| 5246 if (from_representation() == kUnboxedInt32) { |
| 5247 __ Asr(out, out, 32 - kSmiTagSize); |
| 5248 } else { |
| 5249 ASSERT(from_representation() == kUnboxedUint32); |
| 5250 __ Lsr(out, out, 32 - kSmiTagSize); |
| 5251 } |
| 5252 } |
| 5253 |
| 5254 |
| 5255 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Isolate* isolate, |
| 5256 bool opt) const { |
| 5257 const intptr_t kNumInputs = 1; |
| 5258 const intptr_t kNumTemps = 0; |
| 5259 LocationSummary* summary = new(isolate) LocationSummary( |
| 5260 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5261 if (from() == kUnboxedMint) { |
| 5262 UNREACHABLE(); |
| 5263 } else if (to() == kUnboxedMint) { |
| 5264 UNREACHABLE(); |
| 5265 } else { |
| 5266 ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32)); |
| 5267 ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32)); |
| 5268 summary->set_in(0, Location::RequiresRegister()); |
| 5269 summary->set_out(0, Location::RequiresRegister()); |
| 5270 } |
| 5271 return summary; |
| 5272 } |
| 5273 |
| 5274 |
| 5275 void UnboxedIntConverterInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5276 if (from() == kUnboxedInt32 && to() == kUnboxedUint32) { |
| 5277 const Register value = locs()->in(0).reg(); |
| 5278 const Register out = locs()->out(0).reg(); |
| 5279 // Representations are bitwise equivalent but we want to normalize |
| 5280 // upperbits for safety reasons. |
| 5281 // TODO(vegorov) if we ensure that we never use kDoubleWord size |
| 5282 // with it then we could avoid this. |
| 5283 // TODO(vegorov) implement and use UBFM for zero extension. |
| 5284 __ Lsl(out, value, 32); |
| 5285 __ Lsr(out, out, 32); |
| 5286 } else if (from() == kUnboxedUint32 && to() == kUnboxedInt32) { |
| 5287 // Representations are bitwise equivalent. |
| 5288 // TODO(vegorov) if we ensure that we never use kDoubleWord size |
| 5289 // with it then we could avoid this. |
| 5290 // TODO(vegorov) implement and use SBFM for sign extension. |
| 5291 const Register value = locs()->in(0).reg(); |
| 5292 const Register out = locs()->out(0).reg(); |
| 5293 __ Lsl(out, value, 32); |
| 5294 __ Asr(out, out, 32); |
| 5295 if (CanDeoptimize()) { |
| 5296 Label* deopt = |
| 5297 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnboxInteger); |
| 5298 __ cmp(out, Operand(value, UXTW, 0)); |
| 5299 __ b(deopt, NE); |
| 5300 } |
| 5301 } else if (from() == kUnboxedMint) { |
| 5302 UNREACHABLE(); |
| 5303 } else if (to() == kUnboxedMint) { |
| 5304 ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32)); |
| 5305 UNREACHABLE(); |
| 5306 } else { |
| 5307 UNREACHABLE(); |
| 5308 } |
| 5309 } |
| 5310 |
5195 | 5311 |
5196 LocationSummary* ThrowInstr::MakeLocationSummary(Isolate* isolate, | 5312 LocationSummary* ThrowInstr::MakeLocationSummary(Isolate* isolate, |
5197 bool opt) const { | 5313 bool opt) const { |
5198 return new(isolate) LocationSummary(isolate, 0, 0, LocationSummary::kCall); | 5314 return new(isolate) LocationSummary(isolate, 0, 0, LocationSummary::kCall); |
5199 } | 5315 } |
5200 | 5316 |
5201 | 5317 |
5202 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5318 void ThrowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5203 compiler->GenerateRuntimeCall(token_pos(), | 5319 compiler->GenerateRuntimeCall(token_pos(), |
5204 deopt_id(), | 5320 deopt_id(), |
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5427 compiler->GenerateCall(token_pos(), &label, stub_kind_, locs()); | 5543 compiler->GenerateCall(token_pos(), &label, stub_kind_, locs()); |
5428 #if defined(DEBUG) | 5544 #if defined(DEBUG) |
5429 __ LoadImmediate(R4, kInvalidObjectPointer, kNoPP); | 5545 __ LoadImmediate(R4, kInvalidObjectPointer, kNoPP); |
5430 __ LoadImmediate(R5, kInvalidObjectPointer, kNoPP); | 5546 __ LoadImmediate(R5, kInvalidObjectPointer, kNoPP); |
5431 #endif | 5547 #endif |
5432 } | 5548 } |
5433 | 5549 |
5434 } // namespace dart | 5550 } // namespace dart |
5435 | 5551 |
5436 #endif // defined TARGET_ARCH_ARM64 | 5552 #endif // defined TARGET_ARCH_ARM64 |
OLD | NEW |