Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 2188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2199 summary->set_out(Location::SameAsFirstInput()); | 2199 summary->set_out(Location::SameAsFirstInput()); |
| 2200 } else { | 2200 } else { |
| 2201 // Both inputs must be writable because they will be untagged. | 2201 // Both inputs must be writable because they will be untagged. |
| 2202 summary->set_in(0, Location::RegisterLocation(EAX)); | 2202 summary->set_in(0, Location::RegisterLocation(EAX)); |
| 2203 summary->set_in(1, Location::WritableRegister()); | 2203 summary->set_in(1, Location::WritableRegister()); |
| 2204 summary->set_out(Location::SameAsFirstInput()); | 2204 summary->set_out(Location::SameAsFirstInput()); |
| 2205 // Will be used for sign extension and division. | 2205 // Will be used for sign extension and division. |
| 2206 summary->set_temp(0, Location::RegisterLocation(EDX)); | 2206 summary->set_temp(0, Location::RegisterLocation(EDX)); |
| 2207 } | 2207 } |
| 2208 return summary; | 2208 return summary; |
| 2209 } else if (op_kind() == Token::kMOD) { | |
| 2210 const intptr_t kNumTemps = 1; | |
| 2211 LocationSummary* summary = | |
| 2212 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | |
| 2213 // Both inputs must be writable because they will be untagged. | |
| 2214 summary->set_in(0, Location::RegisterLocation(EDX)); | |
| 2215 summary->set_in(1, Location::WritableRegister()); | |
| 2216 summary->set_out(Location::SameAsFirstInput()); | |
| 2217 // Will be used for sign extension and division. | |
| 2218 summary->set_temp(0, Location::RegisterLocation(EAX)); | |
| 2219 return summary; | |
| 2209 } else if (op_kind() == Token::kSHR) { | 2220 } else if (op_kind() == Token::kSHR) { |
| 2210 const intptr_t kNumTemps = 0; | 2221 const intptr_t kNumTemps = 0; |
| 2211 LocationSummary* summary = | 2222 LocationSummary* summary = |
| 2212 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2223 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2213 summary->set_in(0, Location::RequiresRegister()); | 2224 summary->set_in(0, Location::RequiresRegister()); |
| 2214 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX)); | 2225 summary->set_in(1, Location::FixedRegisterOrSmiConstant(right(), ECX)); |
| 2215 summary->set_out(Location::SameAsFirstInput()); | 2226 summary->set_out(Location::SameAsFirstInput()); |
| 2216 return summary; | 2227 return summary; |
| 2217 } else if (op_kind() == Token::kSHL) { | 2228 } else if (op_kind() == Token::kSHL) { |
| 2218 const intptr_t kNumTemps = 0; | 2229 const intptr_t kNumTemps = 0; |
| (...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2444 __ SmiUntag(right); | 2455 __ SmiUntag(right); |
| 2445 __ cdq(); // Sign extend EAX -> EDX:EAX. | 2456 __ cdq(); // Sign extend EAX -> EDX:EAX. |
| 2446 __ idivl(right); // EAX: quotient, EDX: remainder. | 2457 __ idivl(right); // EAX: quotient, EDX: remainder. |
| 2447 // Check the corner case of dividing the 'MIN_SMI' with -1, in which | 2458 // Check the corner case of dividing the 'MIN_SMI' with -1, in which |
| 2448 // case we cannot tag the result. | 2459 // case we cannot tag the result. |
| 2449 __ cmpl(result, Immediate(0x40000000)); | 2460 __ cmpl(result, Immediate(0x40000000)); |
| 2450 __ j(EQUAL, deopt); | 2461 __ j(EQUAL, deopt); |
| 2451 __ SmiTag(result); | 2462 __ SmiTag(result); |
| 2452 break; | 2463 break; |
| 2453 } | 2464 } |
| 2465 case Token::kMOD: { | |
| 2466 // Handle divide by zero in runtime. | |
| 2467 __ testl(right, right); | |
| 2468 __ j(ZERO, deopt); | |
|
sra1
2013/11/07 00:50:23
This should be unnecessary in cases where right ==
srdjan
2013/11/07 05:26:52
Yes. I had the code in and have removed it in orde
sra1
2013/11/08 01:40:16
I see. The latency of idiv covers everything else
srdjan
2013/11/08 16:02:53
Yes, preliminary measurement show a big benefit of
| |
| 2469 ASSERT(left == EDX); | |
| 2470 ASSERT((right != EDX) && (right != EAX)); | |
| 2471 ASSERT(locs()->temp(0).reg() == EAX); | |
| 2472 ASSERT(result == EDX); | |
| 2473 __ SmiUntag(left); | |
| 2474 __ SmiUntag(right); | |
| 2475 __ movl(EAX, EDX); | |
| 2476 __ cdq(); // Sign extend EAX -> EDX:EAX. | |
| 2477 __ idivl(right); // EAX: quotient, EDX: remainder. | |
| 2478 // res = left % right; | |
| 2479 // if (res < 0) { | |
| 2480 // if (right < 0) { | |
| 2481 // res = res - right; | |
| 2482 // } else { | |
| 2483 // res = res + right; | |
| 2484 // } | |
| 2485 // } | |
| 2486 Label subtract, done; | |
| 2487 __ cmpl(result, Immediate(0)); | |
| 2488 __ j(GREATER_EQUAL, &done, Assembler::kNearJump); | |
|
sra1
2013/11/07 00:50:23
You might be able to test whether this is necessar
srdjan
2013/11/07 05:26:52
Ditto. I have not used the val range, but the rang
| |
| 2489 // Result is negative, adjust it. | |
| 2490 __ cmpl(right, Immediate(0)); | |
| 2491 __ j(LESS, &subtract, Assembler::kNearJump); | |
| 2492 __ addl(result, right); | |
| 2493 __ jmp(&done, Assembler::kNearJump); | |
| 2494 __ Bind(&subtract); | |
| 2495 __ subl(result, right); | |
| 2496 __ Bind(&done); | |
| 2497 __ SmiTag(result); | |
| 2498 break; | |
| 2499 } | |
| 2454 case Token::kSHR: { | 2500 case Token::kSHR: { |
| 2455 if (CanDeoptimize()) { | 2501 if (CanDeoptimize()) { |
| 2456 __ cmpl(right, Immediate(0)); | 2502 __ cmpl(right, Immediate(0)); |
| 2457 __ j(LESS, deopt); | 2503 __ j(LESS, deopt); |
| 2458 } | 2504 } |
| 2459 __ SmiUntag(right); | 2505 __ SmiUntag(right); |
| 2460 // sarl operation masks the count to 5 bits. | 2506 // sarl operation masks the count to 5 bits. |
| 2461 const intptr_t kCountLimit = 0x1F; | 2507 const intptr_t kCountLimit = 0x1F; |
| 2462 Range* right_range = this->right()->definition()->range(); | 2508 Range* right_range = this->right()->definition()->range(); |
| 2463 if ((right_range == NULL) || | 2509 if ((right_range == NULL) || |
| 2464 !right_range->IsWithin(RangeBoundary::kMinusInfinity, kCountLimit)) { | 2510 !right_range->IsWithin(RangeBoundary::kMinusInfinity, kCountLimit)) { |
| 2465 __ cmpl(right, Immediate(kCountLimit)); | 2511 __ cmpl(right, Immediate(kCountLimit)); |
| 2466 Label count_ok; | 2512 Label count_ok; |
| 2467 __ j(LESS, &count_ok, Assembler::kNearJump); | 2513 __ j(LESS, &count_ok, Assembler::kNearJump); |
| 2468 __ movl(right, Immediate(kCountLimit)); | 2514 __ movl(right, Immediate(kCountLimit)); |
| 2469 __ Bind(&count_ok); | 2515 __ Bind(&count_ok); |
| 2470 } | 2516 } |
| 2471 ASSERT(right == ECX); // Count must be in ECX | 2517 ASSERT(right == ECX); // Count must be in ECX |
| 2472 __ SmiUntag(left); | 2518 __ SmiUntag(left); |
| 2473 __ sarl(left, right); | 2519 __ sarl(left, right); |
| 2474 __ SmiTag(left); | 2520 __ SmiTag(left); |
| 2475 break; | 2521 break; |
| 2476 } | 2522 } |
| 2477 case Token::kDIV: { | 2523 case Token::kDIV: { |
| 2478 // Dispatches to 'Double./'. | 2524 // Dispatches to 'Double./'. |
| 2479 // TODO(srdjan): Implement as conversion to double and double division. | 2525 // TODO(srdjan): Implement as conversion to double and double division. |
| 2480 UNREACHABLE(); | 2526 UNREACHABLE(); |
| 2481 break; | 2527 break; |
| 2482 } | 2528 } |
| 2483 case Token::kMOD: { | |
| 2484 // TODO(srdjan): Implement. | |
| 2485 UNREACHABLE(); | |
| 2486 break; | |
| 2487 } | |
| 2488 case Token::kOR: | 2529 case Token::kOR: |
| 2489 case Token::kAND: { | 2530 case Token::kAND: { |
| 2490 // Flow graph builder has dissected this operation to guarantee correct | 2531 // Flow graph builder has dissected this operation to guarantee correct |
| 2491 // behavior (short-circuit evaluation). | 2532 // behavior (short-circuit evaluation). |
| 2492 UNREACHABLE(); | 2533 UNREACHABLE(); |
| 2493 break; | 2534 break; |
| 2494 } | 2535 } |
| 2495 default: | 2536 default: |
| 2496 UNREACHABLE(); | 2537 UNREACHABLE(); |
| 2497 break; | 2538 break; |
| (...skipping 2423 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4921 PcDescriptors::kOther, | 4962 PcDescriptors::kOther, |
| 4922 locs()); | 4963 locs()); |
| 4923 __ Drop(2); // Discard type arguments and receiver. | 4964 __ Drop(2); // Discard type arguments and receiver. |
| 4924 } | 4965 } |
| 4925 | 4966 |
| 4926 } // namespace dart | 4967 } // namespace dart |
| 4927 | 4968 |
| 4928 #undef __ | 4969 #undef __ |
| 4929 | 4970 |
| 4930 #endif // defined TARGET_ARCH_IA32 | 4971 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |