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

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

Issue 68663003: Merge TRUNCDIV and MOD into TRUNCDIV_MOD single operation. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 1 month 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
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_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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698