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

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

Issue 21885003: Enables unboxed mints in ia32 javascript int compatability mode. (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/vm/intermediate_language_ia32.cc ('k') | no next file » | 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 2134 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 EmitJavascriptOverflowCheck(FlowGraphCompiler* compiler, 2154 static void EmitJavascriptOverflowCheck(FlowGraphCompiler* compiler,
2155 Range* range,
2155 Label* overflow, 2156 Label* overflow,
2156 Register result) { 2157 Register result) {
2157 if (FLAG_throw_on_javascript_int_overflow) { 2158 if (!range->IsWithin(-0x20000000000000LL, 0x20000000000000LL)) {
2158 ASSERT(overflow != NULL); 2159 ASSERT(overflow != NULL);
2159 __ cmpq(result, Immediate(-0x20000000000000)); 2160 __ cmpq(result, Immediate(-0x20000000000000LL));
2160 __ j(LESS, overflow); 2161 __ j(LESS, overflow);
2161 __ cmpq(result, Immediate(0x20000000000000)); 2162 __ cmpq(result, Immediate(0x20000000000000LL));
2162 __ j(GREATER, overflow); 2163 __ j(GREATER, overflow);
2163 } 2164 }
2164 } 2165 }
2165 2166
2166 2167
2167 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler, 2168 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler,
2168 BinarySmiOpInstr* shift_left) { 2169 BinarySmiOpInstr* shift_left) {
2169 const bool is_truncating = shift_left->is_truncating(); 2170 const bool is_truncating = shift_left->is_truncating();
2170 const LocationSummary& locs = *shift_left->locs(); 2171 const LocationSummary& locs = *shift_left->locs();
2171 Register left = locs.in(0).reg(); 2172 Register left = locs.in(0).reg();
(...skipping 24 matching lines...) Expand all
2196 Register temp = locs.temp(0).reg(); 2197 Register temp = locs.temp(0).reg();
2197 __ movq(temp, left); 2198 __ movq(temp, left);
2198 __ shlq(left, Immediate(value)); 2199 __ shlq(left, Immediate(value));
2199 __ sarq(left, Immediate(value)); 2200 __ sarq(left, Immediate(value));
2200 __ cmpq(left, temp); 2201 __ cmpq(left, temp);
2201 __ j(NOT_EQUAL, deopt); // Overflow. 2202 __ j(NOT_EQUAL, deopt); // Overflow.
2202 } 2203 }
2203 // Shift for result now we know there is no overflow. 2204 // Shift for result now we know there is no overflow.
2204 __ shlq(left, Immediate(value)); 2205 __ shlq(left, Immediate(value));
2205 } 2206 }
2206 EmitJavascriptOverflowCheck(compiler, deopt, result); 2207 if (FLAG_throw_on_javascript_int_overflow) {
2208 EmitJavascriptOverflowCheck(compiler, shift_left->range(), deopt, result);
2209 }
2207 return; 2210 return;
2208 } 2211 }
2209 2212
2210 // Right (locs.in(1)) is not constant. 2213 // Right (locs.in(1)) is not constant.
2211 Register right = locs.in(1).reg(); 2214 Register right = locs.in(1).reg();
2212 Range* right_range = shift_left->right()->definition()->range(); 2215 Range* right_range = shift_left->right()->definition()->range();
2213 if (shift_left->left()->BindsToConstant() && !is_truncating) { 2216 if (shift_left->left()->BindsToConstant() && !is_truncating) {
2214 // TODO(srdjan): Implement code below for is_truncating(). 2217 // TODO(srdjan): Implement code below for is_truncating().
2215 // If left is constant, we know the maximal allowed size for right. 2218 // If left is constant, we know the maximal allowed size for right.
2216 const Object& obj = shift_left->left()->BoundConstant(); 2219 const Object& obj = shift_left->left()->BoundConstant();
2217 if (obj.IsSmi()) { 2220 if (obj.IsSmi()) {
2218 const intptr_t left_int = Smi::Cast(obj).Value(); 2221 const intptr_t left_int = Smi::Cast(obj).Value();
2219 if (left_int == 0) { 2222 if (left_int == 0) {
2220 __ cmpq(right, Immediate(0)); 2223 __ cmpq(right, Immediate(0));
2221 __ j(NEGATIVE, deopt); 2224 __ j(NEGATIVE, deopt);
2222 return; 2225 return;
2223 } 2226 }
2224 const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int); 2227 const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int);
2225 const bool right_needs_check = 2228 const bool right_needs_check =
2226 (right_range == NULL) || 2229 (right_range == NULL) ||
2227 !right_range->IsWithin(0, max_right - 1); 2230 !right_range->IsWithin(0, max_right - 1);
2228 if (right_needs_check) { 2231 if (right_needs_check) {
2229 __ cmpq(right, 2232 __ cmpq(right,
2230 Immediate(reinterpret_cast<int64_t>(Smi::New(max_right)))); 2233 Immediate(reinterpret_cast<int64_t>(Smi::New(max_right))));
2231 __ j(ABOVE_EQUAL, deopt); 2234 __ j(ABOVE_EQUAL, deopt);
2232 } 2235 }
2233 __ SmiUntag(right); 2236 __ SmiUntag(right);
2234 __ shlq(left, right); 2237 __ shlq(left, right);
2235 } 2238 }
2236 EmitJavascriptOverflowCheck(compiler, deopt, result); 2239 if (FLAG_throw_on_javascript_int_overflow) {
2240 EmitJavascriptOverflowCheck(compiler, shift_left->range(), deopt, result);
2241 }
2237 return; 2242 return;
2238 } 2243 }
2239 2244
2240 const bool right_needs_check = 2245 const bool right_needs_check =
2241 (right_range == NULL) || !right_range->IsWithin(0, (Smi::kBits - 1)); 2246 (right_range == NULL) || !right_range->IsWithin(0, (Smi::kBits - 1));
2242 ASSERT(right == RCX); // Count must be in RCX 2247 ASSERT(right == RCX); // Count must be in RCX
2243 if (is_truncating) { 2248 if (is_truncating) {
2244 if (right_needs_check) { 2249 if (right_needs_check) {
2245 const bool right_may_be_negative = 2250 const bool right_may_be_negative =
2246 (right_range == NULL) || 2251 (right_range == NULL) ||
(...skipping 30 matching lines...) Expand all
2277 __ movq(temp, left); 2282 __ movq(temp, left);
2278 __ SmiUntag(right); 2283 __ SmiUntag(right);
2279 // Overflow test (preserve temp and right); 2284 // Overflow test (preserve temp and right);
2280 __ shlq(left, right); 2285 __ shlq(left, right);
2281 __ sarq(left, right); 2286 __ sarq(left, right);
2282 __ cmpq(left, temp); 2287 __ cmpq(left, temp);
2283 __ j(NOT_EQUAL, deopt); // Overflow. 2288 __ j(NOT_EQUAL, deopt); // Overflow.
2284 // Shift for result now we know there is no overflow. 2289 // Shift for result now we know there is no overflow.
2285 __ shlq(left, right); 2290 __ shlq(left, right);
2286 } 2291 }
2287 EmitJavascriptOverflowCheck(compiler, deopt, result); 2292 if (FLAG_throw_on_javascript_int_overflow) {
2293 EmitJavascriptOverflowCheck(compiler, shift_left->range(), deopt, result);
2294 }
2288 } 2295 }
2289 2296
2290 2297
2291 static bool CanBeImmediate(const Object& constant) { 2298 static bool CanBeImmediate(const Object& constant) {
2292 return constant.IsSmi() && 2299 return constant.IsSmi() &&
2293 Immediate(reinterpret_cast<int64_t>(constant.raw())).is_int32(); 2300 Immediate(reinterpret_cast<int64_t>(constant.raw())).is_int32();
2294 } 2301 }
2295 2302
2296 2303
2297 LocationSummary* BinarySmiOpInstr::MakeLocationSummary() const { 2304 LocationSummary* BinarySmiOpInstr::MakeLocationSummary() const {
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
2476 2483
2477 __ sarq(left, Immediate(value)); 2484 __ sarq(left, Immediate(value));
2478 __ SmiTag(left); 2485 __ SmiTag(left);
2479 break; 2486 break;
2480 } 2487 }
2481 2488
2482 default: 2489 default:
2483 UNREACHABLE(); 2490 UNREACHABLE();
2484 break; 2491 break;
2485 } 2492 }
2486 EmitJavascriptOverflowCheck(compiler, deopt, result); 2493 if (FLAG_throw_on_javascript_int_overflow) {
2494 EmitJavascriptOverflowCheck(compiler, range(), deopt, result);
2495 }
2487 return; 2496 return;
2488 } // locs()->in(1).IsConstant(). 2497 } // locs()->in(1).IsConstant().
2489 2498
2490 2499
2491 if (locs()->in(1).IsStackSlot()) { 2500 if (locs()->in(1).IsStackSlot()) {
2492 const Address& right = locs()->in(1).ToStackSlotAddress(); 2501 const Address& right = locs()->in(1).ToStackSlotAddress();
2493 switch (op_kind()) { 2502 switch (op_kind()) {
2494 case Token::kADD: { 2503 case Token::kADD: {
2495 __ addq(left, right); 2504 __ addq(left, right);
2496 if (deopt != NULL) __ j(OVERFLOW, deopt); 2505 if (deopt != NULL) __ j(OVERFLOW, deopt);
(...skipping 22 matching lines...) Expand all
2519 } 2528 }
2520 case Token::kBIT_XOR: { 2529 case Token::kBIT_XOR: {
2521 // No overflow check. 2530 // No overflow check.
2522 __ xorq(left, right); 2531 __ xorq(left, right);
2523 break; 2532 break;
2524 } 2533 }
2525 default: 2534 default:
2526 UNREACHABLE(); 2535 UNREACHABLE();
2527 break; 2536 break;
2528 } 2537 }
2529 EmitJavascriptOverflowCheck(compiler, deopt, result); 2538 if (FLAG_throw_on_javascript_int_overflow) {
2539 EmitJavascriptOverflowCheck(compiler, range(), deopt, result);
2540 }
2530 return; 2541 return;
2531 } // locs()->in(1).IsStackSlot(). 2542 } // locs()->in(1).IsStackSlot().
2532 2543
2533 // if locs()->in(1).IsRegister. 2544 // if locs()->in(1).IsRegister.
2534 Register right = locs()->in(1).reg(); 2545 Register right = locs()->in(1).reg();
2535 switch (op_kind()) { 2546 switch (op_kind()) {
2536 case Token::kADD: { 2547 case Token::kADD: {
2537 __ addq(left, right); 2548 __ addq(left, right);
2538 if (deopt != NULL) __ j(OVERFLOW, deopt); 2549 if (deopt != NULL) __ j(OVERFLOW, deopt);
2539 break; 2550 break;
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
2649 case Token::kAND: { 2660 case Token::kAND: {
2650 // Flow graph builder has dissected this operation to guarantee correct 2661 // Flow graph builder has dissected this operation to guarantee correct
2651 // behavior (short-circuit evaluation). 2662 // behavior (short-circuit evaluation).
2652 UNREACHABLE(); 2663 UNREACHABLE();
2653 break; 2664 break;
2654 } 2665 }
2655 default: 2666 default:
2656 UNREACHABLE(); 2667 UNREACHABLE();
2657 break; 2668 break;
2658 } 2669 }
2659 EmitJavascriptOverflowCheck(compiler, deopt, result); 2670 if (FLAG_throw_on_javascript_int_overflow) {
2671 EmitJavascriptOverflowCheck(compiler, range(), deopt, result);
2672 }
2660 } 2673 }
2661 2674
2662 2675
2663 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary() const { 2676 LocationSummary* CheckEitherNonSmiInstr::MakeLocationSummary() const {
2664 intptr_t left_cid = left()->Type()->ToCid(); 2677 intptr_t left_cid = left()->Type()->ToCid();
2665 intptr_t right_cid = right()->Type()->ToCid(); 2678 intptr_t right_cid = right()->Type()->ToCid();
2666 ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid)); 2679 ASSERT((left_cid != kDoubleCid) && (right_cid != kDoubleCid));
2667 const intptr_t kNumInputs = 2; 2680 const intptr_t kNumInputs = 2;
2668 const bool need_temp = (left_cid != kSmiCid) && (right_cid != kSmiCid); 2681 const bool need_temp = (left_cid != kSmiCid) && (right_cid != kSmiCid);
2669 const intptr_t kNumTemps = need_temp ? 1 : 0; 2682 const intptr_t kNumTemps = need_temp ? 1 : 0;
(...skipping 1157 matching lines...) Expand 10 before | Expand all | Expand 10 after
3827 3840
3828 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3841 void UnarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3829 Register value = locs()->in(0).reg(); 3842 Register value = locs()->in(0).reg();
3830 ASSERT(value == locs()->out().reg()); 3843 ASSERT(value == locs()->out().reg());
3831 switch (op_kind()) { 3844 switch (op_kind()) {
3832 case Token::kNEGATE: { 3845 case Token::kNEGATE: {
3833 Label* deopt = compiler->AddDeoptStub(deopt_id(), 3846 Label* deopt = compiler->AddDeoptStub(deopt_id(),
3834 kDeoptUnaryOp); 3847 kDeoptUnaryOp);
3835 __ negq(value); 3848 __ negq(value);
3836 __ j(OVERFLOW, deopt); 3849 __ j(OVERFLOW, deopt);
3837 EmitJavascriptOverflowCheck(compiler, deopt, value); 3850 if (FLAG_throw_on_javascript_int_overflow) {
3851 EmitJavascriptOverflowCheck(compiler, range(), deopt, value);
3852 }
3838 break; 3853 break;
3839 } 3854 }
3840 case Token::kBIT_NOT: 3855 case Token::kBIT_NOT:
3841 __ notq(value); 3856 __ notq(value);
3842 __ andq(value, Immediate(~kSmiTagMask)); // Remove inverted smi-tag. 3857 __ andq(value, Immediate(~kSmiTagMask)); // Remove inverted smi-tag.
3843 break; 3858 break;
3844 default: 3859 default:
3845 UNREACHABLE(); 3860 UNREACHABLE();
3846 } 3861 }
3847 } 3862 }
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
3888 ASSERT(result != temp); 3903 ASSERT(result != temp);
3889 __ movsd(value_double, FieldAddress(value_obj, Double::value_offset())); 3904 __ movsd(value_double, FieldAddress(value_obj, Double::value_offset()));
3890 __ cvttsd2siq(result, value_double); 3905 __ cvttsd2siq(result, value_double);
3891 // Overflow is signalled with minint. 3906 // Overflow is signalled with minint.
3892 Label do_call, done; 3907 Label do_call, done;
3893 // Check for overflow and that it fits into Smi. 3908 // Check for overflow and that it fits into Smi.
3894 __ movq(temp, result); 3909 __ movq(temp, result);
3895 __ shlq(temp, Immediate(1)); 3910 __ shlq(temp, Immediate(1));
3896 __ j(OVERFLOW, &do_call, Assembler::kNearJump); 3911 __ j(OVERFLOW, &do_call, Assembler::kNearJump);
3897 __ SmiTag(result); 3912 __ SmiTag(result);
3898 EmitJavascriptOverflowCheck(compiler, &do_call, result); 3913 if (FLAG_throw_on_javascript_int_overflow) {
3914 EmitJavascriptOverflowCheck(compiler, range(), &do_call, result);
3915 }
3899 __ jmp(&done); 3916 __ jmp(&done);
3900 __ Bind(&do_call); 3917 __ Bind(&do_call);
3901 ASSERT(instance_call()->HasICData()); 3918 ASSERT(instance_call()->HasICData());
3902 const ICData& ic_data = *instance_call()->ic_data(); 3919 const ICData& ic_data = *instance_call()->ic_data();
3903 ASSERT((ic_data.NumberOfChecks() == 1)); 3920 ASSERT((ic_data.NumberOfChecks() == 1));
3904 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0)); 3921 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0));
3905 3922
3906 const intptr_t kNumberOfArguments = 1; 3923 const intptr_t kNumberOfArguments = 1;
3907 __ pushq(value_obj); 3924 __ pushq(value_obj);
3908 compiler->GenerateStaticCall(deopt_id(), 3925 compiler->GenerateStaticCall(deopt_id(),
(...skipping 25 matching lines...) Expand all
3934 Register temp = locs()->temp(0).reg(); 3951 Register temp = locs()->temp(0).reg();
3935 3952
3936 __ cvttsd2siq(result, value); 3953 __ cvttsd2siq(result, value);
3937 // Overflow is signalled with minint. 3954 // Overflow is signalled with minint.
3938 Label do_call, done; 3955 Label do_call, done;
3939 // Check for overflow and that it fits into Smi. 3956 // Check for overflow and that it fits into Smi.
3940 __ movq(temp, result); 3957 __ movq(temp, result);
3941 __ shlq(temp, Immediate(1)); 3958 __ shlq(temp, Immediate(1));
3942 __ j(OVERFLOW, deopt); 3959 __ j(OVERFLOW, deopt);
3943 __ SmiTag(result); 3960 __ SmiTag(result);
3944 EmitJavascriptOverflowCheck(compiler, deopt, result); 3961 if (FLAG_throw_on_javascript_int_overflow) {
3962 EmitJavascriptOverflowCheck(compiler, range(), deopt, result);
3963 }
3945 } 3964 }
3946 3965
3947 3966
3948 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary() const { 3967 LocationSummary* DoubleToDoubleInstr::MakeLocationSummary() const {
3949 const intptr_t kNumInputs = 1; 3968 const intptr_t kNumInputs = 1;
3950 const intptr_t kNumTemps = 0; 3969 const intptr_t kNumTemps = 0;
3951 LocationSummary* result = 3970 LocationSummary* result =
3952 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 3971 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
3953 result->set_in(0, Location::RequiresFpuRegister()); 3972 result->set_in(0, Location::RequiresFpuRegister());
3954 result->set_out(Location::RequiresFpuRegister()); 3973 result->set_out(Location::RequiresFpuRegister());
(...skipping 589 matching lines...) Expand 10 before | Expand all | Expand 10 after
4544 PcDescriptors::kOther, 4563 PcDescriptors::kOther,
4545 locs()); 4564 locs());
4546 __ Drop(2); // Discard type arguments and receiver. 4565 __ Drop(2); // Discard type arguments and receiver.
4547 } 4566 }
4548 4567
4549 } // namespace dart 4568 } // namespace dart
4550 4569
4551 #undef __ 4570 #undef __
4552 4571
4553 #endif // defined TARGET_ARCH_X64 4572 #endif // defined TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language_ia32.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698