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_ARM. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. |
6 #if defined(TARGET_ARCH_ARM) | 6 #if defined(TARGET_ARCH_ARM) |
7 | 7 |
8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
9 | 9 |
10 #include "vm/cpu.h" | 10 #include "vm/cpu.h" |
(...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
298 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 298 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
299 locs->set_out(0, Location::RequiresFpuRegister()); | 299 locs->set_out(0, Location::RequiresFpuRegister()); |
300 locs->set_temp(0, Location::RequiresRegister()); | 300 locs->set_temp(0, Location::RequiresRegister()); |
301 return locs; | 301 return locs; |
302 } | 302 } |
303 | 303 |
304 | 304 |
305 void UnboxedConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 305 void UnboxedConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
306 // The register allocator drops constant definitions that have no uses. | 306 // The register allocator drops constant definitions that have no uses. |
307 if (!locs()->out(0).IsInvalid()) { | 307 if (!locs()->out(0).IsInvalid()) { |
308 if (Utils::DoublesBitEqual(Double::Cast(value()).value(), 0.0) && | 308 switch (representation_) { |
309 TargetCPUFeatures::neon_supported()) { | 309 case kUnboxedDouble: |
310 const QRegister dst = locs()->out(0).fpu_reg(); | 310 if (Utils::DoublesBitEqual(Double::Cast(value()).value(), 0.0) && |
311 __ veorq(dst, dst, dst); | 311 TargetCPUFeatures::neon_supported()) { |
312 } else { | 312 const QRegister dst = locs()->out(0).fpu_reg(); |
313 const DRegister dst = EvenDRegisterOf(locs()->out(0).fpu_reg()); | 313 __ veorq(dst, dst, dst); |
314 const Register temp = locs()->temp(0).reg(); | 314 } else { |
315 __ LoadDImmediate(dst, Double::Cast(value()).value(), temp); | 315 const DRegister dst = EvenDRegisterOf(locs()->out(0).fpu_reg()); |
316 const Register temp = locs()->temp(0).reg(); | |
317 __ LoadDImmediate(dst, Double::Cast(value()).value(), temp); | |
318 } | |
319 break; | |
320 case kUnboxedInt32: | |
321 __ LoadImmediate(locs()->out(0).reg(), Smi::Cast(value()).Value()); | |
322 break; | |
323 default: | |
324 UNREACHABLE(); | |
325 break; | |
316 } | 326 } |
317 } | 327 } |
318 } | 328 } |
319 | 329 |
320 | 330 |
321 LocationSummary* AssertAssignableInstr::MakeLocationSummary(Isolate* isolate, | 331 LocationSummary* AssertAssignableInstr::MakeLocationSummary(Isolate* isolate, |
322 bool opt) const { | 332 bool opt) const { |
323 const intptr_t kNumInputs = 3; | 333 const intptr_t kNumInputs = 3; |
324 const intptr_t kNumTemps = 0; | 334 const intptr_t kNumTemps = 0; |
325 LocationSummary* summary = new(isolate) LocationSummary( | 335 LocationSummary* summary = new(isolate) LocationSummary( |
(...skipping 853 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1179 const intptr_t kNumInputs = 2; | 1189 const intptr_t kNumInputs = 2; |
1180 const intptr_t kNumTemps = 0; | 1190 const intptr_t kNumTemps = 0; |
1181 LocationSummary* locs = new(isolate) LocationSummary( | 1191 LocationSummary* locs = new(isolate) LocationSummary( |
1182 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1192 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
1183 locs->set_in(0, Location::RequiresRegister()); | 1193 locs->set_in(0, Location::RequiresRegister()); |
1184 bool needs_base = false; | 1194 bool needs_base = false; |
1185 if (CanBeImmediateIndex(index(), class_id(), IsExternal(), | 1195 if (CanBeImmediateIndex(index(), class_id(), IsExternal(), |
1186 true, // Load. | 1196 true, // Load. |
1187 &needs_base)) { | 1197 &needs_base)) { |
1188 // CanBeImmediateIndex must return false for unsafe smis. | 1198 // CanBeImmediateIndex must return false for unsafe smis. |
1189 locs->set_in(1, Location::Constant(index()->BoundConstant())); | 1199 locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); |
1190 } else { | 1200 } else { |
1191 locs->set_in(1, Location::RequiresRegister()); | 1201 locs->set_in(1, Location::RequiresRegister()); |
1192 } | 1202 } |
1193 if ((representation() == kUnboxedDouble) || | 1203 if ((representation() == kUnboxedDouble) || |
1194 (representation() == kUnboxedFloat32x4) || | 1204 (representation() == kUnboxedFloat32x4) || |
1195 (representation() == kUnboxedInt32x4) || | 1205 (representation() == kUnboxedInt32x4) || |
1196 (representation() == kUnboxedFloat64x2)) { | 1206 (representation() == kUnboxedFloat64x2)) { |
1197 if (class_id() == kTypedDataFloat32ArrayCid) { | 1207 if (class_id() == kTypedDataFloat32ArrayCid) { |
1198 // Need register <= Q7 for float operations. | 1208 // Need register <= Q7 for float operations. |
1199 // TODO(fschneider): Add a register policy to specify a subset of | 1209 // TODO(fschneider): Add a register policy to specify a subset of |
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1380 | 1390 |
1381 bool needs_base = false; | 1391 bool needs_base = false; |
1382 if (CanBeImmediateIndex(index(), class_id(), IsExternal(), | 1392 if (CanBeImmediateIndex(index(), class_id(), IsExternal(), |
1383 false, // Store. | 1393 false, // Store. |
1384 &needs_base)) { | 1394 &needs_base)) { |
1385 const intptr_t kNumTemps = needs_base ? 1 : 0; | 1395 const intptr_t kNumTemps = needs_base ? 1 : 0; |
1386 locs = new(isolate) LocationSummary( | 1396 locs = new(isolate) LocationSummary( |
1387 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1397 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
1388 | 1398 |
1389 // CanBeImmediateIndex must return false for unsafe smis. | 1399 // CanBeImmediateIndex must return false for unsafe smis. |
1390 locs->set_in(1, Location::Constant(index()->BoundConstant())); | 1400 locs->set_in(1, Location::Constant(index()->definition()->AsConstant())); |
1391 if (needs_base) { | 1401 if (needs_base) { |
1392 locs->set_temp(0, Location::RequiresRegister()); | 1402 locs->set_temp(0, Location::RequiresRegister()); |
1393 } | 1403 } |
1394 } else { | 1404 } else { |
1395 const intptr_t kNumTemps = 0; | 1405 const intptr_t kNumTemps = 0; |
1396 locs = new(isolate) LocationSummary( | 1406 locs = new(isolate) LocationSummary( |
1397 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 1407 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
1398 | 1408 |
1399 locs->set_in(1, Location::WritableRegister()); | 1409 locs->set_in(1, Location::WritableRegister()); |
1400 } | 1410 } |
(...skipping 1552 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2953 } else if ((op_kind() == Token::kMUL) && | 2963 } else if ((op_kind() == Token::kMUL) && |
2954 (TargetCPUFeatures::arm_version() != ARMv7)) { | 2964 (TargetCPUFeatures::arm_version() != ARMv7)) { |
2955 num_temps = 1; | 2965 num_temps = 1; |
2956 } | 2966 } |
2957 LocationSummary* summary = new(isolate) LocationSummary( | 2967 LocationSummary* summary = new(isolate) LocationSummary( |
2958 isolate, kNumInputs, num_temps, LocationSummary::kNoCall); | 2968 isolate, kNumInputs, num_temps, LocationSummary::kNoCall); |
2959 if (op_kind() == Token::kTRUNCDIV) { | 2969 if (op_kind() == Token::kTRUNCDIV) { |
2960 summary->set_in(0, Location::RequiresRegister()); | 2970 summary->set_in(0, Location::RequiresRegister()); |
2961 if (RightIsPowerOfTwoConstant()) { | 2971 if (RightIsPowerOfTwoConstant()) { |
2962 ConstantInstr* right_constant = right()->definition()->AsConstant(); | 2972 ConstantInstr* right_constant = right()->definition()->AsConstant(); |
2963 summary->set_in(1, Location::Constant(right_constant->value())); | 2973 summary->set_in(1, Location::Constant(right_constant)); |
2964 summary->set_temp(0, Location::RequiresRegister()); | 2974 summary->set_temp(0, Location::RequiresRegister()); |
2965 } else { | 2975 } else { |
2966 summary->set_in(1, Location::RequiresRegister()); | 2976 summary->set_in(1, Location::RequiresRegister()); |
2967 summary->set_temp(0, Location::RequiresRegister()); | 2977 summary->set_temp(0, Location::RequiresRegister()); |
2968 summary->set_temp(1, Location::RequiresFpuRegister()); | 2978 summary->set_temp(1, Location::RequiresFpuRegister()); |
2969 } | 2979 } |
2970 summary->set_out(0, Location::RequiresRegister()); | 2980 summary->set_out(0, Location::RequiresRegister()); |
2971 return summary; | 2981 return summary; |
2972 } | 2982 } |
2973 if (op_kind() == Token::kMOD) { | 2983 if (op_kind() == Token::kMOD) { |
(...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3317 UNREACHABLE(); | 3327 UNREACHABLE(); |
3318 break; | 3328 break; |
3319 } | 3329 } |
3320 default: | 3330 default: |
3321 UNREACHABLE(); | 3331 UNREACHABLE(); |
3322 break; | 3332 break; |
3323 } | 3333 } |
3324 } | 3334 } |
3325 | 3335 |
3326 | 3336 |
3337 static void EmitInt32ShiftLeft(FlowGraphCompiler* compiler, | |
3338 BinaryInt32OpInstr* shift_left) { | |
3339 const bool is_truncating = shift_left->IsTruncating(); | |
3340 const LocationSummary& locs = *shift_left->locs(); | |
3341 const Register left = locs.in(0).reg(); | |
3342 const Register result = locs.out(0).reg(); | |
3343 Label* deopt = shift_left->CanDeoptimize() ? | |
3344 compiler->AddDeoptStub(shift_left->deopt_id(), ICData::kDeoptBinarySmiOp) | |
3345 : NULL; | |
3346 ASSERT(locs.in(1).IsConstant()); | |
3347 const Object& constant = locs.in(1).constant(); | |
3348 ASSERT(constant.IsSmi()); | |
3349 // Immediate shift operation takes 5 bits for the count. | |
3350 const intptr_t kCountLimit = 0x1F; | |
3351 const intptr_t value = Smi::Cast(constant).Value(); | |
3352 if (value == 0) { | |
Florian Schneider
2014/08/27 09:36:51
TODO: Shift by 0 constant should be folded away. I
Vyacheslav Egorov (Google)
2014/08/27 11:45:37
Yes, I have this as part of my BinarySmiOpInstr re
| |
3353 __ MoveRegister(result, left); | |
3354 } else if ((value < 0) || (value >= kCountLimit)) { | |
3355 // This condition may not be known earlier in some cases because | |
3356 // of constant propagation, inlining, etc. | |
3357 if ((value >= kCountLimit) && is_truncating) { | |
3358 __ mov(result, Operand(0)); | |
3359 } else { | |
3360 // Result is Mint or exception. | |
3361 __ b(deopt); | |
3362 } | |
3363 } else { | |
3364 if (!is_truncating) { | |
3365 // Check for overflow (preserve left). | |
3366 __ Lsl(IP, left, value); | |
3367 __ cmp(left, Operand(IP, ASR, value)); | |
3368 __ b(deopt, NE); // Overflow. | |
3369 } | |
3370 // Shift for result now we know there is no overflow. | |
3371 __ Lsl(result, left, value); | |
3372 } | |
3373 } | |
3374 | |
3375 | |
3376 LocationSummary* BinaryInt32OpInstr::MakeLocationSummary(Isolate* isolate, | |
3377 bool opt) const { | |
3378 const intptr_t kNumInputs = 2; | |
3379 // Calculate number of temporaries. | |
3380 intptr_t num_temps = 0; | |
3381 if (((op_kind() == Token::kSHL) && !IsTruncating()) || | |
3382 (op_kind() == Token::kSHR)) { | |
3383 num_temps = 1; | |
3384 } else if ((op_kind() == Token::kMUL) && | |
3385 (TargetCPUFeatures::arm_version() != ARMv7)) { | |
3386 num_temps = 1; | |
3387 } | |
3388 LocationSummary* summary = new(isolate) LocationSummary( | |
3389 isolate, kNumInputs, num_temps, LocationSummary::kNoCall); | |
3390 summary->set_in(0, Location::RequiresRegister()); | |
3391 summary->set_in(1, Location::RegisterOrSmiConstant(right())); | |
3392 if (((op_kind() == Token::kSHL) && !IsTruncating()) || | |
3393 (op_kind() == Token::kSHR)) { | |
3394 summary->set_temp(0, Location::RequiresRegister()); | |
3395 } | |
3396 if (op_kind() == Token::kMUL) { | |
3397 if (TargetCPUFeatures::arm_version() != ARMv7) { | |
3398 summary->set_temp(0, Location::RequiresFpuRegister()); | |
3399 } | |
3400 } | |
3401 // We make use of 3-operand instructions by not requiring result register | |
3402 // to be identical to first input register as on Intel. | |
3403 summary->set_out(0, Location::RequiresRegister()); | |
3404 return summary; | |
3405 } | |
3406 | |
3407 | |
3408 void BinaryInt32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
3409 if (op_kind() == Token::kSHL) { | |
3410 EmitInt32ShiftLeft(compiler, this); | |
3411 return; | |
3412 } | |
3413 | |
3414 const Register left = locs()->in(0).reg(); | |
3415 const Register result = locs()->out(0).reg(); | |
3416 Label* deopt = NULL; | |
3417 if (CanDeoptimize()) { | |
3418 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp); | |
3419 } | |
3420 | |
3421 if (locs()->in(1).IsConstant()) { | |
3422 const Object& constant = locs()->in(1).constant(); | |
3423 ASSERT(constant.IsSmi()); | |
3424 const int32_t value = Smi::Cast(constant).Value(); | |
3425 switch (op_kind()) { | |
3426 case Token::kADD: { | |
3427 if (deopt == NULL) { | |
3428 __ AddImmediate(result, left, value); | |
3429 } else { | |
3430 __ AddImmediateSetFlags(result, left, value); | |
3431 __ b(deopt, VS); | |
3432 } | |
3433 break; | |
3434 } | |
3435 case Token::kSUB: { | |
3436 if (deopt == NULL) { | |
3437 __ AddImmediate(result, left, -value); | |
3438 } else { | |
3439 // Negating value and using AddImmediateSetFlags would not detect the | |
3440 // overflow when value == kMinInt32. | |
3441 __ SubImmediateSetFlags(result, left, value); | |
3442 __ b(deopt, VS); | |
3443 } | |
3444 break; | |
3445 } | |
3446 case Token::kMUL: { | |
3447 if (deopt == NULL) { | |
3448 if (value == 2) { | |
3449 __ mov(result, Operand(left, LSL, 1)); | |
3450 } else { | |
3451 __ LoadImmediate(IP, value); | |
3452 __ mul(result, left, IP); | |
3453 } | |
3454 } else { | |
3455 if (value == 2) { | |
3456 __ CompareImmediate(left, 0xC0000000); | |
3457 __ b(deopt, MI); | |
3458 __ mov(result, Operand(left, LSL, 1)); | |
3459 } else { | |
3460 if (TargetCPUFeatures::arm_version() == ARMv7) { | |
3461 __ LoadImmediate(IP, value); | |
3462 __ smull(result, IP, left, IP); | |
3463 // IP: result bits 32..63. | |
3464 __ cmp(IP, Operand(result, ASR, 31)); | |
3465 __ b(deopt, NE); | |
3466 } else if (TargetCPUFeatures::can_divide()) { | |
3467 const QRegister qtmp = locs()->temp(0).fpu_reg(); | |
3468 const DRegister dtmp0 = EvenDRegisterOf(qtmp); | |
3469 const DRegister dtmp1 = OddDRegisterOf(qtmp); | |
3470 __ LoadImmediate(IP, value); | |
3471 __ CheckMultSignedOverflow(left, IP, result, dtmp0, dtmp1, deopt); | |
3472 __ mul(result, left, IP); | |
3473 } else { | |
3474 __ b(deopt); | |
Florian Schneider
2014/08/27 09:36:51
It seems wrong to always deoptimize in this case.
Vyacheslav Egorov (Google)
2014/08/27 11:45:37
Yes, I was also surprised we do it this way and as
| |
3475 } | |
3476 } | |
3477 } | |
3478 break; | |
3479 } | |
3480 case Token::kBIT_AND: { | |
3481 // No overflow check. | |
3482 Operand o; | |
3483 if (Operand::CanHold(value, &o)) { | |
3484 __ and_(result, left, o); | |
3485 } else if (Operand::CanHold(~value, &o)) { | |
3486 __ bic(result, left, o); | |
3487 } else { | |
3488 __ LoadImmediate(IP, value); | |
3489 __ and_(result, left, Operand(IP)); | |
3490 } | |
3491 break; | |
3492 } | |
3493 case Token::kBIT_OR: { | |
3494 // No overflow check. | |
3495 Operand o; | |
3496 if (Operand::CanHold(value, &o)) { | |
3497 __ orr(result, left, o); | |
3498 } else { | |
3499 __ LoadImmediate(IP, value); | |
3500 __ orr(result, left, Operand(IP)); | |
3501 } | |
3502 break; | |
3503 } | |
3504 case Token::kBIT_XOR: { | |
3505 // No overflow check. | |
3506 Operand o; | |
3507 if (Operand::CanHold(value, &o)) { | |
3508 __ eor(result, left, o); | |
3509 } else { | |
3510 __ LoadImmediate(IP, value); | |
3511 __ eor(result, left, Operand(IP)); | |
3512 } | |
3513 break; | |
3514 } | |
3515 case Token::kSHR: { | |
3516 // sarl operation masks the count to 5 bits. | |
3517 const intptr_t kCountLimit = 0x1F; | |
3518 | |
3519 if (value == 0) { | |
3520 // TODO(vegorov): should be handled outside. | |
3521 __ MoveRegister(result, left); | |
3522 break; | |
3523 } else if (value < 0) { | |
3524 // TODO(vegorov): should be handled outside. | |
3525 __ b(deopt); | |
3526 break; | |
3527 } | |
3528 | |
3529 if (value >= kCountLimit) { | |
3530 __ Asr(result, left, kCountLimit); | |
3531 } else { | |
3532 __ Asr(result, left, value); | |
3533 } | |
3534 break; | |
3535 } | |
3536 | |
3537 default: | |
3538 UNREACHABLE(); | |
3539 break; | |
3540 } | |
3541 return; | |
3542 } | |
3543 | |
3544 const Register right = locs()->in(1).reg(); | |
3545 switch (op_kind()) { | |
3546 case Token::kADD: { | |
3547 if (deopt == NULL) { | |
3548 __ add(result, left, Operand(right)); | |
3549 } else { | |
3550 __ adds(result, left, Operand(right)); | |
3551 __ b(deopt, VS); | |
3552 } | |
3553 break; | |
3554 } | |
3555 case Token::kSUB: { | |
3556 if (deopt == NULL) { | |
3557 __ sub(result, left, Operand(right)); | |
3558 } else { | |
3559 __ subs(result, left, Operand(right)); | |
3560 __ b(deopt, VS); | |
3561 } | |
3562 break; | |
3563 } | |
3564 case Token::kMUL: { | |
3565 if (deopt == NULL) { | |
3566 __ mul(result, left, right); | |
3567 } else { | |
3568 if (TargetCPUFeatures::arm_version() == ARMv7) { | |
3569 __ smull(result, IP, left, right); | |
3570 // IP: result bits 32..63. | |
3571 __ cmp(IP, Operand(result, ASR, 31)); | |
3572 __ b(deopt, NE); | |
3573 } else if (TargetCPUFeatures::can_divide()) { | |
3574 const QRegister qtmp = locs()->temp(0).fpu_reg(); | |
3575 const DRegister dtmp0 = EvenDRegisterOf(qtmp); | |
3576 const DRegister dtmp1 = OddDRegisterOf(qtmp); | |
3577 __ CheckMultSignedOverflow(left, right, result, dtmp0, dtmp1, deopt); | |
3578 __ mul(result, left, right); | |
3579 } else { | |
3580 __ b(deopt); | |
Florian Schneider
2014/08/27 09:36:51
Add TODO here as well.
| |
3581 } | |
3582 } | |
3583 break; | |
3584 } | |
3585 case Token::kBIT_AND: { | |
3586 // No overflow check. | |
3587 __ and_(result, left, Operand(right)); | |
3588 break; | |
3589 } | |
3590 case Token::kBIT_OR: { | |
3591 // No overflow check. | |
3592 __ orr(result, left, Operand(right)); | |
3593 break; | |
3594 } | |
3595 case Token::kBIT_XOR: { | |
3596 // No overflow check. | |
3597 __ eor(result, left, Operand(right)); | |
3598 break; | |
3599 } | |
3600 default: | |
3601 UNREACHABLE(); | |
3602 break; | |
3603 } | |
3604 } | |
3605 | |
3606 | |
3327 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(Isolate* isolate, | 3607 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(Isolate* isolate, |
3328 bool opt) const { | 3608 bool opt) const { |
3329 intptr_t left_cid = left()->Type()->ToCid(); | 3609 intptr_t left_cid = left()->Type()->ToCid(); |
3330 intptr_t right_cid = right()->Type()->ToCid(); | 3610 intptr_t right_cid = right()->Type()->ToCid(); |
3331 ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid)); | 3611 ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid)); |
3332 const intptr_t kNumInputs = 2; | 3612 const intptr_t kNumInputs = 2; |
3333 const intptr_t kNumTemps = 0; | 3613 const intptr_t kNumTemps = 0; |
3334 LocationSummary* summary = new(isolate) LocationSummary( | 3614 LocationSummary* summary = new(isolate) LocationSummary( |
3335 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3615 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
3336 summary->set_in(0, Location::RequiresRegister()); | 3616 summary->set_in(0, Location::RequiresRegister()); |
(...skipping 1695 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5032 } | 5312 } |
5033 | 5313 |
5034 | 5314 |
5035 void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5315 void UnaryDoubleOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
5036 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); | 5316 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); |
5037 const DRegister value = EvenDRegisterOf(locs()->in(0).fpu_reg()); | 5317 const DRegister value = EvenDRegisterOf(locs()->in(0).fpu_reg()); |
5038 __ vnegd(result, value); | 5318 __ vnegd(result, value); |
5039 } | 5319 } |
5040 | 5320 |
5041 | 5321 |
5322 LocationSummary* Int32ToDoubleInstr::MakeLocationSummary(Isolate* isolate, | |
5323 bool opt) const { | |
5324 const intptr_t kNumInputs = 1; | |
5325 const intptr_t kNumTemps = 0; | |
5326 LocationSummary* result = new(isolate) LocationSummary( | |
5327 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | |
5328 result->set_in(0, Location::RequiresRegister()); | |
5329 result->set_out(0, Location::RequiresFpuRegister()); | |
5330 return result; | |
5331 } | |
5332 | |
5333 | |
5334 void Int32ToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
5335 const Register value = locs()->in(0).reg(); | |
5336 const DRegister result = EvenDRegisterOf(locs()->out(0).fpu_reg()); | |
5337 __ vmovsr(STMP, value); | |
5338 __ vcvtdi(result, STMP); | |
5339 } | |
5340 | |
5341 | |
5042 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(Isolate* isolate, | 5342 LocationSummary* SmiToDoubleInstr::MakeLocationSummary(Isolate* isolate, |
5043 bool opt) const { | 5343 bool opt) const { |
5044 const intptr_t kNumInputs = 1; | 5344 const intptr_t kNumInputs = 1; |
5045 const intptr_t kNumTemps = 0; | 5345 const intptr_t kNumTemps = 0; |
5046 LocationSummary* result = new(isolate) LocationSummary( | 5346 LocationSummary* result = new(isolate) LocationSummary( |
5047 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5347 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
5048 result->set_in(0, Location::RequiresRegister()); | 5348 result->set_in(0, Location::RequiresRegister()); |
5049 result->set_out(0, Location::RequiresFpuRegister()); | 5349 result->set_out(0, Location::RequiresFpuRegister()); |
5050 return result; | 5350 return result; |
5051 } | 5351 } |
(...skipping 1159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6211 CompileType ShiftUint32OpInstr::ComputeType() const { | 6511 CompileType ShiftUint32OpInstr::ComputeType() const { |
6212 return CompileType::Int(); | 6512 return CompileType::Int(); |
6213 } | 6513 } |
6214 | 6514 |
6215 | 6515 |
6216 CompileType UnaryUint32OpInstr::ComputeType() const { | 6516 CompileType UnaryUint32OpInstr::ComputeType() const { |
6217 return CompileType::Int(); | 6517 return CompileType::Int(); |
6218 } | 6518 } |
6219 | 6519 |
6220 | 6520 |
6221 CompileType BoxUint32Instr::ComputeType() const { | |
6222 return CompileType::Int(); | |
6223 } | |
6224 | |
6225 | |
6226 CompileType UnboxUint32Instr::ComputeType() const { | |
6227 return CompileType::Int(); | |
6228 } | |
6229 | |
6230 | |
6231 LocationSummary* BinaryUint32OpInstr::MakeLocationSummary(Isolate* isolate, | 6521 LocationSummary* BinaryUint32OpInstr::MakeLocationSummary(Isolate* isolate, |
6232 bool opt) const { | 6522 bool opt) const { |
6233 const intptr_t kNumInputs = 2; | 6523 const intptr_t kNumInputs = 2; |
6234 const intptr_t kNumTemps = 0; | 6524 const intptr_t kNumTemps = 0; |
6235 LocationSummary* summary = new(isolate) LocationSummary( | 6525 LocationSummary* summary = new(isolate) LocationSummary( |
6236 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6526 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
6237 summary->set_in(0, Location::RequiresRegister()); | 6527 summary->set_in(0, Location::RequiresRegister()); |
6238 summary->set_in(1, Location::RequiresRegister()); | 6528 summary->set_in(1, Location::RequiresRegister()); |
6239 summary->set_out(0, Location::RequiresRegister()); | 6529 summary->set_out(0, Location::RequiresRegister()); |
6240 return summary; | 6530 return summary; |
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6473 __ b(&done, EQ); | 6763 __ b(&done, EQ); |
6474 // Mint case. | 6764 // Mint case. |
6475 __ CompareClassId(value, kMintCid, temp); | 6765 __ CompareClassId(value, kMintCid, temp); |
6476 __ b(deopt, NE); | 6766 __ b(deopt, NE); |
6477 __ LoadFromOffset(kWord, out, value, Mint::value_offset() - kHeapObjectTag); | 6767 __ LoadFromOffset(kWord, out, value, Mint::value_offset() - kHeapObjectTag); |
6478 __ Bind(&done); | 6768 __ Bind(&done); |
6479 } | 6769 } |
6480 } | 6770 } |
6481 | 6771 |
6482 | 6772 |
6773 LocationSummary* BoxInt32Instr::MakeLocationSummary(Isolate* isolate, | |
6774 bool opt) const { | |
6775 const intptr_t kNumInputs = 1; | |
6776 const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1; | |
6777 LocationSummary* summary = new(isolate) LocationSummary( | |
6778 isolate, | |
6779 kNumInputs, | |
6780 kNumTemps, | |
6781 ValueFitsSmi() ? LocationSummary::kNoCall | |
6782 : LocationSummary::kCallOnSlowPath); | |
6783 summary->set_in(0, Location::RequiresRegister()); | |
6784 if (!ValueFitsSmi()) { | |
6785 summary->set_temp(0, Location::RequiresRegister()); | |
6786 } | |
6787 summary->set_out(0, Location::RequiresRegister()); | |
6788 return summary; | |
6789 } | |
6790 | |
6791 | |
6792 void BoxInt32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
6793 Register value = locs()->in(0).reg(); | |
6794 Register out = locs()->out(0).reg(); | |
6795 ASSERT(value != out); | |
6796 | |
6797 __ Lsl(out, value, 1); | |
6798 if (!ValueFitsSmi()) { | |
6799 Register temp = locs()->temp(0).reg(); | |
6800 Label done; | |
6801 __ cmp(value, Operand(out, ASR, 1)); | |
6802 __ b(&done, EQ); | |
6803 BoxAllocationSlowPath::Allocate( | |
6804 compiler, | |
6805 this, | |
6806 compiler->mint_class(), | |
6807 out, | |
6808 temp); | |
6809 __ Asr(temp, value, kBitsPerWord - 1); | |
6810 __ StoreToOffset(kWord, | |
6811 value, | |
6812 out, | |
6813 Mint::value_offset() - kHeapObjectTag); | |
6814 __ StoreToOffset(kWord, | |
6815 temp, | |
6816 out, | |
6817 Mint::value_offset() - kHeapObjectTag + kWordSize); | |
6818 __ Bind(&done); | |
6819 } | |
6820 } | |
6821 | |
6822 | |
6823 | |
6824 LocationSummary* UnboxInt32Instr::MakeLocationSummary(Isolate* isolate, | |
6825 bool opt) const { | |
6826 const intptr_t value_cid = value()->Type()->ToCid(); | |
6827 const intptr_t kNumInputs = 1; | |
6828 const intptr_t kNumTemps = | |
6829 ((value_cid == kMintCid) || (value_cid == kSmiCid)) ? 0 : 1; | |
6830 LocationSummary* summary = new(isolate) LocationSummary( | |
6831 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | |
6832 summary->set_in(0, Location::RequiresRegister()); | |
6833 if (kNumTemps > 0) { | |
6834 summary->set_temp(0, Location::RequiresRegister()); | |
6835 } | |
6836 summary->set_out(0, Location::RequiresRegister()); | |
6837 return summary; | |
6838 } | |
6839 | |
6840 | |
6841 static void LoadInt32FromMint(FlowGraphCompiler* compiler, | |
6842 Register mint, | |
6843 Register result, | |
6844 Register temp, | |
6845 Label* deopt) { | |
6846 __ LoadFromOffset(kWord, | |
6847 result, | |
6848 mint, | |
6849 Mint::value_offset() - kHeapObjectTag); | |
6850 if (deopt != NULL) { | |
6851 __ LoadFromOffset(kWord, | |
6852 temp, | |
6853 mint, | |
6854 Mint::value_offset() - kHeapObjectTag + kWordSize); | |
6855 __ cmp(temp, Operand(result, ASR, kBitsPerWord - 1)); | |
6856 __ b(deopt, NE); | |
6857 } | |
6858 } | |
6859 | |
6860 | |
6861 void UnboxInt32Instr::EmitNativeCode(FlowGraphCompiler* compiler) { | |
6862 const intptr_t value_cid = value()->Type()->ToCid(); | |
6863 const Register value = locs()->in(0).reg(); | |
6864 const Register out = locs()->out(0).reg(); | |
6865 ASSERT(value != out); | |
6866 | |
6867 if (value_cid == kMintCid) { | |
6868 Register temp = CanDeoptimize() ? locs()->temp(0).reg() : kNoRegister; | |
6869 Label* deopt = CanDeoptimize() ? | |
6870 compiler->AddDeoptStub(deopt_id_, ICData::kDeoptUnboxInteger) : NULL; | |
6871 LoadInt32FromMint(compiler, | |
6872 value, | |
6873 out, | |
6874 temp, | |
6875 deopt); | |
6876 } else if (value_cid == kSmiCid) { | |
6877 __ SmiUntag(out, value); | |
6878 } else { | |
6879 Register temp = locs()->temp(0).reg(); | |
6880 Label* deopt = compiler->AddDeoptStub(deopt_id_, | |
6881 ICData::kDeoptUnboxInteger); | |
6882 Label done; | |
6883 __ tst(value, Operand(kSmiTagMask)); | |
6884 // Smi case. | |
6885 __ mov(out, Operand(value), EQ); | |
6886 __ SmiUntag(out, EQ); | |
6887 __ b(&done, EQ); | |
6888 // Mint case. | |
6889 __ CompareClassId(value, kMintCid, temp); | |
6890 __ b(deopt, NE); | |
6891 LoadInt32FromMint(compiler, | |
6892 value, | |
6893 out, | |
6894 temp, | |
6895 deopt); | |
6896 __ Bind(&done); | |
6897 } | |
6898 } | |
6899 | |
6900 | |
6483 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Isolate* isolate, | 6901 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Isolate* isolate, |
6484 bool opt) const { | 6902 bool opt) const { |
6485 const intptr_t kNumInputs = 1; | 6903 const intptr_t kNumInputs = 1; |
6486 const intptr_t kNumTemps = 0; | 6904 const intptr_t kNumTemps = 0; |
6487 LocationSummary* summary = new(isolate) LocationSummary( | 6905 LocationSummary* summary = new(isolate) LocationSummary( |
6488 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 6906 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
6489 if (from() == kUnboxedMint) { | 6907 if (from() == kUnboxedMint) { |
6908 ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32)); | |
6490 summary->set_in(0, Location::Pair(Location::RequiresRegister(), | 6909 summary->set_in(0, Location::Pair(Location::RequiresRegister(), |
6491 Location::RequiresRegister())); | 6910 Location::RequiresRegister())); |
6492 summary->set_out(0, Location::RequiresRegister()); | 6911 summary->set_out(0, Location::RequiresRegister()); |
6493 } else { | 6912 } else if (to() == kUnboxedMint) { |
6494 ASSERT(from() == kUnboxedUint32); | 6913 ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32)); |
6495 summary->set_in(0, Location::RequiresRegister()); | 6914 summary->set_in(0, Location::RequiresRegister()); |
6496 summary->set_out(0, Location::Pair(Location::RequiresRegister(), | 6915 summary->set_out(0, Location::Pair(Location::RequiresRegister(), |
6497 Location::RequiresRegister())); | 6916 Location::RequiresRegister())); |
6917 } else { | |
6918 ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32)); | |
6919 ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32)); | |
6920 summary->set_in(0, Location::RequiresRegister()); | |
6921 summary->set_out(0, Location::SameAsFirstInput()); | |
6498 } | 6922 } |
6499 return summary; | 6923 return summary; |
6500 } | 6924 } |
6501 | 6925 |
6502 | 6926 |
6503 void UnboxedIntConverterInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6927 void UnboxedIntConverterInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
6504 if (from() == kUnboxedMint) { | 6928 if (from() == kUnboxedInt32 && to() == kUnboxedUint32) { |
6929 const Register out = locs()->out(0).reg(); | |
6930 // Representations are bitwise equivalent. | |
6931 ASSERT(out == locs()->in(0).reg()); | |
6932 } else if (from() == kUnboxedUint32 && to() == kUnboxedInt32) { | |
6933 const Register out = locs()->out(0).reg(); | |
6934 // Representations are bitwise equivalent. | |
6935 ASSERT(out == locs()->in(0).reg()); | |
6936 if (CanDeoptimize()) { | |
6937 Label* deopt = | |
6938 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnboxInteger); | |
6939 __ tst(out, Operand(out)); | |
6940 __ b(deopt, MI); | |
6941 } | |
6942 } else if (from() == kUnboxedMint) { | |
6943 ASSERT(to() == kUnboxedUint32 || to() == kUnboxedInt32); | |
6505 PairLocation* in_pair = locs()->in(0).AsPairLocation(); | 6944 PairLocation* in_pair = locs()->in(0).AsPairLocation(); |
6506 Register in_lo = in_pair->At(0).reg(); | 6945 Register in_lo = in_pair->At(0).reg(); |
6946 Register in_hi = in_pair->At(1).reg(); | |
6507 Register out = locs()->out(0).reg(); | 6947 Register out = locs()->out(0).reg(); |
6508 // Copy low word. | 6948 // Copy low word. |
6509 __ mov(out, Operand(in_lo)); | 6949 __ mov(out, Operand(in_lo)); |
6510 } else { | 6950 if (CanDeoptimize()) { |
6511 ASSERT(from() == kUnboxedUint32); | 6951 Label* deopt = |
6952 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnboxInteger); | |
6953 ASSERT(to() == kUnboxedInt32); | |
6954 __ cmp(in_hi, Operand(in_lo, ASR, kBitsPerWord - 1)); | |
6955 __ b(deopt, NE); | |
6956 } | |
6957 } else if (from() == kUnboxedUint32 || from() == kUnboxedInt32) { | |
6958 ASSERT(to() == kUnboxedMint); | |
6512 Register in = locs()->in(0).reg(); | 6959 Register in = locs()->in(0).reg(); |
6513 PairLocation* out_pair = locs()->out(0).AsPairLocation(); | 6960 PairLocation* out_pair = locs()->out(0).AsPairLocation(); |
6514 Register out_lo = out_pair->At(0).reg(); | 6961 Register out_lo = out_pair->At(0).reg(); |
6515 Register out_hi = out_pair->At(1).reg(); | 6962 Register out_hi = out_pair->At(1).reg(); |
6516 // Copy low word. | 6963 // Copy low word. |
6517 __ mov(out_lo, Operand(in)); | 6964 __ mov(out_lo, Operand(in)); |
6518 // Zero upper word. | 6965 if (from() == kUnboxedUint32) { |
6519 __ eor(out_hi, out_hi, Operand(out_hi)); | 6966 __ eor(out_hi, out_hi, Operand(out_hi)); |
6967 } else { | |
6968 ASSERT(from() == kUnboxedInt32); | |
6969 __ mov(out_hi, Operand(in, ASR, kBitsPerWord - 1)); | |
6970 } | |
6971 } else { | |
6972 UNREACHABLE(); | |
6520 } | 6973 } |
6521 } | 6974 } |
6522 | 6975 |
6523 | 6976 |
6524 LocationSummary* ThrowInstr::MakeLocationSummary(Isolate* isolate, | 6977 LocationSummary* ThrowInstr::MakeLocationSummary(Isolate* isolate, |
6525 bool opt) const { | 6978 bool opt) const { |
6526 return new(isolate) LocationSummary(isolate, 0, 0, LocationSummary::kCall); | 6979 return new(isolate) LocationSummary(isolate, 0, 0, LocationSummary::kCall); |
6527 } | 6980 } |
6528 | 6981 |
6529 | 6982 |
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6747 compiler->GenerateCall(token_pos(), &label, stub_kind_, locs()); | 7200 compiler->GenerateCall(token_pos(), &label, stub_kind_, locs()); |
6748 #if defined(DEBUG) | 7201 #if defined(DEBUG) |
6749 __ LoadImmediate(R4, kInvalidObjectPointer); | 7202 __ LoadImmediate(R4, kInvalidObjectPointer); |
6750 __ LoadImmediate(R5, kInvalidObjectPointer); | 7203 __ LoadImmediate(R5, kInvalidObjectPointer); |
6751 #endif | 7204 #endif |
6752 } | 7205 } |
6753 | 7206 |
6754 } // namespace dart | 7207 } // namespace dart |
6755 | 7208 |
6756 #endif // defined TARGET_ARCH_ARM | 7209 #endif // defined TARGET_ARCH_ARM |
OLD | NEW |