| 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 2275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2286 summary->set_out(Location::SameAsFirstInput()); | 2286 summary->set_out(Location::SameAsFirstInput()); |
| 2287 } else { | 2287 } else { |
| 2288 // Both inputs must be writable because they will be untagged. | 2288 // Both inputs must be writable because they will be untagged. |
| 2289 summary->set_in(0, Location::RegisterLocation(EAX)); | 2289 summary->set_in(0, Location::RegisterLocation(EAX)); |
| 2290 summary->set_in(1, Location::WritableRegister()); | 2290 summary->set_in(1, Location::WritableRegister()); |
| 2291 summary->set_out(Location::SameAsFirstInput()); | 2291 summary->set_out(Location::SameAsFirstInput()); |
| 2292 // Will be used for sign extension and division. | 2292 // Will be used for sign extension and division. |
| 2293 summary->set_temp(0, Location::RegisterLocation(EDX)); | 2293 summary->set_temp(0, Location::RegisterLocation(EDX)); |
| 2294 } | 2294 } |
| 2295 return summary; | 2295 return summary; |
| 2296 } else if (op_kind() == Token::kTRUNCDIVMOD) { |
| 2297 const intptr_t kNumTemps = 1; |
| 2298 LocationSummary* summary = |
| 2299 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2300 // Both inputs must be writable because they will be untagged. |
| 2301 summary->set_in(0, Location::RegisterLocation(EAX)); |
| 2302 summary->set_in(1, Location::WritableRegister()); |
| 2303 summary->set_out(Location::RequiresRegister()); |
| 2304 // Will be used for sign extension and division. |
| 2305 summary->set_temp(0, Location::RegisterLocation(EDX)); |
| 2306 return summary; |
| 2296 } else if (op_kind() == Token::kMOD) { | 2307 } else if (op_kind() == Token::kMOD) { |
| 2297 const intptr_t kNumTemps = 1; | 2308 const intptr_t kNumTemps = 1; |
| 2298 LocationSummary* summary = | 2309 LocationSummary* summary = |
| 2299 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); | 2310 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 2300 // Both inputs must be writable because they will be untagged. | 2311 // Both inputs must be writable because they will be untagged. |
| 2301 summary->set_in(0, Location::RegisterLocation(EDX)); | 2312 summary->set_in(0, Location::RegisterLocation(EDX)); |
| 2302 summary->set_in(1, Location::WritableRegister()); | 2313 summary->set_in(1, Location::WritableRegister()); |
| 2303 summary->set_out(Location::SameAsFirstInput()); | 2314 summary->set_out(Location::SameAsFirstInput()); |
| 2304 // Will be used for sign extension and division. | 2315 // Will be used for sign extension and division. |
| 2305 summary->set_temp(0, Location::RegisterLocation(EAX)); | 2316 summary->set_temp(0, Location::RegisterLocation(EAX)); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2342 | 2353 |
| 2343 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2354 void BinarySmiOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2344 if (op_kind() == Token::kSHL) { | 2355 if (op_kind() == Token::kSHL) { |
| 2345 EmitSmiShiftLeft(compiler, this); | 2356 EmitSmiShiftLeft(compiler, this); |
| 2346 return; | 2357 return; |
| 2347 } | 2358 } |
| 2348 | 2359 |
| 2349 ASSERT(!is_truncating()); | 2360 ASSERT(!is_truncating()); |
| 2350 Register left = locs()->in(0).reg(); | 2361 Register left = locs()->in(0).reg(); |
| 2351 Register result = locs()->out().reg(); | 2362 Register result = locs()->out().reg(); |
| 2352 ASSERT(left == result); | 2363 // DIVMOD is different. |
| 2364 ASSERT((op_kind() == Token::kTRUNCDIVMOD) || (left == result)); |
| 2353 Label* deopt = NULL; | 2365 Label* deopt = NULL; |
| 2354 if (CanDeoptimize()) { | 2366 if (CanDeoptimize()) { |
| 2355 deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp); | 2367 deopt = compiler->AddDeoptStub(deopt_id(), kDeoptBinarySmiOp); |
| 2356 } | 2368 } |
| 2357 | 2369 |
| 2358 if (locs()->in(1).IsConstant()) { | 2370 if (locs()->in(1).IsConstant()) { |
| 2359 const Object& constant = locs()->in(1).constant(); | 2371 const Object& constant = locs()->in(1).constant(); |
| 2360 ASSERT(constant.IsSmi()); | 2372 ASSERT(constant.IsSmi()); |
| 2361 const int32_t imm = | 2373 const int32_t imm = |
| 2362 reinterpret_cast<int32_t>(constant.raw()); | 2374 reinterpret_cast<int32_t>(constant.raw()); |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2577 __ cmpl(right, Immediate(0)); | 2589 __ cmpl(right, Immediate(0)); |
| 2578 __ j(LESS, &subtract, Assembler::kNearJump); | 2590 __ j(LESS, &subtract, Assembler::kNearJump); |
| 2579 __ addl(result, right); | 2591 __ addl(result, right); |
| 2580 __ jmp(&done, Assembler::kNearJump); | 2592 __ jmp(&done, Assembler::kNearJump); |
| 2581 __ Bind(&subtract); | 2593 __ Bind(&subtract); |
| 2582 __ subl(result, right); | 2594 __ subl(result, right); |
| 2583 __ Bind(&done); | 2595 __ Bind(&done); |
| 2584 __ SmiTag(result); | 2596 __ SmiTag(result); |
| 2585 break; | 2597 break; |
| 2586 } | 2598 } |
| 2599 case Token::kTRUNCDIVMOD: { |
| 2600 // Handle divide by zero in runtime. |
| 2601 __ testl(right, right); |
| 2602 __ j(ZERO, deopt); |
| 2603 ASSERT(left == EAX); |
| 2604 ASSERT((right != EDX) && (right != EAX)); |
| 2605 ASSERT(locs()->temp(0).reg() == EDX); |
| 2606 ASSERT((result != EDX) && (result != EAX)); |
| 2607 __ SmiUntag(left); |
| 2608 __ SmiUntag(right); |
| 2609 __ cdq(); // Sign extend EAX -> EDX:EAX. |
| 2610 __ idivl(right); // EAX: quotient, EDX: remainder. |
| 2611 // Check the corner case of dividing the 'MIN_SMI' with -1, in which |
| 2612 // case we cannot tag the result. |
| 2613 // TODO(srdjan): We could store instead untagged intermediate results in a |
| 2614 // typed array, but then the load indexed instructions would need to be |
| 2615 // able to deoptimize. |
| 2616 __ cmpl(EAX, Immediate(0x40000000)); |
| 2617 __ j(EQUAL, deopt); |
| 2618 // Modulo result (EDX) correction: |
| 2619 // res = left % right; |
| 2620 // if (res < 0) { |
| 2621 // if (right < 0) { |
| 2622 // res = res - right; |
| 2623 // } else { |
| 2624 // res = res + right; |
| 2625 // } |
| 2626 // } |
| 2627 Label subtract, done; |
| 2628 __ cmpl(EDX, Immediate(0)); |
| 2629 __ j(GREATER_EQUAL, &done, Assembler::kNearJump); |
| 2630 // Result is negative, adjust it. |
| 2631 __ cmpl(right, Immediate(0)); |
| 2632 __ j(LESS, &subtract, Assembler::kNearJump); |
| 2633 __ addl(EDX, right); |
| 2634 __ jmp(&done, Assembler::kNearJump); |
| 2635 __ Bind(&subtract); |
| 2636 __ subl(EDX, right); |
| 2637 __ Bind(&done); |
| 2638 |
| 2639 __ LoadObject(result, Array::ZoneHandle(Array::New(2, Heap::kOld))); |
| 2640 const intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(kArrayCid); |
| 2641 Address trunc_div_address( |
| 2642 FlowGraphCompiler::ElementAddressForIntIndex(kArrayCid, |
| 2643 index_scale, |
| 2644 result, |
| 2645 0)); |
| 2646 Address mod_address( |
| 2647 FlowGraphCompiler::ElementAddressForIntIndex(kArrayCid, |
| 2648 index_scale, |
| 2649 result, |
| 2650 1)); |
| 2651 __ SmiTag(EAX); |
| 2652 __ SmiTag(EDX); |
| 2653 __ StoreIntoObjectNoBarrier(result, trunc_div_address, EAX); |
| 2654 __ StoreIntoObjectNoBarrier(result, mod_address, EDX); |
| 2655 break; |
| 2656 } |
| 2587 case Token::kSHR: { | 2657 case Token::kSHR: { |
| 2588 if (CanDeoptimize()) { | 2658 if (CanDeoptimize()) { |
| 2589 __ cmpl(right, Immediate(0)); | 2659 __ cmpl(right, Immediate(0)); |
| 2590 __ j(LESS, deopt); | 2660 __ j(LESS, deopt); |
| 2591 } | 2661 } |
| 2592 __ SmiUntag(right); | 2662 __ SmiUntag(right); |
| 2593 // sarl operation masks the count to 5 bits. | 2663 // sarl operation masks the count to 5 bits. |
| 2594 const intptr_t kCountLimit = 0x1F; | 2664 const intptr_t kCountLimit = 0x1F; |
| 2595 Range* right_range = this->right()->definition()->range(); | 2665 Range* right_range = this->right()->definition()->range(); |
| 2596 if ((right_range == NULL) || | 2666 if ((right_range == NULL) || |
| (...skipping 2370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4967 PcDescriptors::kOther, | 5037 PcDescriptors::kOther, |
| 4968 locs()); | 5038 locs()); |
| 4969 __ Drop(2); // Discard type arguments and receiver. | 5039 __ Drop(2); // Discard type arguments and receiver. |
| 4970 } | 5040 } |
| 4971 | 5041 |
| 4972 } // namespace dart | 5042 } // namespace dart |
| 4973 | 5043 |
| 4974 #undef __ | 5044 #undef __ |
| 4975 | 5045 |
| 4976 #endif // defined TARGET_ARCH_IA32 | 5046 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |