Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(559)

Side by Side Diff: runtime/vm/intermediate_language_ia32.cc

Issue 670263007: IR refactoring: consolidate all boxing and unboxing instructions. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/intermediate_language_arm64.cc ('k') | runtime/vm/intermediate_language_mips.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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_IA32. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32.
6 #if defined(TARGET_ARCH_IA32) 6 #if defined(TARGET_ARCH_IA32)
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 3311 matching lines...) Expand 10 before | Expand all | Expand 10 after
3322 } else { 3322 } else {
3323 Register temp = locs()->temp(0).reg(); 3323 Register temp = locs()->temp(0).reg();
3324 __ movl(temp, left); 3324 __ movl(temp, left);
3325 __ orl(temp, right); 3325 __ orl(temp, right);
3326 __ testl(temp, Immediate(kSmiTagMask)); 3326 __ testl(temp, Immediate(kSmiTagMask));
3327 } 3327 }
3328 __ j(ZERO, deopt); 3328 __ j(ZERO, deopt);
3329 } 3329 }
3330 3330
3331 3331
3332 3332 LocationSummary* BoxInstr::MakeLocationSummary(Isolate* isolate,
3333
3334
3335 LocationSummary* BoxDoubleInstr::MakeLocationSummary(Isolate* isolate,
3336 bool opt) const { 3333 bool opt) const {
3337 const intptr_t kNumInputs = 1; 3334 const intptr_t kNumInputs = 1;
3338 const intptr_t kNumTemps = 0; 3335 const intptr_t kNumTemps = 0;
3339 LocationSummary* summary = new(isolate) LocationSummary( 3336 LocationSummary* summary = new(isolate) LocationSummary(
3340 isolate, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath); 3337 isolate, kNumInputs, kNumTemps, LocationSummary::kCallOnSlowPath);
3341 summary->set_in(0, Location::RequiresFpuRegister()); 3338 summary->set_in(0, Location::RequiresFpuRegister());
3342 summary->set_out(0, Location::RequiresRegister()); 3339 summary->set_out(0, Location::RequiresRegister());
3343 return summary; 3340 return summary;
3344 } 3341 }
3345 3342
3346 3343
3347 void BoxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3344 void BoxInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3348 Register out_reg = locs()->out(0).reg(); 3345 Register out_reg = locs()->out(0).reg();
3349 XmmRegister value = locs()->in(0).fpu_reg(); 3346 XmmRegister value = locs()->in(0).fpu_reg();
3347
3350 BoxAllocationSlowPath::Allocate( 3348 BoxAllocationSlowPath::Allocate(
3351 compiler, this, compiler->double_class(), out_reg, kNoRegister); 3349 compiler,
3352 __ movsd(FieldAddress(out_reg, Double::value_offset()), value); 3350 this,
3353 } 3351 compiler->BoxClassFor(from_representation()),
3354 3352 out_reg,
3355 3353 kNoRegister);
3356 LocationSummary* UnboxDoubleInstr::MakeLocationSummary(Isolate* isolate, 3354
3355 switch (from_representation()) {
3356 case kUnboxedDouble:
3357 __ movsd(FieldAddress(out_reg, ValueOffset()), value);
3358 break;
3359 case kUnboxedFloat32x4:
3360 case kUnboxedFloat64x2:
3361 case kUnboxedInt32x4:
3362 __ movups(FieldAddress(out_reg, ValueOffset()), value);
3363 break;
3364 default:
3365 UNREACHABLE();
3366 break;
3367 }
3368 }
3369
3370
3371 LocationSummary* UnboxInstr::MakeLocationSummary(Isolate* isolate,
3357 bool opt) const { 3372 bool opt) const {
3373 const bool needs_temp = CanDeoptimize() ||
3374 (CanConvertSmi() && (value()->Type()->ToCid() == kSmiCid));
3375
3358 const intptr_t kNumInputs = 1; 3376 const intptr_t kNumInputs = 1;
3359 const intptr_t value_cid = value()->Type()->ToCid();
3360 const bool needs_temp = ((value_cid != kSmiCid) && (value_cid != kDoubleCid));
3361 const bool needs_writable_input = (value_cid == kSmiCid);
3362 const intptr_t kNumTemps = needs_temp ? 1 : 0; 3377 const intptr_t kNumTemps = needs_temp ? 1 : 0;
3363 LocationSummary* summary = new(isolate) LocationSummary( 3378 LocationSummary* summary = new(isolate) LocationSummary(
3364 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); 3379 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
3365 summary->set_in(0, needs_writable_input 3380 summary->set_in(0, Location::RequiresRegister());
3366 ? Location::WritableRegister() 3381 if (needs_temp) {
3367 : Location::RequiresRegister()); 3382 summary->set_temp(0, Location::RequiresRegister());
3368 if (needs_temp) summary->set_temp(0, Location::RequiresRegister()); 3383 }
3369 summary->set_out(0, Location::RequiresFpuRegister()); 3384 if (representation() == kUnboxedMint) {
3385 summary->set_out(0, Location::Pair(Location::RegisterLocation(EAX),
3386 Location::RegisterLocation(EDX)));
3387 } else {
3388 summary->set_out(0, Location::RequiresFpuRegister());
3389 }
3370 return summary; 3390 return summary;
3371 } 3391 }
3372 3392
3373 3393
3374 void UnboxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3394 void UnboxInstr::EmitLoadFromBox(FlowGraphCompiler* compiler) {
3375 CompileType* value_type = value()->Type(); 3395 const Register box = locs()->in(0).reg();
3376 const intptr_t value_cid = value_type->ToCid(); 3396
3377 const Register value = locs()->in(0).reg(); 3397 switch (representation()) {
3378 const XmmRegister result = locs()->out(0).fpu_reg(); 3398 case kUnboxedMint: {
3379 3399 PairLocation* result = locs()->out(0).AsPairLocation();
3380 if (value_cid == kDoubleCid) { 3400 __ movl(result->At(0).reg(), FieldAddress(box, ValueOffset()));
3381 __ movsd(result, FieldAddress(value, Double::value_offset())); 3401 __ movl(result->At(1).reg(),
3382 } else if (value_cid == kSmiCid) { 3402 FieldAddress(box, ValueOffset() + kWordSize));
3383 __ SmiUntag(value); // Untag input before conversion. 3403 break;
3384 __ cvtsi2sd(result, value); 3404 }
3405
3406 case kUnboxedDouble: {
3407 const FpuRegister result = locs()->out(0).fpu_reg();
3408 __ movsd(result, FieldAddress(box, ValueOffset()));
3409 break;
3410 }
3411
3412 case kUnboxedFloat32x4:
3413 case kUnboxedFloat64x2:
3414 case kUnboxedInt32x4: {
3415 const FpuRegister result = locs()->out(0).fpu_reg();
3416 __ movups(result, FieldAddress(box, ValueOffset()));
3417 break;
3418 }
3419
3420 default:
3421 UNREACHABLE();
3422 break;
3423 }
3424 }
3425
3426
3427 void UnboxInstr::EmitSmiConversion(FlowGraphCompiler* compiler) {
3428 const Register box = locs()->in(0).reg();
3429
3430 switch (representation()) {
3431 case kUnboxedMint: {
3432 PairLocation* result = locs()->out(0).AsPairLocation();
3433 ASSERT(result->At(0).reg() == EAX);
3434 ASSERT(result->At(1).reg() == EDX);
3435 __ movl(EAX, box);
3436 __ SmiUntag(EAX);
3437 __ cdq();
3438 break;
3439 }
3440
3441 case kUnboxedDouble: {
3442 const Register temp = locs()->temp(0).reg();
3443 const FpuRegister result = locs()->out(0).fpu_reg();
3444 __ movl(temp, box);
3445 __ SmiUntag(temp);
3446 __ cvtsi2sd(result, temp);
3447 break;
3448 }
3449
3450 default:
3451 UNREACHABLE();
3452 break;
3453 }
3454 }
3455
3456
3457 void UnboxInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3458 const intptr_t value_cid = value()->Type()->ToCid();
3459 const intptr_t box_cid = BoxCid();
3460
3461 if (value_cid == box_cid) {
3462 EmitLoadFromBox(compiler);
3463 } else if (CanConvertSmi() && (value_cid == kSmiCid)) {
3464 EmitSmiConversion(compiler);
3385 } else { 3465 } else {
3466 const Register box = locs()->in(0).reg();
3467 const Register temp = locs()->temp(0).reg();
3386 Label* deopt = compiler->AddDeoptStub(GetDeoptId(), 3468 Label* deopt = compiler->AddDeoptStub(GetDeoptId(),
3387 ICData::kDeoptBinaryDoubleOp); 3469 ICData::kDeoptCheckClass);
3388 Register temp = locs()->temp(0).reg(); 3470 Label is_smi;
3389 if (value_type->is_nullable() && 3471
3390 (value_type->ToNullableCid() == kDoubleCid)) { 3472 if ((value()->Type()->ToNullableCid() == box_cid) &&
3473 value()->Type()->is_nullable()) {
3391 const Immediate& raw_null = 3474 const Immediate& raw_null =
3392 Immediate(reinterpret_cast<intptr_t>(Object::null())); 3475 Immediate(reinterpret_cast<intptr_t>(Object::null()));
3393 __ cmpl(value, raw_null); 3476 __ cmpl(box, raw_null);
3394 __ j(EQUAL, deopt); 3477 __ j(EQUAL, deopt);
3395 // It must be double now.
3396 __ movsd(result, FieldAddress(value, Double::value_offset()));
3397 } else { 3478 } else {
3398 Label is_smi, done; 3479 __ testl(box, Immediate(kSmiTagMask));
3399 __ testl(value, Immediate(kSmiTagMask)); 3480 __ j(ZERO, CanConvertSmi() ? &is_smi : deopt);
3400 __ j(ZERO, &is_smi); 3481 __ CompareClassId(box, box_cid, temp);
3401 __ CompareClassId(value, kDoubleCid, temp);
3402 __ j(NOT_EQUAL, deopt); 3482 __ j(NOT_EQUAL, deopt);
3403 __ movsd(result, FieldAddress(value, Double::value_offset())); 3483 }
3484
3485 EmitLoadFromBox(compiler);
3486
3487 if (is_smi.IsLinked()) {
3488 Label done;
3404 __ jmp(&done); 3489 __ jmp(&done);
3405 __ Bind(&is_smi); 3490 __ Bind(&is_smi);
3406 __ movl(temp, value); 3491 EmitSmiConversion(compiler);
3407 __ SmiUntag(temp);
3408 __ cvtsi2sd(result, temp);
3409 __ Bind(&done); 3492 __ Bind(&done);
3410 } 3493 }
3411 } 3494 }
3412 } 3495 }
3413 3496
3414 3497
3415 LocationSummary* BoxFloat32x4Instr::MakeLocationSummary(Isolate* isolate, 3498 LocationSummary* BoxInteger32Instr::MakeLocationSummary(Isolate* isolate,
3416 bool opt) const { 3499 bool opt) const {
3417 const intptr_t kNumInputs = 1; 3500 const intptr_t kNumInputs = 1;
3418 const intptr_t kNumTemps = 0; 3501 const intptr_t kNumTemps = 0;
3419 LocationSummary* summary = new(isolate) LocationSummary( 3502 LocationSummary* summary = new(isolate) LocationSummary(
3503 isolate, kNumInputs, kNumTemps,
3504 ValueFitsSmi() ? LocationSummary::kNoCall
3505 : LocationSummary::kCallOnSlowPath);
3506 const bool needs_writable_input = ValueFitsSmi() ||
3507 (from_representation() == kUnboxedUint32);
3508 summary->set_in(0, needs_writable_input ? Location::RequiresRegister()
3509 : Location::WritableRegister());
3510 summary->set_out(0, ValueFitsSmi() ? Location::SameAsFirstInput()
3511 : Location::RequiresRegister());
3512 return summary;
3513 }
3514
3515
3516 void BoxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
3517 const Register value = locs()->in(0).reg();
3518 const Register out = locs()->out(0).reg();
3519
3520 __ MoveRegister(out, value);
3521 __ shll(out, Immediate(kSmiTagSize));
3522 if (!ValueFitsSmi()) {
3523 Label done;
3524 ASSERT(value != out);
3525 if (from_representation() == kUnboxedInt32) {
3526 __ j(NO_OVERFLOW, &done);
3527 } else {
3528 __ testl(value, Immediate(0xC0000000));
3529 __ j(ZERO, &done);
3530 }
3531
3532 // Allocate a mint.
3533 // Value input is writable register and has to be manually preserved
3534 // on the slow path.
3535 locs()->live_registers()->Add(locs()->in(0), kUnboxedInt32);
3536 BoxAllocationSlowPath::Allocate(
3537 compiler, this, compiler->mint_class(), out, kNoRegister);
3538 __ movl(FieldAddress(out, Mint::value_offset()), value);
3539 if (from_representation() == kUnboxedInt32) {
3540 __ sarl(value, Immediate(31)); // Sign extend.
3541 __ movl(FieldAddress(out, Mint::value_offset() + kWordSize), value);
3542 } else {
3543 __ movl(FieldAddress(out, Mint::value_offset() + kWordSize),
3544 Immediate(0));
3545 }
3546 __ Bind(&done);
3547 }
3548 }
3549
3550
3551 LocationSummary* BoxInt64Instr::MakeLocationSummary(Isolate* isolate,
3552 bool opt) const {
3553 const intptr_t kNumInputs = 1;
3554 const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1;
3555 LocationSummary* summary = new(isolate) LocationSummary(
3420 isolate, kNumInputs, 3556 isolate, kNumInputs,
3421 kNumTemps, 3557 kNumTemps,
3422 LocationSummary::kCallOnSlowPath); 3558 ValueFitsSmi()
3423 summary->set_in(0, Location::RequiresFpuRegister()); 3559 ? LocationSummary::kNoCall
3560 : LocationSummary::kCallOnSlowPath);
3561 summary->set_in(0, Location::Pair(Location::RequiresRegister(),
3562 Location::RequiresRegister()));
3563 if (!ValueFitsSmi()) {
3564 summary->set_temp(0, Location::RequiresRegister());
3565 }
3424 summary->set_out(0, Location::RequiresRegister()); 3566 summary->set_out(0, Location::RequiresRegister());
3425 return summary; 3567 return summary;
3426 } 3568 }
3427 3569
3428 3570
3429 void BoxFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { 3571 void BoxInt64Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
3572 if (ValueFitsSmi()) {
3573 PairLocation* value_pair = locs()->in(0).AsPairLocation();
3574 Register value_lo = value_pair->At(0).reg();
3575 Register out_reg = locs()->out(0).reg();
3576 __ movl(out_reg, value_lo);
3577 __ SmiTag(out_reg);
3578 return;
3579 }
3580
3581 PairLocation* value_pair = locs()->in(0).AsPairLocation();
3582 Register value_lo = value_pair->At(0).reg();
3583 Register value_hi = value_pair->At(1).reg();
3430 Register out_reg = locs()->out(0).reg(); 3584 Register out_reg = locs()->out(0).reg();
3431 XmmRegister value = locs()->in(0).fpu_reg(); 3585
3586 // Copy value_hi into out_reg as a temporary.
3587 // We modify value_lo but restore it before using it.
3588 __ movl(out_reg, value_hi);
3589
3590 // Unboxed operations produce smis or mint-sized values.
3591 // Check if value fits into a smi.
3592 Label not_smi, done;
3593
3594 // 1. Compute (x + -kMinSmi) which has to be in the range
3595 // 0 .. -kMinSmi+kMaxSmi for x to fit into a smi.
3596 __ addl(value_lo, Immediate(0x40000000));
3597 __ adcl(out_reg, Immediate(0));
3598 // 2. Unsigned compare to -kMinSmi+kMaxSmi.
3599 __ cmpl(value_lo, Immediate(0x80000000));
3600 __ sbbl(out_reg, Immediate(0));
3601 __ j(ABOVE_EQUAL, &not_smi);
3602 // 3. Restore lower half if result is a smi.
3603 __ subl(value_lo, Immediate(0x40000000));
3604 __ movl(out_reg, value_lo);
3605 __ SmiTag(out_reg);
3606 __ jmp(&done);
3607 __ Bind(&not_smi);
3608 // 3. Restore lower half of input before using it.
3609 __ subl(value_lo, Immediate(0x40000000));
3432 3610
3433 BoxAllocationSlowPath::Allocate( 3611 BoxAllocationSlowPath::Allocate(
3434 compiler, this, compiler->float32x4_class(), out_reg, kNoRegister); 3612 compiler, this, compiler->mint_class(), out_reg, kNoRegister);
3435 __ movups(FieldAddress(out_reg, Float32x4::value_offset()), value); 3613 __ movl(FieldAddress(out_reg, Mint::value_offset()), value_lo);
3436 } 3614 __ movl(FieldAddress(out_reg, Mint::value_offset() + kWordSize), value_hi);
3437 3615 __ Bind(&done);
3438 3616 }
3439 LocationSummary* UnboxFloat32x4Instr::MakeLocationSummary(Isolate* isolate, 3617
3618
3619 LocationSummary* UnboxInteger32Instr::MakeLocationSummary(Isolate* isolate,
3440 bool opt) const { 3620 bool opt) const {
3441 const intptr_t value_cid = value()->Type()->ToCid(); 3621 const intptr_t value_cid = value()->Type()->ToCid();
3442 const intptr_t kNumInputs = 1; 3622 const intptr_t kNumInputs = 1;
3443 const intptr_t kNumTemps = value_cid == kFloat32x4Cid ? 0 : 1; 3623 intptr_t kNumTemps = 0;
3624
3625 if (CanDeoptimize()) {
3626 if ((value_cid != kSmiCid) &&
3627 (value_cid != kMintCid) &&
3628 !is_truncating()) {
3629 kNumTemps = 2;
3630 } else {
3631 kNumTemps = 1;
3632 }
3633 }
3634
3444 LocationSummary* summary = new(isolate) LocationSummary( 3635 LocationSummary* summary = new(isolate) LocationSummary(
3445 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); 3636 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
3446 summary->set_in(0, Location::RequiresRegister()); 3637 summary->set_in(0, Location::RequiresRegister());
3447 if (kNumTemps > 0) { 3638 for (int i = 0; i < kNumTemps; i++) {
3448 ASSERT(kNumTemps == 1); 3639 summary->set_temp(i, Location::RequiresRegister());
3449 summary->set_temp(0, Location::RequiresRegister()); 3640 }
3450 } 3641 summary->set_out(0, ((value_cid == kSmiCid) || (value_cid != kMintCid)) ?
3451 summary->set_out(0, Location::RequiresFpuRegister()); 3642 Location::SameAsFirstInput() : Location::RequiresRegister());
3452 return summary; 3643 return summary;
3453 } 3644 }
3454 3645
3455 3646
3456 void UnboxFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { 3647 static void LoadInt32FromMint(FlowGraphCompiler* compiler,
3648 Register result,
3649 const Address& lo,
3650 const Address& hi,
3651 Register temp,
3652 Label* deopt) {
3653 __ movl(result, lo);
3654 if (deopt != NULL) {
3655 ASSERT(temp != result);
3656 __ movl(temp, result);
3657 __ sarl(temp, Immediate(31));
3658 __ cmpl(temp, hi);
3659 __ j(NOT_EQUAL, deopt);
3660 }
3661 }
3662
3663
3664 void UnboxInteger32Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
3457 const intptr_t value_cid = value()->Type()->ToCid(); 3665 const intptr_t value_cid = value()->Type()->ToCid();
3458 const Register value = locs()->in(0).reg(); 3666 Register value = locs()->in(0).reg();
3459 const XmmRegister result = locs()->out(0).fpu_reg(); 3667 const Register result = locs()->out(0).reg();
3460 3668 const Register temp = CanDeoptimize() ? locs()->temp(0).reg() : kNoRegister;
3461 if (value_cid != kFloat32x4Cid) { 3669 Label* deopt = CanDeoptimize() ?
3462 const Register temp = locs()->temp(0).reg(); 3670 compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptUnboxInteger) : NULL;
3463 Label* deopt = 3671 Label* out_of_range = !is_truncating() ? deopt : NULL;
3464 compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptCheckClass); 3672
3465 __ testl(value, Immediate(kSmiTagMask)); 3673 const intptr_t lo_offset = Mint::value_offset();
3466 __ j(ZERO, deopt); 3674 const intptr_t hi_offset = Mint::value_offset() + kWordSize;
3467 __ CompareClassId(value, kFloat32x4Cid, temp); 3675
3676 if (value_cid == kSmiCid) {
3677 ASSERT(value == result);
3678 __ SmiUntag(value);
3679 } else if (value_cid == kMintCid) {
3680 ASSERT((value != result) || (out_of_range == NULL));
3681 LoadInt32FromMint(compiler,
3682 result,
3683 FieldAddress(value, lo_offset),
3684 FieldAddress(value, hi_offset),
3685 temp,
3686 out_of_range);
3687 } else {
3688 ASSERT(value == result);
3689 Label done;
3690 __ SmiUntagOrCheckClass(value, kMintCid, temp, &done);
3468 __ j(NOT_EQUAL, deopt); 3691 __ j(NOT_EQUAL, deopt);
3469 } 3692 if (out_of_range != NULL) {
3470 __ movups(result, FieldAddress(value, Float32x4::value_offset())); 3693 Register value_temp = locs()->temp(1).reg();
3471 } 3694 __ movl(value_temp, value);
3472 3695 value = value_temp;
3473 3696 }
3474 LocationSummary* BoxFloat64x2Instr::MakeLocationSummary(Isolate* isolate, 3697 LoadInt32FromMint(compiler,
3475 bool opt) const { 3698 result,
3476 const intptr_t kNumInputs = 1; 3699 Address(value, TIMES_2, lo_offset),
3477 const intptr_t kNumTemps = 0; 3700 Address(value, TIMES_2, hi_offset),
3478 LocationSummary* summary = new(isolate) LocationSummary( 3701 temp,
3479 isolate, kNumInputs, 3702 out_of_range);
3480 kNumTemps, 3703 __ Bind(&done);
3481 LocationSummary::kCallOnSlowPath); 3704 }
3482 summary->set_in(0, Location::RequiresFpuRegister()); 3705 }
3483 summary->set_out(0, Location::RequiresRegister());
3484 return summary;
3485 }
3486
3487
3488 void BoxFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
3489 Register out_reg = locs()->out(0).reg();
3490 XmmRegister value = locs()->in(0).fpu_reg();
3491
3492 BoxAllocationSlowPath::Allocate(
3493 compiler, this, compiler->float64x2_class(), out_reg, kNoRegister);
3494 __ movups(FieldAddress(out_reg, Float64x2::value_offset()), value);
3495 }
3496
3497
3498 LocationSummary* UnboxFloat64x2Instr::MakeLocationSummary(Isolate* isolate,
3499 bool opt) const {
3500 const intptr_t value_cid = value()->Type()->ToCid();
3501 const intptr_t kNumInputs = 1;
3502 const intptr_t kNumTemps = value_cid == kFloat64x2Cid ? 0 : 1;
3503 LocationSummary* summary = new(isolate) LocationSummary(
3504 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
3505 summary->set_in(0, Location::RequiresRegister());
3506 if (kNumTemps > 0) {
3507 ASSERT(kNumTemps == 1);
3508 summary->set_temp(0, Location::RequiresRegister());
3509 }
3510 summary->set_out(0, Location::RequiresFpuRegister());
3511 return summary;
3512 }
3513
3514
3515 void UnboxFloat64x2Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
3516 const intptr_t value_cid = value()->Type()->ToCid();
3517 const Register value = locs()->in(0).reg();
3518 const XmmRegister result = locs()->out(0).fpu_reg();
3519
3520 if (value_cid != kFloat64x2Cid) {
3521 const Register temp = locs()->temp(0).reg();
3522 Label* deopt =
3523 compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptCheckClass);
3524 __ testl(value, Immediate(kSmiTagMask));
3525 __ j(ZERO, deopt);
3526 __ CompareClassId(value, kFloat64x2Cid, temp);
3527 __ j(NOT_EQUAL, deopt);
3528 }
3529 __ movups(result, FieldAddress(value, Float64x2::value_offset()));
3530 }
3531
3532
3533 LocationSummary* BoxInt32x4Instr::MakeLocationSummary(Isolate* isolate,
3534 bool opt) const {
3535 const intptr_t kNumInputs = 1;
3536 const intptr_t kNumTemps = 0;
3537 LocationSummary* summary = new(isolate) LocationSummary(
3538 isolate, kNumInputs,
3539 kNumTemps,
3540 LocationSummary::kCallOnSlowPath);
3541 summary->set_in(0, Location::RequiresFpuRegister());
3542 summary->set_out(0, Location::RequiresRegister());
3543 return summary;
3544 }
3545
3546
3547 void BoxInt32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
3548 Register out_reg = locs()->out(0).reg();
3549 XmmRegister value = locs()->in(0).fpu_reg();
3550
3551 BoxAllocationSlowPath::Allocate(
3552 compiler, this, compiler->int32x4_class(), out_reg, kNoRegister);
3553 __ movups(FieldAddress(out_reg, Int32x4::value_offset()), value);
3554 }
3555
3556
3557 LocationSummary* UnboxInt32x4Instr::MakeLocationSummary(Isolate* isolate,
3558 bool opt) const {
3559 const intptr_t value_cid = value()->Type()->ToCid();
3560 const intptr_t kNumInputs = 1;
3561 const intptr_t kNumTemps = value_cid == kInt32x4Cid ? 0 : 1;
3562 LocationSummary* summary = new(isolate) LocationSummary(
3563 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
3564 summary->set_in(0, Location::RequiresRegister());
3565 if (kNumTemps > 0) {
3566 ASSERT(kNumTemps == 1);
3567 summary->set_temp(0, Location::RequiresRegister());
3568 }
3569 summary->set_out(0, Location::RequiresFpuRegister());
3570 return summary;
3571 }
3572
3573
3574 void UnboxInt32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
3575 const intptr_t value_cid = value()->Type()->ToCid();
3576 const Register value = locs()->in(0).reg();
3577 const XmmRegister result = locs()->out(0).fpu_reg();
3578
3579 if (value_cid != kInt32x4Cid) {
3580 const Register temp = locs()->temp(0).reg();
3581 Label* deopt =
3582 compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptCheckClass);
3583 __ testl(value, Immediate(kSmiTagMask));
3584 __ j(ZERO, deopt);
3585 __ CompareClassId(value, kInt32x4Cid, temp);
3586 __ j(NOT_EQUAL, deopt);
3587 }
3588 __ movups(result, FieldAddress(value, Int32x4::value_offset()));
3589 }
3590
3591 3706
3592 3707
3593 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary(Isolate* isolate, 3708 LocationSummary* BinaryDoubleOpInstr::MakeLocationSummary(Isolate* isolate,
3594 bool opt) const { 3709 bool opt) const {
3595 const intptr_t kNumInputs = 2; 3710 const intptr_t kNumInputs = 2;
3596 const intptr_t kNumTemps = 0; 3711 const intptr_t kNumTemps = 0;
3597 LocationSummary* summary = new(isolate) LocationSummary( 3712 LocationSummary* summary = new(isolate) LocationSummary(
3598 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); 3713 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
3599 summary->set_in(0, Location::RequiresFpuRegister()); 3714 summary->set_in(0, Location::RequiresFpuRegister());
3600 summary->set_in(1, Location::RequiresFpuRegister()); 3715 summary->set_in(1, Location::RequiresFpuRegister());
(...skipping 2035 matching lines...) Expand 10 before | Expand all | Expand 10 after
5636 __ j(ABOVE_EQUAL, deopt); 5751 __ j(ABOVE_EQUAL, deopt);
5637 } else { 5752 } else {
5638 Register index = index_loc.reg(); 5753 Register index = index_loc.reg();
5639 Register length = length_loc.reg(); 5754 Register length = length_loc.reg();
5640 __ cmpl(length, index); 5755 __ cmpl(length, index);
5641 __ j(BELOW_EQUAL, deopt); 5756 __ j(BELOW_EQUAL, deopt);
5642 } 5757 }
5643 } 5758 }
5644 5759
5645 5760
5646 LocationSummary* UnboxIntegerInstr::MakeLocationSummary(Isolate* isolate,
5647 bool opt) const {
5648 const intptr_t kNumInputs = 1;
5649 const intptr_t kNumTemps = 0;
5650 LocationSummary* summary = new(isolate) LocationSummary(
5651 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
5652 summary->set_in(0, Location::RequiresRegister());
5653 summary->set_out(0, Location::Pair(Location::RegisterLocation(EAX),
5654 Location::RegisterLocation(EDX)));
5655 return summary;
5656 }
5657
5658
5659 void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5660 const intptr_t value_cid = value()->Type()->ToCid();
5661 const Register value = locs()->in(0).reg();
5662 PairLocation* result_pair = locs()->out(0).AsPairLocation();
5663 Register result_lo = result_pair->At(0).reg();
5664 Register result_hi = result_pair->At(1).reg();
5665
5666 ASSERT(value != result_lo);
5667 ASSERT(value != result_hi);
5668 ASSERT(result_lo == EAX);
5669 ASSERT(result_hi == EDX);
5670
5671 if (value_cid == kMintCid) {
5672 __ movl(result_lo, FieldAddress(value, Mint::value_offset()));
5673 __ movl(result_hi, FieldAddress(value, Mint::value_offset() + kWordSize));
5674 } else if (value_cid == kSmiCid) {
5675 __ movl(result_lo, value);
5676 __ SmiUntag(result_lo);
5677 // Sign extend into result_hi.
5678 __ cdq();
5679 } else {
5680 Label* deopt = compiler->AddDeoptStub(GetDeoptId(),
5681 ICData::kDeoptUnboxInteger);
5682 Label is_smi, done;
5683 __ testl(value, Immediate(kSmiTagMask));
5684 __ j(ZERO, &is_smi);
5685 __ CompareClassId(value, kMintCid, result_lo);
5686 __ j(NOT_EQUAL, deopt);
5687 __ movl(result_lo, FieldAddress(value, Mint::value_offset()));
5688 __ movl(result_hi, FieldAddress(value, Mint::value_offset() + kWordSize));
5689 __ jmp(&done);
5690 __ Bind(&is_smi);
5691 __ movl(result_lo, value);
5692 __ SmiUntag(result_lo);
5693 // Sign extend into result_hi.
5694 __ cdq();
5695 __ Bind(&done);
5696 }
5697 }
5698
5699
5700 LocationSummary* BoxIntegerInstr::MakeLocationSummary(Isolate* isolate,
5701 bool opt) const {
5702 const intptr_t kNumInputs = 1;
5703 const intptr_t kNumTemps = is_smi() ? 0 : 1;
5704 LocationSummary* summary = new(isolate) LocationSummary(
5705 isolate, kNumInputs,
5706 kNumTemps,
5707 is_smi()
5708 ? LocationSummary::kNoCall
5709 : LocationSummary::kCallOnSlowPath);
5710 summary->set_in(0, Location::Pair(Location::RequiresRegister(),
5711 Location::RequiresRegister()));
5712 if (!is_smi()) {
5713 summary->set_temp(0, Location::RequiresRegister());
5714 }
5715 summary->set_out(0, Location::RequiresRegister());
5716 return summary;
5717 }
5718
5719
5720 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
5721 if (is_smi()) {
5722 PairLocation* value_pair = locs()->in(0).AsPairLocation();
5723 Register value_lo = value_pair->At(0).reg();
5724 Register out_reg = locs()->out(0).reg();
5725 __ movl(out_reg, value_lo);
5726 __ SmiTag(out_reg);
5727 return;
5728 }
5729
5730 PairLocation* value_pair = locs()->in(0).AsPairLocation();
5731 Register value_lo = value_pair->At(0).reg();
5732 Register value_hi = value_pair->At(1).reg();
5733 Register out_reg = locs()->out(0).reg();
5734
5735 // Copy value_hi into out_reg as a temporary.
5736 // We modify value_lo but restore it before using it.
5737 __ movl(out_reg, value_hi);
5738
5739 // Unboxed operations produce smis or mint-sized values.
5740 // Check if value fits into a smi.
5741 Label not_smi, done;
5742
5743 // 1. Compute (x + -kMinSmi) which has to be in the range
5744 // 0 .. -kMinSmi+kMaxSmi for x to fit into a smi.
5745 __ addl(value_lo, Immediate(0x40000000));
5746 __ adcl(out_reg, Immediate(0));
5747 // 2. Unsigned compare to -kMinSmi+kMaxSmi.
5748 __ cmpl(value_lo, Immediate(0x80000000));
5749 __ sbbl(out_reg, Immediate(0));
5750 __ j(ABOVE_EQUAL, &not_smi);
5751 // 3. Restore lower half if result is a smi.
5752 __ subl(value_lo, Immediate(0x40000000));
5753 __ movl(out_reg, value_lo);
5754 __ SmiTag(out_reg);
5755 __ jmp(&done);
5756 __ Bind(&not_smi);
5757 // 3. Restore lower half of input before using it.
5758 __ subl(value_lo, Immediate(0x40000000));
5759
5760 BoxAllocationSlowPath::Allocate(
5761 compiler, this, compiler->mint_class(), out_reg, kNoRegister);
5762 __ movl(FieldAddress(out_reg, Mint::value_offset()), value_lo);
5763 __ movl(FieldAddress(out_reg, Mint::value_offset() + kWordSize), value_hi);
5764 __ Bind(&done);
5765 }
5766
5767
5768 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(Isolate* isolate, 5761 LocationSummary* BinaryMintOpInstr::MakeLocationSummary(Isolate* isolate,
5769 bool opt) const { 5762 bool opt) const {
5770 const intptr_t kNumInputs = 2; 5763 const intptr_t kNumInputs = 2;
5771 switch (op_kind()) { 5764 switch (op_kind()) {
5772 case Token::kBIT_AND: 5765 case Token::kBIT_AND:
5773 case Token::kBIT_OR: 5766 case Token::kBIT_OR:
5774 case Token::kBIT_XOR: 5767 case Token::kBIT_XOR:
5775 case Token::kADD: 5768 case Token::kADD:
5776 case Token::kSUB: 5769 case Token::kSUB:
5777 case Token::kMUL: { 5770 case Token::kMUL: {
(...skipping 436 matching lines...) Expand 10 before | Expand all | Expand 10 after
6214 void UnaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 6207 void UnaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
6215 Register out = locs()->out(0).reg(); 6208 Register out = locs()->out(0).reg();
6216 ASSERT(locs()->in(0).reg() == out); 6209 ASSERT(locs()->in(0).reg() == out);
6217 6210
6218 ASSERT(op_kind() == Token::kBIT_NOT); 6211 ASSERT(op_kind() == Token::kBIT_NOT);
6219 6212
6220 __ notl(out); 6213 __ notl(out);
6221 } 6214 }
6222 6215
6223 6216
6224 LocationSummary* BoxIntNInstr::MakeLocationSummary(Isolate* isolate,
6225 bool opt) const {
6226 const intptr_t kNumInputs = 1;
6227 const intptr_t kNumTemps = 0;
6228 LocationSummary* summary = new(isolate) LocationSummary(
6229 isolate, kNumInputs, kNumTemps,
6230 ValueFitsSmi() ? LocationSummary::kNoCall
6231 : LocationSummary::kCallOnSlowPath);
6232 const bool needs_writable_input = ValueFitsSmi() ||
6233 (from_representation() == kUnboxedUint32);
6234 summary->set_in(0, needs_writable_input ? Location::RequiresRegister()
6235 : Location::WritableRegister());
6236 summary->set_out(0, ValueFitsSmi() ? Location::SameAsFirstInput()
6237 : Location::RequiresRegister());
6238 return summary;
6239 }
6240
6241
6242 void BoxIntNInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
6243 const Register value = locs()->in(0).reg();
6244 const Register out = locs()->out(0).reg();
6245
6246 __ MoveRegister(out, value);
6247 __ shll(out, Immediate(kSmiTagSize));
6248 if (!ValueFitsSmi()) {
6249 Label done;
6250 ASSERT(value != out);
6251 if (from_representation() == kUnboxedInt32) {
6252 __ j(NO_OVERFLOW, &done);
6253 } else {
6254 __ testl(value, Immediate(0xC0000000));
6255 __ j(ZERO, &done);
6256 }
6257
6258 // Allocate a mint.
6259 // Value input is writable register and has to be manually preserved
6260 // on the slow path.
6261 locs()->live_registers()->Add(locs()->in(0), kUnboxedInt32);
6262 BoxAllocationSlowPath::Allocate(
6263 compiler, this, compiler->mint_class(), out, kNoRegister);
6264 __ movl(FieldAddress(out, Mint::value_offset()), value);
6265 if (from_representation() == kUnboxedInt32) {
6266 __ sarl(value, Immediate(31)); // Sign extend.
6267 __ movl(FieldAddress(out, Mint::value_offset() + kWordSize), value);
6268 } else {
6269 __ movl(FieldAddress(out, Mint::value_offset() + kWordSize),
6270 Immediate(0));
6271 }
6272 __ Bind(&done);
6273 }
6274 }
6275
6276
6277 LocationSummary* UnboxIntNInstr::MakeLocationSummary(Isolate* isolate,
6278 bool opt) const {
6279 const intptr_t value_cid = value()->Type()->ToCid();
6280 const intptr_t kNumInputs = 1;
6281 intptr_t kNumTemps = 0;
6282
6283 if (CanDeoptimize()) {
6284 if ((value_cid != kSmiCid) &&
6285 (value_cid != kMintCid) &&
6286 !is_truncating()) {
6287 kNumTemps = 2;
6288 } else {
6289 kNumTemps = 1;
6290 }
6291 }
6292
6293 LocationSummary* summary = new(isolate) LocationSummary(
6294 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
6295 summary->set_in(0, Location::RequiresRegister());
6296 for (int i = 0; i < kNumTemps; i++) {
6297 summary->set_temp(i, Location::RequiresRegister());
6298 }
6299 summary->set_out(0, ((value_cid == kSmiCid) || (value_cid != kMintCid)) ?
6300 Location::SameAsFirstInput() : Location::RequiresRegister());
6301 return summary;
6302 }
6303
6304
6305 static void LoadInt32FromMint(FlowGraphCompiler* compiler,
6306 Register result,
6307 const Address& lo,
6308 const Address& hi,
6309 Register temp,
6310 Label* deopt) {
6311 __ movl(result, lo);
6312 if (deopt != NULL) {
6313 ASSERT(temp != result);
6314 __ movl(temp, result);
6315 __ sarl(temp, Immediate(31));
6316 __ cmpl(temp, hi);
6317 __ j(NOT_EQUAL, deopt);
6318 }
6319 }
6320
6321
6322 void UnboxIntNInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
6323 const intptr_t value_cid = value()->Type()->ToCid();
6324 Register value = locs()->in(0).reg();
6325 const Register result = locs()->out(0).reg();
6326 const Register temp = CanDeoptimize() ? locs()->temp(0).reg() : kNoRegister;
6327 Label* deopt = CanDeoptimize() ?
6328 compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptUnboxInteger) : NULL;
6329 Label* out_of_range = !is_truncating() ? deopt : NULL;
6330
6331 const intptr_t lo_offset = Mint::value_offset();
6332 const intptr_t hi_offset = Mint::value_offset() + kWordSize;
6333
6334 if (value_cid == kSmiCid) {
6335 ASSERT(value == result);
6336 __ SmiUntag(value);
6337 } else if (value_cid == kMintCid) {
6338 ASSERT((value != result) || (out_of_range == NULL));
6339 LoadInt32FromMint(compiler,
6340 result,
6341 FieldAddress(value, lo_offset),
6342 FieldAddress(value, hi_offset),
6343 temp,
6344 out_of_range);
6345 } else {
6346 ASSERT(value == result);
6347 Label done;
6348 __ SmiUntagOrCheckClass(value, kMintCid, temp, &done);
6349 __ j(NOT_EQUAL, deopt);
6350 if (out_of_range != NULL) {
6351 Register value_temp = locs()->temp(1).reg();
6352 __ movl(value_temp, value);
6353 value = value_temp;
6354 }
6355 LoadInt32FromMint(compiler,
6356 result,
6357 Address(value, TIMES_2, lo_offset),
6358 Address(value, TIMES_2, hi_offset),
6359 temp,
6360 out_of_range);
6361 __ Bind(&done);
6362 }
6363 }
6364
6365
6366 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Isolate* isolate, 6217 LocationSummary* UnboxedIntConverterInstr::MakeLocationSummary(Isolate* isolate,
6367 bool opt) const { 6218 bool opt) const {
6368 const intptr_t kNumInputs = 1; 6219 const intptr_t kNumInputs = 1;
6369 const intptr_t kNumTemps = 0; 6220 const intptr_t kNumTemps = 0;
6370 LocationSummary* summary = new(isolate) LocationSummary( 6221 LocationSummary* summary = new(isolate) LocationSummary(
6371 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall); 6222 isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
6372 if ((from() == kUnboxedInt32 || from() == kUnboxedUint32) && 6223 if ((from() == kUnboxedInt32 || from() == kUnboxedUint32) &&
6373 (to() == kUnboxedInt32 || to() == kUnboxedUint32)) { 6224 (to() == kUnboxedInt32 || to() == kUnboxedUint32)) {
6374 summary->set_in(0, Location::RequiresRegister()); 6225 summary->set_in(0, Location::RequiresRegister());
6375 summary->set_out(0, Location::SameAsFirstInput()); 6226 summary->set_out(0, Location::SameAsFirstInput());
(...skipping 24 matching lines...) Expand all
6400 // Representations are bitwise equivalent. 6251 // Representations are bitwise equivalent.
6401 ASSERT(locs()->out(0).reg() == locs()->in(0).reg()); 6252 ASSERT(locs()->out(0).reg() == locs()->in(0).reg());
6402 if (CanDeoptimize()) { 6253 if (CanDeoptimize()) {
6403 Label* deopt = 6254 Label* deopt =
6404 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnboxInteger); 6255 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnboxInteger);
6405 __ testl(locs()->out(0).reg(), locs()->out(0).reg()); 6256 __ testl(locs()->out(0).reg(), locs()->out(0).reg());
6406 __ j(NEGATIVE, deopt); 6257 __ j(NEGATIVE, deopt);
6407 } 6258 }
6408 } else if (from() == kUnboxedMint) { 6259 } else if (from() == kUnboxedMint) {
6409 // TODO(vegorov) kUnboxedMint -> kInt32 conversion is currently usually 6260 // TODO(vegorov) kUnboxedMint -> kInt32 conversion is currently usually
6410 // dominated by a CheckSmi(BoxInteger(val)) which is an artifact of ordering 6261 // dominated by a CheckSmi(BoxInt64(val)) which is an artifact of ordering
6411 // of optimization passes and the way we check smi-ness of values. 6262 // of optimization passes and the way we check smi-ness of values.
6412 // Optimize it away. 6263 // Optimize it away.
6413 ASSERT(to() == kUnboxedInt32 || to() == kUnboxedUint32); 6264 ASSERT(to() == kUnboxedInt32 || to() == kUnboxedUint32);
6414 PairLocation* in_pair = locs()->in(0).AsPairLocation(); 6265 PairLocation* in_pair = locs()->in(0).AsPairLocation();
6415 Register in_lo = in_pair->At(0).reg(); 6266 Register in_lo = in_pair->At(0).reg();
6416 Register in_hi = in_pair->At(1).reg(); 6267 Register in_hi = in_pair->At(1).reg();
6417 Register out = locs()->out(0).reg(); 6268 Register out = locs()->out(0).reg();
6418 // Copy low word. 6269 // Copy low word.
6419 __ movl(out, in_lo); 6270 __ movl(out, in_lo);
6420 if (CanDeoptimize()) { 6271 if (CanDeoptimize()) {
(...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after
6768 __ movl(EDX, Immediate(kInvalidObjectPointer)); 6619 __ movl(EDX, Immediate(kInvalidObjectPointer));
6769 __ movl(EDX, Immediate(kInvalidObjectPointer)); 6620 __ movl(EDX, Immediate(kInvalidObjectPointer));
6770 #endif 6621 #endif
6771 } 6622 }
6772 6623
6773 } // namespace dart 6624 } // namespace dart
6774 6625
6775 #undef __ 6626 #undef __
6776 6627
6777 #endif // defined TARGET_ARCH_IA32 6628 #endif // defined TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language_arm64.cc ('k') | runtime/vm/intermediate_language_mips.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698