| 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 2408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2419 break; | 2419 break; |
| 2420 } | 2420 } |
| 2421 default: | 2421 default: |
| 2422 UNREACHABLE(); | 2422 UNREACHABLE(); |
| 2423 } | 2423 } |
| 2424 return; | 2424 return; |
| 2425 } // if locs()->in(1).IsStackSlot. | 2425 } // if locs()->in(1).IsStackSlot. |
| 2426 | 2426 |
| 2427 // if locs()->in(1).IsRegister. | 2427 // if locs()->in(1).IsRegister. |
| 2428 Register right = locs()->in(1).reg(); | 2428 Register right = locs()->in(1).reg(); |
| 2429 Range* right_range = this->right()->definition()->range(); |
| 2429 switch (op_kind()) { | 2430 switch (op_kind()) { |
| 2430 case Token::kADD: { | 2431 case Token::kADD: { |
| 2431 __ addl(left, right); | 2432 __ addl(left, right); |
| 2432 if (deopt != NULL) __ j(OVERFLOW, deopt); | 2433 if (deopt != NULL) __ j(OVERFLOW, deopt); |
| 2433 break; | 2434 break; |
| 2434 } | 2435 } |
| 2435 case Token::kSUB: { | 2436 case Token::kSUB: { |
| 2436 __ subl(left, right); | 2437 __ subl(left, right); |
| 2437 if (deopt != NULL) __ j(OVERFLOW, deopt); | 2438 if (deopt != NULL) __ j(OVERFLOW, deopt); |
| 2438 break; | 2439 break; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 2452 // No overflow check. | 2453 // No overflow check. |
| 2453 __ orl(left, right); | 2454 __ orl(left, right); |
| 2454 break; | 2455 break; |
| 2455 } | 2456 } |
| 2456 case Token::kBIT_XOR: { | 2457 case Token::kBIT_XOR: { |
| 2457 // No overflow check. | 2458 // No overflow check. |
| 2458 __ xorl(left, right); | 2459 __ xorl(left, right); |
| 2459 break; | 2460 break; |
| 2460 } | 2461 } |
| 2461 case Token::kTRUNCDIV: { | 2462 case Token::kTRUNCDIV: { |
| 2462 // Handle divide by zero in runtime. | 2463 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { |
| 2463 __ testl(right, right); | 2464 // Handle divide by zero in runtime. |
| 2464 __ j(ZERO, deopt); | 2465 __ testl(right, right); |
| 2466 __ j(ZERO, deopt); |
| 2467 } |
| 2465 ASSERT(left == EAX); | 2468 ASSERT(left == EAX); |
| 2466 ASSERT((right != EDX) && (right != EAX)); | 2469 ASSERT((right != EDX) && (right != EAX)); |
| 2467 ASSERT(locs()->temp(0).reg() == EDX); | 2470 ASSERT(locs()->temp(0).reg() == EDX); |
| 2468 ASSERT(result == EAX); | 2471 ASSERT(result == EAX); |
| 2469 __ SmiUntag(left); | 2472 __ SmiUntag(left); |
| 2470 __ SmiUntag(right); | 2473 __ SmiUntag(right); |
| 2471 __ cdq(); // Sign extend EAX -> EDX:EAX. | 2474 __ cdq(); // Sign extend EAX -> EDX:EAX. |
| 2472 __ idivl(right); // EAX: quotient, EDX: remainder. | 2475 __ idivl(right); // EAX: quotient, EDX: remainder. |
| 2473 // Check the corner case of dividing the 'MIN_SMI' with -1, in which | 2476 // Check the corner case of dividing the 'MIN_SMI' with -1, in which |
| 2474 // case we cannot tag the result. | 2477 // case we cannot tag the result. |
| 2475 __ cmpl(result, Immediate(0x40000000)); | 2478 __ cmpl(result, Immediate(0x40000000)); |
| 2476 __ j(EQUAL, deopt); | 2479 __ j(EQUAL, deopt); |
| 2477 __ SmiTag(result); | 2480 __ SmiTag(result); |
| 2478 break; | 2481 break; |
| 2479 } | 2482 } |
| 2480 case Token::kMOD: { | 2483 case Token::kMOD: { |
| 2481 // Handle divide by zero in runtime. | 2484 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { |
| 2482 __ testl(right, right); | 2485 // Handle divide by zero in runtime. |
| 2483 __ j(ZERO, deopt); | 2486 __ testl(right, right); |
| 2487 __ j(ZERO, deopt); |
| 2488 } |
| 2484 ASSERT(left == EDX); | 2489 ASSERT(left == EDX); |
| 2485 ASSERT((right != EDX) && (right != EAX)); | 2490 ASSERT((right != EDX) && (right != EAX)); |
| 2486 ASSERT(locs()->temp(0).reg() == EAX); | 2491 ASSERT(locs()->temp(0).reg() == EAX); |
| 2487 ASSERT(result == EDX); | 2492 ASSERT(result == EDX); |
| 2488 __ SmiUntag(left); | 2493 __ SmiUntag(left); |
| 2489 __ SmiUntag(right); | 2494 __ SmiUntag(right); |
| 2490 __ movl(EAX, EDX); | 2495 __ movl(EAX, EDX); |
| 2491 __ cdq(); // Sign extend EAX -> EDX:EAX. | 2496 __ cdq(); // Sign extend EAX -> EDX:EAX. |
| 2492 __ idivl(right); // EAX: quotient, EDX: remainder. | 2497 __ idivl(right); // EAX: quotient, EDX: remainder. |
| 2493 // res = left % right; | 2498 // res = left % right; |
| 2494 // if (res < 0) { | 2499 // if (res < 0) { |
| 2495 // if (right < 0) { | 2500 // if (right < 0) { |
| 2496 // res = res - right; | 2501 // res = res - right; |
| 2497 // } else { | 2502 // } else { |
| 2498 // res = res + right; | 2503 // res = res + right; |
| 2499 // } | 2504 // } |
| 2500 // } | 2505 // } |
| 2501 Label subtract, done; | 2506 Label done; |
| 2502 __ cmpl(result, Immediate(0)); | 2507 __ cmpl(result, Immediate(0)); |
| 2503 __ j(GREATER_EQUAL, &done, Assembler::kNearJump); | 2508 __ j(GREATER_EQUAL, &done, Assembler::kNearJump); |
| 2504 // Result is negative, adjust it. | 2509 // Result is negative, adjust it. |
| 2505 __ cmpl(right, Immediate(0)); | 2510 if ((right_range == NULL) || right_range->Overlaps(-1, 1)) { |
| 2506 __ j(LESS, &subtract, Assembler::kNearJump); | 2511 // Right can be positive and negative. |
| 2507 __ addl(result, right); | 2512 Label subtract; |
| 2508 __ jmp(&done, Assembler::kNearJump); | 2513 __ cmpl(right, Immediate(0)); |
| 2509 __ Bind(&subtract); | 2514 __ j(LESS, &subtract, Assembler::kNearJump); |
| 2510 __ subl(result, right); | 2515 __ addl(result, right); |
| 2516 __ jmp(&done, Assembler::kNearJump); |
| 2517 __ Bind(&subtract); |
| 2518 __ subl(result, right); |
| 2519 } else if (right_range->IsWithin(0, RangeBoundary::kPlusInfinity)) { |
| 2520 // Right is positive. |
| 2521 __ addl(result, right); |
| 2522 } else { |
| 2523 // Right is negative. |
| 2524 __ subl(result, right); |
| 2525 } |
| 2511 __ Bind(&done); | 2526 __ Bind(&done); |
| 2512 __ SmiTag(result); | 2527 __ SmiTag(result); |
| 2513 break; | 2528 break; |
| 2514 } | 2529 } |
| 2515 case Token::kSHR: { | 2530 case Token::kSHR: { |
| 2516 if (CanDeoptimize()) { | 2531 if (CanDeoptimize()) { |
| 2517 __ cmpl(right, Immediate(0)); | 2532 __ cmpl(right, Immediate(0)); |
| 2518 __ j(LESS, deopt); | 2533 __ j(LESS, deopt); |
| 2519 } | 2534 } |
| 2520 __ SmiUntag(right); | 2535 __ SmiUntag(right); |
| 2521 // sarl operation masks the count to 5 bits. | 2536 // sarl operation masks the count to 5 bits. |
| 2522 const intptr_t kCountLimit = 0x1F; | 2537 const intptr_t kCountLimit = 0x1F; |
| 2523 Range* right_range = this->right()->definition()->range(); | |
| 2524 if ((right_range == NULL) || | 2538 if ((right_range == NULL) || |
| 2525 !right_range->IsWithin(RangeBoundary::kMinusInfinity, kCountLimit)) { | 2539 !right_range->IsWithin(RangeBoundary::kMinusInfinity, kCountLimit)) { |
| 2526 __ cmpl(right, Immediate(kCountLimit)); | 2540 __ cmpl(right, Immediate(kCountLimit)); |
| 2527 Label count_ok; | 2541 Label count_ok; |
| 2528 __ j(LESS, &count_ok, Assembler::kNearJump); | 2542 __ j(LESS, &count_ok, Assembler::kNearJump); |
| 2529 __ movl(right, Immediate(kCountLimit)); | 2543 __ movl(right, Immediate(kCountLimit)); |
| 2530 __ Bind(&count_ok); | 2544 __ Bind(&count_ok); |
| 2531 } | 2545 } |
| 2532 ASSERT(right == ECX); // Count must be in ECX | 2546 ASSERT(right == ECX); // Count must be in ECX |
| 2533 __ SmiUntag(left); | 2547 __ SmiUntag(left); |
| (...skipping 1472 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4006 void MergedMathInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4020 void MergedMathInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4007 Label* deopt = NULL; | 4021 Label* deopt = NULL; |
| 4008 if (CanDeoptimize()) { | 4022 if (CanDeoptimize()) { |
| 4009 deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp); | 4023 deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp); |
| 4010 } | 4024 } |
| 4011 | 4025 |
| 4012 if (kind() == MergedMathInstr::kTruncDivMod) { | 4026 if (kind() == MergedMathInstr::kTruncDivMod) { |
| 4013 Register left = locs()->in(0).reg(); | 4027 Register left = locs()->in(0).reg(); |
| 4014 Register right = locs()->in(1).reg(); | 4028 Register right = locs()->in(1).reg(); |
| 4015 Register result = locs()->out().reg(); | 4029 Register result = locs()->out().reg(); |
| 4016 // Handle divide by zero in runtime. | 4030 Range* right_range = InputAt(1)->definition()->range(); |
| 4017 __ testl(right, right); | 4031 if ((right_range == NULL) || right_range->Overlaps(0, 0)) { |
| 4018 __ j(ZERO, deopt); | 4032 // Handle divide by zero in runtime. |
| 4033 __ testl(right, right); |
| 4034 __ j(ZERO, deopt); |
| 4035 } |
| 4019 ASSERT(left == EAX); | 4036 ASSERT(left == EAX); |
| 4020 ASSERT((right != EDX) && (right != EAX)); | 4037 ASSERT((right != EDX) && (right != EAX)); |
| 4021 ASSERT(locs()->temp(0).reg() == EDX); | 4038 ASSERT(locs()->temp(0).reg() == EDX); |
| 4022 ASSERT((result != EDX) && (result != EAX)); | 4039 ASSERT((result != EDX) && (result != EAX)); |
| 4023 __ SmiUntag(left); | 4040 __ SmiUntag(left); |
| 4024 __ SmiUntag(right); | 4041 __ SmiUntag(right); |
| 4025 __ cdq(); // Sign extend EAX -> EDX:EAX. | 4042 __ cdq(); // Sign extend EAX -> EDX:EAX. |
| 4026 __ idivl(right); // EAX: quotient, EDX: remainder. | 4043 __ idivl(right); // EAX: quotient, EDX: remainder. |
| 4027 // Check the corner case of dividing the 'MIN_SMI' with -1, in which | 4044 // Check the corner case of dividing the 'MIN_SMI' with -1, in which |
| 4028 // case we cannot tag the result. | 4045 // case we cannot tag the result. |
| 4029 // TODO(srdjan): We could store instead untagged intermediate results in a | 4046 // TODO(srdjan): We could store instead untagged intermediate results in a |
| 4030 // typed array, but then the load indexed instructions would need to be | 4047 // typed array, but then the load indexed instructions would need to be |
| 4031 // able to deoptimize. | 4048 // able to deoptimize. |
| 4032 __ cmpl(EAX, Immediate(0x40000000)); | 4049 __ cmpl(EAX, Immediate(0x40000000)); |
| 4033 __ j(EQUAL, deopt); | 4050 __ j(EQUAL, deopt); |
| 4034 // Modulo result (EDX) correction: | 4051 // Modulo result (EDX) correction: |
| 4035 // res = left % right; | 4052 // res = left % right; |
| 4036 // if (res < 0) { | 4053 // if (res < 0) { |
| 4037 // if (right < 0) { | 4054 // if (right < 0) { |
| 4038 // res = res - right; | 4055 // res = res - right; |
| 4039 // } else { | 4056 // } else { |
| 4040 // res = res + right; | 4057 // res = res + right; |
| 4041 // } | 4058 // } |
| 4042 // } | 4059 // } |
| 4043 Label subtract, done; | 4060 Label done; |
| 4044 __ cmpl(EDX, Immediate(0)); | 4061 __ cmpl(EDX, Immediate(0)); |
| 4045 __ j(GREATER_EQUAL, &done, Assembler::kNearJump); | 4062 __ j(GREATER_EQUAL, &done, Assembler::kNearJump); |
| 4046 // Result is negative, adjust it. | 4063 // Result is negative, adjust it. |
| 4047 __ cmpl(right, Immediate(0)); | 4064 if ((right_range == NULL) || right_range->Overlaps(-1, 1)) { |
| 4048 __ j(LESS, &subtract, Assembler::kNearJump); | 4065 Label subtract; |
| 4049 __ addl(EDX, right); | 4066 __ cmpl(right, Immediate(0)); |
| 4050 __ jmp(&done, Assembler::kNearJump); | 4067 __ j(LESS, &subtract, Assembler::kNearJump); |
| 4051 __ Bind(&subtract); | 4068 __ addl(EDX, right); |
| 4052 __ subl(EDX, right); | 4069 __ jmp(&done, Assembler::kNearJump); |
| 4070 __ Bind(&subtract); |
| 4071 __ subl(EDX, right); |
| 4072 } else if (right_range->IsWithin(0, RangeBoundary::kPlusInfinity)) { |
| 4073 // Right is positive. |
| 4074 __ addl(EDX, right); |
| 4075 } else { |
| 4076 // Right is negative. |
| 4077 __ subl(EDX, right); |
| 4078 } |
| 4053 __ Bind(&done); | 4079 __ Bind(&done); |
| 4054 | 4080 |
| 4055 __ LoadObject(result, Array::ZoneHandle(Array::New(2, Heap::kOld))); | 4081 __ LoadObject(result, Array::ZoneHandle(Array::New(2, Heap::kOld))); |
| 4056 const intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(kArrayCid); | 4082 const intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(kArrayCid); |
| 4057 Address trunc_div_address( | 4083 Address trunc_div_address( |
| 4058 FlowGraphCompiler::ElementAddressForIntIndex(kArrayCid, | 4084 FlowGraphCompiler::ElementAddressForIntIndex(kArrayCid, |
| 4059 index_scale, | 4085 index_scale, |
| 4060 result, | 4086 result, |
| 4061 0)); | 4087 0)); |
| 4062 Address mod_address( | 4088 Address mod_address( |
| (...skipping 879 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4942 PcDescriptors::kOther, | 4968 PcDescriptors::kOther, |
| 4943 locs()); | 4969 locs()); |
| 4944 __ Drop(2); // Discard type arguments and receiver. | 4970 __ Drop(2); // Discard type arguments and receiver. |
| 4945 } | 4971 } |
| 4946 | 4972 |
| 4947 } // namespace dart | 4973 } // namespace dart |
| 4948 | 4974 |
| 4949 #undef __ | 4975 #undef __ |
| 4950 | 4976 |
| 4951 #endif // defined TARGET_ARCH_IA32 | 4977 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |