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

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

Issue 10968059: Support for unboxed 64-bit integer bitwise operations and equality on ia32. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 2 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.cc ('k') | runtime/vm/intermediate_language_x64.cc » ('j') | 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) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 "lib/error.h" 10 #include "lib/error.h"
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after
255 UNREACHABLE(); 255 UNREACHABLE();
256 return OVERFLOW; 256 return OVERFLOW;
257 } 257 }
258 } 258 }
259 259
260 260
261 LocationSummary* EqualityCompareInstr::MakeLocationSummary() const { 261 LocationSummary* EqualityCompareInstr::MakeLocationSummary() const {
262 const intptr_t kNumInputs = 2; 262 const intptr_t kNumInputs = 2;
263 const bool is_checked_strict_equal = 263 const bool is_checked_strict_equal =
264 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); 264 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid);
265 if (receiver_class_id() == kMintCid) {
266 const intptr_t kNumTemps = 1;
267 LocationSummary* locs =
268 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
269 locs->set_in(0, Location::RequiresXmmRegister());
270 locs->set_in(1, Location::RequiresXmmRegister());
271 locs->set_temp(0, Location::RequiresRegister());
272 locs->set_out(Location::RequiresRegister());
273 return locs;
274 }
265 if (receiver_class_id() == kDoubleCid) { 275 if (receiver_class_id() == kDoubleCid) {
266 const intptr_t kNumTemps = 0; 276 const intptr_t kNumTemps = 0;
267 LocationSummary* locs = 277 LocationSummary* locs =
268 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 278 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
269 locs->set_in(0, Location::RequiresXmmRegister()); 279 locs->set_in(0, Location::RequiresXmmRegister());
270 locs->set_in(1, Location::RequiresXmmRegister()); 280 locs->set_in(1, Location::RequiresXmmRegister());
271 locs->set_out(Location::RequiresRegister()); 281 locs->set_out(Location::RequiresRegister());
272 return locs; 282 return locs;
273 } 283 }
274 if (receiver_class_id() == kSmiCid) { 284 if (receiver_class_id() == kSmiCid) {
(...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after
612 __ j(true_condition, &is_true); 622 __ j(true_condition, &is_true);
613 __ LoadObject(result, compiler->bool_false()); 623 __ LoadObject(result, compiler->bool_false());
614 __ jmp(&done); 624 __ jmp(&done);
615 __ Bind(&is_true); 625 __ Bind(&is_true);
616 __ LoadObject(result, compiler->bool_true()); 626 __ LoadObject(result, compiler->bool_true());
617 __ Bind(&done); 627 __ Bind(&done);
618 } 628 }
619 } 629 }
620 630
621 631
632 static Condition TokenKindToMintCondition(Token::Kind kind) {
633 switch (kind) {
634 case Token::kEQ: return EQUAL;
635 case Token::kNE: return NOT_EQUAL;
636 default:
637 UNIMPLEMENTED();
638 return OVERFLOW;
639 }
640 }
641
642
643 static void EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler,
644 const LocationSummary& locs,
645 Token::Kind kind,
646 BranchInstr* branch) {
647 ASSERT(Token::IsEqualityOperator(kind));
648 XmmRegister left = locs.in(0).xmm_reg();
649 XmmRegister right = locs.in(1).xmm_reg();
650 Register temp = locs.temp(0).reg();
651 __ movaps(XMM0, left);
652 __ pcmpeqq(XMM0, right);
653 __ movd(temp, XMM0);
654
655 Condition true_condition = TokenKindToMintCondition(kind);
656 __ cmpl(temp, Immediate(-1));
657
658 if (branch != NULL) {
659 branch->EmitBranchOnCondition(compiler, true_condition);
660 } else {
661 Register result = locs.out().reg();
662 Label done, is_true;
663 __ j(true_condition, &is_true);
664 __ LoadObject(result, compiler->bool_false());
665 __ jmp(&done);
666 __ Bind(&is_true);
667 __ LoadObject(result, compiler->bool_true());
668 __ Bind(&done);
669 }
670 }
671
672
622 static Condition TokenKindToDoubleCondition(Token::Kind kind) { 673 static Condition TokenKindToDoubleCondition(Token::Kind kind) {
623 switch (kind) { 674 switch (kind) {
624 case Token::kEQ: return EQUAL; 675 case Token::kEQ: return EQUAL;
625 case Token::kNE: return NOT_EQUAL; 676 case Token::kNE: return NOT_EQUAL;
626 case Token::kLT: return BELOW; 677 case Token::kLT: return BELOW;
627 case Token::kGT: return ABOVE; 678 case Token::kGT: return ABOVE;
628 case Token::kLTE: return BELOW_EQUAL; 679 case Token::kLTE: return BELOW_EQUAL;
629 case Token::kGTE: return ABOVE_EQUAL; 680 case Token::kGTE: return ABOVE_EQUAL;
630 default: 681 default:
631 UNREACHABLE(); 682 UNREACHABLE();
(...skipping 21 matching lines...) Expand all
653 704
654 705
655 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 706 void EqualityCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
656 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); 707 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
657 BranchInstr* kNoBranch = NULL; 708 BranchInstr* kNoBranch = NULL;
658 if (receiver_class_id() == kSmiCid) { 709 if (receiver_class_id() == kSmiCid) {
659 // Deoptimizes if both arguments not Smi. 710 // Deoptimizes if both arguments not Smi.
660 EmitSmiComparisonOp(compiler, *locs(), kind(), kNoBranch); 711 EmitSmiComparisonOp(compiler, *locs(), kind(), kNoBranch);
661 return; 712 return;
662 } 713 }
714 if (receiver_class_id() == kMintCid) {
715 EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), kNoBranch);
716 return;
717 }
663 if (receiver_class_id() == kDoubleCid) { 718 if (receiver_class_id() == kDoubleCid) {
664 EmitDoubleComparisonOp(compiler, *locs(), kind(), kNoBranch); 719 EmitDoubleComparisonOp(compiler, *locs(), kind(), kNoBranch);
665 return; 720 return;
666 } 721 }
667 const bool is_checked_strict_equal = 722 const bool is_checked_strict_equal =
668 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); 723 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid);
669 if (is_checked_strict_equal) { 724 if (is_checked_strict_equal) {
670 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), kNoBranch, 725 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), kNoBranch,
671 deopt_id()); 726 deopt_id());
672 return; 727 return;
(...skipping 13 matching lines...) Expand all
686 741
687 742
688 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, 743 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler,
689 BranchInstr* branch) { 744 BranchInstr* branch) {
690 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); 745 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ));
691 if (receiver_class_id() == kSmiCid) { 746 if (receiver_class_id() == kSmiCid) {
692 // Deoptimizes if both arguments not Smi. 747 // Deoptimizes if both arguments not Smi.
693 EmitSmiComparisonOp(compiler, *locs(), kind(), branch); 748 EmitSmiComparisonOp(compiler, *locs(), kind(), branch);
694 return; 749 return;
695 } 750 }
751 if (receiver_class_id() == kMintCid) {
752 EmitUnboxedMintEqualityOp(compiler, *locs(), kind(), branch);
753 return;
754 }
696 if (receiver_class_id() == kDoubleCid) { 755 if (receiver_class_id() == kDoubleCid) {
697 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch); 756 EmitDoubleComparisonOp(compiler, *locs(), kind(), branch);
698 return; 757 return;
699 } 758 }
700 const bool is_checked_strict_equal = 759 const bool is_checked_strict_equal =
701 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid); 760 HasICData() && ic_data()->AllTargetsHaveSameOwner(kInstanceCid);
702 if (is_checked_strict_equal) { 761 if (is_checked_strict_equal) {
703 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), branch, 762 EmitCheckedStrictEqual(compiler, *ic_data(), *locs(), kind(), branch,
704 deopt_id()); 763 deopt_id());
705 return; 764 return;
(...skipping 1512 matching lines...) Expand 10 before | Expand all | Expand 10 after
2218 __ j(ABOVE_EQUAL, deopt); 2277 __ j(ABOVE_EQUAL, deopt);
2219 } else { 2278 } else {
2220 Register receiver = locs()->in(0).reg(); 2279 Register receiver = locs()->in(0).reg();
2221 Register index = locs()->in(1).reg(); 2280 Register index = locs()->in(1).reg();
2222 __ cmpl(index, FieldAddress(receiver, length_offset)); 2281 __ cmpl(index, FieldAddress(receiver, length_offset));
2223 __ j(ABOVE_EQUAL, deopt); 2282 __ j(ABOVE_EQUAL, deopt);
2224 } 2283 }
2225 } 2284 }
2226 2285
2227 2286
2287 LocationSummary* UnboxIntegerInstr::MakeLocationSummary() const {
2288 const intptr_t kNumInputs = 1;
2289 const intptr_t kNumTemps = CanDeoptimize() ? 1 : 0;
2290 LocationSummary* summary =
2291 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
2292 summary->set_in(0, Location::RequiresRegister());
2293 if (CanDeoptimize()) summary->set_temp(0, Location::RequiresRegister());
2294 summary->set_out(Location::RequiresXmmRegister());
2295 return summary;
2296 }
2297
2298
2299 void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2300 const intptr_t value_cid = value()->ResultCid();
2301 const Register value = locs()->in(0).reg();
2302 const XmmRegister result = locs()->out().xmm_reg();
2303
2304 if (value_cid == kMintCid) {
2305 __ movsd(result, FieldAddress(value, Mint::value_offset()));
2306 } else if (value_cid == kSmiCid) {
2307 __ SmiUntag(value); // Untag input before conversion.
2308 __ movd(result, value);
2309 __ pmovsxdq(result, result);
2310 __ SmiTag(value); // Restore input register.
2311 } else {
2312 Register temp = locs()->temp(0).reg();
2313 Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptBinaryDoubleOp);
2314 Label is_smi, done;
2315 __ testl(value, Immediate(kSmiTagMask));
2316 __ j(ZERO, &is_smi);
2317 __ CompareClassId(value, kMintCid, temp);
2318 __ j(NOT_EQUAL, deopt);
2319 __ movsd(result, FieldAddress(value, Mint::value_offset()));
2320 __ jmp(&done);
2321 __ Bind(&is_smi);
2322 __ movl(temp, value);
2323 __ SmiUntag(temp);
2324 __ movd(result, temp);
2325 __ pmovsxdq(result, result);
2326 __ Bind(&done);
2327 }
2328 }
2329
2330
2331 LocationSummary* BoxIntegerInstr::MakeLocationSummary() const {
2332 const intptr_t kNumInputs = 1;
2333 const intptr_t kNumTemps = 2;
2334 LocationSummary* summary =
2335 new LocationSummary(kNumInputs,
2336 kNumTemps,
2337 LocationSummary::kCallOnSlowPath);
2338 summary->set_in(0, Location::RequiresXmmRegister());
2339 summary->set_temp(0, Location::RegisterLocation(EAX));
2340 summary->set_temp(1, Location::RegisterLocation(EDX));
2341 // TODO(fschneider): Save one temp by using result register as a temp.
2342 summary->set_out(Location::RequiresRegister());
2343 return summary;
2344 }
2345
2346
2347 class BoxIntegerSlowPath : public SlowPathCode {
2348 public:
2349 explicit BoxIntegerSlowPath(BoxIntegerInstr* instruction)
2350 : instruction_(instruction) { }
2351
2352 virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
2353 __ Bind(entry_label());
2354 const Class& mint_class =
2355 Class::ZoneHandle(Isolate::Current()->object_store()->mint_class());
2356 const Code& stub =
2357 Code::Handle(StubCode::GetAllocationStubForClass(mint_class));
2358 const ExternalLabel label(mint_class.ToCString(), stub.EntryPoint());
2359
2360 LocationSummary* locs = instruction_->locs();
2361 locs->live_registers()->Remove(locs->out());
2362
2363 compiler->SaveLiveRegisters(locs);
2364 compiler->GenerateCall(0, // No token pos.
2365 &label,
2366 PcDescriptors::kOther,
2367 locs);
2368 if (EAX != locs->out().reg()) __ movl(locs->out().reg(), EAX);
2369 compiler->RestoreLiveRegisters(locs);
2370
2371 __ jmp(exit_label());
2372 }
2373
2374 private:
2375 BoxIntegerInstr* instruction_;
2376 };
2377
2378
2379 void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2380 BoxIntegerSlowPath* slow_path = new BoxIntegerSlowPath(this);
2381 compiler->AddSlowPathCode(slow_path);
2382
2383 Register out_reg = locs()->out().reg();
2384 XmmRegister value = locs()->in(0).xmm_reg();
2385
2386 // Unboxed operations produce smis or mint-sized values.
2387 // Check if value fits into a smi.
2388 Label not_smi, done;
2389 __ pextrd(EDX, value, Immediate(1)); // Upper half.
2390 __ pextrd(EAX, value, Immediate(0)); // Lower half.
2391 // 1. Compute (x + -kMinSmi) which has to be in the range
2392 // 0 .. -kMinSmi+kMaxSmi for x to fit into a smi.
2393 __ addl(EAX, Immediate(0x40000000));
2394 __ adcl(EDX, Immediate(0));
2395 // 2. Unsigned compare to -kMinSmi+kMaxSmi.
2396 __ cmpl(EAX, Immediate(0x80000000));
2397 __ sbbl(EDX, Immediate(0));
2398 __ j(ABOVE_EQUAL, &not_smi);
2399 // 3. Restore lower half if result is a smi.
2400 __ subl(EAX, Immediate(0x40000000));
2401
2402 __ SmiTag(EAX);
2403 __ movl(out_reg, EAX);
2404 __ jmp(&done);
2405
2406 __ Bind(&not_smi);
2407 AssemblerMacros::TryAllocate(
2408 compiler->assembler(),
2409 Class::ZoneHandle(Isolate::Current()->object_store()->mint_class()),
2410 slow_path->entry_label(),
2411 Assembler::kFarJump,
2412 out_reg);
2413 __ Bind(slow_path->exit_label());
2414 __ movsd(FieldAddress(out_reg, Mint::value_offset()), value);
2415 __ Bind(&done);
2416 }
2417
2418
2419 LocationSummary* UnboxedMintBinaryOpInstr::MakeLocationSummary() const {
2420 const intptr_t kNumInputs = 2;
2421 const intptr_t kNumTemps = 0;
2422 LocationSummary* summary =
2423 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
2424 summary->set_in(0, Location::RequiresXmmRegister());
2425 summary->set_in(1, Location::RequiresXmmRegister());
2426 summary->set_out(Location::SameAsFirstInput());
2427 return summary;
2428 }
2429
2430
2431 void UnboxedMintBinaryOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2432 XmmRegister left = locs()->in(0).xmm_reg();
2433 XmmRegister right = locs()->in(1).xmm_reg();
2434
2435 ASSERT(locs()->out().xmm_reg() == left);
2436
2437 switch (op_kind()) {
2438 case Token::kBIT_AND: __ andpd(left, right); break;
2439 case Token::kBIT_OR: __ orpd(left, right); break;
2440 case Token::kBIT_XOR: __ xorpd(left, right); break;
2441 default: UNREACHABLE();
2442 }
2443 }
2444
2445
2446
2228 } // namespace dart 2447 } // namespace dart
2229 2448
2230 #undef __ 2449 #undef __
2231 2450
2232 #endif // defined TARGET_ARCH_X64 2451 #endif // defined TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « runtime/vm/intermediate_language.cc ('k') | runtime/vm/intermediate_language_x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698