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)); | |
zra
2014/09/10 23:17:22
Not sure if this helps you any, but if you specify
Vyacheslav Egorov (Google)
2014/09/11 11:49:17
I am doing int64 -> int32 convertion here. What I
| |
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 |