| 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 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 49 | 49 |
| 50 | 50 |
| 51 void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 51 void PushArgumentInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 52 // In SSA mode, we need an explicit push. Nothing to do in non-SSA mode | 52 // In SSA mode, we need an explicit push. Nothing to do in non-SSA mode |
| 53 // where PushArgument is handled by BindInstr::EmitNativeCode. | 53 // where PushArgument is handled by BindInstr::EmitNativeCode. |
| 54 if (compiler->is_optimizing()) { | 54 if (compiler->is_optimizing()) { |
| 55 Location value = locs()->in(0); | 55 Location value = locs()->in(0); |
| 56 if (value.IsRegister()) { | 56 if (value.IsRegister()) { |
| 57 __ pushq(value.reg()); | 57 __ pushq(value.reg()); |
| 58 } else if (value.IsConstant()) { | 58 } else if (value.IsConstant()) { |
| 59 __ PushObject(value.constant(), PP); | 59 __ PushObject(value.constant()); |
| 60 } else { | 60 } else { |
| 61 ASSERT(value.IsStackSlot()); | 61 ASSERT(value.IsStackSlot()); |
| 62 __ pushq(value.ToStackSlotAddress()); | 62 __ pushq(value.ToStackSlotAddress()); |
| 63 } | 63 } |
| 64 } | 64 } |
| 65 } | 65 } |
| 66 | 66 |
| 67 | 67 |
| 68 LocationSummary* ReturnInstr::MakeLocationSummary(Zone* zone, | 68 LocationSummary* ReturnInstr::MakeLocationSummary(Zone* zone, |
| 69 bool opt) const { | 69 bool opt) const { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 90 } | 90 } |
| 91 | 91 |
| 92 #if defined(DEBUG) | 92 #if defined(DEBUG) |
| 93 __ Comment("Stack Check"); | 93 __ Comment("Stack Check"); |
| 94 Label done; | 94 Label done; |
| 95 const intptr_t fp_sp_dist = | 95 const intptr_t fp_sp_dist = |
| 96 (kFirstLocalSlotFromFp + 1 - compiler->StackSize()) * kWordSize; | 96 (kFirstLocalSlotFromFp + 1 - compiler->StackSize()) * kWordSize; |
| 97 ASSERT(fp_sp_dist <= 0); | 97 ASSERT(fp_sp_dist <= 0); |
| 98 __ movq(RDI, RSP); | 98 __ movq(RDI, RSP); |
| 99 __ subq(RDI, RBP); | 99 __ subq(RDI, RBP); |
| 100 __ CompareImmediate(RDI, Immediate(fp_sp_dist), PP); | 100 __ CompareImmediate(RDI, Immediate(fp_sp_dist)); |
| 101 __ j(EQUAL, &done, Assembler::kNearJump); | 101 __ j(EQUAL, &done, Assembler::kNearJump); |
| 102 __ int3(); | 102 __ int3(); |
| 103 __ Bind(&done); | 103 __ Bind(&done); |
| 104 #endif | 104 #endif |
| 105 __ LeaveDartFrame(); | 105 ASSERT(__ constant_pool_allowed()); |
| 106 __ LeaveDartFrame(); // Disallows constant pool use. |
| 106 __ ret(); | 107 __ ret(); |
| 108 // This ReturnInstr may be emitted out of order by the optimizer. The next |
| 109 // block may be a target expecting a properly set constant pool pointer. |
| 110 __ set_constant_pool_allowed(true); |
| 107 } | 111 } |
| 108 | 112 |
| 109 | 113 |
| 110 static Condition NegateCondition(Condition condition) { | 114 static Condition NegateCondition(Condition condition) { |
| 111 switch (condition) { | 115 switch (condition) { |
| 112 case EQUAL: return NOT_EQUAL; | 116 case EQUAL: return NOT_EQUAL; |
| 113 case NOT_EQUAL: return EQUAL; | 117 case NOT_EQUAL: return EQUAL; |
| 114 case LESS: return GREATER_EQUAL; | 118 case LESS: return GREATER_EQUAL; |
| 115 case LESS_EQUAL: return GREATER; | 119 case LESS_EQUAL: return GREATER; |
| 116 case GREATER: return LESS_EQUAL; | 120 case GREATER: return LESS_EQUAL; |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 176 | 180 |
| 177 __ setcc(true_condition, DL); | 181 __ setcc(true_condition, DL); |
| 178 | 182 |
| 179 if (is_power_of_two_kind) { | 183 if (is_power_of_two_kind) { |
| 180 const intptr_t shift = | 184 const intptr_t shift = |
| 181 Utils::ShiftForPowerOfTwo(Utils::Maximum(true_value, false_value)); | 185 Utils::ShiftForPowerOfTwo(Utils::Maximum(true_value, false_value)); |
| 182 __ shlq(RDX, Immediate(shift + kSmiTagSize)); | 186 __ shlq(RDX, Immediate(shift + kSmiTagSize)); |
| 183 } else { | 187 } else { |
| 184 __ decq(RDX); | 188 __ decq(RDX); |
| 185 __ AndImmediate(RDX, | 189 __ AndImmediate(RDX, |
| 186 Immediate(Smi::RawValue(true_value) - Smi::RawValue(false_value)), PP); | 190 Immediate(Smi::RawValue(true_value) - Smi::RawValue(false_value))); |
| 187 if (false_value != 0) { | 191 if (false_value != 0) { |
| 188 __ AddImmediate(RDX, Immediate(Smi::RawValue(false_value)), PP); | 192 __ AddImmediate(RDX, Immediate(Smi::RawValue(false_value))); |
| 189 } | 193 } |
| 190 } | 194 } |
| 191 } | 195 } |
| 192 | 196 |
| 193 | 197 |
| 194 LocationSummary* LoadLocalInstr::MakeLocationSummary(Zone* zone, | 198 LocationSummary* LoadLocalInstr::MakeLocationSummary(Zone* zone, |
| 195 bool opt) const { | 199 bool opt) const { |
| 196 const intptr_t kNumInputs = 0; | 200 const intptr_t kNumInputs = 0; |
| 197 const intptr_t stack_index = (local().index() < 0) | 201 const intptr_t stack_index = (local().index() < 0) |
| 198 ? kFirstLocalSlotFromFp - local().index() | 202 ? kFirstLocalSlotFromFp - local().index() |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 235 kNumInputs, | 239 kNumInputs, |
| 236 Location::RequiresRegister(), | 240 Location::RequiresRegister(), |
| 237 LocationSummary::kNoCall); | 241 LocationSummary::kNoCall); |
| 238 } | 242 } |
| 239 | 243 |
| 240 | 244 |
| 241 void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 245 void ConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 242 // The register allocator drops constant definitions that have no uses. | 246 // The register allocator drops constant definitions that have no uses. |
| 243 if (!locs()->out(0).IsInvalid()) { | 247 if (!locs()->out(0).IsInvalid()) { |
| 244 Register result = locs()->out(0).reg(); | 248 Register result = locs()->out(0).reg(); |
| 245 __ LoadObject(result, value(), PP); | 249 __ LoadObject(result, value()); |
| 246 } | 250 } |
| 247 } | 251 } |
| 248 | 252 |
| 249 | 253 |
| 250 LocationSummary* UnboxedConstantInstr::MakeLocationSummary(Zone* zone, | 254 LocationSummary* UnboxedConstantInstr::MakeLocationSummary(Zone* zone, |
| 251 bool opt) const { | 255 bool opt) const { |
| 252 const intptr_t kNumInputs = 0; | 256 const intptr_t kNumInputs = 0; |
| 253 const intptr_t kNumTemps = 0; | 257 const intptr_t kNumTemps = 0; |
| 254 LocationSummary* locs = new(zone) LocationSummary( | 258 LocationSummary* locs = new(zone) LocationSummary( |
| 255 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 259 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 270 | 274 |
| 271 void UnboxedConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 275 void UnboxedConstantInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 272 // The register allocator drops constant definitions that have no uses. | 276 // The register allocator drops constant definitions that have no uses. |
| 273 if (!locs()->out(0).IsInvalid()) { | 277 if (!locs()->out(0).IsInvalid()) { |
| 274 switch (representation()) { | 278 switch (representation()) { |
| 275 case kUnboxedDouble: { | 279 case kUnboxedDouble: { |
| 276 XmmRegister result = locs()->out(0).fpu_reg(); | 280 XmmRegister result = locs()->out(0).fpu_reg(); |
| 277 if (Utils::DoublesBitEqual(Double::Cast(value()).value(), 0.0)) { | 281 if (Utils::DoublesBitEqual(Double::Cast(value()).value(), 0.0)) { |
| 278 __ xorps(result, result); | 282 __ xorps(result, result); |
| 279 } else { | 283 } else { |
| 280 __ LoadObject(TMP, value(), PP); | 284 __ LoadObject(TMP, value()); |
| 281 __ movsd(result, FieldAddress(TMP, Double::value_offset())); | 285 __ movsd(result, FieldAddress(TMP, Double::value_offset())); |
| 282 } | 286 } |
| 283 break; | 287 break; |
| 284 } | 288 } |
| 285 case kUnboxedInt32: | 289 case kUnboxedInt32: |
| 286 __ movl(locs()->out(0).reg(), | 290 __ movl(locs()->out(0).reg(), |
| 287 Immediate(static_cast<int32_t>(Smi::Cast(value()).Value()))); | 291 Immediate(static_cast<int32_t>(Smi::Cast(value()).Value()))); |
| 288 break; | 292 break; |
| 289 default: | 293 default: |
| 290 UNREACHABLE(); | 294 UNREACHABLE(); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 323 intptr_t token_pos, | 327 intptr_t token_pos, |
| 324 intptr_t deopt_id, | 328 intptr_t deopt_id, |
| 325 LocationSummary* locs, | 329 LocationSummary* locs, |
| 326 FlowGraphCompiler* compiler) { | 330 FlowGraphCompiler* compiler) { |
| 327 // Check that the type of the value is allowed in conditional context. | 331 // Check that the type of the value is allowed in conditional context. |
| 328 // Call the runtime if the object is not bool::true or bool::false. | 332 // Call the runtime if the object is not bool::true or bool::false. |
| 329 ASSERT(locs->always_calls()); | 333 ASSERT(locs->always_calls()); |
| 330 Label done; | 334 Label done; |
| 331 | 335 |
| 332 if (Isolate::Current()->flags().type_checks()) { | 336 if (Isolate::Current()->flags().type_checks()) { |
| 333 __ CompareObject(reg, Bool::True(), PP); | 337 __ CompareObject(reg, Bool::True()); |
| 334 __ j(EQUAL, &done, Assembler::kNearJump); | 338 __ j(EQUAL, &done, Assembler::kNearJump); |
| 335 __ CompareObject(reg, Bool::False(), PP); | 339 __ CompareObject(reg, Bool::False()); |
| 336 __ j(EQUAL, &done, Assembler::kNearJump); | 340 __ j(EQUAL, &done, Assembler::kNearJump); |
| 337 } else { | 341 } else { |
| 338 ASSERT(Isolate::Current()->flags().asserts()); | 342 ASSERT(Isolate::Current()->flags().asserts()); |
| 339 __ CompareObject(reg, Object::null_instance(), PP); | 343 __ CompareObject(reg, Object::null_instance()); |
| 340 __ j(NOT_EQUAL, &done, Assembler::kNearJump); | 344 __ j(NOT_EQUAL, &done, Assembler::kNearJump); |
| 341 } | 345 } |
| 342 | 346 |
| 343 __ pushq(reg); // Push the source object. | 347 __ pushq(reg); // Push the source object. |
| 344 compiler->GenerateRuntimeCall(token_pos, | 348 compiler->GenerateRuntimeCall(token_pos, |
| 345 deopt_id, | 349 deopt_id, |
| 346 kNonBoolTypeErrorRuntimeEntry, | 350 kNonBoolTypeErrorRuntimeEntry, |
| 347 1, | 351 1, |
| 348 locs); | 352 locs); |
| 349 // We should never return here. | 353 // We should never return here. |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 415 return NULL; | 419 return NULL; |
| 416 } | 420 } |
| 417 | 421 |
| 418 | 422 |
| 419 static void LoadValueCid(FlowGraphCompiler* compiler, | 423 static void LoadValueCid(FlowGraphCompiler* compiler, |
| 420 Register value_cid_reg, | 424 Register value_cid_reg, |
| 421 Register value_reg, | 425 Register value_reg, |
| 422 Label* value_is_smi = NULL) { | 426 Label* value_is_smi = NULL) { |
| 423 Label done; | 427 Label done; |
| 424 if (value_is_smi == NULL) { | 428 if (value_is_smi == NULL) { |
| 425 __ LoadImmediate(value_cid_reg, Immediate(kSmiCid), PP); | 429 __ LoadImmediate(value_cid_reg, Immediate(kSmiCid)); |
| 426 } | 430 } |
| 427 __ testq(value_reg, Immediate(kSmiTagMask)); | 431 __ testq(value_reg, Immediate(kSmiTagMask)); |
| 428 if (value_is_smi == NULL) { | 432 if (value_is_smi == NULL) { |
| 429 __ j(ZERO, &done, Assembler::kNearJump); | 433 __ j(ZERO, &done, Assembler::kNearJump); |
| 430 } else { | 434 } else { |
| 431 __ j(ZERO, value_is_smi); | 435 __ j(ZERO, value_is_smi); |
| 432 } | 436 } |
| 433 __ LoadClassId(value_cid_reg, value_reg); | 437 __ LoadClassId(value_cid_reg, value_reg); |
| 434 __ Bind(&done); | 438 __ Bind(&done); |
| 435 } | 439 } |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 477 const LocationSummary& locs, | 481 const LocationSummary& locs, |
| 478 Token::Kind kind, | 482 Token::Kind kind, |
| 479 BranchLabels labels) { | 483 BranchLabels labels) { |
| 480 Location left = locs.in(0); | 484 Location left = locs.in(0); |
| 481 Location right = locs.in(1); | 485 Location right = locs.in(1); |
| 482 ASSERT(!left.IsConstant() || !right.IsConstant()); | 486 ASSERT(!left.IsConstant() || !right.IsConstant()); |
| 483 | 487 |
| 484 Condition true_condition = TokenKindToIntCondition(kind); | 488 Condition true_condition = TokenKindToIntCondition(kind); |
| 485 | 489 |
| 486 if (left.IsConstant()) { | 490 if (left.IsConstant()) { |
| 487 __ CompareObject(right.reg(), left.constant(), PP); | 491 __ CompareObject(right.reg(), left.constant()); |
| 488 true_condition = FlipCondition(true_condition); | 492 true_condition = FlipCondition(true_condition); |
| 489 } else if (right.IsConstant()) { | 493 } else if (right.IsConstant()) { |
| 490 __ CompareObject(left.reg(), right.constant(), PP); | 494 __ CompareObject(left.reg(), right.constant()); |
| 491 } else if (right.IsStackSlot()) { | 495 } else if (right.IsStackSlot()) { |
| 492 __ cmpq(left.reg(), right.ToStackSlotAddress()); | 496 __ cmpq(left.reg(), right.ToStackSlotAddress()); |
| 493 } else { | 497 } else { |
| 494 __ cmpq(left.reg(), right.reg()); | 498 __ cmpq(left.reg(), right.reg()); |
| 495 } | 499 } |
| 496 return true_condition; | 500 return true_condition; |
| 497 } | 501 } |
| 498 | 502 |
| 499 | 503 |
| 500 static Condition TokenKindToDoubleCondition(Token::Kind kind) { | 504 static Condition TokenKindToDoubleCondition(Token::Kind kind) { |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 544 ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE)); | 548 ASSERT((kind() == Token::kEQ) || (kind() == Token::kNE)); |
| 545 | 549 |
| 546 Label is_true, is_false; | 550 Label is_true, is_false; |
| 547 BranchLabels labels = { &is_true, &is_false, &is_false }; | 551 BranchLabels labels = { &is_true, &is_false, &is_false }; |
| 548 Condition true_condition = EmitComparisonCode(compiler, labels); | 552 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 549 EmitBranchOnCondition(compiler, true_condition, labels); | 553 EmitBranchOnCondition(compiler, true_condition, labels); |
| 550 | 554 |
| 551 Register result = locs()->out(0).reg(); | 555 Register result = locs()->out(0).reg(); |
| 552 Label done; | 556 Label done; |
| 553 __ Bind(&is_false); | 557 __ Bind(&is_false); |
| 554 __ LoadObject(result, Bool::False(), PP); | 558 __ LoadObject(result, Bool::False()); |
| 555 __ jmp(&done); | 559 __ jmp(&done); |
| 556 __ Bind(&is_true); | 560 __ Bind(&is_true); |
| 557 __ LoadObject(result, Bool::True(), PP); | 561 __ LoadObject(result, Bool::True()); |
| 558 __ Bind(&done); | 562 __ Bind(&done); |
| 559 } | 563 } |
| 560 | 564 |
| 561 | 565 |
| 562 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 566 void EqualityCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 563 BranchInstr* branch) { | 567 BranchInstr* branch) { |
| 564 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); | 568 ASSERT((kind() == Token::kNE) || (kind() == Token::kEQ)); |
| 565 | 569 |
| 566 BranchLabels labels = compiler->CreateBranchLabels(branch); | 570 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 567 Condition true_condition = EmitComparisonCode(compiler, labels); | 571 Condition true_condition = EmitComparisonCode(compiler, labels); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 584 | 588 |
| 585 | 589 |
| 586 Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler, | 590 Condition TestSmiInstr::EmitComparisonCode(FlowGraphCompiler* compiler, |
| 587 BranchLabels labels) { | 591 BranchLabels labels) { |
| 588 Register left_reg = locs()->in(0).reg(); | 592 Register left_reg = locs()->in(0).reg(); |
| 589 Location right = locs()->in(1); | 593 Location right = locs()->in(1); |
| 590 if (right.IsConstant()) { | 594 if (right.IsConstant()) { |
| 591 ASSERT(right.constant().IsSmi()); | 595 ASSERT(right.constant().IsSmi()); |
| 592 const int64_t imm = | 596 const int64_t imm = |
| 593 reinterpret_cast<int64_t>(right.constant().raw()); | 597 reinterpret_cast<int64_t>(right.constant().raw()); |
| 594 __ TestImmediate(left_reg, Immediate(imm), PP); | 598 __ TestImmediate(left_reg, Immediate(imm)); |
| 595 } else { | 599 } else { |
| 596 __ testq(left_reg, right.reg()); | 600 __ testq(left_reg, right.reg()); |
| 597 } | 601 } |
| 598 Condition true_condition = (kind() == Token::kNE) ? NOT_ZERO : ZERO; | 602 Condition true_condition = (kind() == Token::kNE) ? NOT_ZERO : ZERO; |
| 599 return true_condition; | 603 return true_condition; |
| 600 } | 604 } |
| 601 | 605 |
| 602 | 606 |
| 603 void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 607 void TestSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 604 // Never emitted outside of the BranchInstr. | 608 // Never emitted outside of the BranchInstr. |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 672 EmitComparisonCode(compiler, labels); | 676 EmitComparisonCode(compiler, labels); |
| 673 } | 677 } |
| 674 | 678 |
| 675 | 679 |
| 676 void TestCidsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 680 void TestCidsInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 677 Register result_reg = locs()->out(0).reg(); | 681 Register result_reg = locs()->out(0).reg(); |
| 678 Label is_true, is_false, done; | 682 Label is_true, is_false, done; |
| 679 BranchLabels labels = { &is_true, &is_false, &is_false }; | 683 BranchLabels labels = { &is_true, &is_false, &is_false }; |
| 680 EmitComparisonCode(compiler, labels); | 684 EmitComparisonCode(compiler, labels); |
| 681 __ Bind(&is_false); | 685 __ Bind(&is_false); |
| 682 __ LoadObject(result_reg, Bool::False(), PP); | 686 __ LoadObject(result_reg, Bool::False()); |
| 683 __ jmp(&done, Assembler::kNearJump); | 687 __ jmp(&done, Assembler::kNearJump); |
| 684 __ Bind(&is_true); | 688 __ Bind(&is_true); |
| 685 __ LoadObject(result_reg, Bool::True(), PP); | 689 __ LoadObject(result_reg, Bool::True()); |
| 686 __ Bind(&done); | 690 __ Bind(&done); |
| 687 } | 691 } |
| 688 | 692 |
| 689 | 693 |
| 690 LocationSummary* RelationalOpInstr::MakeLocationSummary(Zone* zone, | 694 LocationSummary* RelationalOpInstr::MakeLocationSummary(Zone* zone, |
| 691 bool opt) const { | 695 bool opt) const { |
| 692 const intptr_t kNumInputs = 2; | 696 const intptr_t kNumInputs = 2; |
| 693 const intptr_t kNumTemps = 0; | 697 const intptr_t kNumTemps = 0; |
| 694 if (operation_cid() == kDoubleCid) { | 698 if (operation_cid() == kDoubleCid) { |
| 695 LocationSummary* summary = new(zone) LocationSummary( | 699 LocationSummary* summary = new(zone) LocationSummary( |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 733 | 737 |
| 734 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 738 void RelationalOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 735 Label is_true, is_false; | 739 Label is_true, is_false; |
| 736 BranchLabels labels = { &is_true, &is_false, &is_false }; | 740 BranchLabels labels = { &is_true, &is_false, &is_false }; |
| 737 Condition true_condition = EmitComparisonCode(compiler, labels); | 741 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 738 EmitBranchOnCondition(compiler, true_condition, labels); | 742 EmitBranchOnCondition(compiler, true_condition, labels); |
| 739 | 743 |
| 740 Register result = locs()->out(0).reg(); | 744 Register result = locs()->out(0).reg(); |
| 741 Label done; | 745 Label done; |
| 742 __ Bind(&is_false); | 746 __ Bind(&is_false); |
| 743 __ LoadObject(result, Bool::False(), PP); | 747 __ LoadObject(result, Bool::False()); |
| 744 __ jmp(&done); | 748 __ jmp(&done); |
| 745 __ Bind(&is_true); | 749 __ Bind(&is_true); |
| 746 __ LoadObject(result, Bool::True(), PP); | 750 __ LoadObject(result, Bool::True()); |
| 747 __ Bind(&done); | 751 __ Bind(&done); |
| 748 } | 752 } |
| 749 | 753 |
| 750 | 754 |
| 751 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 755 void RelationalOpInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 752 BranchInstr* branch) { | 756 BranchInstr* branch) { |
| 753 BranchLabels labels = compiler->CreateBranchLabels(branch); | 757 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 754 Condition true_condition = EmitComparisonCode(compiler, labels); | 758 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 755 EmitBranchOnCondition(compiler, true_condition, labels); | 759 EmitBranchOnCondition(compiler, true_condition, labels); |
| 756 } | 760 } |
| 757 | 761 |
| 758 | 762 |
| 759 LocationSummary* NativeCallInstr::MakeLocationSummary(Zone* zone, | 763 LocationSummary* NativeCallInstr::MakeLocationSummary(Zone* zone, |
| 760 bool opt) const { | 764 bool opt) const { |
| 761 return MakeCallSummary(zone); | 765 return MakeCallSummary(zone); |
| 762 } | 766 } |
| 763 | 767 |
| 764 | 768 |
| 765 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 769 void NativeCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 766 Register result = locs()->out(0).reg(); | 770 Register result = locs()->out(0).reg(); |
| 767 const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function()); | 771 const intptr_t argc_tag = NativeArguments::ComputeArgcTag(function()); |
| 768 const bool is_leaf_call = | 772 const bool is_leaf_call = |
| 769 (argc_tag & NativeArguments::AutoSetupScopeMask()) == 0; | 773 (argc_tag & NativeArguments::AutoSetupScopeMask()) == 0; |
| 770 | 774 |
| 771 // Push the result place holder initialized to NULL. | 775 // Push the result place holder initialized to NULL. |
| 772 __ PushObject(Object::null_object(), PP); | 776 __ PushObject(Object::null_object()); |
| 773 // Pass a pointer to the first argument in RAX. | 777 // Pass a pointer to the first argument in RAX. |
| 774 if (!function().HasOptionalParameters()) { | 778 if (!function().HasOptionalParameters()) { |
| 775 __ leaq(RAX, Address(RBP, (kParamEndSlotFromFp + | 779 __ leaq(RAX, Address(RBP, (kParamEndSlotFromFp + |
| 776 function().NumParameters()) * kWordSize)); | 780 function().NumParameters()) * kWordSize)); |
| 777 } else { | 781 } else { |
| 778 __ leaq(RAX, | 782 __ leaq(RAX, Address(RBP, kFirstLocalSlotFromFp * kWordSize)); |
| 779 Address(RBP, kFirstLocalSlotFromFp * kWordSize)); | |
| 780 } | 783 } |
| 781 __ LoadImmediate( | 784 __ LoadImmediate( |
| 782 RBX, Immediate(reinterpret_cast<uword>(native_c_function())), PP); | 785 RBX, Immediate(reinterpret_cast<uword>(native_c_function()))); |
| 783 __ LoadImmediate( | 786 __ LoadImmediate(R10, Immediate(argc_tag)); |
| 784 R10, Immediate(argc_tag), PP); | |
| 785 const ExternalLabel* stub_entry = (is_bootstrap_native() || is_leaf_call) ? | 787 const ExternalLabel* stub_entry = (is_bootstrap_native() || is_leaf_call) ? |
| 786 &StubCode::CallBootstrapCFunctionLabel() : | 788 &StubCode::CallBootstrapCFunctionLabel() : |
| 787 &StubCode::CallNativeCFunctionLabel(); | 789 &StubCode::CallNativeCFunctionLabel(); |
| 788 compiler->GenerateCall(token_pos(), | 790 compiler->GenerateCall(token_pos(), |
| 789 stub_entry, | 791 stub_entry, |
| 790 RawPcDescriptors::kOther, | 792 RawPcDescriptors::kOther, |
| 791 locs()); | 793 locs()); |
| 792 __ popq(result); | 794 __ popq(result); |
| 793 } | 795 } |
| 794 | 796 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 814 Location::RequiresRegister(), | 816 Location::RequiresRegister(), |
| 815 LocationSummary::kNoCall); | 817 LocationSummary::kNoCall); |
| 816 } | 818 } |
| 817 | 819 |
| 818 | 820 |
| 819 void StringFromCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 821 void StringFromCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 820 ASSERT(compiler->is_optimizing()); | 822 ASSERT(compiler->is_optimizing()); |
| 821 Register char_code = locs()->in(0).reg(); | 823 Register char_code = locs()->in(0).reg(); |
| 822 Register result = locs()->out(0).reg(); | 824 Register result = locs()->out(0).reg(); |
| 823 __ LoadImmediate(result, | 825 __ LoadImmediate(result, |
| 824 Immediate(reinterpret_cast<uword>(Symbols::PredefinedAddress())), PP); | 826 Immediate(reinterpret_cast<uword>(Symbols::PredefinedAddress()))); |
| 825 __ movq(result, Address(result, | 827 __ movq(result, Address(result, |
| 826 char_code, | 828 char_code, |
| 827 TIMES_HALF_WORD_SIZE, // Char code is a smi. | 829 TIMES_HALF_WORD_SIZE, // Char code is a smi. |
| 828 Symbols::kNullCharCodeSymbolOffset * kWordSize)); | 830 Symbols::kNullCharCodeSymbolOffset * kWordSize)); |
| 829 } | 831 } |
| 830 | 832 |
| 831 | 833 |
| 832 LocationSummary* StringToCharCodeInstr::MakeLocationSummary(Zone* zone, | 834 LocationSummary* StringToCharCodeInstr::MakeLocationSummary(Zone* zone, |
| 833 bool opt) const { | 835 bool opt) const { |
| 834 const intptr_t kNumInputs = 1; | 836 const intptr_t kNumInputs = 1; |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 919 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 921 void LoadClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 920 const Register object = locs()->in(0).reg(); | 922 const Register object = locs()->in(0).reg(); |
| 921 const Register result = locs()->out(0).reg(); | 923 const Register result = locs()->out(0).reg(); |
| 922 Label load, done; | 924 Label load, done; |
| 923 | 925 |
| 924 // We don't use Assembler::LoadTaggedClassIdMayBeSmi() here---which uses | 926 // We don't use Assembler::LoadTaggedClassIdMayBeSmi() here---which uses |
| 925 // a conditional move instead---because it is slower, probably due to | 927 // a conditional move instead---because it is slower, probably due to |
| 926 // branch prediction usually working just fine in this case. | 928 // branch prediction usually working just fine in this case. |
| 927 __ testq(object, Immediate(kSmiTagMask)); | 929 __ testq(object, Immediate(kSmiTagMask)); |
| 928 __ j(NOT_ZERO, &load, Assembler::kNearJump); | 930 __ j(NOT_ZERO, &load, Assembler::kNearJump); |
| 929 __ LoadImmediate(result, Immediate(Smi::RawValue(kSmiCid)), PP); | 931 __ LoadImmediate(result, Immediate(Smi::RawValue(kSmiCid))); |
| 930 __ jmp(&done); | 932 __ jmp(&done); |
| 931 __ Bind(&load); | 933 __ Bind(&load); |
| 932 __ LoadClassId(result, object); | 934 __ LoadClassId(result, object); |
| 933 __ SmiTag(result); | 935 __ SmiTag(result); |
| 934 __ Bind(&done); | 936 __ Bind(&done); |
| 935 } | 937 } |
| 936 | 938 |
| 937 | 939 |
| 938 CompileType LoadIndexedInstr::ComputeType() const { | 940 CompileType LoadIndexedInstr::ComputeType() const { |
| 939 switch (class_id_) { | 941 switch (class_id_) { |
| (...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1312 if ((index_scale() == 1) && index.IsRegister()) { | 1314 if ((index_scale() == 1) && index.IsRegister()) { |
| 1313 __ SmiUntag(index.reg()); | 1315 __ SmiUntag(index.reg()); |
| 1314 } | 1316 } |
| 1315 switch (class_id()) { | 1317 switch (class_id()) { |
| 1316 case kArrayCid: | 1318 case kArrayCid: |
| 1317 if (ShouldEmitStoreBarrier()) { | 1319 if (ShouldEmitStoreBarrier()) { |
| 1318 Register value = locs()->in(2).reg(); | 1320 Register value = locs()->in(2).reg(); |
| 1319 __ StoreIntoObject(array, element_address, value); | 1321 __ StoreIntoObject(array, element_address, value); |
| 1320 } else if (locs()->in(2).IsConstant()) { | 1322 } else if (locs()->in(2).IsConstant()) { |
| 1321 const Object& constant = locs()->in(2).constant(); | 1323 const Object& constant = locs()->in(2).constant(); |
| 1322 __ StoreIntoObjectNoBarrier(array, element_address, constant, PP); | 1324 __ StoreIntoObjectNoBarrier(array, element_address, constant); |
| 1323 } else { | 1325 } else { |
| 1324 Register value = locs()->in(2).reg(); | 1326 Register value = locs()->in(2).reg(); |
| 1325 __ StoreIntoObjectNoBarrier(array, element_address, value); | 1327 __ StoreIntoObjectNoBarrier(array, element_address, value); |
| 1326 } | 1328 } |
| 1327 break; | 1329 break; |
| 1328 case kTypedDataInt8ArrayCid: | 1330 case kTypedDataInt8ArrayCid: |
| 1329 case kTypedDataUint8ArrayCid: | 1331 case kTypedDataUint8ArrayCid: |
| 1330 case kExternalTypedDataUint8ArrayCid: | 1332 case kExternalTypedDataUint8ArrayCid: |
| 1331 case kOneByteStringCid: | 1333 case kOneByteStringCid: |
| 1332 if (locs()->in(2).IsConstant()) { | 1334 if (locs()->in(2).IsConstant()) { |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1349 value = 0xFF; | 1351 value = 0xFF; |
| 1350 } else if (value < 0) { | 1352 } else if (value < 0) { |
| 1351 value = 0; | 1353 value = 0; |
| 1352 } | 1354 } |
| 1353 __ movb(element_address, | 1355 __ movb(element_address, |
| 1354 Immediate(static_cast<int8_t>(value))); | 1356 Immediate(static_cast<int8_t>(value))); |
| 1355 } else { | 1357 } else { |
| 1356 ASSERT(locs()->in(2).reg() == RAX); | 1358 ASSERT(locs()->in(2).reg() == RAX); |
| 1357 Label store_value, store_0xff; | 1359 Label store_value, store_0xff; |
| 1358 __ SmiUntag(RAX); | 1360 __ SmiUntag(RAX); |
| 1359 __ CompareImmediate(RAX, Immediate(0xFF), PP); | 1361 __ CompareImmediate(RAX, Immediate(0xFF)); |
| 1360 __ j(BELOW_EQUAL, &store_value, Assembler::kNearJump); | 1362 __ j(BELOW_EQUAL, &store_value, Assembler::kNearJump); |
| 1361 // Clamp to 0x0 or 0xFF respectively. | 1363 // Clamp to 0x0 or 0xFF respectively. |
| 1362 __ j(GREATER, &store_0xff); | 1364 __ j(GREATER, &store_0xff); |
| 1363 __ xorq(RAX, RAX); | 1365 __ xorq(RAX, RAX); |
| 1364 __ jmp(&store_value, Assembler::kNearJump); | 1366 __ jmp(&store_value, Assembler::kNearJump); |
| 1365 __ Bind(&store_0xff); | 1367 __ Bind(&store_0xff); |
| 1366 __ LoadImmediate(RAX, Immediate(0xFF), PP); | 1368 __ LoadImmediate(RAX, Immediate(0xFF)); |
| 1367 __ Bind(&store_value); | 1369 __ Bind(&store_value); |
| 1368 __ movb(element_address, RAX); | 1370 __ movb(element_address, RAX); |
| 1369 } | 1371 } |
| 1370 break; | 1372 break; |
| 1371 } | 1373 } |
| 1372 case kTypedDataInt16ArrayCid: | 1374 case kTypedDataInt16ArrayCid: |
| 1373 case kTypedDataUint16ArrayCid: { | 1375 case kTypedDataUint16ArrayCid: { |
| 1374 Register value = locs()->in(2).reg(); | 1376 Register value = locs()->in(2).reg(); |
| 1375 __ SmiUntag(value); | 1377 __ SmiUntag(value); |
| 1376 __ movw(element_address, value); | 1378 __ movw(element_address, value); |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1465 locs()->temp(locs()->temp_count() - 1).reg() : kNoRegister; | 1467 locs()->temp(locs()->temp_count() - 1).reg() : kNoRegister; |
| 1466 | 1468 |
| 1467 Label ok, fail_label; | 1469 Label ok, fail_label; |
| 1468 | 1470 |
| 1469 Label* deopt = compiler->is_optimizing() ? | 1471 Label* deopt = compiler->is_optimizing() ? |
| 1470 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) : NULL; | 1472 compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField) : NULL; |
| 1471 | 1473 |
| 1472 Label* fail = (deopt != NULL) ? deopt : &fail_label; | 1474 Label* fail = (deopt != NULL) ? deopt : &fail_label; |
| 1473 | 1475 |
| 1474 if (emit_full_guard) { | 1476 if (emit_full_guard) { |
| 1475 __ LoadObject(field_reg, Field::ZoneHandle(field().raw()), PP); | 1477 __ LoadObject(field_reg, Field::ZoneHandle(field().raw())); |
| 1476 | 1478 |
| 1477 FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset()); | 1479 FieldAddress field_cid_operand(field_reg, Field::guarded_cid_offset()); |
| 1478 FieldAddress field_nullability_operand( | 1480 FieldAddress field_nullability_operand( |
| 1479 field_reg, Field::is_nullable_offset()); | 1481 field_reg, Field::is_nullable_offset()); |
| 1480 | 1482 |
| 1481 if (value_cid == kDynamicCid) { | 1483 if (value_cid == kDynamicCid) { |
| 1482 LoadValueCid(compiler, value_cid_reg, value_reg); | 1484 LoadValueCid(compiler, value_cid_reg, value_reg); |
| 1483 | 1485 |
| 1484 __ cmpl(value_cid_reg, field_cid_operand); | 1486 __ cmpl(value_cid_reg, field_cid_operand); |
| 1485 __ j(EQUAL, &ok); | 1487 __ j(EQUAL, &ok); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1534 ASSERT(deopt != NULL); | 1536 ASSERT(deopt != NULL); |
| 1535 | 1537 |
| 1536 // Field guard class has been initialized and is known. | 1538 // Field guard class has been initialized and is known. |
| 1537 if (value_cid == kDynamicCid) { | 1539 if (value_cid == kDynamicCid) { |
| 1538 // Value's class id is not known. | 1540 // Value's class id is not known. |
| 1539 __ testq(value_reg, Immediate(kSmiTagMask)); | 1541 __ testq(value_reg, Immediate(kSmiTagMask)); |
| 1540 | 1542 |
| 1541 if (field_cid != kSmiCid) { | 1543 if (field_cid != kSmiCid) { |
| 1542 __ j(ZERO, fail); | 1544 __ j(ZERO, fail); |
| 1543 __ LoadClassId(value_cid_reg, value_reg); | 1545 __ LoadClassId(value_cid_reg, value_reg); |
| 1544 __ CompareImmediate(value_cid_reg, Immediate(field_cid), PP); | 1546 __ CompareImmediate(value_cid_reg, Immediate(field_cid)); |
| 1545 } | 1547 } |
| 1546 | 1548 |
| 1547 if (field().is_nullable() && (field_cid != kNullCid)) { | 1549 if (field().is_nullable() && (field_cid != kNullCid)) { |
| 1548 __ j(EQUAL, &ok); | 1550 __ j(EQUAL, &ok); |
| 1549 __ CompareObject(value_reg, Object::null_object(), PP); | 1551 __ CompareObject(value_reg, Object::null_object()); |
| 1550 } | 1552 } |
| 1551 | 1553 |
| 1552 __ j(NOT_EQUAL, fail); | 1554 __ j(NOT_EQUAL, fail); |
| 1553 } else { | 1555 } else { |
| 1554 // Both value's and field's class id is known. | 1556 // Both value's and field's class id is known. |
| 1555 ASSERT((value_cid != field_cid) && (value_cid != nullability)); | 1557 ASSERT((value_cid != field_cid) && (value_cid != nullability)); |
| 1556 __ jmp(fail); | 1558 __ jmp(fail); |
| 1557 } | 1559 } |
| 1558 } | 1560 } |
| 1559 __ Bind(&ok); | 1561 __ Bind(&ok); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1595 const Register value_reg = locs()->in(0).reg(); | 1597 const Register value_reg = locs()->in(0).reg(); |
| 1596 | 1598 |
| 1597 if (!compiler->is_optimizing() || | 1599 if (!compiler->is_optimizing() || |
| 1598 (field().guarded_list_length() == Field::kUnknownFixedLength)) { | 1600 (field().guarded_list_length() == Field::kUnknownFixedLength)) { |
| 1599 const Register field_reg = locs()->temp(0).reg(); | 1601 const Register field_reg = locs()->temp(0).reg(); |
| 1600 const Register offset_reg = locs()->temp(1).reg(); | 1602 const Register offset_reg = locs()->temp(1).reg(); |
| 1601 const Register length_reg = locs()->temp(2).reg(); | 1603 const Register length_reg = locs()->temp(2).reg(); |
| 1602 | 1604 |
| 1603 Label ok; | 1605 Label ok; |
| 1604 | 1606 |
| 1605 __ LoadObject(field_reg, Field::ZoneHandle(field().raw()), PP); | 1607 __ LoadObject(field_reg, Field::ZoneHandle(field().raw())); |
| 1606 | 1608 |
| 1607 __ movsxb(offset_reg, FieldAddress(field_reg, | 1609 __ movsxb(offset_reg, FieldAddress(field_reg, |
| 1608 Field::guarded_list_length_in_object_offset_offset())); | 1610 Field::guarded_list_length_in_object_offset_offset())); |
| 1609 __ movq(length_reg, FieldAddress(field_reg, | 1611 __ movq(length_reg, FieldAddress(field_reg, |
| 1610 Field::guarded_list_length_offset())); | 1612 Field::guarded_list_length_offset())); |
| 1611 | 1613 |
| 1612 __ cmpq(offset_reg, Immediate(0)); | 1614 __ cmpq(offset_reg, Immediate(0)); |
| 1613 __ j(NEGATIVE, &ok); | 1615 __ j(NEGATIVE, &ok); |
| 1614 | 1616 |
| 1615 // Load the length from the value. GuardFieldClass already verified that | 1617 // Load the length from the value. GuardFieldClass already verified that |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1632 __ Bind(&ok); | 1634 __ Bind(&ok); |
| 1633 } else { | 1635 } else { |
| 1634 ASSERT(compiler->is_optimizing()); | 1636 ASSERT(compiler->is_optimizing()); |
| 1635 ASSERT(field().guarded_list_length() >= 0); | 1637 ASSERT(field().guarded_list_length() >= 0); |
| 1636 ASSERT(field().guarded_list_length_in_object_offset() != | 1638 ASSERT(field().guarded_list_length_in_object_offset() != |
| 1637 Field::kUnknownLengthOffset); | 1639 Field::kUnknownLengthOffset); |
| 1638 | 1640 |
| 1639 __ CompareImmediate( | 1641 __ CompareImmediate( |
| 1640 FieldAddress(value_reg, | 1642 FieldAddress(value_reg, |
| 1641 field().guarded_list_length_in_object_offset()), | 1643 field().guarded_list_length_in_object_offset()), |
| 1642 Immediate(Smi::RawValue(field().guarded_list_length())), | 1644 Immediate(Smi::RawValue(field().guarded_list_length()))); |
| 1643 PP); | |
| 1644 __ j(NOT_EQUAL, deopt); | 1645 __ j(NOT_EQUAL, deopt); |
| 1645 } | 1646 } |
| 1646 } | 1647 } |
| 1647 | 1648 |
| 1648 | 1649 |
| 1649 class BoxAllocationSlowPath : public SlowPathCode { | 1650 class BoxAllocationSlowPath : public SlowPathCode { |
| 1650 public: | 1651 public: |
| 1651 BoxAllocationSlowPath(Instruction* instruction, | 1652 BoxAllocationSlowPath(Instruction* instruction, |
| 1652 const Class& cls, | 1653 const Class& cls, |
| 1653 Register result) | 1654 Register result) |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1683 } | 1684 } |
| 1684 | 1685 |
| 1685 static void Allocate(FlowGraphCompiler* compiler, | 1686 static void Allocate(FlowGraphCompiler* compiler, |
| 1686 Instruction* instruction, | 1687 Instruction* instruction, |
| 1687 const Class& cls, | 1688 const Class& cls, |
| 1688 Register result) { | 1689 Register result) { |
| 1689 if (compiler->intrinsic_mode()) { | 1690 if (compiler->intrinsic_mode()) { |
| 1690 __ TryAllocate(cls, | 1691 __ TryAllocate(cls, |
| 1691 compiler->intrinsic_slow_path_label(), | 1692 compiler->intrinsic_slow_path_label(), |
| 1692 Assembler::kFarJump, | 1693 Assembler::kFarJump, |
| 1693 result, | 1694 result); |
| 1694 PP); | |
| 1695 } else { | 1695 } else { |
| 1696 BoxAllocationSlowPath* slow_path = | 1696 BoxAllocationSlowPath* slow_path = |
| 1697 new BoxAllocationSlowPath(instruction, cls, result); | 1697 new BoxAllocationSlowPath(instruction, cls, result); |
| 1698 compiler->AddSlowPathCode(slow_path); | 1698 compiler->AddSlowPathCode(slow_path); |
| 1699 | 1699 |
| 1700 __ TryAllocate(cls, | 1700 __ TryAllocate(cls, |
| 1701 slow_path->entry_label(), | 1701 slow_path->entry_label(), |
| 1702 Assembler::kFarJump, | 1702 Assembler::kFarJump, |
| 1703 result, | 1703 result); |
| 1704 PP); | |
| 1705 __ Bind(slow_path->exit_label()); | 1704 __ Bind(slow_path->exit_label()); |
| 1706 } | 1705 } |
| 1707 } | 1706 } |
| 1708 | 1707 |
| 1709 private: | 1708 private: |
| 1710 Instruction* instruction_; | 1709 Instruction* instruction_; |
| 1711 const Class& cls_; | 1710 const Class& cls_; |
| 1712 const Register result_; | 1711 const Register result_; |
| 1713 }; | 1712 }; |
| 1714 | 1713 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1750 | 1749 |
| 1751 static void EnsureMutableBox(FlowGraphCompiler* compiler, | 1750 static void EnsureMutableBox(FlowGraphCompiler* compiler, |
| 1752 StoreInstanceFieldInstr* instruction, | 1751 StoreInstanceFieldInstr* instruction, |
| 1753 Register box_reg, | 1752 Register box_reg, |
| 1754 const Class& cls, | 1753 const Class& cls, |
| 1755 Register instance_reg, | 1754 Register instance_reg, |
| 1756 intptr_t offset, | 1755 intptr_t offset, |
| 1757 Register temp) { | 1756 Register temp) { |
| 1758 Label done; | 1757 Label done; |
| 1759 __ movq(box_reg, FieldAddress(instance_reg, offset)); | 1758 __ movq(box_reg, FieldAddress(instance_reg, offset)); |
| 1760 __ CompareObject(box_reg, Object::null_object(), PP); | 1759 __ CompareObject(box_reg, Object::null_object()); |
| 1761 __ j(NOT_EQUAL, &done); | 1760 __ j(NOT_EQUAL, &done); |
| 1762 BoxAllocationSlowPath::Allocate(compiler, instruction, cls, box_reg); | 1761 BoxAllocationSlowPath::Allocate(compiler, instruction, cls, box_reg); |
| 1763 __ movq(temp, box_reg); | 1762 __ movq(temp, box_reg); |
| 1764 __ StoreIntoObject(instance_reg, | 1763 __ StoreIntoObject(instance_reg, |
| 1765 FieldAddress(instance_reg, offset), | 1764 FieldAddress(instance_reg, offset), |
| 1766 temp); | 1765 temp); |
| 1767 | 1766 |
| 1768 __ Bind(&done); | 1767 __ Bind(&done); |
| 1769 } | 1768 } |
| 1770 | 1769 |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1834 // Value input is a writable register and should be manually preserved | 1833 // Value input is a writable register and should be manually preserved |
| 1835 // across allocation slow-path. | 1834 // across allocation slow-path. |
| 1836 locs()->live_registers()->Add(locs()->in(1), kTagged); | 1835 locs()->live_registers()->Add(locs()->in(1), kTagged); |
| 1837 } | 1836 } |
| 1838 | 1837 |
| 1839 Label store_pointer; | 1838 Label store_pointer; |
| 1840 Label store_double; | 1839 Label store_double; |
| 1841 Label store_float32x4; | 1840 Label store_float32x4; |
| 1842 Label store_float64x2; | 1841 Label store_float64x2; |
| 1843 | 1842 |
| 1844 __ LoadObject(temp, Field::ZoneHandle(field().raw()), PP); | 1843 __ LoadObject(temp, Field::ZoneHandle(field().raw())); |
| 1845 | 1844 |
| 1846 __ cmpl(FieldAddress(temp, Field::is_nullable_offset()), | 1845 __ cmpl(FieldAddress(temp, Field::is_nullable_offset()), |
| 1847 Immediate(kNullCid)); | 1846 Immediate(kNullCid)); |
| 1848 __ j(EQUAL, &store_pointer); | 1847 __ j(EQUAL, &store_pointer); |
| 1849 | 1848 |
| 1850 __ movzxb(temp2, FieldAddress(temp, Field::kind_bits_offset())); | 1849 __ movzxb(temp2, FieldAddress(temp, Field::kind_bits_offset())); |
| 1851 __ testq(temp2, Immediate(1 << Field::kUnboxingCandidateBit)); | 1850 __ testq(temp2, Immediate(1 << Field::kUnboxingCandidateBit)); |
| 1852 __ j(ZERO, &store_pointer); | 1851 __ j(ZERO, &store_pointer); |
| 1853 | 1852 |
| 1854 __ cmpl(FieldAddress(temp, Field::guarded_cid_offset()), | 1853 __ cmpl(FieldAddress(temp, Field::guarded_cid_offset()), |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1920 Register value_reg = locs()->in(1).reg(); | 1919 Register value_reg = locs()->in(1).reg(); |
| 1921 __ StoreIntoObject(instance_reg, | 1920 __ StoreIntoObject(instance_reg, |
| 1922 FieldAddress(instance_reg, offset_in_bytes_), | 1921 FieldAddress(instance_reg, offset_in_bytes_), |
| 1923 value_reg, | 1922 value_reg, |
| 1924 CanValueBeSmi()); | 1923 CanValueBeSmi()); |
| 1925 } else { | 1924 } else { |
| 1926 if (locs()->in(1).IsConstant()) { | 1925 if (locs()->in(1).IsConstant()) { |
| 1927 __ StoreIntoObjectNoBarrier(instance_reg, | 1926 __ StoreIntoObjectNoBarrier(instance_reg, |
| 1928 FieldAddress(instance_reg, offset_in_bytes_), | 1927 FieldAddress(instance_reg, offset_in_bytes_), |
| 1929 locs()->in(1).constant(), | 1928 locs()->in(1).constant(), |
| 1930 PP, | |
| 1931 is_object_reference_initialization_ ? | 1929 is_object_reference_initialization_ ? |
| 1932 Assembler::kEmptyOrSmiOrNull : | 1930 Assembler::kEmptyOrSmiOrNull : |
| 1933 Assembler::kHeapObjectOrSmi); | 1931 Assembler::kHeapObjectOrSmi); |
| 1934 } else { | 1932 } else { |
| 1935 Register value_reg = locs()->in(1).reg(); | 1933 Register value_reg = locs()->in(1).reg(); |
| 1936 __ StoreIntoObjectNoBarrier(instance_reg, | 1934 __ StoreIntoObjectNoBarrier(instance_reg, |
| 1937 FieldAddress(instance_reg, offset_in_bytes_), | 1935 FieldAddress(instance_reg, offset_in_bytes_), |
| 1938 value_reg, | 1936 value_reg, |
| 1939 is_object_reference_initialization_ ? | 1937 is_object_reference_initialization_ ? |
| 1940 Assembler::kEmptyOrSmiOrNull : | 1938 Assembler::kEmptyOrSmiOrNull : |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1977 : Location::RequiresRegister()); | 1975 : Location::RequiresRegister()); |
| 1978 locs->set_temp(0, Location::RequiresRegister()); | 1976 locs->set_temp(0, Location::RequiresRegister()); |
| 1979 return locs; | 1977 return locs; |
| 1980 } | 1978 } |
| 1981 | 1979 |
| 1982 | 1980 |
| 1983 void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 1981 void StoreStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 1984 Register value = locs()->in(0).reg(); | 1982 Register value = locs()->in(0).reg(); |
| 1985 Register temp = locs()->temp(0).reg(); | 1983 Register temp = locs()->temp(0).reg(); |
| 1986 | 1984 |
| 1987 __ LoadObject(temp, field(), PP); | 1985 __ LoadObject(temp, field()); |
| 1988 if (this->value()->NeedsStoreBuffer()) { | 1986 if (this->value()->NeedsStoreBuffer()) { |
| 1989 __ StoreIntoObject(temp, | 1987 __ StoreIntoObject(temp, |
| 1990 FieldAddress(temp, Field::value_offset()), value, CanValueBeSmi()); | 1988 FieldAddress(temp, Field::value_offset()), value, CanValueBeSmi()); |
| 1991 } else { | 1989 } else { |
| 1992 __ StoreIntoObjectNoBarrier( | 1990 __ StoreIntoObjectNoBarrier( |
| 1993 temp, FieldAddress(temp, Field::value_offset()), value); | 1991 temp, FieldAddress(temp, Field::value_offset()), value); |
| 1994 } | 1992 } |
| 1995 } | 1993 } |
| 1996 | 1994 |
| 1997 | 1995 |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2063 FieldAddress(RAX, Array::length_offset()), | 2061 FieldAddress(RAX, Array::length_offset()), |
| 2064 kLengthReg); | 2062 kLengthReg); |
| 2065 | 2063 |
| 2066 // Initialize all array elements to raw_null. | 2064 // Initialize all array elements to raw_null. |
| 2067 // RAX: new object start as a tagged pointer. | 2065 // RAX: new object start as a tagged pointer. |
| 2068 // RCX: new object end address. | 2066 // RCX: new object end address. |
| 2069 // RDI: iterator which initially points to the start of the variable | 2067 // RDI: iterator which initially points to the start of the variable |
| 2070 // data area to be initialized. | 2068 // data area to be initialized. |
| 2071 if (num_elements > 0) { | 2069 if (num_elements > 0) { |
| 2072 const intptr_t array_size = instance_size - sizeof(RawArray); | 2070 const intptr_t array_size = instance_size - sizeof(RawArray); |
| 2073 __ LoadObject(R12, Object::null_object(), PP); | 2071 __ LoadObject(R12, Object::null_object()); |
| 2074 __ leaq(RDI, FieldAddress(RAX, sizeof(RawArray))); | 2072 __ leaq(RDI, FieldAddress(RAX, sizeof(RawArray))); |
| 2075 if (array_size < (kInlineArraySize * kWordSize)) { | 2073 if (array_size < (kInlineArraySize * kWordSize)) { |
| 2076 intptr_t current_offset = 0; | 2074 intptr_t current_offset = 0; |
| 2077 while (current_offset < array_size) { | 2075 while (current_offset < array_size) { |
| 2078 __ InitializeFieldNoBarrier(RAX, Address(RDI, current_offset), R12); | 2076 __ InitializeFieldNoBarrier(RAX, Address(RDI, current_offset), R12); |
| 2079 current_offset += kWordSize; | 2077 current_offset += kWordSize; |
| 2080 } | 2078 } |
| 2081 } else { | 2079 } else { |
| 2082 Label init_loop; | 2080 Label init_loop; |
| 2083 __ Bind(&init_loop); | 2081 __ Bind(&init_loop); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 2101 | 2099 |
| 2102 Label slow_path, done; | 2100 Label slow_path, done; |
| 2103 if (compiler->is_optimizing() && | 2101 if (compiler->is_optimizing() && |
| 2104 num_elements()->BindsToConstant() && | 2102 num_elements()->BindsToConstant() && |
| 2105 num_elements()->BoundConstant().IsSmi()) { | 2103 num_elements()->BoundConstant().IsSmi()) { |
| 2106 const intptr_t length = Smi::Cast(num_elements()->BoundConstant()).Value(); | 2104 const intptr_t length = Smi::Cast(num_elements()->BoundConstant()).Value(); |
| 2107 if ((length >= 0) && (length <= Array::kMaxElements)) { | 2105 if ((length >= 0) && (length <= Array::kMaxElements)) { |
| 2108 Label slow_path, done; | 2106 Label slow_path, done; |
| 2109 InlineArrayAllocation(compiler, length, &slow_path, &done); | 2107 InlineArrayAllocation(compiler, length, &slow_path, &done); |
| 2110 __ Bind(&slow_path); | 2108 __ Bind(&slow_path); |
| 2111 __ PushObject(Object::null_object(), PP); // Make room for the result. | 2109 __ PushObject(Object::null_object()); // Make room for the result. |
| 2112 __ pushq(kLengthReg); | 2110 __ pushq(kLengthReg); |
| 2113 __ pushq(kElemTypeReg); | 2111 __ pushq(kElemTypeReg); |
| 2114 compiler->GenerateRuntimeCall(token_pos(), | 2112 compiler->GenerateRuntimeCall(token_pos(), |
| 2115 deopt_id(), | 2113 deopt_id(), |
| 2116 kAllocateArrayRuntimeEntry, | 2114 kAllocateArrayRuntimeEntry, |
| 2117 2, | 2115 2, |
| 2118 locs()); | 2116 locs()); |
| 2119 __ Drop(2); | 2117 __ Drop(2); |
| 2120 __ popq(kResultReg); | 2118 __ popq(kResultReg); |
| 2121 __ Bind(&done); | 2119 __ Bind(&done); |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2191 Register result = locs()->out(0).reg(); | 2189 Register result = locs()->out(0).reg(); |
| 2192 if (IsPotentialUnboxedLoad()) { | 2190 if (IsPotentialUnboxedLoad()) { |
| 2193 Register temp = locs()->temp(1).reg(); | 2191 Register temp = locs()->temp(1).reg(); |
| 2194 XmmRegister value = locs()->temp(0).fpu_reg(); | 2192 XmmRegister value = locs()->temp(0).fpu_reg(); |
| 2195 | 2193 |
| 2196 Label load_pointer; | 2194 Label load_pointer; |
| 2197 Label load_double; | 2195 Label load_double; |
| 2198 Label load_float32x4; | 2196 Label load_float32x4; |
| 2199 Label load_float64x2; | 2197 Label load_float64x2; |
| 2200 | 2198 |
| 2201 __ LoadObject(result, Field::ZoneHandle(field()->raw()), PP); | 2199 __ LoadObject(result, Field::ZoneHandle(field()->raw())); |
| 2202 | 2200 |
| 2203 __ cmpl(FieldAddress(result, Field::is_nullable_offset()), | 2201 __ cmpl(FieldAddress(result, Field::is_nullable_offset()), |
| 2204 Immediate(kNullCid)); | 2202 Immediate(kNullCid)); |
| 2205 __ j(EQUAL, &load_pointer); | 2203 __ j(EQUAL, &load_pointer); |
| 2206 | 2204 |
| 2207 __ cmpl(FieldAddress(result, Field::guarded_cid_offset()), | 2205 __ cmpl(FieldAddress(result, Field::guarded_cid_offset()), |
| 2208 Immediate(kDoubleCid)); | 2206 Immediate(kDoubleCid)); |
| 2209 __ j(EQUAL, &load_double); | 2207 __ j(EQUAL, &load_double); |
| 2210 | 2208 |
| 2211 __ cmpl(FieldAddress(result, Field::guarded_cid_offset()), | 2209 __ cmpl(FieldAddress(result, Field::guarded_cid_offset()), |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2271 return locs; | 2269 return locs; |
| 2272 } | 2270 } |
| 2273 | 2271 |
| 2274 | 2272 |
| 2275 void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2273 void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2276 Register instantiator_reg = locs()->in(0).reg(); | 2274 Register instantiator_reg = locs()->in(0).reg(); |
| 2277 Register result_reg = locs()->out(0).reg(); | 2275 Register result_reg = locs()->out(0).reg(); |
| 2278 | 2276 |
| 2279 // 'instantiator_reg' is the instantiator TypeArguments object (or null). | 2277 // 'instantiator_reg' is the instantiator TypeArguments object (or null). |
| 2280 // A runtime call to instantiate the type is required. | 2278 // A runtime call to instantiate the type is required. |
| 2281 __ PushObject(Object::null_object(), PP); // Make room for the result. | 2279 __ PushObject(Object::null_object()); // Make room for the result. |
| 2282 __ PushObject(type(), PP); | 2280 __ PushObject(type()); |
| 2283 __ pushq(instantiator_reg); // Push instantiator type arguments. | 2281 __ pushq(instantiator_reg); // Push instantiator type arguments. |
| 2284 compiler->GenerateRuntimeCall(token_pos(), | 2282 compiler->GenerateRuntimeCall(token_pos(), |
| 2285 deopt_id(), | 2283 deopt_id(), |
| 2286 kInstantiateTypeRuntimeEntry, | 2284 kInstantiateTypeRuntimeEntry, |
| 2287 2, | 2285 2, |
| 2288 locs()); | 2286 locs()); |
| 2289 __ Drop(2); // Drop instantiator and uninstantiated type. | 2287 __ Drop(2); // Drop instantiator and uninstantiated type. |
| 2290 __ popq(result_reg); // Pop instantiated type. | 2288 __ popq(result_reg); // Pop instantiated type. |
| 2291 ASSERT(instantiator_reg == result_reg); | 2289 ASSERT(instantiator_reg == result_reg); |
| 2292 } | 2290 } |
| (...skipping 21 matching lines...) Expand all Loading... |
| 2314 // 'instantiator_reg' is the instantiator TypeArguments object (or null). | 2312 // 'instantiator_reg' is the instantiator TypeArguments object (or null). |
| 2315 ASSERT(!type_arguments().IsUninstantiatedIdentity() && | 2313 ASSERT(!type_arguments().IsUninstantiatedIdentity() && |
| 2316 !type_arguments().CanShareInstantiatorTypeArguments( | 2314 !type_arguments().CanShareInstantiatorTypeArguments( |
| 2317 instantiator_class())); | 2315 instantiator_class())); |
| 2318 // If the instantiator is null and if the type argument vector | 2316 // If the instantiator is null and if the type argument vector |
| 2319 // instantiated from null becomes a vector of dynamic, then use null as | 2317 // instantiated from null becomes a vector of dynamic, then use null as |
| 2320 // the type arguments. | 2318 // the type arguments. |
| 2321 Label type_arguments_instantiated; | 2319 Label type_arguments_instantiated; |
| 2322 const intptr_t len = type_arguments().Length(); | 2320 const intptr_t len = type_arguments().Length(); |
| 2323 if (type_arguments().IsRawInstantiatedRaw(len)) { | 2321 if (type_arguments().IsRawInstantiatedRaw(len)) { |
| 2324 __ CompareObject(instantiator_reg, Object::null_object(), PP); | 2322 __ CompareObject(instantiator_reg, Object::null_object()); |
| 2325 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 2323 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
| 2326 } | 2324 } |
| 2327 | 2325 |
| 2328 // Lookup cache before calling runtime. | 2326 // Lookup cache before calling runtime. |
| 2329 // TODO(fschneider): Consider moving this into a shared stub to reduce | 2327 // TODO(fschneider): Consider moving this into a shared stub to reduce |
| 2330 // generated code size. | 2328 // generated code size. |
| 2331 __ LoadObject(RDI, type_arguments(), PP); | 2329 __ LoadObject(RDI, type_arguments()); |
| 2332 __ movq(RDI, FieldAddress(RDI, TypeArguments::instantiations_offset())); | 2330 __ movq(RDI, FieldAddress(RDI, TypeArguments::instantiations_offset())); |
| 2333 __ leaq(RDI, FieldAddress(RDI, Array::data_offset())); | 2331 __ leaq(RDI, FieldAddress(RDI, Array::data_offset())); |
| 2334 // The instantiations cache is initialized with Object::zero_array() and is | 2332 // The instantiations cache is initialized with Object::zero_array() and is |
| 2335 // therefore guaranteed to contain kNoInstantiator. No length check needed. | 2333 // therefore guaranteed to contain kNoInstantiator. No length check needed. |
| 2336 Label loop, found, slow_case; | 2334 Label loop, found, slow_case; |
| 2337 __ Bind(&loop); | 2335 __ Bind(&loop); |
| 2338 __ movq(RDX, Address(RDI, 0 * kWordSize)); // Cached instantiator. | 2336 __ movq(RDX, Address(RDI, 0 * kWordSize)); // Cached instantiator. |
| 2339 __ cmpq(RDX, RAX); | 2337 __ cmpq(RDX, RAX); |
| 2340 __ j(EQUAL, &found, Assembler::kNearJump); | 2338 __ j(EQUAL, &found, Assembler::kNearJump); |
| 2341 __ addq(RDI, Immediate(2 * kWordSize)); | 2339 __ addq(RDI, Immediate(2 * kWordSize)); |
| 2342 __ cmpq(RDX, Immediate(Smi::RawValue(StubCode::kNoInstantiator))); | 2340 __ cmpq(RDX, Immediate(Smi::RawValue(StubCode::kNoInstantiator))); |
| 2343 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); | 2341 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); |
| 2344 __ jmp(&slow_case, Assembler::kNearJump); | 2342 __ jmp(&slow_case, Assembler::kNearJump); |
| 2345 __ Bind(&found); | 2343 __ Bind(&found); |
| 2346 __ movq(RAX, Address(RDI, 1 * kWordSize)); // Cached instantiated args. | 2344 __ movq(RAX, Address(RDI, 1 * kWordSize)); // Cached instantiated args. |
| 2347 __ jmp(&type_arguments_instantiated, Assembler::kNearJump); | 2345 __ jmp(&type_arguments_instantiated, Assembler::kNearJump); |
| 2348 | 2346 |
| 2349 __ Bind(&slow_case); | 2347 __ Bind(&slow_case); |
| 2350 // Instantiate non-null type arguments. | 2348 // Instantiate non-null type arguments. |
| 2351 // A runtime call to instantiate the type arguments is required. | 2349 // A runtime call to instantiate the type arguments is required. |
| 2352 __ PushObject(Object::null_object(), PP); // Make room for the result. | 2350 __ PushObject(Object::null_object()); // Make room for the result. |
| 2353 __ PushObject(type_arguments(), PP); | 2351 __ PushObject(type_arguments()); |
| 2354 __ pushq(instantiator_reg); // Push instantiator type arguments. | 2352 __ pushq(instantiator_reg); // Push instantiator type arguments. |
| 2355 compiler->GenerateRuntimeCall(token_pos(), | 2353 compiler->GenerateRuntimeCall(token_pos(), |
| 2356 deopt_id(), | 2354 deopt_id(), |
| 2357 kInstantiateTypeArgumentsRuntimeEntry, | 2355 kInstantiateTypeArgumentsRuntimeEntry, |
| 2358 2, | 2356 2, |
| 2359 locs()); | 2357 locs()); |
| 2360 __ Drop(2); // Drop instantiator and uninstantiated type arguments. | 2358 __ Drop(2); // Drop instantiator and uninstantiated type arguments. |
| 2361 __ popq(result_reg); // Pop instantiated type arguments. | 2359 __ popq(result_reg); // Pop instantiated type arguments. |
| 2362 __ Bind(&type_arguments_instantiated); | 2360 __ Bind(&type_arguments_instantiated); |
| 2363 ASSERT(instantiator_reg == result_reg); | 2361 ASSERT(instantiator_reg == result_reg); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 2386 | 2384 |
| 2387 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 2385 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2388 __ Comment("AllocateContextSlowPath"); | 2386 __ Comment("AllocateContextSlowPath"); |
| 2389 __ Bind(entry_label()); | 2387 __ Bind(entry_label()); |
| 2390 | 2388 |
| 2391 LocationSummary* locs = instruction_->locs(); | 2389 LocationSummary* locs = instruction_->locs(); |
| 2392 locs->live_registers()->Remove(locs->out(0)); | 2390 locs->live_registers()->Remove(locs->out(0)); |
| 2393 | 2391 |
| 2394 compiler->SaveLiveRegisters(locs); | 2392 compiler->SaveLiveRegisters(locs); |
| 2395 | 2393 |
| 2396 __ LoadImmediate(R10, Immediate(instruction_->num_context_variables()), PP); | 2394 __ LoadImmediate(R10, Immediate(instruction_->num_context_variables())); |
| 2397 const ExternalLabel label(StubCode::AllocateContextEntryPoint()); | 2395 const ExternalLabel label(StubCode::AllocateContextEntryPoint()); |
| 2398 compiler->GenerateCall(instruction_->token_pos(), | 2396 compiler->GenerateCall(instruction_->token_pos(), |
| 2399 &label, | 2397 &label, |
| 2400 RawPcDescriptors::kOther, | 2398 RawPcDescriptors::kOther, |
| 2401 locs); | 2399 locs); |
| 2402 ASSERT(instruction_->locs()->out(0).reg() == RAX); | 2400 ASSERT(instruction_->locs()->out(0).reg() == RAX); |
| 2403 compiler->RestoreLiveRegisters(instruction_->locs()); | 2401 compiler->RestoreLiveRegisters(instruction_->locs()); |
| 2404 __ jmp(exit_label()); | 2402 __ jmp(exit_label()); |
| 2405 } | 2403 } |
| 2406 | 2404 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2441 locs->set_temp(0, Location::RegisterLocation(R10)); | 2439 locs->set_temp(0, Location::RegisterLocation(R10)); |
| 2442 locs->set_out(0, Location::RegisterLocation(RAX)); | 2440 locs->set_out(0, Location::RegisterLocation(RAX)); |
| 2443 return locs; | 2441 return locs; |
| 2444 } | 2442 } |
| 2445 | 2443 |
| 2446 | 2444 |
| 2447 void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2445 void AllocateContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2448 ASSERT(locs()->temp(0).reg() == R10); | 2446 ASSERT(locs()->temp(0).reg() == R10); |
| 2449 ASSERT(locs()->out(0).reg() == RAX); | 2447 ASSERT(locs()->out(0).reg() == RAX); |
| 2450 | 2448 |
| 2451 __ LoadImmediate(R10, Immediate(num_context_variables()), PP); | 2449 __ LoadImmediate(R10, Immediate(num_context_variables())); |
| 2452 const ExternalLabel label(StubCode::AllocateContextEntryPoint()); | 2450 const ExternalLabel label(StubCode::AllocateContextEntryPoint()); |
| 2453 compiler->GenerateCall(token_pos(), | 2451 compiler->GenerateCall(token_pos(), |
| 2454 &label, | 2452 &label, |
| 2455 RawPcDescriptors::kOther, | 2453 RawPcDescriptors::kOther, |
| 2456 locs()); | 2454 locs()); |
| 2457 } | 2455 } |
| 2458 | 2456 |
| 2459 | 2457 |
| 2460 LocationSummary* InitStaticFieldInstr::MakeLocationSummary(Zone* zone, | 2458 LocationSummary* InitStaticFieldInstr::MakeLocationSummary(Zone* zone, |
| 2461 bool opt) const { | 2459 bool opt) const { |
| 2462 const intptr_t kNumInputs = 1; | 2460 const intptr_t kNumInputs = 1; |
| 2463 const intptr_t kNumTemps = 1; | 2461 const intptr_t kNumTemps = 1; |
| 2464 LocationSummary* locs = new(zone) LocationSummary( | 2462 LocationSummary* locs = new(zone) LocationSummary( |
| 2465 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2463 zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2466 locs->set_in(0, Location::RegisterLocation(RAX)); | 2464 locs->set_in(0, Location::RegisterLocation(RAX)); |
| 2467 locs->set_temp(0, Location::RegisterLocation(RCX)); | 2465 locs->set_temp(0, Location::RegisterLocation(RCX)); |
| 2468 return locs; | 2466 return locs; |
| 2469 } | 2467 } |
| 2470 | 2468 |
| 2471 | 2469 |
| 2472 void InitStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2470 void InitStaticFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2473 Register field = locs()->in(0).reg(); | 2471 Register field = locs()->in(0).reg(); |
| 2474 Register temp = locs()->temp(0).reg(); | 2472 Register temp = locs()->temp(0).reg(); |
| 2475 | 2473 |
| 2476 Label call_runtime, no_call; | 2474 Label call_runtime, no_call; |
| 2477 | 2475 |
| 2478 __ movq(temp, FieldAddress(field, Field::value_offset())); | 2476 __ movq(temp, FieldAddress(field, Field::value_offset())); |
| 2479 __ CompareObject(temp, Object::sentinel(), PP); | 2477 __ CompareObject(temp, Object::sentinel()); |
| 2480 __ j(EQUAL, &call_runtime); | 2478 __ j(EQUAL, &call_runtime); |
| 2481 | 2479 |
| 2482 __ CompareObject(temp, Object::transition_sentinel(), PP); | 2480 __ CompareObject(temp, Object::transition_sentinel()); |
| 2483 __ j(NOT_EQUAL, &no_call); | 2481 __ j(NOT_EQUAL, &no_call); |
| 2484 | 2482 |
| 2485 __ Bind(&call_runtime); | 2483 __ Bind(&call_runtime); |
| 2486 __ PushObject(Object::null_object(), PP); // Make room for (unused) result. | 2484 __ PushObject(Object::null_object()); // Make room for (unused) result. |
| 2487 __ pushq(field); | 2485 __ pushq(field); |
| 2488 compiler->GenerateRuntimeCall(token_pos(), | 2486 compiler->GenerateRuntimeCall(token_pos(), |
| 2489 deopt_id(), | 2487 deopt_id(), |
| 2490 kInitStaticFieldRuntimeEntry, | 2488 kInitStaticFieldRuntimeEntry, |
| 2491 1, | 2489 1, |
| 2492 locs()); | 2490 locs()); |
| 2493 __ Drop(2); // Remove argument and unused result. | 2491 __ Drop(2); // Remove argument and unused result. |
| 2494 __ Bind(&no_call); | 2492 __ Bind(&no_call); |
| 2495 } | 2493 } |
| 2496 | 2494 |
| 2497 | 2495 |
| 2498 LocationSummary* CloneContextInstr::MakeLocationSummary(Zone* zone, | 2496 LocationSummary* CloneContextInstr::MakeLocationSummary(Zone* zone, |
| 2499 bool opt) const { | 2497 bool opt) const { |
| 2500 const intptr_t kNumInputs = 1; | 2498 const intptr_t kNumInputs = 1; |
| 2501 const intptr_t kNumTemps = 0; | 2499 const intptr_t kNumTemps = 0; |
| 2502 LocationSummary* locs = new(zone) LocationSummary( | 2500 LocationSummary* locs = new(zone) LocationSummary( |
| 2503 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 2501 zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 2504 locs->set_in(0, Location::RegisterLocation(RAX)); | 2502 locs->set_in(0, Location::RegisterLocation(RAX)); |
| 2505 locs->set_out(0, Location::RegisterLocation(RAX)); | 2503 locs->set_out(0, Location::RegisterLocation(RAX)); |
| 2506 return locs; | 2504 return locs; |
| 2507 } | 2505 } |
| 2508 | 2506 |
| 2509 | 2507 |
| 2510 void CloneContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2508 void CloneContextInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2511 Register context_value = locs()->in(0).reg(); | 2509 Register context_value = locs()->in(0).reg(); |
| 2512 Register result = locs()->out(0).reg(); | 2510 Register result = locs()->out(0).reg(); |
| 2513 | 2511 |
| 2514 __ PushObject(Object::null_object(), PP); // Make room for the result. | 2512 __ PushObject(Object::null_object()); // Make room for the result. |
| 2515 __ pushq(context_value); | 2513 __ pushq(context_value); |
| 2516 compiler->GenerateRuntimeCall(token_pos(), | 2514 compiler->GenerateRuntimeCall(token_pos(), |
| 2517 deopt_id(), | 2515 deopt_id(), |
| 2518 kCloneContextRuntimeEntry, | 2516 kCloneContextRuntimeEntry, |
| 2519 1, | 2517 1, |
| 2520 locs()); | 2518 locs()); |
| 2521 __ popq(result); // Remove argument. | 2519 __ popq(result); // Remove argument. |
| 2522 __ popq(result); // Get result (cloned context). | 2520 __ popq(result); // Get result (cloned context). |
| 2523 } | 2521 } |
| 2524 | 2522 |
| 2525 | 2523 |
| 2526 LocationSummary* CatchBlockEntryInstr::MakeLocationSummary(Zone* zone, | 2524 LocationSummary* CatchBlockEntryInstr::MakeLocationSummary(Zone* zone, |
| 2527 bool opt) const { | 2525 bool opt) const { |
| 2528 UNREACHABLE(); | 2526 UNREACHABLE(); |
| 2529 return NULL; | 2527 return NULL; |
| 2530 } | 2528 } |
| 2531 | 2529 |
| 2532 | 2530 |
| 2533 void CatchBlockEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2531 void CatchBlockEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2534 __ Bind(compiler->GetJumpLabel(this)); | 2532 __ Bind(compiler->GetJumpLabel(this)); |
| 2535 compiler->AddExceptionHandler(catch_try_index(), | 2533 compiler->AddExceptionHandler(catch_try_index(), |
| 2536 try_index(), | 2534 try_index(), |
| 2537 compiler->assembler()->CodeSize(), | 2535 compiler->assembler()->CodeSize(), |
| 2538 catch_handler_types_, | 2536 catch_handler_types_, |
| 2539 needs_stacktrace()); | 2537 needs_stacktrace()); |
| 2540 | 2538 |
| 2541 // Restore the pool pointer. | 2539 // Restore the pool pointer. |
| 2542 __ LoadPoolPointer(PP); | 2540 __ LoadPoolPointer(); |
| 2543 | 2541 |
| 2544 if (HasParallelMove()) { | 2542 if (HasParallelMove()) { |
| 2545 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); | 2543 compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); |
| 2546 } | 2544 } |
| 2547 | 2545 |
| 2548 // Restore RSP from RBP as we are coming from a throw and the code for | 2546 // Restore RSP from RBP as we are coming from a throw and the code for |
| 2549 // popping arguments has not been run. | 2547 // popping arguments has not been run. |
| 2550 const intptr_t fp_sp_dist = | 2548 const intptr_t fp_sp_dist = |
| 2551 (kFirstLocalSlotFromFp + 1 - compiler->StackSize()) * kWordSize; | 2549 (kFirstLocalSlotFromFp + 1 - compiler->StackSize()) * kWordSize; |
| 2552 ASSERT(fp_sp_dist <= 0); | 2550 ASSERT(fp_sp_dist <= 0); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 2578 public: | 2576 public: |
| 2579 explicit CheckStackOverflowSlowPath(CheckStackOverflowInstr* instruction) | 2577 explicit CheckStackOverflowSlowPath(CheckStackOverflowInstr* instruction) |
| 2580 : instruction_(instruction) { } | 2578 : instruction_(instruction) { } |
| 2581 | 2579 |
| 2582 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 2580 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2583 if (FLAG_use_osr && osr_entry_label()->IsLinked()) { | 2581 if (FLAG_use_osr && osr_entry_label()->IsLinked()) { |
| 2584 uword flags_address = Isolate::Current()->stack_overflow_flags_address(); | 2582 uword flags_address = Isolate::Current()->stack_overflow_flags_address(); |
| 2585 Register temp = instruction_->locs()->temp(0).reg(); | 2583 Register temp = instruction_->locs()->temp(0).reg(); |
| 2586 __ Comment("CheckStackOverflowSlowPathOsr"); | 2584 __ Comment("CheckStackOverflowSlowPathOsr"); |
| 2587 __ Bind(osr_entry_label()); | 2585 __ Bind(osr_entry_label()); |
| 2588 __ LoadImmediate(temp, Immediate(flags_address), PP); | 2586 __ LoadImmediate(temp, Immediate(flags_address)); |
| 2589 __ movq(Address(temp, 0), Immediate(Isolate::kOsrRequest)); | 2587 __ movq(Address(temp, 0), Immediate(Isolate::kOsrRequest)); |
| 2590 } | 2588 } |
| 2591 __ Comment("CheckStackOverflowSlowPath"); | 2589 __ Comment("CheckStackOverflowSlowPath"); |
| 2592 __ Bind(entry_label()); | 2590 __ Bind(entry_label()); |
| 2593 compiler->SaveLiveRegisters(instruction_->locs()); | 2591 compiler->SaveLiveRegisters(instruction_->locs()); |
| 2594 // pending_deoptimization_env_ is needed to generate a runtime call that | 2592 // pending_deoptimization_env_ is needed to generate a runtime call that |
| 2595 // may throw an exception. | 2593 // may throw an exception. |
| 2596 ASSERT(compiler->pending_deoptimization_env_ == NULL); | 2594 ASSERT(compiler->pending_deoptimization_env_ == NULL); |
| 2597 Environment* env = compiler->SlowPathEnvironmentFor(instruction_); | 2595 Environment* env = compiler->SlowPathEnvironmentFor(instruction_); |
| 2598 compiler->pending_deoptimization_env_ = env; | 2596 compiler->pending_deoptimization_env_ = env; |
| (...skipping 27 matching lines...) Expand all Loading... |
| 2626 | 2624 |
| 2627 | 2625 |
| 2628 void CheckStackOverflowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2626 void CheckStackOverflowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2629 CheckStackOverflowSlowPath* slow_path = new CheckStackOverflowSlowPath(this); | 2627 CheckStackOverflowSlowPath* slow_path = new CheckStackOverflowSlowPath(this); |
| 2630 compiler->AddSlowPathCode(slow_path); | 2628 compiler->AddSlowPathCode(slow_path); |
| 2631 | 2629 |
| 2632 Register temp = locs()->temp(0).reg(); | 2630 Register temp = locs()->temp(0).reg(); |
| 2633 // Generate stack overflow check. | 2631 // Generate stack overflow check. |
| 2634 if (compiler->is_optimizing()) { | 2632 if (compiler->is_optimizing()) { |
| 2635 __ LoadImmediate( | 2633 __ LoadImmediate( |
| 2636 temp, Immediate(Isolate::Current()->stack_limit_address()), PP); | 2634 temp, Immediate(Isolate::Current()->stack_limit_address())); |
| 2637 __ cmpq(RSP, Address(temp, 0)); | 2635 __ cmpq(RSP, Address(temp, 0)); |
| 2638 } else { | 2636 } else { |
| 2639 __ LoadIsolate(temp); | 2637 __ LoadIsolate(temp); |
| 2640 __ cmpq(RSP, Address(temp, Isolate::stack_limit_offset())); | 2638 __ cmpq(RSP, Address(temp, Isolate::stack_limit_offset())); |
| 2641 } | 2639 } |
| 2642 __ j(BELOW_EQUAL, slow_path->entry_label()); | 2640 __ j(BELOW_EQUAL, slow_path->entry_label()); |
| 2643 if (compiler->CanOSRFunction() && in_loop()) { | 2641 if (compiler->CanOSRFunction() && in_loop()) { |
| 2644 // In unoptimized code check the usage counter to trigger OSR at loop | 2642 // In unoptimized code check the usage counter to trigger OSR at loop |
| 2645 // stack checks. Use progressively higher thresholds for more deeply | 2643 // stack checks. Use progressively higher thresholds for more deeply |
| 2646 // nested loops to attempt to hit outer loops with OSR when possible. | 2644 // nested loops to attempt to hit outer loops with OSR when possible. |
| 2647 __ LoadObject(temp, compiler->parsed_function().function(), PP); | 2645 __ LoadObject(temp, compiler->parsed_function().function()); |
| 2648 int32_t threshold = | 2646 int32_t threshold = |
| 2649 FLAG_optimization_counter_threshold * (loop_depth() + 1); | 2647 FLAG_optimization_counter_threshold * (loop_depth() + 1); |
| 2650 __ cmpl(FieldAddress(temp, Function::usage_counter_offset()), | 2648 __ cmpl(FieldAddress(temp, Function::usage_counter_offset()), |
| 2651 Immediate(threshold)); | 2649 Immediate(threshold)); |
| 2652 __ j(GREATER_EQUAL, slow_path->osr_entry_label()); | 2650 __ j(GREATER_EQUAL, slow_path->osr_entry_label()); |
| 2653 } | 2651 } |
| 2654 if (compiler->ForceSlowPathForStackOverflow()) { | 2652 if (compiler->ForceSlowPathForStackOverflow()) { |
| 2655 __ jmp(slow_path->entry_label()); | 2653 __ jmp(slow_path->entry_label()); |
| 2656 } | 2654 } |
| 2657 __ Bind(slow_path->exit_label()); | 2655 __ Bind(slow_path->exit_label()); |
| 2658 } | 2656 } |
| 2659 | 2657 |
| 2660 | 2658 |
| 2661 static void EmitJavascriptOverflowCheck(FlowGraphCompiler* compiler, | 2659 static void EmitJavascriptOverflowCheck(FlowGraphCompiler* compiler, |
| 2662 Range* range, | 2660 Range* range, |
| 2663 Label* overflow, | 2661 Label* overflow, |
| 2664 Register result) { | 2662 Register result) { |
| 2665 if (!RangeUtils::IsWithin(range, -0x20000000000000LL, 0x20000000000000LL)) { | 2663 if (!RangeUtils::IsWithin(range, -0x20000000000000LL, 0x20000000000000LL)) { |
| 2666 ASSERT(overflow != NULL); | 2664 ASSERT(overflow != NULL); |
| 2667 // TODO(zra): This can be tightened to one compare/branch using: | 2665 // TODO(zra): This can be tightened to one compare/branch using: |
| 2668 // overflow = (result + 2^52) > 2^53 with an unsigned comparison. | 2666 // overflow = (result + 2^52) > 2^53 with an unsigned comparison. |
| 2669 __ CompareImmediate(result, Immediate(-0x20000000000000LL), PP); | 2667 __ CompareImmediate(result, Immediate(-0x20000000000000LL)); |
| 2670 __ j(LESS, overflow); | 2668 __ j(LESS, overflow); |
| 2671 __ CompareImmediate(result, Immediate(0x20000000000000LL), PP); | 2669 __ CompareImmediate(result, Immediate(0x20000000000000LL)); |
| 2672 __ j(GREATER, overflow); | 2670 __ j(GREATER, overflow); |
| 2673 } | 2671 } |
| 2674 } | 2672 } |
| 2675 | 2673 |
| 2676 | 2674 |
| 2677 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler, | 2675 static void EmitSmiShiftLeft(FlowGraphCompiler* compiler, |
| 2678 BinarySmiOpInstr* shift_left) { | 2676 BinarySmiOpInstr* shift_left) { |
| 2679 const LocationSummary& locs = *shift_left->locs(); | 2677 const LocationSummary& locs = *shift_left->locs(); |
| 2680 Register left = locs.in(0).reg(); | 2678 Register left = locs.in(0).reg(); |
| 2681 Register result = locs.out(0).reg(); | 2679 Register result = locs.out(0).reg(); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 2710 // Right (locs.in(1)) is not constant. | 2708 // Right (locs.in(1)) is not constant. |
| 2711 Register right = locs.in(1).reg(); | 2709 Register right = locs.in(1).reg(); |
| 2712 Range* right_range = shift_left->right()->definition()->range(); | 2710 Range* right_range = shift_left->right()->definition()->range(); |
| 2713 if (shift_left->left()->BindsToConstant() && shift_left->can_overflow()) { | 2711 if (shift_left->left()->BindsToConstant() && shift_left->can_overflow()) { |
| 2714 // TODO(srdjan): Implement code below for is_truncating(). | 2712 // TODO(srdjan): Implement code below for is_truncating(). |
| 2715 // If left is constant, we know the maximal allowed size for right. | 2713 // If left is constant, we know the maximal allowed size for right. |
| 2716 const Object& obj = shift_left->left()->BoundConstant(); | 2714 const Object& obj = shift_left->left()->BoundConstant(); |
| 2717 if (obj.IsSmi()) { | 2715 if (obj.IsSmi()) { |
| 2718 const intptr_t left_int = Smi::Cast(obj).Value(); | 2716 const intptr_t left_int = Smi::Cast(obj).Value(); |
| 2719 if (left_int == 0) { | 2717 if (left_int == 0) { |
| 2720 __ CompareImmediate(right, Immediate(0), PP); | 2718 __ CompareImmediate(right, Immediate(0)); |
| 2721 __ j(NEGATIVE, deopt); | 2719 __ j(NEGATIVE, deopt); |
| 2722 return; | 2720 return; |
| 2723 } | 2721 } |
| 2724 const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int); | 2722 const intptr_t max_right = kSmiBits - Utils::HighestBit(left_int); |
| 2725 const bool right_needs_check = | 2723 const bool right_needs_check = |
| 2726 !RangeUtils::IsWithin(right_range, 0, max_right - 1); | 2724 !RangeUtils::IsWithin(right_range, 0, max_right - 1); |
| 2727 if (right_needs_check) { | 2725 if (right_needs_check) { |
| 2728 __ CompareImmediate(right, | 2726 __ CompareImmediate(right, |
| 2729 Immediate(reinterpret_cast<int64_t>(Smi::New(max_right))), PP); | 2727 Immediate(reinterpret_cast<int64_t>(Smi::New(max_right)))); |
| 2730 __ j(ABOVE_EQUAL, deopt); | 2728 __ j(ABOVE_EQUAL, deopt); |
| 2731 } | 2729 } |
| 2732 __ SmiUntag(right); | 2730 __ SmiUntag(right); |
| 2733 __ shlq(left, right); | 2731 __ shlq(left, right); |
| 2734 } | 2732 } |
| 2735 if (FLAG_throw_on_javascript_int_overflow) { | 2733 if (FLAG_throw_on_javascript_int_overflow) { |
| 2736 EmitJavascriptOverflowCheck(compiler, shift_left->range(), deopt, result); | 2734 EmitJavascriptOverflowCheck(compiler, shift_left->range(), deopt, result); |
| 2737 } | 2735 } |
| 2738 return; | 2736 return; |
| 2739 } | 2737 } |
| 2740 | 2738 |
| 2741 const bool right_needs_check = | 2739 const bool right_needs_check = |
| 2742 !RangeUtils::IsWithin(right_range, 0, (Smi::kBits - 1)); | 2740 !RangeUtils::IsWithin(right_range, 0, (Smi::kBits - 1)); |
| 2743 ASSERT(right == RCX); // Count must be in RCX | 2741 ASSERT(right == RCX); // Count must be in RCX |
| 2744 if (!shift_left->can_overflow()) { | 2742 if (!shift_left->can_overflow()) { |
| 2745 if (right_needs_check) { | 2743 if (right_needs_check) { |
| 2746 const bool right_may_be_negative = | 2744 const bool right_may_be_negative = |
| 2747 (right_range == NULL) || !right_range->IsPositive(); | 2745 (right_range == NULL) || !right_range->IsPositive(); |
| 2748 if (right_may_be_negative) { | 2746 if (right_may_be_negative) { |
| 2749 ASSERT(shift_left->CanDeoptimize()); | 2747 ASSERT(shift_left->CanDeoptimize()); |
| 2750 __ CompareImmediate(right, Immediate(0), PP); | 2748 __ CompareImmediate(right, Immediate(0)); |
| 2751 __ j(NEGATIVE, deopt); | 2749 __ j(NEGATIVE, deopt); |
| 2752 } | 2750 } |
| 2753 Label done, is_not_zero; | 2751 Label done, is_not_zero; |
| 2754 __ CompareImmediate(right, | 2752 __ CompareImmediate(right, |
| 2755 Immediate(reinterpret_cast<int64_t>(Smi::New(Smi::kBits))), PP); | 2753 Immediate(reinterpret_cast<int64_t>(Smi::New(Smi::kBits)))); |
| 2756 __ j(BELOW, &is_not_zero, Assembler::kNearJump); | 2754 __ j(BELOW, &is_not_zero, Assembler::kNearJump); |
| 2757 __ xorq(left, left); | 2755 __ xorq(left, left); |
| 2758 __ jmp(&done, Assembler::kNearJump); | 2756 __ jmp(&done, Assembler::kNearJump); |
| 2759 __ Bind(&is_not_zero); | 2757 __ Bind(&is_not_zero); |
| 2760 __ SmiUntag(right); | 2758 __ SmiUntag(right); |
| 2761 __ shlq(left, right); | 2759 __ shlq(left, right); |
| 2762 __ Bind(&done); | 2760 __ Bind(&done); |
| 2763 } else { | 2761 } else { |
| 2764 __ SmiUntag(right); | 2762 __ SmiUntag(right); |
| 2765 __ shlq(left, right); | 2763 __ shlq(left, right); |
| 2766 } | 2764 } |
| 2767 } else { | 2765 } else { |
| 2768 if (right_needs_check) { | 2766 if (right_needs_check) { |
| 2769 ASSERT(shift_left->CanDeoptimize()); | 2767 ASSERT(shift_left->CanDeoptimize()); |
| 2770 __ CompareImmediate(right, | 2768 __ CompareImmediate(right, |
| 2771 Immediate(reinterpret_cast<int64_t>(Smi::New(Smi::kBits))), PP); | 2769 Immediate(reinterpret_cast<int64_t>(Smi::New(Smi::kBits)))); |
| 2772 __ j(ABOVE_EQUAL, deopt); | 2770 __ j(ABOVE_EQUAL, deopt); |
| 2773 } | 2771 } |
| 2774 // Left is not a constant. | 2772 // Left is not a constant. |
| 2775 Register temp = locs.temp(0).reg(); | 2773 Register temp = locs.temp(0).reg(); |
| 2776 // Check if count too large for handling it inlined. | 2774 // Check if count too large for handling it inlined. |
| 2777 __ movq(temp, left); | 2775 __ movq(temp, left); |
| 2778 __ SmiUntag(right); | 2776 __ SmiUntag(right); |
| 2779 // Overflow test (preserve temp and right); | 2777 // Overflow test (preserve temp and right); |
| 2780 __ shlq(left, right); | 2778 __ shlq(left, right); |
| 2781 __ sarq(left, right); | 2779 __ sarq(left, right); |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2894 if (CanDeoptimize()) { | 2892 if (CanDeoptimize()) { |
| 2895 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp); | 2893 deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinarySmiOp); |
| 2896 } | 2894 } |
| 2897 | 2895 |
| 2898 if (locs()->in(1).IsConstant()) { | 2896 if (locs()->in(1).IsConstant()) { |
| 2899 const Object& constant = locs()->in(1).constant(); | 2897 const Object& constant = locs()->in(1).constant(); |
| 2900 ASSERT(constant.IsSmi()); | 2898 ASSERT(constant.IsSmi()); |
| 2901 const int64_t imm = reinterpret_cast<int64_t>(constant.raw()); | 2899 const int64_t imm = reinterpret_cast<int64_t>(constant.raw()); |
| 2902 switch (op_kind()) { | 2900 switch (op_kind()) { |
| 2903 case Token::kADD: { | 2901 case Token::kADD: { |
| 2904 __ AddImmediate(left, Immediate(imm), PP); | 2902 __ AddImmediate(left, Immediate(imm)); |
| 2905 if (deopt != NULL) __ j(OVERFLOW, deopt); | 2903 if (deopt != NULL) __ j(OVERFLOW, deopt); |
| 2906 break; | 2904 break; |
| 2907 } | 2905 } |
| 2908 case Token::kSUB: { | 2906 case Token::kSUB: { |
| 2909 __ SubImmediate(left, Immediate(imm), PP); | 2907 __ SubImmediate(left, Immediate(imm)); |
| 2910 if (deopt != NULL) __ j(OVERFLOW, deopt); | 2908 if (deopt != NULL) __ j(OVERFLOW, deopt); |
| 2911 break; | 2909 break; |
| 2912 } | 2910 } |
| 2913 case Token::kMUL: { | 2911 case Token::kMUL: { |
| 2914 // Keep left value tagged and untag right value. | 2912 // Keep left value tagged and untag right value. |
| 2915 const intptr_t value = Smi::Cast(constant).Value(); | 2913 const intptr_t value = Smi::Cast(constant).Value(); |
| 2916 __ MulImmediate(left, Immediate(value), PP); | 2914 __ MulImmediate(left, Immediate(value)); |
| 2917 if (deopt != NULL) __ j(OVERFLOW, deopt); | 2915 if (deopt != NULL) __ j(OVERFLOW, deopt); |
| 2918 break; | 2916 break; |
| 2919 } | 2917 } |
| 2920 case Token::kTRUNCDIV: { | 2918 case Token::kTRUNCDIV: { |
| 2921 const intptr_t value = Smi::Cast(constant).Value(); | 2919 const intptr_t value = Smi::Cast(constant).Value(); |
| 2922 ASSERT(Utils::IsPowerOfTwo(Utils::Abs(value))); | 2920 ASSERT(Utils::IsPowerOfTwo(Utils::Abs(value))); |
| 2923 const intptr_t shift_count = | 2921 const intptr_t shift_count = |
| 2924 Utils::ShiftForPowerOfTwo(Utils::Abs(value)) + kSmiTagSize; | 2922 Utils::ShiftForPowerOfTwo(Utils::Abs(value)) + kSmiTagSize; |
| 2925 ASSERT(kSmiTagSize == 1); | 2923 ASSERT(kSmiTagSize == 1); |
| 2926 Register temp = locs()->temp(0).reg(); | 2924 Register temp = locs()->temp(0).reg(); |
| 2927 __ movq(temp, left); | 2925 __ movq(temp, left); |
| 2928 __ sarq(temp, Immediate(63)); | 2926 __ sarq(temp, Immediate(63)); |
| 2929 ASSERT(shift_count > 1); // 1, -1 case handled above. | 2927 ASSERT(shift_count > 1); // 1, -1 case handled above. |
| 2930 __ shrq(temp, Immediate(64 - shift_count)); | 2928 __ shrq(temp, Immediate(64 - shift_count)); |
| 2931 __ addq(left, temp); | 2929 __ addq(left, temp); |
| 2932 ASSERT(shift_count > 0); | 2930 ASSERT(shift_count > 0); |
| 2933 __ sarq(left, Immediate(shift_count)); | 2931 __ sarq(left, Immediate(shift_count)); |
| 2934 if (value < 0) { | 2932 if (value < 0) { |
| 2935 __ negq(left); | 2933 __ negq(left); |
| 2936 } | 2934 } |
| 2937 __ SmiTag(left); | 2935 __ SmiTag(left); |
| 2938 break; | 2936 break; |
| 2939 } | 2937 } |
| 2940 case Token::kBIT_AND: { | 2938 case Token::kBIT_AND: { |
| 2941 // No overflow check. | 2939 // No overflow check. |
| 2942 __ AndImmediate(left, Immediate(imm), PP); | 2940 __ AndImmediate(left, Immediate(imm)); |
| 2943 break; | 2941 break; |
| 2944 } | 2942 } |
| 2945 case Token::kBIT_OR: { | 2943 case Token::kBIT_OR: { |
| 2946 // No overflow check. | 2944 // No overflow check. |
| 2947 __ OrImmediate(left, Immediate(imm), PP); | 2945 __ OrImmediate(left, Immediate(imm)); |
| 2948 break; | 2946 break; |
| 2949 } | 2947 } |
| 2950 case Token::kBIT_XOR: { | 2948 case Token::kBIT_XOR: { |
| 2951 // No overflow check. | 2949 // No overflow check. |
| 2952 __ XorImmediate(left, Immediate(imm), PP); | 2950 __ XorImmediate(left, Immediate(imm)); |
| 2953 break; | 2951 break; |
| 2954 } | 2952 } |
| 2955 | 2953 |
| 2956 case Token::kSHR: { | 2954 case Token::kSHR: { |
| 2957 // sarq operation masks the count to 6 bits. | 2955 // sarq operation masks the count to 6 bits. |
| 2958 const intptr_t kCountLimit = 0x3F; | 2956 const intptr_t kCountLimit = 0x3F; |
| 2959 const intptr_t value = Smi::Cast(constant).Value(); | 2957 const intptr_t value = Smi::Cast(constant).Value(); |
| 2960 __ sarq(left, Immediate( | 2958 __ sarq(left, Immediate( |
| 2961 Utils::Minimum(value + kSmiTagSize, kCountLimit))); | 2959 Utils::Minimum(value + kSmiTagSize, kCountLimit))); |
| 2962 __ SmiTag(left); | 2960 __ SmiTag(left); |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3087 __ jmp(&done); | 3085 __ jmp(&done); |
| 3088 | 3086 |
| 3089 // Divide using 64bit idiv. | 3087 // Divide using 64bit idiv. |
| 3090 __ Bind(¬_32bit); | 3088 __ Bind(¬_32bit); |
| 3091 __ SmiUntag(left); | 3089 __ SmiUntag(left); |
| 3092 __ SmiUntag(right); | 3090 __ SmiUntag(right); |
| 3093 __ cqo(); // Sign extend RAX -> RDX:RAX. | 3091 __ cqo(); // Sign extend RAX -> RDX:RAX. |
| 3094 __ idivq(right); // RAX: quotient, RDX: remainder. | 3092 __ idivq(right); // RAX: quotient, RDX: remainder. |
| 3095 // Check the corner case of dividing the 'MIN_SMI' with -1, in which | 3093 // Check the corner case of dividing the 'MIN_SMI' with -1, in which |
| 3096 // case we cannot tag the result. | 3094 // case we cannot tag the result. |
| 3097 __ CompareImmediate(result, Immediate(0x4000000000000000), PP); | 3095 __ CompareImmediate(result, Immediate(0x4000000000000000)); |
| 3098 __ j(EQUAL, deopt); | 3096 __ j(EQUAL, deopt); |
| 3099 __ Bind(&done); | 3097 __ Bind(&done); |
| 3100 __ SmiTag(result); | 3098 __ SmiTag(result); |
| 3101 break; | 3099 break; |
| 3102 } | 3100 } |
| 3103 case Token::kMOD: { | 3101 case Token::kMOD: { |
| 3104 Label not_32bit, div_done; | 3102 Label not_32bit, div_done; |
| 3105 | 3103 |
| 3106 Register temp = locs()->temp(0).reg(); | 3104 Register temp = locs()->temp(0).reg(); |
| 3107 ASSERT(left == RDX); | 3105 ASSERT(left == RDX); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3167 } else { | 3165 } else { |
| 3168 // Right is negative. | 3166 // Right is negative. |
| 3169 __ subq(result, right); | 3167 __ subq(result, right); |
| 3170 } | 3168 } |
| 3171 __ Bind(&all_done); | 3169 __ Bind(&all_done); |
| 3172 __ SmiTag(result); | 3170 __ SmiTag(result); |
| 3173 break; | 3171 break; |
| 3174 } | 3172 } |
| 3175 case Token::kSHR: { | 3173 case Token::kSHR: { |
| 3176 if (CanDeoptimize()) { | 3174 if (CanDeoptimize()) { |
| 3177 __ CompareImmediate(right, Immediate(0), PP); | 3175 __ CompareImmediate(right, Immediate(0)); |
| 3178 __ j(LESS, deopt); | 3176 __ j(LESS, deopt); |
| 3179 } | 3177 } |
| 3180 __ SmiUntag(right); | 3178 __ SmiUntag(right); |
| 3181 // sarq operation masks the count to 6 bits. | 3179 // sarq operation masks the count to 6 bits. |
| 3182 const intptr_t kCountLimit = 0x3F; | 3180 const intptr_t kCountLimit = 0x3F; |
| 3183 if ((right_range == NULL) || | 3181 if ((right_range == NULL) || |
| 3184 !right_range->OnlyLessThanOrEqualTo(kCountLimit)) { | 3182 !right_range->OnlyLessThanOrEqualTo(kCountLimit)) { |
| 3185 __ CompareImmediate(right, Immediate(kCountLimit), PP); | 3183 __ CompareImmediate(right, Immediate(kCountLimit)); |
| 3186 Label count_ok; | 3184 Label count_ok; |
| 3187 __ j(LESS, &count_ok, Assembler::kNearJump); | 3185 __ j(LESS, &count_ok, Assembler::kNearJump); |
| 3188 __ LoadImmediate(right, Immediate(kCountLimit), PP); | 3186 __ LoadImmediate(right, Immediate(kCountLimit)); |
| 3189 __ Bind(&count_ok); | 3187 __ Bind(&count_ok); |
| 3190 } | 3188 } |
| 3191 ASSERT(right == RCX); // Count must be in RCX | 3189 ASSERT(right == RCX); // Count must be in RCX |
| 3192 __ SmiUntag(left); | 3190 __ SmiUntag(left); |
| 3193 __ sarq(left, right); | 3191 __ sarq(left, right); |
| 3194 __ SmiTag(left); | 3192 __ SmiTag(left); |
| 3195 break; | 3193 break; |
| 3196 } | 3194 } |
| 3197 case Token::kDIV: { | 3195 case Token::kDIV: { |
| 3198 // Dispatches to 'Double./'. | 3196 // Dispatches to 'Double./'. |
| (...skipping 529 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3728 return summary; | 3726 return summary; |
| 3729 } | 3727 } |
| 3730 | 3728 |
| 3731 | 3729 |
| 3732 void Float32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3730 void Float32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3733 XmmRegister v0 = locs()->in(0).fpu_reg(); | 3731 XmmRegister v0 = locs()->in(0).fpu_reg(); |
| 3734 XmmRegister v1 = locs()->in(1).fpu_reg(); | 3732 XmmRegister v1 = locs()->in(1).fpu_reg(); |
| 3735 XmmRegister v2 = locs()->in(2).fpu_reg(); | 3733 XmmRegister v2 = locs()->in(2).fpu_reg(); |
| 3736 XmmRegister v3 = locs()->in(3).fpu_reg(); | 3734 XmmRegister v3 = locs()->in(3).fpu_reg(); |
| 3737 ASSERT(v0 == locs()->out(0).fpu_reg()); | 3735 ASSERT(v0 == locs()->out(0).fpu_reg()); |
| 3738 __ AddImmediate(RSP, Immediate(-16), PP); | 3736 __ AddImmediate(RSP, Immediate(-16)); |
| 3739 __ cvtsd2ss(v0, v0); | 3737 __ cvtsd2ss(v0, v0); |
| 3740 __ movss(Address(RSP, 0), v0); | 3738 __ movss(Address(RSP, 0), v0); |
| 3741 __ movsd(v0, v1); | 3739 __ movsd(v0, v1); |
| 3742 __ cvtsd2ss(v0, v0); | 3740 __ cvtsd2ss(v0, v0); |
| 3743 __ movss(Address(RSP, 4), v0); | 3741 __ movss(Address(RSP, 4), v0); |
| 3744 __ movsd(v0, v2); | 3742 __ movsd(v0, v2); |
| 3745 __ cvtsd2ss(v0, v0); | 3743 __ cvtsd2ss(v0, v0); |
| 3746 __ movss(Address(RSP, 8), v0); | 3744 __ movss(Address(RSP, 8), v0); |
| 3747 __ movsd(v0, v3); | 3745 __ movsd(v0, v3); |
| 3748 __ cvtsd2ss(v0, v0); | 3746 __ cvtsd2ss(v0, v0); |
| 3749 __ movss(Address(RSP, 12), v0); | 3747 __ movss(Address(RSP, 12), v0); |
| 3750 __ movups(v0, Address(RSP, 0)); | 3748 __ movups(v0, Address(RSP, 0)); |
| 3751 __ AddImmediate(RSP, Immediate(16), PP); | 3749 __ AddImmediate(RSP, Immediate(16)); |
| 3752 } | 3750 } |
| 3753 | 3751 |
| 3754 | 3752 |
| 3755 LocationSummary* Float32x4ZeroInstr::MakeLocationSummary(Zone* zone, | 3753 LocationSummary* Float32x4ZeroInstr::MakeLocationSummary(Zone* zone, |
| 3756 bool opt) const { | 3754 bool opt) const { |
| 3757 const intptr_t kNumInputs = 0; | 3755 const intptr_t kNumInputs = 0; |
| 3758 const intptr_t kNumTemps = 0; | 3756 const intptr_t kNumTemps = 0; |
| 3759 LocationSummary* summary = new(zone) LocationSummary( | 3757 LocationSummary* summary = new(zone) LocationSummary( |
| 3760 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 3758 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 3761 summary->set_out(0, Location::RequiresFpuRegister()); | 3759 summary->set_out(0, Location::RequiresFpuRegister()); |
| (...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3995 | 3993 |
| 3996 void Float32x4WithInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 3994 void Float32x4WithInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 3997 XmmRegister replacement = locs()->in(0).fpu_reg(); | 3995 XmmRegister replacement = locs()->in(0).fpu_reg(); |
| 3998 XmmRegister value = locs()->in(1).fpu_reg(); | 3996 XmmRegister value = locs()->in(1).fpu_reg(); |
| 3999 | 3997 |
| 4000 ASSERT(locs()->out(0).fpu_reg() == replacement); | 3998 ASSERT(locs()->out(0).fpu_reg() == replacement); |
| 4001 | 3999 |
| 4002 switch (op_kind()) { | 4000 switch (op_kind()) { |
| 4003 case MethodRecognizer::kFloat32x4WithX: | 4001 case MethodRecognizer::kFloat32x4WithX: |
| 4004 __ cvtsd2ss(replacement, replacement); | 4002 __ cvtsd2ss(replacement, replacement); |
| 4005 __ AddImmediate(RSP, Immediate(-16), PP); | 4003 __ AddImmediate(RSP, Immediate(-16)); |
| 4006 // Move value to stack. | 4004 // Move value to stack. |
| 4007 __ movups(Address(RSP, 0), value); | 4005 __ movups(Address(RSP, 0), value); |
| 4008 // Write over X value. | 4006 // Write over X value. |
| 4009 __ movss(Address(RSP, 0), replacement); | 4007 __ movss(Address(RSP, 0), replacement); |
| 4010 // Move updated value into output register. | 4008 // Move updated value into output register. |
| 4011 __ movups(replacement, Address(RSP, 0)); | 4009 __ movups(replacement, Address(RSP, 0)); |
| 4012 __ AddImmediate(RSP, Immediate(16), PP); | 4010 __ AddImmediate(RSP, Immediate(16)); |
| 4013 break; | 4011 break; |
| 4014 case MethodRecognizer::kFloat32x4WithY: | 4012 case MethodRecognizer::kFloat32x4WithY: |
| 4015 __ cvtsd2ss(replacement, replacement); | 4013 __ cvtsd2ss(replacement, replacement); |
| 4016 __ AddImmediate(RSP, Immediate(-16), PP); | 4014 __ AddImmediate(RSP, Immediate(-16)); |
| 4017 // Move value to stack. | 4015 // Move value to stack. |
| 4018 __ movups(Address(RSP, 0), value); | 4016 __ movups(Address(RSP, 0), value); |
| 4019 // Write over Y value. | 4017 // Write over Y value. |
| 4020 __ movss(Address(RSP, 4), replacement); | 4018 __ movss(Address(RSP, 4), replacement); |
| 4021 // Move updated value into output register. | 4019 // Move updated value into output register. |
| 4022 __ movups(replacement, Address(RSP, 0)); | 4020 __ movups(replacement, Address(RSP, 0)); |
| 4023 __ AddImmediate(RSP, Immediate(16), PP); | 4021 __ AddImmediate(RSP, Immediate(16)); |
| 4024 break; | 4022 break; |
| 4025 case MethodRecognizer::kFloat32x4WithZ: | 4023 case MethodRecognizer::kFloat32x4WithZ: |
| 4026 __ cvtsd2ss(replacement, replacement); | 4024 __ cvtsd2ss(replacement, replacement); |
| 4027 __ AddImmediate(RSP, Immediate(-16), PP); | 4025 __ AddImmediate(RSP, Immediate(-16)); |
| 4028 // Move value to stack. | 4026 // Move value to stack. |
| 4029 __ movups(Address(RSP, 0), value); | 4027 __ movups(Address(RSP, 0), value); |
| 4030 // Write over Z value. | 4028 // Write over Z value. |
| 4031 __ movss(Address(RSP, 8), replacement); | 4029 __ movss(Address(RSP, 8), replacement); |
| 4032 // Move updated value into output register. | 4030 // Move updated value into output register. |
| 4033 __ movups(replacement, Address(RSP, 0)); | 4031 __ movups(replacement, Address(RSP, 0)); |
| 4034 __ AddImmediate(RSP, Immediate(16), PP); | 4032 __ AddImmediate(RSP, Immediate(16)); |
| 4035 break; | 4033 break; |
| 4036 case MethodRecognizer::kFloat32x4WithW: | 4034 case MethodRecognizer::kFloat32x4WithW: |
| 4037 __ cvtsd2ss(replacement, replacement); | 4035 __ cvtsd2ss(replacement, replacement); |
| 4038 __ AddImmediate(RSP, Immediate(-16), PP); | 4036 __ AddImmediate(RSP, Immediate(-16)); |
| 4039 // Move value to stack. | 4037 // Move value to stack. |
| 4040 __ movups(Address(RSP, 0), value); | 4038 __ movups(Address(RSP, 0), value); |
| 4041 // Write over W value. | 4039 // Write over W value. |
| 4042 __ movss(Address(RSP, 12), replacement); | 4040 __ movss(Address(RSP, 12), replacement); |
| 4043 // Move updated value into output register. | 4041 // Move updated value into output register. |
| 4044 __ movups(replacement, Address(RSP, 0)); | 4042 __ movups(replacement, Address(RSP, 0)); |
| 4045 __ AddImmediate(RSP, Immediate(16), PP); | 4043 __ AddImmediate(RSP, Immediate(16)); |
| 4046 break; | 4044 break; |
| 4047 default: UNREACHABLE(); | 4045 default: UNREACHABLE(); |
| 4048 } | 4046 } |
| 4049 } | 4047 } |
| 4050 | 4048 |
| 4051 | 4049 |
| 4052 LocationSummary* Float32x4ToInt32x4Instr::MakeLocationSummary(Zone* zone, | 4050 LocationSummary* Float32x4ToInt32x4Instr::MakeLocationSummary(Zone* zone, |
| 4053 bool opt) const { | 4051 bool opt) const { |
| 4054 const intptr_t kNumInputs = 1; | 4052 const intptr_t kNumInputs = 1; |
| 4055 const intptr_t kNumTemps = 0; | 4053 const intptr_t kNumTemps = 0; |
| (...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4300 return summary; | 4298 return summary; |
| 4301 } | 4299 } |
| 4302 | 4300 |
| 4303 | 4301 |
| 4304 void Int32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4302 void Int32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4305 Register v0 = locs()->in(0).reg(); | 4303 Register v0 = locs()->in(0).reg(); |
| 4306 Register v1 = locs()->in(1).reg(); | 4304 Register v1 = locs()->in(1).reg(); |
| 4307 Register v2 = locs()->in(2).reg(); | 4305 Register v2 = locs()->in(2).reg(); |
| 4308 Register v3 = locs()->in(3).reg(); | 4306 Register v3 = locs()->in(3).reg(); |
| 4309 XmmRegister result = locs()->out(0).fpu_reg(); | 4307 XmmRegister result = locs()->out(0).fpu_reg(); |
| 4310 __ AddImmediate(RSP, Immediate(-4 * kInt32Size), PP); | 4308 __ AddImmediate(RSP, Immediate(-4 * kInt32Size)); |
| 4311 __ movl(Address(RSP, 0 * kInt32Size), v0); | 4309 __ movl(Address(RSP, 0 * kInt32Size), v0); |
| 4312 __ movl(Address(RSP, 1 * kInt32Size), v1); | 4310 __ movl(Address(RSP, 1 * kInt32Size), v1); |
| 4313 __ movl(Address(RSP, 2 * kInt32Size), v2); | 4311 __ movl(Address(RSP, 2 * kInt32Size), v2); |
| 4314 __ movl(Address(RSP, 3 * kInt32Size), v3); | 4312 __ movl(Address(RSP, 3 * kInt32Size), v3); |
| 4315 __ movups(result, Address(RSP, 0)); | 4313 __ movups(result, Address(RSP, 0)); |
| 4316 __ AddImmediate(RSP, Immediate(4 * kInt32Size), PP); | 4314 __ AddImmediate(RSP, Immediate(4 * kInt32Size)); |
| 4317 } | 4315 } |
| 4318 | 4316 |
| 4319 | 4317 |
| 4320 LocationSummary* Int32x4BoolConstructorInstr::MakeLocationSummary( | 4318 LocationSummary* Int32x4BoolConstructorInstr::MakeLocationSummary( |
| 4321 Zone* zone, bool opt) const { | 4319 Zone* zone, bool opt) const { |
| 4322 const intptr_t kNumInputs = 4; | 4320 const intptr_t kNumInputs = 4; |
| 4323 const intptr_t kNumTemps = 1; | 4321 const intptr_t kNumTemps = 1; |
| 4324 LocationSummary* summary = new(zone) LocationSummary( | 4322 LocationSummary* summary = new(zone) LocationSummary( |
| 4325 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4323 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4326 summary->set_in(0, Location::RequiresRegister()); | 4324 summary->set_in(0, Location::RequiresRegister()); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 4337 Register v0 = locs()->in(0).reg(); | 4335 Register v0 = locs()->in(0).reg(); |
| 4338 Register v1 = locs()->in(1).reg(); | 4336 Register v1 = locs()->in(1).reg(); |
| 4339 Register v2 = locs()->in(2).reg(); | 4337 Register v2 = locs()->in(2).reg(); |
| 4340 Register v3 = locs()->in(3).reg(); | 4338 Register v3 = locs()->in(3).reg(); |
| 4341 Register temp = locs()->temp(0).reg(); | 4339 Register temp = locs()->temp(0).reg(); |
| 4342 XmmRegister result = locs()->out(0).fpu_reg(); | 4340 XmmRegister result = locs()->out(0).fpu_reg(); |
| 4343 Label x_false, x_done; | 4341 Label x_false, x_done; |
| 4344 Label y_false, y_done; | 4342 Label y_false, y_done; |
| 4345 Label z_false, z_done; | 4343 Label z_false, z_done; |
| 4346 Label w_false, w_done; | 4344 Label w_false, w_done; |
| 4347 __ AddImmediate(RSP, Immediate(-16), PP); | 4345 __ AddImmediate(RSP, Immediate(-16)); |
| 4348 | 4346 |
| 4349 __ CompareObject(v0, Bool::True(), PP); | 4347 __ CompareObject(v0, Bool::True()); |
| 4350 __ j(NOT_EQUAL, &x_false); | 4348 __ j(NOT_EQUAL, &x_false); |
| 4351 __ LoadImmediate(temp, Immediate(0xFFFFFFFF), PP); | 4349 __ LoadImmediate(temp, Immediate(0xFFFFFFFF)); |
| 4352 __ jmp(&x_done); | 4350 __ jmp(&x_done); |
| 4353 __ Bind(&x_false); | 4351 __ Bind(&x_false); |
| 4354 __ LoadImmediate(temp, Immediate(0x0), PP); | 4352 __ LoadImmediate(temp, Immediate(0x0)); |
| 4355 __ Bind(&x_done); | 4353 __ Bind(&x_done); |
| 4356 __ movl(Address(RSP, 0), temp); | 4354 __ movl(Address(RSP, 0), temp); |
| 4357 | 4355 |
| 4358 __ CompareObject(v1, Bool::True(), PP); | 4356 __ CompareObject(v1, Bool::True()); |
| 4359 __ j(NOT_EQUAL, &y_false); | 4357 __ j(NOT_EQUAL, &y_false); |
| 4360 __ LoadImmediate(temp, Immediate(0xFFFFFFFF), PP); | 4358 __ LoadImmediate(temp, Immediate(0xFFFFFFFF)); |
| 4361 __ jmp(&y_done); | 4359 __ jmp(&y_done); |
| 4362 __ Bind(&y_false); | 4360 __ Bind(&y_false); |
| 4363 __ LoadImmediate(temp, Immediate(0x0), PP); | 4361 __ LoadImmediate(temp, Immediate(0x0)); |
| 4364 __ Bind(&y_done); | 4362 __ Bind(&y_done); |
| 4365 __ movl(Address(RSP, 4), temp); | 4363 __ movl(Address(RSP, 4), temp); |
| 4366 | 4364 |
| 4367 __ CompareObject(v2, Bool::True(), PP); | 4365 __ CompareObject(v2, Bool::True()); |
| 4368 __ j(NOT_EQUAL, &z_false); | 4366 __ j(NOT_EQUAL, &z_false); |
| 4369 __ LoadImmediate(temp, Immediate(0xFFFFFFFF), PP); | 4367 __ LoadImmediate(temp, Immediate(0xFFFFFFFF)); |
| 4370 __ jmp(&z_done); | 4368 __ jmp(&z_done); |
| 4371 __ Bind(&z_false); | 4369 __ Bind(&z_false); |
| 4372 __ LoadImmediate(temp, Immediate(0x0), PP); | 4370 __ LoadImmediate(temp, Immediate(0x0)); |
| 4373 __ Bind(&z_done); | 4371 __ Bind(&z_done); |
| 4374 __ movl(Address(RSP, 8), temp); | 4372 __ movl(Address(RSP, 8), temp); |
| 4375 | 4373 |
| 4376 __ CompareObject(v3, Bool::True(), PP); | 4374 __ CompareObject(v3, Bool::True()); |
| 4377 __ j(NOT_EQUAL, &w_false); | 4375 __ j(NOT_EQUAL, &w_false); |
| 4378 __ LoadImmediate(temp, Immediate(0xFFFFFFFF), PP); | 4376 __ LoadImmediate(temp, Immediate(0xFFFFFFFF)); |
| 4379 __ jmp(&w_done); | 4377 __ jmp(&w_done); |
| 4380 __ Bind(&w_false); | 4378 __ Bind(&w_false); |
| 4381 __ LoadImmediate(temp, Immediate(0x0), PP); | 4379 __ LoadImmediate(temp, Immediate(0x0)); |
| 4382 __ Bind(&w_done); | 4380 __ Bind(&w_done); |
| 4383 __ movl(Address(RSP, 12), temp); | 4381 __ movl(Address(RSP, 12), temp); |
| 4384 | 4382 |
| 4385 __ movups(result, Address(RSP, 0)); | 4383 __ movups(result, Address(RSP, 0)); |
| 4386 __ AddImmediate(RSP, Immediate(16), PP); | 4384 __ AddImmediate(RSP, Immediate(16)); |
| 4387 } | 4385 } |
| 4388 | 4386 |
| 4389 | 4387 |
| 4390 LocationSummary* Int32x4GetFlagInstr::MakeLocationSummary(Zone* zone, | 4388 LocationSummary* Int32x4GetFlagInstr::MakeLocationSummary(Zone* zone, |
| 4391 bool opt) const { | 4389 bool opt) const { |
| 4392 const intptr_t kNumInputs = 1; | 4390 const intptr_t kNumInputs = 1; |
| 4393 const intptr_t kNumTemps = 0; | 4391 const intptr_t kNumTemps = 0; |
| 4394 LocationSummary* summary = new(zone) LocationSummary( | 4392 LocationSummary* summary = new(zone) LocationSummary( |
| 4395 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4393 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4396 summary->set_in(0, Location::RequiresFpuRegister()); | 4394 summary->set_in(0, Location::RequiresFpuRegister()); |
| 4397 summary->set_out(0, Location::RequiresRegister()); | 4395 summary->set_out(0, Location::RequiresRegister()); |
| 4398 return summary; | 4396 return summary; |
| 4399 } | 4397 } |
| 4400 | 4398 |
| 4401 | 4399 |
| 4402 void Int32x4GetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4400 void Int32x4GetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4403 XmmRegister value = locs()->in(0).fpu_reg(); | 4401 XmmRegister value = locs()->in(0).fpu_reg(); |
| 4404 Register result = locs()->out(0).reg(); | 4402 Register result = locs()->out(0).reg(); |
| 4405 Label done; | 4403 Label done; |
| 4406 Label non_zero; | 4404 Label non_zero; |
| 4407 __ AddImmediate(RSP, Immediate(-16), PP); | 4405 __ AddImmediate(RSP, Immediate(-16)); |
| 4408 // Move value to stack. | 4406 // Move value to stack. |
| 4409 __ movups(Address(RSP, 0), value); | 4407 __ movups(Address(RSP, 0), value); |
| 4410 switch (op_kind()) { | 4408 switch (op_kind()) { |
| 4411 case MethodRecognizer::kInt32x4GetFlagX: | 4409 case MethodRecognizer::kInt32x4GetFlagX: |
| 4412 __ movl(result, Address(RSP, 0)); | 4410 __ movl(result, Address(RSP, 0)); |
| 4413 break; | 4411 break; |
| 4414 case MethodRecognizer::kInt32x4GetFlagY: | 4412 case MethodRecognizer::kInt32x4GetFlagY: |
| 4415 __ movl(result, Address(RSP, 4)); | 4413 __ movl(result, Address(RSP, 4)); |
| 4416 break; | 4414 break; |
| 4417 case MethodRecognizer::kInt32x4GetFlagZ: | 4415 case MethodRecognizer::kInt32x4GetFlagZ: |
| 4418 __ movl(result, Address(RSP, 8)); | 4416 __ movl(result, Address(RSP, 8)); |
| 4419 break; | 4417 break; |
| 4420 case MethodRecognizer::kInt32x4GetFlagW: | 4418 case MethodRecognizer::kInt32x4GetFlagW: |
| 4421 __ movl(result, Address(RSP, 12)); | 4419 __ movl(result, Address(RSP, 12)); |
| 4422 break; | 4420 break; |
| 4423 default: UNREACHABLE(); | 4421 default: UNREACHABLE(); |
| 4424 } | 4422 } |
| 4425 __ AddImmediate(RSP, Immediate(16), PP); | 4423 __ AddImmediate(RSP, Immediate(16)); |
| 4426 __ testl(result, result); | 4424 __ testl(result, result); |
| 4427 __ j(NOT_ZERO, &non_zero, Assembler::kNearJump); | 4425 __ j(NOT_ZERO, &non_zero, Assembler::kNearJump); |
| 4428 __ LoadObject(result, Bool::False(), PP); | 4426 __ LoadObject(result, Bool::False()); |
| 4429 __ jmp(&done); | 4427 __ jmp(&done); |
| 4430 __ Bind(&non_zero); | 4428 __ Bind(&non_zero); |
| 4431 __ LoadObject(result, Bool::True(), PP); | 4429 __ LoadObject(result, Bool::True()); |
| 4432 __ Bind(&done); | 4430 __ Bind(&done); |
| 4433 } | 4431 } |
| 4434 | 4432 |
| 4435 | 4433 |
| 4436 LocationSummary* Int32x4SelectInstr::MakeLocationSummary(Zone* zone, | 4434 LocationSummary* Int32x4SelectInstr::MakeLocationSummary(Zone* zone, |
| 4437 bool opt) const { | 4435 bool opt) const { |
| 4438 const intptr_t kNumInputs = 3; | 4436 const intptr_t kNumInputs = 3; |
| 4439 const intptr_t kNumTemps = 1; | 4437 const intptr_t kNumTemps = 1; |
| 4440 LocationSummary* summary = new(zone) LocationSummary( | 4438 LocationSummary* summary = new(zone) LocationSummary( |
| 4441 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4439 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4480 summary->set_out(0, Location::SameAsFirstInput()); | 4478 summary->set_out(0, Location::SameAsFirstInput()); |
| 4481 return summary; | 4479 return summary; |
| 4482 } | 4480 } |
| 4483 | 4481 |
| 4484 | 4482 |
| 4485 void Int32x4SetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 4483 void Int32x4SetFlagInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 4486 XmmRegister mask = locs()->in(0).fpu_reg(); | 4484 XmmRegister mask = locs()->in(0).fpu_reg(); |
| 4487 Register flag = locs()->in(1).reg(); | 4485 Register flag = locs()->in(1).reg(); |
| 4488 Register temp = locs()->temp(0).reg(); | 4486 Register temp = locs()->temp(0).reg(); |
| 4489 ASSERT(mask == locs()->out(0).fpu_reg()); | 4487 ASSERT(mask == locs()->out(0).fpu_reg()); |
| 4490 __ AddImmediate(RSP, Immediate(-16), PP); | 4488 __ AddImmediate(RSP, Immediate(-16)); |
| 4491 // Copy mask to stack. | 4489 // Copy mask to stack. |
| 4492 __ movups(Address(RSP, 0), mask); | 4490 __ movups(Address(RSP, 0), mask); |
| 4493 Label falsePath, exitPath; | 4491 Label falsePath, exitPath; |
| 4494 __ CompareObject(flag, Bool::True(), PP); | 4492 __ CompareObject(flag, Bool::True()); |
| 4495 __ j(NOT_EQUAL, &falsePath); | 4493 __ j(NOT_EQUAL, &falsePath); |
| 4496 switch (op_kind()) { | 4494 switch (op_kind()) { |
| 4497 case MethodRecognizer::kInt32x4WithFlagX: | 4495 case MethodRecognizer::kInt32x4WithFlagX: |
| 4498 __ LoadImmediate(temp, Immediate(0xFFFFFFFF), PP); | 4496 __ LoadImmediate(temp, Immediate(0xFFFFFFFF)); |
| 4499 __ movl(Address(RSP, 0), temp); | 4497 __ movl(Address(RSP, 0), temp); |
| 4500 __ jmp(&exitPath); | 4498 __ jmp(&exitPath); |
| 4501 __ Bind(&falsePath); | 4499 __ Bind(&falsePath); |
| 4502 __ LoadImmediate(temp, Immediate(0x0), PP); | 4500 __ LoadImmediate(temp, Immediate(0x0)); |
| 4503 __ movl(Address(RSP, 0), temp); | 4501 __ movl(Address(RSP, 0), temp); |
| 4504 break; | 4502 break; |
| 4505 case MethodRecognizer::kInt32x4WithFlagY: | 4503 case MethodRecognizer::kInt32x4WithFlagY: |
| 4506 __ LoadImmediate(temp, Immediate(0xFFFFFFFF), PP); | 4504 __ LoadImmediate(temp, Immediate(0xFFFFFFFF)); |
| 4507 __ movl(Address(RSP, 4), temp); | 4505 __ movl(Address(RSP, 4), temp); |
| 4508 __ jmp(&exitPath); | 4506 __ jmp(&exitPath); |
| 4509 __ Bind(&falsePath); | 4507 __ Bind(&falsePath); |
| 4510 __ LoadImmediate(temp, Immediate(0x0), PP); | 4508 __ LoadImmediate(temp, Immediate(0x0)); |
| 4511 __ movl(Address(RSP, 4), temp); | 4509 __ movl(Address(RSP, 4), temp); |
| 4512 break; | 4510 break; |
| 4513 case MethodRecognizer::kInt32x4WithFlagZ: | 4511 case MethodRecognizer::kInt32x4WithFlagZ: |
| 4514 __ LoadImmediate(temp, Immediate(0xFFFFFFFF), PP); | 4512 __ LoadImmediate(temp, Immediate(0xFFFFFFFF)); |
| 4515 __ movl(Address(RSP, 8), temp); | 4513 __ movl(Address(RSP, 8), temp); |
| 4516 __ jmp(&exitPath); | 4514 __ jmp(&exitPath); |
| 4517 __ Bind(&falsePath); | 4515 __ Bind(&falsePath); |
| 4518 __ LoadImmediate(temp, Immediate(0x0), PP); | 4516 __ LoadImmediate(temp, Immediate(0x0)); |
| 4519 __ movl(Address(RSP, 8), temp); | 4517 __ movl(Address(RSP, 8), temp); |
| 4520 break; | 4518 break; |
| 4521 case MethodRecognizer::kInt32x4WithFlagW: | 4519 case MethodRecognizer::kInt32x4WithFlagW: |
| 4522 __ LoadImmediate(temp, Immediate(0xFFFFFFFF), PP); | 4520 __ LoadImmediate(temp, Immediate(0xFFFFFFFF)); |
| 4523 __ movl(Address(RSP, 12), temp); | 4521 __ movl(Address(RSP, 12), temp); |
| 4524 __ jmp(&exitPath); | 4522 __ jmp(&exitPath); |
| 4525 __ Bind(&falsePath); | 4523 __ Bind(&falsePath); |
| 4526 __ LoadImmediate(temp, Immediate(0x0), PP); | 4524 __ LoadImmediate(temp, Immediate(0x0)); |
| 4527 __ movl(Address(RSP, 12), temp); | 4525 __ movl(Address(RSP, 12), temp); |
| 4528 break; | 4526 break; |
| 4529 default: UNREACHABLE(); | 4527 default: UNREACHABLE(); |
| 4530 } | 4528 } |
| 4531 __ Bind(&exitPath); | 4529 __ Bind(&exitPath); |
| 4532 // Copy mask back to register. | 4530 // Copy mask back to register. |
| 4533 __ movups(mask, Address(RSP, 0)); | 4531 __ movups(mask, Address(RSP, 0)); |
| 4534 __ AddImmediate(RSP, Immediate(16), PP); | 4532 __ AddImmediate(RSP, Immediate(16)); |
| 4535 } | 4533 } |
| 4536 | 4534 |
| 4537 | 4535 |
| 4538 LocationSummary* Int32x4ToFloat32x4Instr::MakeLocationSummary(Zone* zone, | 4536 LocationSummary* Int32x4ToFloat32x4Instr::MakeLocationSummary(Zone* zone, |
| 4539 bool opt) const { | 4537 bool opt) const { |
| 4540 const intptr_t kNumInputs = 1; | 4538 const intptr_t kNumInputs = 1; |
| 4541 const intptr_t kNumTemps = 0; | 4539 const intptr_t kNumTemps = 0; |
| 4542 LocationSummary* summary = new(zone) LocationSummary( | 4540 LocationSummary* summary = new(zone) LocationSummary( |
| 4543 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 4541 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 4544 summary->set_in(0, Location::RequiresFpuRegister()); | 4542 summary->set_in(0, Location::RequiresFpuRegister()); |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4699 __ negq(value); | 4697 __ negq(value); |
| 4700 __ j(OVERFLOW, deopt); | 4698 __ j(OVERFLOW, deopt); |
| 4701 if (FLAG_throw_on_javascript_int_overflow) { | 4699 if (FLAG_throw_on_javascript_int_overflow) { |
| 4702 EmitJavascriptOverflowCheck(compiler, range(), deopt, value); | 4700 EmitJavascriptOverflowCheck(compiler, range(), deopt, value); |
| 4703 } | 4701 } |
| 4704 break; | 4702 break; |
| 4705 } | 4703 } |
| 4706 case Token::kBIT_NOT: | 4704 case Token::kBIT_NOT: |
| 4707 __ notq(value); | 4705 __ notq(value); |
| 4708 // Remove inverted smi-tag. | 4706 // Remove inverted smi-tag. |
| 4709 __ AndImmediate(value, Immediate(~kSmiTagMask), PP); | 4707 __ AndImmediate(value, Immediate(~kSmiTagMask)); |
| 4710 break; | 4708 break; |
| 4711 default: | 4709 default: |
| 4712 UNREACHABLE(); | 4710 UNREACHABLE(); |
| 4713 } | 4711 } |
| 4714 } | 4712 } |
| 4715 | 4713 |
| 4716 | 4714 |
| 4717 LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(Zone* zone, | 4715 LocationSummary* UnaryDoubleOpInstr::MakeLocationSummary(Zone* zone, |
| 4718 bool opt) const { | 4716 bool opt) const { |
| 4719 const intptr_t kNumInputs = 1; | 4717 const intptr_t kNumInputs = 1; |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4776 const Condition double_condition = | 4774 const Condition double_condition = |
| 4777 is_min ? TokenKindToDoubleCondition(Token::kLT) | 4775 is_min ? TokenKindToDoubleCondition(Token::kLT) |
| 4778 : TokenKindToDoubleCondition(Token::kGT); | 4776 : TokenKindToDoubleCondition(Token::kGT); |
| 4779 ASSERT(left == result); | 4777 ASSERT(left == result); |
| 4780 __ j(double_condition, &done, Assembler::kNearJump); | 4778 __ j(double_condition, &done, Assembler::kNearJump); |
| 4781 __ movsd(result, right); | 4779 __ movsd(result, right); |
| 4782 __ jmp(&done, Assembler::kNearJump); | 4780 __ jmp(&done, Assembler::kNearJump); |
| 4783 | 4781 |
| 4784 __ Bind(&returns_nan); | 4782 __ Bind(&returns_nan); |
| 4785 static double kNaN = NAN; | 4783 static double kNaN = NAN; |
| 4786 __ LoadImmediate(temp, Immediate(reinterpret_cast<intptr_t>(&kNaN)), PP); | 4784 __ LoadImmediate(temp, Immediate(reinterpret_cast<intptr_t>(&kNaN))); |
| 4787 __ movsd(result, Address(temp, 0)); | 4785 __ movsd(result, Address(temp, 0)); |
| 4788 __ jmp(&done, Assembler::kNearJump); | 4786 __ jmp(&done, Assembler::kNearJump); |
| 4789 | 4787 |
| 4790 __ Bind(&are_equal); | 4788 __ Bind(&are_equal); |
| 4791 Label left_is_negative; | 4789 Label left_is_negative; |
| 4792 // Check for negative zero: -0.0 is equal 0.0 but min or max must return | 4790 // Check for negative zero: -0.0 is equal 0.0 but min or max must return |
| 4793 // -0.0 or 0.0 respectively. | 4791 // -0.0 or 0.0 respectively. |
| 4794 // Check for negative left value (get the sign bit): | 4792 // Check for negative left value (get the sign bit): |
| 4795 // - min -> left is negative ? left : right. | 4793 // - min -> left is negative ? left : right. |
| 4796 // - max -> left is negative ? right : left | 4794 // - max -> left is negative ? right : left |
| (...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5077 | 5075 |
| 5078 XmmRegister base = locs->in(0).fpu_reg(); | 5076 XmmRegister base = locs->in(0).fpu_reg(); |
| 5079 XmmRegister exp = locs->in(1).fpu_reg(); | 5077 XmmRegister exp = locs->in(1).fpu_reg(); |
| 5080 XmmRegister result = locs->out(0).fpu_reg(); | 5078 XmmRegister result = locs->out(0).fpu_reg(); |
| 5081 Register temp = | 5079 Register temp = |
| 5082 locs->temp(InvokeMathCFunctionInstr::kObjectTempIndex).reg(); | 5080 locs->temp(InvokeMathCFunctionInstr::kObjectTempIndex).reg(); |
| 5083 XmmRegister zero_temp = | 5081 XmmRegister zero_temp = |
| 5084 locs->temp(InvokeMathCFunctionInstr::kDoubleTempIndex).fpu_reg(); | 5082 locs->temp(InvokeMathCFunctionInstr::kDoubleTempIndex).fpu_reg(); |
| 5085 | 5083 |
| 5086 __ xorps(zero_temp, zero_temp); | 5084 __ xorps(zero_temp, zero_temp); |
| 5087 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(1)), PP); | 5085 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(1))); |
| 5088 __ movsd(result, FieldAddress(temp, Double::value_offset())); | 5086 __ movsd(result, FieldAddress(temp, Double::value_offset())); |
| 5089 | 5087 |
| 5090 Label check_base, skip_call; | 5088 Label check_base, skip_call; |
| 5091 // exponent == 0.0 -> return 1.0; | 5089 // exponent == 0.0 -> return 1.0; |
| 5092 __ comisd(exp, zero_temp); | 5090 __ comisd(exp, zero_temp); |
| 5093 __ j(PARITY_EVEN, &check_base, Assembler::kNearJump); | 5091 __ j(PARITY_EVEN, &check_base, Assembler::kNearJump); |
| 5094 __ j(EQUAL, &skip_call); // 'result' is 1.0. | 5092 __ j(EQUAL, &skip_call); // 'result' is 1.0. |
| 5095 | 5093 |
| 5096 // exponent == 1.0 ? | 5094 // exponent == 1.0 ? |
| 5097 __ comisd(exp, result); | 5095 __ comisd(exp, result); |
| 5098 Label return_base; | 5096 Label return_base; |
| 5099 __ j(EQUAL, &return_base, Assembler::kNearJump); | 5097 __ j(EQUAL, &return_base, Assembler::kNearJump); |
| 5100 | 5098 |
| 5101 // exponent == 2.0 ? | 5099 // exponent == 2.0 ? |
| 5102 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(2.0)), PP); | 5100 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(2.0))); |
| 5103 __ movsd(XMM0, FieldAddress(temp, Double::value_offset())); | 5101 __ movsd(XMM0, FieldAddress(temp, Double::value_offset())); |
| 5104 __ comisd(exp, XMM0); | 5102 __ comisd(exp, XMM0); |
| 5105 Label return_base_times_2; | 5103 Label return_base_times_2; |
| 5106 __ j(EQUAL, &return_base_times_2, Assembler::kNearJump); | 5104 __ j(EQUAL, &return_base_times_2, Assembler::kNearJump); |
| 5107 | 5105 |
| 5108 // exponent == 3.0 ? | 5106 // exponent == 3.0 ? |
| 5109 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(3.0)), PP); | 5107 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(3.0))); |
| 5110 __ movsd(XMM0, FieldAddress(temp, Double::value_offset())); | 5108 __ movsd(XMM0, FieldAddress(temp, Double::value_offset())); |
| 5111 __ comisd(exp, XMM0); | 5109 __ comisd(exp, XMM0); |
| 5112 __ j(NOT_EQUAL, &check_base); | 5110 __ j(NOT_EQUAL, &check_base); |
| 5113 | 5111 |
| 5114 // Base times 3. | 5112 // Base times 3. |
| 5115 __ movsd(result, base); | 5113 __ movsd(result, base); |
| 5116 __ mulsd(result, base); | 5114 __ mulsd(result, base); |
| 5117 __ mulsd(result, base); | 5115 __ mulsd(result, base); |
| 5118 __ jmp(&skip_call); | 5116 __ jmp(&skip_call); |
| 5119 | 5117 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 5134 __ comisd(base, result); | 5132 __ comisd(base, result); |
| 5135 __ j(PARITY_EVEN, &return_nan, Assembler::kNearJump); | 5133 __ j(PARITY_EVEN, &return_nan, Assembler::kNearJump); |
| 5136 __ j(EQUAL, &skip_call, Assembler::kNearJump); | 5134 __ j(EQUAL, &skip_call, Assembler::kNearJump); |
| 5137 // Note: 'base' could be NaN. | 5135 // Note: 'base' could be NaN. |
| 5138 __ comisd(exp, base); | 5136 __ comisd(exp, base); |
| 5139 // Neither 'exp' nor 'base' is NaN. | 5137 // Neither 'exp' nor 'base' is NaN. |
| 5140 Label try_sqrt; | 5138 Label try_sqrt; |
| 5141 __ j(PARITY_ODD, &try_sqrt, Assembler::kNearJump); | 5139 __ j(PARITY_ODD, &try_sqrt, Assembler::kNearJump); |
| 5142 // Return NaN. | 5140 // Return NaN. |
| 5143 __ Bind(&return_nan); | 5141 __ Bind(&return_nan); |
| 5144 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(NAN)), PP); | 5142 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(NAN))); |
| 5145 __ movsd(result, FieldAddress(temp, Double::value_offset())); | 5143 __ movsd(result, FieldAddress(temp, Double::value_offset())); |
| 5146 __ jmp(&skip_call); | 5144 __ jmp(&skip_call); |
| 5147 | 5145 |
| 5148 Label do_pow, return_zero; | 5146 Label do_pow, return_zero; |
| 5149 __ Bind(&try_sqrt); | 5147 __ Bind(&try_sqrt); |
| 5150 // Before calling pow, check if we could use sqrt instead of pow. | 5148 // Before calling pow, check if we could use sqrt instead of pow. |
| 5151 __ LoadObject(temp, | 5149 __ LoadObject(temp, |
| 5152 Double::ZoneHandle(Double::NewCanonical(kNegInfinity)), PP); | 5150 Double::ZoneHandle(Double::NewCanonical(kNegInfinity))); |
| 5153 __ movsd(result, FieldAddress(temp, Double::value_offset())); | 5151 __ movsd(result, FieldAddress(temp, Double::value_offset())); |
| 5154 // base == -Infinity -> call pow; | 5152 // base == -Infinity -> call pow; |
| 5155 __ comisd(base, result); | 5153 __ comisd(base, result); |
| 5156 __ j(EQUAL, &do_pow, Assembler::kNearJump); | 5154 __ j(EQUAL, &do_pow, Assembler::kNearJump); |
| 5157 | 5155 |
| 5158 // exponent == 0.5 ? | 5156 // exponent == 0.5 ? |
| 5159 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(0.5)), PP); | 5157 __ LoadObject(temp, Double::ZoneHandle(Double::NewCanonical(0.5))); |
| 5160 __ movsd(result, FieldAddress(temp, Double::value_offset())); | 5158 __ movsd(result, FieldAddress(temp, Double::value_offset())); |
| 5161 __ comisd(exp, result); | 5159 __ comisd(exp, result); |
| 5162 __ j(NOT_EQUAL, &do_pow, Assembler::kNearJump); | 5160 __ j(NOT_EQUAL, &do_pow, Assembler::kNearJump); |
| 5163 | 5161 |
| 5164 // base == 0 -> return 0; | 5162 // base == 0 -> return 0; |
| 5165 __ comisd(base, zero_temp); | 5163 __ comisd(base, zero_temp); |
| 5166 __ j(EQUAL, &return_zero, Assembler::kNearJump); | 5164 __ j(EQUAL, &return_zero, Assembler::kNearJump); |
| 5167 | 5165 |
| 5168 __ sqrtsd(result, base); | 5166 __ sqrtsd(result, base); |
| 5169 __ jmp(&skip_call, Assembler::kNearJump); | 5167 __ jmp(&skip_call, Assembler::kNearJump); |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5346 __ jmp(&done); | 5344 __ jmp(&done); |
| 5347 | 5345 |
| 5348 // Divide using 64bit idiv. | 5346 // Divide using 64bit idiv. |
| 5349 __ Bind(¬_32bit); | 5347 __ Bind(¬_32bit); |
| 5350 __ SmiUntag(left); | 5348 __ SmiUntag(left); |
| 5351 __ SmiUntag(right); | 5349 __ SmiUntag(right); |
| 5352 __ cqo(); // Sign extend RAX -> RDX:RAX. | 5350 __ cqo(); // Sign extend RAX -> RDX:RAX. |
| 5353 __ idivq(right); // RAX: quotient, RDX: remainder. | 5351 __ idivq(right); // RAX: quotient, RDX: remainder. |
| 5354 // Check the corner case of dividing the 'MIN_SMI' with -1, in which | 5352 // Check the corner case of dividing the 'MIN_SMI' with -1, in which |
| 5355 // case we cannot tag the result. | 5353 // case we cannot tag the result. |
| 5356 __ CompareImmediate(RAX, Immediate(0x4000000000000000), PP); | 5354 __ CompareImmediate(RAX, Immediate(0x4000000000000000)); |
| 5357 __ j(EQUAL, deopt); | 5355 __ j(EQUAL, deopt); |
| 5358 __ Bind(&done); | 5356 __ Bind(&done); |
| 5359 | 5357 |
| 5360 // Modulo correction (RDX). | 5358 // Modulo correction (RDX). |
| 5361 // res = left % right; | 5359 // res = left % right; |
| 5362 // if (res < 0) { | 5360 // if (res < 0) { |
| 5363 // if (right < 0) { | 5361 // if (right < 0) { |
| 5364 // res = res - right; | 5362 // res = res - right; |
| 5365 // } else { | 5363 // } else { |
| 5366 // res = res + right; | 5364 // res = res + right; |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5470 return summary; | 5468 return summary; |
| 5471 } | 5469 } |
| 5472 | 5470 |
| 5473 | 5471 |
| 5474 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5472 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5475 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 5473 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
| 5476 ICData::kDeoptCheckClass, | 5474 ICData::kDeoptCheckClass, |
| 5477 licm_hoisted_ ? ICData::kHoisted : 0); | 5475 licm_hoisted_ ? ICData::kHoisted : 0); |
| 5478 if (IsNullCheck()) { | 5476 if (IsNullCheck()) { |
| 5479 __ CompareObject(locs()->in(0).reg(), | 5477 __ CompareObject(locs()->in(0).reg(), |
| 5480 Object::null_object(), PP); | 5478 Object::null_object()); |
| 5481 Condition cond = DeoptIfNull() ? EQUAL : NOT_EQUAL; | 5479 Condition cond = DeoptIfNull() ? EQUAL : NOT_EQUAL; |
| 5482 __ j(cond, deopt); | 5480 __ j(cond, deopt); |
| 5483 return; | 5481 return; |
| 5484 } | 5482 } |
| 5485 | 5483 |
| 5486 ASSERT((unary_checks().GetReceiverClassIdAt(0) != kSmiCid) || | 5484 ASSERT((unary_checks().GetReceiverClassIdAt(0) != kSmiCid) || |
| 5487 (unary_checks().NumberOfChecks() > 1)); | 5485 (unary_checks().NumberOfChecks() > 1)); |
| 5488 Register value = locs()->in(0).reg(); | 5486 Register value = locs()->in(0).reg(); |
| 5489 Register temp = locs()->temp(0).reg(); | 5487 Register temp = locs()->temp(0).reg(); |
| 5490 Label is_ok; | 5488 Label is_ok; |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5565 LocationSummary* summary = new(zone) LocationSummary( | 5563 LocationSummary* summary = new(zone) LocationSummary( |
| 5566 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5564 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| 5567 summary->set_in(0, Location::RequiresRegister()); | 5565 summary->set_in(0, Location::RequiresRegister()); |
| 5568 return summary; | 5566 return summary; |
| 5569 } | 5567 } |
| 5570 | 5568 |
| 5571 | 5569 |
| 5572 void CheckClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5570 void CheckClassIdInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5573 Register value = locs()->in(0).reg(); | 5571 Register value = locs()->in(0).reg(); |
| 5574 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass); | 5572 Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptCheckClass); |
| 5575 __ CompareImmediate(value, Immediate(Smi::RawValue(cid_)), PP); | 5573 __ CompareImmediate(value, Immediate(Smi::RawValue(cid_))); |
| 5576 __ j(NOT_ZERO, deopt); | 5574 __ j(NOT_ZERO, deopt); |
| 5577 } | 5575 } |
| 5578 | 5576 |
| 5579 | 5577 |
| 5580 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary(Zone* zone, | 5578 LocationSummary* CheckArrayBoundInstr::MakeLocationSummary(Zone* zone, |
| 5581 bool opt) const { | 5579 bool opt) const { |
| 5582 const intptr_t kNumInputs = 2; | 5580 const intptr_t kNumInputs = 2; |
| 5583 const intptr_t kNumTemps = 0; | 5581 const intptr_t kNumTemps = 0; |
| 5584 LocationSummary* locs = new(zone) LocationSummary( | 5582 LocationSummary* locs = new(zone) LocationSummary( |
| 5585 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); | 5583 zone, kNumInputs, kNumTemps, LocationSummary::kNoCall); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 5607 // Unconditionally deoptimize for constant bounds checks because they | 5605 // Unconditionally deoptimize for constant bounds checks because they |
| 5608 // only occur only when index is out-of-bounds. | 5606 // only occur only when index is out-of-bounds. |
| 5609 __ jmp(deopt); | 5607 __ jmp(deopt); |
| 5610 return; | 5608 return; |
| 5611 } | 5609 } |
| 5612 | 5610 |
| 5613 if (index_loc.IsConstant()) { | 5611 if (index_loc.IsConstant()) { |
| 5614 Register length = length_loc.reg(); | 5612 Register length = length_loc.reg(); |
| 5615 const Smi& index = Smi::Cast(index_loc.constant()); | 5613 const Smi& index = Smi::Cast(index_loc.constant()); |
| 5616 __ CompareImmediate( | 5614 __ CompareImmediate( |
| 5617 length, Immediate(reinterpret_cast<int64_t>(index.raw())), PP); | 5615 length, Immediate(reinterpret_cast<int64_t>(index.raw()))); |
| 5618 __ j(BELOW_EQUAL, deopt); | 5616 __ j(BELOW_EQUAL, deopt); |
| 5619 } else if (length_loc.IsConstant()) { | 5617 } else if (length_loc.IsConstant()) { |
| 5620 const Smi& length = Smi::Cast(length_loc.constant()); | 5618 const Smi& length = Smi::Cast(length_loc.constant()); |
| 5621 Register index = index_loc.reg(); | 5619 Register index = index_loc.reg(); |
| 5622 if (length.Value() == Smi::kMaxValue) { | 5620 if (length.Value() == Smi::kMaxValue) { |
| 5623 __ testq(index, index); | 5621 __ testq(index, index); |
| 5624 __ j(NEGATIVE, deopt); | 5622 __ j(NEGATIVE, deopt); |
| 5625 } else { | 5623 } else { |
| 5626 __ CompareImmediate( | 5624 __ CompareImmediate( |
| 5627 index, Immediate(reinterpret_cast<int64_t>(length.raw())), PP); | 5625 index, Immediate(reinterpret_cast<int64_t>(length.raw()))); |
| 5628 __ j(ABOVE_EQUAL, deopt); | 5626 __ j(ABOVE_EQUAL, deopt); |
| 5629 } | 5627 } |
| 5630 } else { | 5628 } else { |
| 5631 Register length = length_loc.reg(); | 5629 Register length = length_loc.reg(); |
| 5632 Register index = index_loc.reg(); | 5630 Register index = index_loc.reg(); |
| 5633 __ cmpq(index, length); | 5631 __ cmpq(index, length); |
| 5634 __ j(ABOVE_EQUAL, deopt); | 5632 __ j(ABOVE_EQUAL, deopt); |
| 5635 } | 5633 } |
| 5636 } | 5634 } |
| 5637 | 5635 |
| (...skipping 636 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6274 | 6272 |
| 6275 Label is_true, is_false; | 6273 Label is_true, is_false; |
| 6276 BranchLabels labels = { &is_true, &is_false, &is_false }; | 6274 BranchLabels labels = { &is_true, &is_false, &is_false }; |
| 6277 | 6275 |
| 6278 Condition true_condition = EmitComparisonCode(compiler, labels); | 6276 Condition true_condition = EmitComparisonCode(compiler, labels); |
| 6279 EmitBranchOnCondition(compiler, true_condition, labels); | 6277 EmitBranchOnCondition(compiler, true_condition, labels); |
| 6280 | 6278 |
| 6281 Register result = locs()->out(0).reg(); | 6279 Register result = locs()->out(0).reg(); |
| 6282 Label done; | 6280 Label done; |
| 6283 __ Bind(&is_false); | 6281 __ Bind(&is_false); |
| 6284 __ LoadObject(result, Bool::False(), PP); | 6282 __ LoadObject(result, Bool::False()); |
| 6285 __ jmp(&done); | 6283 __ jmp(&done); |
| 6286 __ Bind(&is_true); | 6284 __ Bind(&is_true); |
| 6287 __ LoadObject(result, Bool::True(), PP); | 6285 __ LoadObject(result, Bool::True()); |
| 6288 __ Bind(&done); | 6286 __ Bind(&done); |
| 6289 } | 6287 } |
| 6290 | 6288 |
| 6291 | 6289 |
| 6292 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, | 6290 void StrictCompareInstr::EmitBranchCode(FlowGraphCompiler* compiler, |
| 6293 BranchInstr* branch) { | 6291 BranchInstr* branch) { |
| 6294 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); | 6292 ASSERT(kind() == Token::kEQ_STRICT || kind() == Token::kNE_STRICT); |
| 6295 | 6293 |
| 6296 BranchLabels labels = compiler->CreateBranchLabels(branch); | 6294 BranchLabels labels = compiler->CreateBranchLabels(branch); |
| 6297 Condition true_condition = EmitComparisonCode(compiler, labels); | 6295 Condition true_condition = EmitComparisonCode(compiler, labels); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 6310 return summary; | 6308 return summary; |
| 6311 } | 6309 } |
| 6312 | 6310 |
| 6313 | 6311 |
| 6314 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6312 void ClosureCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6315 // Arguments descriptor is expected in R10. | 6313 // Arguments descriptor is expected in R10. |
| 6316 intptr_t argument_count = ArgumentCount(); | 6314 intptr_t argument_count = ArgumentCount(); |
| 6317 const Array& arguments_descriptor = | 6315 const Array& arguments_descriptor = |
| 6318 Array::ZoneHandle(ArgumentsDescriptor::New(argument_count, | 6316 Array::ZoneHandle(ArgumentsDescriptor::New(argument_count, |
| 6319 argument_names())); | 6317 argument_names())); |
| 6320 __ LoadObject(R10, arguments_descriptor, PP); | 6318 __ LoadObject(R10, arguments_descriptor); |
| 6321 | 6319 |
| 6322 // Function in RAX. | 6320 // Function in RAX. |
| 6323 ASSERT(locs()->in(0).reg() == RAX); | 6321 ASSERT(locs()->in(0).reg() == RAX); |
| 6324 __ movq(RCX, FieldAddress(RAX, Function::instructions_offset())); | 6322 __ movq(RCX, FieldAddress(RAX, Function::instructions_offset())); |
| 6325 | 6323 |
| 6326 // RAX: Function. | 6324 // RAX: Function. |
| 6327 // R10: Arguments descriptor array. | 6325 // R10: Arguments descriptor array. |
| 6328 // RBX: Smi 0 (no IC data; the lazy-compile stub expects a GC-safe value). | 6326 // RBX: Smi 0 (no IC data; the lazy-compile stub expects a GC-safe value). |
| 6329 __ xorq(RBX, RBX); | 6327 __ xorq(RBX, RBX); |
| 6330 __ addq(RCX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 6328 __ addq(RCX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 6353 Location::RequiresRegister(), | 6351 Location::RequiresRegister(), |
| 6354 LocationSummary::kNoCall); | 6352 LocationSummary::kNoCall); |
| 6355 } | 6353 } |
| 6356 | 6354 |
| 6357 | 6355 |
| 6358 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6356 void BooleanNegateInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6359 Register value = locs()->in(0).reg(); | 6357 Register value = locs()->in(0).reg(); |
| 6360 Register result = locs()->out(0).reg(); | 6358 Register result = locs()->out(0).reg(); |
| 6361 | 6359 |
| 6362 Label done; | 6360 Label done; |
| 6363 __ LoadObject(result, Bool::True(), PP); | 6361 __ LoadObject(result, Bool::True()); |
| 6364 __ CompareRegisters(result, value); | 6362 __ CompareRegisters(result, value); |
| 6365 __ j(NOT_EQUAL, &done, Assembler::kNearJump); | 6363 __ j(NOT_EQUAL, &done, Assembler::kNearJump); |
| 6366 __ LoadObject(result, Bool::False(), PP); | 6364 __ LoadObject(result, Bool::False()); |
| 6367 __ Bind(&done); | 6365 __ Bind(&done); |
| 6368 } | 6366 } |
| 6369 | 6367 |
| 6370 | 6368 |
| 6371 LocationSummary* AllocateObjectInstr::MakeLocationSummary(Zone* zone, | 6369 LocationSummary* AllocateObjectInstr::MakeLocationSummary(Zone* zone, |
| 6372 bool opt) const { | 6370 bool opt) const { |
| 6373 return MakeCallSummary(zone); | 6371 return MakeCallSummary(zone); |
| 6374 } | 6372 } |
| 6375 | 6373 |
| 6376 | 6374 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 6405 zone, kNumInputs, kNumTemps, LocationSummary::kCall); | 6403 zone, kNumInputs, kNumTemps, LocationSummary::kCall); |
| 6406 locs->set_in(0, Location::RegisterLocation(RAX)); | 6404 locs->set_in(0, Location::RegisterLocation(RAX)); |
| 6407 locs->set_out(0, Location::RegisterLocation(RAX)); | 6405 locs->set_out(0, Location::RegisterLocation(RAX)); |
| 6408 return locs; | 6406 return locs; |
| 6409 } | 6407 } |
| 6410 | 6408 |
| 6411 | 6409 |
| 6412 void GrowRegExpStackInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 6410 void GrowRegExpStackInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 6413 const Register typed_data = locs()->in(0).reg(); | 6411 const Register typed_data = locs()->in(0).reg(); |
| 6414 const Register result = locs()->out(0).reg(); | 6412 const Register result = locs()->out(0).reg(); |
| 6415 __ PushObject(Object::null_object(), PP); | 6413 __ PushObject(Object::null_object()); |
| 6416 __ pushq(typed_data); | 6414 __ pushq(typed_data); |
| 6417 compiler->GenerateRuntimeCall(Scanner::kNoSourcePos, // No token position. | 6415 compiler->GenerateRuntimeCall(Scanner::kNoSourcePos, // No token position. |
| 6418 deopt_id(), | 6416 deopt_id(), |
| 6419 kGrowRegExpStackRuntimeEntry, | 6417 kGrowRegExpStackRuntimeEntry, |
| 6420 1, | 6418 1, |
| 6421 locs()); | 6419 locs()); |
| 6422 __ Drop(1); | 6420 __ Drop(1); |
| 6423 __ popq(result); | 6421 __ popq(result); |
| 6424 } | 6422 } |
| 6425 | 6423 |
| 6426 | 6424 |
| 6427 } // namespace dart | 6425 } // namespace dart |
| 6428 | 6426 |
| 6429 #undef __ | 6427 #undef __ |
| 6430 | 6428 |
| 6431 #endif // defined TARGET_ARCH_X64 | 6429 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |