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

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

Issue 21876005: Fixes obo error in javascript int checking. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 4 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 | « runtime/lib/integers.dart ('k') | runtime/vm/object.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_X64. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64.
6 #if defined(TARGET_ARCH_X64) 6 #if defined(TARGET_ARCH_X64)
7 7
8 #include "vm/intermediate_language.h" 8 #include "vm/intermediate_language.h"
9 9
10 #include "lib/error.h" 10 #include "lib/error.h"
(...skipping 2133 matching lines...) Expand 10 before | Expand all | Expand 10 after
2144 intptr_t threshold = 2144 intptr_t threshold =
2145 FLAG_optimization_counter_threshold * (loop_depth() + 1); 2145 FLAG_optimization_counter_threshold * (loop_depth() + 1);
2146 __ cmpq(FieldAddress(temp, Function::usage_counter_offset()), 2146 __ cmpq(FieldAddress(temp, Function::usage_counter_offset()),
2147 Immediate(threshold)); 2147 Immediate(threshold));
2148 __ j(GREATER_EQUAL, slow_path->entry_label()); 2148 __ j(GREATER_EQUAL, slow_path->entry_label());
2149 } 2149 }
2150 __ Bind(slow_path->exit_label()); 2150 __ Bind(slow_path->exit_label());
2151 } 2151 }
2152 2152
2153 2153
2154 static void Emit54BitOverflowCheck(FlowGraphCompiler* compiler, 2154 static void EmitJavascriptOverflowCheck(FlowGraphCompiler* compiler,
2155 Label* overflow, 2155 Label* overflow,
2156 Register result) { 2156 Register result) {
2157 if (FLAG_throw_on_javascript_int_overflow) { 2157 if (FLAG_throw_on_javascript_int_overflow) {
2158 ASSERT(overflow != NULL); 2158 ASSERT(overflow != NULL);
2159 __ movq(TMP, result); // result is a tagged Smi. 2159 __ cmpq(result, Immediate(-0x20000000000000));
2160 // Bits 55...64 must be all 0 or all 1. (It would be bit 54, but result 2160 __ j(LESS, overflow);
2161 // is tagged.) 2161 __ cmpq(result, Immediate(0x20000000000000));
2162 __ shlq(result, Immediate(64 - 55)); 2162 __ j(GREATER, overflow);
2163 __ sarq(result, Immediate(64 - 55));
2164 __ cmpq(result, TMP);
2165 __ j(NOT_EQUAL, overflow); // 54-bit overflow.
2166 __ cmpq(result, Immediate(-0x1FFFFFFFFFFFFFLL - 1));
2167 __ j(EQUAL, overflow); // The most negative 54-bit int is also disallowed.
2168 } 2163 }
2169 } 2164 }
2170 2165
2171 2166
2172 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler, 2167 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler,
2173 BinarySmiOpInstr* shift_left) { 2168 BinarySmiOpInstr* shift_left) {
2174 const bool is_truncating = shift_left->is_truncating(); 2169 const bool is_truncating = shift_left->is_truncating();
2175 const LocationSummary& locs = *shift_left->locs(); 2170 const LocationSummary& locs = *shift_left->locs();
2176 Register left = locs.in(0).reg(); 2171 Register left = locs.in(0).reg();
2177 Register result = locs.out().reg(); 2172 Register result = locs.out().reg();
(...skipping 23 matching lines...) Expand all
2201 Register temp = locs.temp(0).reg(); 2196 Register temp = locs.temp(0).reg();
2202 __ movq(temp, left); 2197 __ movq(temp, left);
2203 __ shlq(left, Immediate(value)); 2198 __ shlq(left, Immediate(value));
2204 __ sarq(left, Immediate(value)); 2199 __ sarq(left, Immediate(value));
2205 __ cmpq(left, temp); 2200 __ cmpq(left, temp);
2206 __ j(NOT_EQUAL, deopt); // Overflow. 2201 __ j(NOT_EQUAL, deopt); // Overflow.
2207 } 2202 }
2208 // Shift for result now we know there is no overflow. 2203 // Shift for result now we know there is no overflow.
2209 __ shlq(left, Immediate(value)); 2204 __ shlq(left, Immediate(value));
2210 } 2205 }
2211 Emit54BitOverflowCheck(compiler, deopt, result); 2206 EmitJavascriptOverflowCheck(compiler, deopt, result);
2212 return; 2207 return;
2213 } 2208 }
2214 2209
2215 // Right (locs.in(1)) is not constant. 2210 // Right (locs.in(1)) is not constant.
2216 Register right = locs.in(1).reg(); 2211 Register right = locs.in(1).reg();
2217 Range* right_range = shift_left->right()->definition()->range(); 2212 Range* right_range = shift_left->right()->definition()->range();
2218 if (shift_left->left()->BindsToConstant() && !is_truncating) { 2213 if (shift_left->left()->BindsToConstant() && !is_truncating) {
2219 // TODO(srdjan): Implement code below for is_truncating(). 2214 // TODO(srdjan): Implement code below for is_truncating().
2220 // If left is constant, we know the maximal allowed size for right. 2215 // If left is constant, we know the maximal allowed size for right.
2221 const Object& obj = shift_left->left()->BoundConstant(); 2216 const Object& obj = shift_left->left()->BoundConstant();
2222 if (obj.IsSmi()) { 2217 if (obj.IsSmi()) {
2223 const intptr_t left_int = Smi::Cast(obj).Value(); 2218 const intptr_t left_int = Smi::Cast(obj).Value();
2224 if (left_int == 0) { 2219 if (left_int == 0) {
2225 __ cmpq(right, Immediate(0)); 2220 __ cmpq(right, Immediate(0));
2226 __ j(NEGATIVE, deopt); 2221 __ j(NEGATIVE, deopt);
2227 return; 2222 return;
2228 } 2223 }
2229 const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int); 2224 const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int);
2230 const bool right_needs_check = 2225 const bool right_needs_check =
2231 (right_range == NULL) || 2226 (right_range == NULL) ||
2232 !right_range->IsWithin(0, max_right - 1); 2227 !right_range->IsWithin(0, max_right - 1);
2233 if (right_needs_check) { 2228 if (right_needs_check) {
2234 __ cmpq(right, 2229 __ cmpq(right,
2235 Immediate(reinterpret_cast<int64_t>(Smi::New(max_right)))); 2230 Immediate(reinterpret_cast<int64_t>(Smi::New(max_right))));
2236 __ j(ABOVE_EQUAL, deopt); 2231 __ j(ABOVE_EQUAL, deopt);
2237 } 2232 }
2238 __ SmiUntag(right); 2233 __ SmiUntag(right);
2239 __ shlq(left, right); 2234 __ shlq(left, right);
2240 } 2235 }
2241 Emit54BitOverflowCheck(compiler, deopt, result); 2236 EmitJavascriptOverflowCheck(compiler, deopt, result);
2242 return; 2237 return;
2243 } 2238 }
2244 2239
2245 const bool right_needs_check = 2240 const bool right_needs_check =
2246 (right_range == NULL) || !right_range->IsWithin(0, (Smi::kBits - 1)); 2241 (right_range == NULL) || !right_range->IsWithin(0, (Smi::kBits - 1));
2247 ASSERT(right == RCX); // Count must be in RCX 2242 ASSERT(right == RCX); // Count must be in RCX
2248 if (is_truncating) { 2243 if (is_truncating) {
2249 if (right_needs_check) { 2244 if (right_needs_check) {
2250 const bool right_may_be_negative = 2245 const bool right_may_be_negative =
2251 (right_range == NULL) || 2246 (right_range == NULL) ||
(...skipping 30 matching lines...) Expand all
2282 __ movq(temp, left); 2277 __ movq(temp, left);
2283 __ SmiUntag(right); 2278 __ SmiUntag(right);
2284 // Overflow test (preserve temp and right); 2279 // Overflow test (preserve temp and right);
2285 __ shlq(left, right); 2280 __ shlq(left, right);
2286 __ sarq(left, right); 2281 __ sarq(left, right);
2287 __ cmpq(left, temp); 2282 __ cmpq(left, temp);
2288 __ j(NOT_EQUAL, deopt); // Overflow. 2283 __ j(NOT_EQUAL, deopt); // Overflow.
2289 // Shift for result now we know there is no overflow. 2284 // Shift for result now we know there is no overflow.
2290 __ shlq(left, right); 2285 __ shlq(left, right);
2291 } 2286 }
2292 Emit54BitOverflowCheck(compiler, deopt, result); 2287 EmitJavascriptOverflowCheck(compiler, deopt, result);
2293 } 2288 }
2294 2289
2295 2290
2296 static bool CanBeImmediate(const Object& constant) { 2291 static bool CanBeImmediate(const Object& constant) {
2297 return constant.IsSmi() && 2292 return constant.IsSmi() &&
2298 Immediate(reinterpret_cast<int64_t>(constant.raw())).is_int32(); 2293 Immediate(reinterpret_cast<int64_t>(constant.raw())).is_int32();
2299 } 2294 }
2300 2295
2301 2296
2302 LocationSummary* BinarySmiOpInstr::MakeLocationSummary() const { 2297 LocationSummary* BinarySmiOpInstr::MakeLocationSummary() const {
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
2481 2476
2482 __ sarq(left, Immediate(value)); 2477 __ sarq(left, Immediate(value));
2483 __ SmiTag(left); 2478 __ SmiTag(left);
2484 break; 2479 break;
2485 } 2480 }
2486 2481
2487 default: 2482 default:
2488 UNREACHABLE(); 2483 UNREACHABLE();
2489 break; 2484 break;
2490 } 2485 }
2491 Emit54BitOverflowCheck(compiler, deopt, result); 2486 EmitJavascriptOverflowCheck(compiler, deopt, result);
2492 return; 2487 return;
2493 } // locs()->in(1).IsConstant(). 2488 } // locs()->in(1).IsConstant().
2494 2489
2495 2490
2496 if (locs()->in(1).IsStackSlot()) { 2491 if (locs()->in(1).IsStackSlot()) {
2497 const Address& right = locs()->in(1).ToStackSlotAddress(); 2492 const Address& right = locs()->in(1).ToStackSlotAddress();
2498 switch (op_kind()) { 2493 switch (op_kind()) {
2499 case Token::kADD: { 2494 case Token::kADD: {
2500 __ addq(left, right); 2495 __ addq(left, right);
2501 if (deopt != NULL) __ j(OVERFLOW, deopt); 2496 if (deopt != NULL) __ j(OVERFLOW, deopt);
(...skipping 22 matching lines...) Expand all
2524 } 2519 }
2525 case Token::kBIT_XOR: { 2520 case Token::kBIT_XOR: {
2526 // No overflow check. 2521 // No overflow check.
2527 __ xorq(left, right); 2522 __ xorq(left, right);
2528 break; 2523 break;
2529 } 2524 }
2530 default: 2525 default:
2531 UNREACHABLE(); 2526 UNREACHABLE();
2532 break; 2527 break;
2533 } 2528 }
2534 Emit54BitOverflowCheck(compiler, deopt, result); 2529 EmitJavascriptOverflowCheck(compiler, deopt, result);
2535 return; 2530 return;
2536 } // locs()->in(1).IsStackSlot(). 2531 } // locs()->in(1).IsStackSlot().
2537 2532
2538 // if locs()->in(1).IsRegister. 2533 // if locs()->in(1).IsRegister.
2539 Register right = locs()->in(1).reg(); 2534 Register right = locs()->in(1).reg();
2540 switch (op_kind()) { 2535 switch (op_kind()) {
2541 case Token::kADD: { 2536 case Token::kADD: {
2542 __ addq(left, right); 2537 __ addq(left, right);
2543 if (deopt != NULL) __ j(OVERFLOW, deopt); 2538 if (deopt != NULL) __ j(OVERFLOW, deopt);
2544 break; 2539 break;
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
2654 case Token::kAND: { 2649 case Token::kAND: {
2655 // Flow graph builder has dissected this operation to guarantee correct 2650 // Flow graph builder has dissected this operation to guarantee correct
2656 // behavior (short-circuit evaluation). 2651 // behavior (short-circuit evaluation).
2657 UNREACHABLE(); 2652 UNREACHABLE();
2658 break; 2653 break;
2659 } 2654 }
2660 default: 2655 default:
2661 UNREACHABLE(); 2656 UNREACHABLE();
2662 break; 2657 break;
2663 } 2658 }
2664 Emit54BitOverflowCheck(compiler, deopt, result); 2659 EmitJavascriptOverflowCheck(compiler, deopt, result);
2665 } 2660 }
2666 2661
2667 2662
2668 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary() const { 2663 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary() const {
2669 intptr_t left_cid = left()->Type()->ToCid(); 2664 intptr_t left_cid = left()->Type()->ToCid();
2670 intptr_t right_cid = right()->Type()->ToCid(); 2665 intptr_t right_cid = right()->Type()->ToCid();
2671 ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid)); 2666 ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid));
2672 const intptr_t kNumInputs = 2; 2667 const intptr_t kNumInputs = 2;
2673 const bool need_temp = (left_cid != kSmiCid) && (right_cid != kSmiCid); 2668 const bool need_temp = (left_cid != kSmiCid) && (right_cid != kSmiCid);
2674 const intptr_t kNumTemps = need_temp ? 1 : 0; 2669 const intptr_t kNumTemps = need_temp ? 1 : 0;
(...skipping 1157 matching lines...) Expand 10 before | Expand all | Expand 10 after
3832 3827
3833 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3828 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3834 Register value = locs()->in(0).reg(); 3829 Register value = locs()->in(0).reg();
3835 ASSERT(value == locs()->out().reg()); 3830 ASSERT(value == locs()->out().reg());
3836 switch (op_kind()) { 3831 switch (op_kind()) {
3837 case Token::kNEGATE: { 3832 case Token::kNEGATE: {
3838 Label* deopt = compiler->AddDeoptStub(deopt_id(), 3833 Label* deopt = compiler->AddDeoptStub(deopt_id(),
3839 kDeoptUnaryOp); 3834 kDeoptUnaryOp);
3840 __ negq(value); 3835 __ negq(value);
3841 __ j(OVERFLOW, deopt); 3836 __ j(OVERFLOW, deopt);
3842 Emit54BitOverflowCheck(compiler, deopt, value); 3837 EmitJavascriptOverflowCheck(compiler, deopt, value);
3843 break; 3838 break;
3844 } 3839 }
3845 case Token::kBIT_NOT: 3840 case Token::kBIT_NOT:
3846 __ notq(value); 3841 __ notq(value);
3847 __ andq(value, Immediate(~kSmiTagMask)); // Remove inverted smi-tag. 3842 __ andq(value, Immediate(~kSmiTagMask)); // Remove inverted smi-tag.
3848 break; 3843 break;
3849 default: 3844 default:
3850 UNREACHABLE(); 3845 UNREACHABLE();
3851 } 3846 }
3852 } 3847 }
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
3893 ASSERT(result != temp); 3888 ASSERT(result != temp);
3894 __ movsd(value_double, FieldAddress(value_obj, Double::value_offset())); 3889 __ movsd(value_double, FieldAddress(value_obj, Double::value_offset()));
3895 __ cvttsd2siq(result, value_double); 3890 __ cvttsd2siq(result, value_double);
3896 // Overflow is signalled with minint. 3891 // Overflow is signalled with minint.
3897 Label do_call, done; 3892 Label do_call, done;
3898 // Check for overflow and that it fits into Smi. 3893 // Check for overflow and that it fits into Smi.
3899 __ movq(temp, result); 3894 __ movq(temp, result);
3900 __ shlq(temp, Immediate(1)); 3895 __ shlq(temp, Immediate(1));
3901 __ j(OVERFLOW, &do_call, Assembler::kNearJump); 3896 __ j(OVERFLOW, &do_call, Assembler::kNearJump);
3902 __ SmiTag(result); 3897 __ SmiTag(result);
3903 Emit54BitOverflowCheck(compiler, &do_call, result); 3898 EmitJavascriptOverflowCheck(compiler, &do_call, result);
3904 __ jmp(&done); 3899 __ jmp(&done);
3905 __ Bind(&do_call); 3900 __ Bind(&do_call);
3906 ASSERT(instance_call()->HasICData()); 3901 ASSERT(instance_call()->HasICData());
3907 const ICData& ic_data = *instance_call()->ic_data(); 3902 const ICData& ic_data = *instance_call()->ic_data();
3908 ASSERT((ic_data.NumberOfChecks() == 1)); 3903 ASSERT((ic_data.NumberOfChecks() == 1));
3909 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0)); 3904 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0));
3910 3905
3911 const intptr_t kNumberOfArguments = 1; 3906 const intptr_t kNumberOfArguments = 1;
3912 __ pushq(value_obj); 3907 __ pushq(value_obj);
3913 compiler->GenerateStaticCall(deopt_id(), 3908 compiler->GenerateStaticCall(deopt_id(),
(...skipping 25 matching lines...) Expand all
3939 Register temp = locs()->temp(0).reg(); 3934 Register temp = locs()->temp(0).reg();
3940 3935
3941 __ cvttsd2siq(result, value); 3936 __ cvttsd2siq(result, value);
3942 // Overflow is signalled with minint. 3937 // Overflow is signalled with minint.
3943 Label do_call, done; 3938 Label do_call, done;
3944 // Check for overflow and that it fits into Smi. 3939 // Check for overflow and that it fits into Smi.
3945 __ movq(temp, result); 3940 __ movq(temp, result);
3946 __ shlq(temp, Immediate(1)); 3941 __ shlq(temp, Immediate(1));
3947 __ j(OVERFLOW, deopt); 3942 __ j(OVERFLOW, deopt);
3948 __ SmiTag(result); 3943 __ SmiTag(result);
3949 Emit54BitOverflowCheck(compiler, deopt, result); 3944 EmitJavascriptOverflowCheck(compiler, deopt, result);
3950 } 3945 }
3951 3946
3952 3947
3953 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary() const { 3948 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary() const {
3954 const intptr_t kNumInputs = 1; 3949 const intptr_t kNumInputs = 1;
3955 const intptr_t kNumTemps = 0; 3950 const intptr_t kNumTemps = 0;
3956 LocationSummary* result = 3951 LocationSummary* result =
3957 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 3952 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
3958 result->set_in(0, Location::RequiresFpuRegister()); 3953 result->set_in(0, Location::RequiresFpuRegister());
3959 result->set_out(Location::RequiresFpuRegister()); 3954 result->set_out(Location::RequiresFpuRegister());
(...skipping 589 matching lines...) Expand 10 before | Expand all | Expand 10 after
4549 PcDescriptors::kOther, 4544 PcDescriptors::kOther,
4550 locs()); 4545 locs());
4551 __ Drop(2); // Discard type arguments and receiver. 4546 __ Drop(2); // Discard type arguments and receiver.
4552 } 4547 }
4553 4548
4554 } // namespace dart 4549 } // namespace dart
4555 4550
4556 #undef __ 4551 #undef __
4557 4552
4558 #endif // defined TARGET_ARCH_X64 4553 #endif // defined TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « runtime/lib/integers.dart ('k') | runtime/vm/object.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698