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

Side by Side Diff: src/ia32/lithium-codegen-ia32.cc

Issue 275433004: Require SSE2 support for the ia32 port. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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, &not_heap_number, Label::kNear); 2176 __ j(not_equal, &not_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(&not_heap_number); 2182 __ bind(&not_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
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
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
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
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
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
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
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
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
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
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
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
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, &not_zero_input); 3822 __ j(not_zero, &not_zero_input);
4209 __ Move(result, Immediate(63)); // 63^31 == 32 3823 __ Move(result, Immediate(63)); // 63^31 == 32
4210 3824
4211 __ bind(&not_zero_input); 3825 __ bind(&not_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
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
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
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
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
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 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
4770 RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); 4317 RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
4771 } 4318 }
4772 __ bind(&not_applicable); 4319 __ bind(&not_applicable);
4773 } 4320 }
4774 4321
4775 4322
4776 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { 4323 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
4777 class DeferredStringCharCodeAt V8_FINAL : public LDeferredCode { 4324 class DeferredStringCharCodeAt V8_FINAL : public LDeferredCode {
4778 public: 4325 public:
4779 DeferredStringCharCodeAt(LCodeGen* codegen, 4326 DeferredStringCharCodeAt(LCodeGen* codegen,
4780 LStringCharCodeAt* instr, 4327 LStringCharCodeAt* instr)
4781 const X87Stack& x87_stack) 4328 : LDeferredCode(codegen), instr_(instr) { }
4782 : LDeferredCode(codegen, x87_stack), instr_(instr) { }
4783 virtual void Generate() V8_OVERRIDE { 4329 virtual void Generate() V8_OVERRIDE {
4784 codegen()->DoDeferredStringCharCodeAt(instr_); 4330 codegen()->DoDeferredStringCharCodeAt(instr_);
4785 } 4331 }
4786 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } 4332 virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
4787 private: 4333 private:
4788 LStringCharCodeAt* instr_; 4334 LStringCharCodeAt* instr_;
4789 }; 4335 };
4790 4336
4791 DeferredStringCharCodeAt* deferred = 4337 DeferredStringCharCodeAt* deferred =
4792 new(zone()) DeferredStringCharCodeAt(this, instr, x87_stack_); 4338 new(zone()) DeferredStringCharCodeAt(this, instr);
4793 4339
4794 StringCharLoadGenerator::Generate(masm(), 4340 StringCharLoadGenerator::Generate(masm(),
4795 factory(), 4341 factory(),
4796 ToRegister(instr->string()), 4342 ToRegister(instr->string()),
4797 ToRegister(instr->index()), 4343 ToRegister(instr->index()),
4798 ToRegister(instr->result()), 4344 ToRegister(instr->result()),
4799 deferred->entry()); 4345 deferred->entry());
4800 __ bind(deferred->exit()); 4346 __ bind(deferred->exit());
4801 } 4347 }
4802 4348
(...skipping 26 matching lines...) Expand all
4829 __ AssertSmi(eax); 4375 __ AssertSmi(eax);
4830 __ SmiUntag(eax); 4376 __ SmiUntag(eax);
4831 __ StoreToSafepointRegisterSlot(result, eax); 4377 __ StoreToSafepointRegisterSlot(result, eax);
4832 } 4378 }
4833 4379
4834 4380
4835 void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) { 4381 void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) {
4836 class DeferredStringCharFromCode V8_FINAL : public LDeferredCode { 4382 class DeferredStringCharFromCode V8_FINAL : public LDeferredCode {
4837 public: 4383 public:
4838 DeferredStringCharFromCode(LCodeGen* codegen, 4384 DeferredStringCharFromCode(LCodeGen* codegen,
4839 LStringCharFromCode* instr, 4385 LStringCharFromCode* instr)
4840 const X87Stack& x87_stack) 4386 : LDeferredCode(codegen), instr_(instr) { }
4841 : LDeferredCode(codegen, x87_stack), instr_(instr) { }
4842 virtual void Generate() V8_OVERRIDE { 4387 virtual void Generate() V8_OVERRIDE {
4843 codegen()->DoDeferredStringCharFromCode(instr_); 4388 codegen()->DoDeferredStringCharFromCode(instr_);
4844 } 4389 }
4845 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } 4390 virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
4846 private: 4391 private:
4847 LStringCharFromCode* instr_; 4392 LStringCharFromCode* instr_;
4848 }; 4393 };
4849 4394
4850 DeferredStringCharFromCode* deferred = 4395 DeferredStringCharFromCode* deferred =
4851 new(zone()) DeferredStringCharFromCode(this, instr, x87_stack_); 4396 new(zone()) DeferredStringCharFromCode(this, instr);
4852 4397
4853 ASSERT(instr->hydrogen()->value()->representation().IsInteger32()); 4398 ASSERT(instr->hydrogen()->value()->representation().IsInteger32());
4854 Register char_code = ToRegister(instr->char_code()); 4399 Register char_code = ToRegister(instr->char_code());
4855 Register result = ToRegister(instr->result()); 4400 Register result = ToRegister(instr->result());
4856 ASSERT(!char_code.is(result)); 4401 ASSERT(!char_code.is(result));
4857 4402
4858 __ cmp(char_code, String::kMaxOneByteCharCode); 4403 __ cmp(char_code, String::kMaxOneByteCharCode);
4859 __ j(above, deferred->entry()); 4404 __ j(above, deferred->entry());
4860 __ Move(result, Immediate(factory()->single_character_string_cache())); 4405 __ Move(result, Immediate(factory()->single_character_string_cache()));
4861 __ mov(result, FieldOperand(result, 4406 __ mov(result, FieldOperand(result,
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
4893 instr->hydrogen()->pretenure_flag()); 4438 instr->hydrogen()->pretenure_flag());
4894 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 4439 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
4895 } 4440 }
4896 4441
4897 4442
4898 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { 4443 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) {
4899 LOperand* input = instr->value(); 4444 LOperand* input = instr->value();
4900 LOperand* output = instr->result(); 4445 LOperand* output = instr->result();
4901 ASSERT(input->IsRegister() || input->IsStackSlot()); 4446 ASSERT(input->IsRegister() || input->IsStackSlot());
4902 ASSERT(output->IsDoubleRegister()); 4447 ASSERT(output->IsDoubleRegister());
4903 if (CpuFeatures::IsSupported(SSE2)) { 4448 __ Cvtsi2sd(ToDoubleRegister(output), ToOperand(input));
4904 CpuFeatureScope scope(masm(), SSE2);
4905 __ Cvtsi2sd(ToDoubleRegister(output), ToOperand(input));
4906 } else if (input->IsRegister()) {
4907 Register input_reg = ToRegister(input);
4908 __ push(input_reg);
4909 X87Mov(ToX87Register(output), Operand(esp, 0), kX87IntOperand);
4910 __ pop(input_reg);
4911 } else {
4912 X87Mov(ToX87Register(output), ToOperand(input), kX87IntOperand);
4913 }
4914 } 4449 }
4915 4450
4916 4451
4917 void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) { 4452 void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) {
4918 LOperand* input = instr->value(); 4453 LOperand* input = instr->value();
4919 LOperand* output = instr->result(); 4454 LOperand* output = instr->result();
4920 if (CpuFeatures::IsSupported(SSE2)) { 4455 LOperand* temp = instr->temp();
4921 CpuFeatureScope scope(masm(), SSE2); 4456 __ LoadUint32(ToDoubleRegister(output),
4922 LOperand* temp = instr->temp(); 4457 ToRegister(input),
4923 4458 ToDoubleRegister(temp));
4924 __ LoadUint32(ToDoubleRegister(output),
4925 ToRegister(input),
4926 ToDoubleRegister(temp));
4927 } else {
4928 X87Register res = ToX87Register(output);
4929 X87PrepareToWrite(res);
4930 __ LoadUint32NoSSE2(ToRegister(input));
4931 X87CommitWrite(res);
4932 }
4933 } 4459 }
4934 4460
4935 4461
4936 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { 4462 void LCodeGen::DoNumberTagI(LNumberTagI* instr) {
4937 class DeferredNumberTagI V8_FINAL : public LDeferredCode { 4463 class DeferredNumberTagI V8_FINAL : public LDeferredCode {
4938 public: 4464 public:
4939 DeferredNumberTagI(LCodeGen* codegen, 4465 DeferredNumberTagI(LCodeGen* codegen,
4940 LNumberTagI* instr, 4466 LNumberTagI* instr)
4941 const X87Stack& x87_stack) 4467 : LDeferredCode(codegen), instr_(instr) { }
4942 : LDeferredCode(codegen, x87_stack), instr_(instr) { }
4943 virtual void Generate() V8_OVERRIDE { 4468 virtual void Generate() V8_OVERRIDE {
4944 codegen()->DoDeferredNumberTagIU(instr_, instr_->value(), instr_->temp(), 4469 codegen()->DoDeferredNumberTagIU(instr_, instr_->value(), instr_->temp(),
4945 NULL, SIGNED_INT32); 4470 NULL, SIGNED_INT32);
4946 } 4471 }
4947 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } 4472 virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
4948 private: 4473 private:
4949 LNumberTagI* instr_; 4474 LNumberTagI* instr_;
4950 }; 4475 };
4951 4476
4952 LOperand* input = instr->value(); 4477 LOperand* input = instr->value();
4953 ASSERT(input->IsRegister() && input->Equals(instr->result())); 4478 ASSERT(input->IsRegister() && input->Equals(instr->result()));
4954 Register reg = ToRegister(input); 4479 Register reg = ToRegister(input);
4955 4480
4956 DeferredNumberTagI* deferred = 4481 DeferredNumberTagI* deferred =
4957 new(zone()) DeferredNumberTagI(this, instr, x87_stack_); 4482 new(zone()) DeferredNumberTagI(this, instr);
4958 __ SmiTag(reg); 4483 __ SmiTag(reg);
4959 __ j(overflow, deferred->entry()); 4484 __ j(overflow, deferred->entry());
4960 __ bind(deferred->exit()); 4485 __ bind(deferred->exit());
4961 } 4486 }
4962 4487
4963 4488
4964 void LCodeGen::DoNumberTagU(LNumberTagU* instr) { 4489 void LCodeGen::DoNumberTagU(LNumberTagU* instr) {
4965 class DeferredNumberTagU V8_FINAL : public LDeferredCode { 4490 class DeferredNumberTagU V8_FINAL : public LDeferredCode {
4966 public: 4491 public:
4967 DeferredNumberTagU(LCodeGen* codegen, 4492 DeferredNumberTagU(LCodeGen* codegen, LNumberTagU* instr)
4968 LNumberTagU* instr, 4493 : LDeferredCode(codegen), instr_(instr) { }
4969 const X87Stack& x87_stack)
4970 : LDeferredCode(codegen, x87_stack), instr_(instr) { }
4971 virtual void Generate() V8_OVERRIDE { 4494 virtual void Generate() V8_OVERRIDE {
4972 codegen()->DoDeferredNumberTagIU(instr_, instr_->value(), instr_->temp1(), 4495 codegen()->DoDeferredNumberTagIU(instr_, instr_->value(), instr_->temp1(),
4973 instr_->temp2(), UNSIGNED_INT32); 4496 instr_->temp2(), UNSIGNED_INT32);
4974 } 4497 }
4975 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } 4498 virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
4976 private: 4499 private:
4977 LNumberTagU* instr_; 4500 LNumberTagU* instr_;
4978 }; 4501 };
4979 4502
4980 LOperand* input = instr->value(); 4503 LOperand* input = instr->value();
4981 ASSERT(input->IsRegister() && input->Equals(instr->result())); 4504 ASSERT(input->IsRegister() && input->Equals(instr->result()));
4982 Register reg = ToRegister(input); 4505 Register reg = ToRegister(input);
4983 4506
4984 DeferredNumberTagU* deferred = 4507 DeferredNumberTagU* deferred =
4985 new(zone()) DeferredNumberTagU(this, instr, x87_stack_); 4508 new(zone()) DeferredNumberTagU(this, instr);
4986 __ cmp(reg, Immediate(Smi::kMaxValue)); 4509 __ cmp(reg, Immediate(Smi::kMaxValue));
4987 __ j(above, deferred->entry()); 4510 __ j(above, deferred->entry());
4988 __ SmiTag(reg); 4511 __ SmiTag(reg);
4989 __ bind(deferred->exit()); 4512 __ bind(deferred->exit());
4990 } 4513 }
4991 4514
4992 4515
4993 void LCodeGen::DoDeferredNumberTagIU(LInstruction* instr, 4516 void LCodeGen::DoDeferredNumberTagIU(LInstruction* instr,
4994 LOperand* value, 4517 LOperand* value,
4995 LOperand* temp1, 4518 LOperand* temp1,
4996 LOperand* temp2, 4519 LOperand* temp2,
4997 IntegerSignedness signedness) { 4520 IntegerSignedness signedness) {
4998 Label done, slow; 4521 Label done, slow;
4999 Register reg = ToRegister(value); 4522 Register reg = ToRegister(value);
5000 Register tmp = ToRegister(temp1); 4523 Register tmp = ToRegister(temp1);
5001 XMMRegister xmm_scratch = double_scratch0(); 4524 XMMRegister xmm_scratch = double_scratch0();
5002 4525
5003 if (signedness == SIGNED_INT32) { 4526 if (signedness == SIGNED_INT32) {
5004 // There was overflow, so bits 30 and 31 of the original integer 4527 // There was overflow, so bits 30 and 31 of the original integer
5005 // disagree. Try to allocate a heap number in new space and store 4528 // disagree. Try to allocate a heap number in new space and store
5006 // the value in there. If that fails, call the runtime system. 4529 // the value in there. If that fails, call the runtime system.
5007 __ SmiUntag(reg); 4530 __ SmiUntag(reg);
5008 __ xor_(reg, 0x80000000); 4531 __ xor_(reg, 0x80000000);
5009 if (CpuFeatures::IsSupported(SSE2)) { 4532 __ Cvtsi2sd(xmm_scratch, Operand(reg));
5010 CpuFeatureScope feature_scope(masm(), SSE2);
5011 __ Cvtsi2sd(xmm_scratch, Operand(reg));
5012 } else {
5013 __ push(reg);
5014 __ fild_s(Operand(esp, 0));
5015 __ pop(reg);
5016 }
5017 } else { 4533 } else {
5018 if (CpuFeatures::IsSupported(SSE2)) { 4534 __ LoadUint32(xmm_scratch, reg, ToDoubleRegister(temp2));
5019 CpuFeatureScope feature_scope(masm(), SSE2);
5020 __ LoadUint32(xmm_scratch, reg, ToDoubleRegister(temp2));
5021 } else {
5022 // There's no fild variant for unsigned values, so zero-extend to a 64-bit
5023 // int manually.
5024 __ push(Immediate(0));
5025 __ push(reg);
5026 __ fild_d(Operand(esp, 0));
5027 __ pop(reg);
5028 __ pop(reg);
5029 }
5030 } 4535 }
5031 4536
5032 if (FLAG_inline_new) { 4537 if (FLAG_inline_new) {
5033 __ AllocateHeapNumber(reg, tmp, no_reg, &slow); 4538 __ AllocateHeapNumber(reg, tmp, no_reg, &slow);
5034 __ jmp(&done, Label::kNear); 4539 __ jmp(&done, Label::kNear);
5035 } 4540 }
5036 4541
5037 // Slow case: Call the runtime system to do the number allocation. 4542 // Slow case: Call the runtime system to do the number allocation.
5038 __ bind(&slow); 4543 __ bind(&slow);
5039 { 4544 {
(...skipping 13 matching lines...) Expand all
5053 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 4558 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
5054 __ CallRuntimeSaveDoubles(Runtime::kHiddenAllocateHeapNumber); 4559 __ CallRuntimeSaveDoubles(Runtime::kHiddenAllocateHeapNumber);
5055 RecordSafepointWithRegisters( 4560 RecordSafepointWithRegisters(
5056 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); 4561 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
5057 __ StoreToSafepointRegisterSlot(reg, eax); 4562 __ StoreToSafepointRegisterSlot(reg, eax);
5058 } 4563 }
5059 4564
5060 // Done. Put the value in xmm_scratch into the value of the allocated heap 4565 // Done. Put the value in xmm_scratch into the value of the allocated heap
5061 // number. 4566 // number.
5062 __ bind(&done); 4567 __ bind(&done);
5063 if (CpuFeatures::IsSupported(SSE2)) { 4568 __ movsd(FieldOperand(reg, HeapNumber::kValueOffset), xmm_scratch);
5064 CpuFeatureScope feature_scope(masm(), SSE2);
5065 __ movsd(FieldOperand(reg, HeapNumber::kValueOffset), xmm_scratch);
5066 } else {
5067 __ fstp_d(FieldOperand(reg, HeapNumber::kValueOffset));
5068 }
5069 } 4569 }
5070 4570
5071 4571
5072 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { 4572 void LCodeGen::DoNumberTagD(LNumberTagD* instr) {
5073 class DeferredNumberTagD V8_FINAL : public LDeferredCode { 4573 class DeferredNumberTagD V8_FINAL : public LDeferredCode {
5074 public: 4574 public:
5075 DeferredNumberTagD(LCodeGen* codegen, 4575 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr)
5076 LNumberTagD* instr, 4576 : LDeferredCode(codegen), instr_(instr) { }
5077 const X87Stack& x87_stack)
5078 : LDeferredCode(codegen, x87_stack), instr_(instr) { }
5079 virtual void Generate() V8_OVERRIDE { 4577 virtual void Generate() V8_OVERRIDE {
5080 codegen()->DoDeferredNumberTagD(instr_); 4578 codegen()->DoDeferredNumberTagD(instr_);
5081 } 4579 }
5082 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } 4580 virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
5083 private: 4581 private:
5084 LNumberTagD* instr_; 4582 LNumberTagD* instr_;
5085 }; 4583 };
5086 4584
5087 Register reg = ToRegister(instr->result()); 4585 Register reg = ToRegister(instr->result());
5088 4586
5089 bool use_sse2 = CpuFeatures::IsSupported(SSE2);
5090 if (!use_sse2) {
5091 // Put the value to the top of stack
5092 X87Register src = ToX87Register(instr->value());
5093 X87LoadForUsage(src);
5094 }
5095
5096 DeferredNumberTagD* deferred = 4587 DeferredNumberTagD* deferred =
5097 new(zone()) DeferredNumberTagD(this, instr, x87_stack_); 4588 new(zone()) DeferredNumberTagD(this, instr);
5098 if (FLAG_inline_new) { 4589 if (FLAG_inline_new) {
5099 Register tmp = ToRegister(instr->temp()); 4590 Register tmp = ToRegister(instr->temp());
5100 __ AllocateHeapNumber(reg, tmp, no_reg, deferred->entry()); 4591 __ AllocateHeapNumber(reg, tmp, no_reg, deferred->entry());
5101 } else { 4592 } else {
5102 __ jmp(deferred->entry()); 4593 __ jmp(deferred->entry());
5103 } 4594 }
5104 __ bind(deferred->exit()); 4595 __ bind(deferred->exit());
5105 if (use_sse2) { 4596 XMMRegister input_reg = ToDoubleRegister(instr->value());
5106 CpuFeatureScope scope(masm(), SSE2); 4597 __ movsd(FieldOperand(reg, HeapNumber::kValueOffset), input_reg);
5107 XMMRegister input_reg = ToDoubleRegister(instr->value());
5108 __ movsd(FieldOperand(reg, HeapNumber::kValueOffset), input_reg);
5109 } else {
5110 __ fstp_d(FieldOperand(reg, HeapNumber::kValueOffset));
5111 }
5112 } 4598 }
5113 4599
5114 4600
5115 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { 4601 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) {
5116 // TODO(3095996): Get rid of this. For now, we need to make the 4602 // TODO(3095996): Get rid of this. For now, we need to make the
5117 // result register contain a valid pointer because it is already 4603 // result register contain a valid pointer because it is already
5118 // contained in the register pointer map. 4604 // contained in the register pointer map.
5119 Register reg = ToRegister(instr->result()); 4605 Register reg = ToRegister(instr->result());
5120 __ Move(reg, Immediate(0)); 4606 __ Move(reg, Immediate(0));
5121 4607
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
5156 if (instr->needs_check()) { 4642 if (instr->needs_check()) {
5157 __ test(result, Immediate(kSmiTagMask)); 4643 __ test(result, Immediate(kSmiTagMask));
5158 DeoptimizeIf(not_zero, instr->environment()); 4644 DeoptimizeIf(not_zero, instr->environment());
5159 } else { 4645 } else {
5160 __ AssertSmi(result); 4646 __ AssertSmi(result);
5161 } 4647 }
5162 __ SmiUntag(result); 4648 __ SmiUntag(result);
5163 } 4649 }
5164 4650
5165 4651
5166 void LCodeGen::EmitNumberUntagDNoSSE2(Register input_reg,
5167 Register temp_reg,
5168 X87Register res_reg,
5169 bool can_convert_undefined_to_nan,
5170 bool deoptimize_on_minus_zero,
5171 LEnvironment* env,
5172 NumberUntagDMode mode) {
5173 Label load_smi, done;
5174
5175 X87PrepareToWrite(res_reg);
5176 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) {
5177 // Smi check.
5178 __ JumpIfSmi(input_reg, &load_smi, Label::kNear);
5179
5180 // Heap number map check.
5181 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
5182 factory()->heap_number_map());
5183 if (!can_convert_undefined_to_nan) {
5184 DeoptimizeIf(not_equal, env);
5185 } else {
5186 Label heap_number, convert;
5187 __ j(equal, &heap_number, Label::kNear);
5188
5189 // Convert undefined (or hole) to NaN.
5190 __ cmp(input_reg, factory()->undefined_value());
5191 DeoptimizeIf(not_equal, env);
5192
5193 __ bind(&convert);
5194 ExternalReference nan =
5195 ExternalReference::address_of_canonical_non_hole_nan();
5196 __ fld_d(Operand::StaticVariable(nan));
5197 __ jmp(&done, Label::kNear);
5198
5199 __ bind(&heap_number);
5200 }
5201 // Heap number to x87 conversion.
5202 __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset));
5203 if (deoptimize_on_minus_zero) {
5204 __ fldz();
5205 __ FCmp();
5206 __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset));
5207 __ j(not_zero, &done, Label::kNear);
5208
5209 // Use general purpose registers to check if we have -0.0
5210 __ mov(temp_reg, FieldOperand(input_reg, HeapNumber::kExponentOffset));
5211 __ test(temp_reg, Immediate(HeapNumber::kSignMask));
5212 __ j(zero, &done, Label::kNear);
5213
5214 // Pop FPU stack before deoptimizing.
5215 __ fstp(0);
5216 DeoptimizeIf(not_zero, env);
5217 }
5218 __ jmp(&done, Label::kNear);
5219 } else {
5220 ASSERT(mode == NUMBER_CANDIDATE_IS_SMI);
5221 }
5222
5223 __ bind(&load_smi);
5224 // Clobbering a temp is faster than re-tagging the
5225 // input register since we avoid dependencies.
5226 __ mov(temp_reg, input_reg);
5227 __ SmiUntag(temp_reg); // Untag smi before converting to float.
5228 __ push(temp_reg);
5229 __ fild_s(Operand(esp, 0));
5230 __ add(esp, Immediate(kPointerSize));
5231 __ bind(&done);
5232 X87CommitWrite(res_reg);
5233 }
5234
5235
5236 void LCodeGen::EmitNumberUntagD(Register input_reg, 4652 void LCodeGen::EmitNumberUntagD(Register input_reg,
5237 Register temp_reg, 4653 Register temp_reg,
5238 XMMRegister result_reg, 4654 XMMRegister result_reg,
5239 bool can_convert_undefined_to_nan, 4655 bool can_convert_undefined_to_nan,
5240 bool deoptimize_on_minus_zero, 4656 bool deoptimize_on_minus_zero,
5241 LEnvironment* env, 4657 LEnvironment* env,
5242 NumberUntagDMode mode) { 4658 NumberUntagDMode mode) {
5243 Label convert, load_smi, done; 4659 Label convert, load_smi, done;
5244 4660
5245 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) { 4661 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) {
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
5341 __ jmp(done); 4757 __ jmp(done);
5342 __ bind(&bailout); 4758 __ bind(&bailout);
5343 DeoptimizeIf(no_condition, instr->environment()); 4759 DeoptimizeIf(no_condition, instr->environment());
5344 } 4760 }
5345 } 4761 }
5346 4762
5347 4763
5348 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { 4764 void LCodeGen::DoTaggedToI(LTaggedToI* instr) {
5349 class DeferredTaggedToI V8_FINAL : public LDeferredCode { 4765 class DeferredTaggedToI V8_FINAL : public LDeferredCode {
5350 public: 4766 public:
5351 DeferredTaggedToI(LCodeGen* codegen, 4767 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr)
5352 LTaggedToI* instr, 4768 : LDeferredCode(codegen), instr_(instr) { }
5353 const X87Stack& x87_stack)
5354 : LDeferredCode(codegen, x87_stack), instr_(instr) { }
5355 virtual void Generate() V8_OVERRIDE { 4769 virtual void Generate() V8_OVERRIDE {
5356 codegen()->DoDeferredTaggedToI(instr_, done()); 4770 codegen()->DoDeferredTaggedToI(instr_, done());
5357 } 4771 }
5358 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } 4772 virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
5359 private: 4773 private:
5360 LTaggedToI* instr_; 4774 LTaggedToI* instr_;
5361 }; 4775 };
5362 4776
5363 LOperand* input = instr->value(); 4777 LOperand* input = instr->value();
5364 ASSERT(input->IsRegister()); 4778 ASSERT(input->IsRegister());
5365 Register input_reg = ToRegister(input); 4779 Register input_reg = ToRegister(input);
5366 ASSERT(input_reg.is(ToRegister(instr->result()))); 4780 ASSERT(input_reg.is(ToRegister(instr->result())));
5367 4781
5368 if (instr->hydrogen()->value()->representation().IsSmi()) { 4782 if (instr->hydrogen()->value()->representation().IsSmi()) {
5369 __ SmiUntag(input_reg); 4783 __ SmiUntag(input_reg);
5370 } else { 4784 } else {
5371 DeferredTaggedToI* deferred = 4785 DeferredTaggedToI* deferred =
5372 new(zone()) DeferredTaggedToI(this, instr, x87_stack_); 4786 new(zone()) DeferredTaggedToI(this, instr);
5373 // Optimistically untag the input. 4787 // Optimistically untag the input.
5374 // If the input is a HeapObject, SmiUntag will set the carry flag. 4788 // If the input is a HeapObject, SmiUntag will set the carry flag.
5375 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); 4789 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
5376 __ SmiUntag(input_reg); 4790 __ SmiUntag(input_reg);
5377 // Branch to deferred code if the input was tagged. 4791 // Branch to deferred code if the input was tagged.
5378 // The deferred code will take care of restoring the tag. 4792 // The deferred code will take care of restoring the tag.
5379 __ j(carry, deferred->entry()); 4793 __ j(carry, deferred->entry());
5380 __ bind(deferred->exit()); 4794 __ bind(deferred->exit());
5381 } 4795 }
5382 } 4796 }
5383 4797
5384 4798
5385 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { 4799 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) {
5386 LOperand* input = instr->value(); 4800 LOperand* input = instr->value();
5387 ASSERT(input->IsRegister()); 4801 ASSERT(input->IsRegister());
5388 LOperand* temp = instr->temp(); 4802 LOperand* temp = instr->temp();
5389 ASSERT(temp->IsRegister()); 4803 ASSERT(temp->IsRegister());
5390 LOperand* result = instr->result(); 4804 LOperand* result = instr->result();
5391 ASSERT(result->IsDoubleRegister()); 4805 ASSERT(result->IsDoubleRegister());
5392 4806
5393 Register input_reg = ToRegister(input); 4807 Register input_reg = ToRegister(input);
5394 bool deoptimize_on_minus_zero = 4808 bool deoptimize_on_minus_zero =
5395 instr->hydrogen()->deoptimize_on_minus_zero(); 4809 instr->hydrogen()->deoptimize_on_minus_zero();
5396 Register temp_reg = ToRegister(temp); 4810 Register temp_reg = ToRegister(temp);
5397 4811
5398 HValue* value = instr->hydrogen()->value(); 4812 HValue* value = instr->hydrogen()->value();
5399 NumberUntagDMode mode = value->representation().IsSmi() 4813 NumberUntagDMode mode = value->representation().IsSmi()
5400 ? NUMBER_CANDIDATE_IS_SMI : NUMBER_CANDIDATE_IS_ANY_TAGGED; 4814 ? NUMBER_CANDIDATE_IS_SMI : NUMBER_CANDIDATE_IS_ANY_TAGGED;
5401 4815
5402 if (CpuFeatures::IsSupported(SSE2)) { 4816 XMMRegister result_reg = ToDoubleRegister(result);
5403 CpuFeatureScope scope(masm(), SSE2); 4817 EmitNumberUntagD(input_reg,
5404 XMMRegister result_reg = ToDoubleRegister(result); 4818 temp_reg,
5405 EmitNumberUntagD(input_reg, 4819 result_reg,
5406 temp_reg, 4820 instr->hydrogen()->can_convert_undefined_to_nan(),
5407 result_reg, 4821 deoptimize_on_minus_zero,
5408 instr->hydrogen()->can_convert_undefined_to_nan(), 4822 instr->environment(),
5409 deoptimize_on_minus_zero, 4823 mode);
5410 instr->environment(),
5411 mode);
5412 } else {
5413 EmitNumberUntagDNoSSE2(input_reg,
5414 temp_reg,
5415 ToX87Register(instr->result()),
5416 instr->hydrogen()->can_convert_undefined_to_nan(),
5417 deoptimize_on_minus_zero,
5418 instr->environment(),
5419 mode);
5420 }
5421 } 4824 }
5422 4825
5423 4826
5424 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { 4827 void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
5425 LOperand* input = instr->value(); 4828 LOperand* input = instr->value();
5426 ASSERT(input->IsDoubleRegister()); 4829 ASSERT(input->IsDoubleRegister());
5427 LOperand* result = instr->result(); 4830 LOperand* result = instr->result();
5428 ASSERT(result->IsRegister()); 4831 ASSERT(result->IsRegister());
5429 Register result_reg = ToRegister(result); 4832 Register result_reg = ToRegister(result);
5430 4833
5431 if (instr->truncating()) { 4834 if (instr->truncating()) {
5432 if (CpuFeatures::IsSafeForSnapshot(isolate(), SSE2)) { 4835 XMMRegister input_reg = ToDoubleRegister(input);
5433 CpuFeatureScope scope(masm(), SSE2); 4836 __ TruncateDoubleToI(result_reg, input_reg);
5434 XMMRegister input_reg = ToDoubleRegister(input);
5435 __ TruncateDoubleToI(result_reg, input_reg);
5436 } else {
5437 X87Register input_reg = ToX87Register(input);
5438 X87Fxch(input_reg);
5439 __ TruncateX87TOSToI(result_reg);
5440 }
5441 } else { 4837 } else {
5442 Label bailout, done; 4838 Label bailout, done;
5443 if (CpuFeatures::IsSafeForSnapshot(isolate(), SSE2)) { 4839 XMMRegister input_reg = ToDoubleRegister(input);
5444 CpuFeatureScope scope(masm(), SSE2); 4840 XMMRegister xmm_scratch = double_scratch0();
5445 XMMRegister input_reg = ToDoubleRegister(input); 4841 __ DoubleToI(result_reg, input_reg, xmm_scratch,
5446 XMMRegister xmm_scratch = double_scratch0(); 4842 instr->hydrogen()->GetMinusZeroMode(), &bailout, Label::kNear);
5447 __ DoubleToI(result_reg, input_reg, xmm_scratch,
5448 instr->hydrogen()->GetMinusZeroMode(), &bailout, Label::kNear);
5449 } else {
5450 X87Register input_reg = ToX87Register(input);
5451 X87Fxch(input_reg);
5452 __ X87TOSToI(result_reg, instr->hydrogen()->GetMinusZeroMode(),
5453 &bailout, Label::kNear);
5454 }
5455 __ jmp(&done, Label::kNear); 4843 __ jmp(&done, Label::kNear);
5456 __ bind(&bailout); 4844 __ bind(&bailout);
5457 DeoptimizeIf(no_condition, instr->environment()); 4845 DeoptimizeIf(no_condition, instr->environment());
5458 __ bind(&done); 4846 __ bind(&done);
5459 } 4847 }
5460 } 4848 }
5461 4849
5462 4850
5463 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) { 4851 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) {
5464 LOperand* input = instr->value(); 4852 LOperand* input = instr->value();
5465 ASSERT(input->IsDoubleRegister()); 4853 ASSERT(input->IsDoubleRegister());
5466 LOperand* result = instr->result(); 4854 LOperand* result = instr->result();
5467 ASSERT(result->IsRegister()); 4855 ASSERT(result->IsRegister());
5468 Register result_reg = ToRegister(result); 4856 Register result_reg = ToRegister(result);
5469 4857
5470 Label bailout, done; 4858 Label bailout, done;
5471 if (CpuFeatures::IsSafeForSnapshot(isolate(), SSE2)) { 4859 XMMRegister input_reg = ToDoubleRegister(input);
5472 CpuFeatureScope scope(masm(), SSE2); 4860 XMMRegister xmm_scratch = double_scratch0();
5473 XMMRegister input_reg = ToDoubleRegister(input); 4861 __ DoubleToI(result_reg, input_reg, xmm_scratch,
5474 XMMRegister xmm_scratch = double_scratch0(); 4862 instr->hydrogen()->GetMinusZeroMode(), &bailout, Label::kNear);
5475 __ DoubleToI(result_reg, input_reg, xmm_scratch,
5476 instr->hydrogen()->GetMinusZeroMode(), &bailout, Label::kNear);
5477 } else {
5478 X87Register input_reg = ToX87Register(input);
5479 X87Fxch(input_reg);
5480 __ X87TOSToI(result_reg, instr->hydrogen()->GetMinusZeroMode(),
5481 &bailout, Label::kNear);
5482 }
5483 __ jmp(&done, Label::kNear); 4863 __ jmp(&done, Label::kNear);
5484 __ bind(&bailout); 4864 __ bind(&bailout);
5485 DeoptimizeIf(no_condition, instr->environment()); 4865 DeoptimizeIf(no_condition, instr->environment());
5486 __ bind(&done); 4866 __ bind(&done);
5487 4867
5488 __ SmiTag(result_reg); 4868 __ SmiTag(result_reg);
5489 DeoptimizeIf(overflow, instr->environment()); 4869 DeoptimizeIf(overflow, instr->environment());
5490 } 4870 }
5491 4871
5492 4872
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
5576 4956
5577 __ test(eax, Immediate(kSmiTagMask)); 4957 __ test(eax, Immediate(kSmiTagMask));
5578 } 4958 }
5579 DeoptimizeIf(zero, instr->environment()); 4959 DeoptimizeIf(zero, instr->environment());
5580 } 4960 }
5581 4961
5582 4962
5583 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { 4963 void LCodeGen::DoCheckMaps(LCheckMaps* instr) {
5584 class DeferredCheckMaps V8_FINAL : public LDeferredCode { 4964 class DeferredCheckMaps V8_FINAL : public LDeferredCode {
5585 public: 4965 public:
5586 DeferredCheckMaps(LCodeGen* codegen, 4966 DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr, Register object)
5587 LCheckMaps* instr, 4967 : LDeferredCode(codegen), instr_(instr), object_(object) {
5588 Register object,
5589 const X87Stack& x87_stack)
5590 : LDeferredCode(codegen, x87_stack), instr_(instr), object_(object) {
5591 SetExit(check_maps()); 4968 SetExit(check_maps());
5592 } 4969 }
5593 virtual void Generate() V8_OVERRIDE { 4970 virtual void Generate() V8_OVERRIDE {
5594 codegen()->DoDeferredInstanceMigration(instr_, object_); 4971 codegen()->DoDeferredInstanceMigration(instr_, object_);
5595 } 4972 }
5596 Label* check_maps() { return &check_maps_; } 4973 Label* check_maps() { return &check_maps_; }
5597 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } 4974 virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
5598 private: 4975 private:
5599 LCheckMaps* instr_; 4976 LCheckMaps* instr_;
5600 Label check_maps_; 4977 Label check_maps_;
5601 Register object_; 4978 Register object_;
5602 }; 4979 };
5603 4980
5604 if (instr->hydrogen()->IsStabilityCheck()) { 4981 if (instr->hydrogen()->IsStabilityCheck()) {
5605 const UniqueSet<Map>* maps = instr->hydrogen()->maps(); 4982 const UniqueSet<Map>* maps = instr->hydrogen()->maps();
5606 for (int i = 0; i < maps->size(); ++i) { 4983 for (int i = 0; i < maps->size(); ++i) {
5607 AddStabilityDependency(maps->at(i).handle()); 4984 AddStabilityDependency(maps->at(i).handle());
5608 } 4985 }
5609 return; 4986 return;
5610 } 4987 }
5611 4988
5612 LOperand* input = instr->value(); 4989 LOperand* input = instr->value();
5613 ASSERT(input->IsRegister()); 4990 ASSERT(input->IsRegister());
5614 Register reg = ToRegister(input); 4991 Register reg = ToRegister(input);
5615 4992
5616 DeferredCheckMaps* deferred = NULL; 4993 DeferredCheckMaps* deferred = NULL;
5617 if (instr->hydrogen()->HasMigrationTarget()) { 4994 if (instr->hydrogen()->HasMigrationTarget()) {
5618 deferred = new(zone()) DeferredCheckMaps(this, instr, reg, x87_stack_); 4995 deferred = new(zone()) DeferredCheckMaps(this, instr, reg);
5619 __ bind(deferred->check_maps()); 4996 __ bind(deferred->check_maps());
5620 } 4997 }
5621 4998
5622 const UniqueSet<Map>* maps = instr->hydrogen()->maps(); 4999 const UniqueSet<Map>* maps = instr->hydrogen()->maps();
5623 Label success; 5000 Label success;
5624 for (int i = 0; i < maps->size() - 1; i++) { 5001 for (int i = 0; i < maps->size() - 1; i++) {
5625 Handle<Map> map = maps->at(i).handle(); 5002 Handle<Map> map = maps->at(i).handle();
5626 __ CompareMap(reg, map); 5003 __ CompareMap(reg, map);
5627 __ j(equal, &success, Label::kNear); 5004 __ j(equal, &success, Label::kNear);
5628 } 5005 }
5629 5006
5630 Handle<Map> map = maps->at(maps->size() - 1).handle(); 5007 Handle<Map> map = maps->at(maps->size() - 1).handle();
5631 __ CompareMap(reg, map); 5008 __ CompareMap(reg, map);
5632 if (instr->hydrogen()->HasMigrationTarget()) { 5009 if (instr->hydrogen()->HasMigrationTarget()) {
5633 __ j(not_equal, deferred->entry()); 5010 __ j(not_equal, deferred->entry());
5634 } else { 5011 } else {
5635 DeoptimizeIf(not_equal, instr->environment()); 5012 DeoptimizeIf(not_equal, instr->environment());
5636 } 5013 }
5637 5014
5638 __ bind(&success); 5015 __ bind(&success);
5639 } 5016 }
5640 5017
5641 5018
5642 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { 5019 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) {
5643 CpuFeatureScope scope(masm(), SSE2);
5644 XMMRegister value_reg = ToDoubleRegister(instr->unclamped()); 5020 XMMRegister value_reg = ToDoubleRegister(instr->unclamped());
5645 XMMRegister xmm_scratch = double_scratch0(); 5021 XMMRegister xmm_scratch = double_scratch0();
5646 Register result_reg = ToRegister(instr->result()); 5022 Register result_reg = ToRegister(instr->result());
5647 __ ClampDoubleToUint8(value_reg, xmm_scratch, result_reg); 5023 __ ClampDoubleToUint8(value_reg, xmm_scratch, result_reg);
5648 } 5024 }
5649 5025
5650 5026
5651 void LCodeGen::DoClampIToUint8(LClampIToUint8* instr) { 5027 void LCodeGen::DoClampIToUint8(LClampIToUint8* instr) {
5652 ASSERT(instr->unclamped()->Equals(instr->result())); 5028 ASSERT(instr->unclamped()->Equals(instr->result()));
5653 Register value_reg = ToRegister(instr->result()); 5029 Register value_reg = ToRegister(instr->result());
5654 __ ClampUint8(value_reg); 5030 __ ClampUint8(value_reg);
5655 } 5031 }
5656 5032
5657 5033
5658 void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) { 5034 void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) {
5659 CpuFeatureScope scope(masm(), SSE2);
5660
5661 ASSERT(instr->unclamped()->Equals(instr->result())); 5035 ASSERT(instr->unclamped()->Equals(instr->result()));
5662 Register input_reg = ToRegister(instr->unclamped()); 5036 Register input_reg = ToRegister(instr->unclamped());
5663 XMMRegister temp_xmm_reg = ToDoubleRegister(instr->temp_xmm()); 5037 XMMRegister temp_xmm_reg = ToDoubleRegister(instr->temp_xmm());
5664 XMMRegister xmm_scratch = double_scratch0(); 5038 XMMRegister xmm_scratch = double_scratch0();
5665 Label is_smi, done, heap_number; 5039 Label is_smi, done, heap_number;
5666 5040
5667 __ JumpIfSmi(input_reg, &is_smi); 5041 __ JumpIfSmi(input_reg, &is_smi);
5668 5042
5669 // Check for heap number 5043 // Check for heap number
5670 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), 5044 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
(...skipping 14 matching lines...) Expand all
5685 __ jmp(&done, Label::kNear); 5059 __ jmp(&done, Label::kNear);
5686 5060
5687 // smi 5061 // smi
5688 __ bind(&is_smi); 5062 __ bind(&is_smi);
5689 __ SmiUntag(input_reg); 5063 __ SmiUntag(input_reg);
5690 __ ClampUint8(input_reg); 5064 __ ClampUint8(input_reg);
5691 __ bind(&done); 5065 __ bind(&done);
5692 } 5066 }
5693 5067
5694 5068
5695 void LCodeGen::DoClampTToUint8NoSSE2(LClampTToUint8NoSSE2* instr) {
5696 Register input_reg = ToRegister(instr->unclamped());
5697 Register result_reg = ToRegister(instr->result());
5698 Register scratch = ToRegister(instr->scratch());
5699 Register scratch2 = ToRegister(instr->scratch2());
5700 Register scratch3 = ToRegister(instr->scratch3());
5701 Label is_smi, done, heap_number, valid_exponent,
5702 largest_value, zero_result, maybe_nan_or_infinity;
5703
5704 __ JumpIfSmi(input_reg, &is_smi);
5705
5706 // Check for heap number
5707 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
5708 factory()->heap_number_map());
5709 __ j(equal, &heap_number, Label::kNear);
5710
5711 // Check for undefined. Undefined is converted to zero for clamping
5712 // conversions.
5713 __ cmp(input_reg, factory()->undefined_value());
5714 DeoptimizeIf(not_equal, instr->environment());
5715 __ jmp(&zero_result, Label::kNear);
5716
5717 // Heap number
5718 __ bind(&heap_number);
5719
5720 // Surprisingly, all of the hand-crafted bit-manipulations below are much
5721 // faster than the x86 FPU built-in instruction, especially since "banker's
5722 // rounding" would be additionally very expensive
5723
5724 // Get exponent word.
5725 __ mov(scratch, FieldOperand(input_reg, HeapNumber::kExponentOffset));
5726 __ mov(scratch3, FieldOperand(input_reg, HeapNumber::kMantissaOffset));
5727
5728 // Test for negative values --> clamp to zero
5729 __ test(scratch, scratch);
5730 __ j(negative, &zero_result, Label::kNear);
5731
5732 // Get exponent alone in scratch2.
5733 __ mov(scratch2, scratch);
5734 __ and_(scratch2, HeapNumber::kExponentMask);
5735 __ shr(scratch2, HeapNumber::kExponentShift);
5736 __ j(zero, &zero_result, Label::kNear);
5737 __ sub(scratch2, Immediate(HeapNumber::kExponentBias - 1));
5738 __ j(negative, &zero_result, Label::kNear);
5739
5740 const uint32_t non_int8_exponent = 7;
5741 __ cmp(scratch2, Immediate(non_int8_exponent + 1));
5742 // If the exponent is too big, check for special values.
5743 __ j(greater, &maybe_nan_or_infinity, Label::kNear);
5744
5745 __ bind(&valid_exponent);
5746 // Exponent word in scratch, exponent in scratch2. We know that 0 <= exponent
5747 // < 7. The shift bias is the number of bits to shift the mantissa such that
5748 // with an exponent of 7 such the that top-most one is in bit 30, allowing
5749 // detection the rounding overflow of a 255.5 to 256 (bit 31 goes from 0 to
5750 // 1).
5751 int shift_bias = (30 - HeapNumber::kExponentShift) - 7 - 1;
5752 __ lea(result_reg, MemOperand(scratch2, shift_bias));
5753 // Here result_reg (ecx) is the shift, scratch is the exponent word. Get the
5754 // top bits of the mantissa.
5755 __ and_(scratch, HeapNumber::kMantissaMask);
5756 // Put back the implicit 1 of the mantissa
5757 __ or_(scratch, 1 << HeapNumber::kExponentShift);
5758 // Shift up to round
5759 __ shl_cl(scratch);
5760 // Use "banker's rounding" to spec: If fractional part of number is 0.5, then
5761 // use the bit in the "ones" place and add it to the "halves" place, which has
5762 // the effect of rounding to even.
5763 __ mov(scratch2, scratch);
5764 const uint32_t one_half_bit_shift = 30 - sizeof(uint8_t) * 8;
5765 const uint32_t one_bit_shift = one_half_bit_shift + 1;
5766 __ and_(scratch2, Immediate((1 << one_bit_shift) - 1));
5767 __ cmp(scratch2, Immediate(1 << one_half_bit_shift));
5768 Label no_round;
5769 __ j(less, &no_round, Label::kNear);
5770 Label round_up;
5771 __ mov(scratch2, Immediate(1 << one_half_bit_shift));
5772 __ j(greater, &round_up, Label::kNear);
5773 __ test(scratch3, scratch3);
5774 __ j(not_zero, &round_up, Label::kNear);
5775 __ mov(scratch2, scratch);
5776 __ and_(scratch2, Immediate(1 << one_bit_shift));
5777 __ shr(scratch2, 1);
5778 __ bind(&round_up);
5779 __ add(scratch, scratch2);
5780 __ j(overflow, &largest_value, Label::kNear);
5781 __ bind(&no_round);
5782 __ shr(scratch, 23);
5783 __ mov(result_reg, scratch);
5784 __ jmp(&done, Label::kNear);
5785
5786 __ bind(&maybe_nan_or_infinity);
5787 // Check for NaN/Infinity, all other values map to 255
5788 __ cmp(scratch2, Immediate(HeapNumber::kInfinityOrNanExponent + 1));
5789 __ j(not_equal, &largest_value, Label::kNear);
5790
5791 // Check for NaN, which differs from Infinity in that at least one mantissa
5792 // bit is set.
5793 __ and_(scratch, HeapNumber::kMantissaMask);
5794 __ or_(scratch, FieldOperand(input_reg, HeapNumber::kMantissaOffset));
5795 __ j(not_zero, &zero_result, Label::kNear); // M!=0 --> NaN
5796 // Infinity -> Fall through to map to 255.
5797
5798 __ bind(&largest_value);
5799 __ mov(result_reg, Immediate(255));
5800 __ jmp(&done, Label::kNear);
5801
5802 __ bind(&zero_result);
5803 __ xor_(result_reg, result_reg);
5804 __ jmp(&done, Label::kNear);
5805
5806 // smi
5807 __ bind(&is_smi);
5808 if (!input_reg.is(result_reg)) {
5809 __ mov(result_reg, input_reg);
5810 }
5811 __ SmiUntag(result_reg);
5812 __ ClampUint8(result_reg);
5813 __ bind(&done);
5814 }
5815
5816
5817 void LCodeGen::DoDoubleBits(LDoubleBits* instr) { 5069 void LCodeGen::DoDoubleBits(LDoubleBits* instr) {
5818 CpuFeatureScope scope(masm(), SSE2);
5819 XMMRegister value_reg = ToDoubleRegister(instr->value()); 5070 XMMRegister value_reg = ToDoubleRegister(instr->value());
5820 Register result_reg = ToRegister(instr->result()); 5071 Register result_reg = ToRegister(instr->result());
5821 if (instr->hydrogen()->bits() == HDoubleBits::HIGH) { 5072 if (instr->hydrogen()->bits() == HDoubleBits::HIGH) {
5822 if (CpuFeatures::IsSupported(SSE4_1)) { 5073 if (CpuFeatures::IsSupported(SSE4_1)) {
5823 CpuFeatureScope scope2(masm(), SSE4_1); 5074 CpuFeatureScope scope2(masm(), SSE4_1);
5824 __ pextrd(result_reg, value_reg, 1); 5075 __ pextrd(result_reg, value_reg, 1);
5825 } else { 5076 } else {
5826 XMMRegister xmm_scratch = double_scratch0(); 5077 XMMRegister xmm_scratch = double_scratch0();
5827 __ pshufd(xmm_scratch, value_reg, 1); 5078 __ pshufd(xmm_scratch, value_reg, 1);
5828 __ movd(result_reg, xmm_scratch); 5079 __ movd(result_reg, xmm_scratch);
5829 } 5080 }
5830 } else { 5081 } else {
5831 __ movd(result_reg, value_reg); 5082 __ movd(result_reg, value_reg);
5832 } 5083 }
5833 } 5084 }
5834 5085
5835 5086
5836 void LCodeGen::DoConstructDouble(LConstructDouble* instr) { 5087 void LCodeGen::DoConstructDouble(LConstructDouble* instr) {
5837 Register hi_reg = ToRegister(instr->hi()); 5088 Register hi_reg = ToRegister(instr->hi());
5838 Register lo_reg = ToRegister(instr->lo()); 5089 Register lo_reg = ToRegister(instr->lo());
5839 XMMRegister result_reg = ToDoubleRegister(instr->result()); 5090 XMMRegister result_reg = ToDoubleRegister(instr->result());
5840 CpuFeatureScope scope(masm(), SSE2);
5841 5091
5842 if (CpuFeatures::IsSupported(SSE4_1)) { 5092 if (CpuFeatures::IsSupported(SSE4_1)) {
5843 CpuFeatureScope scope2(masm(), SSE4_1); 5093 CpuFeatureScope scope2(masm(), SSE4_1);
5844 __ movd(result_reg, lo_reg); 5094 __ movd(result_reg, lo_reg);
5845 __ pinsrd(result_reg, hi_reg, 1); 5095 __ pinsrd(result_reg, hi_reg, 1);
5846 } else { 5096 } else {
5847 XMMRegister xmm_scratch = double_scratch0(); 5097 XMMRegister xmm_scratch = double_scratch0();
5848 __ movd(result_reg, hi_reg); 5098 __ movd(result_reg, hi_reg);
5849 __ psllq(result_reg, 32); 5099 __ psllq(result_reg, 32);
5850 __ movd(xmm_scratch, lo_reg); 5100 __ movd(xmm_scratch, lo_reg);
5851 __ orps(result_reg, xmm_scratch); 5101 __ orps(result_reg, xmm_scratch);
5852 } 5102 }
5853 } 5103 }
5854 5104
5855 5105
5856 void LCodeGen::DoAllocate(LAllocate* instr) { 5106 void LCodeGen::DoAllocate(LAllocate* instr) {
5857 class DeferredAllocate V8_FINAL : public LDeferredCode { 5107 class DeferredAllocate V8_FINAL : public LDeferredCode {
5858 public: 5108 public:
5859 DeferredAllocate(LCodeGen* codegen, 5109 DeferredAllocate(LCodeGen* codegen, LAllocate* instr)
5860 LAllocate* instr, 5110 : LDeferredCode(codegen), instr_(instr) { }
5861 const X87Stack& x87_stack)
5862 : LDeferredCode(codegen, x87_stack), instr_(instr) { }
5863 virtual void Generate() V8_OVERRIDE { 5111 virtual void Generate() V8_OVERRIDE {
5864 codegen()->DoDeferredAllocate(instr_); 5112 codegen()->DoDeferredAllocate(instr_);
5865 } 5113 }
5866 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } 5114 virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
5867 private: 5115 private:
5868 LAllocate* instr_; 5116 LAllocate* instr_;
5869 }; 5117 };
5870 5118
5871 DeferredAllocate* deferred = 5119 DeferredAllocate* deferred = new(zone()) DeferredAllocate(this, instr);
5872 new(zone()) DeferredAllocate(this, instr, x87_stack_);
5873 5120
5874 Register result = ToRegister(instr->result()); 5121 Register result = ToRegister(instr->result());
5875 Register temp = ToRegister(instr->temp()); 5122 Register temp = ToRegister(instr->temp());
5876 5123
5877 // Allocate memory for the object. 5124 // Allocate memory for the object.
5878 AllocationFlags flags = TAG_OBJECT; 5125 AllocationFlags flags = TAG_OBJECT;
5879 if (instr->hydrogen()->MustAllocateDoubleAligned()) { 5126 if (instr->hydrogen()->MustAllocateDoubleAligned()) {
5880 flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT); 5127 flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT);
5881 } 5128 }
5882 if (instr->hydrogen()->IsOldPointerSpaceAllocation()) { 5129 if (instr->hydrogen()->IsOldPointerSpaceAllocation()) {
(...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after
6227 instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); 5474 instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
6228 ASSERT(instr->HasEnvironment()); 5475 ASSERT(instr->HasEnvironment());
6229 LEnvironment* env = instr->environment(); 5476 LEnvironment* env = instr->environment();
6230 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); 5477 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
6231 } 5478 }
6232 5479
6233 5480
6234 void LCodeGen::DoStackCheck(LStackCheck* instr) { 5481 void LCodeGen::DoStackCheck(LStackCheck* instr) {
6235 class DeferredStackCheck V8_FINAL : public LDeferredCode { 5482 class DeferredStackCheck V8_FINAL : public LDeferredCode {
6236 public: 5483 public:
6237 DeferredStackCheck(LCodeGen* codegen, 5484 DeferredStackCheck(LCodeGen* codegen, LStackCheck* instr)
6238 LStackCheck* instr, 5485 : LDeferredCode(codegen), instr_(instr) { }
6239 const X87Stack& x87_stack)
6240 : LDeferredCode(codegen, x87_stack), instr_(instr) { }
6241 virtual void Generate() V8_OVERRIDE { 5486 virtual void Generate() V8_OVERRIDE {
6242 codegen()->DoDeferredStackCheck(instr_); 5487 codegen()->DoDeferredStackCheck(instr_);
6243 } 5488 }
6244 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } 5489 virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
6245 private: 5490 private:
6246 LStackCheck* instr_; 5491 LStackCheck* instr_;
6247 }; 5492 };
6248 5493
6249 ASSERT(instr->HasEnvironment()); 5494 ASSERT(instr->HasEnvironment());
6250 LEnvironment* env = instr->environment(); 5495 LEnvironment* env = instr->environment();
(...skipping 10 matching lines...) Expand all
6261 ASSERT(instr->context()->IsRegister()); 5506 ASSERT(instr->context()->IsRegister());
6262 ASSERT(ToRegister(instr->context()).is(esi)); 5507 ASSERT(ToRegister(instr->context()).is(esi));
6263 CallCode(isolate()->builtins()->StackCheck(), 5508 CallCode(isolate()->builtins()->StackCheck(),
6264 RelocInfo::CODE_TARGET, 5509 RelocInfo::CODE_TARGET,
6265 instr); 5510 instr);
6266 __ bind(&done); 5511 __ bind(&done);
6267 } else { 5512 } else {
6268 ASSERT(instr->hydrogen()->is_backwards_branch()); 5513 ASSERT(instr->hydrogen()->is_backwards_branch());
6269 // Perform stack overflow check if this goto needs it before jumping. 5514 // Perform stack overflow check if this goto needs it before jumping.
6270 DeferredStackCheck* deferred_stack_check = 5515 DeferredStackCheck* deferred_stack_check =
6271 new(zone()) DeferredStackCheck(this, instr, x87_stack_); 5516 new(zone()) DeferredStackCheck(this, instr);
6272 ExternalReference stack_limit = 5517 ExternalReference stack_limit =
6273 ExternalReference::address_of_stack_limit(isolate()); 5518 ExternalReference::address_of_stack_limit(isolate());
6274 __ cmp(esp, Operand::StaticVariable(stack_limit)); 5519 __ cmp(esp, Operand::StaticVariable(stack_limit));
6275 __ j(below, deferred_stack_check->entry()); 5520 __ j(below, deferred_stack_check->entry());
6276 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); 5521 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size());
6277 __ bind(instr->done_label()); 5522 __ bind(instr->done_label());
6278 deferred_stack_check->SetExit(instr->done_label()); 5523 deferred_stack_check->SetExit(instr->done_label());
6279 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); 5524 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
6280 // Don't record a deoptimization index for the safepoint here. 5525 // Don't record a deoptimization index for the safepoint here.
6281 // This will be done explicitly when emitting call and the safepoint in 5526 // This will be done explicitly when emitting call and the safepoint in
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
6375 __ StoreToSafepointRegisterSlot(object, eax); 5620 __ StoreToSafepointRegisterSlot(object, eax);
6376 } 5621 }
6377 5622
6378 5623
6379 void LCodeGen::DoLoadFieldByIndex(LLoadFieldByIndex* instr) { 5624 void LCodeGen::DoLoadFieldByIndex(LLoadFieldByIndex* instr) {
6380 class DeferredLoadMutableDouble V8_FINAL : public LDeferredCode { 5625 class DeferredLoadMutableDouble V8_FINAL : public LDeferredCode {
6381 public: 5626 public:
6382 DeferredLoadMutableDouble(LCodeGen* codegen, 5627 DeferredLoadMutableDouble(LCodeGen* codegen,
6383 LLoadFieldByIndex* instr, 5628 LLoadFieldByIndex* instr,
6384 Register object, 5629 Register object,
6385 Register index, 5630 Register index)
6386 const X87Stack& x87_stack) 5631 : LDeferredCode(codegen),
6387 : LDeferredCode(codegen, x87_stack),
6388 instr_(instr), 5632 instr_(instr),
6389 object_(object), 5633 object_(object),
6390 index_(index) { 5634 index_(index) {
6391 } 5635 }
6392 virtual void Generate() V8_OVERRIDE { 5636 virtual void Generate() V8_OVERRIDE {
6393 codegen()->DoDeferredLoadMutableDouble(instr_, object_, index_); 5637 codegen()->DoDeferredLoadMutableDouble(instr_, object_, index_);
6394 } 5638 }
6395 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } 5639 virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
6396 private: 5640 private:
6397 LLoadFieldByIndex* instr_; 5641 LLoadFieldByIndex* instr_;
6398 Register object_; 5642 Register object_;
6399 Register index_; 5643 Register index_;
6400 }; 5644 };
6401 5645
6402 Register object = ToRegister(instr->object()); 5646 Register object = ToRegister(instr->object());
6403 Register index = ToRegister(instr->index()); 5647 Register index = ToRegister(instr->index());
6404 5648
6405 DeferredLoadMutableDouble* deferred; 5649 DeferredLoadMutableDouble* deferred;
6406 deferred = new(zone()) DeferredLoadMutableDouble( 5650 deferred = new(zone()) DeferredLoadMutableDouble(
6407 this, instr, object, index, x87_stack_); 5651 this, instr, object, index);
6408 5652
6409 Label out_of_object, done; 5653 Label out_of_object, done;
6410 __ test(index, Immediate(Smi::FromInt(1))); 5654 __ test(index, Immediate(Smi::FromInt(1)));
6411 __ j(not_zero, deferred->entry()); 5655 __ j(not_zero, deferred->entry());
6412 5656
6413 __ sar(index, 1); 5657 __ sar(index, 1);
6414 5658
6415 __ cmp(index, Immediate(0)); 5659 __ cmp(index, Immediate(0));
6416 __ j(less, &out_of_object, Label::kNear); 5660 __ j(less, &out_of_object, Label::kNear);
6417 __ mov(object, FieldOperand(object, 5661 __ mov(object, FieldOperand(object,
(...skipping 13 matching lines...) Expand all
6431 __ bind(deferred->exit()); 5675 __ bind(deferred->exit());
6432 __ bind(&done); 5676 __ bind(&done);
6433 } 5677 }
6434 5678
6435 5679
6436 #undef __ 5680 #undef __
6437 5681
6438 } } // namespace v8::internal 5682 } } // namespace v8::internal
6439 5683
6440 #endif // V8_TARGET_ARCH_IA32 5684 #endif // V8_TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698