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

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

Issue 288993003: Adds javascript overflow checking to arm64. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 7 months 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 | « no previous file | tests/standalone/standalone.status » ('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) 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 2430 matching lines...) Expand 10 before | Expand all | Expand 10 after
2441 __ CompareImmediate(temp, threshold, PP); 2441 __ CompareImmediate(temp, threshold, PP);
2442 __ b(slow_path->osr_entry_label(), GE); 2442 __ b(slow_path->osr_entry_label(), GE);
2443 } 2443 }
2444 if (compiler->ForceSlowPathForStackOverflow()) { 2444 if (compiler->ForceSlowPathForStackOverflow()) {
2445 __ b(slow_path->entry_label()); 2445 __ b(slow_path->entry_label());
2446 } 2446 }
2447 __ Bind(slow_path->exit_label()); 2447 __ Bind(slow_path->exit_label());
2448 } 2448 }
2449 2449
2450 2450
2451 static void EmitJavascriptOverflowCheck(FlowGraphCompiler* compiler,
2452 Range* range,
2453 Label* overflow,
2454 Register result) {
2455 if (!range->IsWithin(-0x20000000000000LL, 0x20000000000000LL)) {
2456 ASSERT(overflow != NULL);
2457 __ CompareImmediate(result, -0x20000000000000LL, PP);
2458 __ b(overflow, LT);
2459 __ CompareImmediate(result, 0x20000000000000LL, PP);
2460 __ b(overflow, GT);
2461 }
2462 }
2463
2464
2451 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler, 2465 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler,
2452 BinarySmiOpInstr* shift_left) { 2466 BinarySmiOpInstr* shift_left) {
2453 const bool is_truncating = shift_left->is_truncating(); 2467 const bool is_truncating = shift_left->is_truncating();
2454 const LocationSummary& locs = *shift_left->locs(); 2468 const LocationSummary& locs = *shift_left->locs();
2455 Register left = locs.in(0).reg(); 2469 Register left = locs.in(0).reg();
2456 Register result = locs.out(0).reg(); 2470 Register result = locs.out(0).reg();
2457 Label* deopt = shift_left->CanDeoptimize() ? 2471 Label* deopt = shift_left->CanDeoptimize() ?
2458 compiler->AddDeoptStub(shift_left->deopt_id(), ICData::kDeoptBinarySmiOp) 2472 compiler->AddDeoptStub(shift_left->deopt_id(), ICData::kDeoptBinarySmiOp)
2459 : NULL; 2473 : NULL;
2460 if (locs.in(1).IsConstant()) { 2474 if (locs.in(1).IsConstant()) {
(...skipping 16 matching lines...) Expand all
2477 } else { 2491 } else {
2478 if (!is_truncating) { 2492 if (!is_truncating) {
2479 // Check for overflow (preserve left). 2493 // Check for overflow (preserve left).
2480 __ Lsl(TMP, left, value); 2494 __ Lsl(TMP, left, value);
2481 __ cmp(left, Operand(TMP, ASR, value)); 2495 __ cmp(left, Operand(TMP, ASR, value));
2482 __ b(deopt, NE); // Overflow. 2496 __ b(deopt, NE); // Overflow.
2483 } 2497 }
2484 // Shift for result now we know there is no overflow. 2498 // Shift for result now we know there is no overflow.
2485 __ Lsl(result, left, value); 2499 __ Lsl(result, left, value);
2486 } 2500 }
2501 if (FLAG_throw_on_javascript_int_overflow) {
2502 EmitJavascriptOverflowCheck(compiler, shift_left->range(), deopt, result);
2503 }
2487 return; 2504 return;
2488 } 2505 }
2489 2506
2490 // Right (locs.in(1)) is not constant. 2507 // Right (locs.in(1)) is not constant.
2491 Register right = locs.in(1).reg(); 2508 Register right = locs.in(1).reg();
2492 Range* right_range = shift_left->right()->definition()->range(); 2509 Range* right_range = shift_left->right()->definition()->range();
2493 if (shift_left->left()->BindsToConstant() && !is_truncating) { 2510 if (shift_left->left()->BindsToConstant() && !is_truncating) {
2494 // TODO(srdjan): Implement code below for is_truncating(). 2511 // TODO(srdjan): Implement code below for is_truncating().
2495 // If left is constant, we know the maximal allowed size for right. 2512 // If left is constant, we know the maximal allowed size for right.
2496 const Object& obj = shift_left->left()->BoundConstant(); 2513 const Object& obj = shift_left->left()->BoundConstant();
(...skipping 10 matching lines...) Expand all
2507 (right_range == NULL) || 2524 (right_range == NULL) ||
2508 !right_range->IsWithin(0, max_right - 1); 2525 !right_range->IsWithin(0, max_right - 1);
2509 if (right_needs_check) { 2526 if (right_needs_check) {
2510 __ CompareImmediate(right, 2527 __ CompareImmediate(right,
2511 reinterpret_cast<int64_t>(Smi::New(max_right)), PP); 2528 reinterpret_cast<int64_t>(Smi::New(max_right)), PP);
2512 __ b(deopt, CS); 2529 __ b(deopt, CS);
2513 } 2530 }
2514 __ Asr(TMP, right, kSmiTagSize); // SmiUntag right into TMP. 2531 __ Asr(TMP, right, kSmiTagSize); // SmiUntag right into TMP.
2515 __ lslv(result, left, TMP); 2532 __ lslv(result, left, TMP);
2516 } 2533 }
2534 if (FLAG_throw_on_javascript_int_overflow) {
2535 EmitJavascriptOverflowCheck(compiler, shift_left->range(), deopt, result);
2536 }
2517 return; 2537 return;
2518 } 2538 }
2519 2539
2520 const bool right_needs_check = 2540 const bool right_needs_check =
2521 (right_range == NULL) || !right_range->IsWithin(0, (Smi::kBits - 1)); 2541 (right_range == NULL) || !right_range->IsWithin(0, (Smi::kBits - 1));
2522 if (is_truncating) { 2542 if (is_truncating) {
2523 if (right_needs_check) { 2543 if (right_needs_check) {
2524 const bool right_may_be_negative = 2544 const bool right_may_be_negative =
2525 (right_range == NULL) || 2545 (right_range == NULL) ||
2526 !right_range->IsWithin(0, RangeBoundary::kPlusInfinity); 2546 !right_range->IsWithin(0, RangeBoundary::kPlusInfinity);
(...skipping 25 matching lines...) Expand all
2552 __ Asr(TMP, right, kSmiTagSize); // SmiUntag right into IP. 2572 __ Asr(TMP, right, kSmiTagSize); // SmiUntag right into IP.
2553 // Overflow test (preserve left, right, and IP); 2573 // Overflow test (preserve left, right, and IP);
2554 Register temp = locs.temp(0).reg(); 2574 Register temp = locs.temp(0).reg();
2555 __ lslv(temp, left, TMP); 2575 __ lslv(temp, left, TMP);
2556 __ asrv(TMP2, temp, TMP); 2576 __ asrv(TMP2, temp, TMP);
2557 __ CompareRegisters(left, TMP2); 2577 __ CompareRegisters(left, TMP2);
2558 __ b(deopt, NE); // Overflow. 2578 __ b(deopt, NE); // Overflow.
2559 // Shift for result now we know there is no overflow. 2579 // Shift for result now we know there is no overflow.
2560 __ lslv(result, left, TMP); 2580 __ lslv(result, left, TMP);
2561 } 2581 }
2582 if (FLAG_throw_on_javascript_int_overflow) {
2583 EmitJavascriptOverflowCheck(compiler, shift_left->range(), deopt, result);
2584 }
2562 } 2585 }
2563 2586
2564 2587
2565 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(bool opt) const { 2588 LocationSummary* BinarySmiOpInstr::MakeLocationSummary(bool opt) const {
2566 const intptr_t kNumInputs = 2; 2589 const intptr_t kNumInputs = 2;
2567 const intptr_t kNumTemps = 0; 2590 const intptr_t kNumTemps = 0;
2568 LocationSummary* summary = 2591 LocationSummary* summary =
2569 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 2592 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
2570 if (op_kind() == Token::kTRUNCDIV) { 2593 if (op_kind() == Token::kTRUNCDIV) {
2571 summary->set_in(0, Location::RequiresRegister()); 2594 summary->set_in(0, Location::RequiresRegister());
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
2726 } 2749 }
2727 2750
2728 __ Asr(result, left, value); 2751 __ Asr(result, left, value);
2729 __ SmiTag(result); 2752 __ SmiTag(result);
2730 break; 2753 break;
2731 } 2754 }
2732 default: 2755 default:
2733 UNREACHABLE(); 2756 UNREACHABLE();
2734 break; 2757 break;
2735 } 2758 }
2759 if (FLAG_throw_on_javascript_int_overflow) {
2760 EmitJavascriptOverflowCheck(compiler, range(), deopt, result);
2761 }
2736 return; 2762 return;
2737 } 2763 }
2738 2764
2739 Register right = locs()->in(1).reg(); 2765 Register right = locs()->in(1).reg();
2740 Range* right_range = this->right()->definition()->range(); 2766 Range* right_range = this->right()->definition()->range();
2741 switch (op_kind()) { 2767 switch (op_kind()) {
2742 case Token::kADD: { 2768 case Token::kADD: {
2743 if (deopt == NULL) { 2769 if (deopt == NULL) {
2744 __ add(result, left, Operand(right)); 2770 __ add(result, left, Operand(right));
2745 } else { 2771 } else {
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
2868 case Token::kAND: { 2894 case Token::kAND: {
2869 // Flow graph builder has dissected this operation to guarantee correct 2895 // Flow graph builder has dissected this operation to guarantee correct
2870 // behavior (short-circuit evaluation). 2896 // behavior (short-circuit evaluation).
2871 UNREACHABLE(); 2897 UNREACHABLE();
2872 break; 2898 break;
2873 } 2899 }
2874 default: 2900 default:
2875 UNREACHABLE(); 2901 UNREACHABLE();
2876 break; 2902 break;
2877 } 2903 }
2904 if (FLAG_throw_on_javascript_int_overflow) {
2905 EmitJavascriptOverflowCheck(compiler, range(), deopt, result);
2906 }
2878 } 2907 }
2879 2908
2880 2909
2881 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(bool opt) const { 2910 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary(bool opt) const {
2882 intptr_t left_cid = left()->Type()->ToCid(); 2911 intptr_t left_cid = left()->Type()->ToCid();
2883 intptr_t right_cid = right()->Type()->ToCid(); 2912 intptr_t right_cid = right()->Type()->ToCid();
2884 ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid)); 2913 ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid));
2885 const intptr_t kNumInputs = 2; 2914 const intptr_t kNumInputs = 2;
2886 const intptr_t kNumTemps = 0; 2915 const intptr_t kNumTemps = 0;
2887 LocationSummary* summary = 2916 LocationSummary* summary =
(...skipping 667 matching lines...) Expand 10 before | Expand all | Expand 10 after
3555 3584
3556 3585
3557 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3586 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3558 Register value = locs()->in(0).reg(); 3587 Register value = locs()->in(0).reg();
3559 Register result = locs()->out(0).reg(); 3588 Register result = locs()->out(0).reg();
3560 switch (op_kind()) { 3589 switch (op_kind()) {
3561 case Token::kNEGATE: { 3590 case Token::kNEGATE: {
3562 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryOp); 3591 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryOp);
3563 __ subs(result, ZR, Operand(value)); 3592 __ subs(result, ZR, Operand(value));
3564 __ b(deopt, VS); 3593 __ b(deopt, VS);
3594 if (FLAG_throw_on_javascript_int_overflow) {
3595 EmitJavascriptOverflowCheck(compiler, range(), deopt, value);
3596 }
3565 break; 3597 break;
3566 } 3598 }
3567 case Token::kBIT_NOT: 3599 case Token::kBIT_NOT:
3568 __ mvn(result, value); 3600 __ mvn(result, value);
3569 // Remove inverted smi-tag. 3601 // Remove inverted smi-tag.
3570 __ andi(result, result, ~kSmiTagMask); 3602 __ andi(result, result, ~kSmiTagMask);
3571 break; 3603 break;
3572 default: 3604 default:
3573 UNREACHABLE(); 3605 UNREACHABLE();
3574 } 3606 }
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
3636 __ fcmpd(VTMP, VTMP); 3668 __ fcmpd(VTMP, VTMP);
3637 __ b(&do_call, VS); 3669 __ b(&do_call, VS);
3638 3670
3639 __ fcvtzds(result, VTMP); 3671 __ fcvtzds(result, VTMP);
3640 // Overflow is signaled with minint. 3672 // Overflow is signaled with minint.
3641 3673
3642 // Check for overflow and that it fits into Smi. 3674 // Check for overflow and that it fits into Smi.
3643 __ CompareImmediate(result, 0xC000000000000000, PP); 3675 __ CompareImmediate(result, 0xC000000000000000, PP);
3644 __ b(&do_call, MI); 3676 __ b(&do_call, MI);
3645 __ SmiTag(result); 3677 __ SmiTag(result);
3678 if (FLAG_throw_on_javascript_int_overflow) {
3679 EmitJavascriptOverflowCheck(compiler, range(), &do_call, result);
3680 }
3646 __ b(&done); 3681 __ b(&done);
3647 __ Bind(&do_call); 3682 __ Bind(&do_call);
3648 __ Push(value_obj); 3683 __ Push(value_obj);
3649 ASSERT(instance_call()->HasICData()); 3684 ASSERT(instance_call()->HasICData());
3650 const ICData& ic_data = *instance_call()->ic_data(); 3685 const ICData& ic_data = *instance_call()->ic_data();
3651 ASSERT((ic_data.NumberOfChecks() == 1)); 3686 ASSERT((ic_data.NumberOfChecks() == 1));
3652 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0)); 3687 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0));
3653 3688
3654 const intptr_t kNumberOfArguments = 1; 3689 const intptr_t kNumberOfArguments = 1;
3655 compiler->GenerateStaticCall(deopt_id(), 3690 compiler->GenerateStaticCall(deopt_id(),
(...skipping 25 matching lines...) Expand all
3681 // on ARM64 because fcvtzds gives 0 for NaN. 3716 // on ARM64 because fcvtzds gives 0 for NaN.
3682 // TODO(zra): Check spec that this is true. 3717 // TODO(zra): Check spec that this is true.
3683 __ fcmpd(value, value); 3718 __ fcmpd(value, value);
3684 __ b(deopt, VS); 3719 __ b(deopt, VS);
3685 3720
3686 __ fcvtzds(result, value); 3721 __ fcvtzds(result, value);
3687 // Check for overflow and that it fits into Smi. 3722 // Check for overflow and that it fits into Smi.
3688 __ CompareImmediate(result, 0xC000000000000000, PP); 3723 __ CompareImmediate(result, 0xC000000000000000, PP);
3689 __ b(deopt, MI); 3724 __ b(deopt, MI);
3690 __ SmiTag(result); 3725 __ SmiTag(result);
3726 if (FLAG_throw_on_javascript_int_overflow) {
3727 EmitJavascriptOverflowCheck(compiler, range(), deopt, result);
3728 }
3691 } 3729 }
3692 3730
3693 3731
3694 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary(bool opt) const { 3732 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary(bool opt) const {
3695 UNIMPLEMENTED(); 3733 UNIMPLEMENTED();
3696 return NULL; 3734 return NULL;
3697 } 3735 }
3698 3736
3699 3737
3700 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3738 void DoubleToDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after
3987 // } 4025 // }
3988 Label done; 4026 Label done;
3989 __ CompareRegisters(result_mod, ZR);; 4027 __ CompareRegisters(result_mod, ZR);;
3990 __ b(&done, GE); 4028 __ b(&done, GE);
3991 // Result is negative, adjust it. 4029 // Result is negative, adjust it.
3992 __ CompareRegisters(right, ZR); 4030 __ CompareRegisters(right, ZR);
3993 __ sub(TMP2, result_mod, Operand(right)); 4031 __ sub(TMP2, result_mod, Operand(right));
3994 __ add(TMP, result_mod, Operand(right)); 4032 __ add(TMP, result_mod, Operand(right));
3995 __ csel(result_mod, TMP, TMP2, GE); 4033 __ csel(result_mod, TMP, TMP2, GE);
3996 __ Bind(&done); 4034 __ Bind(&done);
3997 4035 // FLAG_throw_on_javascript_int_overflow: not needed.
4036 // Note that the result of an integer division/modulo of two
4037 // in-range arguments, cannot create out-of-range result.
3998 return; 4038 return;
3999 } 4039 }
4000 if (kind() == MergedMathInstr::kSinCos) { 4040 if (kind() == MergedMathInstr::kSinCos) {
4001 UNIMPLEMENTED(); 4041 UNIMPLEMENTED();
4002 } 4042 }
4003 UNIMPLEMENTED(); 4043 UNIMPLEMENTED();
4004 } 4044 }
4005 4045
4006 4046
4007 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary( 4047 LocationSummary* PolymorphicInstanceCallInstr::MakeLocationSummary(
(...skipping 439 matching lines...) Expand 10 before | Expand all | Expand 10 after
4447 compiler->GenerateCall(token_pos(), 4487 compiler->GenerateCall(token_pos(),
4448 &label, 4488 &label,
4449 PcDescriptors::kOther, 4489 PcDescriptors::kOther,
4450 locs()); 4490 locs());
4451 __ Drop(ArgumentCount()); // Discard arguments. 4491 __ Drop(ArgumentCount()); // Discard arguments.
4452 } 4492 }
4453 4493
4454 } // namespace dart 4494 } // namespace dart
4455 4495
4456 #endif // defined TARGET_ARCH_ARM64 4496 #endif // defined TARGET_ARCH_ARM64
OLDNEW
« no previous file with comments | « no previous file | tests/standalone/standalone.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698