| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "v8.h" | 5 #include "v8.h" |
| 6 | 6 |
| 7 #if V8_TARGET_ARCH_IA32 | 7 #if V8_TARGET_ARCH_IA32 |
| 8 | 8 |
| 9 #include "ia32/lithium-codegen-ia32.h" | 9 #include "ia32/lithium-codegen-ia32.h" |
| 10 #include "ic.h" | 10 #include "ic.h" |
| 11 #include "code-stubs.h" | 11 #include "code-stubs.h" |
| 12 #include "deoptimizer.h" | 12 #include "deoptimizer.h" |
| 13 #include "stub-cache.h" | 13 #include "stub-cache.h" |
| 14 #include "codegen.h" | 14 #include "codegen.h" |
| 15 #include "hydrogen-osr.h" | 15 #include "hydrogen-osr.h" |
| 16 | 16 |
| 17 namespace v8 { | 17 namespace v8 { |
| 18 namespace internal { | 18 namespace internal { |
| 19 | 19 |
| 20 | |
| 21 static SaveFPRegsMode GetSaveFPRegsMode(Isolate* isolate) { | |
| 22 // We don't need to save floating point regs when generating the snapshot | |
| 23 return CpuFeatures::IsSafeForSnapshot(isolate, SSE2) ? kSaveFPRegs | |
| 24 : kDontSaveFPRegs; | |
| 25 } | |
| 26 | |
| 27 | |
| 28 // When invoking builtins, we need to record the safepoint in the middle of | 20 // When invoking builtins, we need to record the safepoint in the middle of |
| 29 // the invoke instruction sequence generated by the macro assembler. | 21 // the invoke instruction sequence generated by the macro assembler. |
| 30 class SafepointGenerator V8_FINAL : public CallWrapper { | 22 class SafepointGenerator V8_FINAL : public CallWrapper { |
| 31 public: | 23 public: |
| 32 SafepointGenerator(LCodeGen* codegen, | 24 SafepointGenerator(LCodeGen* codegen, |
| 33 LPointerMap* pointers, | 25 LPointerMap* pointers, |
| 34 Safepoint::DeoptMode mode) | 26 Safepoint::DeoptMode mode) |
| 35 : codegen_(codegen), | 27 : codegen_(codegen), |
| 36 pointers_(pointers), | 28 pointers_(pointers), |
| 37 deopt_mode_(mode) {} | 29 deopt_mode_(mode) {} |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 96 __ mov(Operand(esp, offset), eax); | 88 __ mov(Operand(esp, offset), eax); |
| 97 } | 89 } |
| 98 } | 90 } |
| 99 #endif | 91 #endif |
| 100 | 92 |
| 101 | 93 |
| 102 void LCodeGen::SaveCallerDoubles() { | 94 void LCodeGen::SaveCallerDoubles() { |
| 103 ASSERT(info()->saves_caller_doubles()); | 95 ASSERT(info()->saves_caller_doubles()); |
| 104 ASSERT(NeedsEagerFrame()); | 96 ASSERT(NeedsEagerFrame()); |
| 105 Comment(";;; Save clobbered callee double registers"); | 97 Comment(";;; Save clobbered callee double registers"); |
| 106 CpuFeatureScope scope(masm(), SSE2); | |
| 107 int count = 0; | 98 int count = 0; |
| 108 BitVector* doubles = chunk()->allocated_double_registers(); | 99 BitVector* doubles = chunk()->allocated_double_registers(); |
| 109 BitVector::Iterator save_iterator(doubles); | 100 BitVector::Iterator save_iterator(doubles); |
| 110 while (!save_iterator.Done()) { | 101 while (!save_iterator.Done()) { |
| 111 __ movsd(MemOperand(esp, count * kDoubleSize), | 102 __ movsd(MemOperand(esp, count * kDoubleSize), |
| 112 XMMRegister::FromAllocationIndex(save_iterator.Current())); | 103 XMMRegister::FromAllocationIndex(save_iterator.Current())); |
| 113 save_iterator.Advance(); | 104 save_iterator.Advance(); |
| 114 count++; | 105 count++; |
| 115 } | 106 } |
| 116 } | 107 } |
| 117 | 108 |
| 118 | 109 |
| 119 void LCodeGen::RestoreCallerDoubles() { | 110 void LCodeGen::RestoreCallerDoubles() { |
| 120 ASSERT(info()->saves_caller_doubles()); | 111 ASSERT(info()->saves_caller_doubles()); |
| 121 ASSERT(NeedsEagerFrame()); | 112 ASSERT(NeedsEagerFrame()); |
| 122 Comment(";;; Restore clobbered callee double registers"); | 113 Comment(";;; Restore clobbered callee double registers"); |
| 123 CpuFeatureScope scope(masm(), SSE2); | |
| 124 BitVector* doubles = chunk()->allocated_double_registers(); | 114 BitVector* doubles = chunk()->allocated_double_registers(); |
| 125 BitVector::Iterator save_iterator(doubles); | 115 BitVector::Iterator save_iterator(doubles); |
| 126 int count = 0; | 116 int count = 0; |
| 127 while (!save_iterator.Done()) { | 117 while (!save_iterator.Done()) { |
| 128 __ movsd(XMMRegister::FromAllocationIndex(save_iterator.Current()), | 118 __ movsd(XMMRegister::FromAllocationIndex(save_iterator.Current()), |
| 129 MemOperand(esp, count * kDoubleSize)); | 119 MemOperand(esp, count * kDoubleSize)); |
| 130 save_iterator.Advance(); | 120 save_iterator.Advance(); |
| 131 count++; | 121 count++; |
| 132 } | 122 } |
| 133 } | 123 } |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 246 // Store dynamic frame alignment state in the first local. | 236 // Store dynamic frame alignment state in the first local. |
| 247 int offset = JavaScriptFrameConstants::kDynamicAlignmentStateOffset; | 237 int offset = JavaScriptFrameConstants::kDynamicAlignmentStateOffset; |
| 248 if (dynamic_frame_alignment_) { | 238 if (dynamic_frame_alignment_) { |
| 249 __ mov(Operand(ebp, offset), edx); | 239 __ mov(Operand(ebp, offset), edx); |
| 250 } else { | 240 } else { |
| 251 __ mov(Operand(ebp, offset), Immediate(kNoAlignmentPadding)); | 241 __ mov(Operand(ebp, offset), Immediate(kNoAlignmentPadding)); |
| 252 } | 242 } |
| 253 } | 243 } |
| 254 } | 244 } |
| 255 | 245 |
| 256 if (info()->saves_caller_doubles() && CpuFeatures::IsSupported(SSE2)) { | 246 if (info()->saves_caller_doubles()) SaveCallerDoubles(); |
| 257 SaveCallerDoubles(); | |
| 258 } | |
| 259 } | 247 } |
| 260 | 248 |
| 261 // Possibly allocate a local context. | 249 // Possibly allocate a local context. |
| 262 int heap_slots = info_->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; | 250 int heap_slots = info_->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; |
| 263 if (heap_slots > 0) { | 251 if (heap_slots > 0) { |
| 264 Comment(";;; Allocate local context"); | 252 Comment(";;; Allocate local context"); |
| 265 // Argument to NewContext is the function, which is still in edi. | 253 // Argument to NewContext is the function, which is still in edi. |
| 266 if (heap_slots <= FastNewContextStub::kMaximumSlots) { | 254 if (heap_slots <= FastNewContextStub::kMaximumSlots) { |
| 267 FastNewContextStub stub(isolate(), heap_slots); | 255 FastNewContextStub stub(isolate(), heap_slots); |
| 268 __ CallStub(&stub); | 256 __ CallStub(&stub); |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 360 } | 348 } |
| 361 | 349 |
| 362 | 350 |
| 363 void LCodeGen::GenerateBodyInstructionPre(LInstruction* instr) { | 351 void LCodeGen::GenerateBodyInstructionPre(LInstruction* instr) { |
| 364 if (instr->IsCall()) { | 352 if (instr->IsCall()) { |
| 365 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); | 353 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); |
| 366 } | 354 } |
| 367 if (!instr->IsLazyBailout() && !instr->IsGap()) { | 355 if (!instr->IsLazyBailout() && !instr->IsGap()) { |
| 368 safepoints_.BumpLastLazySafepointIndex(); | 356 safepoints_.BumpLastLazySafepointIndex(); |
| 369 } | 357 } |
| 370 if (!CpuFeatures::IsSupported(SSE2)) FlushX87StackIfNecessary(instr); | |
| 371 } | |
| 372 | |
| 373 | |
| 374 void LCodeGen::GenerateBodyInstructionPost(LInstruction* instr) { | |
| 375 if (!CpuFeatures::IsSupported(SSE2)) { | |
| 376 if (instr->IsGoto()) { | |
| 377 x87_stack_.LeavingBlock(current_block_, LGoto::cast(instr)); | |
| 378 } else if (FLAG_debug_code && FLAG_enable_slow_asserts && | |
| 379 !instr->IsGap() && !instr->IsReturn()) { | |
| 380 if (instr->ClobbersDoubleRegisters(isolate())) { | |
| 381 if (instr->HasDoubleRegisterResult()) { | |
| 382 ASSERT_EQ(1, x87_stack_.depth()); | |
| 383 } else { | |
| 384 ASSERT_EQ(0, x87_stack_.depth()); | |
| 385 } | |
| 386 } | |
| 387 __ VerifyX87StackDepth(x87_stack_.depth()); | |
| 388 } | |
| 389 } | |
| 390 } | 358 } |
| 391 | 359 |
| 392 | 360 |
| 361 void LCodeGen::GenerateBodyInstructionPost(LInstruction* instr) { } |
| 362 |
| 363 |
| 393 bool LCodeGen::GenerateJumpTable() { | 364 bool LCodeGen::GenerateJumpTable() { |
| 394 Label needs_frame; | 365 Label needs_frame; |
| 395 if (jump_table_.length() > 0) { | 366 if (jump_table_.length() > 0) { |
| 396 Comment(";;; -------------------- Jump table --------------------"); | 367 Comment(";;; -------------------- Jump table --------------------"); |
| 397 } | 368 } |
| 398 for (int i = 0; i < jump_table_.length(); i++) { | 369 for (int i = 0; i < jump_table_.length(); i++) { |
| 399 __ bind(&jump_table_[i].label); | 370 __ bind(&jump_table_[i].label); |
| 400 Address entry = jump_table_[i].address; | 371 Address entry = jump_table_[i].address; |
| 401 Deoptimizer::BailoutType type = jump_table_[i].bailout_type; | 372 Deoptimizer::BailoutType type = jump_table_[i].bailout_type; |
| 402 int id = Deoptimizer::GetDeoptimizationId(isolate(), entry, type); | 373 int id = Deoptimizer::GetDeoptimizationId(isolate(), entry, type); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 426 __ call(&push_approx_pc); | 397 __ call(&push_approx_pc); |
| 427 __ bind(&push_approx_pc); | 398 __ bind(&push_approx_pc); |
| 428 // Push the continuation which was stashed were the ebp should | 399 // Push the continuation which was stashed were the ebp should |
| 429 // be. Replace it with the saved ebp. | 400 // be. Replace it with the saved ebp. |
| 430 __ push(MemOperand(esp, 3 * kPointerSize)); | 401 __ push(MemOperand(esp, 3 * kPointerSize)); |
| 431 __ mov(MemOperand(esp, 4 * kPointerSize), ebp); | 402 __ mov(MemOperand(esp, 4 * kPointerSize), ebp); |
| 432 __ lea(ebp, MemOperand(esp, 4 * kPointerSize)); | 403 __ lea(ebp, MemOperand(esp, 4 * kPointerSize)); |
| 433 __ ret(0); // Call the continuation without clobbering registers. | 404 __ ret(0); // Call the continuation without clobbering registers. |
| 434 } | 405 } |
| 435 } else { | 406 } else { |
| 436 if (info()->saves_caller_doubles() && CpuFeatures::IsSupported(SSE2)) { | 407 if (info()->saves_caller_doubles()) RestoreCallerDoubles(); |
| 437 RestoreCallerDoubles(); | |
| 438 } | |
| 439 __ call(entry, RelocInfo::RUNTIME_ENTRY); | 408 __ call(entry, RelocInfo::RUNTIME_ENTRY); |
| 440 } | 409 } |
| 441 } | 410 } |
| 442 return !is_aborted(); | 411 return !is_aborted(); |
| 443 } | 412 } |
| 444 | 413 |
| 445 | 414 |
| 446 bool LCodeGen::GenerateDeferredCode() { | 415 bool LCodeGen::GenerateDeferredCode() { |
| 447 ASSERT(is_generating()); | 416 ASSERT(is_generating()); |
| 448 if (deferred_.length() > 0) { | 417 if (deferred_.length() > 0) { |
| 449 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) { | 418 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) { |
| 450 LDeferredCode* code = deferred_[i]; | 419 LDeferredCode* code = deferred_[i]; |
| 451 X87Stack copy(code->x87_stack()); | |
| 452 x87_stack_ = copy; | |
| 453 | 420 |
| 454 HValue* value = | 421 HValue* value = |
| 455 instructions_->at(code->instruction_index())->hydrogen_value(); | 422 instructions_->at(code->instruction_index())->hydrogen_value(); |
| 456 RecordAndWritePosition( | 423 RecordAndWritePosition( |
| 457 chunk()->graph()->SourcePositionToScriptPosition(value->position())); | 424 chunk()->graph()->SourcePositionToScriptPosition(value->position())); |
| 458 | 425 |
| 459 Comment(";;; <@%d,#%d> " | 426 Comment(";;; <@%d,#%d> " |
| 460 "-------------------- Deferred %s --------------------", | 427 "-------------------- Deferred %s --------------------", |
| 461 code->instruction_index(), | 428 code->instruction_index(), |
| 462 code->instr()->hydrogen_value()->id(), | 429 code->instr()->hydrogen_value()->id(), |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 508 safepoints_.Emit(masm(), GetStackSlotCount()); | 475 safepoints_.Emit(masm(), GetStackSlotCount()); |
| 509 return !is_aborted(); | 476 return !is_aborted(); |
| 510 } | 477 } |
| 511 | 478 |
| 512 | 479 |
| 513 Register LCodeGen::ToRegister(int index) const { | 480 Register LCodeGen::ToRegister(int index) const { |
| 514 return Register::FromAllocationIndex(index); | 481 return Register::FromAllocationIndex(index); |
| 515 } | 482 } |
| 516 | 483 |
| 517 | 484 |
| 518 X87Register LCodeGen::ToX87Register(int index) const { | |
| 519 return X87Register::FromAllocationIndex(index); | |
| 520 } | |
| 521 | |
| 522 | |
| 523 XMMRegister LCodeGen::ToDoubleRegister(int index) const { | 485 XMMRegister LCodeGen::ToDoubleRegister(int index) const { |
| 524 return XMMRegister::FromAllocationIndex(index); | 486 return XMMRegister::FromAllocationIndex(index); |
| 525 } | 487 } |
| 526 | 488 |
| 527 | 489 |
| 528 void LCodeGen::X87LoadForUsage(X87Register reg) { | |
| 529 ASSERT(x87_stack_.Contains(reg)); | |
| 530 x87_stack_.Fxch(reg); | |
| 531 x87_stack_.pop(); | |
| 532 } | |
| 533 | |
| 534 | |
| 535 void LCodeGen::X87LoadForUsage(X87Register reg1, X87Register reg2) { | |
| 536 ASSERT(x87_stack_.Contains(reg1)); | |
| 537 ASSERT(x87_stack_.Contains(reg2)); | |
| 538 x87_stack_.Fxch(reg1, 1); | |
| 539 x87_stack_.Fxch(reg2); | |
| 540 x87_stack_.pop(); | |
| 541 x87_stack_.pop(); | |
| 542 } | |
| 543 | |
| 544 | |
| 545 void LCodeGen::X87Stack::Fxch(X87Register reg, int other_slot) { | |
| 546 ASSERT(is_mutable_); | |
| 547 ASSERT(Contains(reg) && stack_depth_ > other_slot); | |
| 548 int i = ArrayIndex(reg); | |
| 549 int st = st2idx(i); | |
| 550 if (st != other_slot) { | |
| 551 int other_i = st2idx(other_slot); | |
| 552 X87Register other = stack_[other_i]; | |
| 553 stack_[other_i] = reg; | |
| 554 stack_[i] = other; | |
| 555 if (st == 0) { | |
| 556 __ fxch(other_slot); | |
| 557 } else if (other_slot == 0) { | |
| 558 __ fxch(st); | |
| 559 } else { | |
| 560 __ fxch(st); | |
| 561 __ fxch(other_slot); | |
| 562 __ fxch(st); | |
| 563 } | |
| 564 } | |
| 565 } | |
| 566 | |
| 567 | |
| 568 int LCodeGen::X87Stack::st2idx(int pos) { | |
| 569 return stack_depth_ - pos - 1; | |
| 570 } | |
| 571 | |
| 572 | |
| 573 int LCodeGen::X87Stack::ArrayIndex(X87Register reg) { | |
| 574 for (int i = 0; i < stack_depth_; i++) { | |
| 575 if (stack_[i].is(reg)) return i; | |
| 576 } | |
| 577 UNREACHABLE(); | |
| 578 return -1; | |
| 579 } | |
| 580 | |
| 581 | |
| 582 bool LCodeGen::X87Stack::Contains(X87Register reg) { | |
| 583 for (int i = 0; i < stack_depth_; i++) { | |
| 584 if (stack_[i].is(reg)) return true; | |
| 585 } | |
| 586 return false; | |
| 587 } | |
| 588 | |
| 589 | |
| 590 void LCodeGen::X87Stack::Free(X87Register reg) { | |
| 591 ASSERT(is_mutable_); | |
| 592 ASSERT(Contains(reg)); | |
| 593 int i = ArrayIndex(reg); | |
| 594 int st = st2idx(i); | |
| 595 if (st > 0) { | |
| 596 // keep track of how fstp(i) changes the order of elements | |
| 597 int tos_i = st2idx(0); | |
| 598 stack_[i] = stack_[tos_i]; | |
| 599 } | |
| 600 pop(); | |
| 601 __ fstp(st); | |
| 602 } | |
| 603 | |
| 604 | |
| 605 void LCodeGen::X87Mov(X87Register dst, Operand src, X87OperandType opts) { | |
| 606 if (x87_stack_.Contains(dst)) { | |
| 607 x87_stack_.Fxch(dst); | |
| 608 __ fstp(0); | |
| 609 } else { | |
| 610 x87_stack_.push(dst); | |
| 611 } | |
| 612 X87Fld(src, opts); | |
| 613 } | |
| 614 | |
| 615 | |
| 616 void LCodeGen::X87Fld(Operand src, X87OperandType opts) { | |
| 617 ASSERT(!src.is_reg_only()); | |
| 618 switch (opts) { | |
| 619 case kX87DoubleOperand: | |
| 620 __ fld_d(src); | |
| 621 break; | |
| 622 case kX87FloatOperand: | |
| 623 __ fld_s(src); | |
| 624 break; | |
| 625 case kX87IntOperand: | |
| 626 __ fild_s(src); | |
| 627 break; | |
| 628 default: | |
| 629 UNREACHABLE(); | |
| 630 } | |
| 631 } | |
| 632 | |
| 633 | |
| 634 void LCodeGen::X87Mov(Operand dst, X87Register src, X87OperandType opts) { | |
| 635 ASSERT(!dst.is_reg_only()); | |
| 636 x87_stack_.Fxch(src); | |
| 637 switch (opts) { | |
| 638 case kX87DoubleOperand: | |
| 639 __ fst_d(dst); | |
| 640 break; | |
| 641 case kX87IntOperand: | |
| 642 __ fist_s(dst); | |
| 643 break; | |
| 644 default: | |
| 645 UNREACHABLE(); | |
| 646 } | |
| 647 } | |
| 648 | |
| 649 | |
| 650 void LCodeGen::X87Stack::PrepareToWrite(X87Register reg) { | |
| 651 ASSERT(is_mutable_); | |
| 652 if (Contains(reg)) { | |
| 653 Free(reg); | |
| 654 } | |
| 655 // Mark this register as the next register to write to | |
| 656 stack_[stack_depth_] = reg; | |
| 657 } | |
| 658 | |
| 659 | |
| 660 void LCodeGen::X87Stack::CommitWrite(X87Register reg) { | |
| 661 ASSERT(is_mutable_); | |
| 662 // Assert the reg is prepared to write, but not on the virtual stack yet | |
| 663 ASSERT(!Contains(reg) && stack_[stack_depth_].is(reg) && | |
| 664 stack_depth_ < X87Register::kNumAllocatableRegisters); | |
| 665 stack_depth_++; | |
| 666 } | |
| 667 | |
| 668 | |
| 669 void LCodeGen::X87PrepareBinaryOp( | |
| 670 X87Register left, X87Register right, X87Register result) { | |
| 671 // You need to use DefineSameAsFirst for x87 instructions | |
| 672 ASSERT(result.is(left)); | |
| 673 x87_stack_.Fxch(right, 1); | |
| 674 x87_stack_.Fxch(left); | |
| 675 } | |
| 676 | |
| 677 | |
| 678 void LCodeGen::X87Stack::FlushIfNecessary(LInstruction* instr, LCodeGen* cgen) { | |
| 679 if (stack_depth_ > 0 && instr->ClobbersDoubleRegisters(isolate())) { | |
| 680 bool double_inputs = instr->HasDoubleRegisterInput(); | |
| 681 | |
| 682 // Flush stack from tos down, since FreeX87() will mess with tos | |
| 683 for (int i = stack_depth_-1; i >= 0; i--) { | |
| 684 X87Register reg = stack_[i]; | |
| 685 // Skip registers which contain the inputs for the next instruction | |
| 686 // when flushing the stack | |
| 687 if (double_inputs && instr->IsDoubleInput(reg, cgen)) { | |
| 688 continue; | |
| 689 } | |
| 690 Free(reg); | |
| 691 if (i < stack_depth_-1) i++; | |
| 692 } | |
| 693 } | |
| 694 if (instr->IsReturn()) { | |
| 695 while (stack_depth_ > 0) { | |
| 696 __ fstp(0); | |
| 697 stack_depth_--; | |
| 698 } | |
| 699 if (FLAG_debug_code && FLAG_enable_slow_asserts) __ VerifyX87StackDepth(0); | |
| 700 } | |
| 701 } | |
| 702 | |
| 703 | |
| 704 void LCodeGen::X87Stack::LeavingBlock(int current_block_id, LGoto* goto_instr) { | |
| 705 ASSERT(stack_depth_ <= 1); | |
| 706 // If ever used for new stubs producing two pairs of doubles joined into two | |
| 707 // phis this assert hits. That situation is not handled, since the two stacks | |
| 708 // might have st0 and st1 swapped. | |
| 709 if (current_block_id + 1 != goto_instr->block_id()) { | |
| 710 // If we have a value on the x87 stack on leaving a block, it must be a | |
| 711 // phi input. If the next block we compile is not the join block, we have | |
| 712 // to discard the stack state. | |
| 713 stack_depth_ = 0; | |
| 714 } | |
| 715 } | |
| 716 | |
| 717 | |
| 718 void LCodeGen::EmitFlushX87ForDeopt() { | |
| 719 // The deoptimizer does not support X87 Registers. But as long as we | |
| 720 // deopt from a stub its not a problem, since we will re-materialize the | |
| 721 // original stub inputs, which can't be double registers. | |
| 722 ASSERT(info()->IsStub()); | |
| 723 if (FLAG_debug_code && FLAG_enable_slow_asserts) { | |
| 724 __ pushfd(); | |
| 725 __ VerifyX87StackDepth(x87_stack_.depth()); | |
| 726 __ popfd(); | |
| 727 } | |
| 728 for (int i = 0; i < x87_stack_.depth(); i++) __ fstp(0); | |
| 729 } | |
| 730 | |
| 731 | |
| 732 Register LCodeGen::ToRegister(LOperand* op) const { | 490 Register LCodeGen::ToRegister(LOperand* op) const { |
| 733 ASSERT(op->IsRegister()); | 491 ASSERT(op->IsRegister()); |
| 734 return ToRegister(op->index()); | 492 return ToRegister(op->index()); |
| 735 } | 493 } |
| 736 | 494 |
| 737 | 495 |
| 738 X87Register LCodeGen::ToX87Register(LOperand* op) const { | |
| 739 ASSERT(op->IsDoubleRegister()); | |
| 740 return ToX87Register(op->index()); | |
| 741 } | |
| 742 | |
| 743 | |
| 744 XMMRegister LCodeGen::ToDoubleRegister(LOperand* op) const { | 496 XMMRegister LCodeGen::ToDoubleRegister(LOperand* op) const { |
| 745 ASSERT(op->IsDoubleRegister()); | 497 ASSERT(op->IsDoubleRegister()); |
| 746 return ToDoubleRegister(op->index()); | 498 return ToDoubleRegister(op->index()); |
| 747 } | 499 } |
| 748 | 500 |
| 749 | 501 |
| 750 int32_t LCodeGen::ToInteger32(LConstantOperand* op) const { | 502 int32_t LCodeGen::ToInteger32(LConstantOperand* op) const { |
| 751 return ToRepresentation(op, Representation::Integer32()); | 503 return ToRepresentation(op, Representation::Integer32()); |
| 752 } | 504 } |
| 753 | 505 |
| (...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1085 __ pop(eax); | 837 __ pop(eax); |
| 1086 __ popfd(); | 838 __ popfd(); |
| 1087 ASSERT(frame_is_built_); | 839 ASSERT(frame_is_built_); |
| 1088 __ call(entry, RelocInfo::RUNTIME_ENTRY); | 840 __ call(entry, RelocInfo::RUNTIME_ENTRY); |
| 1089 __ bind(&no_deopt); | 841 __ bind(&no_deopt); |
| 1090 __ mov(Operand::StaticVariable(count), eax); | 842 __ mov(Operand::StaticVariable(count), eax); |
| 1091 __ pop(eax); | 843 __ pop(eax); |
| 1092 __ popfd(); | 844 __ popfd(); |
| 1093 } | 845 } |
| 1094 | 846 |
| 1095 // Before Instructions which can deopt, we normally flush the x87 stack. But | |
| 1096 // we can have inputs or outputs of the current instruction on the stack, | |
| 1097 // thus we need to flush them here from the physical stack to leave it in a | |
| 1098 // consistent state. | |
| 1099 if (x87_stack_.depth() > 0) { | |
| 1100 Label done; | |
| 1101 if (cc != no_condition) __ j(NegateCondition(cc), &done, Label::kNear); | |
| 1102 EmitFlushX87ForDeopt(); | |
| 1103 __ bind(&done); | |
| 1104 } | |
| 1105 | |
| 1106 if (info()->ShouldTrapOnDeopt()) { | 847 if (info()->ShouldTrapOnDeopt()) { |
| 1107 Label done; | 848 Label done; |
| 1108 if (cc != no_condition) __ j(NegateCondition(cc), &done, Label::kNear); | 849 if (cc != no_condition) __ j(NegateCondition(cc), &done, Label::kNear); |
| 1109 __ int3(); | 850 __ int3(); |
| 1110 __ bind(&done); | 851 __ bind(&done); |
| 1111 } | 852 } |
| 1112 | 853 |
| 1113 ASSERT(info()->IsStub() || frame_is_built_); | 854 ASSERT(info()->IsStub() || frame_is_built_); |
| 1114 if (cc == no_condition && frame_is_built_) { | 855 if (cc == no_condition && frame_is_built_) { |
| 1115 __ call(entry, RelocInfo::RUNTIME_ENTRY); | 856 __ call(entry, RelocInfo::RUNTIME_ENTRY); |
| (...skipping 840 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1956 } | 1697 } |
| 1957 | 1698 |
| 1958 | 1699 |
| 1959 void LCodeGen::DoConstantD(LConstantD* instr) { | 1700 void LCodeGen::DoConstantD(LConstantD* instr) { |
| 1960 double v = instr->value(); | 1701 double v = instr->value(); |
| 1961 uint64_t int_val = BitCast<uint64_t, double>(v); | 1702 uint64_t int_val = BitCast<uint64_t, double>(v); |
| 1962 int32_t lower = static_cast<int32_t>(int_val); | 1703 int32_t lower = static_cast<int32_t>(int_val); |
| 1963 int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt)); | 1704 int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt)); |
| 1964 ASSERT(instr->result()->IsDoubleRegister()); | 1705 ASSERT(instr->result()->IsDoubleRegister()); |
| 1965 | 1706 |
| 1966 if (!CpuFeatures::IsSafeForSnapshot(isolate(), SSE2)) { | 1707 XMMRegister res = ToDoubleRegister(instr->result()); |
| 1967 __ push(Immediate(upper)); | 1708 if (int_val == 0) { |
| 1968 __ push(Immediate(lower)); | 1709 __ xorps(res, res); |
| 1969 X87Register reg = ToX87Register(instr->result()); | |
| 1970 X87Mov(reg, Operand(esp, 0)); | |
| 1971 __ add(Operand(esp), Immediate(kDoubleSize)); | |
| 1972 } else { | 1710 } else { |
| 1973 CpuFeatureScope scope1(masm(), SSE2); | 1711 Register temp = ToRegister(instr->temp()); |
| 1974 XMMRegister res = ToDoubleRegister(instr->result()); | 1712 if (CpuFeatures::IsSupported(SSE4_1)) { |
| 1975 if (int_val == 0) { | 1713 CpuFeatureScope scope2(masm(), SSE4_1); |
| 1976 __ xorps(res, res); | 1714 if (lower != 0) { |
| 1715 __ Move(temp, Immediate(lower)); |
| 1716 __ movd(res, Operand(temp)); |
| 1717 __ Move(temp, Immediate(upper)); |
| 1718 __ pinsrd(res, Operand(temp), 1); |
| 1719 } else { |
| 1720 __ xorps(res, res); |
| 1721 __ Move(temp, Immediate(upper)); |
| 1722 __ pinsrd(res, Operand(temp), 1); |
| 1723 } |
| 1977 } else { | 1724 } else { |
| 1978 Register temp = ToRegister(instr->temp()); | 1725 __ Move(temp, Immediate(upper)); |
| 1979 if (CpuFeatures::IsSupported(SSE4_1)) { | 1726 __ movd(res, Operand(temp)); |
| 1980 CpuFeatureScope scope2(masm(), SSE4_1); | 1727 __ psllq(res, 32); |
| 1981 if (lower != 0) { | 1728 if (lower != 0) { |
| 1982 __ Move(temp, Immediate(lower)); | 1729 XMMRegister xmm_scratch = double_scratch0(); |
| 1983 __ movd(res, Operand(temp)); | 1730 __ Move(temp, Immediate(lower)); |
| 1984 __ Move(temp, Immediate(upper)); | 1731 __ movd(xmm_scratch, Operand(temp)); |
| 1985 __ pinsrd(res, Operand(temp), 1); | 1732 __ orps(res, xmm_scratch); |
| 1986 } else { | |
| 1987 __ xorps(res, res); | |
| 1988 __ Move(temp, Immediate(upper)); | |
| 1989 __ pinsrd(res, Operand(temp), 1); | |
| 1990 } | |
| 1991 } else { | |
| 1992 __ Move(temp, Immediate(upper)); | |
| 1993 __ movd(res, Operand(temp)); | |
| 1994 __ psllq(res, 32); | |
| 1995 if (lower != 0) { | |
| 1996 XMMRegister xmm_scratch = double_scratch0(); | |
| 1997 __ Move(temp, Immediate(lower)); | |
| 1998 __ movd(xmm_scratch, Operand(temp)); | |
| 1999 __ orps(res, xmm_scratch); | |
| 2000 } | |
| 2001 } | 1733 } |
| 2002 } | 1734 } |
| 2003 } | 1735 } |
| 2004 } | 1736 } |
| 2005 | 1737 |
| 2006 | 1738 |
| 2007 void LCodeGen::DoConstantE(LConstantE* instr) { | 1739 void LCodeGen::DoConstantE(LConstantE* instr) { |
| 2008 __ lea(ToRegister(instr->result()), Operand::StaticVariable(instr->value())); | 1740 __ lea(ToRegister(instr->result()), Operand::StaticVariable(instr->value())); |
| 2009 } | 1741 } |
| 2010 | 1742 |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2173 __ add(ToRegister(left), ToOperand(right)); | 1905 __ add(ToRegister(left), ToOperand(right)); |
| 2174 } | 1906 } |
| 2175 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | 1907 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
| 2176 DeoptimizeIf(overflow, instr->environment()); | 1908 DeoptimizeIf(overflow, instr->environment()); |
| 2177 } | 1909 } |
| 2178 } | 1910 } |
| 2179 } | 1911 } |
| 2180 | 1912 |
| 2181 | 1913 |
| 2182 void LCodeGen::DoMathMinMax(LMathMinMax* instr) { | 1914 void LCodeGen::DoMathMinMax(LMathMinMax* instr) { |
| 2183 CpuFeatureScope scope(masm(), SSE2); | |
| 2184 LOperand* left = instr->left(); | 1915 LOperand* left = instr->left(); |
| 2185 LOperand* right = instr->right(); | 1916 LOperand* right = instr->right(); |
| 2186 ASSERT(left->Equals(instr->result())); | 1917 ASSERT(left->Equals(instr->result())); |
| 2187 HMathMinMax::Operation operation = instr->hydrogen()->operation(); | 1918 HMathMinMax::Operation operation = instr->hydrogen()->operation(); |
| 2188 if (instr->hydrogen()->representation().IsSmiOrInteger32()) { | 1919 if (instr->hydrogen()->representation().IsSmiOrInteger32()) { |
| 2189 Label return_left; | 1920 Label return_left; |
| 2190 Condition condition = (operation == HMathMinMax::kMathMin) | 1921 Condition condition = (operation == HMathMinMax::kMathMin) |
| 2191 ? less_equal | 1922 ? less_equal |
| 2192 : greater_equal; | 1923 : greater_equal; |
| 2193 if (right->IsConstantOperand()) { | 1924 if (right->IsConstantOperand()) { |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2236 __ j(parity_even, &return_left, Label::kNear); // left == NaN. | 1967 __ j(parity_even, &return_left, Label::kNear); // left == NaN. |
| 2237 __ bind(&return_right); | 1968 __ bind(&return_right); |
| 2238 __ movaps(left_reg, right_reg); | 1969 __ movaps(left_reg, right_reg); |
| 2239 | 1970 |
| 2240 __ bind(&return_left); | 1971 __ bind(&return_left); |
| 2241 } | 1972 } |
| 2242 } | 1973 } |
| 2243 | 1974 |
| 2244 | 1975 |
| 2245 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { | 1976 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { |
| 2246 if (CpuFeatures::IsSafeForSnapshot(isolate(), SSE2)) { | 1977 XMMRegister left = ToDoubleRegister(instr->left()); |
| 2247 CpuFeatureScope scope(masm(), SSE2); | 1978 XMMRegister right = ToDoubleRegister(instr->right()); |
| 2248 XMMRegister left = ToDoubleRegister(instr->left()); | 1979 XMMRegister result = ToDoubleRegister(instr->result()); |
| 2249 XMMRegister right = ToDoubleRegister(instr->right()); | 1980 switch (instr->op()) { |
| 2250 XMMRegister result = ToDoubleRegister(instr->result()); | 1981 case Token::ADD: |
| 2251 switch (instr->op()) { | 1982 __ addsd(left, right); |
| 2252 case Token::ADD: | 1983 break; |
| 2253 __ addsd(left, right); | 1984 case Token::SUB: |
| 2254 break; | 1985 __ subsd(left, right); |
| 2255 case Token::SUB: | 1986 break; |
| 2256 __ subsd(left, right); | 1987 case Token::MUL: |
| 2257 break; | 1988 __ mulsd(left, right); |
| 2258 case Token::MUL: | 1989 break; |
| 2259 __ mulsd(left, right); | 1990 case Token::DIV: |
| 2260 break; | 1991 __ divsd(left, right); |
| 2261 case Token::DIV: | 1992 // Don't delete this mov. It may improve performance on some CPUs, |
| 2262 __ divsd(left, right); | 1993 // when there is a mulsd depending on the result |
| 2263 // Don't delete this mov. It may improve performance on some CPUs, | 1994 __ movaps(left, left); |
| 2264 // when there is a mulsd depending on the result | 1995 break; |
| 2265 __ movaps(left, left); | 1996 case Token::MOD: { |
| 2266 break; | 1997 // Pass two doubles as arguments on the stack. |
| 2267 case Token::MOD: { | 1998 __ PrepareCallCFunction(4, eax); |
| 2268 // Pass two doubles as arguments on the stack. | 1999 __ movsd(Operand(esp, 0 * kDoubleSize), left); |
| 2269 __ PrepareCallCFunction(4, eax); | 2000 __ movsd(Operand(esp, 1 * kDoubleSize), right); |
| 2270 __ movsd(Operand(esp, 0 * kDoubleSize), left); | 2001 __ CallCFunction( |
| 2271 __ movsd(Operand(esp, 1 * kDoubleSize), right); | 2002 ExternalReference::mod_two_doubles_operation(isolate()), |
| 2272 __ CallCFunction( | 2003 4); |
| 2273 ExternalReference::mod_two_doubles_operation(isolate()), | |
| 2274 4); | |
| 2275 | 2004 |
| 2276 // Return value is in st(0) on ia32. | 2005 // Return value is in st(0) on ia32. |
| 2277 // Store it into the result register. | 2006 // Store it into the result register. |
| 2278 __ sub(Operand(esp), Immediate(kDoubleSize)); | 2007 __ sub(Operand(esp), Immediate(kDoubleSize)); |
| 2279 __ fstp_d(Operand(esp, 0)); | 2008 __ fstp_d(Operand(esp, 0)); |
| 2280 __ movsd(result, Operand(esp, 0)); | 2009 __ movsd(result, Operand(esp, 0)); |
| 2281 __ add(Operand(esp), Immediate(kDoubleSize)); | 2010 __ add(Operand(esp), Immediate(kDoubleSize)); |
| 2282 break; | 2011 break; |
| 2283 } | |
| 2284 default: | |
| 2285 UNREACHABLE(); | |
| 2286 break; | |
| 2287 } | 2012 } |
| 2288 } else { | 2013 default: |
| 2289 X87Register left = ToX87Register(instr->left()); | 2014 UNREACHABLE(); |
| 2290 X87Register right = ToX87Register(instr->right()); | 2015 break; |
| 2291 X87Register result = ToX87Register(instr->result()); | |
| 2292 if (instr->op() != Token::MOD) { | |
| 2293 X87PrepareBinaryOp(left, right, result); | |
| 2294 } | |
| 2295 switch (instr->op()) { | |
| 2296 case Token::ADD: | |
| 2297 __ fadd_i(1); | |
| 2298 break; | |
| 2299 case Token::SUB: | |
| 2300 __ fsub_i(1); | |
| 2301 break; | |
| 2302 case Token::MUL: | |
| 2303 __ fmul_i(1); | |
| 2304 break; | |
| 2305 case Token::DIV: | |
| 2306 __ fdiv_i(1); | |
| 2307 break; | |
| 2308 case Token::MOD: { | |
| 2309 // Pass two doubles as arguments on the stack. | |
| 2310 __ PrepareCallCFunction(4, eax); | |
| 2311 X87Mov(Operand(esp, 1 * kDoubleSize), right); | |
| 2312 X87Mov(Operand(esp, 0), left); | |
| 2313 X87Free(right); | |
| 2314 ASSERT(left.is(result)); | |
| 2315 X87PrepareToWrite(result); | |
| 2316 __ CallCFunction( | |
| 2317 ExternalReference::mod_two_doubles_operation(isolate()), | |
| 2318 4); | |
| 2319 | |
| 2320 // Return value is in st(0) on ia32. | |
| 2321 X87CommitWrite(result); | |
| 2322 break; | |
| 2323 } | |
| 2324 default: | |
| 2325 UNREACHABLE(); | |
| 2326 break; | |
| 2327 } | |
| 2328 } | 2016 } |
| 2329 } | 2017 } |
| 2330 | 2018 |
| 2331 | 2019 |
| 2332 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { | 2020 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { |
| 2333 ASSERT(ToRegister(instr->context()).is(esi)); | 2021 ASSERT(ToRegister(instr->context()).is(esi)); |
| 2334 ASSERT(ToRegister(instr->left()).is(edx)); | 2022 ASSERT(ToRegister(instr->left()).is(edx)); |
| 2335 ASSERT(ToRegister(instr->right()).is(eax)); | 2023 ASSERT(ToRegister(instr->right()).is(eax)); |
| 2336 ASSERT(ToRegister(instr->result()).is(eax)); | 2024 ASSERT(ToRegister(instr->result()).is(eax)); |
| 2337 | 2025 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2372 | 2060 |
| 2373 | 2061 |
| 2374 void LCodeGen::DoBranch(LBranch* instr) { | 2062 void LCodeGen::DoBranch(LBranch* instr) { |
| 2375 Representation r = instr->hydrogen()->value()->representation(); | 2063 Representation r = instr->hydrogen()->value()->representation(); |
| 2376 if (r.IsSmiOrInteger32()) { | 2064 if (r.IsSmiOrInteger32()) { |
| 2377 Register reg = ToRegister(instr->value()); | 2065 Register reg = ToRegister(instr->value()); |
| 2378 __ test(reg, Operand(reg)); | 2066 __ test(reg, Operand(reg)); |
| 2379 EmitBranch(instr, not_zero); | 2067 EmitBranch(instr, not_zero); |
| 2380 } else if (r.IsDouble()) { | 2068 } else if (r.IsDouble()) { |
| 2381 ASSERT(!info()->IsStub()); | 2069 ASSERT(!info()->IsStub()); |
| 2382 CpuFeatureScope scope(masm(), SSE2); | |
| 2383 XMMRegister reg = ToDoubleRegister(instr->value()); | 2070 XMMRegister reg = ToDoubleRegister(instr->value()); |
| 2384 XMMRegister xmm_scratch = double_scratch0(); | 2071 XMMRegister xmm_scratch = double_scratch0(); |
| 2385 __ xorps(xmm_scratch, xmm_scratch); | 2072 __ xorps(xmm_scratch, xmm_scratch); |
| 2386 __ ucomisd(reg, xmm_scratch); | 2073 __ ucomisd(reg, xmm_scratch); |
| 2387 EmitBranch(instr, not_equal); | 2074 EmitBranch(instr, not_equal); |
| 2388 } else { | 2075 } else { |
| 2389 ASSERT(r.IsTagged()); | 2076 ASSERT(r.IsTagged()); |
| 2390 Register reg = ToRegister(instr->value()); | 2077 Register reg = ToRegister(instr->value()); |
| 2391 HType type = instr->hydrogen()->value()->type(); | 2078 HType type = instr->hydrogen()->value()->type(); |
| 2392 if (type.IsBoolean()) { | 2079 if (type.IsBoolean()) { |
| 2393 ASSERT(!info()->IsStub()); | 2080 ASSERT(!info()->IsStub()); |
| 2394 __ cmp(reg, factory()->true_value()); | 2081 __ cmp(reg, factory()->true_value()); |
| 2395 EmitBranch(instr, equal); | 2082 EmitBranch(instr, equal); |
| 2396 } else if (type.IsSmi()) { | 2083 } else if (type.IsSmi()) { |
| 2397 ASSERT(!info()->IsStub()); | 2084 ASSERT(!info()->IsStub()); |
| 2398 __ test(reg, Operand(reg)); | 2085 __ test(reg, Operand(reg)); |
| 2399 EmitBranch(instr, not_equal); | 2086 EmitBranch(instr, not_equal); |
| 2400 } else if (type.IsJSArray()) { | 2087 } else if (type.IsJSArray()) { |
| 2401 ASSERT(!info()->IsStub()); | 2088 ASSERT(!info()->IsStub()); |
| 2402 EmitBranch(instr, no_condition); | 2089 EmitBranch(instr, no_condition); |
| 2403 } else if (type.IsHeapNumber()) { | 2090 } else if (type.IsHeapNumber()) { |
| 2404 ASSERT(!info()->IsStub()); | 2091 ASSERT(!info()->IsStub()); |
| 2405 CpuFeatureScope scope(masm(), SSE2); | |
| 2406 XMMRegister xmm_scratch = double_scratch0(); | 2092 XMMRegister xmm_scratch = double_scratch0(); |
| 2407 __ xorps(xmm_scratch, xmm_scratch); | 2093 __ xorps(xmm_scratch, xmm_scratch); |
| 2408 __ ucomisd(xmm_scratch, FieldOperand(reg, HeapNumber::kValueOffset)); | 2094 __ ucomisd(xmm_scratch, FieldOperand(reg, HeapNumber::kValueOffset)); |
| 2409 EmitBranch(instr, not_equal); | 2095 EmitBranch(instr, not_equal); |
| 2410 } else if (type.IsString()) { | 2096 } else if (type.IsString()) { |
| 2411 ASSERT(!info()->IsStub()); | 2097 ASSERT(!info()->IsStub()); |
| 2412 __ cmp(FieldOperand(reg, String::kLengthOffset), Immediate(0)); | 2098 __ cmp(FieldOperand(reg, String::kLengthOffset), Immediate(0)); |
| 2413 EmitBranch(instr, not_equal); | 2099 EmitBranch(instr, not_equal); |
| 2414 } else { | 2100 } else { |
| 2415 ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types(); | 2101 ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types(); |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2481 __ CmpInstanceType(map, SYMBOL_TYPE); | 2167 __ CmpInstanceType(map, SYMBOL_TYPE); |
| 2482 __ j(equal, instr->TrueLabel(chunk_)); | 2168 __ j(equal, instr->TrueLabel(chunk_)); |
| 2483 } | 2169 } |
| 2484 | 2170 |
| 2485 if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) { | 2171 if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) { |
| 2486 // heap number -> false iff +0, -0, or NaN. | 2172 // heap number -> false iff +0, -0, or NaN. |
| 2487 Label not_heap_number; | 2173 Label not_heap_number; |
| 2488 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), | 2174 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), |
| 2489 factory()->heap_number_map()); | 2175 factory()->heap_number_map()); |
| 2490 __ j(not_equal, ¬_heap_number, Label::kNear); | 2176 __ j(not_equal, ¬_heap_number, Label::kNear); |
| 2491 if (CpuFeatures::IsSafeForSnapshot(isolate(), SSE2)) { | 2177 XMMRegister xmm_scratch = double_scratch0(); |
| 2492 CpuFeatureScope scope(masm(), SSE2); | 2178 __ xorps(xmm_scratch, xmm_scratch); |
| 2493 XMMRegister xmm_scratch = double_scratch0(); | 2179 __ ucomisd(xmm_scratch, FieldOperand(reg, HeapNumber::kValueOffset)); |
| 2494 __ xorps(xmm_scratch, xmm_scratch); | |
| 2495 __ ucomisd(xmm_scratch, FieldOperand(reg, HeapNumber::kValueOffset)); | |
| 2496 } else { | |
| 2497 __ fldz(); | |
| 2498 __ fld_d(FieldOperand(reg, HeapNumber::kValueOffset)); | |
| 2499 __ FCmp(); | |
| 2500 } | |
| 2501 __ j(zero, instr->FalseLabel(chunk_)); | 2180 __ j(zero, instr->FalseLabel(chunk_)); |
| 2502 __ jmp(instr->TrueLabel(chunk_)); | 2181 __ jmp(instr->TrueLabel(chunk_)); |
| 2503 __ bind(¬_heap_number); | 2182 __ bind(¬_heap_number); |
| 2504 } | 2183 } |
| 2505 | 2184 |
| 2506 if (!expected.IsGeneric()) { | 2185 if (!expected.IsGeneric()) { |
| 2507 // We've seen something for the first time -> deopt. | 2186 // We've seen something for the first time -> deopt. |
| 2508 // This can only happen if we are not generic already. | 2187 // This can only happen if we are not generic already. |
| 2509 DeoptimizeIf(no_condition, instr->environment()); | 2188 DeoptimizeIf(no_condition, instr->environment()); |
| 2510 } | 2189 } |
| 2511 } | 2190 } |
| 2512 } | 2191 } |
| 2513 } | 2192 } |
| 2514 | 2193 |
| 2515 | 2194 |
| 2516 void LCodeGen::EmitGoto(int block) { | 2195 void LCodeGen::EmitGoto(int block) { |
| 2517 if (!IsNextEmittedBlock(block)) { | 2196 if (!IsNextEmittedBlock(block)) { |
| 2518 __ jmp(chunk_->GetAssemblyLabel(LookupDestination(block))); | 2197 __ jmp(chunk_->GetAssemblyLabel(LookupDestination(block))); |
| 2519 } | 2198 } |
| 2520 } | 2199 } |
| 2521 | 2200 |
| 2522 | 2201 |
| 2523 void LCodeGen::DoClobberDoubles(LClobberDoubles* instr) { | |
| 2524 } | |
| 2525 | |
| 2526 | |
| 2527 void LCodeGen::DoGoto(LGoto* instr) { | 2202 void LCodeGen::DoGoto(LGoto* instr) { |
| 2528 EmitGoto(instr->block_id()); | 2203 EmitGoto(instr->block_id()); |
| 2529 } | 2204 } |
| 2530 | 2205 |
| 2531 | 2206 |
| 2532 Condition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) { | 2207 Condition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) { |
| 2533 Condition cond = no_condition; | 2208 Condition cond = no_condition; |
| 2534 switch (op) { | 2209 switch (op) { |
| 2535 case Token::EQ: | 2210 case Token::EQ: |
| 2536 case Token::EQ_STRICT: | 2211 case Token::EQ_STRICT: |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2568 | 2243 |
| 2569 if (left->IsConstantOperand() && right->IsConstantOperand()) { | 2244 if (left->IsConstantOperand() && right->IsConstantOperand()) { |
| 2570 // We can statically evaluate the comparison. | 2245 // We can statically evaluate the comparison. |
| 2571 double left_val = ToDouble(LConstantOperand::cast(left)); | 2246 double left_val = ToDouble(LConstantOperand::cast(left)); |
| 2572 double right_val = ToDouble(LConstantOperand::cast(right)); | 2247 double right_val = ToDouble(LConstantOperand::cast(right)); |
| 2573 int next_block = EvalComparison(instr->op(), left_val, right_val) ? | 2248 int next_block = EvalComparison(instr->op(), left_val, right_val) ? |
| 2574 instr->TrueDestination(chunk_) : instr->FalseDestination(chunk_); | 2249 instr->TrueDestination(chunk_) : instr->FalseDestination(chunk_); |
| 2575 EmitGoto(next_block); | 2250 EmitGoto(next_block); |
| 2576 } else { | 2251 } else { |
| 2577 if (instr->is_double()) { | 2252 if (instr->is_double()) { |
| 2578 if (CpuFeatures::IsSafeForSnapshot(isolate(), SSE2)) { | 2253 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); |
| 2579 CpuFeatureScope scope(masm(), SSE2); | |
| 2580 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); | |
| 2581 } else { | |
| 2582 X87LoadForUsage(ToX87Register(right), ToX87Register(left)); | |
| 2583 __ FCmp(); | |
| 2584 } | |
| 2585 // Don't base result on EFLAGS when a NaN is involved. Instead | 2254 // Don't base result on EFLAGS when a NaN is involved. Instead |
| 2586 // jump to the false block. | 2255 // jump to the false block. |
| 2587 __ j(parity_even, instr->FalseLabel(chunk_)); | 2256 __ j(parity_even, instr->FalseLabel(chunk_)); |
| 2588 } else { | 2257 } else { |
| 2589 if (right->IsConstantOperand()) { | 2258 if (right->IsConstantOperand()) { |
| 2590 __ cmp(ToOperand(left), | 2259 __ cmp(ToOperand(left), |
| 2591 ToImmediate(right, instr->hydrogen()->representation())); | 2260 ToImmediate(right, instr->hydrogen()->representation())); |
| 2592 } else if (left->IsConstantOperand()) { | 2261 } else if (left->IsConstantOperand()) { |
| 2593 __ cmp(ToOperand(right), | 2262 __ cmp(ToOperand(right), |
| 2594 ToImmediate(left, instr->hydrogen()->representation())); | 2263 ToImmediate(left, instr->hydrogen()->representation())); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 2618 | 2287 |
| 2619 | 2288 |
| 2620 void LCodeGen::DoCmpHoleAndBranch(LCmpHoleAndBranch* instr) { | 2289 void LCodeGen::DoCmpHoleAndBranch(LCmpHoleAndBranch* instr) { |
| 2621 if (instr->hydrogen()->representation().IsTagged()) { | 2290 if (instr->hydrogen()->representation().IsTagged()) { |
| 2622 Register input_reg = ToRegister(instr->object()); | 2291 Register input_reg = ToRegister(instr->object()); |
| 2623 __ cmp(input_reg, factory()->the_hole_value()); | 2292 __ cmp(input_reg, factory()->the_hole_value()); |
| 2624 EmitBranch(instr, equal); | 2293 EmitBranch(instr, equal); |
| 2625 return; | 2294 return; |
| 2626 } | 2295 } |
| 2627 | 2296 |
| 2628 bool use_sse2 = CpuFeatures::IsSupported(SSE2); | 2297 XMMRegister input_reg = ToDoubleRegister(instr->object()); |
| 2629 if (use_sse2) { | 2298 __ ucomisd(input_reg, input_reg); |
| 2630 CpuFeatureScope scope(masm(), SSE2); | 2299 EmitFalseBranch(instr, parity_odd); |
| 2631 XMMRegister input_reg = ToDoubleRegister(instr->object()); | |
| 2632 __ ucomisd(input_reg, input_reg); | |
| 2633 EmitFalseBranch(instr, parity_odd); | |
| 2634 } else { | |
| 2635 // Put the value to the top of stack | |
| 2636 X87Register src = ToX87Register(instr->object()); | |
| 2637 X87LoadForUsage(src); | |
| 2638 __ fld(0); | |
| 2639 __ fld(0); | |
| 2640 __ FCmp(); | |
| 2641 Label ok; | |
| 2642 __ j(parity_even, &ok, Label::kNear); | |
| 2643 __ fstp(0); | |
| 2644 EmitFalseBranch(instr, no_condition); | |
| 2645 __ bind(&ok); | |
| 2646 } | |
| 2647 | |
| 2648 | 2300 |
| 2649 __ sub(esp, Immediate(kDoubleSize)); | 2301 __ sub(esp, Immediate(kDoubleSize)); |
| 2650 if (use_sse2) { | 2302 __ movsd(MemOperand(esp, 0), input_reg); |
| 2651 CpuFeatureScope scope(masm(), SSE2); | |
| 2652 XMMRegister input_reg = ToDoubleRegister(instr->object()); | |
| 2653 __ movsd(MemOperand(esp, 0), input_reg); | |
| 2654 } else { | |
| 2655 __ fstp_d(MemOperand(esp, 0)); | |
| 2656 } | |
| 2657 | 2303 |
| 2658 __ add(esp, Immediate(kDoubleSize)); | 2304 __ add(esp, Immediate(kDoubleSize)); |
| 2659 int offset = sizeof(kHoleNanUpper32); | 2305 int offset = sizeof(kHoleNanUpper32); |
| 2660 __ cmp(MemOperand(esp, -offset), Immediate(kHoleNanUpper32)); | 2306 __ cmp(MemOperand(esp, -offset), Immediate(kHoleNanUpper32)); |
| 2661 EmitBranch(instr, equal); | 2307 EmitBranch(instr, equal); |
| 2662 } | 2308 } |
| 2663 | 2309 |
| 2664 | 2310 |
| 2665 void LCodeGen::DoCompareMinusZeroAndBranch(LCompareMinusZeroAndBranch* instr) { | 2311 void LCodeGen::DoCompareMinusZeroAndBranch(LCompareMinusZeroAndBranch* instr) { |
| 2666 Representation rep = instr->hydrogen()->value()->representation(); | 2312 Representation rep = instr->hydrogen()->value()->representation(); |
| 2667 ASSERT(!rep.IsInteger32()); | 2313 ASSERT(!rep.IsInteger32()); |
| 2668 Register scratch = ToRegister(instr->temp()); | 2314 Register scratch = ToRegister(instr->temp()); |
| 2669 | 2315 |
| 2670 if (rep.IsDouble()) { | 2316 if (rep.IsDouble()) { |
| 2671 CpuFeatureScope use_sse2(masm(), SSE2); | |
| 2672 XMMRegister value = ToDoubleRegister(instr->value()); | 2317 XMMRegister value = ToDoubleRegister(instr->value()); |
| 2673 XMMRegister xmm_scratch = double_scratch0(); | 2318 XMMRegister xmm_scratch = double_scratch0(); |
| 2674 __ xorps(xmm_scratch, xmm_scratch); | 2319 __ xorps(xmm_scratch, xmm_scratch); |
| 2675 __ ucomisd(xmm_scratch, value); | 2320 __ ucomisd(xmm_scratch, value); |
| 2676 EmitFalseBranch(instr, not_equal); | 2321 EmitFalseBranch(instr, not_equal); |
| 2677 __ movmskpd(scratch, value); | 2322 __ movmskpd(scratch, value); |
| 2678 __ test(scratch, Immediate(1)); | 2323 __ test(scratch, Immediate(1)); |
| 2679 EmitBranch(instr, not_zero); | 2324 EmitBranch(instr, not_zero); |
| 2680 } else { | 2325 } else { |
| 2681 Register value = ToRegister(instr->value()); | 2326 Register value = ToRegister(instr->value()); |
| (...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2964 __ bind(&true_value); | 2609 __ bind(&true_value); |
| 2965 __ mov(ToRegister(instr->result()), factory()->true_value()); | 2610 __ mov(ToRegister(instr->result()), factory()->true_value()); |
| 2966 __ bind(&done); | 2611 __ bind(&done); |
| 2967 } | 2612 } |
| 2968 | 2613 |
| 2969 | 2614 |
| 2970 void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { | 2615 void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { |
| 2971 class DeferredInstanceOfKnownGlobal V8_FINAL : public LDeferredCode { | 2616 class DeferredInstanceOfKnownGlobal V8_FINAL : public LDeferredCode { |
| 2972 public: | 2617 public: |
| 2973 DeferredInstanceOfKnownGlobal(LCodeGen* codegen, | 2618 DeferredInstanceOfKnownGlobal(LCodeGen* codegen, |
| 2974 LInstanceOfKnownGlobal* instr, | 2619 LInstanceOfKnownGlobal* instr) |
| 2975 const X87Stack& x87_stack) | 2620 : LDeferredCode(codegen), instr_(instr) { } |
| 2976 : LDeferredCode(codegen, x87_stack), instr_(instr) { } | |
| 2977 virtual void Generate() V8_OVERRIDE { | 2621 virtual void Generate() V8_OVERRIDE { |
| 2978 codegen()->DoDeferredInstanceOfKnownGlobal(instr_, &map_check_); | 2622 codegen()->DoDeferredInstanceOfKnownGlobal(instr_, &map_check_); |
| 2979 } | 2623 } |
| 2980 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } | 2624 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
| 2981 Label* map_check() { return &map_check_; } | 2625 Label* map_check() { return &map_check_; } |
| 2982 private: | 2626 private: |
| 2983 LInstanceOfKnownGlobal* instr_; | 2627 LInstanceOfKnownGlobal* instr_; |
| 2984 Label map_check_; | 2628 Label map_check_; |
| 2985 }; | 2629 }; |
| 2986 | 2630 |
| 2987 DeferredInstanceOfKnownGlobal* deferred; | 2631 DeferredInstanceOfKnownGlobal* deferred; |
| 2988 deferred = new(zone()) DeferredInstanceOfKnownGlobal(this, instr, x87_stack_); | 2632 deferred = new(zone()) DeferredInstanceOfKnownGlobal(this, instr); |
| 2989 | 2633 |
| 2990 Label done, false_result; | 2634 Label done, false_result; |
| 2991 Register object = ToRegister(instr->value()); | 2635 Register object = ToRegister(instr->value()); |
| 2992 Register temp = ToRegister(instr->temp()); | 2636 Register temp = ToRegister(instr->temp()); |
| 2993 | 2637 |
| 2994 // A Smi is not an instance of anything. | 2638 // A Smi is not an instance of anything. |
| 2995 __ JumpIfSmi(object, &false_result, Label::kNear); | 2639 __ JumpIfSmi(object, &false_result, Label::kNear); |
| 2996 | 2640 |
| 2997 // This is the inlined call site instanceof cache. The two occurences of the | 2641 // This is the inlined call site instanceof cache. The two occurences of the |
| 2998 // hole value will be patched to the last map/result pair generated by the | 2642 // hole value will be patched to the last map/result pair generated by the |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3127 void LCodeGen::DoReturn(LReturn* instr) { | 2771 void LCodeGen::DoReturn(LReturn* instr) { |
| 3128 if (FLAG_trace && info()->IsOptimizing()) { | 2772 if (FLAG_trace && info()->IsOptimizing()) { |
| 3129 // Preserve the return value on the stack and rely on the runtime call | 2773 // Preserve the return value on the stack and rely on the runtime call |
| 3130 // to return the value in the same register. We're leaving the code | 2774 // to return the value in the same register. We're leaving the code |
| 3131 // managed by the register allocator and tearing down the frame, it's | 2775 // managed by the register allocator and tearing down the frame, it's |
| 3132 // safe to write to the context register. | 2776 // safe to write to the context register. |
| 3133 __ push(eax); | 2777 __ push(eax); |
| 3134 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 2778 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 3135 __ CallRuntime(Runtime::kTraceExit, 1); | 2779 __ CallRuntime(Runtime::kTraceExit, 1); |
| 3136 } | 2780 } |
| 3137 if (info()->saves_caller_doubles() && CpuFeatures::IsSupported(SSE2)) { | 2781 if (info()->saves_caller_doubles()) RestoreCallerDoubles(); |
| 3138 RestoreCallerDoubles(); | |
| 3139 } | |
| 3140 if (dynamic_frame_alignment_) { | 2782 if (dynamic_frame_alignment_) { |
| 3141 // Fetch the state of the dynamic frame alignment. | 2783 // Fetch the state of the dynamic frame alignment. |
| 3142 __ mov(edx, Operand(ebp, | 2784 __ mov(edx, Operand(ebp, |
| 3143 JavaScriptFrameConstants::kDynamicAlignmentStateOffset)); | 2785 JavaScriptFrameConstants::kDynamicAlignmentStateOffset)); |
| 3144 } | 2786 } |
| 3145 int no_frame_start = -1; | 2787 int no_frame_start = -1; |
| 3146 if (NeedsEagerFrame()) { | 2788 if (NeedsEagerFrame()) { |
| 3147 __ mov(esp, ebp); | 2789 __ mov(esp, ebp); |
| 3148 __ pop(ebp); | 2790 __ pop(ebp); |
| 3149 no_frame_start = masm_->pc_offset(); | 2791 no_frame_start = masm_->pc_offset(); |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3244 if (instr->hydrogen()->NeedsWriteBarrier()) { | 2886 if (instr->hydrogen()->NeedsWriteBarrier()) { |
| 3245 SmiCheck check_needed = | 2887 SmiCheck check_needed = |
| 3246 instr->hydrogen()->value()->IsHeapObject() | 2888 instr->hydrogen()->value()->IsHeapObject() |
| 3247 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; | 2889 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
| 3248 Register temp = ToRegister(instr->temp()); | 2890 Register temp = ToRegister(instr->temp()); |
| 3249 int offset = Context::SlotOffset(instr->slot_index()); | 2891 int offset = Context::SlotOffset(instr->slot_index()); |
| 3250 __ RecordWriteContextSlot(context, | 2892 __ RecordWriteContextSlot(context, |
| 3251 offset, | 2893 offset, |
| 3252 value, | 2894 value, |
| 3253 temp, | 2895 temp, |
| 3254 GetSaveFPRegsMode(isolate()), | 2896 kSaveFPRegs, |
| 3255 EMIT_REMEMBERED_SET, | 2897 EMIT_REMEMBERED_SET, |
| 3256 check_needed); | 2898 check_needed); |
| 3257 } | 2899 } |
| 3258 | 2900 |
| 3259 __ bind(&skip_assignment); | 2901 __ bind(&skip_assignment); |
| 3260 } | 2902 } |
| 3261 | 2903 |
| 3262 | 2904 |
| 3263 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { | 2905 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { |
| 3264 HObjectAccess access = instr->hydrogen()->access(); | 2906 HObjectAccess access = instr->hydrogen()->access(); |
| 3265 int offset = access.offset(); | 2907 int offset = access.offset(); |
| 3266 | 2908 |
| 3267 if (access.IsExternalMemory()) { | 2909 if (access.IsExternalMemory()) { |
| 3268 Register result = ToRegister(instr->result()); | 2910 Register result = ToRegister(instr->result()); |
| 3269 MemOperand operand = instr->object()->IsConstantOperand() | 2911 MemOperand operand = instr->object()->IsConstantOperand() |
| 3270 ? MemOperand::StaticVariable(ToExternalReference( | 2912 ? MemOperand::StaticVariable(ToExternalReference( |
| 3271 LConstantOperand::cast(instr->object()))) | 2913 LConstantOperand::cast(instr->object()))) |
| 3272 : MemOperand(ToRegister(instr->object()), offset); | 2914 : MemOperand(ToRegister(instr->object()), offset); |
| 3273 __ Load(result, operand, access.representation()); | 2915 __ Load(result, operand, access.representation()); |
| 3274 return; | 2916 return; |
| 3275 } | 2917 } |
| 3276 | 2918 |
| 3277 Register object = ToRegister(instr->object()); | 2919 Register object = ToRegister(instr->object()); |
| 3278 if (instr->hydrogen()->representation().IsDouble()) { | 2920 if (instr->hydrogen()->representation().IsDouble()) { |
| 3279 if (CpuFeatures::IsSupported(SSE2)) { | 2921 XMMRegister result = ToDoubleRegister(instr->result()); |
| 3280 CpuFeatureScope scope(masm(), SSE2); | 2922 __ movsd(result, FieldOperand(object, offset)); |
| 3281 XMMRegister result = ToDoubleRegister(instr->result()); | |
| 3282 __ movsd(result, FieldOperand(object, offset)); | |
| 3283 } else { | |
| 3284 X87Mov(ToX87Register(instr->result()), FieldOperand(object, offset)); | |
| 3285 } | |
| 3286 return; | 2923 return; |
| 3287 } | 2924 } |
| 3288 | 2925 |
| 3289 Register result = ToRegister(instr->result()); | 2926 Register result = ToRegister(instr->result()); |
| 3290 if (!access.IsInobject()) { | 2927 if (!access.IsInobject()) { |
| 3291 __ mov(result, FieldOperand(object, JSObject::kPropertiesOffset)); | 2928 __ mov(result, FieldOperand(object, JSObject::kPropertiesOffset)); |
| 3292 object = result; | 2929 object = result; |
| 3293 } | 2930 } |
| 3294 __ Load(result, FieldOperand(object, offset), access.representation()); | 2931 __ Load(result, FieldOperand(object, offset), access.representation()); |
| 3295 } | 2932 } |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3402 } | 3039 } |
| 3403 Operand operand(BuildFastArrayOperand( | 3040 Operand operand(BuildFastArrayOperand( |
| 3404 instr->elements(), | 3041 instr->elements(), |
| 3405 key, | 3042 key, |
| 3406 instr->hydrogen()->key()->representation(), | 3043 instr->hydrogen()->key()->representation(), |
| 3407 elements_kind, | 3044 elements_kind, |
| 3408 0, | 3045 0, |
| 3409 instr->additional_index())); | 3046 instr->additional_index())); |
| 3410 if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS || | 3047 if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS || |
| 3411 elements_kind == FLOAT32_ELEMENTS) { | 3048 elements_kind == FLOAT32_ELEMENTS) { |
| 3412 if (CpuFeatures::IsSupported(SSE2)) { | 3049 XMMRegister result(ToDoubleRegister(instr->result())); |
| 3413 CpuFeatureScope scope(masm(), SSE2); | 3050 __ movss(result, operand); |
| 3414 XMMRegister result(ToDoubleRegister(instr->result())); | 3051 __ cvtss2sd(result, result); |
| 3415 __ movss(result, operand); | |
| 3416 __ cvtss2sd(result, result); | |
| 3417 } else { | |
| 3418 X87Mov(ToX87Register(instr->result()), operand, kX87FloatOperand); | |
| 3419 } | |
| 3420 } else if (elements_kind == EXTERNAL_FLOAT64_ELEMENTS || | 3052 } else if (elements_kind == EXTERNAL_FLOAT64_ELEMENTS || |
| 3421 elements_kind == FLOAT64_ELEMENTS) { | 3053 elements_kind == FLOAT64_ELEMENTS) { |
| 3422 if (CpuFeatures::IsSupported(SSE2)) { | 3054 __ movsd(ToDoubleRegister(instr->result()), operand); |
| 3423 CpuFeatureScope scope(masm(), SSE2); | |
| 3424 __ movsd(ToDoubleRegister(instr->result()), operand); | |
| 3425 } else { | |
| 3426 X87Mov(ToX87Register(instr->result()), operand); | |
| 3427 } | |
| 3428 } else { | 3055 } else { |
| 3429 Register result(ToRegister(instr->result())); | 3056 Register result(ToRegister(instr->result())); |
| 3430 switch (elements_kind) { | 3057 switch (elements_kind) { |
| 3431 case EXTERNAL_INT8_ELEMENTS: | 3058 case EXTERNAL_INT8_ELEMENTS: |
| 3432 case INT8_ELEMENTS: | 3059 case INT8_ELEMENTS: |
| 3433 __ movsx_b(result, operand); | 3060 __ movsx_b(result, operand); |
| 3434 break; | 3061 break; |
| 3435 case EXTERNAL_UINT8_CLAMPED_ELEMENTS: | 3062 case EXTERNAL_UINT8_CLAMPED_ELEMENTS: |
| 3436 case EXTERNAL_UINT8_ELEMENTS: | 3063 case EXTERNAL_UINT8_ELEMENTS: |
| 3437 case UINT8_ELEMENTS: | 3064 case UINT8_ELEMENTS: |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3491 DeoptimizeIf(equal, instr->environment()); | 3118 DeoptimizeIf(equal, instr->environment()); |
| 3492 } | 3119 } |
| 3493 | 3120 |
| 3494 Operand double_load_operand = BuildFastArrayOperand( | 3121 Operand double_load_operand = BuildFastArrayOperand( |
| 3495 instr->elements(), | 3122 instr->elements(), |
| 3496 instr->key(), | 3123 instr->key(), |
| 3497 instr->hydrogen()->key()->representation(), | 3124 instr->hydrogen()->key()->representation(), |
| 3498 FAST_DOUBLE_ELEMENTS, | 3125 FAST_DOUBLE_ELEMENTS, |
| 3499 FixedDoubleArray::kHeaderSize - kHeapObjectTag, | 3126 FixedDoubleArray::kHeaderSize - kHeapObjectTag, |
| 3500 instr->additional_index()); | 3127 instr->additional_index()); |
| 3501 if (CpuFeatures::IsSupported(SSE2)) { | 3128 XMMRegister result = ToDoubleRegister(instr->result()); |
| 3502 CpuFeatureScope scope(masm(), SSE2); | 3129 __ movsd(result, double_load_operand); |
| 3503 XMMRegister result = ToDoubleRegister(instr->result()); | |
| 3504 __ movsd(result, double_load_operand); | |
| 3505 } else { | |
| 3506 X87Mov(ToX87Register(instr->result()), double_load_operand); | |
| 3507 } | |
| 3508 } | 3130 } |
| 3509 | 3131 |
| 3510 | 3132 |
| 3511 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { | 3133 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { |
| 3512 Register result = ToRegister(instr->result()); | 3134 Register result = ToRegister(instr->result()); |
| 3513 | 3135 |
| 3514 // Load the result. | 3136 // Load the result. |
| 3515 __ mov(result, | 3137 __ mov(result, |
| 3516 BuildFastArrayOperand(instr->elements(), | 3138 BuildFastArrayOperand(instr->elements(), |
| 3517 instr->key(), | 3139 instr->key(), |
| (...skipping 401 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3919 DeoptimizeIf(negative, instr->environment()); | 3541 DeoptimizeIf(negative, instr->environment()); |
| 3920 __ bind(&is_positive); | 3542 __ bind(&is_positive); |
| 3921 } | 3543 } |
| 3922 | 3544 |
| 3923 | 3545 |
| 3924 void LCodeGen::DoMathAbs(LMathAbs* instr) { | 3546 void LCodeGen::DoMathAbs(LMathAbs* instr) { |
| 3925 // Class for deferred case. | 3547 // Class for deferred case. |
| 3926 class DeferredMathAbsTaggedHeapNumber V8_FINAL : public LDeferredCode { | 3548 class DeferredMathAbsTaggedHeapNumber V8_FINAL : public LDeferredCode { |
| 3927 public: | 3549 public: |
| 3928 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, | 3550 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, |
| 3929 LMathAbs* instr, | 3551 LMathAbs* instr) |
| 3930 const X87Stack& x87_stack) | 3552 : LDeferredCode(codegen), instr_(instr) { } |
| 3931 : LDeferredCode(codegen, x87_stack), instr_(instr) { } | |
| 3932 virtual void Generate() V8_OVERRIDE { | 3553 virtual void Generate() V8_OVERRIDE { |
| 3933 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); | 3554 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); |
| 3934 } | 3555 } |
| 3935 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } | 3556 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
| 3936 private: | 3557 private: |
| 3937 LMathAbs* instr_; | 3558 LMathAbs* instr_; |
| 3938 }; | 3559 }; |
| 3939 | 3560 |
| 3940 ASSERT(instr->value()->Equals(instr->result())); | 3561 ASSERT(instr->value()->Equals(instr->result())); |
| 3941 Representation r = instr->hydrogen()->value()->representation(); | 3562 Representation r = instr->hydrogen()->value()->representation(); |
| 3942 | 3563 |
| 3943 CpuFeatureScope scope(masm(), SSE2); | |
| 3944 if (r.IsDouble()) { | 3564 if (r.IsDouble()) { |
| 3945 XMMRegister scratch = double_scratch0(); | 3565 XMMRegister scratch = double_scratch0(); |
| 3946 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 3566 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
| 3947 __ xorps(scratch, scratch); | 3567 __ xorps(scratch, scratch); |
| 3948 __ subsd(scratch, input_reg); | 3568 __ subsd(scratch, input_reg); |
| 3949 __ andps(input_reg, scratch); | 3569 __ andps(input_reg, scratch); |
| 3950 } else if (r.IsSmiOrInteger32()) { | 3570 } else if (r.IsSmiOrInteger32()) { |
| 3951 EmitIntegerMathAbs(instr); | 3571 EmitIntegerMathAbs(instr); |
| 3952 } else { // Tagged case. | 3572 } else { // Tagged case. |
| 3953 DeferredMathAbsTaggedHeapNumber* deferred = | 3573 DeferredMathAbsTaggedHeapNumber* deferred = |
| 3954 new(zone()) DeferredMathAbsTaggedHeapNumber(this, instr, x87_stack_); | 3574 new(zone()) DeferredMathAbsTaggedHeapNumber(this, instr); |
| 3955 Register input_reg = ToRegister(instr->value()); | 3575 Register input_reg = ToRegister(instr->value()); |
| 3956 // Smi check. | 3576 // Smi check. |
| 3957 __ JumpIfNotSmi(input_reg, deferred->entry()); | 3577 __ JumpIfNotSmi(input_reg, deferred->entry()); |
| 3958 EmitIntegerMathAbs(instr); | 3578 EmitIntegerMathAbs(instr); |
| 3959 __ bind(deferred->exit()); | 3579 __ bind(deferred->exit()); |
| 3960 } | 3580 } |
| 3961 } | 3581 } |
| 3962 | 3582 |
| 3963 | 3583 |
| 3964 void LCodeGen::DoMathFloor(LMathFloor* instr) { | 3584 void LCodeGen::DoMathFloor(LMathFloor* instr) { |
| 3965 CpuFeatureScope scope(masm(), SSE2); | |
| 3966 XMMRegister xmm_scratch = double_scratch0(); | 3585 XMMRegister xmm_scratch = double_scratch0(); |
| 3967 Register output_reg = ToRegister(instr->result()); | 3586 Register output_reg = ToRegister(instr->result()); |
| 3968 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 3587 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
| 3969 | 3588 |
| 3970 if (CpuFeatures::IsSupported(SSE4_1)) { | 3589 if (CpuFeatures::IsSupported(SSE4_1)) { |
| 3971 CpuFeatureScope scope(masm(), SSE4_1); | 3590 CpuFeatureScope scope(masm(), SSE4_1); |
| 3972 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3591 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 3973 // Deoptimize on negative zero. | 3592 // Deoptimize on negative zero. |
| 3974 Label non_zero; | 3593 Label non_zero; |
| 3975 __ xorps(xmm_scratch, xmm_scratch); // Zero the register. | 3594 __ xorps(xmm_scratch, xmm_scratch); // Zero the register. |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4021 __ j(equal, &done, Label::kNear); | 3640 __ j(equal, &done, Label::kNear); |
| 4022 __ sub(output_reg, Immediate(1)); | 3641 __ sub(output_reg, Immediate(1)); |
| 4023 DeoptimizeIf(overflow, instr->environment()); | 3642 DeoptimizeIf(overflow, instr->environment()); |
| 4024 | 3643 |
| 4025 __ bind(&done); | 3644 __ bind(&done); |
| 4026 } | 3645 } |
| 4027 } | 3646 } |
| 4028 | 3647 |
| 4029 | 3648 |
| 4030 void LCodeGen::DoMathRound(LMathRound* instr) { | 3649 void LCodeGen::DoMathRound(LMathRound* instr) { |
| 4031 CpuFeatureScope scope(masm(), SSE2); | |
| 4032 Register output_reg = ToRegister(instr->result()); | 3650 Register output_reg = ToRegister(instr->result()); |
| 4033 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 3651 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
| 4034 XMMRegister xmm_scratch = double_scratch0(); | 3652 XMMRegister xmm_scratch = double_scratch0(); |
| 4035 XMMRegister input_temp = ToDoubleRegister(instr->temp()); | 3653 XMMRegister input_temp = ToDoubleRegister(instr->temp()); |
| 4036 ExternalReference one_half = ExternalReference::address_of_one_half(); | 3654 ExternalReference one_half = ExternalReference::address_of_one_half(); |
| 4037 ExternalReference minus_one_half = | 3655 ExternalReference minus_one_half = |
| 4038 ExternalReference::address_of_minus_one_half(); | 3656 ExternalReference::address_of_minus_one_half(); |
| 4039 | 3657 |
| 4040 Label done, round_to_zero, below_one_half, do_not_compensate; | 3658 Label done, round_to_zero, below_one_half, do_not_compensate; |
| 4041 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear; | 3659 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear; |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4084 __ test(output_reg, Immediate(1)); | 3702 __ test(output_reg, Immediate(1)); |
| 4085 __ RecordComment("Minus zero"); | 3703 __ RecordComment("Minus zero"); |
| 4086 DeoptimizeIf(not_zero, instr->environment()); | 3704 DeoptimizeIf(not_zero, instr->environment()); |
| 4087 } | 3705 } |
| 4088 __ Move(output_reg, Immediate(0)); | 3706 __ Move(output_reg, Immediate(0)); |
| 4089 __ bind(&done); | 3707 __ bind(&done); |
| 4090 } | 3708 } |
| 4091 | 3709 |
| 4092 | 3710 |
| 4093 void LCodeGen::DoMathSqrt(LMathSqrt* instr) { | 3711 void LCodeGen::DoMathSqrt(LMathSqrt* instr) { |
| 4094 CpuFeatureScope scope(masm(), SSE2); | |
| 4095 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 3712 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
| 4096 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); | 3713 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); |
| 4097 __ sqrtsd(input_reg, input_reg); | 3714 __ sqrtsd(input_reg, input_reg); |
| 4098 } | 3715 } |
| 4099 | 3716 |
| 4100 | 3717 |
| 4101 void LCodeGen::DoMathPowHalf(LMathPowHalf* instr) { | 3718 void LCodeGen::DoMathPowHalf(LMathPowHalf* instr) { |
| 4102 CpuFeatureScope scope(masm(), SSE2); | |
| 4103 XMMRegister xmm_scratch = double_scratch0(); | 3719 XMMRegister xmm_scratch = double_scratch0(); |
| 4104 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 3720 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
| 4105 Register scratch = ToRegister(instr->temp()); | 3721 Register scratch = ToRegister(instr->temp()); |
| 4106 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); | 3722 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); |
| 4107 | 3723 |
| 4108 // Note that according to ECMA-262 15.8.2.13: | 3724 // Note that according to ECMA-262 15.8.2.13: |
| 4109 // Math.pow(-Infinity, 0.5) == Infinity | 3725 // Math.pow(-Infinity, 0.5) == Infinity |
| 4110 // Math.sqrt(-Infinity) == NaN | 3726 // Math.sqrt(-Infinity) == NaN |
| 4111 Label done, sqrt; | 3727 Label done, sqrt; |
| 4112 // Check base for -Infinity. According to IEEE-754, single-precision | 3728 // Check base for -Infinity. According to IEEE-754, single-precision |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4160 __ CallStub(&stub); | 3776 __ CallStub(&stub); |
| 4161 } else { | 3777 } else { |
| 4162 ASSERT(exponent_type.IsDouble()); | 3778 ASSERT(exponent_type.IsDouble()); |
| 4163 MathPowStub stub(isolate(), MathPowStub::DOUBLE); | 3779 MathPowStub stub(isolate(), MathPowStub::DOUBLE); |
| 4164 __ CallStub(&stub); | 3780 __ CallStub(&stub); |
| 4165 } | 3781 } |
| 4166 } | 3782 } |
| 4167 | 3783 |
| 4168 | 3784 |
| 4169 void LCodeGen::DoMathLog(LMathLog* instr) { | 3785 void LCodeGen::DoMathLog(LMathLog* instr) { |
| 4170 CpuFeatureScope scope(masm(), SSE2); | |
| 4171 ASSERT(instr->value()->Equals(instr->result())); | 3786 ASSERT(instr->value()->Equals(instr->result())); |
| 4172 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 3787 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
| 4173 XMMRegister xmm_scratch = double_scratch0(); | 3788 XMMRegister xmm_scratch = double_scratch0(); |
| 4174 Label positive, done, zero; | 3789 Label positive, done, zero; |
| 4175 __ xorps(xmm_scratch, xmm_scratch); | 3790 __ xorps(xmm_scratch, xmm_scratch); |
| 4176 __ ucomisd(input_reg, xmm_scratch); | 3791 __ ucomisd(input_reg, xmm_scratch); |
| 4177 __ j(above, &positive, Label::kNear); | 3792 __ j(above, &positive, Label::kNear); |
| 4178 __ j(not_carry, &zero, Label::kNear); | 3793 __ j(not_carry, &zero, Label::kNear); |
| 4179 ExternalReference nan = | 3794 ExternalReference nan = |
| 4180 ExternalReference::address_of_canonical_non_hole_nan(); | 3795 ExternalReference::address_of_canonical_non_hole_nan(); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 4192 __ fld_d(Operand(esp, 0)); | 3807 __ fld_d(Operand(esp, 0)); |
| 4193 __ fyl2x(); | 3808 __ fyl2x(); |
| 4194 __ fstp_d(Operand(esp, 0)); | 3809 __ fstp_d(Operand(esp, 0)); |
| 4195 __ movsd(input_reg, Operand(esp, 0)); | 3810 __ movsd(input_reg, Operand(esp, 0)); |
| 4196 __ add(Operand(esp), Immediate(kDoubleSize)); | 3811 __ add(Operand(esp), Immediate(kDoubleSize)); |
| 4197 __ bind(&done); | 3812 __ bind(&done); |
| 4198 } | 3813 } |
| 4199 | 3814 |
| 4200 | 3815 |
| 4201 void LCodeGen::DoMathClz32(LMathClz32* instr) { | 3816 void LCodeGen::DoMathClz32(LMathClz32* instr) { |
| 4202 CpuFeatureScope scope(masm(), SSE2); | |
| 4203 Register input = ToRegister(instr->value()); | 3817 Register input = ToRegister(instr->value()); |
| 4204 Register result = ToRegister(instr->result()); | 3818 Register result = ToRegister(instr->result()); |
| 4205 Label not_zero_input; | 3819 Label not_zero_input; |
| 4206 __ bsr(result, input); | 3820 __ bsr(result, input); |
| 4207 | 3821 |
| 4208 __ j(not_zero, ¬_zero_input); | 3822 __ j(not_zero, ¬_zero_input); |
| 4209 __ Move(result, Immediate(63)); // 63^31 == 32 | 3823 __ Move(result, Immediate(63)); // 63^31 == 32 |
| 4210 | 3824 |
| 4211 __ bind(¬_zero_input); | 3825 __ bind(¬_zero_input); |
| 4212 __ xor_(result, Immediate(31)); // for x in [0..31], 31^x == 31-x. | 3826 __ xor_(result, Immediate(31)); // for x in [0..31], 31^x == 31-x. |
| 4213 } | 3827 } |
| 4214 | 3828 |
| 4215 | 3829 |
| 4216 void LCodeGen::DoMathExp(LMathExp* instr) { | 3830 void LCodeGen::DoMathExp(LMathExp* instr) { |
| 4217 CpuFeatureScope scope(masm(), SSE2); | |
| 4218 XMMRegister input = ToDoubleRegister(instr->value()); | 3831 XMMRegister input = ToDoubleRegister(instr->value()); |
| 4219 XMMRegister result = ToDoubleRegister(instr->result()); | 3832 XMMRegister result = ToDoubleRegister(instr->result()); |
| 4220 XMMRegister temp0 = double_scratch0(); | 3833 XMMRegister temp0 = double_scratch0(); |
| 4221 Register temp1 = ToRegister(instr->temp1()); | 3834 Register temp1 = ToRegister(instr->temp1()); |
| 4222 Register temp2 = ToRegister(instr->temp2()); | 3835 Register temp2 = ToRegister(instr->temp2()); |
| 4223 | 3836 |
| 4224 MathExpGenerator::EmitMathExp(masm(), input, result, temp0, temp1, temp2); | 3837 MathExpGenerator::EmitMathExp(masm(), input, result, temp0, temp1, temp2); |
| 4225 } | 3838 } |
| 4226 | 3839 |
| 4227 | 3840 |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4386 DeoptimizeIf(zero, instr->environment()); | 3999 DeoptimizeIf(zero, instr->environment()); |
| 4387 | 4000 |
| 4388 // We know now that value is not a smi, so we can omit the check below. | 4001 // We know now that value is not a smi, so we can omit the check below. |
| 4389 check_needed = OMIT_SMI_CHECK; | 4002 check_needed = OMIT_SMI_CHECK; |
| 4390 } | 4003 } |
| 4391 } | 4004 } |
| 4392 } else if (representation.IsDouble()) { | 4005 } else if (representation.IsDouble()) { |
| 4393 ASSERT(access.IsInobject()); | 4006 ASSERT(access.IsInobject()); |
| 4394 ASSERT(!instr->hydrogen()->has_transition()); | 4007 ASSERT(!instr->hydrogen()->has_transition()); |
| 4395 ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); | 4008 ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); |
| 4396 if (CpuFeatures::IsSupported(SSE2)) { | 4009 XMMRegister value = ToDoubleRegister(instr->value()); |
| 4397 CpuFeatureScope scope(masm(), SSE2); | 4010 __ movsd(FieldOperand(object, offset), value); |
| 4398 XMMRegister value = ToDoubleRegister(instr->value()); | |
| 4399 __ movsd(FieldOperand(object, offset), value); | |
| 4400 } else { | |
| 4401 X87Register value = ToX87Register(instr->value()); | |
| 4402 X87Mov(FieldOperand(object, offset), value); | |
| 4403 } | |
| 4404 return; | 4011 return; |
| 4405 } | 4012 } |
| 4406 | 4013 |
| 4407 if (instr->hydrogen()->has_transition()) { | 4014 if (instr->hydrogen()->has_transition()) { |
| 4408 Handle<Map> transition = instr->hydrogen()->transition_map(); | 4015 Handle<Map> transition = instr->hydrogen()->transition_map(); |
| 4409 AddDeprecationDependency(transition); | 4016 AddDeprecationDependency(transition); |
| 4410 if (!instr->hydrogen()->NeedsWriteBarrierForMap()) { | 4017 if (!instr->hydrogen()->NeedsWriteBarrierForMap()) { |
| 4411 __ mov(FieldOperand(object, HeapObject::kMapOffset), transition); | 4018 __ mov(FieldOperand(object, HeapObject::kMapOffset), transition); |
| 4412 } else { | 4019 } else { |
| 4413 Register temp = ToRegister(instr->temp()); | 4020 Register temp = ToRegister(instr->temp()); |
| 4414 Register temp_map = ToRegister(instr->temp_map()); | 4021 Register temp_map = ToRegister(instr->temp_map()); |
| 4415 __ mov(temp_map, transition); | 4022 __ mov(temp_map, transition); |
| 4416 __ mov(FieldOperand(object, HeapObject::kMapOffset), temp_map); | 4023 __ mov(FieldOperand(object, HeapObject::kMapOffset), temp_map); |
| 4417 // Update the write barrier for the map field. | 4024 // Update the write barrier for the map field. |
| 4418 __ RecordWriteField(object, | 4025 __ RecordWriteField(object, |
| 4419 HeapObject::kMapOffset, | 4026 HeapObject::kMapOffset, |
| 4420 temp_map, | 4027 temp_map, |
| 4421 temp, | 4028 temp, |
| 4422 GetSaveFPRegsMode(isolate()), | 4029 kSaveFPRegs, |
| 4423 OMIT_REMEMBERED_SET, | 4030 OMIT_REMEMBERED_SET, |
| 4424 OMIT_SMI_CHECK); | 4031 OMIT_SMI_CHECK); |
| 4425 } | 4032 } |
| 4426 } | 4033 } |
| 4427 | 4034 |
| 4428 // Do the store. | 4035 // Do the store. |
| 4429 Register write_register = object; | 4036 Register write_register = object; |
| 4430 if (!access.IsInobject()) { | 4037 if (!access.IsInobject()) { |
| 4431 write_register = ToRegister(instr->temp()); | 4038 write_register = ToRegister(instr->temp()); |
| 4432 __ mov(write_register, FieldOperand(object, JSObject::kPropertiesOffset)); | 4039 __ mov(write_register, FieldOperand(object, JSObject::kPropertiesOffset)); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 4453 } | 4060 } |
| 4454 | 4061 |
| 4455 if (instr->hydrogen()->NeedsWriteBarrier()) { | 4062 if (instr->hydrogen()->NeedsWriteBarrier()) { |
| 4456 Register value = ToRegister(instr->value()); | 4063 Register value = ToRegister(instr->value()); |
| 4457 Register temp = access.IsInobject() ? ToRegister(instr->temp()) : object; | 4064 Register temp = access.IsInobject() ? ToRegister(instr->temp()) : object; |
| 4458 // Update the write barrier for the object for in-object properties. | 4065 // Update the write barrier for the object for in-object properties. |
| 4459 __ RecordWriteField(write_register, | 4066 __ RecordWriteField(write_register, |
| 4460 offset, | 4067 offset, |
| 4461 value, | 4068 value, |
| 4462 temp, | 4069 temp, |
| 4463 GetSaveFPRegsMode(isolate()), | 4070 kSaveFPRegs, |
| 4464 EMIT_REMEMBERED_SET, | 4071 EMIT_REMEMBERED_SET, |
| 4465 check_needed); | 4072 check_needed); |
| 4466 } | 4073 } |
| 4467 } | 4074 } |
| 4468 | 4075 |
| 4469 | 4076 |
| 4470 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { | 4077 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { |
| 4471 ASSERT(ToRegister(instr->context()).is(esi)); | 4078 ASSERT(ToRegister(instr->context()).is(esi)); |
| 4472 ASSERT(ToRegister(instr->object()).is(edx)); | 4079 ASSERT(ToRegister(instr->object()).is(edx)); |
| 4473 ASSERT(ToRegister(instr->value()).is(eax)); | 4080 ASSERT(ToRegister(instr->value()).is(eax)); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4513 } | 4120 } |
| 4514 Operand operand(BuildFastArrayOperand( | 4121 Operand operand(BuildFastArrayOperand( |
| 4515 instr->elements(), | 4122 instr->elements(), |
| 4516 key, | 4123 key, |
| 4517 instr->hydrogen()->key()->representation(), | 4124 instr->hydrogen()->key()->representation(), |
| 4518 elements_kind, | 4125 elements_kind, |
| 4519 0, | 4126 0, |
| 4520 instr->additional_index())); | 4127 instr->additional_index())); |
| 4521 if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS || | 4128 if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS || |
| 4522 elements_kind == FLOAT32_ELEMENTS) { | 4129 elements_kind == FLOAT32_ELEMENTS) { |
| 4523 if (CpuFeatures::IsSafeForSnapshot(isolate(), SSE2)) { | 4130 XMMRegister xmm_scratch = double_scratch0(); |
| 4524 CpuFeatureScope scope(masm(), SSE2); | 4131 __ cvtsd2ss(xmm_scratch, ToDoubleRegister(instr->value())); |
| 4525 XMMRegister xmm_scratch = double_scratch0(); | 4132 __ movss(operand, xmm_scratch); |
| 4526 __ cvtsd2ss(xmm_scratch, ToDoubleRegister(instr->value())); | |
| 4527 __ movss(operand, xmm_scratch); | |
| 4528 } else { | |
| 4529 __ fld(0); | |
| 4530 __ fstp_s(operand); | |
| 4531 } | |
| 4532 } else if (elements_kind == EXTERNAL_FLOAT64_ELEMENTS || | 4133 } else if (elements_kind == EXTERNAL_FLOAT64_ELEMENTS || |
| 4533 elements_kind == FLOAT64_ELEMENTS) { | 4134 elements_kind == FLOAT64_ELEMENTS) { |
| 4534 if (CpuFeatures::IsSafeForSnapshot(isolate(), SSE2)) { | 4135 __ movsd(operand, ToDoubleRegister(instr->value())); |
| 4535 CpuFeatureScope scope(masm(), SSE2); | |
| 4536 __ movsd(operand, ToDoubleRegister(instr->value())); | |
| 4537 } else { | |
| 4538 X87Mov(operand, ToX87Register(instr->value())); | |
| 4539 } | |
| 4540 } else { | 4136 } else { |
| 4541 Register value = ToRegister(instr->value()); | 4137 Register value = ToRegister(instr->value()); |
| 4542 switch (elements_kind) { | 4138 switch (elements_kind) { |
| 4543 case EXTERNAL_UINT8_CLAMPED_ELEMENTS: | 4139 case EXTERNAL_UINT8_CLAMPED_ELEMENTS: |
| 4544 case EXTERNAL_UINT8_ELEMENTS: | 4140 case EXTERNAL_UINT8_ELEMENTS: |
| 4545 case EXTERNAL_INT8_ELEMENTS: | 4141 case EXTERNAL_INT8_ELEMENTS: |
| 4546 case UINT8_ELEMENTS: | 4142 case UINT8_ELEMENTS: |
| 4547 case INT8_ELEMENTS: | 4143 case INT8_ELEMENTS: |
| 4548 case UINT8_CLAMPED_ELEMENTS: | 4144 case UINT8_CLAMPED_ELEMENTS: |
| 4549 __ mov_b(operand, value); | 4145 __ mov_b(operand, value); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4583 ExternalReference canonical_nan_reference = | 4179 ExternalReference canonical_nan_reference = |
| 4584 ExternalReference::address_of_canonical_non_hole_nan(); | 4180 ExternalReference::address_of_canonical_non_hole_nan(); |
| 4585 Operand double_store_operand = BuildFastArrayOperand( | 4181 Operand double_store_operand = BuildFastArrayOperand( |
| 4586 instr->elements(), | 4182 instr->elements(), |
| 4587 instr->key(), | 4183 instr->key(), |
| 4588 instr->hydrogen()->key()->representation(), | 4184 instr->hydrogen()->key()->representation(), |
| 4589 FAST_DOUBLE_ELEMENTS, | 4185 FAST_DOUBLE_ELEMENTS, |
| 4590 FixedDoubleArray::kHeaderSize - kHeapObjectTag, | 4186 FixedDoubleArray::kHeaderSize - kHeapObjectTag, |
| 4591 instr->additional_index()); | 4187 instr->additional_index()); |
| 4592 | 4188 |
| 4593 if (CpuFeatures::IsSafeForSnapshot(isolate(), SSE2)) { | 4189 XMMRegister value = ToDoubleRegister(instr->value()); |
| 4594 CpuFeatureScope scope(masm(), SSE2); | |
| 4595 XMMRegister value = ToDoubleRegister(instr->value()); | |
| 4596 | 4190 |
| 4597 if (instr->NeedsCanonicalization()) { | 4191 if (instr->NeedsCanonicalization()) { |
| 4598 Label have_value; | 4192 Label have_value; |
| 4599 | 4193 |
| 4600 __ ucomisd(value, value); | 4194 __ ucomisd(value, value); |
| 4601 __ j(parity_odd, &have_value, Label::kNear); // NaN. | 4195 __ j(parity_odd, &have_value, Label::kNear); // NaN. |
| 4602 | 4196 |
| 4603 __ movsd(value, Operand::StaticVariable(canonical_nan_reference)); | 4197 __ movsd(value, Operand::StaticVariable(canonical_nan_reference)); |
| 4604 __ bind(&have_value); | 4198 __ bind(&have_value); |
| 4605 } | 4199 } |
| 4606 | 4200 |
| 4607 __ movsd(double_store_operand, value); | 4201 __ movsd(double_store_operand, value); |
| 4608 } else { | |
| 4609 // Can't use SSE2 in the serializer | |
| 4610 if (instr->hydrogen()->IsConstantHoleStore()) { | |
| 4611 // This means we should store the (double) hole. No floating point | |
| 4612 // registers required. | |
| 4613 double nan_double = FixedDoubleArray::hole_nan_as_double(); | |
| 4614 uint64_t int_val = BitCast<uint64_t, double>(nan_double); | |
| 4615 int32_t lower = static_cast<int32_t>(int_val); | |
| 4616 int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt)); | |
| 4617 | |
| 4618 __ mov(double_store_operand, Immediate(lower)); | |
| 4619 Operand double_store_operand2 = BuildFastArrayOperand( | |
| 4620 instr->elements(), | |
| 4621 instr->key(), | |
| 4622 instr->hydrogen()->key()->representation(), | |
| 4623 FAST_DOUBLE_ELEMENTS, | |
| 4624 FixedDoubleArray::kHeaderSize - kHeapObjectTag + kPointerSize, | |
| 4625 instr->additional_index()); | |
| 4626 __ mov(double_store_operand2, Immediate(upper)); | |
| 4627 } else { | |
| 4628 Label no_special_nan_handling; | |
| 4629 X87Register value = ToX87Register(instr->value()); | |
| 4630 X87Fxch(value); | |
| 4631 | |
| 4632 if (instr->NeedsCanonicalization()) { | |
| 4633 __ fld(0); | |
| 4634 __ fld(0); | |
| 4635 __ FCmp(); | |
| 4636 | |
| 4637 __ j(parity_odd, &no_special_nan_handling, Label::kNear); | |
| 4638 __ sub(esp, Immediate(kDoubleSize)); | |
| 4639 __ fst_d(MemOperand(esp, 0)); | |
| 4640 __ cmp(MemOperand(esp, sizeof(kHoleNanLower32)), | |
| 4641 Immediate(kHoleNanUpper32)); | |
| 4642 __ add(esp, Immediate(kDoubleSize)); | |
| 4643 Label canonicalize; | |
| 4644 __ j(not_equal, &canonicalize, Label::kNear); | |
| 4645 __ jmp(&no_special_nan_handling, Label::kNear); | |
| 4646 __ bind(&canonicalize); | |
| 4647 __ fstp(0); | |
| 4648 __ fld_d(Operand::StaticVariable(canonical_nan_reference)); | |
| 4649 } | |
| 4650 | |
| 4651 __ bind(&no_special_nan_handling); | |
| 4652 __ fst_d(double_store_operand); | |
| 4653 } | |
| 4654 } | |
| 4655 } | 4202 } |
| 4656 | 4203 |
| 4657 | 4204 |
| 4658 void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) { | 4205 void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) { |
| 4659 Register elements = ToRegister(instr->elements()); | 4206 Register elements = ToRegister(instr->elements()); |
| 4660 Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg; | 4207 Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg; |
| 4661 | 4208 |
| 4662 Operand operand = BuildFastArrayOperand( | 4209 Operand operand = BuildFastArrayOperand( |
| 4663 instr->elements(), | 4210 instr->elements(), |
| 4664 instr->key(), | 4211 instr->key(), |
| (...skipping 20 matching lines...) Expand all Loading... |
| 4685 Register value = ToRegister(instr->value()); | 4232 Register value = ToRegister(instr->value()); |
| 4686 ASSERT(!instr->key()->IsConstantOperand()); | 4233 ASSERT(!instr->key()->IsConstantOperand()); |
| 4687 SmiCheck check_needed = | 4234 SmiCheck check_needed = |
| 4688 instr->hydrogen()->value()->IsHeapObject() | 4235 instr->hydrogen()->value()->IsHeapObject() |
| 4689 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; | 4236 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
| 4690 // Compute address of modified element and store it into key register. | 4237 // Compute address of modified element and store it into key register. |
| 4691 __ lea(key, operand); | 4238 __ lea(key, operand); |
| 4692 __ RecordWrite(elements, | 4239 __ RecordWrite(elements, |
| 4693 key, | 4240 key, |
| 4694 value, | 4241 value, |
| 4695 GetSaveFPRegsMode(isolate()), | 4242 kSaveFPRegs, |
| 4696 EMIT_REMEMBERED_SET, | 4243 EMIT_REMEMBERED_SET, |
| 4697 check_needed); | 4244 check_needed); |
| 4698 } | 4245 } |
| 4699 } | 4246 } |
| 4700 | 4247 |
| 4701 | 4248 |
| 4702 void LCodeGen::DoStoreKeyed(LStoreKeyed* instr) { | 4249 void LCodeGen::DoStoreKeyed(LStoreKeyed* instr) { |
| 4703 // By cases...external, fast-double, fast | 4250 // By cases...external, fast-double, fast |
| 4704 if (instr->is_typed_elements()) { | 4251 if (instr->is_typed_elements()) { |
| 4705 DoStoreKeyedExternalArray(instr); | 4252 DoStoreKeyedExternalArray(instr); |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4779 ASSERT(ToRegister(instr->result()).is(eax)); | 4326 ASSERT(ToRegister(instr->result()).is(eax)); |
| 4780 ArrayShiftStub stub(isolate(), instr->hydrogen()->kind()); | 4327 ArrayShiftStub stub(isolate(), instr->hydrogen()->kind()); |
| 4781 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 4328 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 4782 } | 4329 } |
| 4783 | 4330 |
| 4784 | 4331 |
| 4785 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { | 4332 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { |
| 4786 class DeferredStringCharCodeAt V8_FINAL : public LDeferredCode { | 4333 class DeferredStringCharCodeAt V8_FINAL : public LDeferredCode { |
| 4787 public: | 4334 public: |
| 4788 DeferredStringCharCodeAt(LCodeGen* codegen, | 4335 DeferredStringCharCodeAt(LCodeGen* codegen, |
| 4789 LStringCharCodeAt* instr, | 4336 LStringCharCodeAt* instr) |
| 4790 const X87Stack& x87_stack) | 4337 : LDeferredCode(codegen), instr_(instr) { } |
| 4791 : LDeferredCode(codegen, x87_stack), instr_(instr) { } | |
| 4792 virtual void Generate() V8_OVERRIDE { | 4338 virtual void Generate() V8_OVERRIDE { |
| 4793 codegen()->DoDeferredStringCharCodeAt(instr_); | 4339 codegen()->DoDeferredStringCharCodeAt(instr_); |
| 4794 } | 4340 } |
| 4795 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } | 4341 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
| 4796 private: | 4342 private: |
| 4797 LStringCharCodeAt* instr_; | 4343 LStringCharCodeAt* instr_; |
| 4798 }; | 4344 }; |
| 4799 | 4345 |
| 4800 DeferredStringCharCodeAt* deferred = | 4346 DeferredStringCharCodeAt* deferred = |
| 4801 new(zone()) DeferredStringCharCodeAt(this, instr, x87_stack_); | 4347 new(zone()) DeferredStringCharCodeAt(this, instr); |
| 4802 | 4348 |
| 4803 StringCharLoadGenerator::Generate(masm(), | 4349 StringCharLoadGenerator::Generate(masm(), |
| 4804 factory(), | 4350 factory(), |
| 4805 ToRegister(instr->string()), | 4351 ToRegister(instr->string()), |
| 4806 ToRegister(instr->index()), | 4352 ToRegister(instr->index()), |
| 4807 ToRegister(instr->result()), | 4353 ToRegister(instr->result()), |
| 4808 deferred->entry()); | 4354 deferred->entry()); |
| 4809 __ bind(deferred->exit()); | 4355 __ bind(deferred->exit()); |
| 4810 } | 4356 } |
| 4811 | 4357 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 4838 __ AssertSmi(eax); | 4384 __ AssertSmi(eax); |
| 4839 __ SmiUntag(eax); | 4385 __ SmiUntag(eax); |
| 4840 __ StoreToSafepointRegisterSlot(result, eax); | 4386 __ StoreToSafepointRegisterSlot(result, eax); |
| 4841 } | 4387 } |
| 4842 | 4388 |
| 4843 | 4389 |
| 4844 void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) { | 4390 void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) { |
| 4845 class DeferredStringCharFromCode V8_FINAL : public LDeferredCode { | 4391 class DeferredStringCharFromCode V8_FINAL : public LDeferredCode { |
| 4846 public: | 4392 public: |
| 4847 DeferredStringCharFromCode(LCodeGen* codegen, | 4393 DeferredStringCharFromCode(LCodeGen* codegen, |
| 4848 LStringCharFromCode* instr, | 4394 LStringCharFromCode* instr) |
| 4849 const X87Stack& x87_stack) | 4395 : LDeferredCode(codegen), instr_(instr) { } |
| 4850 : LDeferredCode(codegen, x87_stack), instr_(instr) { } | |
| 4851 virtual void Generate() V8_OVERRIDE { | 4396 virtual void Generate() V8_OVERRIDE { |
| 4852 codegen()->DoDeferredStringCharFromCode(instr_); | 4397 codegen()->DoDeferredStringCharFromCode(instr_); |
| 4853 } | 4398 } |
| 4854 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } | 4399 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
| 4855 private: | 4400 private: |
| 4856 LStringCharFromCode* instr_; | 4401 LStringCharFromCode* instr_; |
| 4857 }; | 4402 }; |
| 4858 | 4403 |
| 4859 DeferredStringCharFromCode* deferred = | 4404 DeferredStringCharFromCode* deferred = |
| 4860 new(zone()) DeferredStringCharFromCode(this, instr, x87_stack_); | 4405 new(zone()) DeferredStringCharFromCode(this, instr); |
| 4861 | 4406 |
| 4862 ASSERT(instr->hydrogen()->value()->representation().IsInteger32()); | 4407 ASSERT(instr->hydrogen()->value()->representation().IsInteger32()); |
| 4863 Register char_code = ToRegister(instr->char_code()); | 4408 Register char_code = ToRegister(instr->char_code()); |
| 4864 Register result = ToRegister(instr->result()); | 4409 Register result = ToRegister(instr->result()); |
| 4865 ASSERT(!char_code.is(result)); | 4410 ASSERT(!char_code.is(result)); |
| 4866 | 4411 |
| 4867 __ cmp(char_code, String::kMaxOneByteCharCode); | 4412 __ cmp(char_code, String::kMaxOneByteCharCode); |
| 4868 __ j(above, deferred->entry()); | 4413 __ j(above, deferred->entry()); |
| 4869 __ Move(result, Immediate(factory()->single_character_string_cache())); | 4414 __ Move(result, Immediate(factory()->single_character_string_cache())); |
| 4870 __ mov(result, FieldOperand(result, | 4415 __ mov(result, FieldOperand(result, |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4902 instr->hydrogen()->pretenure_flag()); | 4447 instr->hydrogen()->pretenure_flag()); |
| 4903 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 4448 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 4904 } | 4449 } |
| 4905 | 4450 |
| 4906 | 4451 |
| 4907 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { | 4452 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { |
| 4908 LOperand* input = instr->value(); | 4453 LOperand* input = instr->value(); |
| 4909 LOperand* output = instr->result(); | 4454 LOperand* output = instr->result(); |
| 4910 ASSERT(input->IsRegister() || input->IsStackSlot()); | 4455 ASSERT(input->IsRegister() || input->IsStackSlot()); |
| 4911 ASSERT(output->IsDoubleRegister()); | 4456 ASSERT(output->IsDoubleRegister()); |
| 4912 if (CpuFeatures::IsSupported(SSE2)) { | 4457 __ Cvtsi2sd(ToDoubleRegister(output), ToOperand(input)); |
| 4913 CpuFeatureScope scope(masm(), SSE2); | |
| 4914 __ Cvtsi2sd(ToDoubleRegister(output), ToOperand(input)); | |
| 4915 } else if (input->IsRegister()) { | |
| 4916 Register input_reg = ToRegister(input); | |
| 4917 __ push(input_reg); | |
| 4918 X87Mov(ToX87Register(output), Operand(esp, 0), kX87IntOperand); | |
| 4919 __ pop(input_reg); | |
| 4920 } else { | |
| 4921 X87Mov(ToX87Register(output), ToOperand(input), kX87IntOperand); | |
| 4922 } | |
| 4923 } | 4458 } |
| 4924 | 4459 |
| 4925 | 4460 |
| 4926 void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) { | 4461 void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) { |
| 4927 LOperand* input = instr->value(); | 4462 LOperand* input = instr->value(); |
| 4928 LOperand* output = instr->result(); | 4463 LOperand* output = instr->result(); |
| 4929 if (CpuFeatures::IsSupported(SSE2)) { | 4464 LOperand* temp = instr->temp(); |
| 4930 CpuFeatureScope scope(masm(), SSE2); | 4465 __ LoadUint32(ToDoubleRegister(output), |
| 4931 LOperand* temp = instr->temp(); | 4466 ToRegister(input), |
| 4932 | 4467 ToDoubleRegister(temp)); |
| 4933 __ LoadUint32(ToDoubleRegister(output), | |
| 4934 ToRegister(input), | |
| 4935 ToDoubleRegister(temp)); | |
| 4936 } else { | |
| 4937 X87Register res = ToX87Register(output); | |
| 4938 X87PrepareToWrite(res); | |
| 4939 __ LoadUint32NoSSE2(ToRegister(input)); | |
| 4940 X87CommitWrite(res); | |
| 4941 } | |
| 4942 } | 4468 } |
| 4943 | 4469 |
| 4944 | 4470 |
| 4945 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { | 4471 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { |
| 4946 class DeferredNumberTagI V8_FINAL : public LDeferredCode { | 4472 class DeferredNumberTagI V8_FINAL : public LDeferredCode { |
| 4947 public: | 4473 public: |
| 4948 DeferredNumberTagI(LCodeGen* codegen, | 4474 DeferredNumberTagI(LCodeGen* codegen, |
| 4949 LNumberTagI* instr, | 4475 LNumberTagI* instr) |
| 4950 const X87Stack& x87_stack) | 4476 : LDeferredCode(codegen), instr_(instr) { } |
| 4951 : LDeferredCode(codegen, x87_stack), instr_(instr) { } | |
| 4952 virtual void Generate() V8_OVERRIDE { | 4477 virtual void Generate() V8_OVERRIDE { |
| 4953 codegen()->DoDeferredNumberTagIU(instr_, instr_->value(), instr_->temp(), | 4478 codegen()->DoDeferredNumberTagIU(instr_, instr_->value(), instr_->temp(), |
| 4954 NULL, SIGNED_INT32); | 4479 NULL, SIGNED_INT32); |
| 4955 } | 4480 } |
| 4956 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } | 4481 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
| 4957 private: | 4482 private: |
| 4958 LNumberTagI* instr_; | 4483 LNumberTagI* instr_; |
| 4959 }; | 4484 }; |
| 4960 | 4485 |
| 4961 LOperand* input = instr->value(); | 4486 LOperand* input = instr->value(); |
| 4962 ASSERT(input->IsRegister() && input->Equals(instr->result())); | 4487 ASSERT(input->IsRegister() && input->Equals(instr->result())); |
| 4963 Register reg = ToRegister(input); | 4488 Register reg = ToRegister(input); |
| 4964 | 4489 |
| 4965 DeferredNumberTagI* deferred = | 4490 DeferredNumberTagI* deferred = |
| 4966 new(zone()) DeferredNumberTagI(this, instr, x87_stack_); | 4491 new(zone()) DeferredNumberTagI(this, instr); |
| 4967 __ SmiTag(reg); | 4492 __ SmiTag(reg); |
| 4968 __ j(overflow, deferred->entry()); | 4493 __ j(overflow, deferred->entry()); |
| 4969 __ bind(deferred->exit()); | 4494 __ bind(deferred->exit()); |
| 4970 } | 4495 } |
| 4971 | 4496 |
| 4972 | 4497 |
| 4973 void LCodeGen::DoNumberTagU(LNumberTagU* instr) { | 4498 void LCodeGen::DoNumberTagU(LNumberTagU* instr) { |
| 4974 class DeferredNumberTagU V8_FINAL : public LDeferredCode { | 4499 class DeferredNumberTagU V8_FINAL : public LDeferredCode { |
| 4975 public: | 4500 public: |
| 4976 DeferredNumberTagU(LCodeGen* codegen, | 4501 DeferredNumberTagU(LCodeGen* codegen, LNumberTagU* instr) |
| 4977 LNumberTagU* instr, | 4502 : LDeferredCode(codegen), instr_(instr) { } |
| 4978 const X87Stack& x87_stack) | |
| 4979 : LDeferredCode(codegen, x87_stack), instr_(instr) { } | |
| 4980 virtual void Generate() V8_OVERRIDE { | 4503 virtual void Generate() V8_OVERRIDE { |
| 4981 codegen()->DoDeferredNumberTagIU(instr_, instr_->value(), instr_->temp1(), | 4504 codegen()->DoDeferredNumberTagIU(instr_, instr_->value(), instr_->temp1(), |
| 4982 instr_->temp2(), UNSIGNED_INT32); | 4505 instr_->temp2(), UNSIGNED_INT32); |
| 4983 } | 4506 } |
| 4984 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } | 4507 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
| 4985 private: | 4508 private: |
| 4986 LNumberTagU* instr_; | 4509 LNumberTagU* instr_; |
| 4987 }; | 4510 }; |
| 4988 | 4511 |
| 4989 LOperand* input = instr->value(); | 4512 LOperand* input = instr->value(); |
| 4990 ASSERT(input->IsRegister() && input->Equals(instr->result())); | 4513 ASSERT(input->IsRegister() && input->Equals(instr->result())); |
| 4991 Register reg = ToRegister(input); | 4514 Register reg = ToRegister(input); |
| 4992 | 4515 |
| 4993 DeferredNumberTagU* deferred = | 4516 DeferredNumberTagU* deferred = |
| 4994 new(zone()) DeferredNumberTagU(this, instr, x87_stack_); | 4517 new(zone()) DeferredNumberTagU(this, instr); |
| 4995 __ cmp(reg, Immediate(Smi::kMaxValue)); | 4518 __ cmp(reg, Immediate(Smi::kMaxValue)); |
| 4996 __ j(above, deferred->entry()); | 4519 __ j(above, deferred->entry()); |
| 4997 __ SmiTag(reg); | 4520 __ SmiTag(reg); |
| 4998 __ bind(deferred->exit()); | 4521 __ bind(deferred->exit()); |
| 4999 } | 4522 } |
| 5000 | 4523 |
| 5001 | 4524 |
| 5002 void LCodeGen::DoDeferredNumberTagIU(LInstruction* instr, | 4525 void LCodeGen::DoDeferredNumberTagIU(LInstruction* instr, |
| 5003 LOperand* value, | 4526 LOperand* value, |
| 5004 LOperand* temp1, | 4527 LOperand* temp1, |
| 5005 LOperand* temp2, | 4528 LOperand* temp2, |
| 5006 IntegerSignedness signedness) { | 4529 IntegerSignedness signedness) { |
| 5007 Label done, slow; | 4530 Label done, slow; |
| 5008 Register reg = ToRegister(value); | 4531 Register reg = ToRegister(value); |
| 5009 Register tmp = ToRegister(temp1); | 4532 Register tmp = ToRegister(temp1); |
| 5010 XMMRegister xmm_scratch = double_scratch0(); | 4533 XMMRegister xmm_scratch = double_scratch0(); |
| 5011 | 4534 |
| 5012 if (signedness == SIGNED_INT32) { | 4535 if (signedness == SIGNED_INT32) { |
| 5013 // There was overflow, so bits 30 and 31 of the original integer | 4536 // There was overflow, so bits 30 and 31 of the original integer |
| 5014 // disagree. Try to allocate a heap number in new space and store | 4537 // disagree. Try to allocate a heap number in new space and store |
| 5015 // the value in there. If that fails, call the runtime system. | 4538 // the value in there. If that fails, call the runtime system. |
| 5016 __ SmiUntag(reg); | 4539 __ SmiUntag(reg); |
| 5017 __ xor_(reg, 0x80000000); | 4540 __ xor_(reg, 0x80000000); |
| 5018 if (CpuFeatures::IsSupported(SSE2)) { | 4541 __ Cvtsi2sd(xmm_scratch, Operand(reg)); |
| 5019 CpuFeatureScope feature_scope(masm(), SSE2); | |
| 5020 __ Cvtsi2sd(xmm_scratch, Operand(reg)); | |
| 5021 } else { | |
| 5022 __ push(reg); | |
| 5023 __ fild_s(Operand(esp, 0)); | |
| 5024 __ pop(reg); | |
| 5025 } | |
| 5026 } else { | 4542 } else { |
| 5027 if (CpuFeatures::IsSupported(SSE2)) { | 4543 __ LoadUint32(xmm_scratch, reg, ToDoubleRegister(temp2)); |
| 5028 CpuFeatureScope feature_scope(masm(), SSE2); | |
| 5029 __ LoadUint32(xmm_scratch, reg, ToDoubleRegister(temp2)); | |
| 5030 } else { | |
| 5031 // There's no fild variant for unsigned values, so zero-extend to a 64-bit | |
| 5032 // int manually. | |
| 5033 __ push(Immediate(0)); | |
| 5034 __ push(reg); | |
| 5035 __ fild_d(Operand(esp, 0)); | |
| 5036 __ pop(reg); | |
| 5037 __ pop(reg); | |
| 5038 } | |
| 5039 } | 4544 } |
| 5040 | 4545 |
| 5041 if (FLAG_inline_new) { | 4546 if (FLAG_inline_new) { |
| 5042 __ AllocateHeapNumber(reg, tmp, no_reg, &slow); | 4547 __ AllocateHeapNumber(reg, tmp, no_reg, &slow); |
| 5043 __ jmp(&done, Label::kNear); | 4548 __ jmp(&done, Label::kNear); |
| 5044 } | 4549 } |
| 5045 | 4550 |
| 5046 // Slow case: Call the runtime system to do the number allocation. | 4551 // Slow case: Call the runtime system to do the number allocation. |
| 5047 __ bind(&slow); | 4552 __ bind(&slow); |
| 5048 { | 4553 { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 5062 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 4567 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 5063 __ CallRuntimeSaveDoubles(Runtime::kHiddenAllocateHeapNumber); | 4568 __ CallRuntimeSaveDoubles(Runtime::kHiddenAllocateHeapNumber); |
| 5064 RecordSafepointWithRegisters( | 4569 RecordSafepointWithRegisters( |
| 5065 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); | 4570 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); |
| 5066 __ StoreToSafepointRegisterSlot(reg, eax); | 4571 __ StoreToSafepointRegisterSlot(reg, eax); |
| 5067 } | 4572 } |
| 5068 | 4573 |
| 5069 // Done. Put the value in xmm_scratch into the value of the allocated heap | 4574 // Done. Put the value in xmm_scratch into the value of the allocated heap |
| 5070 // number. | 4575 // number. |
| 5071 __ bind(&done); | 4576 __ bind(&done); |
| 5072 if (CpuFeatures::IsSupported(SSE2)) { | 4577 __ movsd(FieldOperand(reg, HeapNumber::kValueOffset), xmm_scratch); |
| 5073 CpuFeatureScope feature_scope(masm(), SSE2); | |
| 5074 __ movsd(FieldOperand(reg, HeapNumber::kValueOffset), xmm_scratch); | |
| 5075 } else { | |
| 5076 __ fstp_d(FieldOperand(reg, HeapNumber::kValueOffset)); | |
| 5077 } | |
| 5078 } | 4578 } |
| 5079 | 4579 |
| 5080 | 4580 |
| 5081 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { | 4581 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { |
| 5082 class DeferredNumberTagD V8_FINAL : public LDeferredCode { | 4582 class DeferredNumberTagD V8_FINAL : public LDeferredCode { |
| 5083 public: | 4583 public: |
| 5084 DeferredNumberTagD(LCodeGen* codegen, | 4584 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) |
| 5085 LNumberTagD* instr, | 4585 : LDeferredCode(codegen), instr_(instr) { } |
| 5086 const X87Stack& x87_stack) | |
| 5087 : LDeferredCode(codegen, x87_stack), instr_(instr) { } | |
| 5088 virtual void Generate() V8_OVERRIDE { | 4586 virtual void Generate() V8_OVERRIDE { |
| 5089 codegen()->DoDeferredNumberTagD(instr_); | 4587 codegen()->DoDeferredNumberTagD(instr_); |
| 5090 } | 4588 } |
| 5091 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } | 4589 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
| 5092 private: | 4590 private: |
| 5093 LNumberTagD* instr_; | 4591 LNumberTagD* instr_; |
| 5094 }; | 4592 }; |
| 5095 | 4593 |
| 5096 Register reg = ToRegister(instr->result()); | 4594 Register reg = ToRegister(instr->result()); |
| 5097 | 4595 |
| 5098 bool use_sse2 = CpuFeatures::IsSupported(SSE2); | |
| 5099 if (!use_sse2) { | |
| 5100 // Put the value to the top of stack | |
| 5101 X87Register src = ToX87Register(instr->value()); | |
| 5102 X87LoadForUsage(src); | |
| 5103 } | |
| 5104 | |
| 5105 DeferredNumberTagD* deferred = | 4596 DeferredNumberTagD* deferred = |
| 5106 new(zone()) DeferredNumberTagD(this, instr, x87_stack_); | 4597 new(zone()) DeferredNumberTagD(this, instr); |
| 5107 if (FLAG_inline_new) { | 4598 if (FLAG_inline_new) { |
| 5108 Register tmp = ToRegister(instr->temp()); | 4599 Register tmp = ToRegister(instr->temp()); |
| 5109 __ AllocateHeapNumber(reg, tmp, no_reg, deferred->entry()); | 4600 __ AllocateHeapNumber(reg, tmp, no_reg, deferred->entry()); |
| 5110 } else { | 4601 } else { |
| 5111 __ jmp(deferred->entry()); | 4602 __ jmp(deferred->entry()); |
| 5112 } | 4603 } |
| 5113 __ bind(deferred->exit()); | 4604 __ bind(deferred->exit()); |
| 5114 if (use_sse2) { | 4605 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
| 5115 CpuFeatureScope scope(masm(), SSE2); | 4606 __ movsd(FieldOperand(reg, HeapNumber::kValueOffset), input_reg); |
| 5116 XMMRegister input_reg = ToDoubleRegister(instr->value()); | |
| 5117 __ movsd(FieldOperand(reg, HeapNumber::kValueOffset), input_reg); | |
| 5118 } else { | |
| 5119 __ fstp_d(FieldOperand(reg, HeapNumber::kValueOffset)); | |
| 5120 } | |
| 5121 } | 4607 } |
| 5122 | 4608 |
| 5123 | 4609 |
| 5124 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { | 4610 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { |
| 5125 // TODO(3095996): Get rid of this. For now, we need to make the | 4611 // TODO(3095996): Get rid of this. For now, we need to make the |
| 5126 // result register contain a valid pointer because it is already | 4612 // result register contain a valid pointer because it is already |
| 5127 // contained in the register pointer map. | 4613 // contained in the register pointer map. |
| 5128 Register reg = ToRegister(instr->result()); | 4614 Register reg = ToRegister(instr->result()); |
| 5129 __ Move(reg, Immediate(0)); | 4615 __ Move(reg, Immediate(0)); |
| 5130 | 4616 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5165 if (instr->needs_check()) { | 4651 if (instr->needs_check()) { |
| 5166 __ test(result, Immediate(kSmiTagMask)); | 4652 __ test(result, Immediate(kSmiTagMask)); |
| 5167 DeoptimizeIf(not_zero, instr->environment()); | 4653 DeoptimizeIf(not_zero, instr->environment()); |
| 5168 } else { | 4654 } else { |
| 5169 __ AssertSmi(result); | 4655 __ AssertSmi(result); |
| 5170 } | 4656 } |
| 5171 __ SmiUntag(result); | 4657 __ SmiUntag(result); |
| 5172 } | 4658 } |
| 5173 | 4659 |
| 5174 | 4660 |
| 5175 void LCodeGen::EmitNumberUntagDNoSSE2(Register input_reg, | |
| 5176 Register temp_reg, | |
| 5177 X87Register res_reg, | |
| 5178 bool can_convert_undefined_to_nan, | |
| 5179 bool deoptimize_on_minus_zero, | |
| 5180 LEnvironment* env, | |
| 5181 NumberUntagDMode mode) { | |
| 5182 Label load_smi, done; | |
| 5183 | |
| 5184 X87PrepareToWrite(res_reg); | |
| 5185 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) { | |
| 5186 // Smi check. | |
| 5187 __ JumpIfSmi(input_reg, &load_smi, Label::kNear); | |
| 5188 | |
| 5189 // Heap number map check. | |
| 5190 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), | |
| 5191 factory()->heap_number_map()); | |
| 5192 if (!can_convert_undefined_to_nan) { | |
| 5193 DeoptimizeIf(not_equal, env); | |
| 5194 } else { | |
| 5195 Label heap_number, convert; | |
| 5196 __ j(equal, &heap_number, Label::kNear); | |
| 5197 | |
| 5198 // Convert undefined (or hole) to NaN. | |
| 5199 __ cmp(input_reg, factory()->undefined_value()); | |
| 5200 DeoptimizeIf(not_equal, env); | |
| 5201 | |
| 5202 __ bind(&convert); | |
| 5203 ExternalReference nan = | |
| 5204 ExternalReference::address_of_canonical_non_hole_nan(); | |
| 5205 __ fld_d(Operand::StaticVariable(nan)); | |
| 5206 __ jmp(&done, Label::kNear); | |
| 5207 | |
| 5208 __ bind(&heap_number); | |
| 5209 } | |
| 5210 // Heap number to x87 conversion. | |
| 5211 __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset)); | |
| 5212 if (deoptimize_on_minus_zero) { | |
| 5213 __ fldz(); | |
| 5214 __ FCmp(); | |
| 5215 __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset)); | |
| 5216 __ j(not_zero, &done, Label::kNear); | |
| 5217 | |
| 5218 // Use general purpose registers to check if we have -0.0 | |
| 5219 __ mov(temp_reg, FieldOperand(input_reg, HeapNumber::kExponentOffset)); | |
| 5220 __ test(temp_reg, Immediate(HeapNumber::kSignMask)); | |
| 5221 __ j(zero, &done, Label::kNear); | |
| 5222 | |
| 5223 // Pop FPU stack before deoptimizing. | |
| 5224 __ fstp(0); | |
| 5225 DeoptimizeIf(not_zero, env); | |
| 5226 } | |
| 5227 __ jmp(&done, Label::kNear); | |
| 5228 } else { | |
| 5229 ASSERT(mode == NUMBER_CANDIDATE_IS_SMI); | |
| 5230 } | |
| 5231 | |
| 5232 __ bind(&load_smi); | |
| 5233 // Clobbering a temp is faster than re-tagging the | |
| 5234 // input register since we avoid dependencies. | |
| 5235 __ mov(temp_reg, input_reg); | |
| 5236 __ SmiUntag(temp_reg); // Untag smi before converting to float. | |
| 5237 __ push(temp_reg); | |
| 5238 __ fild_s(Operand(esp, 0)); | |
| 5239 __ add(esp, Immediate(kPointerSize)); | |
| 5240 __ bind(&done); | |
| 5241 X87CommitWrite(res_reg); | |
| 5242 } | |
| 5243 | |
| 5244 | |
| 5245 void LCodeGen::EmitNumberUntagD(Register input_reg, | 4661 void LCodeGen::EmitNumberUntagD(Register input_reg, |
| 5246 Register temp_reg, | 4662 Register temp_reg, |
| 5247 XMMRegister result_reg, | 4663 XMMRegister result_reg, |
| 5248 bool can_convert_undefined_to_nan, | 4664 bool can_convert_undefined_to_nan, |
| 5249 bool deoptimize_on_minus_zero, | 4665 bool deoptimize_on_minus_zero, |
| 5250 LEnvironment* env, | 4666 LEnvironment* env, |
| 5251 NumberUntagDMode mode) { | 4667 NumberUntagDMode mode) { |
| 5252 Label convert, load_smi, done; | 4668 Label convert, load_smi, done; |
| 5253 | 4669 |
| 5254 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) { | 4670 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) { |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5350 __ jmp(done); | 4766 __ jmp(done); |
| 5351 __ bind(&bailout); | 4767 __ bind(&bailout); |
| 5352 DeoptimizeIf(no_condition, instr->environment()); | 4768 DeoptimizeIf(no_condition, instr->environment()); |
| 5353 } | 4769 } |
| 5354 } | 4770 } |
| 5355 | 4771 |
| 5356 | 4772 |
| 5357 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { | 4773 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { |
| 5358 class DeferredTaggedToI V8_FINAL : public LDeferredCode { | 4774 class DeferredTaggedToI V8_FINAL : public LDeferredCode { |
| 5359 public: | 4775 public: |
| 5360 DeferredTaggedToI(LCodeGen* codegen, | 4776 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) |
| 5361 LTaggedToI* instr, | 4777 : LDeferredCode(codegen), instr_(instr) { } |
| 5362 const X87Stack& x87_stack) | |
| 5363 : LDeferredCode(codegen, x87_stack), instr_(instr) { } | |
| 5364 virtual void Generate() V8_OVERRIDE { | 4778 virtual void Generate() V8_OVERRIDE { |
| 5365 codegen()->DoDeferredTaggedToI(instr_, done()); | 4779 codegen()->DoDeferredTaggedToI(instr_, done()); |
| 5366 } | 4780 } |
| 5367 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } | 4781 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
| 5368 private: | 4782 private: |
| 5369 LTaggedToI* instr_; | 4783 LTaggedToI* instr_; |
| 5370 }; | 4784 }; |
| 5371 | 4785 |
| 5372 LOperand* input = instr->value(); | 4786 LOperand* input = instr->value(); |
| 5373 ASSERT(input->IsRegister()); | 4787 ASSERT(input->IsRegister()); |
| 5374 Register input_reg = ToRegister(input); | 4788 Register input_reg = ToRegister(input); |
| 5375 ASSERT(input_reg.is(ToRegister(instr->result()))); | 4789 ASSERT(input_reg.is(ToRegister(instr->result()))); |
| 5376 | 4790 |
| 5377 if (instr->hydrogen()->value()->representation().IsSmi()) { | 4791 if (instr->hydrogen()->value()->representation().IsSmi()) { |
| 5378 __ SmiUntag(input_reg); | 4792 __ SmiUntag(input_reg); |
| 5379 } else { | 4793 } else { |
| 5380 DeferredTaggedToI* deferred = | 4794 DeferredTaggedToI* deferred = |
| 5381 new(zone()) DeferredTaggedToI(this, instr, x87_stack_); | 4795 new(zone()) DeferredTaggedToI(this, instr); |
| 5382 // Optimistically untag the input. | 4796 // Optimistically untag the input. |
| 5383 // If the input is a HeapObject, SmiUntag will set the carry flag. | 4797 // If the input is a HeapObject, SmiUntag will set the carry flag. |
| 5384 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); | 4798 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); |
| 5385 __ SmiUntag(input_reg); | 4799 __ SmiUntag(input_reg); |
| 5386 // Branch to deferred code if the input was tagged. | 4800 // Branch to deferred code if the input was tagged. |
| 5387 // The deferred code will take care of restoring the tag. | 4801 // The deferred code will take care of restoring the tag. |
| 5388 __ j(carry, deferred->entry()); | 4802 __ j(carry, deferred->entry()); |
| 5389 __ bind(deferred->exit()); | 4803 __ bind(deferred->exit()); |
| 5390 } | 4804 } |
| 5391 } | 4805 } |
| 5392 | 4806 |
| 5393 | 4807 |
| 5394 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { | 4808 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { |
| 5395 LOperand* input = instr->value(); | 4809 LOperand* input = instr->value(); |
| 5396 ASSERT(input->IsRegister()); | 4810 ASSERT(input->IsRegister()); |
| 5397 LOperand* temp = instr->temp(); | 4811 LOperand* temp = instr->temp(); |
| 5398 ASSERT(temp->IsRegister()); | 4812 ASSERT(temp->IsRegister()); |
| 5399 LOperand* result = instr->result(); | 4813 LOperand* result = instr->result(); |
| 5400 ASSERT(result->IsDoubleRegister()); | 4814 ASSERT(result->IsDoubleRegister()); |
| 5401 | 4815 |
| 5402 Register input_reg = ToRegister(input); | 4816 Register input_reg = ToRegister(input); |
| 5403 bool deoptimize_on_minus_zero = | 4817 bool deoptimize_on_minus_zero = |
| 5404 instr->hydrogen()->deoptimize_on_minus_zero(); | 4818 instr->hydrogen()->deoptimize_on_minus_zero(); |
| 5405 Register temp_reg = ToRegister(temp); | 4819 Register temp_reg = ToRegister(temp); |
| 5406 | 4820 |
| 5407 HValue* value = instr->hydrogen()->value(); | 4821 HValue* value = instr->hydrogen()->value(); |
| 5408 NumberUntagDMode mode = value->representation().IsSmi() | 4822 NumberUntagDMode mode = value->representation().IsSmi() |
| 5409 ? NUMBER_CANDIDATE_IS_SMI : NUMBER_CANDIDATE_IS_ANY_TAGGED; | 4823 ? NUMBER_CANDIDATE_IS_SMI : NUMBER_CANDIDATE_IS_ANY_TAGGED; |
| 5410 | 4824 |
| 5411 if (CpuFeatures::IsSupported(SSE2)) { | 4825 XMMRegister result_reg = ToDoubleRegister(result); |
| 5412 CpuFeatureScope scope(masm(), SSE2); | 4826 EmitNumberUntagD(input_reg, |
| 5413 XMMRegister result_reg = ToDoubleRegister(result); | 4827 temp_reg, |
| 5414 EmitNumberUntagD(input_reg, | 4828 result_reg, |
| 5415 temp_reg, | 4829 instr->hydrogen()->can_convert_undefined_to_nan(), |
| 5416 result_reg, | 4830 deoptimize_on_minus_zero, |
| 5417 instr->hydrogen()->can_convert_undefined_to_nan(), | 4831 instr->environment(), |
| 5418 deoptimize_on_minus_zero, | 4832 mode); |
| 5419 instr->environment(), | |
| 5420 mode); | |
| 5421 } else { | |
| 5422 EmitNumberUntagDNoSSE2(input_reg, | |
| 5423 temp_reg, | |
| 5424 ToX87Register(instr->result()), | |
| 5425 instr->hydrogen()->can_convert_undefined_to_nan(), | |
| 5426 deoptimize_on_minus_zero, | |
| 5427 instr->environment(), | |
| 5428 mode); | |
| 5429 } | |
| 5430 } | 4833 } |
| 5431 | 4834 |
| 5432 | 4835 |
| 5433 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { | 4836 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { |
| 5434 LOperand* input = instr->value(); | 4837 LOperand* input = instr->value(); |
| 5435 ASSERT(input->IsDoubleRegister()); | 4838 ASSERT(input->IsDoubleRegister()); |
| 5436 LOperand* result = instr->result(); | 4839 LOperand* result = instr->result(); |
| 5437 ASSERT(result->IsRegister()); | 4840 ASSERT(result->IsRegister()); |
| 5438 Register result_reg = ToRegister(result); | 4841 Register result_reg = ToRegister(result); |
| 5439 | 4842 |
| 5440 if (instr->truncating()) { | 4843 if (instr->truncating()) { |
| 5441 if (CpuFeatures::IsSafeForSnapshot(isolate(), SSE2)) { | 4844 XMMRegister input_reg = ToDoubleRegister(input); |
| 5442 CpuFeatureScope scope(masm(), SSE2); | 4845 __ TruncateDoubleToI(result_reg, input_reg); |
| 5443 XMMRegister input_reg = ToDoubleRegister(input); | |
| 5444 __ TruncateDoubleToI(result_reg, input_reg); | |
| 5445 } else { | |
| 5446 X87Register input_reg = ToX87Register(input); | |
| 5447 X87Fxch(input_reg); | |
| 5448 __ TruncateX87TOSToI(result_reg); | |
| 5449 } | |
| 5450 } else { | 4846 } else { |
| 5451 Label bailout, done; | 4847 Label bailout, done; |
| 5452 if (CpuFeatures::IsSafeForSnapshot(isolate(), SSE2)) { | 4848 XMMRegister input_reg = ToDoubleRegister(input); |
| 5453 CpuFeatureScope scope(masm(), SSE2); | 4849 XMMRegister xmm_scratch = double_scratch0(); |
| 5454 XMMRegister input_reg = ToDoubleRegister(input); | 4850 __ DoubleToI(result_reg, input_reg, xmm_scratch, |
| 5455 XMMRegister xmm_scratch = double_scratch0(); | 4851 instr->hydrogen()->GetMinusZeroMode(), &bailout, Label::kNear); |
| 5456 __ DoubleToI(result_reg, input_reg, xmm_scratch, | |
| 5457 instr->hydrogen()->GetMinusZeroMode(), &bailout, Label::kNear); | |
| 5458 } else { | |
| 5459 X87Register input_reg = ToX87Register(input); | |
| 5460 X87Fxch(input_reg); | |
| 5461 __ X87TOSToI(result_reg, instr->hydrogen()->GetMinusZeroMode(), | |
| 5462 &bailout, Label::kNear); | |
| 5463 } | |
| 5464 __ jmp(&done, Label::kNear); | 4852 __ jmp(&done, Label::kNear); |
| 5465 __ bind(&bailout); | 4853 __ bind(&bailout); |
| 5466 DeoptimizeIf(no_condition, instr->environment()); | 4854 DeoptimizeIf(no_condition, instr->environment()); |
| 5467 __ bind(&done); | 4855 __ bind(&done); |
| 5468 } | 4856 } |
| 5469 } | 4857 } |
| 5470 | 4858 |
| 5471 | 4859 |
| 5472 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) { | 4860 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) { |
| 5473 LOperand* input = instr->value(); | 4861 LOperand* input = instr->value(); |
| 5474 ASSERT(input->IsDoubleRegister()); | 4862 ASSERT(input->IsDoubleRegister()); |
| 5475 LOperand* result = instr->result(); | 4863 LOperand* result = instr->result(); |
| 5476 ASSERT(result->IsRegister()); | 4864 ASSERT(result->IsRegister()); |
| 5477 Register result_reg = ToRegister(result); | 4865 Register result_reg = ToRegister(result); |
| 5478 | 4866 |
| 5479 Label bailout, done; | 4867 Label bailout, done; |
| 5480 if (CpuFeatures::IsSafeForSnapshot(isolate(), SSE2)) { | 4868 XMMRegister input_reg = ToDoubleRegister(input); |
| 5481 CpuFeatureScope scope(masm(), SSE2); | 4869 XMMRegister xmm_scratch = double_scratch0(); |
| 5482 XMMRegister input_reg = ToDoubleRegister(input); | 4870 __ DoubleToI(result_reg, input_reg, xmm_scratch, |
| 5483 XMMRegister xmm_scratch = double_scratch0(); | 4871 instr->hydrogen()->GetMinusZeroMode(), &bailout, Label::kNear); |
| 5484 __ DoubleToI(result_reg, input_reg, xmm_scratch, | |
| 5485 instr->hydrogen()->GetMinusZeroMode(), &bailout, Label::kNear); | |
| 5486 } else { | |
| 5487 X87Register input_reg = ToX87Register(input); | |
| 5488 X87Fxch(input_reg); | |
| 5489 __ X87TOSToI(result_reg, instr->hydrogen()->GetMinusZeroMode(), | |
| 5490 &bailout, Label::kNear); | |
| 5491 } | |
| 5492 __ jmp(&done, Label::kNear); | 4872 __ jmp(&done, Label::kNear); |
| 5493 __ bind(&bailout); | 4873 __ bind(&bailout); |
| 5494 DeoptimizeIf(no_condition, instr->environment()); | 4874 DeoptimizeIf(no_condition, instr->environment()); |
| 5495 __ bind(&done); | 4875 __ bind(&done); |
| 5496 | 4876 |
| 5497 __ SmiTag(result_reg); | 4877 __ SmiTag(result_reg); |
| 5498 DeoptimizeIf(overflow, instr->environment()); | 4878 DeoptimizeIf(overflow, instr->environment()); |
| 5499 } | 4879 } |
| 5500 | 4880 |
| 5501 | 4881 |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5585 | 4965 |
| 5586 __ test(eax, Immediate(kSmiTagMask)); | 4966 __ test(eax, Immediate(kSmiTagMask)); |
| 5587 } | 4967 } |
| 5588 DeoptimizeIf(zero, instr->environment()); | 4968 DeoptimizeIf(zero, instr->environment()); |
| 5589 } | 4969 } |
| 5590 | 4970 |
| 5591 | 4971 |
| 5592 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { | 4972 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { |
| 5593 class DeferredCheckMaps V8_FINAL : public LDeferredCode { | 4973 class DeferredCheckMaps V8_FINAL : public LDeferredCode { |
| 5594 public: | 4974 public: |
| 5595 DeferredCheckMaps(LCodeGen* codegen, | 4975 DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr, Register object) |
| 5596 LCheckMaps* instr, | 4976 : LDeferredCode(codegen), instr_(instr), object_(object) { |
| 5597 Register object, | |
| 5598 const X87Stack& x87_stack) | |
| 5599 : LDeferredCode(codegen, x87_stack), instr_(instr), object_(object) { | |
| 5600 SetExit(check_maps()); | 4977 SetExit(check_maps()); |
| 5601 } | 4978 } |
| 5602 virtual void Generate() V8_OVERRIDE { | 4979 virtual void Generate() V8_OVERRIDE { |
| 5603 codegen()->DoDeferredInstanceMigration(instr_, object_); | 4980 codegen()->DoDeferredInstanceMigration(instr_, object_); |
| 5604 } | 4981 } |
| 5605 Label* check_maps() { return &check_maps_; } | 4982 Label* check_maps() { return &check_maps_; } |
| 5606 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } | 4983 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
| 5607 private: | 4984 private: |
| 5608 LCheckMaps* instr_; | 4985 LCheckMaps* instr_; |
| 5609 Label check_maps_; | 4986 Label check_maps_; |
| 5610 Register object_; | 4987 Register object_; |
| 5611 }; | 4988 }; |
| 5612 | 4989 |
| 5613 if (instr->hydrogen()->IsStabilityCheck()) { | 4990 if (instr->hydrogen()->IsStabilityCheck()) { |
| 5614 const UniqueSet<Map>* maps = instr->hydrogen()->maps(); | 4991 const UniqueSet<Map>* maps = instr->hydrogen()->maps(); |
| 5615 for (int i = 0; i < maps->size(); ++i) { | 4992 for (int i = 0; i < maps->size(); ++i) { |
| 5616 AddStabilityDependency(maps->at(i).handle()); | 4993 AddStabilityDependency(maps->at(i).handle()); |
| 5617 } | 4994 } |
| 5618 return; | 4995 return; |
| 5619 } | 4996 } |
| 5620 | 4997 |
| 5621 LOperand* input = instr->value(); | 4998 LOperand* input = instr->value(); |
| 5622 ASSERT(input->IsRegister()); | 4999 ASSERT(input->IsRegister()); |
| 5623 Register reg = ToRegister(input); | 5000 Register reg = ToRegister(input); |
| 5624 | 5001 |
| 5625 DeferredCheckMaps* deferred = NULL; | 5002 DeferredCheckMaps* deferred = NULL; |
| 5626 if (instr->hydrogen()->HasMigrationTarget()) { | 5003 if (instr->hydrogen()->HasMigrationTarget()) { |
| 5627 deferred = new(zone()) DeferredCheckMaps(this, instr, reg, x87_stack_); | 5004 deferred = new(zone()) DeferredCheckMaps(this, instr, reg); |
| 5628 __ bind(deferred->check_maps()); | 5005 __ bind(deferred->check_maps()); |
| 5629 } | 5006 } |
| 5630 | 5007 |
| 5631 const UniqueSet<Map>* maps = instr->hydrogen()->maps(); | 5008 const UniqueSet<Map>* maps = instr->hydrogen()->maps(); |
| 5632 Label success; | 5009 Label success; |
| 5633 for (int i = 0; i < maps->size() - 1; i++) { | 5010 for (int i = 0; i < maps->size() - 1; i++) { |
| 5634 Handle<Map> map = maps->at(i).handle(); | 5011 Handle<Map> map = maps->at(i).handle(); |
| 5635 __ CompareMap(reg, map); | 5012 __ CompareMap(reg, map); |
| 5636 __ j(equal, &success, Label::kNear); | 5013 __ j(equal, &success, Label::kNear); |
| 5637 } | 5014 } |
| 5638 | 5015 |
| 5639 Handle<Map> map = maps->at(maps->size() - 1).handle(); | 5016 Handle<Map> map = maps->at(maps->size() - 1).handle(); |
| 5640 __ CompareMap(reg, map); | 5017 __ CompareMap(reg, map); |
| 5641 if (instr->hydrogen()->HasMigrationTarget()) { | 5018 if (instr->hydrogen()->HasMigrationTarget()) { |
| 5642 __ j(not_equal, deferred->entry()); | 5019 __ j(not_equal, deferred->entry()); |
| 5643 } else { | 5020 } else { |
| 5644 DeoptimizeIf(not_equal, instr->environment()); | 5021 DeoptimizeIf(not_equal, instr->environment()); |
| 5645 } | 5022 } |
| 5646 | 5023 |
| 5647 __ bind(&success); | 5024 __ bind(&success); |
| 5648 } | 5025 } |
| 5649 | 5026 |
| 5650 | 5027 |
| 5651 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { | 5028 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { |
| 5652 CpuFeatureScope scope(masm(), SSE2); | |
| 5653 XMMRegister value_reg = ToDoubleRegister(instr->unclamped()); | 5029 XMMRegister value_reg = ToDoubleRegister(instr->unclamped()); |
| 5654 XMMRegister xmm_scratch = double_scratch0(); | 5030 XMMRegister xmm_scratch = double_scratch0(); |
| 5655 Register result_reg = ToRegister(instr->result()); | 5031 Register result_reg = ToRegister(instr->result()); |
| 5656 __ ClampDoubleToUint8(value_reg, xmm_scratch, result_reg); | 5032 __ ClampDoubleToUint8(value_reg, xmm_scratch, result_reg); |
| 5657 } | 5033 } |
| 5658 | 5034 |
| 5659 | 5035 |
| 5660 void LCodeGen::DoClampIToUint8(LClampIToUint8* instr) { | 5036 void LCodeGen::DoClampIToUint8(LClampIToUint8* instr) { |
| 5661 ASSERT(instr->unclamped()->Equals(instr->result())); | 5037 ASSERT(instr->unclamped()->Equals(instr->result())); |
| 5662 Register value_reg = ToRegister(instr->result()); | 5038 Register value_reg = ToRegister(instr->result()); |
| 5663 __ ClampUint8(value_reg); | 5039 __ ClampUint8(value_reg); |
| 5664 } | 5040 } |
| 5665 | 5041 |
| 5666 | 5042 |
| 5667 void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) { | 5043 void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) { |
| 5668 CpuFeatureScope scope(masm(), SSE2); | |
| 5669 | |
| 5670 ASSERT(instr->unclamped()->Equals(instr->result())); | 5044 ASSERT(instr->unclamped()->Equals(instr->result())); |
| 5671 Register input_reg = ToRegister(instr->unclamped()); | 5045 Register input_reg = ToRegister(instr->unclamped()); |
| 5672 XMMRegister temp_xmm_reg = ToDoubleRegister(instr->temp_xmm()); | 5046 XMMRegister temp_xmm_reg = ToDoubleRegister(instr->temp_xmm()); |
| 5673 XMMRegister xmm_scratch = double_scratch0(); | 5047 XMMRegister xmm_scratch = double_scratch0(); |
| 5674 Label is_smi, done, heap_number; | 5048 Label is_smi, done, heap_number; |
| 5675 | 5049 |
| 5676 __ JumpIfSmi(input_reg, &is_smi); | 5050 __ JumpIfSmi(input_reg, &is_smi); |
| 5677 | 5051 |
| 5678 // Check for heap number | 5052 // Check for heap number |
| 5679 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), | 5053 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), |
| (...skipping 14 matching lines...) Expand all Loading... |
| 5694 __ jmp(&done, Label::kNear); | 5068 __ jmp(&done, Label::kNear); |
| 5695 | 5069 |
| 5696 // smi | 5070 // smi |
| 5697 __ bind(&is_smi); | 5071 __ bind(&is_smi); |
| 5698 __ SmiUntag(input_reg); | 5072 __ SmiUntag(input_reg); |
| 5699 __ ClampUint8(input_reg); | 5073 __ ClampUint8(input_reg); |
| 5700 __ bind(&done); | 5074 __ bind(&done); |
| 5701 } | 5075 } |
| 5702 | 5076 |
| 5703 | 5077 |
| 5704 void LCodeGen::DoClampTToUint8NoSSE2(LClampTToUint8NoSSE2* instr) { | |
| 5705 Register input_reg = ToRegister(instr->unclamped()); | |
| 5706 Register result_reg = ToRegister(instr->result()); | |
| 5707 Register scratch = ToRegister(instr->scratch()); | |
| 5708 Register scratch2 = ToRegister(instr->scratch2()); | |
| 5709 Register scratch3 = ToRegister(instr->scratch3()); | |
| 5710 Label is_smi, done, heap_number, valid_exponent, | |
| 5711 largest_value, zero_result, maybe_nan_or_infinity; | |
| 5712 | |
| 5713 __ JumpIfSmi(input_reg, &is_smi); | |
| 5714 | |
| 5715 // Check for heap number | |
| 5716 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), | |
| 5717 factory()->heap_number_map()); | |
| 5718 __ j(equal, &heap_number, Label::kNear); | |
| 5719 | |
| 5720 // Check for undefined. Undefined is converted to zero for clamping | |
| 5721 // conversions. | |
| 5722 __ cmp(input_reg, factory()->undefined_value()); | |
| 5723 DeoptimizeIf(not_equal, instr->environment()); | |
| 5724 __ jmp(&zero_result, Label::kNear); | |
| 5725 | |
| 5726 // Heap number | |
| 5727 __ bind(&heap_number); | |
| 5728 | |
| 5729 // Surprisingly, all of the hand-crafted bit-manipulations below are much | |
| 5730 // faster than the x86 FPU built-in instruction, especially since "banker's | |
| 5731 // rounding" would be additionally very expensive | |
| 5732 | |
| 5733 // Get exponent word. | |
| 5734 __ mov(scratch, FieldOperand(input_reg, HeapNumber::kExponentOffset)); | |
| 5735 __ mov(scratch3, FieldOperand(input_reg, HeapNumber::kMantissaOffset)); | |
| 5736 | |
| 5737 // Test for negative values --> clamp to zero | |
| 5738 __ test(scratch, scratch); | |
| 5739 __ j(negative, &zero_result, Label::kNear); | |
| 5740 | |
| 5741 // Get exponent alone in scratch2. | |
| 5742 __ mov(scratch2, scratch); | |
| 5743 __ and_(scratch2, HeapNumber::kExponentMask); | |
| 5744 __ shr(scratch2, HeapNumber::kExponentShift); | |
| 5745 __ j(zero, &zero_result, Label::kNear); | |
| 5746 __ sub(scratch2, Immediate(HeapNumber::kExponentBias - 1)); | |
| 5747 __ j(negative, &zero_result, Label::kNear); | |
| 5748 | |
| 5749 const uint32_t non_int8_exponent = 7; | |
| 5750 __ cmp(scratch2, Immediate(non_int8_exponent + 1)); | |
| 5751 // If the exponent is too big, check for special values. | |
| 5752 __ j(greater, &maybe_nan_or_infinity, Label::kNear); | |
| 5753 | |
| 5754 __ bind(&valid_exponent); | |
| 5755 // Exponent word in scratch, exponent in scratch2. We know that 0 <= exponent | |
| 5756 // < 7. The shift bias is the number of bits to shift the mantissa such that | |
| 5757 // with an exponent of 7 such the that top-most one is in bit 30, allowing | |
| 5758 // detection the rounding overflow of a 255.5 to 256 (bit 31 goes from 0 to | |
| 5759 // 1). | |
| 5760 int shift_bias = (30 - HeapNumber::kExponentShift) - 7 - 1; | |
| 5761 __ lea(result_reg, MemOperand(scratch2, shift_bias)); | |
| 5762 // Here result_reg (ecx) is the shift, scratch is the exponent word. Get the | |
| 5763 // top bits of the mantissa. | |
| 5764 __ and_(scratch, HeapNumber::kMantissaMask); | |
| 5765 // Put back the implicit 1 of the mantissa | |
| 5766 __ or_(scratch, 1 << HeapNumber::kExponentShift); | |
| 5767 // Shift up to round | |
| 5768 __ shl_cl(scratch); | |
| 5769 // Use "banker's rounding" to spec: If fractional part of number is 0.5, then | |
| 5770 // use the bit in the "ones" place and add it to the "halves" place, which has | |
| 5771 // the effect of rounding to even. | |
| 5772 __ mov(scratch2, scratch); | |
| 5773 const uint32_t one_half_bit_shift = 30 - sizeof(uint8_t) * 8; | |
| 5774 const uint32_t one_bit_shift = one_half_bit_shift + 1; | |
| 5775 __ and_(scratch2, Immediate((1 << one_bit_shift) - 1)); | |
| 5776 __ cmp(scratch2, Immediate(1 << one_half_bit_shift)); | |
| 5777 Label no_round; | |
| 5778 __ j(less, &no_round, Label::kNear); | |
| 5779 Label round_up; | |
| 5780 __ mov(scratch2, Immediate(1 << one_half_bit_shift)); | |
| 5781 __ j(greater, &round_up, Label::kNear); | |
| 5782 __ test(scratch3, scratch3); | |
| 5783 __ j(not_zero, &round_up, Label::kNear); | |
| 5784 __ mov(scratch2, scratch); | |
| 5785 __ and_(scratch2, Immediate(1 << one_bit_shift)); | |
| 5786 __ shr(scratch2, 1); | |
| 5787 __ bind(&round_up); | |
| 5788 __ add(scratch, scratch2); | |
| 5789 __ j(overflow, &largest_value, Label::kNear); | |
| 5790 __ bind(&no_round); | |
| 5791 __ shr(scratch, 23); | |
| 5792 __ mov(result_reg, scratch); | |
| 5793 __ jmp(&done, Label::kNear); | |
| 5794 | |
| 5795 __ bind(&maybe_nan_or_infinity); | |
| 5796 // Check for NaN/Infinity, all other values map to 255 | |
| 5797 __ cmp(scratch2, Immediate(HeapNumber::kInfinityOrNanExponent + 1)); | |
| 5798 __ j(not_equal, &largest_value, Label::kNear); | |
| 5799 | |
| 5800 // Check for NaN, which differs from Infinity in that at least one mantissa | |
| 5801 // bit is set. | |
| 5802 __ and_(scratch, HeapNumber::kMantissaMask); | |
| 5803 __ or_(scratch, FieldOperand(input_reg, HeapNumber::kMantissaOffset)); | |
| 5804 __ j(not_zero, &zero_result, Label::kNear); // M!=0 --> NaN | |
| 5805 // Infinity -> Fall through to map to 255. | |
| 5806 | |
| 5807 __ bind(&largest_value); | |
| 5808 __ mov(result_reg, Immediate(255)); | |
| 5809 __ jmp(&done, Label::kNear); | |
| 5810 | |
| 5811 __ bind(&zero_result); | |
| 5812 __ xor_(result_reg, result_reg); | |
| 5813 __ jmp(&done, Label::kNear); | |
| 5814 | |
| 5815 // smi | |
| 5816 __ bind(&is_smi); | |
| 5817 if (!input_reg.is(result_reg)) { | |
| 5818 __ mov(result_reg, input_reg); | |
| 5819 } | |
| 5820 __ SmiUntag(result_reg); | |
| 5821 __ ClampUint8(result_reg); | |
| 5822 __ bind(&done); | |
| 5823 } | |
| 5824 | |
| 5825 | |
| 5826 void LCodeGen::DoDoubleBits(LDoubleBits* instr) { | 5078 void LCodeGen::DoDoubleBits(LDoubleBits* instr) { |
| 5827 CpuFeatureScope scope(masm(), SSE2); | |
| 5828 XMMRegister value_reg = ToDoubleRegister(instr->value()); | 5079 XMMRegister value_reg = ToDoubleRegister(instr->value()); |
| 5829 Register result_reg = ToRegister(instr->result()); | 5080 Register result_reg = ToRegister(instr->result()); |
| 5830 if (instr->hydrogen()->bits() == HDoubleBits::HIGH) { | 5081 if (instr->hydrogen()->bits() == HDoubleBits::HIGH) { |
| 5831 if (CpuFeatures::IsSupported(SSE4_1)) { | 5082 if (CpuFeatures::IsSupported(SSE4_1)) { |
| 5832 CpuFeatureScope scope2(masm(), SSE4_1); | 5083 CpuFeatureScope scope2(masm(), SSE4_1); |
| 5833 __ pextrd(result_reg, value_reg, 1); | 5084 __ pextrd(result_reg, value_reg, 1); |
| 5834 } else { | 5085 } else { |
| 5835 XMMRegister xmm_scratch = double_scratch0(); | 5086 XMMRegister xmm_scratch = double_scratch0(); |
| 5836 __ pshufd(xmm_scratch, value_reg, 1); | 5087 __ pshufd(xmm_scratch, value_reg, 1); |
| 5837 __ movd(result_reg, xmm_scratch); | 5088 __ movd(result_reg, xmm_scratch); |
| 5838 } | 5089 } |
| 5839 } else { | 5090 } else { |
| 5840 __ movd(result_reg, value_reg); | 5091 __ movd(result_reg, value_reg); |
| 5841 } | 5092 } |
| 5842 } | 5093 } |
| 5843 | 5094 |
| 5844 | 5095 |
| 5845 void LCodeGen::DoConstructDouble(LConstructDouble* instr) { | 5096 void LCodeGen::DoConstructDouble(LConstructDouble* instr) { |
| 5846 Register hi_reg = ToRegister(instr->hi()); | 5097 Register hi_reg = ToRegister(instr->hi()); |
| 5847 Register lo_reg = ToRegister(instr->lo()); | 5098 Register lo_reg = ToRegister(instr->lo()); |
| 5848 XMMRegister result_reg = ToDoubleRegister(instr->result()); | 5099 XMMRegister result_reg = ToDoubleRegister(instr->result()); |
| 5849 CpuFeatureScope scope(masm(), SSE2); | |
| 5850 | 5100 |
| 5851 if (CpuFeatures::IsSupported(SSE4_1)) { | 5101 if (CpuFeatures::IsSupported(SSE4_1)) { |
| 5852 CpuFeatureScope scope2(masm(), SSE4_1); | 5102 CpuFeatureScope scope2(masm(), SSE4_1); |
| 5853 __ movd(result_reg, lo_reg); | 5103 __ movd(result_reg, lo_reg); |
| 5854 __ pinsrd(result_reg, hi_reg, 1); | 5104 __ pinsrd(result_reg, hi_reg, 1); |
| 5855 } else { | 5105 } else { |
| 5856 XMMRegister xmm_scratch = double_scratch0(); | 5106 XMMRegister xmm_scratch = double_scratch0(); |
| 5857 __ movd(result_reg, hi_reg); | 5107 __ movd(result_reg, hi_reg); |
| 5858 __ psllq(result_reg, 32); | 5108 __ psllq(result_reg, 32); |
| 5859 __ movd(xmm_scratch, lo_reg); | 5109 __ movd(xmm_scratch, lo_reg); |
| 5860 __ orps(result_reg, xmm_scratch); | 5110 __ orps(result_reg, xmm_scratch); |
| 5861 } | 5111 } |
| 5862 } | 5112 } |
| 5863 | 5113 |
| 5864 | 5114 |
| 5865 void LCodeGen::DoAllocate(LAllocate* instr) { | 5115 void LCodeGen::DoAllocate(LAllocate* instr) { |
| 5866 class DeferredAllocate V8_FINAL : public LDeferredCode { | 5116 class DeferredAllocate V8_FINAL : public LDeferredCode { |
| 5867 public: | 5117 public: |
| 5868 DeferredAllocate(LCodeGen* codegen, | 5118 DeferredAllocate(LCodeGen* codegen, LAllocate* instr) |
| 5869 LAllocate* instr, | 5119 : LDeferredCode(codegen), instr_(instr) { } |
| 5870 const X87Stack& x87_stack) | |
| 5871 : LDeferredCode(codegen, x87_stack), instr_(instr) { } | |
| 5872 virtual void Generate() V8_OVERRIDE { | 5120 virtual void Generate() V8_OVERRIDE { |
| 5873 codegen()->DoDeferredAllocate(instr_); | 5121 codegen()->DoDeferredAllocate(instr_); |
| 5874 } | 5122 } |
| 5875 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } | 5123 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
| 5876 private: | 5124 private: |
| 5877 LAllocate* instr_; | 5125 LAllocate* instr_; |
| 5878 }; | 5126 }; |
| 5879 | 5127 |
| 5880 DeferredAllocate* deferred = | 5128 DeferredAllocate* deferred = new(zone()) DeferredAllocate(this, instr); |
| 5881 new(zone()) DeferredAllocate(this, instr, x87_stack_); | |
| 5882 | 5129 |
| 5883 Register result = ToRegister(instr->result()); | 5130 Register result = ToRegister(instr->result()); |
| 5884 Register temp = ToRegister(instr->temp()); | 5131 Register temp = ToRegister(instr->temp()); |
| 5885 | 5132 |
| 5886 // Allocate memory for the object. | 5133 // Allocate memory for the object. |
| 5887 AllocationFlags flags = TAG_OBJECT; | 5134 AllocationFlags flags = TAG_OBJECT; |
| 5888 if (instr->hydrogen()->MustAllocateDoubleAligned()) { | 5135 if (instr->hydrogen()->MustAllocateDoubleAligned()) { |
| 5889 flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT); | 5136 flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT); |
| 5890 } | 5137 } |
| 5891 if (instr->hydrogen()->IsOldPointerSpaceAllocation()) { | 5138 if (instr->hydrogen()->IsOldPointerSpaceAllocation()) { |
| (...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6236 instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); | 5483 instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); |
| 6237 ASSERT(instr->HasEnvironment()); | 5484 ASSERT(instr->HasEnvironment()); |
| 6238 LEnvironment* env = instr->environment(); | 5485 LEnvironment* env = instr->environment(); |
| 6239 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); | 5486 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); |
| 6240 } | 5487 } |
| 6241 | 5488 |
| 6242 | 5489 |
| 6243 void LCodeGen::DoStackCheck(LStackCheck* instr) { | 5490 void LCodeGen::DoStackCheck(LStackCheck* instr) { |
| 6244 class DeferredStackCheck V8_FINAL : public LDeferredCode { | 5491 class DeferredStackCheck V8_FINAL : public LDeferredCode { |
| 6245 public: | 5492 public: |
| 6246 DeferredStackCheck(LCodeGen* codegen, | 5493 DeferredStackCheck(LCodeGen* codegen, LStackCheck* instr) |
| 6247 LStackCheck* instr, | 5494 : LDeferredCode(codegen), instr_(instr) { } |
| 6248 const X87Stack& x87_stack) | |
| 6249 : LDeferredCode(codegen, x87_stack), instr_(instr) { } | |
| 6250 virtual void Generate() V8_OVERRIDE { | 5495 virtual void Generate() V8_OVERRIDE { |
| 6251 codegen()->DoDeferredStackCheck(instr_); | 5496 codegen()->DoDeferredStackCheck(instr_); |
| 6252 } | 5497 } |
| 6253 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } | 5498 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
| 6254 private: | 5499 private: |
| 6255 LStackCheck* instr_; | 5500 LStackCheck* instr_; |
| 6256 }; | 5501 }; |
| 6257 | 5502 |
| 6258 ASSERT(instr->HasEnvironment()); | 5503 ASSERT(instr->HasEnvironment()); |
| 6259 LEnvironment* env = instr->environment(); | 5504 LEnvironment* env = instr->environment(); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 6270 ASSERT(instr->context()->IsRegister()); | 5515 ASSERT(instr->context()->IsRegister()); |
| 6271 ASSERT(ToRegister(instr->context()).is(esi)); | 5516 ASSERT(ToRegister(instr->context()).is(esi)); |
| 6272 CallCode(isolate()->builtins()->StackCheck(), | 5517 CallCode(isolate()->builtins()->StackCheck(), |
| 6273 RelocInfo::CODE_TARGET, | 5518 RelocInfo::CODE_TARGET, |
| 6274 instr); | 5519 instr); |
| 6275 __ bind(&done); | 5520 __ bind(&done); |
| 6276 } else { | 5521 } else { |
| 6277 ASSERT(instr->hydrogen()->is_backwards_branch()); | 5522 ASSERT(instr->hydrogen()->is_backwards_branch()); |
| 6278 // Perform stack overflow check if this goto needs it before jumping. | 5523 // Perform stack overflow check if this goto needs it before jumping. |
| 6279 DeferredStackCheck* deferred_stack_check = | 5524 DeferredStackCheck* deferred_stack_check = |
| 6280 new(zone()) DeferredStackCheck(this, instr, x87_stack_); | 5525 new(zone()) DeferredStackCheck(this, instr); |
| 6281 ExternalReference stack_limit = | 5526 ExternalReference stack_limit = |
| 6282 ExternalReference::address_of_stack_limit(isolate()); | 5527 ExternalReference::address_of_stack_limit(isolate()); |
| 6283 __ cmp(esp, Operand::StaticVariable(stack_limit)); | 5528 __ cmp(esp, Operand::StaticVariable(stack_limit)); |
| 6284 __ j(below, deferred_stack_check->entry()); | 5529 __ j(below, deferred_stack_check->entry()); |
| 6285 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); | 5530 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); |
| 6286 __ bind(instr->done_label()); | 5531 __ bind(instr->done_label()); |
| 6287 deferred_stack_check->SetExit(instr->done_label()); | 5532 deferred_stack_check->SetExit(instr->done_label()); |
| 6288 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); | 5533 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); |
| 6289 // Don't record a deoptimization index for the safepoint here. | 5534 // Don't record a deoptimization index for the safepoint here. |
| 6290 // This will be done explicitly when emitting call and the safepoint in | 5535 // This will be done explicitly when emitting call and the safepoint in |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6384 __ StoreToSafepointRegisterSlot(object, eax); | 5629 __ StoreToSafepointRegisterSlot(object, eax); |
| 6385 } | 5630 } |
| 6386 | 5631 |
| 6387 | 5632 |
| 6388 void LCodeGen::DoLoadFieldByIndex(LLoadFieldByIndex* instr) { | 5633 void LCodeGen::DoLoadFieldByIndex(LLoadFieldByIndex* instr) { |
| 6389 class DeferredLoadMutableDouble V8_FINAL : public LDeferredCode { | 5634 class DeferredLoadMutableDouble V8_FINAL : public LDeferredCode { |
| 6390 public: | 5635 public: |
| 6391 DeferredLoadMutableDouble(LCodeGen* codegen, | 5636 DeferredLoadMutableDouble(LCodeGen* codegen, |
| 6392 LLoadFieldByIndex* instr, | 5637 LLoadFieldByIndex* instr, |
| 6393 Register object, | 5638 Register object, |
| 6394 Register index, | 5639 Register index) |
| 6395 const X87Stack& x87_stack) | 5640 : LDeferredCode(codegen), |
| 6396 : LDeferredCode(codegen, x87_stack), | |
| 6397 instr_(instr), | 5641 instr_(instr), |
| 6398 object_(object), | 5642 object_(object), |
| 6399 index_(index) { | 5643 index_(index) { |
| 6400 } | 5644 } |
| 6401 virtual void Generate() V8_OVERRIDE { | 5645 virtual void Generate() V8_OVERRIDE { |
| 6402 codegen()->DoDeferredLoadMutableDouble(instr_, object_, index_); | 5646 codegen()->DoDeferredLoadMutableDouble(instr_, object_, index_); |
| 6403 } | 5647 } |
| 6404 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } | 5648 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
| 6405 private: | 5649 private: |
| 6406 LLoadFieldByIndex* instr_; | 5650 LLoadFieldByIndex* instr_; |
| 6407 Register object_; | 5651 Register object_; |
| 6408 Register index_; | 5652 Register index_; |
| 6409 }; | 5653 }; |
| 6410 | 5654 |
| 6411 Register object = ToRegister(instr->object()); | 5655 Register object = ToRegister(instr->object()); |
| 6412 Register index = ToRegister(instr->index()); | 5656 Register index = ToRegister(instr->index()); |
| 6413 | 5657 |
| 6414 DeferredLoadMutableDouble* deferred; | 5658 DeferredLoadMutableDouble* deferred; |
| 6415 deferred = new(zone()) DeferredLoadMutableDouble( | 5659 deferred = new(zone()) DeferredLoadMutableDouble( |
| 6416 this, instr, object, index, x87_stack_); | 5660 this, instr, object, index); |
| 6417 | 5661 |
| 6418 Label out_of_object, done; | 5662 Label out_of_object, done; |
| 6419 __ test(index, Immediate(Smi::FromInt(1))); | 5663 __ test(index, Immediate(Smi::FromInt(1))); |
| 6420 __ j(not_zero, deferred->entry()); | 5664 __ j(not_zero, deferred->entry()); |
| 6421 | 5665 |
| 6422 __ sar(index, 1); | 5666 __ sar(index, 1); |
| 6423 | 5667 |
| 6424 __ cmp(index, Immediate(0)); | 5668 __ cmp(index, Immediate(0)); |
| 6425 __ j(less, &out_of_object, Label::kNear); | 5669 __ j(less, &out_of_object, Label::kNear); |
| 6426 __ mov(object, FieldOperand(object, | 5670 __ mov(object, FieldOperand(object, |
| (...skipping 13 matching lines...) Expand all Loading... |
| 6440 __ bind(deferred->exit()); | 5684 __ bind(deferred->exit()); |
| 6441 __ bind(&done); | 5685 __ bind(&done); |
| 6442 } | 5686 } |
| 6443 | 5687 |
| 6444 | 5688 |
| 6445 #undef __ | 5689 #undef __ |
| 6446 | 5690 |
| 6447 } } // namespace v8::internal | 5691 } } // namespace v8::internal |
| 6448 | 5692 |
| 6449 #endif // V8_TARGET_ARCH_IA32 | 5693 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |