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

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

Issue 25118002: Eliminates more large immediates from x64 code. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 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/flow_graph_compiler_x64.cc ('k') | runtime/vm/intrinsifier_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) 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_X64. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64.
6 #if defined(TARGET_ARCH_X64) 6 #if defined(TARGET_ARCH_X64)
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 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
45 45
46 46
47 void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 47 void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
48 // In SSA mode, we need an explicit push. Nothing to do in non-SSA mode 48 // In SSA mode, we need an explicit push. Nothing to do in non-SSA mode
49 // where PushArgument is handled by BindInstr::EmitNativeCode. 49 // where PushArgument is handled by BindInstr::EmitNativeCode.
50 if (compiler->is_optimizing()) { 50 if (compiler->is_optimizing()) {
51 Location value = locs()->in(0); 51 Location value = locs()->in(0);
52 if (value.IsRegister()) { 52 if (value.IsRegister()) {
53 __ pushq(value.reg()); 53 __ pushq(value.reg());
54 } else if (value.IsConstant()) { 54 } else if (value.IsConstant()) {
55 __ PushObject(value.constant()); 55 __ PushObject(value.constant(), PP);
56 } else { 56 } else {
57 ASSERT(value.IsStackSlot()); 57 ASSERT(value.IsStackSlot());
58 __ pushq(value.ToStackSlotAddress()); 58 __ pushq(value.ToStackSlotAddress());
59 } 59 }
60 } 60 }
61 } 61 }
62 62
63 63
64 LocationSummary* ReturnInstr::MakeLocationSummary() const { 64 LocationSummary* ReturnInstr::MakeLocationSummary() const {
65 const intptr_t kNumInputs = 1; 65 const intptr_t kNumInputs = 1;
(...skipping 17 matching lines...) Expand all
83 // has its own return instruction. Method that have finally are currently 83 // has its own return instruction. Method that have finally are currently
84 // not optimized. 84 // not optimized.
85 if (!compiler->HasFinally()) { 85 if (!compiler->HasFinally()) {
86 __ Comment("Stack Check"); 86 __ Comment("Stack Check");
87 Label done; 87 Label done;
88 const intptr_t fp_sp_dist = 88 const intptr_t fp_sp_dist =
89 (kFirstLocalSlotFromFp + 1 - compiler->StackSize()) * kWordSize; 89 (kFirstLocalSlotFromFp + 1 - compiler->StackSize()) * kWordSize;
90 ASSERT(fp_sp_dist <= 0); 90 ASSERT(fp_sp_dist <= 0);
91 __ movq(RDI, RSP); 91 __ movq(RDI, RSP);
92 __ subq(RDI, RBP); 92 __ subq(RDI, RBP);
93 __ cmpq(RDI, Immediate(fp_sp_dist)); 93 __ CompareImmediate(RDI, Immediate(fp_sp_dist), PP);
94 __ j(EQUAL, &done, Assembler::kNearJump); 94 __ j(EQUAL, &done, Assembler::kNearJump);
95 __ int3(); 95 __ int3();
96 __ Bind(&done); 96 __ Bind(&done);
97 } 97 }
98 #endif 98 #endif
99 99
100 __ ReturnPatchable(); 100 __ ReturnPatchable();
101 compiler->AddCurrentDescriptor(PcDescriptors::kReturn, 101 compiler->AddCurrentDescriptor(PcDescriptors::kReturn,
102 Isolate::kNoDeoptId, 102 Isolate::kNoDeoptId,
103 token_pos()); 103 token_pos());
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
189 ASSERT(Token::IsEqualityOperator(kind())); 189 ASSERT(Token::IsEqualityOperator(kind()));
190 190
191 Location left = locs()->in(0); 191 Location left = locs()->in(0);
192 Location right = locs()->in(1); 192 Location right = locs()->in(1);
193 if (left.IsConstant() && right.IsConstant()) { 193 if (left.IsConstant() && right.IsConstant()) {
194 // TODO(srdjan): Determine why this instruction was not eliminated. 194 // TODO(srdjan): Determine why this instruction was not eliminated.
195 bool result = (left.constant().raw() == right.constant().raw()); 195 bool result = (left.constant().raw() == right.constant().raw());
196 if ((kind_ == Token::kNE_STRICT) || (kind_ == Token::kNE)) { 196 if ((kind_ == Token::kNE_STRICT) || (kind_ == Token::kNE)) {
197 result = !result; 197 result = !result;
198 } 198 }
199 __ movq(locs()->out().reg(), 199 __ LoadImmediate(locs()->out().reg(),
200 Immediate(reinterpret_cast<int64_t>( 200 Immediate(reinterpret_cast<int64_t>(
201 Smi::New(result ? if_true_ : if_false_)))); 201 Smi::New(result ? if_true_ : if_false_))), PP);
202 return; 202 return;
203 } 203 }
204 204
205 ASSERT(!left.IsConstant() || !right.IsConstant()); 205 ASSERT(!left.IsConstant() || !right.IsConstant());
206 206
207 // Clear upper part of the out register. We are going to use setcc on it 207 // Clear upper part of the out register. We are going to use setcc on it
208 // which is a byte move. 208 // which is a byte move.
209 __ xorq(RDX, RDX); 209 __ xorq(RDX, RDX);
210 210
211 // Compare left and right. For now only equality comparison is supported. 211 // Compare left and right. For now only equality comparison is supported.
212 // TODO(vegorov): reuse code from the other comparison instructions instead of 212 // TODO(vegorov): reuse code from the other comparison instructions instead of
213 // generating it inline here. 213 // generating it inline here.
214 if (left.IsConstant()) { 214 if (left.IsConstant()) {
215 __ CompareObject(right.reg(), left.constant()); 215 __ CompareObject(right.reg(), left.constant(), PP);
216 } else if (right.IsConstant()) { 216 } else if (right.IsConstant()) {
217 __ CompareObject(left.reg(), right.constant()); 217 __ CompareObject(left.reg(), right.constant(), PP);
218 } else { 218 } else {
219 __ cmpq(left.reg(), right.reg()); 219 __ cmpq(left.reg(), right.reg());
220 } 220 }
221 221
222 Condition true_condition = 222 Condition true_condition =
223 ((kind_ == Token::kEQ_STRICT) || (kind_ == Token::kEQ)) ? EQUAL 223 ((kind_ == Token::kEQ_STRICT) || (kind_ == Token::kEQ)) ? EQUAL
224 : NOT_EQUAL; 224 : NOT_EQUAL;
225 225
226 const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_); 226 const bool is_power_of_two_kind = IsPowerOfTwoKind(if_true_, if_false_);
227 227
(...skipping 16 matching lines...) Expand all
244 } 244 }
245 } 245 }
246 246
247 __ setcc(true_condition, DL); 247 __ setcc(true_condition, DL);
248 248
249 if (is_power_of_two_kind) { 249 if (is_power_of_two_kind) {
250 const intptr_t shift = 250 const intptr_t shift =
251 Utils::ShiftForPowerOfTwo(Utils::Maximum(true_value, false_value)); 251 Utils::ShiftForPowerOfTwo(Utils::Maximum(true_value, false_value));
252 __ shlq(RDX, Immediate(shift + kSmiTagSize)); 252 __ shlq(RDX, Immediate(shift + kSmiTagSize));
253 } else { 253 } else {
254 __ subq(RDX, Immediate(1)); 254 __ AddImmediate(RDX, Immediate(-1), PP);
255 __ andq(RDX, Immediate( 255 __ AndImmediate(RDX,
256 Smi::RawValue(true_value) - Smi::RawValue(false_value))); 256 Immediate(Smi::RawValue(true_value) - Smi::RawValue(false_value)), PP);
257 if (false_value != 0) { 257 if (false_value != 0) {
258 __ addq(RDX, Immediate(Smi::RawValue(false_value))); 258 __ AddImmediate(RDX, Immediate(Smi::RawValue(false_value)), PP);
259 } 259 }
260 } 260 }
261 } 261 }
262 262
263 263
264 LocationSummary* LoadLocalInstr::MakeLocationSummary() const { 264 LocationSummary* LoadLocalInstr::MakeLocationSummary() const {
265 const intptr_t kNumInputs = 0; 265 const intptr_t kNumInputs = 0;
266 return LocationSummary::Make(kNumInputs, 266 return LocationSummary::Make(kNumInputs,
267 Location::RequiresRegister(), 267 Location::RequiresRegister(),
268 LocationSummary::kNoCall); 268 LocationSummary::kNoCall);
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
334 334
335 static void EmitAssertBoolean(Register reg, 335 static void EmitAssertBoolean(Register reg,
336 intptr_t token_pos, 336 intptr_t token_pos,
337 intptr_t deopt_id, 337 intptr_t deopt_id,
338 LocationSummary* locs, 338 LocationSummary* locs,
339 FlowGraphCompiler* compiler) { 339 FlowGraphCompiler* compiler) {
340 // Check that the type of the value is allowed in conditional context. 340 // Check that the type of the value is allowed in conditional context.
341 // Call the runtime if the object is not bool::true or bool::false. 341 // Call the runtime if the object is not bool::true or bool::false.
342 ASSERT(locs->always_calls()); 342 ASSERT(locs->always_calls());
343 Label done; 343 Label done;
344 __ CompareObject(reg, Bool::True()); 344 __ CompareObject(reg, Bool::True(), PP);
345 __ j(EQUAL, &done, Assembler::kNearJump); 345 __ j(EQUAL, &done, Assembler::kNearJump);
346 __ CompareObject(reg, Bool::False()); 346 __ CompareObject(reg, Bool::False(), PP);
347 __ j(EQUAL, &done, Assembler::kNearJump); 347 __ j(EQUAL, &done, Assembler::kNearJump);
348 348
349 __ pushq(reg); // Push the source object. 349 __ pushq(reg); // Push the source object.
350 compiler->GenerateCallRuntime(token_pos, 350 compiler->GenerateCallRuntime(token_pos,
351 deopt_id, 351 deopt_id,
352 kConditionTypeErrorRuntimeEntry, 352 kConditionTypeErrorRuntimeEntry,
353 1, 353 1,
354 locs); 354 locs);
355 // We should never return here. 355 // We should never return here.
356 __ int3(); 356 __ int3();
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
515 compiler->GenerateCall(token_pos, 515 compiler->GenerateCall(token_pos,
516 &StubCode::EqualityWithNullArgLabel(), 516 &StubCode::EqualityWithNullArgLabel(),
517 PcDescriptors::kRuntimeCall, 517 PcDescriptors::kRuntimeCall,
518 locs); 518 locs);
519 __ Drop(2); 519 __ Drop(2);
520 } 520 }
521 __ Bind(&check_ne); 521 __ Bind(&check_ne);
522 if (kind == Token::kNE) { 522 if (kind == Token::kNE) {
523 Label true_label, done; 523 Label true_label, done;
524 // Negate the condition: true label returns false and vice versa. 524 // Negate the condition: true label returns false and vice versa.
525 __ CompareObject(RAX, Bool::True()); 525 __ CompareObject(RAX, Bool::True(), PP);
526 __ j(EQUAL, &true_label, Assembler::kNearJump); 526 __ j(EQUAL, &true_label, Assembler::kNearJump);
527 __ LoadObject(RAX, Bool::True(), PP); 527 __ LoadObject(RAX, Bool::True(), PP);
528 __ jmp(&done, Assembler::kNearJump); 528 __ jmp(&done, Assembler::kNearJump);
529 __ Bind(&true_label); 529 __ Bind(&true_label);
530 __ LoadObject(RAX, Bool::False(), PP); 530 __ LoadObject(RAX, Bool::False(), PP);
531 __ Bind(&done); 531 __ Bind(&done);
532 } 532 }
533 __ Bind(&equality_done); 533 __ Bind(&equality_done);
534 } 534 }
535 535
536 536
537 static void LoadValueCid(FlowGraphCompiler* compiler, 537 static void LoadValueCid(FlowGraphCompiler* compiler,
538 Register value_cid_reg, 538 Register value_cid_reg,
539 Register value_reg, 539 Register value_reg,
540 Label* value_is_smi = NULL) { 540 Label* value_is_smi = NULL) {
541 Label done; 541 Label done;
542 if (value_is_smi == NULL) { 542 if (value_is_smi == NULL) {
543 __ movq(value_cid_reg, Immediate(kSmiCid)); 543 __ LoadImmediate(value_cid_reg, Immediate(kSmiCid), PP);
544 } 544 }
545 __ testq(value_reg, Immediate(kSmiTagMask)); 545 __ testq(value_reg, Immediate(kSmiTagMask));
546 if (value_is_smi == NULL) { 546 if (value_is_smi == NULL) {
547 __ j(ZERO, &done, Assembler::kNearJump); 547 __ j(ZERO, &done, Assembler::kNearJump);
548 } else { 548 } else {
549 __ j(ZERO, value_is_smi); 549 __ j(ZERO, value_is_smi);
550 } 550 }
551 __ LoadClassId(value_cid_reg, value_reg); 551 __ LoadClassId(value_cid_reg, value_reg);
552 __ Bind(&done); 552 __ Bind(&done);
553 } 553 }
(...skipping 18 matching lines...) Expand all
572 (ic_data.GetReceiverClassIdAt(0) == kSmiCid) ? NULL : deopt); 572 (ic_data.GetReceiverClassIdAt(0) == kSmiCid) ? NULL : deopt);
573 // 'temp' contains class-id of the left argument. 573 // 'temp' contains class-id of the left argument.
574 ObjectStore* object_store = Isolate::Current()->object_store(); 574 ObjectStore* object_store = Isolate::Current()->object_store();
575 Condition cond = TokenKindToSmiCondition(kind); 575 Condition cond = TokenKindToSmiCondition(kind);
576 Label done; 576 Label done;
577 const intptr_t len = ic_data.NumberOfChecks(); 577 const intptr_t len = ic_data.NumberOfChecks();
578 for (intptr_t i = 0; i < len; i++) { 578 for (intptr_t i = 0; i < len; i++) {
579 // Assert that the Smi is at position 0, if at all. 579 // Assert that the Smi is at position 0, if at all.
580 ASSERT((ic_data.GetReceiverClassIdAt(i) != kSmiCid) || (i == 0)); 580 ASSERT((ic_data.GetReceiverClassIdAt(i) != kSmiCid) || (i == 0));
581 Label next_test; 581 Label next_test;
582 __ cmpq(temp, Immediate(ic_data.GetReceiverClassIdAt(i))); 582 __ CompareImmediate(temp, Immediate(ic_data.GetReceiverClassIdAt(i)), PP);
583 if (i < len - 1) { 583 if (i < len - 1) {
584 __ j(NOT_EQUAL, &next_test); 584 __ j(NOT_EQUAL, &next_test);
585 } else { 585 } else {
586 __ j(NOT_EQUAL, deopt); 586 __ j(NOT_EQUAL, deopt);
587 } 587 }
588 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(i)); 588 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(i));
589 if (target.Owner() == object_store->object_class()) { 589 if (target.Owner() == object_store->object_class()) {
590 // Object.== is same as ===. 590 // Object.== is same as ===.
591 __ Drop(2); 591 __ Drop(2);
592 __ cmpq(left, right); 592 __ cmpq(left, right);
(...skipping 14 matching lines...) Expand all
607 const Array& kNoArgumentNames = Object::null_array(); 607 const Array& kNoArgumentNames = Object::null_array();
608 compiler->GenerateStaticCall(deopt_id, 608 compiler->GenerateStaticCall(deopt_id,
609 token_pos, 609 token_pos,
610 target, 610 target,
611 kNumberOfArguments, 611 kNumberOfArguments,
612 kNoArgumentNames, 612 kNoArgumentNames,
613 locs); 613 locs);
614 if (branch == NULL) { 614 if (branch == NULL) {
615 if (kind == Token::kNE) { 615 if (kind == Token::kNE) {
616 Label false_label; 616 Label false_label;
617 __ CompareObject(RAX, Bool::True()); 617 __ CompareObject(RAX, Bool::True(), PP);
618 __ j(EQUAL, &false_label, Assembler::kNearJump); 618 __ j(EQUAL, &false_label, Assembler::kNearJump);
619 __ LoadObject(RAX, Bool::True(), PP); 619 __ LoadObject(RAX, Bool::True(), PP);
620 __ jmp(&done); 620 __ jmp(&done);
621 __ Bind(&false_label); 621 __ Bind(&false_label);
622 __ LoadObject(RAX, Bool::False(), PP); 622 __ LoadObject(RAX, Bool::False(), PP);
623 } 623 }
624 } else { 624 } else {
625 if (branch->is_checked()) { 625 if (branch->is_checked()) {
626 EmitAssertBoolean(RAX, token_pos, deopt_id, locs, compiler); 626 EmitAssertBoolean(RAX, token_pos, deopt_id, locs, compiler);
627 } 627 }
628 __ CompareObject(RAX, Bool::True()); 628 __ CompareObject(RAX, Bool::True(), PP);
629 branch->EmitBranchOnCondition(compiler, cond); 629 branch->EmitBranchOnCondition(compiler, cond);
630 } 630 }
631 } 631 }
632 if (i < len - 1) { 632 if (i < len - 1) {
633 __ jmp(&done); 633 __ jmp(&done);
634 __ Bind(&next_test); 634 __ Bind(&next_test);
635 } 635 }
636 } 636 }
637 __ Bind(&done); 637 __ Bind(&done);
638 } 638 }
639 639
640 640
641 // Emit code when ICData's targets are all Object == (which is ===). 641 // Emit code when ICData's targets are all Object == (which is ===).
642 static void EmitCheckedStrictEqual(FlowGraphCompiler* compiler, 642 static void EmitCheckedStrictEqual(FlowGraphCompiler* compiler,
643 const ICData& orig_ic_data, 643 const ICData& orig_ic_data,
644 const LocationSummary& locs, 644 const LocationSummary& locs,
645 Token::Kind kind, 645 Token::Kind kind,
646 BranchInstr* branch, 646 BranchInstr* branch,
647 intptr_t deopt_id) { 647 intptr_t deopt_id) {
648 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); 648 ASSERT((kind == Token::kEQ) || (kind == Token::kNE));
649 Register left = locs.in(0).reg(); 649 Register left = locs.in(0).reg();
650 Register right = locs.in(1).reg(); 650 Register right = locs.in(1).reg();
651 Register temp = locs.temp(0).reg(); 651 Register temp = locs.temp(0).reg();
652 Label* deopt = compiler->AddDeoptStub(deopt_id, kDeoptEquality); 652 Label* deopt = compiler->AddDeoptStub(deopt_id, kDeoptEquality);
653 __ testq(left, Immediate(kSmiTagMask)); 653 __ testq(left, Immediate(kSmiTagMask));
654 __ j(ZERO, deopt); 654 __ j(ZERO, deopt);
655 // 'left' is not Smi. 655 // 'left' is not Smi.
656 656
657 Label identity_compare; 657 Label identity_compare;
658 __ CompareObject(right, Object::null_object()); 658 __ CompareObject(right, Object::null_object(), PP);
659 __ j(EQUAL, &identity_compare); 659 __ j(EQUAL, &identity_compare);
660 __ CompareObject(left, Object::null_object()); 660 __ CompareObject(left, Object::null_object(), PP);
661 __ j(EQUAL, &identity_compare); 661 __ j(EQUAL, &identity_compare);
662 662
663 __ LoadClassId(temp, left); 663 __ LoadClassId(temp, left);
664 const ICData& ic_data = ICData::Handle(orig_ic_data.AsUnaryClassChecks()); 664 const ICData& ic_data = ICData::Handle(orig_ic_data.AsUnaryClassChecks());
665 const intptr_t len = ic_data.NumberOfChecks(); 665 const intptr_t len = ic_data.NumberOfChecks();
666 for (intptr_t i = 0; i < len; i++) { 666 for (intptr_t i = 0; i < len; i++) {
667 __ cmpq(temp, Immediate(ic_data.GetReceiverClassIdAt(i))); 667 __ CompareImmediate(temp, Immediate(ic_data.GetReceiverClassIdAt(i)), PP);
668 if (i == (len - 1)) { 668 if (i == (len - 1)) {
669 __ j(NOT_EQUAL, deopt); 669 __ j(NOT_EQUAL, deopt);
670 } else { 670 } else {
671 __ j(EQUAL, &identity_compare); 671 __ j(EQUAL, &identity_compare);
672 } 672 }
673 } 673 }
674 __ Bind(&identity_compare); 674 __ Bind(&identity_compare);
675 __ cmpq(left, right); 675 __ cmpq(left, right);
676 if (branch == NULL) { 676 if (branch == NULL) {
677 Label done, is_equal; 677 Label done, is_equal;
(...skipping 21 matching lines...) Expand all
699 BranchInstr* branch, 699 BranchInstr* branch,
700 const ICData& ic_data, 700 const ICData& ic_data,
701 intptr_t deopt_id, 701 intptr_t deopt_id,
702 intptr_t token_pos) { 702 intptr_t token_pos) {
703 ASSERT((kind == Token::kEQ) || (kind == Token::kNE)); 703 ASSERT((kind == Token::kEQ) || (kind == Token::kNE));
704 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0)); 704 ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0));
705 Register left = locs->in(0).reg(); 705 Register left = locs->in(0).reg();
706 Register right = locs->in(1).reg(); 706 Register right = locs->in(1).reg();
707 707
708 Label done, identity_compare, non_null_compare; 708 Label done, identity_compare, non_null_compare;
709 __ CompareObject(right, Object::null_object()); 709 __ CompareObject(right, Object::null_object(), PP);
710 __ j(EQUAL, &identity_compare, Assembler::kNearJump); 710 __ j(EQUAL, &identity_compare, Assembler::kNearJump);
711 __ CompareObject(left, Object::null_object()); 711 __ CompareObject(left, Object::null_object(), PP);
712 __ j(NOT_EQUAL, &non_null_compare, Assembler::kNearJump); 712 __ j(NOT_EQUAL, &non_null_compare, Assembler::kNearJump);
713 // Comparison with NULL is "===". 713 // Comparison with NULL is "===".
714 __ Bind(&identity_compare); 714 __ Bind(&identity_compare);
715 __ cmpq(left, right); 715 __ cmpq(left, right);
716 Condition cond = TokenKindToSmiCondition(kind); 716 Condition cond = TokenKindToSmiCondition(kind);
717 if (branch != NULL) { 717 if (branch != NULL) {
718 branch->EmitBranchOnCondition(compiler, cond); 718 branch->EmitBranchOnCondition(compiler, cond);
719 } else { 719 } else {
720 Register result = locs->out().reg(); 720 Register result = locs->out().reg();
721 Label load_true; 721 Label load_true;
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
758 const LocationSummary& locs, 758 const LocationSummary& locs,
759 Token::Kind kind, 759 Token::Kind kind,
760 BranchInstr* branch) { 760 BranchInstr* branch) {
761 Location left = locs.in(0); 761 Location left = locs.in(0);
762 Location right = locs.in(1); 762 Location right = locs.in(1);
763 ASSERT(!left.IsConstant() || !right.IsConstant()); 763 ASSERT(!left.IsConstant() || !right.IsConstant());
764 764
765 Condition true_condition = TokenKindToSmiCondition(kind); 765 Condition true_condition = TokenKindToSmiCondition(kind);
766 766
767 if (left.IsConstant()) { 767 if (left.IsConstant()) {
768 __ CompareObject(right.reg(), left.constant()); 768 __ CompareObject(right.reg(), left.constant(), PP);
769 true_condition = FlipCondition(true_condition); 769 true_condition = FlipCondition(true_condition);
770 } else if (right.IsConstant()) { 770 } else if (right.IsConstant()) {
771 __ CompareObject(left.reg(), right.constant()); 771 __ CompareObject(left.reg(), right.constant(), PP);
772 } else if (right.IsStackSlot()) { 772 } else if (right.IsStackSlot()) {
773 __ cmpq(left.reg(), right.ToStackSlotAddress()); 773 __ cmpq(left.reg(), right.ToStackSlotAddress());
774 } else { 774 } else {
775 __ cmpq(left.reg(), right.reg()); 775 __ cmpq(left.reg(), right.reg());
776 } 776 }
777 777
778 if (branch != NULL) { 778 if (branch != NULL) {
779 branch->EmitBranchOnCondition(compiler, true_condition); 779 branch->EmitBranchOnCondition(compiler, true_condition);
780 } else { 780 } else {
781 Register result = locs.out().reg(); 781 Register result = locs.out().reg();
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
890 EmitEqualityAsInstanceCall(compiler, 890 EmitEqualityAsInstanceCall(compiler,
891 deopt_id(), 891 deopt_id(),
892 token_pos(), 892 token_pos(),
893 Token::kEQ, // kNE reverse occurs at branch. 893 Token::kEQ, // kNE reverse occurs at branch.
894 locs(), 894 locs(),
895 *ic_data()); 895 *ic_data());
896 if (branch->is_checked()) { 896 if (branch->is_checked()) {
897 EmitAssertBoolean(RAX, token_pos(), deopt_id(), locs(), compiler); 897 EmitAssertBoolean(RAX, token_pos(), deopt_id(), locs(), compiler);
898 } 898 }
899 Condition branch_condition = (kind() == Token::kNE) ? NOT_EQUAL : EQUAL; 899 Condition branch_condition = (kind() == Token::kNE) ? NOT_EQUAL : EQUAL;
900 __ CompareObject(RAX, Bool::True()); 900 __ CompareObject(RAX, Bool::True(), PP);
901 branch->EmitBranchOnCondition(compiler, branch_condition); 901 branch->EmitBranchOnCondition(compiler, branch_condition);
902 } 902 }
903 903
904 904
905 LocationSummary* RelationalOpInstr::MakeLocationSummary() const { 905 LocationSummary* RelationalOpInstr::MakeLocationSummary() const {
906 const intptr_t kNumInputs = 2; 906 const intptr_t kNumInputs = 2;
907 const intptr_t kNumTemps = 0; 907 const intptr_t kNumTemps = 0;
908 if (operation_cid() == kDoubleCid) { 908 if (operation_cid() == kDoubleCid) {
909 LocationSummary* summary = 909 LocationSummary* summary =
910 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 910 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
961 } 961 }
962 962
963 963
964 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 964 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
965 ASSERT(locs()->temp(0).reg() == RAX); 965 ASSERT(locs()->temp(0).reg() == RAX);
966 ASSERT(locs()->temp(1).reg() == RBX); 966 ASSERT(locs()->temp(1).reg() == RBX);
967 ASSERT(locs()->temp(2).reg() == R10); 967 ASSERT(locs()->temp(2).reg() == R10);
968 Register result = locs()->out().reg(); 968 Register result = locs()->out().reg();
969 969
970 // Push the result place holder initialized to NULL. 970 // Push the result place holder initialized to NULL.
971 __ PushObject(Object::ZoneHandle()); 971 __ PushObject(Object::ZoneHandle(), PP);
972 // Pass a pointer to the first argument in RAX. 972 // Pass a pointer to the first argument in RAX.
973 if (!function().HasOptionalParameters()) { 973 if (!function().HasOptionalParameters()) {
974 __ leaq(RAX, Address(RBP, (kParamEndSlotFromFp + 974 __ leaq(RAX, Address(RBP, (kParamEndSlotFromFp +
975 function().NumParameters()) * kWordSize)); 975 function().NumParameters()) * kWordSize));
976 } else { 976 } else {
977 __ leaq(RAX, 977 __ leaq(RAX,
978 Address(RBP, kFirstLocalSlotFromFp * kWordSize)); 978 Address(RBP, kFirstLocalSlotFromFp * kWordSize));
979 } 979 }
980 __ movq(RBX, Immediate(reinterpret_cast<uword>(native_c_function()))); 980 __ LoadImmediate(
981 __ movq(R10, Immediate(NativeArguments::ComputeArgcTag(function()))); 981 RBX, Immediate(reinterpret_cast<uword>(native_c_function())), PP);
982 __ LoadImmediate(
983 R10, Immediate(NativeArguments::ComputeArgcTag(function())), PP);
982 const ExternalLabel* stub_entry = 984 const ExternalLabel* stub_entry =
983 (is_bootstrap_native()) ? &StubCode::CallBootstrapCFunctionLabel() : 985 (is_bootstrap_native()) ? &StubCode::CallBootstrapCFunctionLabel() :
984 &StubCode::CallNativeCFunctionLabel(); 986 &StubCode::CallNativeCFunctionLabel();
985 compiler->GenerateCall(token_pos(), 987 compiler->GenerateCall(token_pos(),
986 stub_entry, 988 stub_entry,
987 PcDescriptors::kOther, 989 PcDescriptors::kOther,
988 locs()); 990 locs());
989 __ popq(result); 991 __ popq(result);
990 } 992 }
991 993
(...skipping 15 matching lines...) Expand all
1007 // TODO(fschneider): Allow immediate operands for the char code. 1009 // TODO(fschneider): Allow immediate operands for the char code.
1008 return LocationSummary::Make(kNumInputs, 1010 return LocationSummary::Make(kNumInputs,
1009 Location::RequiresRegister(), 1011 Location::RequiresRegister(),
1010 LocationSummary::kNoCall); 1012 LocationSummary::kNoCall);
1011 } 1013 }
1012 1014
1013 1015
1014 void StringFromCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1016 void StringFromCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1015 Register char_code = locs()->in(0).reg(); 1017 Register char_code = locs()->in(0).reg();
1016 Register result = locs()->out().reg(); 1018 Register result = locs()->out().reg();
1017 __ movq(result, 1019 __ LoadImmediate(result,
1018 Immediate(reinterpret_cast<uword>(Symbols::PredefinedAddress()))); 1020 Immediate(reinterpret_cast<uword>(Symbols::PredefinedAddress())), PP);
1019 __ movq(result, Address(result, 1021 __ movq(result, Address(result,
1020 char_code, 1022 char_code,
1021 TIMES_HALF_WORD_SIZE, // Char code is a smi. 1023 TIMES_HALF_WORD_SIZE, // Char code is a smi.
1022 Symbols::kNullCharCodeSymbolOffset * kWordSize)); 1024 Symbols::kNullCharCodeSymbolOffset * kWordSize));
1023 } 1025 }
1024 1026
1025 1027
1026 LocationSummary* LoadUntaggedInstr::MakeLocationSummary() const { 1028 LocationSummary* LoadUntaggedInstr::MakeLocationSummary() const {
1027 const intptr_t kNumInputs = 1; 1029 const intptr_t kNumInputs = 1;
1028 return LocationSummary::Make(kNumInputs, 1030 return LocationSummary::Make(kNumInputs,
(...skipping 16 matching lines...) Expand all
1045 LocationSummary::kNoCall); 1047 LocationSummary::kNoCall);
1046 } 1048 }
1047 1049
1048 1050
1049 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1051 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1050 Register object = locs()->in(0).reg(); 1052 Register object = locs()->in(0).reg();
1051 Register result = locs()->out().reg(); 1053 Register result = locs()->out().reg();
1052 Label load, done; 1054 Label load, done;
1053 __ testq(object, Immediate(kSmiTagMask)); 1055 __ testq(object, Immediate(kSmiTagMask));
1054 __ j(NOT_ZERO, &load, Assembler::kNearJump); 1056 __ j(NOT_ZERO, &load, Assembler::kNearJump);
1055 __ movq(result, Immediate(Smi::RawValue(kSmiCid))); 1057 __ LoadImmediate(result, Immediate(Smi::RawValue(kSmiCid)), PP);
1056 __ jmp(&done); 1058 __ jmp(&done);
1057 __ Bind(&load); 1059 __ Bind(&load);
1058 __ LoadClassId(result, object); 1060 __ LoadClassId(result, object);
1059 __ SmiTag(result); 1061 __ SmiTag(result);
1060 __ Bind(&done); 1062 __ Bind(&done);
1061 } 1063 }
1062 1064
1063 1065
1064 CompileType LoadIndexedInstr::ComputeType() const { 1066 CompileType LoadIndexedInstr::ComputeType() const {
1065 switch (class_id_) { 1067 switch (class_id_) {
(...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after
1353 if ((index_scale() == 1) && index.IsRegister()) { 1355 if ((index_scale() == 1) && index.IsRegister()) {
1354 __ SmiUntag(index.reg()); 1356 __ SmiUntag(index.reg());
1355 } 1357 }
1356 switch (class_id()) { 1358 switch (class_id()) {
1357 case kArrayCid: 1359 case kArrayCid:
1358 if (ShouldEmitStoreBarrier()) { 1360 if (ShouldEmitStoreBarrier()) {
1359 Register value = locs()->in(2).reg(); 1361 Register value = locs()->in(2).reg();
1360 __ StoreIntoObject(array, element_address, value); 1362 __ StoreIntoObject(array, element_address, value);
1361 } else if (locs()->in(2).IsConstant()) { 1363 } else if (locs()->in(2).IsConstant()) {
1362 const Object& constant = locs()->in(2).constant(); 1364 const Object& constant = locs()->in(2).constant();
1363 __ StoreObject(element_address, constant); 1365 __ StoreObject(element_address, constant, PP);
1364 } else { 1366 } else {
1365 Register value = locs()->in(2).reg(); 1367 Register value = locs()->in(2).reg();
1366 __ StoreIntoObjectNoBarrier(array, element_address, value); 1368 __ StoreIntoObjectNoBarrier(array, element_address, value);
1367 } 1369 }
1368 break; 1370 break;
1369 case kTypedDataInt8ArrayCid: 1371 case kTypedDataInt8ArrayCid:
1370 case kTypedDataUint8ArrayCid: 1372 case kTypedDataUint8ArrayCid:
1371 case kExternalTypedDataUint8ArrayCid: 1373 case kExternalTypedDataUint8ArrayCid:
1372 case kOneByteStringCid: 1374 case kOneByteStringCid:
1373 if (locs()->in(2).IsConstant()) { 1375 if (locs()->in(2).IsConstant()) {
(...skipping 16 matching lines...) Expand all
1390 value = 0xFF; 1392 value = 0xFF;
1391 } else if (value < 0) { 1393 } else if (value < 0) {
1392 value = 0; 1394 value = 0;
1393 } 1395 }
1394 __ movb(element_address, 1396 __ movb(element_address,
1395 Immediate(static_cast<int8_t>(value))); 1397 Immediate(static_cast<int8_t>(value)));
1396 } else { 1398 } else {
1397 ASSERT(locs()->in(2).reg() == RAX); 1399 ASSERT(locs()->in(2).reg() == RAX);
1398 Label store_value, store_0xff; 1400 Label store_value, store_0xff;
1399 __ SmiUntag(RAX); 1401 __ SmiUntag(RAX);
1400 __ cmpq(RAX, Immediate(0xFF)); 1402 __ CompareImmediate(RAX, Immediate(0xFF), PP);
1401 __ j(BELOW_EQUAL, &store_value, Assembler::kNearJump); 1403 __ j(BELOW_EQUAL, &store_value, Assembler::kNearJump);
1402 // Clamp to 0x0 or 0xFF respectively. 1404 // Clamp to 0x0 or 0xFF respectively.
1403 __ j(GREATER, &store_0xff); 1405 __ j(GREATER, &store_0xff);
1404 __ xorq(RAX, RAX); 1406 __ xorq(RAX, RAX);
1405 __ jmp(&store_value, Assembler::kNearJump); 1407 __ jmp(&store_value, Assembler::kNearJump);
1406 __ Bind(&store_0xff); 1408 __ Bind(&store_0xff);
1407 __ movq(RAX, Immediate(0xFF)); 1409 __ LoadImmediate(RAX, Immediate(0xFF), PP);
1408 __ Bind(&store_value); 1410 __ Bind(&store_value);
1409 __ movb(element_address, RAX); 1411 __ movb(element_address, RAX);
1410 } 1412 }
1411 break; 1413 break;
1412 } 1414 }
1413 case kTypedDataInt16ArrayCid: 1415 case kTypedDataInt16ArrayCid:
1414 case kTypedDataUint16ArrayCid: { 1416 case kTypedDataUint16ArrayCid: {
1415 Register value = locs()->in(2).reg(); 1417 Register value = locs()->in(2).reg();
1416 __ SmiUntag(value); 1418 __ SmiUntag(value);
1417 __ movw(element_address, value); 1419 __ movw(element_address, value);
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
1531 1533
1532 Label skip_length_check; 1534 Label skip_length_check;
1533 __ cmpq(value_cid_reg, field_cid_operand); 1535 __ cmpq(value_cid_reg, field_cid_operand);
1534 __ j(NOT_EQUAL, &skip_length_check); 1536 __ j(NOT_EQUAL, &skip_length_check);
1535 if (field_has_length) { 1537 if (field_has_length) {
1536 // Field guard may have remembered list length, check it. 1538 // Field guard may have remembered list length, check it.
1537 if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) { 1539 if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) {
1538 __ pushq(value_cid_reg); 1540 __ pushq(value_cid_reg);
1539 __ movq(value_cid_reg, 1541 __ movq(value_cid_reg,
1540 FieldAddress(value_reg, Array::length_offset())); 1542 FieldAddress(value_reg, Array::length_offset()));
1541 __ cmpq(value_cid_reg, Immediate(Smi::RawValue(field_length))); 1543 __ CompareImmediate(
1544 value_cid_reg, Immediate(Smi::RawValue(field_length)), PP);
1542 __ popq(value_cid_reg); 1545 __ popq(value_cid_reg);
1543 } else if (RawObject::IsTypedDataClassId(field_cid)) { 1546 } else if (RawObject::IsTypedDataClassId(field_cid)) {
1544 __ pushq(value_cid_reg); 1547 __ pushq(value_cid_reg);
1545 __ movq(value_cid_reg, 1548 __ movq(value_cid_reg,
1546 FieldAddress(value_reg, TypedData::length_offset())); 1549 FieldAddress(value_reg, TypedData::length_offset()));
1547 __ cmpq(value_cid_reg, Immediate(Smi::RawValue(field_length))); 1550 __ CompareImmediate(
1551 value_cid_reg, Immediate(Smi::RawValue(field_length)), PP);
1548 __ popq(value_cid_reg); 1552 __ popq(value_cid_reg);
1549 } else { 1553 } else {
1550 ASSERT(field_cid == kIllegalCid); 1554 ASSERT(field_cid == kIllegalCid);
1551 ASSERT(field_length == Field::kUnknownFixedLength); 1555 ASSERT(field_length == Field::kUnknownFixedLength);
1552 // At compile time we do not know the type of the field nor its 1556 // At compile time we do not know the type of the field nor its
1553 // length. At execution time we may have set the class id and 1557 // length. At execution time we may have set the class id and
1554 // list length so we compare the guarded length with the 1558 // list length so we compare the guarded length with the
1555 // list length here, without this check the list length could change 1559 // list length here, without this check the list length could change
1556 // without triggering a deoptimization. 1560 // without triggering a deoptimization.
1557 Label check_array, length_compared, no_fixed_length; 1561 Label check_array, length_compared, no_fixed_length;
1558 // If length is negative the length guard is either disabled or 1562 // If length is negative the length guard is either disabled or
1559 // has not been initialized, either way it is safe to skip the 1563 // has not been initialized, either way it is safe to skip the
1560 // length check. 1564 // length check.
1561 __ cmpq(field_length_operand, Immediate(Smi::RawValue(0))); 1565 __ CompareImmediate(
1566 field_length_operand, Immediate(Smi::RawValue(0)), PP);
1562 __ j(LESS, &skip_length_check); 1567 __ j(LESS, &skip_length_check);
1563 __ cmpq(value_cid_reg, Immediate(kNullCid)); 1568 __ CompareImmediate(value_cid_reg, Immediate(kNullCid), PP);
1564 __ j(EQUAL, &no_fixed_length, Assembler::kNearJump); 1569 __ j(EQUAL, &no_fixed_length, Assembler::kNearJump);
1565 // Check for typed data array. 1570 // Check for typed data array.
1566 __ cmpq(value_cid_reg, Immediate(kTypedDataFloat32x4ArrayCid)); 1571 __ CompareImmediate(
1572 value_cid_reg, Immediate(kTypedDataFloat32x4ArrayCid), PP);
1567 // Not a typed array or a regular array. 1573 // Not a typed array or a regular array.
1568 __ j(GREATER, &no_fixed_length, Assembler::kNearJump); 1574 __ j(GREATER, &no_fixed_length, Assembler::kNearJump);
1569 __ cmpq(value_cid_reg, Immediate(kTypedDataInt8ArrayCid)); 1575 __ CompareImmediate(
1576 value_cid_reg, Immediate(kTypedDataInt8ArrayCid), PP);
1570 // Could still be a regular array. 1577 // Could still be a regular array.
1571 __ j(LESS, &check_array, Assembler::kNearJump); 1578 __ j(LESS, &check_array, Assembler::kNearJump);
1572 __ pushq(value_cid_reg); 1579 __ pushq(value_cid_reg);
1573 __ movq(value_cid_reg, 1580 __ movq(value_cid_reg,
1574 FieldAddress(value_reg, TypedData::length_offset())); 1581 FieldAddress(value_reg, TypedData::length_offset()));
1575 __ cmpq(field_length_operand, value_cid_reg); 1582 __ cmpq(field_length_operand, value_cid_reg);
1576 __ popq(value_cid_reg); 1583 __ popq(value_cid_reg);
1577 __ jmp(&length_compared, Assembler::kNearJump); 1584 __ jmp(&length_compared, Assembler::kNearJump);
1578 // Check for regular array. 1585 // Check for regular array.
1579 __ Bind(&check_array); 1586 __ Bind(&check_array);
1580 __ cmpq(value_cid_reg, Immediate(kImmutableArrayCid)); 1587 __ CompareImmediate(value_cid_reg, Immediate(kImmutableArrayCid), PP);
1581 __ j(GREATER, &no_fixed_length, Assembler::kNearJump); 1588 __ j(GREATER, &no_fixed_length, Assembler::kNearJump);
1582 __ cmpq(value_cid_reg, Immediate(kArrayCid)); 1589 __ CompareImmediate(value_cid_reg, Immediate(kArrayCid), PP);
1583 __ j(LESS, &no_fixed_length, Assembler::kNearJump); 1590 __ j(LESS, &no_fixed_length, Assembler::kNearJump);
1584 __ pushq(value_cid_reg); 1591 __ pushq(value_cid_reg);
1585 __ movq(value_cid_reg, 1592 __ movq(value_cid_reg,
1586 FieldAddress(value_reg, Array::length_offset())); 1593 FieldAddress(value_reg, Array::length_offset()));
1587 __ cmpq(field_length_operand, value_cid_reg); 1594 __ cmpq(field_length_operand, value_cid_reg);
1588 __ popq(value_cid_reg); 1595 __ popq(value_cid_reg);
1589 __ jmp(&length_compared, Assembler::kNearJump); 1596 __ jmp(&length_compared, Assembler::kNearJump);
1590 __ Bind(&no_fixed_length); 1597 __ Bind(&no_fixed_length);
1591 __ jmp(fail); 1598 __ jmp(fail);
1592 __ Bind(&length_compared); 1599 __ Bind(&length_compared);
1593 } 1600 }
1594 __ j(NOT_EQUAL, fail); 1601 __ j(NOT_EQUAL, fail);
1595 } 1602 }
1596 __ Bind(&skip_length_check); 1603 __ Bind(&skip_length_check);
1597 __ cmpq(value_cid_reg, field_nullability_operand); 1604 __ cmpq(value_cid_reg, field_nullability_operand);
1598 } else if (value_cid == kNullCid) { 1605 } else if (value_cid == kNullCid) {
1599 __ cmpq(field_nullability_operand, Immediate(value_cid)); 1606 __ CompareImmediate(field_nullability_operand, Immediate(value_cid), PP);
1600 } else { 1607 } else {
1601 Label skip_length_check; 1608 Label skip_length_check;
1602 __ cmpq(field_cid_operand, Immediate(value_cid)); 1609 __ CompareImmediate(field_cid_operand, Immediate(value_cid), PP);
1603 // If not equal, skip over length check. 1610 // If not equal, skip over length check.
1604 __ j(NOT_EQUAL, &skip_length_check); 1611 __ j(NOT_EQUAL, &skip_length_check);
1605 // Insert length check. 1612 // Insert length check.
1606 if (field_has_length) { 1613 if (field_has_length) {
1607 ASSERT(value_cid_reg != kNoRegister); 1614 ASSERT(value_cid_reg != kNoRegister);
1608 if ((value_cid == kArrayCid) || (value_cid == kImmutableArrayCid)) { 1615 if ((value_cid == kArrayCid) || (value_cid == kImmutableArrayCid)) {
1609 __ cmpq(FieldAddress(value_reg, Array::length_offset()), 1616 __ CompareImmediate(FieldAddress(value_reg, Array::length_offset()),
1610 Immediate(Smi::RawValue(field_length))); 1617 Immediate(Smi::RawValue(field_length)), PP);
1611 } else if (RawObject::IsTypedDataClassId(value_cid)) { 1618 } else if (RawObject::IsTypedDataClassId(value_cid)) {
1612 __ cmpq(FieldAddress(value_reg, TypedData::length_offset()), 1619 __ CompareImmediate(
1613 Immediate(Smi::RawValue(field_length))); 1620 FieldAddress(value_reg, TypedData::length_offset()),
1621 Immediate(Smi::RawValue(field_length)), PP);
1614 } else if (field_cid != kIllegalCid) { 1622 } else if (field_cid != kIllegalCid) {
1615 ASSERT(field_cid != value_cid); 1623 ASSERT(field_cid != value_cid);
1616 ASSERT(field_length >= 0); 1624 ASSERT(field_length >= 0);
1617 // Field has a known class id and length. At compile time it is 1625 // Field has a known class id and length. At compile time it is
1618 // known that the value's class id is not a fixed length list. 1626 // known that the value's class id is not a fixed length list.
1619 __ jmp(fail); 1627 __ jmp(fail);
1620 } else { 1628 } else {
1621 ASSERT(field_cid == kIllegalCid); 1629 ASSERT(field_cid == kIllegalCid);
1622 ASSERT(field_length == Field::kUnknownFixedLength); 1630 ASSERT(field_length == Field::kUnknownFixedLength);
1623 // Following jump cannot not occur, fall through. 1631 // Following jump cannot not occur, fall through.
1624 } 1632 }
1625 __ j(NOT_EQUAL, fail); 1633 __ j(NOT_EQUAL, fail);
1626 } 1634 }
1627 // Not identical, possibly null. 1635 // Not identical, possibly null.
1628 __ Bind(&skip_length_check); 1636 __ Bind(&skip_length_check);
1629 } 1637 }
1630 __ j(EQUAL, &ok); 1638 __ j(EQUAL, &ok);
1631 1639
1632 __ cmpq(field_cid_operand, Immediate(kIllegalCid)); 1640 __ CompareImmediate(field_cid_operand, Immediate(kIllegalCid), PP);
1633 __ j(NOT_EQUAL, fail); 1641 __ j(NOT_EQUAL, fail);
1634 1642
1635 if (value_cid == kDynamicCid) { 1643 if (value_cid == kDynamicCid) {
1636 __ movq(field_cid_operand, value_cid_reg); 1644 __ movq(field_cid_operand, value_cid_reg);
1637 __ movq(field_nullability_operand, value_cid_reg); 1645 __ movq(field_nullability_operand, value_cid_reg);
1638 if (field_has_length) { 1646 if (field_has_length) {
1639 Label check_array, length_set, no_fixed_length; 1647 Label check_array, length_set, no_fixed_length;
1640 __ cmpq(value_cid_reg, Immediate(kNullCid)); 1648 __ CompareImmediate(value_cid_reg, Immediate(kNullCid), PP);
1641 __ j(EQUAL, &no_fixed_length, Assembler::kNearJump); 1649 __ j(EQUAL, &no_fixed_length, Assembler::kNearJump);
1642 // Check for typed data array. 1650 // Check for typed data array.
1643 __ cmpq(value_cid_reg, Immediate(kTypedDataFloat32x4ArrayCid)); 1651 __ CompareImmediate(value_cid_reg,
1652 Immediate(kTypedDataFloat32x4ArrayCid), PP);
1644 // Not a typed array or a regular array. 1653 // Not a typed array or a regular array.
1645 __ j(GREATER, &no_fixed_length); 1654 __ j(GREATER, &no_fixed_length);
1646 __ cmpq(value_cid_reg, Immediate(kTypedDataInt8ArrayCid)); 1655 __ CompareImmediate(
1656 value_cid_reg, Immediate(kTypedDataInt8ArrayCid), PP);
1647 // Could still be a regular array. 1657 // Could still be a regular array.
1648 __ j(LESS, &check_array, Assembler::kNearJump); 1658 __ j(LESS, &check_array, Assembler::kNearJump);
1649 // Destroy value_cid_reg (safe because we are finished with it). 1659 // Destroy value_cid_reg (safe because we are finished with it).
1650 __ movq(value_cid_reg, 1660 __ movq(value_cid_reg,
1651 FieldAddress(value_reg, TypedData::length_offset())); 1661 FieldAddress(value_reg, TypedData::length_offset()));
1652 __ movq(field_length_operand, value_cid_reg); 1662 __ movq(field_length_operand, value_cid_reg);
1653 // Updated field length typed data array. 1663 // Updated field length typed data array.
1654 __ jmp(&length_set); 1664 __ jmp(&length_set);
1655 // Check for regular array. 1665 // Check for regular array.
1656 __ Bind(&check_array); 1666 __ Bind(&check_array);
1657 __ cmpq(value_cid_reg, Immediate(kImmutableArrayCid)); 1667 __ CompareImmediate(value_cid_reg, Immediate(kImmutableArrayCid), PP);
1658 __ j(GREATER, &no_fixed_length, Assembler::kNearJump); 1668 __ j(GREATER, &no_fixed_length, Assembler::kNearJump);
1659 __ cmpq(value_cid_reg, Immediate(kArrayCid)); 1669 __ CompareImmediate(value_cid_reg, Immediate(kArrayCid), PP);
1660 __ j(LESS, &no_fixed_length, Assembler::kNearJump); 1670 __ j(LESS, &no_fixed_length, Assembler::kNearJump);
1661 // Destroy value_cid_reg (safe because we are finished with it). 1671 // Destroy value_cid_reg (safe because we are finished with it).
1662 __ movq(value_cid_reg, 1672 __ movq(value_cid_reg,
1663 FieldAddress(value_reg, Array::length_offset())); 1673 FieldAddress(value_reg, Array::length_offset()));
1664 __ movq(field_length_operand, value_cid_reg); 1674 __ movq(field_length_operand, value_cid_reg);
1665 // Updated field length from regular array. 1675 // Updated field length from regular array.
1666 __ jmp(&length_set, Assembler::kNearJump); 1676 __ jmp(&length_set, Assembler::kNearJump);
1667 __ Bind(&no_fixed_length); 1677 __ Bind(&no_fixed_length);
1668 __ movq(field_length_operand, 1678 __ LoadImmediate(field_length_operand,
1669 Immediate(Smi::RawValue(Field::kNoFixedLength))); 1679 Immediate(Smi::RawValue(Field::kNoFixedLength)), PP);
1670 __ Bind(&length_set); 1680 __ Bind(&length_set);
1671 } 1681 }
1672 } else { 1682 } else {
1673 ASSERT(field_reg != kNoRegister); 1683 ASSERT(field_reg != kNoRegister);
1674 __ movq(field_cid_operand, Immediate(value_cid)); 1684 __ LoadImmediate(field_cid_operand, Immediate(value_cid), PP);
1675 __ movq(field_nullability_operand, Immediate(value_cid)); 1685 __ LoadImmediate(field_nullability_operand, Immediate(value_cid), PP);
1676 if (field_has_length) { 1686 if (field_has_length) {
1677 ASSERT(value_cid_reg != kNoRegister); 1687 ASSERT(value_cid_reg != kNoRegister);
1678 if ((value_cid == kArrayCid) || (value_cid == kImmutableArrayCid)) { 1688 if ((value_cid == kArrayCid) || (value_cid == kImmutableArrayCid)) {
1679 // Destroy value_cid_reg (safe because we are finished with it). 1689 // Destroy value_cid_reg (safe because we are finished with it).
1680 __ movq(value_cid_reg, 1690 __ movq(value_cid_reg,
1681 FieldAddress(value_reg, Array::length_offset())); 1691 FieldAddress(value_reg, Array::length_offset()));
1682 __ movq(field_length_operand, value_cid_reg); 1692 __ movq(field_length_operand, value_cid_reg);
1683 } else if (RawObject::IsTypedDataClassId(value_cid)) { 1693 } else if (RawObject::IsTypedDataClassId(value_cid)) {
1684 // Destroy value_cid_reg (safe because we are finished with it). 1694 // Destroy value_cid_reg (safe because we are finished with it).
1685 __ movq(value_cid_reg, 1695 __ movq(value_cid_reg,
1686 FieldAddress(value_reg, TypedData::length_offset())); 1696 FieldAddress(value_reg, TypedData::length_offset()));
1687 __ movq(field_length_operand, value_cid_reg); 1697 __ movq(field_length_operand, value_cid_reg);
1688 } else { 1698 } else {
1689 __ movq(field_length_operand, 1699 __ LoadImmediate(field_length_operand,
1690 Immediate(Smi::RawValue(Field::kNoFixedLength))); 1700 Immediate(Smi::RawValue(Field::kNoFixedLength)), PP);
1691 } 1701 }
1692 } 1702 }
1693 } 1703 }
1694 if (!ok_is_fall_through) { 1704 if (!ok_is_fall_through) {
1695 __ jmp(&ok); 1705 __ jmp(&ok);
1696 } 1706 }
1697 } else { 1707 } else {
1698 if (field_reg != kNoRegister) { 1708 if (field_reg != kNoRegister) {
1699 __ LoadObject(field_reg, Field::ZoneHandle(field().raw()), PP); 1709 __ LoadObject(field_reg, Field::ZoneHandle(field().raw()), PP);
1700 } 1710 }
1701 1711
1702 if (value_cid == kDynamicCid) { 1712 if (value_cid == kDynamicCid) {
1703 // Field's guarded class id is fixed but value's class id is not known. 1713 // Field's guarded class id is fixed but value's class id is not known.
1704 __ testq(value_reg, Immediate(kSmiTagMask)); 1714 __ testq(value_reg, Immediate(kSmiTagMask));
1705 1715
1706 if (field_cid != kSmiCid) { 1716 if (field_cid != kSmiCid) {
1707 __ j(ZERO, fail); 1717 __ j(ZERO, fail);
1708 __ LoadClassId(value_cid_reg, value_reg); 1718 __ LoadClassId(value_cid_reg, value_reg);
1709 __ cmpq(value_cid_reg, Immediate(field_cid)); 1719 __ CompareImmediate(value_cid_reg, Immediate(field_cid), PP);
1710 } 1720 }
1711 1721
1712 if (field_has_length) { 1722 if (field_has_length) {
1713 // Jump when Value CID != Field guard CID 1723 // Jump when Value CID != Field guard CID
1714 __ j(NOT_EQUAL, fail); 1724 __ j(NOT_EQUAL, fail);
1715 1725
1716 // Classes are same, perform guarded list length check. 1726 // Classes are same, perform guarded list length check.
1717 ASSERT(field_reg != kNoRegister); 1727 ASSERT(field_reg != kNoRegister);
1718 ASSERT(value_cid_reg != kNoRegister); 1728 ASSERT(value_cid_reg != kNoRegister);
1719 FieldAddress field_length_operand( 1729 FieldAddress field_length_operand(
1720 field_reg, Field::guarded_list_length_offset()); 1730 field_reg, Field::guarded_list_length_offset());
1721 if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) { 1731 if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) {
1722 // Destroy value_cid_reg (safe because we are finished with it). 1732 // Destroy value_cid_reg (safe because we are finished with it).
1723 __ movq(value_cid_reg, 1733 __ movq(value_cid_reg,
1724 FieldAddress(value_reg, Array::length_offset())); 1734 FieldAddress(value_reg, Array::length_offset()));
1725 } else if (RawObject::IsTypedDataClassId(field_cid)) { 1735 } else if (RawObject::IsTypedDataClassId(field_cid)) {
1726 // Destroy value_cid_reg (safe because we are finished with it). 1736 // Destroy value_cid_reg (safe because we are finished with it).
1727 __ movq(value_cid_reg, 1737 __ movq(value_cid_reg,
1728 FieldAddress(value_reg, TypedData::length_offset())); 1738 FieldAddress(value_reg, TypedData::length_offset()));
1729 } 1739 }
1730 __ cmpq(value_cid_reg, field_length_operand); 1740 __ cmpq(value_cid_reg, field_length_operand);
1731 } 1741 }
1732 1742
1733 if (field().is_nullable() && (field_cid != kNullCid)) { 1743 if (field().is_nullable() && (field_cid != kNullCid)) {
1734 __ j(EQUAL, &ok); 1744 __ j(EQUAL, &ok);
1735 __ CompareObject(value_reg, Object::null_object()); 1745 __ CompareObject(value_reg, Object::null_object(), PP);
1736 } 1746 }
1737 1747
1738 if (ok_is_fall_through) { 1748 if (ok_is_fall_through) {
1739 __ j(NOT_EQUAL, fail); 1749 __ j(NOT_EQUAL, fail);
1740 } else { 1750 } else {
1741 __ j(EQUAL, &ok); 1751 __ j(EQUAL, &ok);
1742 } 1752 }
1743 } else { 1753 } else {
1744 // Both value's and field's class id is known. 1754 // Both value's and field's class id is known.
1745 if ((value_cid != field_cid) && (value_cid != nullability)) { 1755 if ((value_cid != field_cid) && (value_cid != nullability)) {
1746 if (ok_is_fall_through) { 1756 if (ok_is_fall_through) {
1747 __ jmp(fail); 1757 __ jmp(fail);
1748 } 1758 }
1749 } else if (field_has_length && (value_cid == field_cid)) { 1759 } else if (field_has_length && (value_cid == field_cid)) {
1750 ASSERT(value_cid_reg != kNoRegister); 1760 ASSERT(value_cid_reg != kNoRegister);
1751 if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) { 1761 if ((field_cid == kArrayCid) || (field_cid == kImmutableArrayCid)) {
1752 // Destroy value_cid_reg (safe because we are finished with it). 1762 // Destroy value_cid_reg (safe because we are finished with it).
1753 __ movq(value_cid_reg, 1763 __ movq(value_cid_reg,
1754 FieldAddress(value_reg, Array::length_offset())); 1764 FieldAddress(value_reg, Array::length_offset()));
1755 } else if (RawObject::IsTypedDataClassId(field_cid)) { 1765 } else if (RawObject::IsTypedDataClassId(field_cid)) {
1756 // Destroy value_cid_reg (safe because we are finished with it). 1766 // Destroy value_cid_reg (safe because we are finished with it).
1757 __ movq(value_cid_reg, 1767 __ movq(value_cid_reg,
1758 FieldAddress(value_reg, TypedData::length_offset())); 1768 FieldAddress(value_reg, TypedData::length_offset()));
1759 } 1769 }
1760 __ cmpq(value_cid_reg, Immediate(Smi::RawValue(field_length))); 1770 __ CompareImmediate(
1771 value_cid_reg, Immediate(Smi::RawValue(field_length)), PP);
1761 if (ok_is_fall_through) { 1772 if (ok_is_fall_through) {
1762 __ j(NOT_EQUAL, fail); 1773 __ j(NOT_EQUAL, fail);
1763 } 1774 }
1764 } else { 1775 } else {
1765 // Nothing to emit. 1776 // Nothing to emit.
1766 ASSERT(!compiler->is_optimizing()); 1777 ASSERT(!compiler->is_optimizing());
1767 return; 1778 return;
1768 } 1779 }
1769 } 1780 }
1770 } 1781 }
1771 1782
1772 if (deopt == NULL) { 1783 if (deopt == NULL) {
1773 ASSERT(!compiler->is_optimizing()); 1784 ASSERT(!compiler->is_optimizing());
1774 __ Bind(fail); 1785 __ Bind(fail);
1775 1786
1776 __ cmpq(FieldAddress(field_reg, Field::guarded_cid_offset()), 1787 __ CompareImmediate(FieldAddress(field_reg, Field::guarded_cid_offset()),
1777 Immediate(kDynamicCid)); 1788 Immediate(kDynamicCid), PP);
1778 __ j(EQUAL, &ok); 1789 __ j(EQUAL, &ok);
1779 1790
1780 __ pushq(field_reg); 1791 __ pushq(field_reg);
1781 __ pushq(value_reg); 1792 __ pushq(value_reg);
1782 __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2); 1793 __ CallRuntime(kUpdateFieldCidRuntimeEntry, 2);
1783 __ Drop(2); // Drop the field and the value. 1794 __ Drop(2); // Drop the field and the value.
1784 } 1795 }
1785 1796
1786 __ Bind(&ok); 1797 __ Bind(&ok);
1787 } 1798 }
(...skipping 16 matching lines...) Expand all
1804 Register instance_reg = locs()->in(0).reg(); 1815 Register instance_reg = locs()->in(0).reg();
1805 if (ShouldEmitStoreBarrier()) { 1816 if (ShouldEmitStoreBarrier()) {
1806 Register value_reg = locs()->in(1).reg(); 1817 Register value_reg = locs()->in(1).reg();
1807 __ StoreIntoObject(instance_reg, 1818 __ StoreIntoObject(instance_reg,
1808 FieldAddress(instance_reg, field().Offset()), 1819 FieldAddress(instance_reg, field().Offset()),
1809 value_reg, 1820 value_reg,
1810 CanValueBeSmi()); 1821 CanValueBeSmi());
1811 } else { 1822 } else {
1812 if (locs()->in(1).IsConstant()) { 1823 if (locs()->in(1).IsConstant()) {
1813 __ StoreObject(FieldAddress(instance_reg, field().Offset()), 1824 __ StoreObject(FieldAddress(instance_reg, field().Offset()),
1814 locs()->in(1).constant()); 1825 locs()->in(1).constant(), PP);
1815 } else { 1826 } else {
1816 Register value_reg = locs()->in(1).reg(); 1827 Register value_reg = locs()->in(1).reg();
1817 __ StoreIntoObjectNoBarrier(instance_reg, 1828 __ StoreIntoObjectNoBarrier(instance_reg,
1818 FieldAddress(instance_reg, field().Offset()), value_reg); 1829 FieldAddress(instance_reg, field().Offset()), value_reg);
1819 } 1830 }
1820 } 1831 }
1821 } 1832 }
1822 1833
1823 1834
1824 LocationSummary* LoadStaticFieldInstr::MakeLocationSummary() const { 1835 LocationSummary* LoadStaticFieldInstr::MakeLocationSummary() const {
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
1902 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); 1913 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
1903 locs->set_in(0, Location::RegisterLocation(RBX)); 1914 locs->set_in(0, Location::RegisterLocation(RBX));
1904 locs->set_out(Location::RegisterLocation(RAX)); 1915 locs->set_out(Location::RegisterLocation(RAX));
1905 return locs; 1916 return locs;
1906 } 1917 }
1907 1918
1908 1919
1909 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1920 void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1910 // Allocate the array. R10 = length, RBX = element type. 1921 // Allocate the array. R10 = length, RBX = element type.
1911 ASSERT(locs()->in(0).reg() == RBX); 1922 ASSERT(locs()->in(0).reg() == RBX);
1912 __ movq(R10, Immediate(Smi::RawValue(num_elements()))); 1923 __ LoadImmediate(R10, Immediate(Smi::RawValue(num_elements())), PP);
1913 compiler->GenerateCall(token_pos(), 1924 compiler->GenerateCall(token_pos(),
1914 &StubCode::AllocateArrayLabel(), 1925 &StubCode::AllocateArrayLabel(),
1915 PcDescriptors::kOther, 1926 PcDescriptors::kOther,
1916 locs()); 1927 locs());
1917 ASSERT(locs()->out().reg() == RAX); 1928 ASSERT(locs()->out().reg() == RAX);
1918 } 1929 }
1919 1930
1920 1931
1921 LocationSummary* 1932 LocationSummary*
1922 AllocateObjectWithBoundsCheckInstr::MakeLocationSummary() const { 1933 AllocateObjectWithBoundsCheckInstr::MakeLocationSummary() const {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1963 } 1974 }
1964 1975
1965 1976
1966 void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 1977 void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
1967 Register instantiator_reg = locs()->in(0).reg(); 1978 Register instantiator_reg = locs()->in(0).reg();
1968 Register result_reg = locs()->out().reg(); 1979 Register result_reg = locs()->out().reg();
1969 1980
1970 // 'instantiator_reg' is the instantiator AbstractTypeArguments object 1981 // 'instantiator_reg' is the instantiator AbstractTypeArguments object
1971 // (or null). 1982 // (or null).
1972 // A runtime call to instantiate the type is required. 1983 // A runtime call to instantiate the type is required.
1973 __ PushObject(Object::ZoneHandle()); // Make room for the result. 1984 __ PushObject(Object::ZoneHandle(), PP); // Make room for the result.
1974 __ PushObject(type()); 1985 __ PushObject(type(), PP);
1975 __ pushq(instantiator_reg); // Push instantiator type arguments. 1986 __ pushq(instantiator_reg); // Push instantiator type arguments.
1976 compiler->GenerateCallRuntime(token_pos(), 1987 compiler->GenerateCallRuntime(token_pos(),
1977 deopt_id(), 1988 deopt_id(),
1978 kInstantiateTypeRuntimeEntry, 1989 kInstantiateTypeRuntimeEntry,
1979 2, 1990 2,
1980 locs()); 1991 locs());
1981 __ Drop(2); // Drop instantiator and uninstantiated type. 1992 __ Drop(2); // Drop instantiator and uninstantiated type.
1982 __ popq(result_reg); // Pop instantiated type. 1993 __ popq(result_reg); // Pop instantiated type.
1983 ASSERT(instantiator_reg == result_reg); 1994 ASSERT(instantiator_reg == result_reg);
1984 } 1995 }
(...skipping 19 matching lines...) Expand all
2004 // (or null). 2015 // (or null).
2005 ASSERT(!type_arguments().IsUninstantiatedIdentity() && 2016 ASSERT(!type_arguments().IsUninstantiatedIdentity() &&
2006 !type_arguments().CanShareInstantiatorTypeArguments( 2017 !type_arguments().CanShareInstantiatorTypeArguments(
2007 instantiator_class())); 2018 instantiator_class()));
2008 // If the instantiator is null and if the type argument vector 2019 // If the instantiator is null and if the type argument vector
2009 // instantiated from null becomes a vector of dynamic, then use null as 2020 // instantiated from null becomes a vector of dynamic, then use null as
2010 // the type arguments. 2021 // the type arguments.
2011 Label type_arguments_instantiated; 2022 Label type_arguments_instantiated;
2012 const intptr_t len = type_arguments().Length(); 2023 const intptr_t len = type_arguments().Length();
2013 if (type_arguments().IsRawInstantiatedRaw(len)) { 2024 if (type_arguments().IsRawInstantiatedRaw(len)) {
2014 __ CompareObject(instantiator_reg, Object::null_object()); 2025 __ CompareObject(instantiator_reg, Object::null_object(), PP);
2015 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); 2026 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump);
2016 } 2027 }
2017 // Instantiate non-null type arguments. 2028 // Instantiate non-null type arguments.
2018 // A runtime call to instantiate the type arguments is required. 2029 // A runtime call to instantiate the type arguments is required.
2019 __ PushObject(Object::ZoneHandle()); // Make room for the result. 2030 __ PushObject(Object::ZoneHandle(), PP); // Make room for the result.
2020 __ PushObject(type_arguments()); 2031 __ PushObject(type_arguments(), PP);
2021 __ pushq(instantiator_reg); // Push instantiator type arguments. 2032 __ pushq(instantiator_reg); // Push instantiator type arguments.
2022 compiler->GenerateCallRuntime(token_pos(), 2033 compiler->GenerateCallRuntime(token_pos(),
2023 deopt_id(), 2034 deopt_id(),
2024 kInstantiateTypeArgumentsRuntimeEntry, 2035 kInstantiateTypeArgumentsRuntimeEntry,
2025 2, 2036 2,
2026 locs()); 2037 locs());
2027 __ Drop(2); // Drop instantiator and uninstantiated type arguments. 2038 __ Drop(2); // Drop instantiator and uninstantiated type arguments.
2028 __ popq(result_reg); // Pop instantiated type arguments. 2039 __ popq(result_reg); // Pop instantiated type arguments.
2029 __ Bind(&type_arguments_instantiated); 2040 __ Bind(&type_arguments_instantiated);
2030 ASSERT(instantiator_reg == result_reg); 2041 ASSERT(instantiator_reg == result_reg);
(...skipping 22 matching lines...) Expand all
2053 // AbstractTypeArguments object (or null). 2064 // AbstractTypeArguments object (or null).
2054 ASSERT(!type_arguments().IsUninstantiatedIdentity() && 2065 ASSERT(!type_arguments().IsUninstantiatedIdentity() &&
2055 !type_arguments().CanShareInstantiatorTypeArguments( 2066 !type_arguments().CanShareInstantiatorTypeArguments(
2056 instantiator_class())); 2067 instantiator_class()));
2057 // If the instantiator is null and if the type argument vector 2068 // If the instantiator is null and if the type argument vector
2058 // instantiated from null becomes a vector of dynamic, then use null as 2069 // instantiated from null becomes a vector of dynamic, then use null as
2059 // the type arguments. 2070 // the type arguments.
2060 Label type_arguments_instantiated; 2071 Label type_arguments_instantiated;
2061 ASSERT(type_arguments().IsRawInstantiatedRaw(type_arguments().Length())); 2072 ASSERT(type_arguments().IsRawInstantiatedRaw(type_arguments().Length()));
2062 2073
2063 __ CompareObject(instantiator_reg, Object::null_object()); 2074 __ CompareObject(instantiator_reg, Object::null_object(), PP);
2064 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); 2075 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump);
2065 // Instantiate non-null type arguments. 2076 // Instantiate non-null type arguments.
2066 // In the non-factory case, we rely on the allocation stub to 2077 // In the non-factory case, we rely on the allocation stub to
2067 // instantiate the type arguments. 2078 // instantiate the type arguments.
2068 __ LoadObject(result_reg, type_arguments(), PP); 2079 __ LoadObject(result_reg, type_arguments(), PP);
2069 // result_reg: uninstantiated type arguments. 2080 // result_reg: uninstantiated type arguments.
2070 2081
2071 __ Bind(&type_arguments_instantiated); 2082 __ Bind(&type_arguments_instantiated);
2072 // result_reg: uninstantiated or instantiated type arguments. 2083 // result_reg: uninstantiated or instantiated type arguments.
2073 } 2084 }
(...skipping 21 matching lines...) Expand all
2095 ASSERT(!type_arguments().IsUninstantiatedIdentity() && 2106 ASSERT(!type_arguments().IsUninstantiatedIdentity() &&
2096 !type_arguments().CanShareInstantiatorTypeArguments( 2107 !type_arguments().CanShareInstantiatorTypeArguments(
2097 instantiator_class())); 2108 instantiator_class()));
2098 2109
2099 // If the instantiator is null and if the type argument vector 2110 // If the instantiator is null and if the type argument vector
2100 // instantiated from null becomes a vector of dynamic, then use null as 2111 // instantiated from null becomes a vector of dynamic, then use null as
2101 // the type arguments and do not pass the instantiator. 2112 // the type arguments and do not pass the instantiator.
2102 ASSERT(type_arguments().IsRawInstantiatedRaw(type_arguments().Length())); 2113 ASSERT(type_arguments().IsRawInstantiatedRaw(type_arguments().Length()));
2103 2114
2104 Label instantiator_not_null; 2115 Label instantiator_not_null;
2105 __ CompareObject(instantiator_reg, Object::null_object()); 2116 __ CompareObject(instantiator_reg, Object::null_object(), PP);
2106 __ j(NOT_EQUAL, &instantiator_not_null, Assembler::kNearJump); 2117 __ j(NOT_EQUAL, &instantiator_not_null, Assembler::kNearJump);
2107 // Null was used in VisitExtractConstructorTypeArguments as the 2118 // Null was used in VisitExtractConstructorTypeArguments as the
2108 // instantiated type arguments, no proper instantiator needed. 2119 // instantiated type arguments, no proper instantiator needed.
2109 __ movq(instantiator_reg, 2120 __ LoadImmediate(instantiator_reg,
2110 Immediate(Smi::RawValue(StubCode::kNoInstantiator))); 2121 Immediate(Smi::RawValue(StubCode::kNoInstantiator)), PP);
2111 __ Bind(&instantiator_not_null); 2122 __ Bind(&instantiator_not_null);
2112 // instantiator_reg: instantiator or kNoInstantiator. 2123 // instantiator_reg: instantiator or kNoInstantiator.
2113 } 2124 }
2114 2125
2115 2126
2116 LocationSummary* AllocateContextInstr::MakeLocationSummary() const { 2127 LocationSummary* AllocateContextInstr::MakeLocationSummary() const {
2117 const intptr_t kNumInputs = 0; 2128 const intptr_t kNumInputs = 0;
2118 const intptr_t kNumTemps = 1; 2129 const intptr_t kNumTemps = 1;
2119 LocationSummary* locs = 2130 LocationSummary* locs =
2120 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); 2131 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
2121 locs->set_temp(0, Location::RegisterLocation(R10)); 2132 locs->set_temp(0, Location::RegisterLocation(R10));
2122 locs->set_out(Location::RegisterLocation(RAX)); 2133 locs->set_out(Location::RegisterLocation(RAX));
2123 return locs; 2134 return locs;
2124 } 2135 }
2125 2136
2126 2137
2127 void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2138 void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2128 ASSERT(locs()->temp(0).reg() == R10); 2139 ASSERT(locs()->temp(0).reg() == R10);
2129 ASSERT(locs()->out().reg() == RAX); 2140 ASSERT(locs()->out().reg() == RAX);
2130 2141
2131 __ movq(R10, Immediate(num_context_variables())); 2142 __ LoadImmediate(R10, Immediate(num_context_variables()), PP);
2132 const ExternalLabel label("alloc_context", 2143 const ExternalLabel label("alloc_context",
2133 StubCode::AllocateContextEntryPoint()); 2144 StubCode::AllocateContextEntryPoint());
2134 compiler->GenerateCall(token_pos(), 2145 compiler->GenerateCall(token_pos(),
2135 &label, 2146 &label,
2136 PcDescriptors::kOther, 2147 PcDescriptors::kOther,
2137 locs()); 2148 locs());
2138 } 2149 }
2139 2150
2140 2151
2141 LocationSummary* CloneContextInstr::MakeLocationSummary() const { 2152 LocationSummary* CloneContextInstr::MakeLocationSummary() const {
2142 const intptr_t kNumInputs = 1; 2153 const intptr_t kNumInputs = 1;
2143 const intptr_t kNumTemps = 0; 2154 const intptr_t kNumTemps = 0;
2144 LocationSummary* locs = 2155 LocationSummary* locs =
2145 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall); 2156 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kCall);
2146 locs->set_in(0, Location::RegisterLocation(RAX)); 2157 locs->set_in(0, Location::RegisterLocation(RAX));
2147 locs->set_out(Location::RegisterLocation(RAX)); 2158 locs->set_out(Location::RegisterLocation(RAX));
2148 return locs; 2159 return locs;
2149 } 2160 }
2150 2161
2151 2162
2152 void CloneContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2163 void CloneContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2153 Register context_value = locs()->in(0).reg(); 2164 Register context_value = locs()->in(0).reg();
2154 Register result = locs()->out().reg(); 2165 Register result = locs()->out().reg();
2155 2166
2156 __ PushObject(Object::ZoneHandle()); // Make room for the result. 2167 __ PushObject(Object::ZoneHandle(), PP); // Make room for the result.
2157 __ pushq(context_value); 2168 __ pushq(context_value);
2158 compiler->GenerateCallRuntime(token_pos(), 2169 compiler->GenerateCallRuntime(token_pos(),
2159 deopt_id(), 2170 deopt_id(),
2160 kCloneContextRuntimeEntry, 2171 kCloneContextRuntimeEntry,
2161 1, 2172 1,
2162 locs()); 2173 locs());
2163 __ popq(result); // Remove argument. 2174 __ popq(result); // Remove argument.
2164 __ popq(result); // Get result (cloned context). 2175 __ popq(result); // Get result (cloned context).
2165 } 2176 }
2166 2177
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
2248 CheckStackOverflowInstr* instruction_; 2259 CheckStackOverflowInstr* instruction_;
2249 }; 2260 };
2250 2261
2251 2262
2252 void CheckStackOverflowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2263 void CheckStackOverflowInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2253 CheckStackOverflowSlowPath* slow_path = new CheckStackOverflowSlowPath(this); 2264 CheckStackOverflowSlowPath* slow_path = new CheckStackOverflowSlowPath(this);
2254 compiler->AddSlowPathCode(slow_path); 2265 compiler->AddSlowPathCode(slow_path);
2255 2266
2256 Register temp = locs()->temp(0).reg(); 2267 Register temp = locs()->temp(0).reg();
2257 // Generate stack overflow check. 2268 // Generate stack overflow check.
2258 __ movq(temp, Immediate(Isolate::Current()->stack_limit_address())); 2269 __ LoadImmediate(
2270 temp, Immediate(Isolate::Current()->stack_limit_address()), PP);
2259 __ cmpq(RSP, Address(temp, 0)); 2271 __ cmpq(RSP, Address(temp, 0));
2260 __ j(BELOW_EQUAL, slow_path->entry_label()); 2272 __ j(BELOW_EQUAL, slow_path->entry_label());
2261 if (compiler->CanOSRFunction() && in_loop()) { 2273 if (compiler->CanOSRFunction() && in_loop()) {
2262 // In unoptimized code check the usage counter to trigger OSR at loop 2274 // In unoptimized code check the usage counter to trigger OSR at loop
2263 // stack checks. Use progressively higher thresholds for more deeply 2275 // stack checks. Use progressively higher thresholds for more deeply
2264 // nested loops to attempt to hit outer loops with OSR when possible. 2276 // nested loops to attempt to hit outer loops with OSR when possible.
2265 __ LoadObject(temp, compiler->parsed_function().function(), PP); 2277 __ LoadObject(temp, compiler->parsed_function().function(), PP);
2266 intptr_t threshold = 2278 intptr_t threshold =
2267 FLAG_optimization_counter_threshold * (loop_depth() + 1); 2279 FLAG_optimization_counter_threshold * (loop_depth() + 1);
2268 __ cmpq(FieldAddress(temp, Function::usage_counter_offset()), 2280 __ CompareImmediate(FieldAddress(temp, Function::usage_counter_offset()),
2269 Immediate(threshold)); 2281 Immediate(threshold), PP);
2270 __ j(GREATER_EQUAL, slow_path->entry_label()); 2282 __ j(GREATER_EQUAL, slow_path->entry_label());
2271 } 2283 }
2272 __ Bind(slow_path->exit_label()); 2284 __ Bind(slow_path->exit_label());
2273 } 2285 }
2274 2286
2275 2287
2276 static void EmitJavascriptOverflowCheck(FlowGraphCompiler* compiler, 2288 static void EmitJavascriptOverflowCheck(FlowGraphCompiler* compiler,
2277 Range* range, 2289 Range* range,
2278 Label* overflow, 2290 Label* overflow,
2279 Register result) { 2291 Register result) {
2280 if (!range->IsWithin(-0x20000000000000LL, 0x20000000000000LL)) { 2292 if (!range->IsWithin(-0x20000000000000LL, 0x20000000000000LL)) {
2281 ASSERT(overflow != NULL); 2293 ASSERT(overflow != NULL);
2282 __ cmpq(result, Immediate(-0x20000000000000LL)); 2294 __ CompareImmediate(result, Immediate(-0x20000000000000LL), PP);
2283 __ j(LESS, overflow); 2295 __ j(LESS, overflow);
2284 __ cmpq(result, Immediate(0x20000000000000LL)); 2296 __ CompareImmediate(result, Immediate(0x20000000000000LL), PP);
2285 __ j(GREATER, overflow); 2297 __ j(GREATER, overflow);
2286 } 2298 }
2287 } 2299 }
2288 2300
2289 2301
2290 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler, 2302 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler,
2291 BinarySmiOpInstr* shift_left) { 2303 BinarySmiOpInstr* shift_left) {
2292 const bool is_truncating = shift_left->is_truncating(); 2304 const bool is_truncating = shift_left->is_truncating();
2293 const LocationSummary& locs = *shift_left->locs(); 2305 const LocationSummary& locs = *shift_left->locs();
2294 Register left = locs.in(0).reg(); 2306 Register left = locs.in(0).reg();
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
2335 // Right (locs.in(1)) is not constant. 2347 // Right (locs.in(1)) is not constant.
2336 Register right = locs.in(1).reg(); 2348 Register right = locs.in(1).reg();
2337 Range* right_range = shift_left->right()->definition()->range(); 2349 Range* right_range = shift_left->right()->definition()->range();
2338 if (shift_left->left()->BindsToConstant() && !is_truncating) { 2350 if (shift_left->left()->BindsToConstant() && !is_truncating) {
2339 // TODO(srdjan): Implement code below for is_truncating(). 2351 // TODO(srdjan): Implement code below for is_truncating().
2340 // If left is constant, we know the maximal allowed size for right. 2352 // If left is constant, we know the maximal allowed size for right.
2341 const Object& obj = shift_left->left()->BoundConstant(); 2353 const Object& obj = shift_left->left()->BoundConstant();
2342 if (obj.IsSmi()) { 2354 if (obj.IsSmi()) {
2343 const intptr_t left_int = Smi::Cast(obj).Value(); 2355 const intptr_t left_int = Smi::Cast(obj).Value();
2344 if (left_int == 0) { 2356 if (left_int == 0) {
2345 __ cmpq(right, Immediate(0)); 2357 __ CompareImmediate(right, Immediate(0), PP);
2346 __ j(NEGATIVE, deopt); 2358 __ j(NEGATIVE, deopt);
2347 return; 2359 return;
2348 } 2360 }
2349 const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int); 2361 const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int);
2350 const bool right_needs_check = 2362 const bool right_needs_check =
2351 (right_range == NULL) || 2363 (right_range == NULL) ||
2352 !right_range->IsWithin(0, max_right - 1); 2364 !right_range->IsWithin(0, max_right - 1);
2353 if (right_needs_check) { 2365 if (right_needs_check) {
2354 __ cmpq(right, 2366 __ CompareImmediate(right,
2355 Immediate(reinterpret_cast<int64_t>(Smi::New(max_right)))); 2367 Immediate(reinterpret_cast<int64_t>(Smi::New(max_right))), PP);
2356 __ j(ABOVE_EQUAL, deopt); 2368 __ j(ABOVE_EQUAL, deopt);
2357 } 2369 }
2358 __ SmiUntag(right); 2370 __ SmiUntag(right);
2359 __ shlq(left, right); 2371 __ shlq(left, right);
2360 } 2372 }
2361 if (FLAG_throw_on_javascript_int_overflow) { 2373 if (FLAG_throw_on_javascript_int_overflow) {
2362 EmitJavascriptOverflowCheck(compiler, shift_left->range(), deopt, result); 2374 EmitJavascriptOverflowCheck(compiler, shift_left->range(), deopt, result);
2363 } 2375 }
2364 return; 2376 return;
2365 } 2377 }
2366 2378
2367 const bool right_needs_check = 2379 const bool right_needs_check =
2368 (right_range == NULL) || !right_range->IsWithin(0, (Smi::kBits - 1)); 2380 (right_range == NULL) || !right_range->IsWithin(0, (Smi::kBits - 1));
2369 ASSERT(right == RCX); // Count must be in RCX 2381 ASSERT(right == RCX); // Count must be in RCX
2370 if (is_truncating) { 2382 if (is_truncating) {
2371 if (right_needs_check) { 2383 if (right_needs_check) {
2372 const bool right_may_be_negative = 2384 const bool right_may_be_negative =
2373 (right_range == NULL) || 2385 (right_range == NULL) ||
2374 !right_range->IsWithin(0, RangeBoundary::kPlusInfinity); 2386 !right_range->IsWithin(0, RangeBoundary::kPlusInfinity);
2375 if (right_may_be_negative) { 2387 if (right_may_be_negative) {
2376 ASSERT(shift_left->CanDeoptimize()); 2388 ASSERT(shift_left->CanDeoptimize());
2377 __ cmpq(right, Immediate(0)); 2389 __ CompareImmediate(right, Immediate(0), PP);
2378 __ j(NEGATIVE, deopt); 2390 __ j(NEGATIVE, deopt);
2379 } 2391 }
2380 Label done, is_not_zero; 2392 Label done, is_not_zero;
2381 __ cmpq(right, 2393 __ CompareImmediate(right,
2382 Immediate(reinterpret_cast<int64_t>(Smi::New(Smi::kBits)))); 2394 Immediate(reinterpret_cast<int64_t>(Smi::New(Smi::kBits))), PP);
2383 __ j(BELOW, &is_not_zero, Assembler::kNearJump); 2395 __ j(BELOW, &is_not_zero, Assembler::kNearJump);
2384 __ xorq(left, left); 2396 __ xorq(left, left);
2385 __ jmp(&done, Assembler::kNearJump); 2397 __ jmp(&done, Assembler::kNearJump);
2386 __ Bind(&is_not_zero); 2398 __ Bind(&is_not_zero);
2387 __ SmiUntag(right); 2399 __ SmiUntag(right);
2388 __ shlq(left, right); 2400 __ shlq(left, right);
2389 __ Bind(&done); 2401 __ Bind(&done);
2390 } else { 2402 } else {
2391 __ SmiUntag(right); 2403 __ SmiUntag(right);
2392 __ shlq(left, right); 2404 __ shlq(left, right);
2393 } 2405 }
2394 } else { 2406 } else {
2395 if (right_needs_check) { 2407 if (right_needs_check) {
2396 ASSERT(shift_left->CanDeoptimize()); 2408 ASSERT(shift_left->CanDeoptimize());
2397 __ cmpq(right, 2409 __ CompareImmediate(right,
2398 Immediate(reinterpret_cast<int64_t>(Smi::New(Smi::kBits)))); 2410 Immediate(reinterpret_cast<int64_t>(Smi::New(Smi::kBits))), PP);
2399 __ j(ABOVE_EQUAL, deopt); 2411 __ j(ABOVE_EQUAL, deopt);
2400 } 2412 }
2401 // Left is not a constant. 2413 // Left is not a constant.
2402 Register temp = locs.temp(0).reg(); 2414 Register temp = locs.temp(0).reg();
2403 // Check if count too large for handling it inlined. 2415 // Check if count too large for handling it inlined.
2404 __ movq(temp, left); 2416 __ movq(temp, left);
2405 __ SmiUntag(right); 2417 __ SmiUntag(right);
2406 // Overflow test (preserve temp and right); 2418 // Overflow test (preserve temp and right);
2407 __ shlq(left, right); 2419 __ shlq(left, right);
2408 __ sarq(left, right); 2420 __ sarq(left, right);
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
2511 kDeoptBinarySmiOp); 2523 kDeoptBinarySmiOp);
2512 } 2524 }
2513 2525
2514 if (locs()->in(1).IsConstant()) { 2526 if (locs()->in(1).IsConstant()) {
2515 const Object& constant = locs()->in(1).constant(); 2527 const Object& constant = locs()->in(1).constant();
2516 ASSERT(constant.IsSmi()); 2528 ASSERT(constant.IsSmi());
2517 const int64_t imm = 2529 const int64_t imm =
2518 reinterpret_cast<int64_t>(constant.raw()); 2530 reinterpret_cast<int64_t>(constant.raw());
2519 switch (op_kind()) { 2531 switch (op_kind()) {
2520 case Token::kADD: { 2532 case Token::kADD: {
2521 __ addq(left, Immediate(imm)); 2533 __ AddImmediate(left, Immediate(imm), PP);
2522 if (deopt != NULL) __ j(OVERFLOW, deopt); 2534 if (deopt != NULL) __ j(OVERFLOW, deopt);
2523 break; 2535 break;
2524 } 2536 }
2525 case Token::kSUB: { 2537 case Token::kSUB: {
2526 __ subq(left, Immediate(imm)); 2538 __ AddImmediate(left, Immediate(-imm), PP);
2527 if (deopt != NULL) __ j(OVERFLOW, deopt); 2539 if (deopt != NULL) __ j(OVERFLOW, deopt);
2528 break; 2540 break;
2529 } 2541 }
2530 case Token::kMUL: { 2542 case Token::kMUL: {
2531 // Keep left value tagged and untag right value. 2543 // Keep left value tagged and untag right value.
2532 const intptr_t value = Smi::Cast(constant).Value(); 2544 const intptr_t value = Smi::Cast(constant).Value();
2533 if (value == 2) { 2545 if (value == 2) {
2534 __ shlq(left, Immediate(1)); 2546 __ shlq(left, Immediate(1));
2535 } else { 2547 } else {
2536 __ imulq(left, Immediate(value)); 2548 __ MulImmediate(left, Immediate(value), PP);
2537 } 2549 }
2538 if (deopt != NULL) __ j(OVERFLOW, deopt); 2550 if (deopt != NULL) __ j(OVERFLOW, deopt);
2539 break; 2551 break;
2540 } 2552 }
2541 case Token::kTRUNCDIV: { 2553 case Token::kTRUNCDIV: {
2542 const intptr_t value = Smi::Cast(constant).Value(); 2554 const intptr_t value = Smi::Cast(constant).Value();
2543 if (value == 1) { 2555 if (value == 1) {
2544 // Do nothing. 2556 // Do nothing.
2545 break; 2557 break;
2546 } else if (value == -1) { 2558 } else if (value == -1) {
2547 // Check the corner case of dividing the 'MIN_SMI' with -1, in which 2559 // Check the corner case of dividing the 'MIN_SMI' with -1, in which
2548 // case we cannot negate the result. 2560 // case we cannot negate the result.
2549 __ cmpq(left, Immediate(0x8000000000000000)); 2561 __ CompareImmediate(left, Immediate(0x8000000000000000), PP);
2550 __ j(EQUAL, deopt); 2562 __ j(EQUAL, deopt);
2551 __ negq(left); 2563 __ negq(left);
2552 break; 2564 break;
2553 } 2565 }
2554 2566
2555 ASSERT(Utils::IsPowerOfTwo(Utils::Abs(value))); 2567 ASSERT(Utils::IsPowerOfTwo(Utils::Abs(value)));
2556 const intptr_t shift_count = 2568 const intptr_t shift_count =
2557 Utils::ShiftForPowerOfTwo(Utils::Abs(value)) + kSmiTagSize; 2569 Utils::ShiftForPowerOfTwo(Utils::Abs(value)) + kSmiTagSize;
2558 ASSERT(kSmiTagSize == 1); 2570 ASSERT(kSmiTagSize == 1);
2559 Register temp = locs()->temp(0).reg(); 2571 Register temp = locs()->temp(0).reg();
2560 __ movq(temp, left); 2572 __ movq(temp, left);
2561 __ sarq(temp, Immediate(63)); 2573 __ sarq(temp, Immediate(63));
2562 ASSERT(shift_count > 1); // 1, -1 case handled above. 2574 ASSERT(shift_count > 1); // 1, -1 case handled above.
2563 __ shrq(temp, Immediate(64 - shift_count)); 2575 __ shrq(temp, Immediate(64 - shift_count));
2564 __ addq(left, temp); 2576 __ addq(left, temp);
2565 ASSERT(shift_count > 0); 2577 ASSERT(shift_count > 0);
2566 __ sarq(left, Immediate(shift_count)); 2578 __ sarq(left, Immediate(shift_count));
2567 if (value < 0) { 2579 if (value < 0) {
2568 __ negq(left); 2580 __ negq(left);
2569 } 2581 }
2570 __ SmiTag(left); 2582 __ SmiTag(left);
2571 break; 2583 break;
2572 } 2584 }
2573 case Token::kBIT_AND: { 2585 case Token::kBIT_AND: {
2574 // No overflow check. 2586 // No overflow check.
2575 __ andq(left, Immediate(imm)); 2587 __ AndImmediate(left, Immediate(imm), PP);
2576 break; 2588 break;
2577 } 2589 }
2578 case Token::kBIT_OR: { 2590 case Token::kBIT_OR: {
2579 // No overflow check. 2591 // No overflow check.
2580 __ orq(left, Immediate(imm)); 2592 __ OrImmediate(left, Immediate(imm), PP);
2581 break; 2593 break;
2582 } 2594 }
2583 case Token::kBIT_XOR: { 2595 case Token::kBIT_XOR: {
2584 // No overflow check. 2596 // No overflow check.
2585 __ xorq(left, Immediate(imm)); 2597 __ XorImmediate(left, Immediate(imm), PP);
2586 break; 2598 break;
2587 } 2599 }
2588 2600
2589 case Token::kSHR: { 2601 case Token::kSHR: {
2590 // sarq operation masks the count to 6 bits. 2602 // sarq operation masks the count to 6 bits.
2591 const intptr_t kCountLimit = 0x3F; 2603 const intptr_t kCountLimit = 0x3F;
2592 intptr_t value = Smi::Cast(constant).Value(); 2604 intptr_t value = Smi::Cast(constant).Value();
2593 2605
2594 if (value == 0) { 2606 if (value == 0) {
2595 // TODO(vegorov): should be handled outside. 2607 // TODO(vegorov): should be handled outside.
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
2731 __ jmp(&done); 2743 __ jmp(&done);
2732 2744
2733 // Divide using 64bit idiv. 2745 // Divide using 64bit idiv.
2734 __ Bind(&not_32bit); 2746 __ Bind(&not_32bit);
2735 __ SmiUntag(left); 2747 __ SmiUntag(left);
2736 __ SmiUntag(right); 2748 __ SmiUntag(right);
2737 __ cqo(); // Sign extend RAX -> RDX:RAX. 2749 __ cqo(); // Sign extend RAX -> RDX:RAX.
2738 __ idivq(right); // RAX: quotient, RDX: remainder. 2750 __ idivq(right); // RAX: quotient, RDX: remainder.
2739 // Check the corner case of dividing the 'MIN_SMI' with -1, in which 2751 // Check the corner case of dividing the 'MIN_SMI' with -1, in which
2740 // case we cannot tag the result. 2752 // case we cannot tag the result.
2741 __ cmpq(result, Immediate(0x4000000000000000)); 2753 __ CompareImmediate(result, Immediate(0x4000000000000000), PP);
2742 __ j(EQUAL, deopt); 2754 __ j(EQUAL, deopt);
2743 __ Bind(&done); 2755 __ Bind(&done);
2744 __ SmiTag(result); 2756 __ SmiTag(result);
2745 break; 2757 break;
2746 } 2758 }
2747 case Token::kSHR: { 2759 case Token::kSHR: {
2748 if (CanDeoptimize()) { 2760 if (CanDeoptimize()) {
2749 __ cmpq(right, Immediate(0)); 2761 __ CompareImmediate(right, Immediate(0), PP);
2750 __ j(LESS, deopt); 2762 __ j(LESS, deopt);
2751 } 2763 }
2752 __ SmiUntag(right); 2764 __ SmiUntag(right);
2753 // sarq operation masks the count to 6 bits. 2765 // sarq operation masks the count to 6 bits.
2754 const intptr_t kCountLimit = 0x3F; 2766 const intptr_t kCountLimit = 0x3F;
2755 Range* right_range = this->right()->definition()->range(); 2767 Range* right_range = this->right()->definition()->range();
2756 if ((right_range == NULL) || 2768 if ((right_range == NULL) ||
2757 !right_range->IsWithin(RangeBoundary::kMinusInfinity, kCountLimit)) { 2769 !right_range->IsWithin(RangeBoundary::kMinusInfinity, kCountLimit)) {
2758 __ cmpq(right, Immediate(kCountLimit)); 2770 __ CompareImmediate(right, Immediate(kCountLimit), PP);
2759 Label count_ok; 2771 Label count_ok;
2760 __ j(LESS, &count_ok, Assembler::kNearJump); 2772 __ j(LESS, &count_ok, Assembler::kNearJump);
2761 __ movq(right, Immediate(kCountLimit)); 2773 __ LoadImmediate(right, Immediate(kCountLimit), PP);
2762 __ Bind(&count_ok); 2774 __ Bind(&count_ok);
2763 } 2775 }
2764 ASSERT(right == RCX); // Count must be in RCX 2776 ASSERT(right == RCX); // Count must be in RCX
2765 __ SmiUntag(left); 2777 __ SmiUntag(left);
2766 __ sarq(left, right); 2778 __ sarq(left, right);
2767 __ SmiTag(left); 2779 __ SmiTag(left);
2768 break; 2780 break;
2769 } 2781 }
2770 case Token::kDIV: { 2782 case Token::kDIV: {
2771 // Dispatches to 'Double./'. 2783 // Dispatches to 'Double./'.
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
2879 void BoxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 2891 void BoxDoubleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
2880 BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this); 2892 BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this);
2881 compiler->AddSlowPathCode(slow_path); 2893 compiler->AddSlowPathCode(slow_path);
2882 2894
2883 Register out_reg = locs()->out().reg(); 2895 Register out_reg = locs()->out().reg();
2884 XmmRegister value = locs()->in(0).fpu_reg(); 2896 XmmRegister value = locs()->in(0).fpu_reg();
2885 2897
2886 __ TryAllocate(compiler->double_class(), 2898 __ TryAllocate(compiler->double_class(),
2887 slow_path->entry_label(), 2899 slow_path->entry_label(),
2888 Assembler::kFarJump, 2900 Assembler::kFarJump,
2889 out_reg); 2901 out_reg,
2902 PP);
2890 __ Bind(slow_path->exit_label()); 2903 __ Bind(slow_path->exit_label());
2891 __ movsd(FieldAddress(out_reg, Double::value_offset()), value); 2904 __ movsd(FieldAddress(out_reg, Double::value_offset()), value);
2892 } 2905 }
2893 2906
2894 2907
2895 LocationSummary* UnboxDoubleInstr::MakeLocationSummary() const { 2908 LocationSummary* UnboxDoubleInstr::MakeLocationSummary() const {
2896 const intptr_t kNumInputs = 1; 2909 const intptr_t kNumInputs = 1;
2897 const intptr_t kNumTemps = 0; 2910 const intptr_t kNumTemps = 0;
2898 LocationSummary* summary = 2911 LocationSummary* summary =
2899 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 2912 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
2981 void BoxFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { 2994 void BoxFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
2982 BoxFloat32x4SlowPath* slow_path = new BoxFloat32x4SlowPath(this); 2995 BoxFloat32x4SlowPath* slow_path = new BoxFloat32x4SlowPath(this);
2983 compiler->AddSlowPathCode(slow_path); 2996 compiler->AddSlowPathCode(slow_path);
2984 2997
2985 Register out_reg = locs()->out().reg(); 2998 Register out_reg = locs()->out().reg();
2986 XmmRegister value = locs()->in(0).fpu_reg(); 2999 XmmRegister value = locs()->in(0).fpu_reg();
2987 3000
2988 __ TryAllocate(compiler->float32x4_class(), 3001 __ TryAllocate(compiler->float32x4_class(),
2989 slow_path->entry_label(), 3002 slow_path->entry_label(),
2990 Assembler::kFarJump, 3003 Assembler::kFarJump,
2991 out_reg); 3004 out_reg,
3005 PP);
2992 __ Bind(slow_path->exit_label()); 3006 __ Bind(slow_path->exit_label());
2993 __ movups(FieldAddress(out_reg, Float32x4::value_offset()), value); 3007 __ movups(FieldAddress(out_reg, Float32x4::value_offset()), value);
2994 } 3008 }
2995 3009
2996 3010
2997 LocationSummary* UnboxFloat32x4Instr::MakeLocationSummary() const { 3011 LocationSummary* UnboxFloat32x4Instr::MakeLocationSummary() const {
2998 const intptr_t kNumInputs = 1; 3012 const intptr_t kNumInputs = 1;
2999 return LocationSummary::Make(kNumInputs, 3013 return LocationSummary::Make(kNumInputs,
3000 Location::RequiresFpuRegister(), 3014 Location::RequiresFpuRegister(),
3001 LocationSummary::kNoCall); 3015 LocationSummary::kNoCall);
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
3066 void BoxUint32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) { 3080 void BoxUint32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
3067 BoxUint32x4SlowPath* slow_path = new BoxUint32x4SlowPath(this); 3081 BoxUint32x4SlowPath* slow_path = new BoxUint32x4SlowPath(this);
3068 compiler->AddSlowPathCode(slow_path); 3082 compiler->AddSlowPathCode(slow_path);
3069 3083
3070 Register out_reg = locs()->out().reg(); 3084 Register out_reg = locs()->out().reg();
3071 XmmRegister value = locs()->in(0).fpu_reg(); 3085 XmmRegister value = locs()->in(0).fpu_reg();
3072 3086
3073 __ TryAllocate(compiler->uint32x4_class(), 3087 __ TryAllocate(compiler->uint32x4_class(),
3074 slow_path->entry_label(), 3088 slow_path->entry_label(),
3075 Assembler::kFarJump, 3089 Assembler::kFarJump,
3076 out_reg); 3090 out_reg,
3091 PP);
3077 __ Bind(slow_path->exit_label()); 3092 __ Bind(slow_path->exit_label());
3078 __ movups(FieldAddress(out_reg, Uint32x4::value_offset()), value); 3093 __ movups(FieldAddress(out_reg, Uint32x4::value_offset()), value);
3079 } 3094 }
3080 3095
3081 3096
3082 LocationSummary* UnboxUint32x4Instr::MakeLocationSummary() const { 3097 LocationSummary* UnboxUint32x4Instr::MakeLocationSummary() const {
3083 const intptr_t kNumInputs = 1; 3098 const intptr_t kNumInputs = 1;
3084 const intptr_t kNumTemps = 0; 3099 const intptr_t kNumTemps = 0;
3085 LocationSummary* summary = 3100 LocationSummary* summary =
3086 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 3101 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
3236 return summary; 3251 return summary;
3237 } 3252 }
3238 3253
3239 3254
3240 void Float32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3255 void Float32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3241 XmmRegister v0 = locs()->in(0).fpu_reg(); 3256 XmmRegister v0 = locs()->in(0).fpu_reg();
3242 XmmRegister v1 = locs()->in(1).fpu_reg(); 3257 XmmRegister v1 = locs()->in(1).fpu_reg();
3243 XmmRegister v2 = locs()->in(2).fpu_reg(); 3258 XmmRegister v2 = locs()->in(2).fpu_reg();
3244 XmmRegister v3 = locs()->in(3).fpu_reg(); 3259 XmmRegister v3 = locs()->in(3).fpu_reg();
3245 ASSERT(v0 == locs()->out().fpu_reg()); 3260 ASSERT(v0 == locs()->out().fpu_reg());
3246 __ subq(RSP, Immediate(16)); 3261 __ AddImmediate(RSP, Immediate(-16), PP);
3247 __ cvtsd2ss(v0, v0); 3262 __ cvtsd2ss(v0, v0);
3248 __ movss(Address(RSP, 0), v0); 3263 __ movss(Address(RSP, 0), v0);
3249 __ movsd(v0, v1); 3264 __ movsd(v0, v1);
3250 __ cvtsd2ss(v0, v0); 3265 __ cvtsd2ss(v0, v0);
3251 __ movss(Address(RSP, 4), v0); 3266 __ movss(Address(RSP, 4), v0);
3252 __ movsd(v0, v2); 3267 __ movsd(v0, v2);
3253 __ cvtsd2ss(v0, v0); 3268 __ cvtsd2ss(v0, v0);
3254 __ movss(Address(RSP, 8), v0); 3269 __ movss(Address(RSP, 8), v0);
3255 __ movsd(v0, v3); 3270 __ movsd(v0, v3);
3256 __ cvtsd2ss(v0, v0); 3271 __ cvtsd2ss(v0, v0);
3257 __ movss(Address(RSP, 12), v0); 3272 __ movss(Address(RSP, 12), v0);
3258 __ movups(v0, Address(RSP, 0)); 3273 __ movups(v0, Address(RSP, 0));
3259 __ addq(RSP, Immediate(16)); 3274 __ AddImmediate(RSP, Immediate(16), PP);
3260 } 3275 }
3261 3276
3262 3277
3263 LocationSummary* Float32x4ZeroInstr::MakeLocationSummary() const { 3278 LocationSummary* Float32x4ZeroInstr::MakeLocationSummary() const {
3264 const intptr_t kNumInputs = 0; 3279 const intptr_t kNumInputs = 0;
3265 const intptr_t kNumTemps = 0; 3280 const intptr_t kNumTemps = 0;
3266 LocationSummary* summary = 3281 LocationSummary* summary =
3267 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 3282 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
3268 summary->set_out(Location::RequiresFpuRegister()); 3283 summary->set_out(Location::RequiresFpuRegister());
3269 return summary; 3284 return summary;
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after
3494 3509
3495 void Float32x4WithInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3510 void Float32x4WithInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3496 XmmRegister replacement = locs()->in(0).fpu_reg(); 3511 XmmRegister replacement = locs()->in(0).fpu_reg();
3497 XmmRegister value = locs()->in(1).fpu_reg(); 3512 XmmRegister value = locs()->in(1).fpu_reg();
3498 3513
3499 ASSERT(locs()->out().fpu_reg() == replacement); 3514 ASSERT(locs()->out().fpu_reg() == replacement);
3500 3515
3501 switch (op_kind()) { 3516 switch (op_kind()) {
3502 case MethodRecognizer::kFloat32x4WithX: 3517 case MethodRecognizer::kFloat32x4WithX:
3503 __ cvtsd2ss(replacement, replacement); 3518 __ cvtsd2ss(replacement, replacement);
3504 __ subq(RSP, Immediate(16)); 3519 __ AddImmediate(RSP, Immediate(-16), PP);
3505 // Move value to stack. 3520 // Move value to stack.
3506 __ movups(Address(RSP, 0), value); 3521 __ movups(Address(RSP, 0), value);
3507 // Write over X value. 3522 // Write over X value.
3508 __ movss(Address(RSP, 0), replacement); 3523 __ movss(Address(RSP, 0), replacement);
3509 // Move updated value into output register. 3524 // Move updated value into output register.
3510 __ movups(replacement, Address(RSP, 0)); 3525 __ movups(replacement, Address(RSP, 0));
3511 __ addq(RSP, Immediate(16)); 3526 __ AddImmediate(RSP, Immediate(16), PP);
3512 break; 3527 break;
3513 case MethodRecognizer::kFloat32x4WithY: 3528 case MethodRecognizer::kFloat32x4WithY:
3514 __ cvtsd2ss(replacement, replacement); 3529 __ cvtsd2ss(replacement, replacement);
3515 __ subq(RSP, Immediate(16)); 3530 __ AddImmediate(RSP, Immediate(-16), PP);
3516 // Move value to stack. 3531 // Move value to stack.
3517 __ movups(Address(RSP, 0), value); 3532 __ movups(Address(RSP, 0), value);
3518 // Write over Y value. 3533 // Write over Y value.
3519 __ movss(Address(RSP, 4), replacement); 3534 __ movss(Address(RSP, 4), replacement);
3520 // Move updated value into output register. 3535 // Move updated value into output register.
3521 __ movups(replacement, Address(RSP, 0)); 3536 __ movups(replacement, Address(RSP, 0));
3522 __ addq(RSP, Immediate(16)); 3537 __ AddImmediate(RSP, Immediate(16), PP);
3523 break; 3538 break;
3524 case MethodRecognizer::kFloat32x4WithZ: 3539 case MethodRecognizer::kFloat32x4WithZ:
3525 __ cvtsd2ss(replacement, replacement); 3540 __ cvtsd2ss(replacement, replacement);
3526 __ subq(RSP, Immediate(16)); 3541 __ AddImmediate(RSP, Immediate(-16), PP);
3527 // Move value to stack. 3542 // Move value to stack.
3528 __ movups(Address(RSP, 0), value); 3543 __ movups(Address(RSP, 0), value);
3529 // Write over Z value. 3544 // Write over Z value.
3530 __ movss(Address(RSP, 8), replacement); 3545 __ movss(Address(RSP, 8), replacement);
3531 // Move updated value into output register. 3546 // Move updated value into output register.
3532 __ movups(replacement, Address(RSP, 0)); 3547 __ movups(replacement, Address(RSP, 0));
3533 __ addq(RSP, Immediate(16)); 3548 __ AddImmediate(RSP, Immediate(16), PP);
3534 break; 3549 break;
3535 case MethodRecognizer::kFloat32x4WithW: 3550 case MethodRecognizer::kFloat32x4WithW:
3536 __ cvtsd2ss(replacement, replacement); 3551 __ cvtsd2ss(replacement, replacement);
3537 __ subq(RSP, Immediate(16)); 3552 __ AddImmediate(RSP, Immediate(-16), PP);
3538 // Move value to stack. 3553 // Move value to stack.
3539 __ movups(Address(RSP, 0), value); 3554 __ movups(Address(RSP, 0), value);
3540 // Write over W value. 3555 // Write over W value.
3541 __ movss(Address(RSP, 12), replacement); 3556 __ movss(Address(RSP, 12), replacement);
3542 // Move updated value into output register. 3557 // Move updated value into output register.
3543 __ movups(replacement, Address(RSP, 0)); 3558 __ movups(replacement, Address(RSP, 0));
3544 __ addq(RSP, Immediate(16)); 3559 __ AddImmediate(RSP, Immediate(16), PP);
3545 break; 3560 break;
3546 default: UNREACHABLE(); 3561 default: UNREACHABLE();
3547 } 3562 }
3548 } 3563 }
3549 3564
3550 3565
3551 LocationSummary* Float32x4ToUint32x4Instr::MakeLocationSummary() const { 3566 LocationSummary* Float32x4ToUint32x4Instr::MakeLocationSummary() const {
3552 const intptr_t kNumInputs = 1; 3567 const intptr_t kNumInputs = 1;
3553 const intptr_t kNumTemps = 0; 3568 const intptr_t kNumTemps = 0;
3554 LocationSummary* summary = 3569 LocationSummary* summary =
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
3622 Register v0 = locs()->in(0).reg(); 3637 Register v0 = locs()->in(0).reg();
3623 Register v1 = locs()->in(1).reg(); 3638 Register v1 = locs()->in(1).reg();
3624 Register v2 = locs()->in(2).reg(); 3639 Register v2 = locs()->in(2).reg();
3625 Register v3 = locs()->in(3).reg(); 3640 Register v3 = locs()->in(3).reg();
3626 Register temp = locs()->temp(0).reg(); 3641 Register temp = locs()->temp(0).reg();
3627 XmmRegister result = locs()->out().fpu_reg(); 3642 XmmRegister result = locs()->out().fpu_reg();
3628 Label x_false, x_done; 3643 Label x_false, x_done;
3629 Label y_false, y_done; 3644 Label y_false, y_done;
3630 Label z_false, z_done; 3645 Label z_false, z_done;
3631 Label w_false, w_done; 3646 Label w_false, w_done;
3632 __ subq(RSP, Immediate(16)); 3647 __ AddImmediate(RSP, Immediate(-16), PP);
3633 3648
3634 __ CompareObject(v0, Bool::True()); 3649 __ CompareObject(v0, Bool::True(), PP);
3635 __ j(NOT_EQUAL, &x_false); 3650 __ j(NOT_EQUAL, &x_false);
3636 __ movq(temp, Immediate(0xFFFFFFFF)); 3651 __ LoadImmediate(temp, Immediate(0xFFFFFFFF), PP);
3637 __ jmp(&x_done); 3652 __ jmp(&x_done);
3638 __ Bind(&x_false); 3653 __ Bind(&x_false);
3639 __ movq(temp, Immediate(0x0)); 3654 __ LoadImmediate(temp, Immediate(0x0), PP);
3640 __ Bind(&x_done); 3655 __ Bind(&x_done);
3641 __ movl(Address(RSP, 0), temp); 3656 __ movl(Address(RSP, 0), temp);
3642 3657
3643 __ CompareObject(v1, Bool::True()); 3658 __ CompareObject(v1, Bool::True(), PP);
3644 __ j(NOT_EQUAL, &y_false); 3659 __ j(NOT_EQUAL, &y_false);
3645 __ movq(temp, Immediate(0xFFFFFFFF)); 3660 __ LoadImmediate(temp, Immediate(0xFFFFFFFF), PP);
3646 __ jmp(&y_done); 3661 __ jmp(&y_done);
3647 __ Bind(&y_false); 3662 __ Bind(&y_false);
3648 __ movq(temp, Immediate(0x0)); 3663 __ LoadImmediate(temp, Immediate(0x0), PP);
3649 __ Bind(&y_done); 3664 __ Bind(&y_done);
3650 __ movl(Address(RSP, 4), temp); 3665 __ movl(Address(RSP, 4), temp);
3651 3666
3652 __ CompareObject(v2, Bool::True()); 3667 __ CompareObject(v2, Bool::True(), PP);
3653 __ j(NOT_EQUAL, &z_false); 3668 __ j(NOT_EQUAL, &z_false);
3654 __ movq(temp, Immediate(0xFFFFFFFF)); 3669 __ LoadImmediate(temp, Immediate(0xFFFFFFFF), PP);
3655 __ jmp(&z_done); 3670 __ jmp(&z_done);
3656 __ Bind(&z_false); 3671 __ Bind(&z_false);
3657 __ movq(temp, Immediate(0x0)); 3672 __ LoadImmediate(temp, Immediate(0x0), PP);
3658 __ Bind(&z_done); 3673 __ Bind(&z_done);
3659 __ movl(Address(RSP, 8), temp); 3674 __ movl(Address(RSP, 8), temp);
3660 3675
3661 __ CompareObject(v3, Bool::True()); 3676 __ CompareObject(v3, Bool::True(), PP);
3662 __ j(NOT_EQUAL, &w_false); 3677 __ j(NOT_EQUAL, &w_false);
3663 __ movq(temp, Immediate(0xFFFFFFFF)); 3678 __ LoadImmediate(temp, Immediate(0xFFFFFFFF), PP);
3664 __ jmp(&w_done); 3679 __ jmp(&w_done);
3665 __ Bind(&w_false); 3680 __ Bind(&w_false);
3666 __ movq(temp, Immediate(0x0)); 3681 __ LoadImmediate(temp, Immediate(0x0), PP);
3667 __ Bind(&w_done); 3682 __ Bind(&w_done);
3668 __ movl(Address(RSP, 12), temp); 3683 __ movl(Address(RSP, 12), temp);
3669 3684
3670 __ movups(result, Address(RSP, 0)); 3685 __ movups(result, Address(RSP, 0));
3671 __ addq(RSP, Immediate(16)); 3686 __ AddImmediate(RSP, Immediate(16), PP);
3672 } 3687 }
3673 3688
3674 3689
3675 LocationSummary* Uint32x4GetFlagInstr::MakeLocationSummary() const { 3690 LocationSummary* Uint32x4GetFlagInstr::MakeLocationSummary() const {
3676 const intptr_t kNumInputs = 1; 3691 const intptr_t kNumInputs = 1;
3677 const intptr_t kNumTemps = 0; 3692 const intptr_t kNumTemps = 0;
3678 LocationSummary* summary = 3693 LocationSummary* summary =
3679 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 3694 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
3680 summary->set_in(0, Location::RequiresFpuRegister()); 3695 summary->set_in(0, Location::RequiresFpuRegister());
3681 summary->set_out(Location::RequiresRegister()); 3696 summary->set_out(Location::RequiresRegister());
3682 return summary; 3697 return summary;
3683 } 3698 }
3684 3699
3685 3700
3686 void Uint32x4GetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3701 void Uint32x4GetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3687 XmmRegister value = locs()->in(0).fpu_reg(); 3702 XmmRegister value = locs()->in(0).fpu_reg();
3688 Register result = locs()->out().reg(); 3703 Register result = locs()->out().reg();
3689 Label done; 3704 Label done;
3690 Label non_zero; 3705 Label non_zero;
3691 __ subq(RSP, Immediate(16)); 3706 __ AddImmediate(RSP, Immediate(-16), PP);
3692 // Move value to stack. 3707 // Move value to stack.
3693 __ movups(Address(RSP, 0), value); 3708 __ movups(Address(RSP, 0), value);
3694 switch (op_kind()) { 3709 switch (op_kind()) {
3695 case MethodRecognizer::kUint32x4GetFlagX: 3710 case MethodRecognizer::kUint32x4GetFlagX:
3696 __ movl(result, Address(RSP, 0)); 3711 __ movl(result, Address(RSP, 0));
3697 break; 3712 break;
3698 case MethodRecognizer::kUint32x4GetFlagY: 3713 case MethodRecognizer::kUint32x4GetFlagY:
3699 __ movl(result, Address(RSP, 4)); 3714 __ movl(result, Address(RSP, 4));
3700 break; 3715 break;
3701 case MethodRecognizer::kUint32x4GetFlagZ: 3716 case MethodRecognizer::kUint32x4GetFlagZ:
3702 __ movl(result, Address(RSP, 8)); 3717 __ movl(result, Address(RSP, 8));
3703 break; 3718 break;
3704 case MethodRecognizer::kUint32x4GetFlagW: 3719 case MethodRecognizer::kUint32x4GetFlagW:
3705 __ movl(result, Address(RSP, 12)); 3720 __ movl(result, Address(RSP, 12));
3706 break; 3721 break;
3707 default: UNREACHABLE(); 3722 default: UNREACHABLE();
3708 } 3723 }
3709 __ addq(RSP, Immediate(16)); 3724 __ AddImmediate(RSP, Immediate(16), PP);
3710 __ testl(result, result); 3725 __ testl(result, result);
3711 __ j(NOT_ZERO, &non_zero, Assembler::kNearJump); 3726 __ j(NOT_ZERO, &non_zero, Assembler::kNearJump);
3712 __ LoadObject(result, Bool::False(), PP); 3727 __ LoadObject(result, Bool::False(), PP);
3713 __ jmp(&done); 3728 __ jmp(&done);
3714 __ Bind(&non_zero); 3729 __ Bind(&non_zero);
3715 __ LoadObject(result, Bool::True(), PP); 3730 __ LoadObject(result, Bool::True(), PP);
3716 __ Bind(&done); 3731 __ Bind(&done);
3717 } 3732 }
3718 3733
3719 3734
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
3762 summary->set_out(Location::SameAsFirstInput()); 3777 summary->set_out(Location::SameAsFirstInput());
3763 return summary; 3778 return summary;
3764 } 3779 }
3765 3780
3766 3781
3767 void Uint32x4SetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 3782 void Uint32x4SetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
3768 XmmRegister mask = locs()->in(0).fpu_reg(); 3783 XmmRegister mask = locs()->in(0).fpu_reg();
3769 Register flag = locs()->in(1).reg(); 3784 Register flag = locs()->in(1).reg();
3770 Register temp = locs()->temp(0).reg(); 3785 Register temp = locs()->temp(0).reg();
3771 ASSERT(mask == locs()->out().fpu_reg()); 3786 ASSERT(mask == locs()->out().fpu_reg());
3772 __ subq(RSP, Immediate(16)); 3787 __ AddImmediate(RSP, Immediate(-16), PP);
3773 // Copy mask to stack. 3788 // Copy mask to stack.
3774 __ movups(Address(RSP, 0), mask); 3789 __ movups(Address(RSP, 0), mask);
3775 Label falsePath, exitPath; 3790 Label falsePath, exitPath;
3776 __ CompareObject(flag, Bool::True()); 3791 __ CompareObject(flag, Bool::True(), PP);
3777 __ j(NOT_EQUAL, &falsePath); 3792 __ j(NOT_EQUAL, &falsePath);
3778 switch (op_kind()) { 3793 switch (op_kind()) {
3779 case MethodRecognizer::kUint32x4WithFlagX: 3794 case MethodRecognizer::kUint32x4WithFlagX:
3780 __ movq(temp, Immediate(0xFFFFFFFF)); 3795 __ LoadImmediate(temp, Immediate(0xFFFFFFFF), PP);
3781 __ movl(Address(RSP, 0), temp); 3796 __ movl(Address(RSP, 0), temp);
3782 __ jmp(&exitPath); 3797 __ jmp(&exitPath);
3783 __ Bind(&falsePath); 3798 __ Bind(&falsePath);
3784 __ movq(temp, Immediate(0x0)); 3799 __ LoadImmediate(temp, Immediate(0x0), PP);
3785 __ movl(Address(RSP, 0), temp); 3800 __ movl(Address(RSP, 0), temp);
3786 break; 3801 break;
3787 case MethodRecognizer::kUint32x4WithFlagY: 3802 case MethodRecognizer::kUint32x4WithFlagY:
3788 __ movq(temp, Immediate(0xFFFFFFFF)); 3803 __ LoadImmediate(temp, Immediate(0xFFFFFFFF), PP);
3789 __ movl(Address(RSP, 4), temp); 3804 __ movl(Address(RSP, 4), temp);
3790 __ jmp(&exitPath); 3805 __ jmp(&exitPath);
3791 __ Bind(&falsePath); 3806 __ Bind(&falsePath);
3792 __ movq(temp, Immediate(0x0)); 3807 __ LoadImmediate(temp, Immediate(0x0), PP);
3793 __ movl(Address(RSP, 4), temp); 3808 __ movl(Address(RSP, 4), temp);
3794 break; 3809 break;
3795 case MethodRecognizer::kUint32x4WithFlagZ: 3810 case MethodRecognizer::kUint32x4WithFlagZ:
3796 __ movq(temp, Immediate(0xFFFFFFFF)); 3811 __ LoadImmediate(temp, Immediate(0xFFFFFFFF), PP);
3797 __ movl(Address(RSP, 8), temp); 3812 __ movl(Address(RSP, 8), temp);
3798 __ jmp(&exitPath); 3813 __ jmp(&exitPath);
3799 __ Bind(&falsePath); 3814 __ Bind(&falsePath);
3800 __ movq(temp, Immediate(0x0)); 3815 __ LoadImmediate(temp, Immediate(0x0), PP);
3801 __ movl(Address(RSP, 8), temp); 3816 __ movl(Address(RSP, 8), temp);
3802 break; 3817 break;
3803 case MethodRecognizer::kUint32x4WithFlagW: 3818 case MethodRecognizer::kUint32x4WithFlagW:
3804 __ movq(temp, Immediate(0xFFFFFFFF)); 3819 __ LoadImmediate(temp, Immediate(0xFFFFFFFF), PP);
3805 __ movl(Address(RSP, 12), temp); 3820 __ movl(Address(RSP, 12), temp);
3806 __ jmp(&exitPath); 3821 __ jmp(&exitPath);
3807 __ Bind(&falsePath); 3822 __ Bind(&falsePath);
3808 __ movq(temp, Immediate(0x0)); 3823 __ LoadImmediate(temp, Immediate(0x0), PP);
3809 __ movl(Address(RSP, 12), temp); 3824 __ movl(Address(RSP, 12), temp);
3810 break; 3825 break;
3811 default: UNREACHABLE(); 3826 default: UNREACHABLE();
3812 } 3827 }
3813 __ Bind(&exitPath); 3828 __ Bind(&exitPath);
3814 // Copy mask back to register. 3829 // Copy mask back to register.
3815 __ movups(mask, Address(RSP, 0)); 3830 __ movups(mask, Address(RSP, 0));
3816 __ addq(RSP, Immediate(16)); 3831 __ AddImmediate(RSP, Immediate(16), PP);
3817 } 3832 }
3818 3833
3819 3834
3820 LocationSummary* Uint32x4ToFloat32x4Instr::MakeLocationSummary() const { 3835 LocationSummary* Uint32x4ToFloat32x4Instr::MakeLocationSummary() const {
3821 const intptr_t kNumInputs = 1; 3836 const intptr_t kNumInputs = 1;
3822 const intptr_t kNumTemps = 0; 3837 const intptr_t kNumTemps = 0;
3823 LocationSummary* summary = 3838 LocationSummary* summary =
3824 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall); 3839 new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
3825 summary->set_in(0, Location::RequiresFpuRegister()); 3840 summary->set_in(0, Location::RequiresFpuRegister());
3826 summary->set_out(Location::SameAsFirstInput()); 3841 summary->set_out(Location::SameAsFirstInput());
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
3929 kDeoptUnaryOp); 3944 kDeoptUnaryOp);
3930 __ negq(value); 3945 __ negq(value);
3931 __ j(OVERFLOW, deopt); 3946 __ j(OVERFLOW, deopt);
3932 if (FLAG_throw_on_javascript_int_overflow) { 3947 if (FLAG_throw_on_javascript_int_overflow) {
3933 EmitJavascriptOverflowCheck(compiler, range(), deopt, value); 3948 EmitJavascriptOverflowCheck(compiler, range(), deopt, value);
3934 } 3949 }
3935 break; 3950 break;
3936 } 3951 }
3937 case Token::kBIT_NOT: 3952 case Token::kBIT_NOT:
3938 __ notq(value); 3953 __ notq(value);
3939 __ andq(value, Immediate(~kSmiTagMask)); // Remove inverted smi-tag. 3954 // Remove inverted smi-tag.
3955 __ AndImmediate(value, Immediate(~kSmiTagMask), PP);
3940 break; 3956 break;
3941 default: 3957 default:
3942 UNREACHABLE(); 3958 UNREACHABLE();
3943 } 3959 }
3944 } 3960 }
3945 3961
3946 3962
3947 LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary() const { 3963 LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary() const {
3948 const intptr_t kNumInputs = 1; 3964 const intptr_t kNumInputs = 1;
3949 const intptr_t kNumTemps = 0; 3965 const intptr_t kNumTemps = 0;
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
4004 const Condition double_condition = 4020 const Condition double_condition =
4005 is_min ? TokenKindToDoubleCondition(Token::kLT) 4021 is_min ? TokenKindToDoubleCondition(Token::kLT)
4006 : TokenKindToDoubleCondition(Token::kGT); 4022 : TokenKindToDoubleCondition(Token::kGT);
4007 ASSERT(left == result); 4023 ASSERT(left == result);
4008 __ j(double_condition, &done, Assembler::kNearJump); 4024 __ j(double_condition, &done, Assembler::kNearJump);
4009 __ movsd(result, right); 4025 __ movsd(result, right);
4010 __ jmp(&done, Assembler::kNearJump); 4026 __ jmp(&done, Assembler::kNearJump);
4011 4027
4012 __ Bind(&returns_nan); 4028 __ Bind(&returns_nan);
4013 static double kNaN = NAN; 4029 static double kNaN = NAN;
4014 __ movq(temp, Immediate(reinterpret_cast<intptr_t>(&kNaN))); 4030 __ LoadImmediate(temp, Immediate(reinterpret_cast<intptr_t>(&kNaN)), PP);
4015 __ movsd(result, Address(temp, 0)); 4031 __ movsd(result, Address(temp, 0));
4016 __ jmp(&done, Assembler::kNearJump); 4032 __ jmp(&done, Assembler::kNearJump);
4017 4033
4018 __ Bind(&are_equal); 4034 __ Bind(&are_equal);
4019 Label left_is_negative; 4035 Label left_is_negative;
4020 // Check for negative zero: -0.0 is equal 0.0 but min or max must return 4036 // Check for negative zero: -0.0 is equal 0.0 but min or max must return
4021 // -0.0 or 0.0 respectively. 4037 // -0.0 or 0.0 respectively.
4022 // Check for negative left value (get the sign bit): 4038 // Check for negative left value (get the sign bit):
4023 // - min -> left is negative ? left : right. 4039 // - min -> left is negative ? left : right.
4024 // - max -> left is negative ? right : left 4040 // - max -> left is negative ? right : left
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after
4330 } 4346 }
4331 return summary; 4347 return summary;
4332 } 4348 }
4333 4349
4334 4350
4335 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4351 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4336 if (IsNullCheck()) { 4352 if (IsNullCheck()) {
4337 Label* deopt = compiler->AddDeoptStub(deopt_id(), 4353 Label* deopt = compiler->AddDeoptStub(deopt_id(),
4338 kDeoptCheckClass); 4354 kDeoptCheckClass);
4339 __ CompareObject(locs()->in(0).reg(), 4355 __ CompareObject(locs()->in(0).reg(),
4340 Object::null_object()); 4356 Object::null_object(), PP);
4341 __ j(EQUAL, deopt); 4357 __ j(EQUAL, deopt);
4342 return; 4358 return;
4343 } 4359 }
4344 4360
4345 ASSERT((unary_checks().GetReceiverClassIdAt(0) != kSmiCid) || 4361 ASSERT((unary_checks().GetReceiverClassIdAt(0) != kSmiCid) ||
4346 (unary_checks().NumberOfChecks() > 1)); 4362 (unary_checks().NumberOfChecks() > 1));
4347 Register value = locs()->in(0).reg(); 4363 Register value = locs()->in(0).reg();
4348 Register temp = locs()->temp(0).reg(); 4364 Register temp = locs()->temp(0).reg();
4349 Label* deopt = compiler->AddDeoptStub(deopt_id(), 4365 Label* deopt = compiler->AddDeoptStub(deopt_id(),
4350 kDeoptCheckClass); 4366 kDeoptCheckClass);
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
4427 (Smi::Cast(index_loc.constant()).Value() < 0)); 4443 (Smi::Cast(index_loc.constant()).Value() < 0));
4428 // Unconditionally deoptimize for constant bounds checks because they 4444 // Unconditionally deoptimize for constant bounds checks because they
4429 // only occur only when index is out-of-bounds. 4445 // only occur only when index is out-of-bounds.
4430 __ jmp(deopt); 4446 __ jmp(deopt);
4431 return; 4447 return;
4432 } 4448 }
4433 4449
4434 if (index_loc.IsConstant()) { 4450 if (index_loc.IsConstant()) {
4435 Register length = length_loc.reg(); 4451 Register length = length_loc.reg();
4436 const Smi& index = Smi::Cast(index_loc.constant()); 4452 const Smi& index = Smi::Cast(index_loc.constant());
4437 __ cmpq(length, Immediate(reinterpret_cast<int64_t>(index.raw()))); 4453 __ CompareImmediate(
4454 length, Immediate(reinterpret_cast<int64_t>(index.raw())), PP);
4438 __ j(BELOW_EQUAL, deopt); 4455 __ j(BELOW_EQUAL, deopt);
4439 } else if (length_loc.IsConstant()) { 4456 } else if (length_loc.IsConstant()) {
4440 const Smi& length = Smi::Cast(length_loc.constant()); 4457 const Smi& length = Smi::Cast(length_loc.constant());
4441 Register index = index_loc.reg(); 4458 Register index = index_loc.reg();
4442 __ cmpq(index, Immediate(reinterpret_cast<int64_t>(length.raw()))); 4459 __ CompareImmediate(
4460 index, Immediate(reinterpret_cast<int64_t>(length.raw())), PP);
4443 __ j(ABOVE_EQUAL, deopt); 4461 __ j(ABOVE_EQUAL, deopt);
4444 } else { 4462 } else {
4445 Register length = length_loc.reg(); 4463 Register length = length_loc.reg();
4446 Register index = index_loc.reg(); 4464 Register index = index_loc.reg();
4447 __ cmpq(index, length); 4465 __ cmpq(index, length);
4448 __ j(ABOVE_EQUAL, deopt); 4466 __ j(ABOVE_EQUAL, deopt);
4449 } 4467 }
4450 } 4468 }
4451 4469
4452 4470
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
4548 if (!compiler->is_optimizing()) { 4566 if (!compiler->is_optimizing()) {
4549 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, 4567 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt,
4550 deopt_id_, 4568 deopt_id_,
4551 Scanner::kDummyTokenIndex); 4569 Scanner::kDummyTokenIndex);
4552 // Add an edge counter. 4570 // Add an edge counter.
4553 const Array& counter = Array::ZoneHandle(Array::New(1, Heap::kOld)); 4571 const Array& counter = Array::ZoneHandle(Array::New(1, Heap::kOld));
4554 counter.SetAt(0, Smi::Handle(Smi::New(0))); 4572 counter.SetAt(0, Smi::Handle(Smi::New(0)));
4555 Label done; 4573 Label done;
4556 __ Comment("Edge counter"); 4574 __ Comment("Edge counter");
4557 __ LoadObject(RAX, counter, PP); 4575 __ LoadObject(RAX, counter, PP);
4558 __ addq(FieldAddress(RAX, Array::element_offset(0)), 4576 __ AddImmediate(FieldAddress(RAX, Array::element_offset(0)),
4559 Immediate(Smi::RawValue(1))); 4577 Immediate(Smi::RawValue(1)), PP);
4560 __ j(NO_OVERFLOW, &done); 4578 __ j(NO_OVERFLOW, &done);
4561 __ movq(FieldAddress(RAX, Array::element_offset(0)), 4579 __ LoadImmediate(FieldAddress(RAX, Array::element_offset(0)),
4562 Immediate(Smi::RawValue(Smi::kMaxValue))); 4580 Immediate(Smi::RawValue(Smi::kMaxValue)), PP);
4563 __ Bind(&done); 4581 __ Bind(&done);
4564 } 4582 }
4565 if (HasParallelMove()) { 4583 if (HasParallelMove()) {
4566 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); 4584 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
4567 } 4585 }
4568 } 4586 }
4569 4587
4570 4588
4571 LocationSummary* GotoInstr::MakeLocationSummary() const { 4589 LocationSummary* GotoInstr::MakeLocationSummary() const {
4572 return new LocationSummary(0, 0, LocationSummary::kNoCall); 4590 return new LocationSummary(0, 0, LocationSummary::kNoCall);
4573 } 4591 }
4574 4592
4575 4593
4576 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { 4594 void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
4577 if (!compiler->is_optimizing()) { 4595 if (!compiler->is_optimizing()) {
4578 // Add deoptimization descriptor for deoptimizing instructions that may 4596 // Add deoptimization descriptor for deoptimizing instructions that may
4579 // be inserted before this instruction. 4597 // be inserted before this instruction.
4580 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, 4598 compiler->AddCurrentDescriptor(PcDescriptors::kDeopt,
4581 GetDeoptId(), 4599 GetDeoptId(),
4582 0); // No token position. 4600 0); // No token position.
4583 // Add an edge counter. 4601 // Add an edge counter.
4584 const Array& counter = Array::ZoneHandle(Array::New(1, Heap::kOld)); 4602 const Array& counter = Array::ZoneHandle(Array::New(1, Heap::kOld));
4585 counter.SetAt(0, Smi::Handle(Smi::New(0))); 4603 counter.SetAt(0, Smi::Handle(Smi::New(0)));
4586 Label done; 4604 Label done;
4587 __ Comment("Edge counter"); 4605 __ Comment("Edge counter");
4588 __ LoadObject(RAX, counter, PP); 4606 __ LoadObject(RAX, counter, PP);
4589 __ addq(FieldAddress(RAX, Array::element_offset(0)), 4607 __ AddImmediate(FieldAddress(RAX, Array::element_offset(0)),
4590 Immediate(Smi::RawValue(1))); 4608 Immediate(Smi::RawValue(1)), PP);
4591 __ j(NO_OVERFLOW, &done); 4609 __ j(NO_OVERFLOW, &done);
4592 __ movq(FieldAddress(RAX, Array::element_offset(0)), 4610 __ LoadImmediate(FieldAddress(RAX, Array::element_offset(0)),
4593 Immediate(Smi::RawValue(Smi::kMaxValue))); 4611 Immediate(Smi::RawValue(Smi::kMaxValue)), PP);
4594 __ Bind(&done); 4612 __ Bind(&done);
4595 } 4613 }
4596 if (HasParallelMove()) { 4614 if (HasParallelMove()) {
4597 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); 4615 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
4598 } 4616 }
4599 4617
4600 // We can fall through if the successor is the next block in the list. 4618 // We can fall through if the successor is the next block in the list.
4601 // Otherwise, we need a jump. 4619 // Otherwise, we need a jump.
4602 if (!compiler->CanFallThroughTo(successor())) { 4620 if (!compiler->CanFallThroughTo(successor())) {
4603 __ jmp(compiler->GetJumpLabel(successor())); 4621 __ jmp(compiler->GetJumpLabel(successor()));
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after
4842 PcDescriptors::kOther, 4860 PcDescriptors::kOther,
4843 locs()); 4861 locs());
4844 __ Drop(2); // Discard type arguments and receiver. 4862 __ Drop(2); // Discard type arguments and receiver.
4845 } 4863 }
4846 4864
4847 } // namespace dart 4865 } // namespace dart
4848 4866
4849 #undef __ 4867 #undef __
4850 4868
4851 #endif // defined TARGET_ARCH_X64 4869 #endif // defined TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_compiler_x64.cc ('k') | runtime/vm/intrinsifier_x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698