Index: runtime/vm/intermediate_language_arm64.cc |
=================================================================== |
--- runtime/vm/intermediate_language_arm64.cc (revision 36227) |
+++ runtime/vm/intermediate_language_arm64.cc (working copy) |
@@ -2448,6 +2448,20 @@ |
} |
+static void EmitJavascriptOverflowCheck(FlowGraphCompiler* compiler, |
+ Range* range, |
+ Label* overflow, |
+ Register result) { |
+ if (!range->IsWithin(-0x20000000000000LL, 0x20000000000000LL)) { |
+ ASSERT(overflow != NULL); |
+ __ CompareImmediate(result, -0x20000000000000LL, PP); |
+ __ b(overflow, LT); |
+ __ CompareImmediate(result, 0x20000000000000LL, PP); |
+ __ b(overflow, GT); |
+ } |
+} |
+ |
+ |
static void EmitSmiShiftLeft(FlowGraphCompiler* compiler, |
BinarySmiOpInstr* shift_left) { |
const bool is_truncating = shift_left->is_truncating(); |
@@ -2484,6 +2498,9 @@ |
// Shift for result now we know there is no overflow. |
__ Lsl(result, left, value); |
} |
+ if (FLAG_throw_on_javascript_int_overflow) { |
+ EmitJavascriptOverflowCheck(compiler, shift_left->range(), deopt, result); |
+ } |
return; |
} |
@@ -2514,6 +2531,9 @@ |
__ Asr(TMP, right, kSmiTagSize); // SmiUntag right into TMP. |
__ lslv(result, left, TMP); |
} |
+ if (FLAG_throw_on_javascript_int_overflow) { |
+ EmitJavascriptOverflowCheck(compiler, shift_left->range(), deopt, result); |
+ } |
return; |
} |
@@ -2559,6 +2579,9 @@ |
// Shift for result now we know there is no overflow. |
__ lslv(result, left, TMP); |
} |
+ if (FLAG_throw_on_javascript_int_overflow) { |
+ EmitJavascriptOverflowCheck(compiler, shift_left->range(), deopt, result); |
+ } |
} |
@@ -2733,6 +2756,9 @@ |
UNREACHABLE(); |
break; |
} |
+ if (FLAG_throw_on_javascript_int_overflow) { |
+ EmitJavascriptOverflowCheck(compiler, range(), deopt, result); |
+ } |
return; |
} |
@@ -2875,6 +2901,9 @@ |
UNREACHABLE(); |
break; |
} |
+ if (FLAG_throw_on_javascript_int_overflow) { |
+ EmitJavascriptOverflowCheck(compiler, range(), deopt, result); |
+ } |
} |
@@ -3562,6 +3591,9 @@ |
Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryOp); |
__ subs(result, ZR, Operand(value)); |
__ b(deopt, VS); |
+ if (FLAG_throw_on_javascript_int_overflow) { |
+ EmitJavascriptOverflowCheck(compiler, range(), deopt, value); |
+ } |
break; |
} |
case Token::kBIT_NOT: |
@@ -3643,6 +3675,9 @@ |
__ CompareImmediate(result, 0xC000000000000000, PP); |
__ b(&do_call, MI); |
__ SmiTag(result); |
+ if (FLAG_throw_on_javascript_int_overflow) { |
+ EmitJavascriptOverflowCheck(compiler, range(), &do_call, result); |
+ } |
__ b(&done); |
__ Bind(&do_call); |
__ Push(value_obj); |
@@ -3688,6 +3723,9 @@ |
__ CompareImmediate(result, 0xC000000000000000, PP); |
__ b(deopt, MI); |
__ SmiTag(result); |
+ if (FLAG_throw_on_javascript_int_overflow) { |
+ EmitJavascriptOverflowCheck(compiler, range(), deopt, result); |
+ } |
} |
@@ -3994,7 +4032,9 @@ |
__ add(TMP, result_mod, Operand(right)); |
__ csel(result_mod, TMP, TMP2, GE); |
__ Bind(&done); |
- |
+ // FLAG_throw_on_javascript_int_overflow: not needed. |
+ // Note that the result of an integer division/modulo of two |
+ // in-range arguments, cannot create out-of-range result. |
return; |
} |
if (kind() == MergedMathInstr::kSinCos) { |