| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 2731 __ jmp(&done); | 2743 __ jmp(&done); |
| 2732 | 2744 |
| 2733 // Divide using 64bit idiv. | 2745 // Divide using 64bit idiv. |
| 2734 __ Bind(¬_32bit); | 2746 __ Bind(¬_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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |