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

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

Issue 293743005: Introduce x87 port (Closed) Base URL: git://github.com/v8/v8.git@master
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
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_X87
8 8
9 #include "ia32/lithium-codegen-ia32.h" 9 #include "x87/lithium-codegen-x87.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
20 // When invoking builtins, we need to record the safepoint in the middle of 21 // When invoking builtins, we need to record the safepoint in the middle of
21 // the invoke instruction sequence generated by the macro assembler. 22 // the invoke instruction sequence generated by the macro assembler.
22 class SafepointGenerator V8_FINAL : public CallWrapper { 23 class SafepointGenerator V8_FINAL : public CallWrapper {
23 public: 24 public:
24 SafepointGenerator(LCodeGen* codegen, 25 SafepointGenerator(LCodeGen* codegen,
25 LPointerMap* pointers, 26 LPointerMap* pointers,
26 Safepoint::DeoptMode mode) 27 Safepoint::DeoptMode mode)
27 : codegen_(codegen), 28 : codegen_(codegen),
28 pointers_(pointers), 29 pointers_(pointers),
29 deopt_mode_(mode) {} 30 deopt_mode_(mode) {}
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
84 #ifdef _MSC_VER 85 #ifdef _MSC_VER
85 void LCodeGen::MakeSureStackPagesMapped(int offset) { 86 void LCodeGen::MakeSureStackPagesMapped(int offset) {
86 const int kPageSize = 4 * KB; 87 const int kPageSize = 4 * KB;
87 for (offset -= kPageSize; offset > 0; offset -= kPageSize) { 88 for (offset -= kPageSize; offset > 0; offset -= kPageSize) {
88 __ mov(Operand(esp, offset), eax); 89 __ mov(Operand(esp, offset), eax);
89 } 90 }
90 } 91 }
91 #endif 92 #endif
92 93
93 94
94 void LCodeGen::SaveCallerDoubles() {
95 ASSERT(info()->saves_caller_doubles());
96 ASSERT(NeedsEagerFrame());
97 Comment(";;; Save clobbered callee double registers");
98 int count = 0;
99 BitVector* doubles = chunk()->allocated_double_registers();
100 BitVector::Iterator save_iterator(doubles);
101 while (!save_iterator.Done()) {
102 __ movsd(MemOperand(esp, count * kDoubleSize),
103 XMMRegister::FromAllocationIndex(save_iterator.Current()));
104 save_iterator.Advance();
105 count++;
106 }
107 }
108
109
110 void LCodeGen::RestoreCallerDoubles() {
111 ASSERT(info()->saves_caller_doubles());
112 ASSERT(NeedsEagerFrame());
113 Comment(";;; Restore clobbered callee double registers");
114 BitVector* doubles = chunk()->allocated_double_registers();
115 BitVector::Iterator save_iterator(doubles);
116 int count = 0;
117 while (!save_iterator.Done()) {
118 __ movsd(XMMRegister::FromAllocationIndex(save_iterator.Current()),
119 MemOperand(esp, count * kDoubleSize));
120 save_iterator.Advance();
121 count++;
122 }
123 }
124
125
126 bool LCodeGen::GeneratePrologue() { 95 bool LCodeGen::GeneratePrologue() {
127 ASSERT(is_generating()); 96 ASSERT(is_generating());
128 97
129 if (info()->IsOptimizing()) { 98 if (info()->IsOptimizing()) {
130 ProfileEntryHookStub::MaybeCallEntryHook(masm_); 99 ProfileEntryHookStub::MaybeCallEntryHook(masm_);
131 100
132 #ifdef DEBUG 101 #ifdef DEBUG
133 if (strlen(FLAG_stop_at) > 0 && 102 if (strlen(FLAG_stop_at) > 0 &&
134 info_->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { 103 info_->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) {
135 __ int3(); 104 __ int3();
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 Comment(";;; Store dynamic frame alignment tag for spilled doubles"); 208 Comment(";;; Store dynamic frame alignment tag for spilled doubles");
240 // Store dynamic frame alignment state in the first local. 209 // Store dynamic frame alignment state in the first local.
241 int offset = JavaScriptFrameConstants::kDynamicAlignmentStateOffset; 210 int offset = JavaScriptFrameConstants::kDynamicAlignmentStateOffset;
242 if (dynamic_frame_alignment_) { 211 if (dynamic_frame_alignment_) {
243 __ mov(Operand(ebp, offset), edx); 212 __ mov(Operand(ebp, offset), edx);
244 } else { 213 } else {
245 __ mov(Operand(ebp, offset), Immediate(kNoAlignmentPadding)); 214 __ mov(Operand(ebp, offset), Immediate(kNoAlignmentPadding));
246 } 215 }
247 } 216 }
248 } 217 }
249
250 if (info()->saves_caller_doubles()) SaveCallerDoubles();
251 } 218 }
252 219
253 // Possibly allocate a local context. 220 // Possibly allocate a local context.
254 int heap_slots = info_->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; 221 int heap_slots = info_->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
255 if (heap_slots > 0) { 222 if (heap_slots > 0) {
256 Comment(";;; Allocate local context"); 223 Comment(";;; Allocate local context");
257 // Argument to NewContext is the function, which is still in edi. 224 // Argument to NewContext is the function, which is still in edi.
258 if (heap_slots <= FastNewContextStub::kMaximumSlots) { 225 if (heap_slots <= FastNewContextStub::kMaximumSlots) {
259 FastNewContextStub stub(isolate(), heap_slots); 226 FastNewContextStub stub(isolate(), heap_slots);
260 __ CallStub(&stub); 227 __ CallStub(&stub);
(...skipping 16 matching lines...) Expand all
277 (num_parameters - 1 - i) * kPointerSize; 244 (num_parameters - 1 - i) * kPointerSize;
278 // Load parameter from stack. 245 // Load parameter from stack.
279 __ mov(eax, Operand(ebp, parameter_offset)); 246 __ mov(eax, Operand(ebp, parameter_offset));
280 // Store it in the context. 247 // Store it in the context.
281 int context_offset = Context::SlotOffset(var->index()); 248 int context_offset = Context::SlotOffset(var->index());
282 __ mov(Operand(esi, context_offset), eax); 249 __ mov(Operand(esi, context_offset), eax);
283 // Update the write barrier. This clobbers eax and ebx. 250 // Update the write barrier. This clobbers eax and ebx.
284 __ RecordWriteContextSlot(esi, 251 __ RecordWriteContextSlot(esi,
285 context_offset, 252 context_offset,
286 eax, 253 eax,
287 ebx, 254 ebx);
288 kDontSaveFPRegs);
289 } 255 }
290 } 256 }
291 Comment(";;; End allocate local context"); 257 Comment(";;; End allocate local context");
292 } 258 }
293 259
294 // Trace the call. 260 // Trace the call.
295 if (FLAG_trace && info()->IsOptimizing()) { 261 if (FLAG_trace && info()->IsOptimizing()) {
296 // We have not executed any compiled code yet, so esi still holds the 262 // We have not executed any compiled code yet, so esi still holds the
297 // incoming context. 263 // incoming context.
298 __ CallRuntime(Runtime::kTraceEnter, 0); 264 __ CallRuntime(Runtime::kTraceEnter, 0);
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
352 } 318 }
353 319
354 320
355 void LCodeGen::GenerateBodyInstructionPre(LInstruction* instr) { 321 void LCodeGen::GenerateBodyInstructionPre(LInstruction* instr) {
356 if (instr->IsCall()) { 322 if (instr->IsCall()) {
357 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); 323 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size());
358 } 324 }
359 if (!instr->IsLazyBailout() && !instr->IsGap()) { 325 if (!instr->IsLazyBailout() && !instr->IsGap()) {
360 safepoints_.BumpLastLazySafepointIndex(); 326 safepoints_.BumpLastLazySafepointIndex();
361 } 327 }
328 FlushX87StackIfNecessary(instr);
329 }
330
331
332 void LCodeGen::GenerateBodyInstructionPost(LInstruction* instr) {
333 if (instr->IsGoto()) {
334 x87_stack_.LeavingBlock(current_block_, LGoto::cast(instr));
335 } else if (FLAG_debug_code && FLAG_enable_slow_asserts &&
336 !instr->IsGap() && !instr->IsReturn()) {
337 if (instr->ClobbersDoubleRegisters(isolate())) {
338 if (instr->HasDoubleRegisterResult()) {
339 ASSERT_EQ(1, x87_stack_.depth());
340 } else {
341 ASSERT_EQ(0, x87_stack_.depth());
342 }
343 }
344 __ VerifyX87StackDepth(x87_stack_.depth());
345 }
362 } 346 }
363 347
364 348
365 void LCodeGen::GenerateBodyInstructionPost(LInstruction* instr) { }
366
367
368 bool LCodeGen::GenerateJumpTable() { 349 bool LCodeGen::GenerateJumpTable() {
369 Label needs_frame; 350 Label needs_frame;
370 if (jump_table_.length() > 0) { 351 if (jump_table_.length() > 0) {
371 Comment(";;; -------------------- Jump table --------------------"); 352 Comment(";;; -------------------- Jump table --------------------");
372 } 353 }
373 for (int i = 0; i < jump_table_.length(); i++) { 354 for (int i = 0; i < jump_table_.length(); i++) {
374 __ bind(&jump_table_[i].label); 355 __ bind(&jump_table_[i].label);
375 Address entry = jump_table_[i].address; 356 Address entry = jump_table_[i].address;
376 Deoptimizer::BailoutType type = jump_table_[i].bailout_type; 357 Deoptimizer::BailoutType type = jump_table_[i].bailout_type;
377 int id = Deoptimizer::GetDeoptimizationId(isolate(), entry, type); 358 int id = Deoptimizer::GetDeoptimizationId(isolate(), entry, type);
(...skipping 23 matching lines...) Expand all
401 __ call(&push_approx_pc); 382 __ call(&push_approx_pc);
402 __ bind(&push_approx_pc); 383 __ bind(&push_approx_pc);
403 // Push the continuation which was stashed were the ebp should 384 // Push the continuation which was stashed were the ebp should
404 // be. Replace it with the saved ebp. 385 // be. Replace it with the saved ebp.
405 __ push(MemOperand(esp, 3 * kPointerSize)); 386 __ push(MemOperand(esp, 3 * kPointerSize));
406 __ mov(MemOperand(esp, 4 * kPointerSize), ebp); 387 __ mov(MemOperand(esp, 4 * kPointerSize), ebp);
407 __ lea(ebp, MemOperand(esp, 4 * kPointerSize)); 388 __ lea(ebp, MemOperand(esp, 4 * kPointerSize));
408 __ ret(0); // Call the continuation without clobbering registers. 389 __ ret(0); // Call the continuation without clobbering registers.
409 } 390 }
410 } else { 391 } else {
411 if (info()->saves_caller_doubles()) RestoreCallerDoubles();
412 __ call(entry, RelocInfo::RUNTIME_ENTRY); 392 __ call(entry, RelocInfo::RUNTIME_ENTRY);
413 } 393 }
414 } 394 }
415 return !is_aborted(); 395 return !is_aborted();
416 } 396 }
417 397
418 398
419 bool LCodeGen::GenerateDeferredCode() { 399 bool LCodeGen::GenerateDeferredCode() {
420 ASSERT(is_generating()); 400 ASSERT(is_generating());
421 if (deferred_.length() > 0) { 401 if (deferred_.length() > 0) {
422 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) { 402 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) {
423 LDeferredCode* code = deferred_[i]; 403 LDeferredCode* code = deferred_[i];
404 X87Stack copy(code->x87_stack());
405 x87_stack_ = copy;
424 406
425 HValue* value = 407 HValue* value =
426 instructions_->at(code->instruction_index())->hydrogen_value(); 408 instructions_->at(code->instruction_index())->hydrogen_value();
427 RecordAndWritePosition( 409 RecordAndWritePosition(
428 chunk()->graph()->SourcePositionToScriptPosition(value->position())); 410 chunk()->graph()->SourcePositionToScriptPosition(value->position()));
429 411
430 Comment(";;; <@%d,#%d> " 412 Comment(";;; <@%d,#%d> "
431 "-------------------- Deferred %s --------------------", 413 "-------------------- Deferred %s --------------------",
432 code->instruction_index(), 414 code->instruction_index(),
433 code->instr()->hydrogen_value()->id(), 415 code->instr()->hydrogen_value()->id(),
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
479 safepoints_.Emit(masm(), GetStackSlotCount()); 461 safepoints_.Emit(masm(), GetStackSlotCount());
480 return !is_aborted(); 462 return !is_aborted();
481 } 463 }
482 464
483 465
484 Register LCodeGen::ToRegister(int index) const { 466 Register LCodeGen::ToRegister(int index) const {
485 return Register::FromAllocationIndex(index); 467 return Register::FromAllocationIndex(index);
486 } 468 }
487 469
488 470
489 XMMRegister LCodeGen::ToDoubleRegister(int index) const { 471 X87Register LCodeGen::ToX87Register(int index) const {
490 return XMMRegister::FromAllocationIndex(index); 472 return X87Register::FromAllocationIndex(index);
491 } 473 }
492 474
493 475
476 void LCodeGen::X87LoadForUsage(X87Register reg) {
477 ASSERT(x87_stack_.Contains(reg));
478 x87_stack_.Fxch(reg);
479 x87_stack_.pop();
480 }
481
482
483 void LCodeGen::X87LoadForUsage(X87Register reg1, X87Register reg2) {
484 ASSERT(x87_stack_.Contains(reg1));
485 ASSERT(x87_stack_.Contains(reg2));
486 x87_stack_.Fxch(reg1, 1);
487 x87_stack_.Fxch(reg2);
488 x87_stack_.pop();
489 x87_stack_.pop();
490 }
491
492
493 void LCodeGen::X87Stack::Fxch(X87Register reg, int other_slot) {
494 ASSERT(is_mutable_);
495 ASSERT(Contains(reg) && stack_depth_ > other_slot);
496 int i = ArrayIndex(reg);
497 int st = st2idx(i);
498 if (st != other_slot) {
499 int other_i = st2idx(other_slot);
500 X87Register other = stack_[other_i];
501 stack_[other_i] = reg;
502 stack_[i] = other;
503 if (st == 0) {
504 __ fxch(other_slot);
505 } else if (other_slot == 0) {
506 __ fxch(st);
507 } else {
508 __ fxch(st);
509 __ fxch(other_slot);
510 __ fxch(st);
511 }
512 }
513 }
514
515
516 int LCodeGen::X87Stack::st2idx(int pos) {
517 return stack_depth_ - pos - 1;
518 }
519
520
521 int LCodeGen::X87Stack::ArrayIndex(X87Register reg) {
522 for (int i = 0; i < stack_depth_; i++) {
523 if (stack_[i].is(reg)) return i;
524 }
525 UNREACHABLE();
526 return -1;
527 }
528
529
530 bool LCodeGen::X87Stack::Contains(X87Register reg) {
531 for (int i = 0; i < stack_depth_; i++) {
532 if (stack_[i].is(reg)) return true;
533 }
534 return false;
535 }
536
537
538 void LCodeGen::X87Stack::Free(X87Register reg) {
539 ASSERT(is_mutable_);
540 ASSERT(Contains(reg));
541 int i = ArrayIndex(reg);
542 int st = st2idx(i);
543 if (st > 0) {
544 // keep track of how fstp(i) changes the order of elements
545 int tos_i = st2idx(0);
546 stack_[i] = stack_[tos_i];
547 }
548 pop();
549 __ fstp(st);
550 }
551
552
553 void LCodeGen::X87Mov(X87Register dst, Operand src, X87OperandType opts) {
554 if (x87_stack_.Contains(dst)) {
555 x87_stack_.Fxch(dst);
556 __ fstp(0);
557 } else {
558 x87_stack_.push(dst);
559 }
560 X87Fld(src, opts);
561 }
562
563
564 void LCodeGen::X87Fld(Operand src, X87OperandType opts) {
565 ASSERT(!src.is_reg_only());
566 switch (opts) {
567 case kX87DoubleOperand:
568 __ fld_d(src);
569 break;
570 case kX87FloatOperand:
571 __ fld_s(src);
572 break;
573 case kX87IntOperand:
574 __ fild_s(src);
575 break;
576 default:
577 UNREACHABLE();
578 }
579 }
580
581
582 void LCodeGen::X87Mov(Operand dst, X87Register src, X87OperandType opts) {
583 ASSERT(!dst.is_reg_only());
584 x87_stack_.Fxch(src);
585 switch (opts) {
586 case kX87DoubleOperand:
587 __ fst_d(dst);
588 break;
589 case kX87IntOperand:
590 __ fist_s(dst);
591 break;
592 default:
593 UNREACHABLE();
594 }
595 }
596
597
598 void LCodeGen::X87Stack::PrepareToWrite(X87Register reg) {
599 ASSERT(is_mutable_);
600 if (Contains(reg)) {
601 Free(reg);
602 }
603 // Mark this register as the next register to write to
604 stack_[stack_depth_] = reg;
605 }
606
607
608 void LCodeGen::X87Stack::CommitWrite(X87Register reg) {
609 ASSERT(is_mutable_);
610 // Assert the reg is prepared to write, but not on the virtual stack yet
611 ASSERT(!Contains(reg) && stack_[stack_depth_].is(reg) &&
612 stack_depth_ < X87Register::kMaxNumAllocatableRegisters);
613 stack_depth_++;
614 }
615
616
617 void LCodeGen::X87PrepareBinaryOp(
618 X87Register left, X87Register right, X87Register result) {
619 // You need to use DefineSameAsFirst for x87 instructions
620 ASSERT(result.is(left));
621 x87_stack_.Fxch(right, 1);
622 x87_stack_.Fxch(left);
623 }
624
625
626 void LCodeGen::X87Stack::FlushIfNecessary(LInstruction* instr, LCodeGen* cgen) {
627 if (stack_depth_ > 0 && instr->ClobbersDoubleRegisters(isolate())) {
628 bool double_inputs = instr->HasDoubleRegisterInput();
629
630 // Flush stack from tos down, since FreeX87() will mess with tos
631 for (int i = stack_depth_-1; i >= 0; i--) {
632 X87Register reg = stack_[i];
633 // Skip registers which contain the inputs for the next instruction
634 // when flushing the stack
635 if (double_inputs && instr->IsDoubleInput(reg, cgen)) {
636 continue;
637 }
638 Free(reg);
639 if (i < stack_depth_-1) i++;
640 }
641 }
642 if (instr->IsReturn()) {
643 while (stack_depth_ > 0) {
644 __ fstp(0);
645 stack_depth_--;
646 }
647 if (FLAG_debug_code && FLAG_enable_slow_asserts) __ VerifyX87StackDepth(0);
648 }
649 }
650
651
652 void LCodeGen::X87Stack::LeavingBlock(int current_block_id, LGoto* goto_instr) {
653 ASSERT(stack_depth_ <= 1);
654 // If ever used for new stubs producing two pairs of doubles joined into two
655 // phis this assert hits. That situation is not handled, since the two stacks
656 // might have st0 and st1 swapped.
657 if (current_block_id + 1 != goto_instr->block_id()) {
658 // If we have a value on the x87 stack on leaving a block, it must be a
659 // phi input. If the next block we compile is not the join block, we have
660 // to discard the stack state.
661 stack_depth_ = 0;
662 }
663 }
664
665
666 void LCodeGen::EmitFlushX87ForDeopt() {
667 // The deoptimizer does not support X87 Registers. But as long as we
668 // deopt from a stub its not a problem, since we will re-materialize the
669 // original stub inputs, which can't be double registers.
670 ASSERT(info()->IsStub());
671 if (FLAG_debug_code && FLAG_enable_slow_asserts) {
672 __ pushfd();
673 __ VerifyX87StackDepth(x87_stack_.depth());
674 __ popfd();
675 }
676 for (int i = 0; i < x87_stack_.depth(); i++) __ fstp(0);
677 }
678
679
494 Register LCodeGen::ToRegister(LOperand* op) const { 680 Register LCodeGen::ToRegister(LOperand* op) const {
495 ASSERT(op->IsRegister()); 681 ASSERT(op->IsRegister());
496 return ToRegister(op->index()); 682 return ToRegister(op->index());
497 } 683 }
498 684
499 685
500 XMMRegister LCodeGen::ToDoubleRegister(LOperand* op) const { 686 X87Register LCodeGen::ToX87Register(LOperand* op) const {
501 ASSERT(op->IsDoubleRegister()); 687 ASSERT(op->IsDoubleRegister());
502 return ToDoubleRegister(op->index()); 688 return ToX87Register(op->index());
503 } 689 }
504 690
505 691
506 int32_t LCodeGen::ToInteger32(LConstantOperand* op) const { 692 int32_t LCodeGen::ToInteger32(LConstantOperand* op) const {
507 return ToRepresentation(op, Representation::Integer32()); 693 return ToRepresentation(op, Representation::Integer32());
508 } 694 }
509 695
510 696
511 int32_t LCodeGen::ToRepresentation(LConstantOperand* op, 697 int32_t LCodeGen::ToRepresentation(LConstantOperand* op,
512 const Representation& r) const { 698 const Representation& r) const {
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
550 736
551 737
552 static int ArgumentsOffsetWithoutFrame(int index) { 738 static int ArgumentsOffsetWithoutFrame(int index) {
553 ASSERT(index < 0); 739 ASSERT(index < 0);
554 return -(index + 1) * kPointerSize + kPCOnStackSize; 740 return -(index + 1) * kPointerSize + kPCOnStackSize;
555 } 741 }
556 742
557 743
558 Operand LCodeGen::ToOperand(LOperand* op) const { 744 Operand LCodeGen::ToOperand(LOperand* op) const {
559 if (op->IsRegister()) return Operand(ToRegister(op)); 745 if (op->IsRegister()) return Operand(ToRegister(op));
560 if (op->IsDoubleRegister()) return Operand(ToDoubleRegister(op)); 746 ASSERT(!op->IsDoubleRegister());
561 ASSERT(op->IsStackSlot() || op->IsDoubleStackSlot()); 747 ASSERT(op->IsStackSlot() || op->IsDoubleStackSlot());
562 if (NeedsEagerFrame()) { 748 if (NeedsEagerFrame()) {
563 return Operand(ebp, StackSlotOffset(op->index())); 749 return Operand(ebp, StackSlotOffset(op->index()));
564 } else { 750 } else {
565 // Retrieve parameter without eager stack-frame relative to the 751 // Retrieve parameter without eager stack-frame relative to the
566 // stack-pointer. 752 // stack-pointer.
567 return Operand(esp, ArgumentsOffsetWithoutFrame(op->index())); 753 return Operand(esp, ArgumentsOffsetWithoutFrame(op->index()));
568 } 754 }
569 } 755 }
570 756
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
687 translation->StoreDoubleStackSlot(op->index()); 873 translation->StoreDoubleStackSlot(op->index());
688 } else if (op->IsRegister()) { 874 } else if (op->IsRegister()) {
689 Register reg = ToRegister(op); 875 Register reg = ToRegister(op);
690 if (is_tagged) { 876 if (is_tagged) {
691 translation->StoreRegister(reg); 877 translation->StoreRegister(reg);
692 } else if (is_uint32) { 878 } else if (is_uint32) {
693 translation->StoreUint32Register(reg); 879 translation->StoreUint32Register(reg);
694 } else { 880 } else {
695 translation->StoreInt32Register(reg); 881 translation->StoreInt32Register(reg);
696 } 882 }
697 } else if (op->IsDoubleRegister()) {
698 XMMRegister reg = ToDoubleRegister(op);
699 translation->StoreDoubleRegister(reg);
700 } else if (op->IsConstantOperand()) { 883 } else if (op->IsConstantOperand()) {
701 HConstant* constant = chunk()->LookupConstant(LConstantOperand::cast(op)); 884 HConstant* constant = chunk()->LookupConstant(LConstantOperand::cast(op));
702 int src_index = DefineDeoptimizationLiteral(constant->handle(isolate())); 885 int src_index = DefineDeoptimizationLiteral(constant->handle(isolate()));
703 translation->StoreLiteral(src_index); 886 translation->StoreLiteral(src_index);
704 } else { 887 } else {
705 UNREACHABLE(); 888 UNREACHABLE();
706 } 889 }
707 } 890 }
708 891
709 892
(...skipping 16 matching lines...) Expand all
726 909
727 void LCodeGen::CallCode(Handle<Code> code, 910 void LCodeGen::CallCode(Handle<Code> code,
728 RelocInfo::Mode mode, 911 RelocInfo::Mode mode,
729 LInstruction* instr) { 912 LInstruction* instr) {
730 CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT); 913 CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT);
731 } 914 }
732 915
733 916
734 void LCodeGen::CallRuntime(const Runtime::Function* fun, 917 void LCodeGen::CallRuntime(const Runtime::Function* fun,
735 int argc, 918 int argc,
736 LInstruction* instr, 919 LInstruction* instr) {
737 SaveFPRegsMode save_doubles) {
738 ASSERT(instr != NULL); 920 ASSERT(instr != NULL);
739 ASSERT(instr->HasPointerMap()); 921 ASSERT(instr->HasPointerMap());
740 922
741 __ CallRuntime(fun, argc, save_doubles); 923 __ CallRuntime(fun, argc);
742 924
743 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); 925 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
744 926
745 ASSERT(info()->is_calling()); 927 ASSERT(info()->is_calling());
746 } 928 }
747 929
748 930
749 void LCodeGen::LoadContextFromDeferred(LOperand* context) { 931 void LCodeGen::LoadContextFromDeferred(LOperand* context) {
750 if (context->IsRegister()) { 932 if (context->IsRegister()) {
751 if (!ToRegister(context).is(esi)) { 933 if (!ToRegister(context).is(esi)) {
752 __ mov(esi, ToRegister(context)); 934 __ mov(esi, ToRegister(context));
753 } 935 }
754 } else if (context->IsStackSlot()) { 936 } else if (context->IsStackSlot()) {
755 __ mov(esi, ToOperand(context)); 937 __ mov(esi, ToOperand(context));
756 } else if (context->IsConstantOperand()) { 938 } else if (context->IsConstantOperand()) {
757 HConstant* constant = 939 HConstant* constant =
758 chunk_->LookupConstant(LConstantOperand::cast(context)); 940 chunk_->LookupConstant(LConstantOperand::cast(context));
759 __ LoadObject(esi, Handle<Object>::cast(constant->handle(isolate()))); 941 __ LoadObject(esi, Handle<Object>::cast(constant->handle(isolate())));
760 } else { 942 } else {
761 UNREACHABLE(); 943 UNREACHABLE();
762 } 944 }
763 } 945 }
764 946
765 void LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id, 947 void LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id,
766 int argc, 948 int argc,
767 LInstruction* instr, 949 LInstruction* instr,
768 LOperand* context) { 950 LOperand* context) {
769 LoadContextFromDeferred(context); 951 LoadContextFromDeferred(context);
770 952
771 __ CallRuntimeSaveDoubles(id); 953 __ CallRuntime(id);
772 RecordSafepointWithRegisters( 954 RecordSafepointWithRegisters(
773 instr->pointer_map(), argc, Safepoint::kNoLazyDeopt); 955 instr->pointer_map(), argc, Safepoint::kNoLazyDeopt);
774 956
775 ASSERT(info()->is_calling()); 957 ASSERT(info()->is_calling());
776 } 958 }
777 959
778 960
779 void LCodeGen::RegisterEnvironmentForDeoptimization( 961 void LCodeGen::RegisterEnvironmentForDeoptimization(
780 LEnvironment* environment, Safepoint::DeoptMode mode) { 962 LEnvironment* environment, Safepoint::DeoptMode mode) {
781 environment->set_has_been_used(); 963 environment->set_has_been_used();
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
841 __ pop(eax); 1023 __ pop(eax);
842 __ popfd(); 1024 __ popfd();
843 ASSERT(frame_is_built_); 1025 ASSERT(frame_is_built_);
844 __ call(entry, RelocInfo::RUNTIME_ENTRY); 1026 __ call(entry, RelocInfo::RUNTIME_ENTRY);
845 __ bind(&no_deopt); 1027 __ bind(&no_deopt);
846 __ mov(Operand::StaticVariable(count), eax); 1028 __ mov(Operand::StaticVariable(count), eax);
847 __ pop(eax); 1029 __ pop(eax);
848 __ popfd(); 1030 __ popfd();
849 } 1031 }
850 1032
1033 // Before Instructions which can deopt, we normally flush the x87 stack. But
1034 // we can have inputs or outputs of the current instruction on the stack,
1035 // thus we need to flush them here from the physical stack to leave it in a
1036 // consistent state.
1037 if (x87_stack_.depth() > 0) {
1038 Label done;
1039 if (cc != no_condition) __ j(NegateCondition(cc), &done, Label::kNear);
1040 EmitFlushX87ForDeopt();
1041 __ bind(&done);
1042 }
1043
851 if (info()->ShouldTrapOnDeopt()) { 1044 if (info()->ShouldTrapOnDeopt()) {
852 Label done; 1045 Label done;
853 if (cc != no_condition) __ j(NegateCondition(cc), &done, Label::kNear); 1046 if (cc != no_condition) __ j(NegateCondition(cc), &done, Label::kNear);
854 __ int3(); 1047 __ int3();
855 __ bind(&done); 1048 __ bind(&done);
856 } 1049 }
857 1050
858 ASSERT(info()->IsStub() || frame_is_built_); 1051 ASSERT(info()->IsStub() || frame_is_built_);
859 if (cc == no_condition && frame_is_built_) { 1052 if (cc == no_condition && frame_is_built_) {
860 __ call(entry, RelocInfo::RUNTIME_ENTRY); 1053 __ call(entry, RelocInfo::RUNTIME_ENTRY);
(...skipping 840 matching lines...) Expand 10 before | Expand all | Expand 10 after
1701 } 1894 }
1702 1895
1703 1896
1704 void LCodeGen::DoConstantD(LConstantD* instr) { 1897 void LCodeGen::DoConstantD(LConstantD* instr) {
1705 double v = instr->value(); 1898 double v = instr->value();
1706 uint64_t int_val = BitCast<uint64_t, double>(v); 1899 uint64_t int_val = BitCast<uint64_t, double>(v);
1707 int32_t lower = static_cast<int32_t>(int_val); 1900 int32_t lower = static_cast<int32_t>(int_val);
1708 int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt)); 1901 int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt));
1709 ASSERT(instr->result()->IsDoubleRegister()); 1902 ASSERT(instr->result()->IsDoubleRegister());
1710 1903
1711 XMMRegister res = ToDoubleRegister(instr->result()); 1904 __ push(Immediate(upper));
1712 if (int_val == 0) { 1905 __ push(Immediate(lower));
1713 __ xorps(res, res); 1906 X87Register reg = ToX87Register(instr->result());
1714 } else { 1907 X87Mov(reg, Operand(esp, 0));
1715 Register temp = ToRegister(instr->temp()); 1908 __ add(Operand(esp), Immediate(kDoubleSize));
1716 if (CpuFeatures::IsSupported(SSE4_1)) {
1717 CpuFeatureScope scope2(masm(), SSE4_1);
1718 if (lower != 0) {
1719 __ Move(temp, Immediate(lower));
1720 __ movd(res, Operand(temp));
1721 __ Move(temp, Immediate(upper));
1722 __ pinsrd(res, Operand(temp), 1);
1723 } else {
1724 __ xorps(res, res);
1725 __ Move(temp, Immediate(upper));
1726 __ pinsrd(res, Operand(temp), 1);
1727 }
1728 } else {
1729 __ Move(temp, Immediate(upper));
1730 __ movd(res, Operand(temp));
1731 __ psllq(res, 32);
1732 if (lower != 0) {
1733 XMMRegister xmm_scratch = double_scratch0();
1734 __ Move(temp, Immediate(lower));
1735 __ movd(xmm_scratch, Operand(temp));
1736 __ orps(res, xmm_scratch);
1737 }
1738 }
1739 }
1740 } 1909 }
1741 1910
1742 1911
1743 void LCodeGen::DoConstantE(LConstantE* instr) { 1912 void LCodeGen::DoConstantE(LConstantE* instr) {
1744 __ lea(ToRegister(instr->result()), Operand::StaticVariable(instr->value())); 1913 __ lea(ToRegister(instr->result()), Operand::StaticVariable(instr->value()));
1745 } 1914 }
1746 1915
1747 1916
1748 void LCodeGen::DoConstantT(LConstantT* instr) { 1917 void LCodeGen::DoConstantT(LConstantT* instr) {
1749 Register reg = ToRegister(instr->result()); 1918 Register reg = ToRegister(instr->result());
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
1927 __ mov(left_op, immediate); 2096 __ mov(left_op, immediate);
1928 } else { 2097 } else {
1929 Register left_reg = ToRegister(left); 2098 Register left_reg = ToRegister(left);
1930 Operand right_op = ToOperand(right); 2099 Operand right_op = ToOperand(right);
1931 __ cmp(left_reg, right_op); 2100 __ cmp(left_reg, right_op);
1932 __ j(condition, &return_left, Label::kNear); 2101 __ j(condition, &return_left, Label::kNear);
1933 __ mov(left_reg, right_op); 2102 __ mov(left_reg, right_op);
1934 } 2103 }
1935 __ bind(&return_left); 2104 __ bind(&return_left);
1936 } else { 2105 } else {
1937 ASSERT(instr->hydrogen()->representation().IsDouble()); 2106 // TODO(weiliang) use X87 for double representation.
1938 Label check_nan_left, check_zero, return_left, return_right; 2107 UNIMPLEMENTED();
1939 Condition condition = (operation == HMathMinMax::kMathMin) ? below : above;
1940 XMMRegister left_reg = ToDoubleRegister(left);
1941 XMMRegister right_reg = ToDoubleRegister(right);
1942 __ ucomisd(left_reg, right_reg);
1943 __ j(parity_even, &check_nan_left, Label::kNear); // At least one NaN.
1944 __ j(equal, &check_zero, Label::kNear); // left == right.
1945 __ j(condition, &return_left, Label::kNear);
1946 __ jmp(&return_right, Label::kNear);
1947
1948 __ bind(&check_zero);
1949 XMMRegister xmm_scratch = double_scratch0();
1950 __ xorps(xmm_scratch, xmm_scratch);
1951 __ ucomisd(left_reg, xmm_scratch);
1952 __ j(not_equal, &return_left, Label::kNear); // left == right != 0.
1953 // At this point, both left and right are either 0 or -0.
1954 if (operation == HMathMinMax::kMathMin) {
1955 __ orpd(left_reg, right_reg);
1956 } else {
1957 // Since we operate on +0 and/or -0, addsd and andsd have the same effect.
1958 __ addsd(left_reg, right_reg);
1959 }
1960 __ jmp(&return_left, Label::kNear);
1961
1962 __ bind(&check_nan_left);
1963 __ ucomisd(left_reg, left_reg); // NaN check.
1964 __ j(parity_even, &return_left, Label::kNear); // left == NaN.
1965 __ bind(&return_right);
1966 __ movaps(left_reg, right_reg);
1967
1968 __ bind(&return_left);
1969 } 2108 }
1970 } 2109 }
1971 2110
1972 2111
1973 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { 2112 void LCodeGen::DoArithmeticD(LArithmeticD* instr) {
1974 XMMRegister left = ToDoubleRegister(instr->left()); 2113 X87Register left = ToX87Register(instr->left());
1975 XMMRegister right = ToDoubleRegister(instr->right()); 2114 X87Register right = ToX87Register(instr->right());
1976 XMMRegister result = ToDoubleRegister(instr->result()); 2115 X87Register result = ToX87Register(instr->result());
2116 if (instr->op() != Token::MOD) {
2117 X87PrepareBinaryOp(left, right, result);
2118 }
1977 switch (instr->op()) { 2119 switch (instr->op()) {
1978 case Token::ADD: 2120 case Token::ADD:
1979 __ addsd(left, right); 2121 __ fadd_i(1);
1980 break; 2122 break;
1981 case Token::SUB: 2123 case Token::SUB:
1982 __ subsd(left, right); 2124 __ fsub_i(1);
1983 break; 2125 break;
1984 case Token::MUL: 2126 case Token::MUL:
1985 __ mulsd(left, right); 2127 __ fmul_i(1);
1986 break; 2128 break;
1987 case Token::DIV: 2129 case Token::DIV:
1988 __ divsd(left, right); 2130 __ fdiv_i(1);
1989 // Don't delete this mov. It may improve performance on some CPUs,
1990 // when there is a mulsd depending on the result
1991 __ movaps(left, left);
1992 break; 2131 break;
1993 case Token::MOD: { 2132 case Token::MOD: {
1994 // Pass two doubles as arguments on the stack. 2133 // Pass two doubles as arguments on the stack.
1995 __ PrepareCallCFunction(4, eax); 2134 __ PrepareCallCFunction(4, eax);
1996 __ movsd(Operand(esp, 0 * kDoubleSize), left); 2135 X87Mov(Operand(esp, 1 * kDoubleSize), right);
1997 __ movsd(Operand(esp, 1 * kDoubleSize), right); 2136 X87Mov(Operand(esp, 0), left);
2137 X87Free(right);
2138 ASSERT(left.is(result));
2139 X87PrepareToWrite(result);
1998 __ CallCFunction( 2140 __ CallCFunction(
1999 ExternalReference::mod_two_doubles_operation(isolate()), 2141 ExternalReference::mod_two_doubles_operation(isolate()),
2000 4); 2142 4);
2001 2143
2002 // Return value is in st(0) on ia32. 2144 // Return value is in st(0) on ia32.
2003 // Store it into the result register. 2145 X87CommitWrite(result);
2004 __ sub(Operand(esp), Immediate(kDoubleSize));
2005 __ fstp_d(Operand(esp, 0));
2006 __ movsd(result, Operand(esp, 0));
2007 __ add(Operand(esp), Immediate(kDoubleSize));
2008 break; 2146 break;
2009 } 2147 }
2010 default: 2148 default:
2011 UNREACHABLE(); 2149 UNREACHABLE();
2012 break; 2150 break;
2013 } 2151 }
2014 } 2152 }
2015 2153
2016 2154
2017 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { 2155 void LCodeGen::DoArithmeticT(LArithmeticT* instr) {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
2056 } 2194 }
2057 2195
2058 2196
2059 void LCodeGen::DoBranch(LBranch* instr) { 2197 void LCodeGen::DoBranch(LBranch* instr) {
2060 Representation r = instr->hydrogen()->value()->representation(); 2198 Representation r = instr->hydrogen()->value()->representation();
2061 if (r.IsSmiOrInteger32()) { 2199 if (r.IsSmiOrInteger32()) {
2062 Register reg = ToRegister(instr->value()); 2200 Register reg = ToRegister(instr->value());
2063 __ test(reg, Operand(reg)); 2201 __ test(reg, Operand(reg));
2064 EmitBranch(instr, not_zero); 2202 EmitBranch(instr, not_zero);
2065 } else if (r.IsDouble()) { 2203 } else if (r.IsDouble()) {
2066 ASSERT(!info()->IsStub()); 2204 UNREACHABLE();
2067 XMMRegister reg = ToDoubleRegister(instr->value());
2068 XMMRegister xmm_scratch = double_scratch0();
2069 __ xorps(xmm_scratch, xmm_scratch);
2070 __ ucomisd(reg, xmm_scratch);
2071 EmitBranch(instr, not_equal);
2072 } else { 2205 } else {
2073 ASSERT(r.IsTagged()); 2206 ASSERT(r.IsTagged());
2074 Register reg = ToRegister(instr->value()); 2207 Register reg = ToRegister(instr->value());
2075 HType type = instr->hydrogen()->value()->type(); 2208 HType type = instr->hydrogen()->value()->type();
2076 if (type.IsBoolean()) { 2209 if (type.IsBoolean()) {
2077 ASSERT(!info()->IsStub()); 2210 ASSERT(!info()->IsStub());
2078 __ cmp(reg, factory()->true_value()); 2211 __ cmp(reg, factory()->true_value());
2079 EmitBranch(instr, equal); 2212 EmitBranch(instr, equal);
2080 } else if (type.IsSmi()) { 2213 } else if (type.IsSmi()) {
2081 ASSERT(!info()->IsStub()); 2214 ASSERT(!info()->IsStub());
2082 __ test(reg, Operand(reg)); 2215 __ test(reg, Operand(reg));
2083 EmitBranch(instr, not_equal); 2216 EmitBranch(instr, not_equal);
2084 } else if (type.IsJSArray()) { 2217 } else if (type.IsJSArray()) {
2085 ASSERT(!info()->IsStub()); 2218 ASSERT(!info()->IsStub());
2086 EmitBranch(instr, no_condition); 2219 EmitBranch(instr, no_condition);
2087 } else if (type.IsHeapNumber()) { 2220 } else if (type.IsHeapNumber()) {
2088 ASSERT(!info()->IsStub()); 2221 UNREACHABLE();
2089 XMMRegister xmm_scratch = double_scratch0();
2090 __ xorps(xmm_scratch, xmm_scratch);
2091 __ ucomisd(xmm_scratch, FieldOperand(reg, HeapNumber::kValueOffset));
2092 EmitBranch(instr, not_equal);
2093 } else if (type.IsString()) { 2222 } else if (type.IsString()) {
2094 ASSERT(!info()->IsStub()); 2223 ASSERT(!info()->IsStub());
2095 __ cmp(FieldOperand(reg, String::kLengthOffset), Immediate(0)); 2224 __ cmp(FieldOperand(reg, String::kLengthOffset), Immediate(0));
2096 EmitBranch(instr, not_equal); 2225 EmitBranch(instr, not_equal);
2097 } else { 2226 } else {
2098 ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types(); 2227 ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types();
2099 if (expected.IsEmpty()) expected = ToBooleanStub::Types::Generic(); 2228 if (expected.IsEmpty()) expected = ToBooleanStub::Types::Generic();
2100 2229
2101 if (expected.Contains(ToBooleanStub::UNDEFINED)) { 2230 if (expected.Contains(ToBooleanStub::UNDEFINED)) {
2102 // undefined -> false. 2231 // undefined -> false.
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
2164 __ CmpInstanceType(map, SYMBOL_TYPE); 2293 __ CmpInstanceType(map, SYMBOL_TYPE);
2165 __ j(equal, instr->TrueLabel(chunk_)); 2294 __ j(equal, instr->TrueLabel(chunk_));
2166 } 2295 }
2167 2296
2168 if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) { 2297 if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) {
2169 // heap number -> false iff +0, -0, or NaN. 2298 // heap number -> false iff +0, -0, or NaN.
2170 Label not_heap_number; 2299 Label not_heap_number;
2171 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), 2300 __ cmp(FieldOperand(reg, HeapObject::kMapOffset),
2172 factory()->heap_number_map()); 2301 factory()->heap_number_map());
2173 __ j(not_equal, &not_heap_number, Label::kNear); 2302 __ j(not_equal, &not_heap_number, Label::kNear);
2174 XMMRegister xmm_scratch = double_scratch0(); 2303 __ fldz();
2175 __ xorps(xmm_scratch, xmm_scratch); 2304 __ fld_d(FieldOperand(reg, HeapNumber::kValueOffset));
2176 __ ucomisd(xmm_scratch, FieldOperand(reg, HeapNumber::kValueOffset)); 2305 __ FCmp();
2177 __ j(zero, instr->FalseLabel(chunk_)); 2306 __ j(zero, instr->FalseLabel(chunk_));
2178 __ jmp(instr->TrueLabel(chunk_)); 2307 __ jmp(instr->TrueLabel(chunk_));
2179 __ bind(&not_heap_number); 2308 __ bind(&not_heap_number);
2180 } 2309 }
2181 2310
2182 if (!expected.IsGeneric()) { 2311 if (!expected.IsGeneric()) {
2183 // We've seen something for the first time -> deopt. 2312 // We've seen something for the first time -> deopt.
2184 // This can only happen if we are not generic already. 2313 // This can only happen if we are not generic already.
2185 DeoptimizeIf(no_condition, instr->environment()); 2314 DeoptimizeIf(no_condition, instr->environment());
2186 } 2315 }
2187 } 2316 }
2188 } 2317 }
2189 } 2318 }
2190 2319
2191 2320
2192 void LCodeGen::EmitGoto(int block) { 2321 void LCodeGen::EmitGoto(int block) {
2193 if (!IsNextEmittedBlock(block)) { 2322 if (!IsNextEmittedBlock(block)) {
2194 __ jmp(chunk_->GetAssemblyLabel(LookupDestination(block))); 2323 __ jmp(chunk_->GetAssemblyLabel(LookupDestination(block)));
2195 } 2324 }
2196 } 2325 }
2197 2326
2198 2327
2328 void LCodeGen::DoClobberDoubles(LClobberDoubles* instr) {
2329 }
2330
2331
2199 void LCodeGen::DoGoto(LGoto* instr) { 2332 void LCodeGen::DoGoto(LGoto* instr) {
2200 EmitGoto(instr->block_id()); 2333 EmitGoto(instr->block_id());
2201 } 2334 }
2202 2335
2203 2336
2204 Condition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) { 2337 Condition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) {
2205 Condition cond = no_condition; 2338 Condition cond = no_condition;
2206 switch (op) { 2339 switch (op) {
2207 case Token::EQ: 2340 case Token::EQ:
2208 case Token::EQ_STRICT: 2341 case Token::EQ_STRICT:
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
2242 2375
2243 if (left->IsConstantOperand() && right->IsConstantOperand()) { 2376 if (left->IsConstantOperand() && right->IsConstantOperand()) {
2244 // We can statically evaluate the comparison. 2377 // We can statically evaluate the comparison.
2245 double left_val = ToDouble(LConstantOperand::cast(left)); 2378 double left_val = ToDouble(LConstantOperand::cast(left));
2246 double right_val = ToDouble(LConstantOperand::cast(right)); 2379 double right_val = ToDouble(LConstantOperand::cast(right));
2247 int next_block = EvalComparison(instr->op(), left_val, right_val) ? 2380 int next_block = EvalComparison(instr->op(), left_val, right_val) ?
2248 instr->TrueDestination(chunk_) : instr->FalseDestination(chunk_); 2381 instr->TrueDestination(chunk_) : instr->FalseDestination(chunk_);
2249 EmitGoto(next_block); 2382 EmitGoto(next_block);
2250 } else { 2383 } else {
2251 if (instr->is_double()) { 2384 if (instr->is_double()) {
2252 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); 2385 X87LoadForUsage(ToX87Register(right), ToX87Register(left));
2386 __ FCmp();
2253 // Don't base result on EFLAGS when a NaN is involved. Instead 2387 // Don't base result on EFLAGS when a NaN is involved. Instead
2254 // jump to the false block. 2388 // jump to the false block.
2255 __ j(parity_even, instr->FalseLabel(chunk_)); 2389 __ j(parity_even, instr->FalseLabel(chunk_));
2256 } else { 2390 } else {
2257 if (right->IsConstantOperand()) { 2391 if (right->IsConstantOperand()) {
2258 __ cmp(ToOperand(left), 2392 __ cmp(ToOperand(left),
2259 ToImmediate(right, instr->hydrogen()->representation())); 2393 ToImmediate(right, instr->hydrogen()->representation()));
2260 } else if (left->IsConstantOperand()) { 2394 } else if (left->IsConstantOperand()) {
2261 __ cmp(ToOperand(right), 2395 __ cmp(ToOperand(right),
2262 ToImmediate(left, instr->hydrogen()->representation())); 2396 ToImmediate(left, instr->hydrogen()->representation()));
(...skipping 23 matching lines...) Expand all
2286 2420
2287 2421
2288 void LCodeGen::DoCmpHoleAndBranch(LCmpHoleAndBranch* instr) { 2422 void LCodeGen::DoCmpHoleAndBranch(LCmpHoleAndBranch* instr) {
2289 if (instr->hydrogen()->representation().IsTagged()) { 2423 if (instr->hydrogen()->representation().IsTagged()) {
2290 Register input_reg = ToRegister(instr->object()); 2424 Register input_reg = ToRegister(instr->object());
2291 __ cmp(input_reg, factory()->the_hole_value()); 2425 __ cmp(input_reg, factory()->the_hole_value());
2292 EmitBranch(instr, equal); 2426 EmitBranch(instr, equal);
2293 return; 2427 return;
2294 } 2428 }
2295 2429
2296 XMMRegister input_reg = ToDoubleRegister(instr->object()); 2430 // Put the value to the top of stack
2297 __ ucomisd(input_reg, input_reg); 2431 X87Register src = ToX87Register(instr->object());
2298 EmitFalseBranch(instr, parity_odd); 2432 X87LoadForUsage(src);
2433 __ fld(0);
2434 __ fld(0);
2435 __ FCmp();
2436 Label ok;
2437 __ j(parity_even, &ok, Label::kNear);
2438 __ fstp(0);
2439 EmitFalseBranch(instr, no_condition);
2440 __ bind(&ok);
2441
2299 2442
2300 __ sub(esp, Immediate(kDoubleSize)); 2443 __ sub(esp, Immediate(kDoubleSize));
2301 __ movsd(MemOperand(esp, 0), input_reg); 2444 __ fstp_d(MemOperand(esp, 0));
2302 2445
2303 __ add(esp, Immediate(kDoubleSize)); 2446 __ add(esp, Immediate(kDoubleSize));
2304 int offset = sizeof(kHoleNanUpper32); 2447 int offset = sizeof(kHoleNanUpper32);
2305 __ cmp(MemOperand(esp, -offset), Immediate(kHoleNanUpper32)); 2448 __ cmp(MemOperand(esp, -offset), Immediate(kHoleNanUpper32));
2306 EmitBranch(instr, equal); 2449 EmitBranch(instr, equal);
2307 } 2450 }
2308 2451
2309 2452
2310 void LCodeGen::DoCompareMinusZeroAndBranch(LCompareMinusZeroAndBranch* instr) { 2453 void LCodeGen::DoCompareMinusZeroAndBranch(LCompareMinusZeroAndBranch* instr) {
2311 Representation rep = instr->hydrogen()->value()->representation(); 2454 Representation rep = instr->hydrogen()->value()->representation();
2312 ASSERT(!rep.IsInteger32()); 2455 ASSERT(!rep.IsInteger32());
2313 Register scratch = ToRegister(instr->temp());
2314 2456
2315 if (rep.IsDouble()) { 2457 if (rep.IsDouble()) {
2316 XMMRegister value = ToDoubleRegister(instr->value()); 2458 UNREACHABLE();
2317 XMMRegister xmm_scratch = double_scratch0();
2318 __ xorps(xmm_scratch, xmm_scratch);
2319 __ ucomisd(xmm_scratch, value);
2320 EmitFalseBranch(instr, not_equal);
2321 __ movmskpd(scratch, value);
2322 __ test(scratch, Immediate(1));
2323 EmitBranch(instr, not_zero);
2324 } else { 2459 } else {
2325 Register value = ToRegister(instr->value()); 2460 Register value = ToRegister(instr->value());
2326 Handle<Map> map = masm()->isolate()->factory()->heap_number_map(); 2461 Handle<Map> map = masm()->isolate()->factory()->heap_number_map();
2327 __ CheckMap(value, map, instr->FalseLabel(chunk()), DO_SMI_CHECK); 2462 __ CheckMap(value, map, instr->FalseLabel(chunk()), DO_SMI_CHECK);
2328 __ cmp(FieldOperand(value, HeapNumber::kExponentOffset), 2463 __ cmp(FieldOperand(value, HeapNumber::kExponentOffset),
2329 Immediate(0x1)); 2464 Immediate(0x1));
2330 EmitFalseBranch(instr, no_overflow); 2465 EmitFalseBranch(instr, no_overflow);
2331 __ cmp(FieldOperand(value, HeapNumber::kMantissaOffset), 2466 __ cmp(FieldOperand(value, HeapNumber::kMantissaOffset),
2332 Immediate(0x00000000)); 2467 Immediate(0x00000000));
2333 EmitBranch(instr, equal); 2468 EmitBranch(instr, equal);
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after
2608 __ bind(&true_value); 2743 __ bind(&true_value);
2609 __ mov(ToRegister(instr->result()), factory()->true_value()); 2744 __ mov(ToRegister(instr->result()), factory()->true_value());
2610 __ bind(&done); 2745 __ bind(&done);
2611 } 2746 }
2612 2747
2613 2748
2614 void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { 2749 void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) {
2615 class DeferredInstanceOfKnownGlobal V8_FINAL : public LDeferredCode { 2750 class DeferredInstanceOfKnownGlobal V8_FINAL : public LDeferredCode {
2616 public: 2751 public:
2617 DeferredInstanceOfKnownGlobal(LCodeGen* codegen, 2752 DeferredInstanceOfKnownGlobal(LCodeGen* codegen,
2618 LInstanceOfKnownGlobal* instr) 2753 LInstanceOfKnownGlobal* instr,
2619 : LDeferredCode(codegen), instr_(instr) { } 2754 const X87Stack& x87_stack)
2755 : LDeferredCode(codegen, x87_stack), instr_(instr) { }
2620 virtual void Generate() V8_OVERRIDE { 2756 virtual void Generate() V8_OVERRIDE {
2621 codegen()->DoDeferredInstanceOfKnownGlobal(instr_, &map_check_); 2757 codegen()->DoDeferredInstanceOfKnownGlobal(instr_, &map_check_);
2622 } 2758 }
2623 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } 2759 virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
2624 Label* map_check() { return &map_check_; } 2760 Label* map_check() { return &map_check_; }
2625 private: 2761 private:
2626 LInstanceOfKnownGlobal* instr_; 2762 LInstanceOfKnownGlobal* instr_;
2627 Label map_check_; 2763 Label map_check_;
2628 }; 2764 };
2629 2765
2630 DeferredInstanceOfKnownGlobal* deferred; 2766 DeferredInstanceOfKnownGlobal* deferred;
2631 deferred = new(zone()) DeferredInstanceOfKnownGlobal(this, instr); 2767 deferred = new(zone()) DeferredInstanceOfKnownGlobal(this, instr, x87_stack_);
2632 2768
2633 Label done, false_result; 2769 Label done, false_result;
2634 Register object = ToRegister(instr->value()); 2770 Register object = ToRegister(instr->value());
2635 Register temp = ToRegister(instr->temp()); 2771 Register temp = ToRegister(instr->temp());
2636 2772
2637 // A Smi is not an instance of anything. 2773 // A Smi is not an instance of anything.
2638 __ JumpIfSmi(object, &false_result, Label::kNear); 2774 __ JumpIfSmi(object, &false_result, Label::kNear);
2639 2775
2640 // This is the inlined call site instanceof cache. The two occurences of the 2776 // This is the inlined call site instanceof cache. The two occurences of the
2641 // hole value will be patched to the last map/result pair generated by the 2777 // 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
2770 void LCodeGen::DoReturn(LReturn* instr) { 2906 void LCodeGen::DoReturn(LReturn* instr) {
2771 if (FLAG_trace && info()->IsOptimizing()) { 2907 if (FLAG_trace && info()->IsOptimizing()) {
2772 // Preserve the return value on the stack and rely on the runtime call 2908 // Preserve the return value on the stack and rely on the runtime call
2773 // to return the value in the same register. We're leaving the code 2909 // to return the value in the same register. We're leaving the code
2774 // managed by the register allocator and tearing down the frame, it's 2910 // managed by the register allocator and tearing down the frame, it's
2775 // safe to write to the context register. 2911 // safe to write to the context register.
2776 __ push(eax); 2912 __ push(eax);
2777 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 2913 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
2778 __ CallRuntime(Runtime::kTraceExit, 1); 2914 __ CallRuntime(Runtime::kTraceExit, 1);
2779 } 2915 }
2780 if (info()->saves_caller_doubles()) RestoreCallerDoubles();
2781 if (dynamic_frame_alignment_) { 2916 if (dynamic_frame_alignment_) {
2782 // Fetch the state of the dynamic frame alignment. 2917 // Fetch the state of the dynamic frame alignment.
2783 __ mov(edx, Operand(ebp, 2918 __ mov(edx, Operand(ebp,
2784 JavaScriptFrameConstants::kDynamicAlignmentStateOffset)); 2919 JavaScriptFrameConstants::kDynamicAlignmentStateOffset));
2785 } 2920 }
2786 int no_frame_start = -1; 2921 int no_frame_start = -1;
2787 if (NeedsEagerFrame()) { 2922 if (NeedsEagerFrame()) {
2788 __ mov(esp, ebp); 2923 __ mov(esp, ebp);
2789 __ pop(ebp); 2924 __ pop(ebp);
2790 no_frame_start = masm_->pc_offset(); 2925 no_frame_start = masm_->pc_offset();
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
2885 if (instr->hydrogen()->NeedsWriteBarrier()) { 3020 if (instr->hydrogen()->NeedsWriteBarrier()) {
2886 SmiCheck check_needed = 3021 SmiCheck check_needed =
2887 instr->hydrogen()->value()->IsHeapObject() 3022 instr->hydrogen()->value()->IsHeapObject()
2888 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; 3023 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
2889 Register temp = ToRegister(instr->temp()); 3024 Register temp = ToRegister(instr->temp());
2890 int offset = Context::SlotOffset(instr->slot_index()); 3025 int offset = Context::SlotOffset(instr->slot_index());
2891 __ RecordWriteContextSlot(context, 3026 __ RecordWriteContextSlot(context,
2892 offset, 3027 offset,
2893 value, 3028 value,
2894 temp, 3029 temp,
2895 kSaveFPRegs,
2896 EMIT_REMEMBERED_SET, 3030 EMIT_REMEMBERED_SET,
2897 check_needed); 3031 check_needed);
2898 } 3032 }
2899 3033
2900 __ bind(&skip_assignment); 3034 __ bind(&skip_assignment);
2901 } 3035 }
2902 3036
2903 3037
2904 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { 3038 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) {
2905 HObjectAccess access = instr->hydrogen()->access(); 3039 HObjectAccess access = instr->hydrogen()->access();
2906 int offset = access.offset(); 3040 int offset = access.offset();
2907 3041
2908 if (access.IsExternalMemory()) { 3042 if (access.IsExternalMemory()) {
2909 Register result = ToRegister(instr->result()); 3043 Register result = ToRegister(instr->result());
2910 MemOperand operand = instr->object()->IsConstantOperand() 3044 MemOperand operand = instr->object()->IsConstantOperand()
2911 ? MemOperand::StaticVariable(ToExternalReference( 3045 ? MemOperand::StaticVariable(ToExternalReference(
2912 LConstantOperand::cast(instr->object()))) 3046 LConstantOperand::cast(instr->object())))
2913 : MemOperand(ToRegister(instr->object()), offset); 3047 : MemOperand(ToRegister(instr->object()), offset);
2914 __ Load(result, operand, access.representation()); 3048 __ Load(result, operand, access.representation());
2915 return; 3049 return;
2916 } 3050 }
2917 3051
2918 Register object = ToRegister(instr->object()); 3052 Register object = ToRegister(instr->object());
2919 if (instr->hydrogen()->representation().IsDouble()) { 3053 if (instr->hydrogen()->representation().IsDouble()) {
2920 XMMRegister result = ToDoubleRegister(instr->result()); 3054 X87Mov(ToX87Register(instr->result()), FieldOperand(object, offset));
2921 __ movsd(result, FieldOperand(object, offset));
2922 return; 3055 return;
2923 } 3056 }
2924 3057
2925 Register result = ToRegister(instr->result()); 3058 Register result = ToRegister(instr->result());
2926 if (!access.IsInobject()) { 3059 if (!access.IsInobject()) {
2927 __ mov(result, FieldOperand(object, JSObject::kPropertiesOffset)); 3060 __ mov(result, FieldOperand(object, JSObject::kPropertiesOffset));
2928 object = result; 3061 object = result;
2929 } 3062 }
2930 __ Load(result, FieldOperand(object, offset), access.representation()); 3063 __ Load(result, FieldOperand(object, offset), access.representation());
2931 } 3064 }
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
3038 } 3171 }
3039 Operand operand(BuildFastArrayOperand( 3172 Operand operand(BuildFastArrayOperand(
3040 instr->elements(), 3173 instr->elements(),
3041 key, 3174 key,
3042 instr->hydrogen()->key()->representation(), 3175 instr->hydrogen()->key()->representation(),
3043 elements_kind, 3176 elements_kind,
3044 0, 3177 0,
3045 instr->additional_index())); 3178 instr->additional_index()));
3046 if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS || 3179 if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
3047 elements_kind == FLOAT32_ELEMENTS) { 3180 elements_kind == FLOAT32_ELEMENTS) {
3048 XMMRegister result(ToDoubleRegister(instr->result())); 3181 X87Mov(ToX87Register(instr->result()), operand, kX87FloatOperand);
3049 __ movss(result, operand);
3050 __ cvtss2sd(result, result);
3051 } else if (elements_kind == EXTERNAL_FLOAT64_ELEMENTS || 3182 } else if (elements_kind == EXTERNAL_FLOAT64_ELEMENTS ||
3052 elements_kind == FLOAT64_ELEMENTS) { 3183 elements_kind == FLOAT64_ELEMENTS) {
3053 __ movsd(ToDoubleRegister(instr->result()), operand); 3184 X87Mov(ToX87Register(instr->result()), operand);
3054 } else { 3185 } else {
3055 Register result(ToRegister(instr->result())); 3186 Register result(ToRegister(instr->result()));
3056 switch (elements_kind) { 3187 switch (elements_kind) {
3057 case EXTERNAL_INT8_ELEMENTS: 3188 case EXTERNAL_INT8_ELEMENTS:
3058 case INT8_ELEMENTS: 3189 case INT8_ELEMENTS:
3059 __ movsx_b(result, operand); 3190 __ movsx_b(result, operand);
3060 break; 3191 break;
3061 case EXTERNAL_UINT8_CLAMPED_ELEMENTS: 3192 case EXTERNAL_UINT8_CLAMPED_ELEMENTS:
3062 case EXTERNAL_UINT8_ELEMENTS: 3193 case EXTERNAL_UINT8_ELEMENTS:
3063 case UINT8_ELEMENTS: 3194 case UINT8_ELEMENTS:
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
3117 DeoptimizeIf(equal, instr->environment()); 3248 DeoptimizeIf(equal, instr->environment());
3118 } 3249 }
3119 3250
3120 Operand double_load_operand = BuildFastArrayOperand( 3251 Operand double_load_operand = BuildFastArrayOperand(
3121 instr->elements(), 3252 instr->elements(),
3122 instr->key(), 3253 instr->key(),
3123 instr->hydrogen()->key()->representation(), 3254 instr->hydrogen()->key()->representation(),
3124 FAST_DOUBLE_ELEMENTS, 3255 FAST_DOUBLE_ELEMENTS,
3125 FixedDoubleArray::kHeaderSize - kHeapObjectTag, 3256 FixedDoubleArray::kHeaderSize - kHeapObjectTag,
3126 instr->additional_index()); 3257 instr->additional_index());
3127 XMMRegister result = ToDoubleRegister(instr->result()); 3258 X87Mov(ToX87Register(instr->result()), double_load_operand);
3128 __ movsd(result, double_load_operand);
3129 } 3259 }
3130 3260
3131 3261
3132 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { 3262 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) {
3133 Register result = ToRegister(instr->result()); 3263 Register result = ToRegister(instr->result());
3134 3264
3135 // Load the result. 3265 // Load the result.
3136 __ mov(result, 3266 __ mov(result,
3137 BuildFastArrayOperand(instr->elements(), 3267 BuildFastArrayOperand(instr->elements(),
3138 instr->key(), 3268 instr->key(),
(...skipping 401 matching lines...) Expand 10 before | Expand all | Expand 10 after
3540 DeoptimizeIf(negative, instr->environment()); 3670 DeoptimizeIf(negative, instr->environment());
3541 __ bind(&is_positive); 3671 __ bind(&is_positive);
3542 } 3672 }
3543 3673
3544 3674
3545 void LCodeGen::DoMathAbs(LMathAbs* instr) { 3675 void LCodeGen::DoMathAbs(LMathAbs* instr) {
3546 // Class for deferred case. 3676 // Class for deferred case.
3547 class DeferredMathAbsTaggedHeapNumber V8_FINAL : public LDeferredCode { 3677 class DeferredMathAbsTaggedHeapNumber V8_FINAL : public LDeferredCode {
3548 public: 3678 public:
3549 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, 3679 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen,
3550 LMathAbs* instr) 3680 LMathAbs* instr,
3551 : LDeferredCode(codegen), instr_(instr) { } 3681 const X87Stack& x87_stack)
3682 : LDeferredCode(codegen, x87_stack), instr_(instr) { }
3552 virtual void Generate() V8_OVERRIDE { 3683 virtual void Generate() V8_OVERRIDE {
3553 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); 3684 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_);
3554 } 3685 }
3555 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } 3686 virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
3556 private: 3687 private:
3557 LMathAbs* instr_; 3688 LMathAbs* instr_;
3558 }; 3689 };
3559 3690
3560 ASSERT(instr->value()->Equals(instr->result())); 3691 ASSERT(instr->value()->Equals(instr->result()));
3561 Representation r = instr->hydrogen()->value()->representation(); 3692 Representation r = instr->hydrogen()->value()->representation();
3562 3693
3563 if (r.IsDouble()) { 3694 if (r.IsDouble()) {
3564 XMMRegister scratch = double_scratch0(); 3695 UNIMPLEMENTED();
3565 XMMRegister input_reg = ToDoubleRegister(instr->value());
3566 __ xorps(scratch, scratch);
3567 __ subsd(scratch, input_reg);
3568 __ andps(input_reg, scratch);
3569 } else if (r.IsSmiOrInteger32()) { 3696 } else if (r.IsSmiOrInteger32()) {
3570 EmitIntegerMathAbs(instr); 3697 EmitIntegerMathAbs(instr);
3571 } else { // Tagged case. 3698 } else { // Tagged case.
3572 DeferredMathAbsTaggedHeapNumber* deferred = 3699 DeferredMathAbsTaggedHeapNumber* deferred =
3573 new(zone()) DeferredMathAbsTaggedHeapNumber(this, instr); 3700 new(zone()) DeferredMathAbsTaggedHeapNumber(this, instr, x87_stack_);
3574 Register input_reg = ToRegister(instr->value()); 3701 Register input_reg = ToRegister(instr->value());
3575 // Smi check. 3702 // Smi check.
3576 __ JumpIfNotSmi(input_reg, deferred->entry()); 3703 __ JumpIfNotSmi(input_reg, deferred->entry());
3577 EmitIntegerMathAbs(instr); 3704 EmitIntegerMathAbs(instr);
3578 __ bind(deferred->exit()); 3705 __ bind(deferred->exit());
3579 } 3706 }
3580 } 3707 }
3581 3708
3582 3709
3583 void LCodeGen::DoMathFloor(LMathFloor* instr) { 3710 void LCodeGen::DoMathFloor(LMathFloor* instr) {
3584 XMMRegister xmm_scratch = double_scratch0(); 3711 UNIMPLEMENTED();
3585 Register output_reg = ToRegister(instr->result());
3586 XMMRegister input_reg = ToDoubleRegister(instr->value());
3587
3588 if (CpuFeatures::IsSupported(SSE4_1)) {
3589 CpuFeatureScope scope(masm(), SSE4_1);
3590 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
3591 // Deoptimize on negative zero.
3592 Label non_zero;
3593 __ xorps(xmm_scratch, xmm_scratch); // Zero the register.
3594 __ ucomisd(input_reg, xmm_scratch);
3595 __ j(not_equal, &non_zero, Label::kNear);
3596 __ movmskpd(output_reg, input_reg);
3597 __ test(output_reg, Immediate(1));
3598 DeoptimizeIf(not_zero, instr->environment());
3599 __ bind(&non_zero);
3600 }
3601 __ roundsd(xmm_scratch, input_reg, Assembler::kRoundDown);
3602 __ cvttsd2si(output_reg, Operand(xmm_scratch));
3603 // Overflow is signalled with minint.
3604 __ cmp(output_reg, 0x1);
3605 DeoptimizeIf(overflow, instr->environment());
3606 } else {
3607 Label negative_sign, done;
3608 // Deoptimize on unordered.
3609 __ xorps(xmm_scratch, xmm_scratch); // Zero the register.
3610 __ ucomisd(input_reg, xmm_scratch);
3611 DeoptimizeIf(parity_even, instr->environment());
3612 __ j(below, &negative_sign, Label::kNear);
3613
3614 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
3615 // Check for negative zero.
3616 Label positive_sign;
3617 __ j(above, &positive_sign, Label::kNear);
3618 __ movmskpd(output_reg, input_reg);
3619 __ test(output_reg, Immediate(1));
3620 DeoptimizeIf(not_zero, instr->environment());
3621 __ Move(output_reg, Immediate(0));
3622 __ jmp(&done, Label::kNear);
3623 __ bind(&positive_sign);
3624 }
3625
3626 // Use truncating instruction (OK because input is positive).
3627 __ cvttsd2si(output_reg, Operand(input_reg));
3628 // Overflow is signalled with minint.
3629 __ cmp(output_reg, 0x1);
3630 DeoptimizeIf(overflow, instr->environment());
3631 __ jmp(&done, Label::kNear);
3632
3633 // Non-zero negative reaches here.
3634 __ bind(&negative_sign);
3635 // Truncate, then compare and compensate.
3636 __ cvttsd2si(output_reg, Operand(input_reg));
3637 __ Cvtsi2sd(xmm_scratch, output_reg);
3638 __ ucomisd(input_reg, xmm_scratch);
3639 __ j(equal, &done, Label::kNear);
3640 __ sub(output_reg, Immediate(1));
3641 DeoptimizeIf(overflow, instr->environment());
3642
3643 __ bind(&done);
3644 }
3645 } 3712 }
3646 3713
3647 3714
3648 void LCodeGen::DoMathRound(LMathRound* instr) { 3715 void LCodeGen::DoMathRound(LMathRound* instr) {
3649 Register output_reg = ToRegister(instr->result()); 3716 UNIMPLEMENTED();
3650 XMMRegister input_reg = ToDoubleRegister(instr->value());
3651 XMMRegister xmm_scratch = double_scratch0();
3652 XMMRegister input_temp = ToDoubleRegister(instr->temp());
3653 ExternalReference one_half = ExternalReference::address_of_one_half();
3654 ExternalReference minus_one_half =
3655 ExternalReference::address_of_minus_one_half();
3656
3657 Label done, round_to_zero, below_one_half, do_not_compensate;
3658 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear;
3659
3660 __ movsd(xmm_scratch, Operand::StaticVariable(one_half));
3661 __ ucomisd(xmm_scratch, input_reg);
3662 __ j(above, &below_one_half, Label::kNear);
3663
3664 // CVTTSD2SI rounds towards zero, since 0.5 <= x, we use floor(0.5 + x).
3665 __ addsd(xmm_scratch, input_reg);
3666 __ cvttsd2si(output_reg, Operand(xmm_scratch));
3667 // Overflow is signalled with minint.
3668 __ cmp(output_reg, 0x1);
3669 __ RecordComment("D2I conversion overflow");
3670 DeoptimizeIf(overflow, instr->environment());
3671 __ jmp(&done, dist);
3672
3673 __ bind(&below_one_half);
3674 __ movsd(xmm_scratch, Operand::StaticVariable(minus_one_half));
3675 __ ucomisd(xmm_scratch, input_reg);
3676 __ j(below_equal, &round_to_zero, Label::kNear);
3677
3678 // CVTTSD2SI rounds towards zero, we use ceil(x - (-0.5)) and then
3679 // compare and compensate.
3680 __ movaps(input_temp, input_reg); // Do not alter input_reg.
3681 __ subsd(input_temp, xmm_scratch);
3682 __ cvttsd2si(output_reg, Operand(input_temp));
3683 // Catch minint due to overflow, and to prevent overflow when compensating.
3684 __ cmp(output_reg, 0x1);
3685 __ RecordComment("D2I conversion overflow");
3686 DeoptimizeIf(overflow, instr->environment());
3687
3688 __ Cvtsi2sd(xmm_scratch, output_reg);
3689 __ ucomisd(xmm_scratch, input_temp);
3690 __ j(equal, &done, dist);
3691 __ sub(output_reg, Immediate(1));
3692 // No overflow because we already ruled out minint.
3693 __ jmp(&done, dist);
3694
3695 __ bind(&round_to_zero);
3696 // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if
3697 // we can ignore the difference between a result of -0 and +0.
3698 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
3699 // If the sign is positive, we return +0.
3700 __ movmskpd(output_reg, input_reg);
3701 __ test(output_reg, Immediate(1));
3702 __ RecordComment("Minus zero");
3703 DeoptimizeIf(not_zero, instr->environment());
3704 }
3705 __ Move(output_reg, Immediate(0));
3706 __ bind(&done);
3707 } 3717 }
3708 3718
3709 3719
3710 void LCodeGen::DoMathSqrt(LMathSqrt* instr) { 3720 void LCodeGen::DoMathSqrt(LMathSqrt* instr) {
3711 XMMRegister input_reg = ToDoubleRegister(instr->value()); 3721 UNIMPLEMENTED();
3712 ASSERT(ToDoubleRegister(instr->result()).is(input_reg));
3713 __ sqrtsd(input_reg, input_reg);
3714 } 3722 }
3715 3723
3716 3724
3717 void LCodeGen::DoMathPowHalf(LMathPowHalf* instr) { 3725 void LCodeGen::DoMathPowHalf(LMathPowHalf* instr) {
3718 XMMRegister xmm_scratch = double_scratch0(); 3726 UNIMPLEMENTED();
3719 XMMRegister input_reg = ToDoubleRegister(instr->value());
3720 Register scratch = ToRegister(instr->temp());
3721 ASSERT(ToDoubleRegister(instr->result()).is(input_reg));
3722
3723 // Note that according to ECMA-262 15.8.2.13:
3724 // Math.pow(-Infinity, 0.5) == Infinity
3725 // Math.sqrt(-Infinity) == NaN
3726 Label done, sqrt;
3727 // Check base for -Infinity. According to IEEE-754, single-precision
3728 // -Infinity has the highest 9 bits set and the lowest 23 bits cleared.
3729 __ mov(scratch, 0xFF800000);
3730 __ movd(xmm_scratch, scratch);
3731 __ cvtss2sd(xmm_scratch, xmm_scratch);
3732 __ ucomisd(input_reg, xmm_scratch);
3733 // Comparing -Infinity with NaN results in "unordered", which sets the
3734 // zero flag as if both were equal. However, it also sets the carry flag.
3735 __ j(not_equal, &sqrt, Label::kNear);
3736 __ j(carry, &sqrt, Label::kNear);
3737 // If input is -Infinity, return Infinity.
3738 __ xorps(input_reg, input_reg);
3739 __ subsd(input_reg, xmm_scratch);
3740 __ jmp(&done, Label::kNear);
3741
3742 // Square root.
3743 __ bind(&sqrt);
3744 __ xorps(xmm_scratch, xmm_scratch);
3745 __ addsd(input_reg, xmm_scratch); // Convert -0 to +0.
3746 __ sqrtsd(input_reg, input_reg);
3747 __ bind(&done);
3748 } 3727 }
3749 3728
3750 3729
3751 void LCodeGen::DoPower(LPower* instr) { 3730 void LCodeGen::DoPower(LPower* instr) {
3752 Representation exponent_type = instr->hydrogen()->right()->representation(); 3731 UNIMPLEMENTED();
3753 // Having marked this as a call, we can use any registers.
3754 // Just make sure that the input/output registers are the expected ones.
3755 ASSERT(!instr->right()->IsDoubleRegister() ||
3756 ToDoubleRegister(instr->right()).is(xmm1));
3757 ASSERT(!instr->right()->IsRegister() ||
3758 ToRegister(instr->right()).is(eax));
3759 ASSERT(ToDoubleRegister(instr->left()).is(xmm2));
3760 ASSERT(ToDoubleRegister(instr->result()).is(xmm3));
3761
3762 if (exponent_type.IsSmi()) {
3763 MathPowStub stub(isolate(), MathPowStub::TAGGED);
3764 __ CallStub(&stub);
3765 } else if (exponent_type.IsTagged()) {
3766 Label no_deopt;
3767 __ JumpIfSmi(eax, &no_deopt);
3768 __ CmpObjectType(eax, HEAP_NUMBER_TYPE, ecx);
3769 DeoptimizeIf(not_equal, instr->environment());
3770 __ bind(&no_deopt);
3771 MathPowStub stub(isolate(), MathPowStub::TAGGED);
3772 __ CallStub(&stub);
3773 } else if (exponent_type.IsInteger32()) {
3774 MathPowStub stub(isolate(), MathPowStub::INTEGER);
3775 __ CallStub(&stub);
3776 } else {
3777 ASSERT(exponent_type.IsDouble());
3778 MathPowStub stub(isolate(), MathPowStub::DOUBLE);
3779 __ CallStub(&stub);
3780 }
3781 } 3732 }
3782 3733
3783 3734
3784 void LCodeGen::DoMathLog(LMathLog* instr) { 3735 void LCodeGen::DoMathLog(LMathLog* instr) {
3785 ASSERT(instr->value()->Equals(instr->result())); 3736 UNIMPLEMENTED();
3786 XMMRegister input_reg = ToDoubleRegister(instr->value());
3787 XMMRegister xmm_scratch = double_scratch0();
3788 Label positive, done, zero;
3789 __ xorps(xmm_scratch, xmm_scratch);
3790 __ ucomisd(input_reg, xmm_scratch);
3791 __ j(above, &positive, Label::kNear);
3792 __ j(not_carry, &zero, Label::kNear);
3793 ExternalReference nan =
3794 ExternalReference::address_of_canonical_non_hole_nan();
3795 __ movsd(input_reg, Operand::StaticVariable(nan));
3796 __ jmp(&done, Label::kNear);
3797 __ bind(&zero);
3798 ExternalReference ninf =
3799 ExternalReference::address_of_negative_infinity();
3800 __ movsd(input_reg, Operand::StaticVariable(ninf));
3801 __ jmp(&done, Label::kNear);
3802 __ bind(&positive);
3803 __ fldln2();
3804 __ sub(Operand(esp), Immediate(kDoubleSize));
3805 __ movsd(Operand(esp, 0), input_reg);
3806 __ fld_d(Operand(esp, 0));
3807 __ fyl2x();
3808 __ fstp_d(Operand(esp, 0));
3809 __ movsd(input_reg, Operand(esp, 0));
3810 __ add(Operand(esp), Immediate(kDoubleSize));
3811 __ bind(&done);
3812 } 3737 }
3813 3738
3814 3739
3815 void LCodeGen::DoMathClz32(LMathClz32* instr) { 3740 void LCodeGen::DoMathClz32(LMathClz32* instr) {
3816 Register input = ToRegister(instr->value()); 3741 UNIMPLEMENTED();
3817 Register result = ToRegister(instr->result());
3818 Label not_zero_input;
3819 __ bsr(result, input);
3820
3821 __ j(not_zero, &not_zero_input);
3822 __ Move(result, Immediate(63)); // 63^31 == 32
3823
3824 __ bind(&not_zero_input);
3825 __ xor_(result, Immediate(31)); // for x in [0..31], 31^x == 31-x.
3826 } 3742 }
3827 3743
3828 3744
3829 void LCodeGen::DoMathExp(LMathExp* instr) { 3745 void LCodeGen::DoMathExp(LMathExp* instr) {
3830 XMMRegister input = ToDoubleRegister(instr->value()); 3746 UNIMPLEMENTED();
3831 XMMRegister result = ToDoubleRegister(instr->result());
3832 XMMRegister temp0 = double_scratch0();
3833 Register temp1 = ToRegister(instr->temp1());
3834 Register temp2 = ToRegister(instr->temp2());
3835
3836 MathExpGenerator::EmitMathExp(masm(), input, result, temp0, temp1, temp2);
3837 } 3747 }
3838 3748
3839 3749
3840 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { 3750 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) {
3841 ASSERT(ToRegister(instr->context()).is(esi)); 3751 ASSERT(ToRegister(instr->context()).is(esi));
3842 ASSERT(ToRegister(instr->function()).is(edi)); 3752 ASSERT(ToRegister(instr->function()).is(edi));
3843 ASSERT(instr->HasPointerMap()); 3753 ASSERT(instr->HasPointerMap());
3844 3754
3845 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); 3755 Handle<JSFunction> known_function = instr->hydrogen()->known_function();
3846 if (known_function.is_null()) { 3756 if (known_function.is_null()) {
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
3923 __ bind(&done); 3833 __ bind(&done);
3924 } else { 3834 } else {
3925 ArrayNArgumentsConstructorStub stub(isolate(), kind, override_mode); 3835 ArrayNArgumentsConstructorStub stub(isolate(), kind, override_mode);
3926 CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr); 3836 CallCode(stub.GetCode(), RelocInfo::CONSTRUCT_CALL, instr);
3927 } 3837 }
3928 } 3838 }
3929 3839
3930 3840
3931 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { 3841 void LCodeGen::DoCallRuntime(LCallRuntime* instr) {
3932 ASSERT(ToRegister(instr->context()).is(esi)); 3842 ASSERT(ToRegister(instr->context()).is(esi));
3933 CallRuntime(instr->function(), instr->arity(), instr, instr->save_doubles()); 3843 CallRuntime(instr->function(), instr->arity(), instr);
3934 } 3844 }
3935 3845
3936 3846
3937 void LCodeGen::DoStoreCodeEntry(LStoreCodeEntry* instr) { 3847 void LCodeGen::DoStoreCodeEntry(LStoreCodeEntry* instr) {
3938 Register function = ToRegister(instr->function()); 3848 Register function = ToRegister(instr->function());
3939 Register code_object = ToRegister(instr->code_object()); 3849 Register code_object = ToRegister(instr->code_object());
3940 __ lea(code_object, FieldOperand(code_object, Code::kHeaderSize)); 3850 __ lea(code_object, FieldOperand(code_object, Code::kHeaderSize));
3941 __ mov(FieldOperand(function, JSFunction::kCodeEntryOffset), code_object); 3851 __ mov(FieldOperand(function, JSFunction::kCodeEntryOffset), code_object);
3942 } 3852 }
3943 3853
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
3998 DeoptimizeIf(zero, instr->environment()); 3908 DeoptimizeIf(zero, instr->environment());
3999 3909
4000 // We know now that value is not a smi, so we can omit the check below. 3910 // We know now that value is not a smi, so we can omit the check below.
4001 check_needed = OMIT_SMI_CHECK; 3911 check_needed = OMIT_SMI_CHECK;
4002 } 3912 }
4003 } 3913 }
4004 } else if (representation.IsDouble()) { 3914 } else if (representation.IsDouble()) {
4005 ASSERT(access.IsInobject()); 3915 ASSERT(access.IsInobject());
4006 ASSERT(!instr->hydrogen()->has_transition()); 3916 ASSERT(!instr->hydrogen()->has_transition());
4007 ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); 3917 ASSERT(!instr->hydrogen()->NeedsWriteBarrier());
4008 XMMRegister value = ToDoubleRegister(instr->value()); 3918 X87Register value = ToX87Register(instr->value());
4009 __ movsd(FieldOperand(object, offset), value); 3919 X87Mov(FieldOperand(object, offset), value);
4010 return; 3920 return;
4011 } 3921 }
4012 3922
4013 if (instr->hydrogen()->has_transition()) { 3923 if (instr->hydrogen()->has_transition()) {
4014 Handle<Map> transition = instr->hydrogen()->transition_map(); 3924 Handle<Map> transition = instr->hydrogen()->transition_map();
4015 AddDeprecationDependency(transition); 3925 AddDeprecationDependency(transition);
4016 if (!instr->hydrogen()->NeedsWriteBarrierForMap()) { 3926 if (!instr->hydrogen()->NeedsWriteBarrierForMap()) {
4017 __ mov(FieldOperand(object, HeapObject::kMapOffset), transition); 3927 __ mov(FieldOperand(object, HeapObject::kMapOffset), transition);
4018 } else { 3928 } else {
4019 Register temp = ToRegister(instr->temp()); 3929 Register temp = ToRegister(instr->temp());
4020 Register temp_map = ToRegister(instr->temp_map()); 3930 Register temp_map = ToRegister(instr->temp_map());
4021 __ mov(temp_map, transition); 3931 __ mov(temp_map, transition);
4022 __ mov(FieldOperand(object, HeapObject::kMapOffset), temp_map); 3932 __ mov(FieldOperand(object, HeapObject::kMapOffset), temp_map);
4023 // Update the write barrier for the map field. 3933 // Update the write barrier for the map field.
4024 __ RecordWriteField(object, 3934 __ RecordWriteField(object,
4025 HeapObject::kMapOffset, 3935 HeapObject::kMapOffset,
4026 temp_map, 3936 temp_map,
4027 temp, 3937 temp,
4028 kSaveFPRegs,
4029 OMIT_REMEMBERED_SET, 3938 OMIT_REMEMBERED_SET,
4030 OMIT_SMI_CHECK); 3939 OMIT_SMI_CHECK);
4031 } 3940 }
4032 } 3941 }
4033 3942
4034 // Do the store. 3943 // Do the store.
4035 Register write_register = object; 3944 Register write_register = object;
4036 if (!access.IsInobject()) { 3945 if (!access.IsInobject()) {
4037 write_register = ToRegister(instr->temp()); 3946 write_register = ToRegister(instr->temp());
4038 __ mov(write_register, FieldOperand(object, JSObject::kPropertiesOffset)); 3947 __ mov(write_register, FieldOperand(object, JSObject::kPropertiesOffset));
(...skipping 20 matching lines...) Expand all
4059 } 3968 }
4060 3969
4061 if (instr->hydrogen()->NeedsWriteBarrier()) { 3970 if (instr->hydrogen()->NeedsWriteBarrier()) {
4062 Register value = ToRegister(instr->value()); 3971 Register value = ToRegister(instr->value());
4063 Register temp = access.IsInobject() ? ToRegister(instr->temp()) : object; 3972 Register temp = access.IsInobject() ? ToRegister(instr->temp()) : object;
4064 // Update the write barrier for the object for in-object properties. 3973 // Update the write barrier for the object for in-object properties.
4065 __ RecordWriteField(write_register, 3974 __ RecordWriteField(write_register,
4066 offset, 3975 offset,
4067 value, 3976 value,
4068 temp, 3977 temp,
4069 kSaveFPRegs,
4070 EMIT_REMEMBERED_SET, 3978 EMIT_REMEMBERED_SET,
4071 check_needed); 3979 check_needed);
4072 } 3980 }
4073 } 3981 }
4074 3982
4075 3983
4076 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { 3984 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) {
4077 ASSERT(ToRegister(instr->context()).is(esi)); 3985 ASSERT(ToRegister(instr->context()).is(esi));
4078 ASSERT(ToRegister(instr->object()).is(edx)); 3986 ASSERT(ToRegister(instr->object()).is(edx));
4079 ASSERT(ToRegister(instr->value()).is(eax)); 3987 ASSERT(ToRegister(instr->value()).is(eax));
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
4119 } 4027 }
4120 Operand operand(BuildFastArrayOperand( 4028 Operand operand(BuildFastArrayOperand(
4121 instr->elements(), 4029 instr->elements(),
4122 key, 4030 key,
4123 instr->hydrogen()->key()->representation(), 4031 instr->hydrogen()->key()->representation(),
4124 elements_kind, 4032 elements_kind,
4125 0, 4033 0,
4126 instr->additional_index())); 4034 instr->additional_index()));
4127 if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS || 4035 if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS ||
4128 elements_kind == FLOAT32_ELEMENTS) { 4036 elements_kind == FLOAT32_ELEMENTS) {
4129 XMMRegister xmm_scratch = double_scratch0(); 4037 __ fld(0);
4130 __ cvtsd2ss(xmm_scratch, ToDoubleRegister(instr->value())); 4038 __ fstp_s(operand);
4131 __ movss(operand, xmm_scratch);
4132 } else if (elements_kind == EXTERNAL_FLOAT64_ELEMENTS || 4039 } else if (elements_kind == EXTERNAL_FLOAT64_ELEMENTS ||
4133 elements_kind == FLOAT64_ELEMENTS) { 4040 elements_kind == FLOAT64_ELEMENTS) {
4134 __ movsd(operand, ToDoubleRegister(instr->value())); 4041 X87Mov(operand, ToX87Register(instr->value()));
4135 } else { 4042 } else {
4136 Register value = ToRegister(instr->value()); 4043 Register value = ToRegister(instr->value());
4137 switch (elements_kind) { 4044 switch (elements_kind) {
4138 case EXTERNAL_UINT8_CLAMPED_ELEMENTS: 4045 case EXTERNAL_UINT8_CLAMPED_ELEMENTS:
4139 case EXTERNAL_UINT8_ELEMENTS: 4046 case EXTERNAL_UINT8_ELEMENTS:
4140 case EXTERNAL_INT8_ELEMENTS: 4047 case EXTERNAL_INT8_ELEMENTS:
4141 case UINT8_ELEMENTS: 4048 case UINT8_ELEMENTS:
4142 case INT8_ELEMENTS: 4049 case INT8_ELEMENTS:
4143 case UINT8_CLAMPED_ELEMENTS: 4050 case UINT8_CLAMPED_ELEMENTS:
4144 __ mov_b(operand, value); 4051 __ mov_b(operand, value);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
4178 ExternalReference canonical_nan_reference = 4085 ExternalReference canonical_nan_reference =
4179 ExternalReference::address_of_canonical_non_hole_nan(); 4086 ExternalReference::address_of_canonical_non_hole_nan();
4180 Operand double_store_operand = BuildFastArrayOperand( 4087 Operand double_store_operand = BuildFastArrayOperand(
4181 instr->elements(), 4088 instr->elements(),
4182 instr->key(), 4089 instr->key(),
4183 instr->hydrogen()->key()->representation(), 4090 instr->hydrogen()->key()->representation(),
4184 FAST_DOUBLE_ELEMENTS, 4091 FAST_DOUBLE_ELEMENTS,
4185 FixedDoubleArray::kHeaderSize - kHeapObjectTag, 4092 FixedDoubleArray::kHeaderSize - kHeapObjectTag,
4186 instr->additional_index()); 4093 instr->additional_index());
4187 4094
4188 XMMRegister value = ToDoubleRegister(instr->value()); 4095 // Can't use SSE2 in the serializer
4096 if (instr->hydrogen()->IsConstantHoleStore()) {
4097 // This means we should store the (double) hole. No floating point
4098 // registers required.
4099 double nan_double = FixedDoubleArray::hole_nan_as_double();
4100 uint64_t int_val = BitCast<uint64_t, double>(nan_double);
4101 int32_t lower = static_cast<int32_t>(int_val);
4102 int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt));
4189 4103
4190 if (instr->NeedsCanonicalization()) { 4104 __ mov(double_store_operand, Immediate(lower));
4191 Label have_value; 4105 Operand double_store_operand2 = BuildFastArrayOperand(
4106 instr->elements(),
4107 instr->key(),
4108 instr->hydrogen()->key()->representation(),
4109 FAST_DOUBLE_ELEMENTS,
4110 FixedDoubleArray::kHeaderSize - kHeapObjectTag + kPointerSize,
4111 instr->additional_index());
4112 __ mov(double_store_operand2, Immediate(upper));
4113 } else {
4114 Label no_special_nan_handling;
4115 X87Register value = ToX87Register(instr->value());
4116 X87Fxch(value);
4192 4117
4193 __ ucomisd(value, value); 4118 if (instr->NeedsCanonicalization()) {
4194 __ j(parity_odd, &have_value, Label::kNear); // NaN. 4119 __ fld(0);
4120 __ fld(0);
4121 __ FCmp();
4195 4122
4196 __ movsd(value, Operand::StaticVariable(canonical_nan_reference)); 4123 __ j(parity_odd, &no_special_nan_handling, Label::kNear);
4197 __ bind(&have_value); 4124 __ sub(esp, Immediate(kDoubleSize));
4125 __ fst_d(MemOperand(esp, 0));
4126 __ cmp(MemOperand(esp, sizeof(kHoleNanLower32)),
4127 Immediate(kHoleNanUpper32));
4128 __ add(esp, Immediate(kDoubleSize));
4129 Label canonicalize;
4130 __ j(not_equal, &canonicalize, Label::kNear);
4131 __ jmp(&no_special_nan_handling, Label::kNear);
4132 __ bind(&canonicalize);
4133 __ fstp(0);
4134 __ fld_d(Operand::StaticVariable(canonical_nan_reference));
4135 }
4136
4137 __ bind(&no_special_nan_handling);
4138 __ fst_d(double_store_operand);
4198 } 4139 }
4199
4200 __ movsd(double_store_operand, value);
4201 } 4140 }
4202 4141
4203 4142
4204 void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) { 4143 void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) {
4205 Register elements = ToRegister(instr->elements()); 4144 Register elements = ToRegister(instr->elements());
4206 Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg; 4145 Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg;
4207 4146
4208 Operand operand = BuildFastArrayOperand( 4147 Operand operand = BuildFastArrayOperand(
4209 instr->elements(), 4148 instr->elements(),
4210 instr->key(), 4149 instr->key(),
(...skipping 20 matching lines...) Expand all
4231 Register value = ToRegister(instr->value()); 4170 Register value = ToRegister(instr->value());
4232 ASSERT(!instr->key()->IsConstantOperand()); 4171 ASSERT(!instr->key()->IsConstantOperand());
4233 SmiCheck check_needed = 4172 SmiCheck check_needed =
4234 instr->hydrogen()->value()->IsHeapObject() 4173 instr->hydrogen()->value()->IsHeapObject()
4235 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; 4174 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
4236 // Compute address of modified element and store it into key register. 4175 // Compute address of modified element and store it into key register.
4237 __ lea(key, operand); 4176 __ lea(key, operand);
4238 __ RecordWrite(elements, 4177 __ RecordWrite(elements,
4239 key, 4178 key,
4240 value, 4179 value,
4241 kSaveFPRegs,
4242 EMIT_REMEMBERED_SET, 4180 EMIT_REMEMBERED_SET,
4243 check_needed); 4181 check_needed);
4244 } 4182 }
4245 } 4183 }
4246 4184
4247 4185
4248 void LCodeGen::DoStoreKeyed(LStoreKeyed* instr) { 4186 void LCodeGen::DoStoreKeyed(LStoreKeyed* instr) {
4249 // By cases...external, fast-double, fast 4187 // By cases...external, fast-double, fast
4250 if (instr->is_typed_elements()) { 4188 if (instr->is_typed_elements()) {
4251 DoStoreKeyedExternalArray(instr); 4189 DoStoreKeyedExternalArray(instr);
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
4295 is_simple_map_transition ? Label::kNear : Label::kFar; 4233 is_simple_map_transition ? Label::kNear : Label::kFar;
4296 __ cmp(FieldOperand(object_reg, HeapObject::kMapOffset), from_map); 4234 __ cmp(FieldOperand(object_reg, HeapObject::kMapOffset), from_map);
4297 __ j(not_equal, &not_applicable, branch_distance); 4235 __ j(not_equal, &not_applicable, branch_distance);
4298 if (is_simple_map_transition) { 4236 if (is_simple_map_transition) {
4299 Register new_map_reg = ToRegister(instr->new_map_temp()); 4237 Register new_map_reg = ToRegister(instr->new_map_temp());
4300 __ mov(FieldOperand(object_reg, HeapObject::kMapOffset), 4238 __ mov(FieldOperand(object_reg, HeapObject::kMapOffset),
4301 Immediate(to_map)); 4239 Immediate(to_map));
4302 // Write barrier. 4240 // Write barrier.
4303 ASSERT_NE(instr->temp(), NULL); 4241 ASSERT_NE(instr->temp(), NULL);
4304 __ RecordWriteForMap(object_reg, to_map, new_map_reg, 4242 __ RecordWriteForMap(object_reg, to_map, new_map_reg,
4305 ToRegister(instr->temp()), 4243 ToRegister(instr->temp()));
4306 kDontSaveFPRegs);
4307 } else { 4244 } else {
4308 ASSERT(ToRegister(instr->context()).is(esi)); 4245 ASSERT(ToRegister(instr->context()).is(esi));
4309 ASSERT(object_reg.is(eax)); 4246 ASSERT(object_reg.is(eax));
4310 PushSafepointRegistersScope scope(this); 4247 PushSafepointRegistersScope scope(this);
4311 __ mov(ebx, to_map); 4248 __ mov(ebx, to_map);
4312 bool is_js_array = from_map->instance_type() == JS_ARRAY_TYPE; 4249 bool is_js_array = from_map->instance_type() == JS_ARRAY_TYPE;
4313 TransitionElementsKindStub stub(isolate(), from_kind, to_kind, is_js_array); 4250 TransitionElementsKindStub stub(isolate(), from_kind, to_kind, is_js_array);
4314 __ CallStub(&stub); 4251 __ CallStub(&stub);
4315 RecordSafepointWithLazyDeopt(instr, 4252 RecordSafepointWithLazyDeopt(instr,
4316 RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); 4253 RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
4317 } 4254 }
4318 __ bind(&not_applicable); 4255 __ bind(&not_applicable);
4319 } 4256 }
4320 4257
4321 4258
4322 void LCodeGen::DoArrayShift(LArrayShift* instr) { 4259 void LCodeGen::DoArrayShift(LArrayShift* instr) {
4323 ASSERT(ToRegister(instr->context()).is(esi)); 4260 ASSERT(ToRegister(instr->context()).is(esi));
4324 ASSERT(ToRegister(instr->object()).is(eax)); 4261 ASSERT(ToRegister(instr->object()).is(eax));
4325 ASSERT(ToRegister(instr->result()).is(eax)); 4262 ASSERT(ToRegister(instr->result()).is(eax));
4326 ArrayShiftStub stub(isolate(), instr->hydrogen()->kind()); 4263 ArrayShiftStub stub(isolate(), instr->hydrogen()->kind());
4327 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 4264 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
4328 } 4265 }
4329 4266
4330 4267
4331 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { 4268 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
4332 class DeferredStringCharCodeAt V8_FINAL : public LDeferredCode { 4269 class DeferredStringCharCodeAt V8_FINAL : public LDeferredCode {
4333 public: 4270 public:
4334 DeferredStringCharCodeAt(LCodeGen* codegen, 4271 DeferredStringCharCodeAt(LCodeGen* codegen,
4335 LStringCharCodeAt* instr) 4272 LStringCharCodeAt* instr,
4336 : LDeferredCode(codegen), instr_(instr) { } 4273 const X87Stack& x87_stack)
4274 : LDeferredCode(codegen, x87_stack), instr_(instr) { }
4337 virtual void Generate() V8_OVERRIDE { 4275 virtual void Generate() V8_OVERRIDE {
4338 codegen()->DoDeferredStringCharCodeAt(instr_); 4276 codegen()->DoDeferredStringCharCodeAt(instr_);
4339 } 4277 }
4340 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } 4278 virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
4341 private: 4279 private:
4342 LStringCharCodeAt* instr_; 4280 LStringCharCodeAt* instr_;
4343 }; 4281 };
4344 4282
4345 DeferredStringCharCodeAt* deferred = 4283 DeferredStringCharCodeAt* deferred =
4346 new(zone()) DeferredStringCharCodeAt(this, instr); 4284 new(zone()) DeferredStringCharCodeAt(this, instr, x87_stack_);
4347 4285
4348 StringCharLoadGenerator::Generate(masm(), 4286 StringCharLoadGenerator::Generate(masm(),
4349 factory(), 4287 factory(),
4350 ToRegister(instr->string()), 4288 ToRegister(instr->string()),
4351 ToRegister(instr->index()), 4289 ToRegister(instr->index()),
4352 ToRegister(instr->result()), 4290 ToRegister(instr->result()),
4353 deferred->entry()); 4291 deferred->entry());
4354 __ bind(deferred->exit()); 4292 __ bind(deferred->exit());
4355 } 4293 }
4356 4294
(...skipping 26 matching lines...) Expand all
4383 __ AssertSmi(eax); 4321 __ AssertSmi(eax);
4384 __ SmiUntag(eax); 4322 __ SmiUntag(eax);
4385 __ StoreToSafepointRegisterSlot(result, eax); 4323 __ StoreToSafepointRegisterSlot(result, eax);
4386 } 4324 }
4387 4325
4388 4326
4389 void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) { 4327 void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) {
4390 class DeferredStringCharFromCode V8_FINAL : public LDeferredCode { 4328 class DeferredStringCharFromCode V8_FINAL : public LDeferredCode {
4391 public: 4329 public:
4392 DeferredStringCharFromCode(LCodeGen* codegen, 4330 DeferredStringCharFromCode(LCodeGen* codegen,
4393 LStringCharFromCode* instr) 4331 LStringCharFromCode* instr,
4394 : LDeferredCode(codegen), instr_(instr) { } 4332 const X87Stack& x87_stack)
4333 : LDeferredCode(codegen, x87_stack), instr_(instr) { }
4395 virtual void Generate() V8_OVERRIDE { 4334 virtual void Generate() V8_OVERRIDE {
4396 codegen()->DoDeferredStringCharFromCode(instr_); 4335 codegen()->DoDeferredStringCharFromCode(instr_);
4397 } 4336 }
4398 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } 4337 virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
4399 private: 4338 private:
4400 LStringCharFromCode* instr_; 4339 LStringCharFromCode* instr_;
4401 }; 4340 };
4402 4341
4403 DeferredStringCharFromCode* deferred = 4342 DeferredStringCharFromCode* deferred =
4404 new(zone()) DeferredStringCharFromCode(this, instr); 4343 new(zone()) DeferredStringCharFromCode(this, instr, x87_stack_);
4405 4344
4406 ASSERT(instr->hydrogen()->value()->representation().IsInteger32()); 4345 ASSERT(instr->hydrogen()->value()->representation().IsInteger32());
4407 Register char_code = ToRegister(instr->char_code()); 4346 Register char_code = ToRegister(instr->char_code());
4408 Register result = ToRegister(instr->result()); 4347 Register result = ToRegister(instr->result());
4409 ASSERT(!char_code.is(result)); 4348 ASSERT(!char_code.is(result));
4410 4349
4411 __ cmp(char_code, String::kMaxOneByteCharCode); 4350 __ cmp(char_code, String::kMaxOneByteCharCode);
4412 __ j(above, deferred->entry()); 4351 __ j(above, deferred->entry());
4413 __ Move(result, Immediate(factory()->single_character_string_cache())); 4352 __ Move(result, Immediate(factory()->single_character_string_cache()));
4414 __ mov(result, FieldOperand(result, 4353 __ mov(result, FieldOperand(result,
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
4446 instr->hydrogen()->pretenure_flag()); 4385 instr->hydrogen()->pretenure_flag());
4447 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 4386 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
4448 } 4387 }
4449 4388
4450 4389
4451 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { 4390 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) {
4452 LOperand* input = instr->value(); 4391 LOperand* input = instr->value();
4453 LOperand* output = instr->result(); 4392 LOperand* output = instr->result();
4454 ASSERT(input->IsRegister() || input->IsStackSlot()); 4393 ASSERT(input->IsRegister() || input->IsStackSlot());
4455 ASSERT(output->IsDoubleRegister()); 4394 ASSERT(output->IsDoubleRegister());
4456 __ Cvtsi2sd(ToDoubleRegister(output), ToOperand(input)); 4395 if (input->IsRegister()) {
4396 Register input_reg = ToRegister(input);
4397 __ push(input_reg);
4398 X87Mov(ToX87Register(output), Operand(esp, 0), kX87IntOperand);
4399 __ pop(input_reg);
4400 } else {
4401 X87Mov(ToX87Register(output), ToOperand(input), kX87IntOperand);
4402 }
4457 } 4403 }
4458 4404
4459 4405
4460 void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) { 4406 void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) {
4461 LOperand* input = instr->value(); 4407 LOperand* input = instr->value();
4462 LOperand* output = instr->result(); 4408 LOperand* output = instr->result();
4463 LOperand* temp = instr->temp(); 4409 X87Register res = ToX87Register(output);
4464 __ LoadUint32(ToDoubleRegister(output), 4410 X87PrepareToWrite(res);
4465 ToRegister(input), 4411 __ LoadUint32NoSSE2(ToRegister(input));
4466 ToDoubleRegister(temp)); 4412 X87CommitWrite(res);
4467 } 4413 }
4468 4414
4469 4415
4470 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { 4416 void LCodeGen::DoNumberTagI(LNumberTagI* instr) {
4471 class DeferredNumberTagI V8_FINAL : public LDeferredCode { 4417 class DeferredNumberTagI V8_FINAL : public LDeferredCode {
4472 public: 4418 public:
4473 DeferredNumberTagI(LCodeGen* codegen, 4419 DeferredNumberTagI(LCodeGen* codegen,
4474 LNumberTagI* instr) 4420 LNumberTagI* instr,
4475 : LDeferredCode(codegen), instr_(instr) { } 4421 const X87Stack& x87_stack)
4422 : LDeferredCode(codegen, x87_stack), instr_(instr) { }
4476 virtual void Generate() V8_OVERRIDE { 4423 virtual void Generate() V8_OVERRIDE {
4477 codegen()->DoDeferredNumberTagIU(instr_, instr_->value(), instr_->temp(), 4424 codegen()->DoDeferredNumberTagIU(instr_, instr_->value(), instr_->temp(),
4478 NULL, SIGNED_INT32); 4425 SIGNED_INT32);
4479 } 4426 }
4480 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } 4427 virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
4481 private: 4428 private:
4482 LNumberTagI* instr_; 4429 LNumberTagI* instr_;
4483 }; 4430 };
4484 4431
4485 LOperand* input = instr->value(); 4432 LOperand* input = instr->value();
4486 ASSERT(input->IsRegister() && input->Equals(instr->result())); 4433 ASSERT(input->IsRegister() && input->Equals(instr->result()));
4487 Register reg = ToRegister(input); 4434 Register reg = ToRegister(input);
4488 4435
4489 DeferredNumberTagI* deferred = 4436 DeferredNumberTagI* deferred =
4490 new(zone()) DeferredNumberTagI(this, instr); 4437 new(zone()) DeferredNumberTagI(this, instr, x87_stack_);
4491 __ SmiTag(reg); 4438 __ SmiTag(reg);
4492 __ j(overflow, deferred->entry()); 4439 __ j(overflow, deferred->entry());
4493 __ bind(deferred->exit()); 4440 __ bind(deferred->exit());
4494 } 4441 }
4495 4442
4496 4443
4497 void LCodeGen::DoNumberTagU(LNumberTagU* instr) { 4444 void LCodeGen::DoNumberTagU(LNumberTagU* instr) {
4498 class DeferredNumberTagU V8_FINAL : public LDeferredCode { 4445 class DeferredNumberTagU V8_FINAL : public LDeferredCode {
4499 public: 4446 public:
4500 DeferredNumberTagU(LCodeGen* codegen, LNumberTagU* instr) 4447 DeferredNumberTagU(LCodeGen* codegen,
4501 : LDeferredCode(codegen), instr_(instr) { } 4448 LNumberTagU* instr,
4449 const X87Stack& x87_stack)
4450 : LDeferredCode(codegen, x87_stack), instr_(instr) { }
4502 virtual void Generate() V8_OVERRIDE { 4451 virtual void Generate() V8_OVERRIDE {
4503 codegen()->DoDeferredNumberTagIU(instr_, instr_->value(), instr_->temp1(), 4452 codegen()->DoDeferredNumberTagIU(instr_, instr_->value(), instr_->temp(),
4504 instr_->temp2(), UNSIGNED_INT32); 4453 UNSIGNED_INT32);
4505 } 4454 }
4506 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } 4455 virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
4507 private: 4456 private:
4508 LNumberTagU* instr_; 4457 LNumberTagU* instr_;
4509 }; 4458 };
4510 4459
4511 LOperand* input = instr->value(); 4460 LOperand* input = instr->value();
4512 ASSERT(input->IsRegister() && input->Equals(instr->result())); 4461 ASSERT(input->IsRegister() && input->Equals(instr->result()));
4513 Register reg = ToRegister(input); 4462 Register reg = ToRegister(input);
4514 4463
4515 DeferredNumberTagU* deferred = 4464 DeferredNumberTagU* deferred =
4516 new(zone()) DeferredNumberTagU(this, instr); 4465 new(zone()) DeferredNumberTagU(this, instr, x87_stack_);
4517 __ cmp(reg, Immediate(Smi::kMaxValue)); 4466 __ cmp(reg, Immediate(Smi::kMaxValue));
4518 __ j(above, deferred->entry()); 4467 __ j(above, deferred->entry());
4519 __ SmiTag(reg); 4468 __ SmiTag(reg);
4520 __ bind(deferred->exit()); 4469 __ bind(deferred->exit());
4521 } 4470 }
4522 4471
4523 4472
4524 void LCodeGen::DoDeferredNumberTagIU(LInstruction* instr, 4473 void LCodeGen::DoDeferredNumberTagIU(LInstruction* instr,
4525 LOperand* value, 4474 LOperand* value,
4526 LOperand* temp1, 4475 LOperand* temp,
4527 LOperand* temp2,
4528 IntegerSignedness signedness) { 4476 IntegerSignedness signedness) {
4529 Label done, slow; 4477 Label done, slow;
4530 Register reg = ToRegister(value); 4478 Register reg = ToRegister(value);
4531 Register tmp = ToRegister(temp1); 4479 Register tmp = ToRegister(temp);
4532 XMMRegister xmm_scratch = double_scratch0();
4533 4480
4534 if (signedness == SIGNED_INT32) { 4481 if (signedness == SIGNED_INT32) {
4535 // There was overflow, so bits 30 and 31 of the original integer 4482 // There was overflow, so bits 30 and 31 of the original integer
4536 // disagree. Try to allocate a heap number in new space and store 4483 // disagree. Try to allocate a heap number in new space and store
4537 // the value in there. If that fails, call the runtime system. 4484 // the value in there. If that fails, call the runtime system.
4538 __ SmiUntag(reg); 4485 __ SmiUntag(reg);
4539 __ xor_(reg, 0x80000000); 4486 __ xor_(reg, 0x80000000);
4540 __ Cvtsi2sd(xmm_scratch, Operand(reg)); 4487 __ push(reg);
4488 __ fild_s(Operand(esp, 0));
4489 __ pop(reg);
4541 } else { 4490 } else {
4542 __ LoadUint32(xmm_scratch, reg, ToDoubleRegister(temp2)); 4491 // There's no fild variant for unsigned values, so zero-extend to a 64-bit
4492 // int manually.
4493 __ push(Immediate(0));
4494 __ push(reg);
4495 __ fild_d(Operand(esp, 0));
4496 __ pop(reg);
4497 __ pop(reg);
4543 } 4498 }
4544 4499
4545 if (FLAG_inline_new) { 4500 if (FLAG_inline_new) {
4546 __ AllocateHeapNumber(reg, tmp, no_reg, &slow); 4501 __ AllocateHeapNumber(reg, tmp, no_reg, &slow);
4547 __ jmp(&done, Label::kNear); 4502 __ jmp(&done, Label::kNear);
4548 } 4503 }
4549 4504
4550 // Slow case: Call the runtime system to do the number allocation. 4505 // Slow case: Call the runtime system to do the number allocation.
4551 __ bind(&slow); 4506 __ bind(&slow);
4552 { 4507 {
4553 // TODO(3095996): Put a valid pointer value in the stack slot where the 4508 // TODO(3095996): Put a valid pointer value in the stack slot where the
4554 // result register is stored, as this register is in the pointer map, but 4509 // result register is stored, as this register is in the pointer map, but
4555 // contains an integer value. 4510 // contains an integer value.
4556 __ Move(reg, Immediate(0)); 4511 __ Move(reg, Immediate(0));
4557 4512
4558 // Preserve the value of all registers. 4513 // Preserve the value of all registers.
4559 PushSafepointRegistersScope scope(this); 4514 PushSafepointRegistersScope scope(this);
4560 4515
4561 // NumberTagI and NumberTagD use the context from the frame, rather than 4516 // NumberTagI and NumberTagD use the context from the frame, rather than
4562 // the environment's HContext or HInlinedContext value. 4517 // the environment's HContext or HInlinedContext value.
4563 // They only call Runtime::kHiddenAllocateHeapNumber. 4518 // They only call Runtime::kHiddenAllocateHeapNumber.
4564 // The corresponding HChange instructions are added in a phase that does 4519 // The corresponding HChange instructions are added in a phase that does
4565 // not have easy access to the local context. 4520 // not have easy access to the local context.
4566 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 4521 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
4567 __ CallRuntimeSaveDoubles(Runtime::kHiddenAllocateHeapNumber); 4522 __ CallRuntime(Runtime::kHiddenAllocateHeapNumber);
4568 RecordSafepointWithRegisters( 4523 RecordSafepointWithRegisters(
4569 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); 4524 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
4570 __ StoreToSafepointRegisterSlot(reg, eax); 4525 __ StoreToSafepointRegisterSlot(reg, eax);
4571 } 4526 }
4572 4527
4573 // Done. Put the value in xmm_scratch into the value of the allocated heap
4574 // number.
4575 __ bind(&done); 4528 __ bind(&done);
4576 __ movsd(FieldOperand(reg, HeapNumber::kValueOffset), xmm_scratch); 4529 __ fstp_d(FieldOperand(reg, HeapNumber::kValueOffset));
4577 } 4530 }
4578 4531
4579 4532
4580 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { 4533 void LCodeGen::DoNumberTagD(LNumberTagD* instr) {
4581 class DeferredNumberTagD V8_FINAL : public LDeferredCode { 4534 class DeferredNumberTagD V8_FINAL : public LDeferredCode {
4582 public: 4535 public:
4583 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) 4536 DeferredNumberTagD(LCodeGen* codegen,
4584 : LDeferredCode(codegen), instr_(instr) { } 4537 LNumberTagD* instr,
4538 const X87Stack& x87_stack)
4539 : LDeferredCode(codegen, x87_stack), instr_(instr) { }
4585 virtual void Generate() V8_OVERRIDE { 4540 virtual void Generate() V8_OVERRIDE {
4586 codegen()->DoDeferredNumberTagD(instr_); 4541 codegen()->DoDeferredNumberTagD(instr_);
4587 } 4542 }
4588 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } 4543 virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
4589 private: 4544 private:
4590 LNumberTagD* instr_; 4545 LNumberTagD* instr_;
4591 }; 4546 };
4592 4547
4593 Register reg = ToRegister(instr->result()); 4548 Register reg = ToRegister(instr->result());
4594 4549
4550 // Put the value to the top of stack
4551 X87Register src = ToX87Register(instr->value());
4552 X87LoadForUsage(src);
4553
4595 DeferredNumberTagD* deferred = 4554 DeferredNumberTagD* deferred =
4596 new(zone()) DeferredNumberTagD(this, instr); 4555 new(zone()) DeferredNumberTagD(this, instr, x87_stack_);
4597 if (FLAG_inline_new) { 4556 if (FLAG_inline_new) {
4598 Register tmp = ToRegister(instr->temp()); 4557 Register tmp = ToRegister(instr->temp());
4599 __ AllocateHeapNumber(reg, tmp, no_reg, deferred->entry()); 4558 __ AllocateHeapNumber(reg, tmp, no_reg, deferred->entry());
4600 } else { 4559 } else {
4601 __ jmp(deferred->entry()); 4560 __ jmp(deferred->entry());
4602 } 4561 }
4603 __ bind(deferred->exit()); 4562 __ bind(deferred->exit());
4604 XMMRegister input_reg = ToDoubleRegister(instr->value()); 4563 __ fstp_d(FieldOperand(reg, HeapNumber::kValueOffset));
4605 __ movsd(FieldOperand(reg, HeapNumber::kValueOffset), input_reg);
4606 } 4564 }
4607 4565
4608 4566
4609 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { 4567 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) {
4610 // TODO(3095996): Get rid of this. For now, we need to make the 4568 // TODO(3095996): Get rid of this. For now, we need to make the
4611 // result register contain a valid pointer because it is already 4569 // result register contain a valid pointer because it is already
4612 // contained in the register pointer map. 4570 // contained in the register pointer map.
4613 Register reg = ToRegister(instr->result()); 4571 Register reg = ToRegister(instr->result());
4614 __ Move(reg, Immediate(0)); 4572 __ Move(reg, Immediate(0));
4615 4573
4616 PushSafepointRegistersScope scope(this); 4574 PushSafepointRegistersScope scope(this);
4617 // NumberTagI and NumberTagD use the context from the frame, rather than 4575 // NumberTagI and NumberTagD use the context from the frame, rather than
4618 // the environment's HContext or HInlinedContext value. 4576 // the environment's HContext or HInlinedContext value.
4619 // They only call Runtime::kHiddenAllocateHeapNumber. 4577 // They only call Runtime::kHiddenAllocateHeapNumber.
4620 // The corresponding HChange instructions are added in a phase that does 4578 // The corresponding HChange instructions are added in a phase that does
4621 // not have easy access to the local context. 4579 // not have easy access to the local context.
4622 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 4580 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
4623 __ CallRuntimeSaveDoubles(Runtime::kHiddenAllocateHeapNumber); 4581 __ CallRuntime(Runtime::kHiddenAllocateHeapNumber);
4624 RecordSafepointWithRegisters( 4582 RecordSafepointWithRegisters(
4625 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); 4583 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
4626 __ StoreToSafepointRegisterSlot(reg, eax); 4584 __ StoreToSafepointRegisterSlot(reg, eax);
4627 } 4585 }
4628 4586
4629 4587
4630 void LCodeGen::DoSmiTag(LSmiTag* instr) { 4588 void LCodeGen::DoSmiTag(LSmiTag* instr) {
4631 HChange* hchange = instr->hydrogen(); 4589 HChange* hchange = instr->hydrogen();
4632 Register input = ToRegister(instr->value()); 4590 Register input = ToRegister(instr->value());
4633 if (hchange->CheckFlag(HValue::kCanOverflow) && 4591 if (hchange->CheckFlag(HValue::kCanOverflow) &&
(...skipping 16 matching lines...) Expand all
4650 if (instr->needs_check()) { 4608 if (instr->needs_check()) {
4651 __ test(result, Immediate(kSmiTagMask)); 4609 __ test(result, Immediate(kSmiTagMask));
4652 DeoptimizeIf(not_zero, instr->environment()); 4610 DeoptimizeIf(not_zero, instr->environment());
4653 } else { 4611 } else {
4654 __ AssertSmi(result); 4612 __ AssertSmi(result);
4655 } 4613 }
4656 __ SmiUntag(result); 4614 __ SmiUntag(result);
4657 } 4615 }
4658 4616
4659 4617
4660 void LCodeGen::EmitNumberUntagD(Register input_reg, 4618 void LCodeGen::EmitNumberUntagDNoSSE2(Register input_reg,
4661 Register temp_reg, 4619 Register temp_reg,
4662 XMMRegister result_reg, 4620 X87Register res_reg,
4663 bool can_convert_undefined_to_nan, 4621 bool can_convert_undefined_to_nan,
4664 bool deoptimize_on_minus_zero, 4622 bool deoptimize_on_minus_zero,
4665 LEnvironment* env, 4623 LEnvironment* env,
4666 NumberUntagDMode mode) { 4624 NumberUntagDMode mode) {
4667 Label convert, load_smi, done; 4625 Label load_smi, done;
4668 4626
4627 X87PrepareToWrite(res_reg);
4669 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) { 4628 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) {
4670 // Smi check. 4629 // Smi check.
4671 __ JumpIfSmi(input_reg, &load_smi, Label::kNear); 4630 __ JumpIfSmi(input_reg, &load_smi, Label::kNear);
4672 4631
4673 // Heap number map check. 4632 // Heap number map check.
4674 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), 4633 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
4675 factory()->heap_number_map()); 4634 factory()->heap_number_map());
4676 if (can_convert_undefined_to_nan) { 4635 if (!can_convert_undefined_to_nan) {
4677 __ j(not_equal, &convert, Label::kNear); 4636 DeoptimizeIf(not_equal, env);
4678 } else { 4637 } else {
4638 Label heap_number, convert;
4639 __ j(equal, &heap_number, Label::kNear);
4640
4641 // Convert undefined (or hole) to NaN.
4642 __ cmp(input_reg, factory()->undefined_value());
4679 DeoptimizeIf(not_equal, env); 4643 DeoptimizeIf(not_equal, env);
4644
4645 __ bind(&convert);
4646 ExternalReference nan =
4647 ExternalReference::address_of_canonical_non_hole_nan();
4648 __ fld_d(Operand::StaticVariable(nan));
4649 __ jmp(&done, Label::kNear);
4650
4651 __ bind(&heap_number);
4680 } 4652 }
4653 // Heap number to x87 conversion.
4654 __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset));
4655 if (deoptimize_on_minus_zero) {
4656 __ fldz();
4657 __ FCmp();
4658 __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset));
4659 __ j(not_zero, &done, Label::kNear);
4681 4660
4682 // Heap number to XMM conversion. 4661 // Use general purpose registers to check if we have -0.0
4683 __ movsd(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset)); 4662 __ mov(temp_reg, FieldOperand(input_reg, HeapNumber::kExponentOffset));
4663 __ test(temp_reg, Immediate(HeapNumber::kSignMask));
4664 __ j(zero, &done, Label::kNear);
4684 4665
4685 if (deoptimize_on_minus_zero) { 4666 // Pop FPU stack before deoptimizing.
4686 XMMRegister xmm_scratch = double_scratch0(); 4667 __ fstp(0);
4687 __ xorps(xmm_scratch, xmm_scratch);
4688 __ ucomisd(result_reg, xmm_scratch);
4689 __ j(not_zero, &done, Label::kNear);
4690 __ movmskpd(temp_reg, result_reg);
4691 __ test_b(temp_reg, 1);
4692 DeoptimizeIf(not_zero, env); 4668 DeoptimizeIf(not_zero, env);
4693 } 4669 }
4694 __ jmp(&done, Label::kNear); 4670 __ jmp(&done, Label::kNear);
4695
4696 if (can_convert_undefined_to_nan) {
4697 __ bind(&convert);
4698
4699 // Convert undefined (and hole) to NaN.
4700 __ cmp(input_reg, factory()->undefined_value());
4701 DeoptimizeIf(not_equal, env);
4702
4703 ExternalReference nan =
4704 ExternalReference::address_of_canonical_non_hole_nan();
4705 __ movsd(result_reg, Operand::StaticVariable(nan));
4706 __ jmp(&done, Label::kNear);
4707 }
4708 } else { 4671 } else {
4709 ASSERT(mode == NUMBER_CANDIDATE_IS_SMI); 4672 ASSERT(mode == NUMBER_CANDIDATE_IS_SMI);
4710 } 4673 }
4711 4674
4712 __ bind(&load_smi); 4675 __ bind(&load_smi);
4713 // Smi to XMM conversion. Clobbering a temp is faster than re-tagging the 4676 // Clobbering a temp is faster than re-tagging the
4714 // input register since we avoid dependencies. 4677 // input register since we avoid dependencies.
4715 __ mov(temp_reg, input_reg); 4678 __ mov(temp_reg, input_reg);
4716 __ SmiUntag(temp_reg); // Untag smi before converting to float. 4679 __ SmiUntag(temp_reg); // Untag smi before converting to float.
4717 __ Cvtsi2sd(result_reg, Operand(temp_reg)); 4680 __ push(temp_reg);
4681 __ fild_s(Operand(esp, 0));
4682 __ add(esp, Immediate(kPointerSize));
4718 __ bind(&done); 4683 __ bind(&done);
4684 X87CommitWrite(res_reg);
4719 } 4685 }
4720 4686
4721 4687
4722 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr, Label* done) { 4688 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr, Label* done) {
4723 Register input_reg = ToRegister(instr->value()); 4689 Register input_reg = ToRegister(instr->value());
4724 4690
4725 // The input was optimistically untagged; revert it. 4691 // The input was optimistically untagged; revert it.
4726 STATIC_ASSERT(kSmiTagSize == 1); 4692 STATIC_ASSERT(kSmiTagSize == 1);
4727 __ lea(input_reg, Operand(input_reg, times_2, kHeapObjectTag)); 4693 __ lea(input_reg, Operand(input_reg, times_2, kHeapObjectTag));
4728 4694
(...skipping 21 matching lines...) Expand all
4750 __ Move(input_reg, Immediate(1)); 4716 __ Move(input_reg, Immediate(1));
4751 __ jmp(done); 4717 __ jmp(done);
4752 4718
4753 __ bind(&check_false); 4719 __ bind(&check_false);
4754 __ cmp(input_reg, factory()->false_value()); 4720 __ cmp(input_reg, factory()->false_value());
4755 __ RecordComment("Deferred TaggedToI: cannot truncate"); 4721 __ RecordComment("Deferred TaggedToI: cannot truncate");
4756 DeoptimizeIf(not_equal, instr->environment()); 4722 DeoptimizeIf(not_equal, instr->environment());
4757 __ Move(input_reg, Immediate(0)); 4723 __ Move(input_reg, Immediate(0));
4758 } else { 4724 } else {
4759 Label bailout; 4725 Label bailout;
4760 XMMRegister scratch = (instr->temp() != NULL) 4726 __ TaggedToI(input_reg, input_reg,
4761 ? ToDoubleRegister(instr->temp())
4762 : no_xmm_reg;
4763 __ TaggedToI(input_reg, input_reg, scratch,
4764 instr->hydrogen()->GetMinusZeroMode(), &bailout); 4727 instr->hydrogen()->GetMinusZeroMode(), &bailout);
4765 __ jmp(done); 4728 __ jmp(done);
4766 __ bind(&bailout); 4729 __ bind(&bailout);
4767 DeoptimizeIf(no_condition, instr->environment()); 4730 DeoptimizeIf(no_condition, instr->environment());
4768 } 4731 }
4769 } 4732 }
4770 4733
4771 4734
4772 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { 4735 void LCodeGen::DoTaggedToI(LTaggedToI* instr) {
4773 class DeferredTaggedToI V8_FINAL : public LDeferredCode { 4736 class DeferredTaggedToI V8_FINAL : public LDeferredCode {
4774 public: 4737 public:
4775 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) 4738 DeferredTaggedToI(LCodeGen* codegen,
4776 : LDeferredCode(codegen), instr_(instr) { } 4739 LTaggedToI* instr,
4740 const X87Stack& x87_stack)
4741 : LDeferredCode(codegen, x87_stack), instr_(instr) { }
4777 virtual void Generate() V8_OVERRIDE { 4742 virtual void Generate() V8_OVERRIDE {
4778 codegen()->DoDeferredTaggedToI(instr_, done()); 4743 codegen()->DoDeferredTaggedToI(instr_, done());
4779 } 4744 }
4780 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } 4745 virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
4781 private: 4746 private:
4782 LTaggedToI* instr_; 4747 LTaggedToI* instr_;
4783 }; 4748 };
4784 4749
4785 LOperand* input = instr->value(); 4750 LOperand* input = instr->value();
4786 ASSERT(input->IsRegister()); 4751 ASSERT(input->IsRegister());
4787 Register input_reg = ToRegister(input); 4752 Register input_reg = ToRegister(input);
4788 ASSERT(input_reg.is(ToRegister(instr->result()))); 4753 ASSERT(input_reg.is(ToRegister(instr->result())));
4789 4754
4790 if (instr->hydrogen()->value()->representation().IsSmi()) { 4755 if (instr->hydrogen()->value()->representation().IsSmi()) {
4791 __ SmiUntag(input_reg); 4756 __ SmiUntag(input_reg);
4792 } else { 4757 } else {
4793 DeferredTaggedToI* deferred = 4758 DeferredTaggedToI* deferred =
4794 new(zone()) DeferredTaggedToI(this, instr); 4759 new(zone()) DeferredTaggedToI(this, instr, x87_stack_);
4795 // Optimistically untag the input. 4760 // Optimistically untag the input.
4796 // If the input is a HeapObject, SmiUntag will set the carry flag. 4761 // If the input is a HeapObject, SmiUntag will set the carry flag.
4797 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0); 4762 STATIC_ASSERT(kSmiTagSize == 1 && kSmiTag == 0);
4798 __ SmiUntag(input_reg); 4763 __ SmiUntag(input_reg);
4799 // Branch to deferred code if the input was tagged. 4764 // Branch to deferred code if the input was tagged.
4800 // The deferred code will take care of restoring the tag. 4765 // The deferred code will take care of restoring the tag.
4801 __ j(carry, deferred->entry()); 4766 __ j(carry, deferred->entry());
4802 __ bind(deferred->exit()); 4767 __ bind(deferred->exit());
4803 } 4768 }
4804 } 4769 }
4805 4770
4806 4771
4807 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { 4772 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) {
4808 LOperand* input = instr->value(); 4773 LOperand* input = instr->value();
4809 ASSERT(input->IsRegister()); 4774 ASSERT(input->IsRegister());
4810 LOperand* temp = instr->temp(); 4775 LOperand* temp = instr->temp();
4811 ASSERT(temp->IsRegister()); 4776 ASSERT(temp->IsRegister());
4812 LOperand* result = instr->result(); 4777 LOperand* result = instr->result();
4813 ASSERT(result->IsDoubleRegister()); 4778 ASSERT(result->IsDoubleRegister());
4814 4779
4815 Register input_reg = ToRegister(input); 4780 Register input_reg = ToRegister(input);
4816 bool deoptimize_on_minus_zero = 4781 bool deoptimize_on_minus_zero =
4817 instr->hydrogen()->deoptimize_on_minus_zero(); 4782 instr->hydrogen()->deoptimize_on_minus_zero();
4818 Register temp_reg = ToRegister(temp); 4783 Register temp_reg = ToRegister(temp);
4819 4784
4820 HValue* value = instr->hydrogen()->value(); 4785 HValue* value = instr->hydrogen()->value();
4821 NumberUntagDMode mode = value->representation().IsSmi() 4786 NumberUntagDMode mode = value->representation().IsSmi()
4822 ? NUMBER_CANDIDATE_IS_SMI : NUMBER_CANDIDATE_IS_ANY_TAGGED; 4787 ? NUMBER_CANDIDATE_IS_SMI : NUMBER_CANDIDATE_IS_ANY_TAGGED;
4823 4788
4824 XMMRegister result_reg = ToDoubleRegister(result); 4789 EmitNumberUntagDNoSSE2(input_reg,
4825 EmitNumberUntagD(input_reg, 4790 temp_reg,
4826 temp_reg, 4791 ToX87Register(result),
4827 result_reg, 4792 instr->hydrogen()->can_convert_undefined_to_nan(),
4828 instr->hydrogen()->can_convert_undefined_to_nan(), 4793 deoptimize_on_minus_zero,
4829 deoptimize_on_minus_zero, 4794 instr->environment(),
4830 instr->environment(), 4795 mode);
4831 mode);
4832 } 4796 }
4833 4797
4834 4798
4835 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { 4799 void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
4836 LOperand* input = instr->value(); 4800 LOperand* input = instr->value();
4837 ASSERT(input->IsDoubleRegister()); 4801 ASSERT(input->IsDoubleRegister());
4838 LOperand* result = instr->result(); 4802 LOperand* result = instr->result();
4839 ASSERT(result->IsRegister()); 4803 ASSERT(result->IsRegister());
4840 Register result_reg = ToRegister(result); 4804 Register result_reg = ToRegister(result);
4841 4805
4842 if (instr->truncating()) { 4806 if (instr->truncating()) {
4843 XMMRegister input_reg = ToDoubleRegister(input); 4807 X87Register input_reg = ToX87Register(input);
4844 __ TruncateDoubleToI(result_reg, input_reg); 4808 X87Fxch(input_reg);
4809 __ TruncateX87TOSToI(result_reg);
4845 } else { 4810 } else {
4846 Label bailout, done; 4811 Label bailout, done;
4847 XMMRegister input_reg = ToDoubleRegister(input); 4812 X87Register input_reg = ToX87Register(input);
4848 XMMRegister xmm_scratch = double_scratch0(); 4813 X87Fxch(input_reg);
4849 __ DoubleToI(result_reg, input_reg, xmm_scratch, 4814 __ X87TOSToI(result_reg, instr->hydrogen()->GetMinusZeroMode(),
4850 instr->hydrogen()->GetMinusZeroMode(), &bailout, Label::kNear); 4815 &bailout, Label::kNear);
4851 __ jmp(&done, Label::kNear); 4816 __ jmp(&done, Label::kNear);
4852 __ bind(&bailout); 4817 __ bind(&bailout);
4853 DeoptimizeIf(no_condition, instr->environment()); 4818 DeoptimizeIf(no_condition, instr->environment());
4854 __ bind(&done); 4819 __ bind(&done);
4855 } 4820 }
4856 } 4821 }
4857 4822
4858 4823
4859 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) { 4824 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) {
4860 LOperand* input = instr->value(); 4825 LOperand* input = instr->value();
4861 ASSERT(input->IsDoubleRegister()); 4826 ASSERT(input->IsDoubleRegister());
4862 LOperand* result = instr->result(); 4827 LOperand* result = instr->result();
4863 ASSERT(result->IsRegister()); 4828 ASSERT(result->IsRegister());
4864 Register result_reg = ToRegister(result); 4829 Register result_reg = ToRegister(result);
4865 4830
4866 Label bailout, done; 4831 Label bailout, done;
4867 XMMRegister input_reg = ToDoubleRegister(input); 4832 X87Register input_reg = ToX87Register(input);
4868 XMMRegister xmm_scratch = double_scratch0(); 4833 X87Fxch(input_reg);
4869 __ DoubleToI(result_reg, input_reg, xmm_scratch, 4834 __ X87TOSToI(result_reg, instr->hydrogen()->GetMinusZeroMode(),
4870 instr->hydrogen()->GetMinusZeroMode(), &bailout, Label::kNear); 4835 &bailout, Label::kNear);
4871 __ jmp(&done, Label::kNear); 4836 __ jmp(&done, Label::kNear);
4872 __ bind(&bailout); 4837 __ bind(&bailout);
4873 DeoptimizeIf(no_condition, instr->environment()); 4838 DeoptimizeIf(no_condition, instr->environment());
4874 __ bind(&done); 4839 __ bind(&done);
4875 4840
4876 __ SmiTag(result_reg); 4841 __ SmiTag(result_reg);
4877 DeoptimizeIf(overflow, instr->environment()); 4842 DeoptimizeIf(overflow, instr->environment());
4878 } 4843 }
4879 4844
4880 4845
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
4951 } 4916 }
4952 DeoptimizeIf(not_equal, instr->environment()); 4917 DeoptimizeIf(not_equal, instr->environment());
4953 } 4918 }
4954 4919
4955 4920
4956 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) { 4921 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) {
4957 { 4922 {
4958 PushSafepointRegistersScope scope(this); 4923 PushSafepointRegistersScope scope(this);
4959 __ push(object); 4924 __ push(object);
4960 __ xor_(esi, esi); 4925 __ xor_(esi, esi);
4961 __ CallRuntimeSaveDoubles(Runtime::kTryMigrateInstance); 4926 __ CallRuntime(Runtime::kTryMigrateInstance);
4962 RecordSafepointWithRegisters( 4927 RecordSafepointWithRegisters(
4963 instr->pointer_map(), 1, Safepoint::kNoLazyDeopt); 4928 instr->pointer_map(), 1, Safepoint::kNoLazyDeopt);
4964 4929
4965 __ test(eax, Immediate(kSmiTagMask)); 4930 __ test(eax, Immediate(kSmiTagMask));
4966 } 4931 }
4967 DeoptimizeIf(zero, instr->environment()); 4932 DeoptimizeIf(zero, instr->environment());
4968 } 4933 }
4969 4934
4970 4935
4971 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { 4936 void LCodeGen::DoCheckMaps(LCheckMaps* instr) {
4972 class DeferredCheckMaps V8_FINAL : public LDeferredCode { 4937 class DeferredCheckMaps V8_FINAL : public LDeferredCode {
4973 public: 4938 public:
4974 DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr, Register object) 4939 DeferredCheckMaps(LCodeGen* codegen,
4975 : LDeferredCode(codegen), instr_(instr), object_(object) { 4940 LCheckMaps* instr,
4941 Register object,
4942 const X87Stack& x87_stack)
4943 : LDeferredCode(codegen, x87_stack), instr_(instr), object_(object) {
4976 SetExit(check_maps()); 4944 SetExit(check_maps());
4977 } 4945 }
4978 virtual void Generate() V8_OVERRIDE { 4946 virtual void Generate() V8_OVERRIDE {
4979 codegen()->DoDeferredInstanceMigration(instr_, object_); 4947 codegen()->DoDeferredInstanceMigration(instr_, object_);
4980 } 4948 }
4981 Label* check_maps() { return &check_maps_; } 4949 Label* check_maps() { return &check_maps_; }
4982 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } 4950 virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
4983 private: 4951 private:
4984 LCheckMaps* instr_; 4952 LCheckMaps* instr_;
4985 Label check_maps_; 4953 Label check_maps_;
4986 Register object_; 4954 Register object_;
4987 }; 4955 };
4988 4956
4989 if (instr->hydrogen()->IsStabilityCheck()) { 4957 if (instr->hydrogen()->IsStabilityCheck()) {
4990 const UniqueSet<Map>* maps = instr->hydrogen()->maps(); 4958 const UniqueSet<Map>* maps = instr->hydrogen()->maps();
4991 for (int i = 0; i < maps->size(); ++i) { 4959 for (int i = 0; i < maps->size(); ++i) {
4992 AddStabilityDependency(maps->at(i).handle()); 4960 AddStabilityDependency(maps->at(i).handle());
4993 } 4961 }
4994 return; 4962 return;
4995 } 4963 }
4996 4964
4997 LOperand* input = instr->value(); 4965 LOperand* input = instr->value();
4998 ASSERT(input->IsRegister()); 4966 ASSERT(input->IsRegister());
4999 Register reg = ToRegister(input); 4967 Register reg = ToRegister(input);
5000 4968
5001 DeferredCheckMaps* deferred = NULL; 4969 DeferredCheckMaps* deferred = NULL;
5002 if (instr->hydrogen()->HasMigrationTarget()) { 4970 if (instr->hydrogen()->HasMigrationTarget()) {
5003 deferred = new(zone()) DeferredCheckMaps(this, instr, reg); 4971 deferred = new(zone()) DeferredCheckMaps(this, instr, reg, x87_stack_);
5004 __ bind(deferred->check_maps()); 4972 __ bind(deferred->check_maps());
5005 } 4973 }
5006 4974
5007 const UniqueSet<Map>* maps = instr->hydrogen()->maps(); 4975 const UniqueSet<Map>* maps = instr->hydrogen()->maps();
5008 Label success; 4976 Label success;
5009 for (int i = 0; i < maps->size() - 1; i++) { 4977 for (int i = 0; i < maps->size() - 1; i++) {
5010 Handle<Map> map = maps->at(i).handle(); 4978 Handle<Map> map = maps->at(i).handle();
5011 __ CompareMap(reg, map); 4979 __ CompareMap(reg, map);
5012 __ j(equal, &success, Label::kNear); 4980 __ j(equal, &success, Label::kNear);
5013 } 4981 }
5014 4982
5015 Handle<Map> map = maps->at(maps->size() - 1).handle(); 4983 Handle<Map> map = maps->at(maps->size() - 1).handle();
5016 __ CompareMap(reg, map); 4984 __ CompareMap(reg, map);
5017 if (instr->hydrogen()->HasMigrationTarget()) { 4985 if (instr->hydrogen()->HasMigrationTarget()) {
5018 __ j(not_equal, deferred->entry()); 4986 __ j(not_equal, deferred->entry());
5019 } else { 4987 } else {
5020 DeoptimizeIf(not_equal, instr->environment()); 4988 DeoptimizeIf(not_equal, instr->environment());
5021 } 4989 }
5022 4990
5023 __ bind(&success); 4991 __ bind(&success);
5024 } 4992 }
5025 4993
5026 4994
5027 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { 4995 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) {
5028 XMMRegister value_reg = ToDoubleRegister(instr->unclamped()); 4996 UNREACHABLE();
5029 XMMRegister xmm_scratch = double_scratch0();
5030 Register result_reg = ToRegister(instr->result());
5031 __ ClampDoubleToUint8(value_reg, xmm_scratch, result_reg);
5032 } 4997 }
5033 4998
5034 4999
5035 void LCodeGen::DoClampIToUint8(LClampIToUint8* instr) { 5000 void LCodeGen::DoClampIToUint8(LClampIToUint8* instr) {
5036 ASSERT(instr->unclamped()->Equals(instr->result())); 5001 ASSERT(instr->unclamped()->Equals(instr->result()));
5037 Register value_reg = ToRegister(instr->result()); 5002 Register value_reg = ToRegister(instr->result());
5038 __ ClampUint8(value_reg); 5003 __ ClampUint8(value_reg);
5039 } 5004 }
5040 5005
5041 5006
5042 void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) { 5007 void LCodeGen::DoClampTToUint8NoSSE2(LClampTToUint8NoSSE2* instr) {
5043 ASSERT(instr->unclamped()->Equals(instr->result()));
5044 Register input_reg = ToRegister(instr->unclamped()); 5008 Register input_reg = ToRegister(instr->unclamped());
5045 XMMRegister temp_xmm_reg = ToDoubleRegister(instr->temp_xmm()); 5009 Register result_reg = ToRegister(instr->result());
5046 XMMRegister xmm_scratch = double_scratch0(); 5010 Register scratch = ToRegister(instr->scratch());
5047 Label is_smi, done, heap_number; 5011 Register scratch2 = ToRegister(instr->scratch2());
5012 Register scratch3 = ToRegister(instr->scratch3());
5013 Label is_smi, done, heap_number, valid_exponent,
5014 largest_value, zero_result, maybe_nan_or_infinity;
5048 5015
5049 __ JumpIfSmi(input_reg, &is_smi); 5016 __ JumpIfSmi(input_reg, &is_smi);
5050 5017
5051 // Check for heap number 5018 // Check for heap number
5052 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), 5019 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
5053 factory()->heap_number_map()); 5020 factory()->heap_number_map());
5054 __ j(equal, &heap_number, Label::kNear); 5021 __ j(equal, &heap_number, Label::kNear);
5055 5022
5056 // Check for undefined. Undefined is converted to zero for clamping 5023 // Check for undefined. Undefined is converted to zero for clamping
5057 // conversions. 5024 // conversions.
5058 __ cmp(input_reg, factory()->undefined_value()); 5025 __ cmp(input_reg, factory()->undefined_value());
5059 DeoptimizeIf(not_equal, instr->environment()); 5026 DeoptimizeIf(not_equal, instr->environment());
5060 __ mov(input_reg, 0); 5027 __ jmp(&zero_result, Label::kNear);
5061 __ jmp(&done, Label::kNear);
5062 5028
5063 // Heap number 5029 // Heap number
5064 __ bind(&heap_number); 5030 __ bind(&heap_number);
5065 __ movsd(xmm_scratch, FieldOperand(input_reg, HeapNumber::kValueOffset)); 5031
5066 __ ClampDoubleToUint8(xmm_scratch, temp_xmm_reg, input_reg); 5032 // Surprisingly, all of the hand-crafted bit-manipulations below are much
5033 // faster than the x86 FPU built-in instruction, especially since "banker's
5034 // rounding" would be additionally very expensive
5035
5036 // Get exponent word.
5037 __ mov(scratch, FieldOperand(input_reg, HeapNumber::kExponentOffset));
5038 __ mov(scratch3, FieldOperand(input_reg, HeapNumber::kMantissaOffset));
5039
5040 // Test for negative values --> clamp to zero
5041 __ test(scratch, scratch);
5042 __ j(negative, &zero_result, Label::kNear);
5043
5044 // Get exponent alone in scratch2.
5045 __ mov(scratch2, scratch);
5046 __ and_(scratch2, HeapNumber::kExponentMask);
5047 __ shr(scratch2, HeapNumber::kExponentShift);
5048 __ j(zero, &zero_result, Label::kNear);
5049 __ sub(scratch2, Immediate(HeapNumber::kExponentBias - 1));
5050 __ j(negative, &zero_result, Label::kNear);
5051
5052 const uint32_t non_int8_exponent = 7;
5053 __ cmp(scratch2, Immediate(non_int8_exponent + 1));
5054 // If the exponent is too big, check for special values.
5055 __ j(greater, &maybe_nan_or_infinity, Label::kNear);
5056
5057 __ bind(&valid_exponent);
5058 // Exponent word in scratch, exponent in scratch2. We know that 0 <= exponent
5059 // < 7. The shift bias is the number of bits to shift the mantissa such that
5060 // with an exponent of 7 such the that top-most one is in bit 30, allowing
5061 // detection the rounding overflow of a 255.5 to 256 (bit 31 goes from 0 to
5062 // 1).
5063 int shift_bias = (30 - HeapNumber::kExponentShift) - 7 - 1;
5064 __ lea(result_reg, MemOperand(scratch2, shift_bias));
5065 // Here result_reg (ecx) is the shift, scratch is the exponent word. Get the
5066 // top bits of the mantissa.
5067 __ and_(scratch, HeapNumber::kMantissaMask);
5068 // Put back the implicit 1 of the mantissa
5069 __ or_(scratch, 1 << HeapNumber::kExponentShift);
5070 // Shift up to round
5071 __ shl_cl(scratch);
5072 // Use "banker's rounding" to spec: If fractional part of number is 0.5, then
5073 // use the bit in the "ones" place and add it to the "halves" place, which has
5074 // the effect of rounding to even.
5075 __ mov(scratch2, scratch);
5076 const uint32_t one_half_bit_shift = 30 - sizeof(uint8_t) * 8;
5077 const uint32_t one_bit_shift = one_half_bit_shift + 1;
5078 __ and_(scratch2, Immediate((1 << one_bit_shift) - 1));
5079 __ cmp(scratch2, Immediate(1 << one_half_bit_shift));
5080 Label no_round;
5081 __ j(less, &no_round, Label::kNear);
5082 Label round_up;
5083 __ mov(scratch2, Immediate(1 << one_half_bit_shift));
5084 __ j(greater, &round_up, Label::kNear);
5085 __ test(scratch3, scratch3);
5086 __ j(not_zero, &round_up, Label::kNear);
5087 __ mov(scratch2, scratch);
5088 __ and_(scratch2, Immediate(1 << one_bit_shift));
5089 __ shr(scratch2, 1);
5090 __ bind(&round_up);
5091 __ add(scratch, scratch2);
5092 __ j(overflow, &largest_value, Label::kNear);
5093 __ bind(&no_round);
5094 __ shr(scratch, 23);
5095 __ mov(result_reg, scratch);
5096 __ jmp(&done, Label::kNear);
5097
5098 __ bind(&maybe_nan_or_infinity);
5099 // Check for NaN/Infinity, all other values map to 255
5100 __ cmp(scratch2, Immediate(HeapNumber::kInfinityOrNanExponent + 1));
5101 __ j(not_equal, &largest_value, Label::kNear);
5102
5103 // Check for NaN, which differs from Infinity in that at least one mantissa
5104 // bit is set.
5105 __ and_(scratch, HeapNumber::kMantissaMask);
5106 __ or_(scratch, FieldOperand(input_reg, HeapNumber::kMantissaOffset));
5107 __ j(not_zero, &zero_result, Label::kNear); // M!=0 --> NaN
5108 // Infinity -> Fall through to map to 255.
5109
5110 __ bind(&largest_value);
5111 __ mov(result_reg, Immediate(255));
5112 __ jmp(&done, Label::kNear);
5113
5114 __ bind(&zero_result);
5115 __ xor_(result_reg, result_reg);
5067 __ jmp(&done, Label::kNear); 5116 __ jmp(&done, Label::kNear);
5068 5117
5069 // smi 5118 // smi
5070 __ bind(&is_smi); 5119 __ bind(&is_smi);
5071 __ SmiUntag(input_reg); 5120 if (!input_reg.is(result_reg)) {
5072 __ ClampUint8(input_reg); 5121 __ mov(result_reg, input_reg);
5122 }
5123 __ SmiUntag(result_reg);
5124 __ ClampUint8(result_reg);
5073 __ bind(&done); 5125 __ bind(&done);
5074 } 5126 }
5075 5127
5076 5128
5077 void LCodeGen::DoDoubleBits(LDoubleBits* instr) { 5129 void LCodeGen::DoDoubleBits(LDoubleBits* instr) {
5078 XMMRegister value_reg = ToDoubleRegister(instr->value()); 5130 UNREACHABLE();
5079 Register result_reg = ToRegister(instr->result());
5080 if (instr->hydrogen()->bits() == HDoubleBits::HIGH) {
5081 if (CpuFeatures::IsSupported(SSE4_1)) {
5082 CpuFeatureScope scope2(masm(), SSE4_1);
5083 __ pextrd(result_reg, value_reg, 1);
5084 } else {
5085 XMMRegister xmm_scratch = double_scratch0();
5086 __ pshufd(xmm_scratch, value_reg, 1);
5087 __ movd(result_reg, xmm_scratch);
5088 }
5089 } else {
5090 __ movd(result_reg, value_reg);
5091 }
5092 } 5131 }
5093 5132
5094 5133
5095 void LCodeGen::DoConstructDouble(LConstructDouble* instr) { 5134 void LCodeGen::DoConstructDouble(LConstructDouble* instr) {
5096 Register hi_reg = ToRegister(instr->hi()); 5135 UNREACHABLE();
5097 Register lo_reg = ToRegister(instr->lo());
5098 XMMRegister result_reg = ToDoubleRegister(instr->result());
5099
5100 if (CpuFeatures::IsSupported(SSE4_1)) {
5101 CpuFeatureScope scope2(masm(), SSE4_1);
5102 __ movd(result_reg, lo_reg);
5103 __ pinsrd(result_reg, hi_reg, 1);
5104 } else {
5105 XMMRegister xmm_scratch = double_scratch0();
5106 __ movd(result_reg, hi_reg);
5107 __ psllq(result_reg, 32);
5108 __ movd(xmm_scratch, lo_reg);
5109 __ orps(result_reg, xmm_scratch);
5110 }
5111 } 5136 }
5112 5137
5113 5138
5114 void LCodeGen::DoAllocate(LAllocate* instr) { 5139 void LCodeGen::DoAllocate(LAllocate* instr) {
5115 class DeferredAllocate V8_FINAL : public LDeferredCode { 5140 class DeferredAllocate V8_FINAL : public LDeferredCode {
5116 public: 5141 public:
5117 DeferredAllocate(LCodeGen* codegen, LAllocate* instr) 5142 DeferredAllocate(LCodeGen* codegen,
5118 : LDeferredCode(codegen), instr_(instr) { } 5143 LAllocate* instr,
5144 const X87Stack& x87_stack)
5145 : LDeferredCode(codegen, x87_stack), instr_(instr) { }
5119 virtual void Generate() V8_OVERRIDE { 5146 virtual void Generate() V8_OVERRIDE {
5120 codegen()->DoDeferredAllocate(instr_); 5147 codegen()->DoDeferredAllocate(instr_);
5121 } 5148 }
5122 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } 5149 virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
5123 private: 5150 private:
5124 LAllocate* instr_; 5151 LAllocate* instr_;
5125 }; 5152 };
5126 5153
5127 DeferredAllocate* deferred = new(zone()) DeferredAllocate(this, instr); 5154 DeferredAllocate* deferred =
5155 new(zone()) DeferredAllocate(this, instr, x87_stack_);
5128 5156
5129 Register result = ToRegister(instr->result()); 5157 Register result = ToRegister(instr->result());
5130 Register temp = ToRegister(instr->temp()); 5158 Register temp = ToRegister(instr->temp());
5131 5159
5132 // Allocate memory for the object. 5160 // Allocate memory for the object.
5133 AllocationFlags flags = TAG_OBJECT; 5161 AllocationFlags flags = TAG_OBJECT;
5134 if (instr->hydrogen()->MustAllocateDoubleAligned()) { 5162 if (instr->hydrogen()->MustAllocateDoubleAligned()) {
5135 flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT); 5163 flags = static_cast<AllocationFlags>(flags | DOUBLE_ALIGNMENT);
5136 } 5164 }
5137 if (instr->hydrogen()->IsOldPointerSpaceAllocation()) { 5165 if (instr->hydrogen()->IsOldPointerSpaceAllocation()) {
(...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after
5470 5498
5471 5499
5472 void LCodeGen::DoDummyUse(LDummyUse* instr) { 5500 void LCodeGen::DoDummyUse(LDummyUse* instr) {
5473 // Nothing to see here, move on! 5501 // Nothing to see here, move on!
5474 } 5502 }
5475 5503
5476 5504
5477 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) { 5505 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) {
5478 PushSafepointRegistersScope scope(this); 5506 PushSafepointRegistersScope scope(this);
5479 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 5507 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
5480 __ CallRuntimeSaveDoubles(Runtime::kHiddenStackGuard); 5508 __ CallRuntime(Runtime::kHiddenStackGuard);
5481 RecordSafepointWithLazyDeopt( 5509 RecordSafepointWithLazyDeopt(
5482 instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); 5510 instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
5483 ASSERT(instr->HasEnvironment()); 5511 ASSERT(instr->HasEnvironment());
5484 LEnvironment* env = instr->environment(); 5512 LEnvironment* env = instr->environment();
5485 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); 5513 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
5486 } 5514 }
5487 5515
5488 5516
5489 void LCodeGen::DoStackCheck(LStackCheck* instr) { 5517 void LCodeGen::DoStackCheck(LStackCheck* instr) {
5490 class DeferredStackCheck V8_FINAL : public LDeferredCode { 5518 class DeferredStackCheck V8_FINAL : public LDeferredCode {
5491 public: 5519 public:
5492 DeferredStackCheck(LCodeGen* codegen, LStackCheck* instr) 5520 DeferredStackCheck(LCodeGen* codegen,
5493 : LDeferredCode(codegen), instr_(instr) { } 5521 LStackCheck* instr,
5522 const X87Stack& x87_stack)
5523 : LDeferredCode(codegen, x87_stack), instr_(instr) { }
5494 virtual void Generate() V8_OVERRIDE { 5524 virtual void Generate() V8_OVERRIDE {
5495 codegen()->DoDeferredStackCheck(instr_); 5525 codegen()->DoDeferredStackCheck(instr_);
5496 } 5526 }
5497 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } 5527 virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
5498 private: 5528 private:
5499 LStackCheck* instr_; 5529 LStackCheck* instr_;
5500 }; 5530 };
5501 5531
5502 ASSERT(instr->HasEnvironment()); 5532 ASSERT(instr->HasEnvironment());
5503 LEnvironment* env = instr->environment(); 5533 LEnvironment* env = instr->environment();
(...skipping 10 matching lines...) Expand all
5514 ASSERT(instr->context()->IsRegister()); 5544 ASSERT(instr->context()->IsRegister());
5515 ASSERT(ToRegister(instr->context()).is(esi)); 5545 ASSERT(ToRegister(instr->context()).is(esi));
5516 CallCode(isolate()->builtins()->StackCheck(), 5546 CallCode(isolate()->builtins()->StackCheck(),
5517 RelocInfo::CODE_TARGET, 5547 RelocInfo::CODE_TARGET,
5518 instr); 5548 instr);
5519 __ bind(&done); 5549 __ bind(&done);
5520 } else { 5550 } else {
5521 ASSERT(instr->hydrogen()->is_backwards_branch()); 5551 ASSERT(instr->hydrogen()->is_backwards_branch());
5522 // Perform stack overflow check if this goto needs it before jumping. 5552 // Perform stack overflow check if this goto needs it before jumping.
5523 DeferredStackCheck* deferred_stack_check = 5553 DeferredStackCheck* deferred_stack_check =
5524 new(zone()) DeferredStackCheck(this, instr); 5554 new(zone()) DeferredStackCheck(this, instr, x87_stack_);
5525 ExternalReference stack_limit = 5555 ExternalReference stack_limit =
5526 ExternalReference::address_of_stack_limit(isolate()); 5556 ExternalReference::address_of_stack_limit(isolate());
5527 __ cmp(esp, Operand::StaticVariable(stack_limit)); 5557 __ cmp(esp, Operand::StaticVariable(stack_limit));
5528 __ j(below, deferred_stack_check->entry()); 5558 __ j(below, deferred_stack_check->entry());
5529 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); 5559 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size());
5530 __ bind(instr->done_label()); 5560 __ bind(instr->done_label());
5531 deferred_stack_check->SetExit(instr->done_label()); 5561 deferred_stack_check->SetExit(instr->done_label());
5532 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); 5562 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt);
5533 // Don't record a deoptimization index for the safepoint here. 5563 // Don't record a deoptimization index for the safepoint here.
5534 // This will be done explicitly when emitting call and the safepoint in 5564 // This will be done explicitly when emitting call and the safepoint in
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
5615 } 5645 }
5616 5646
5617 5647
5618 void LCodeGen::DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr, 5648 void LCodeGen::DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr,
5619 Register object, 5649 Register object,
5620 Register index) { 5650 Register index) {
5621 PushSafepointRegistersScope scope(this); 5651 PushSafepointRegistersScope scope(this);
5622 __ push(object); 5652 __ push(object);
5623 __ push(index); 5653 __ push(index);
5624 __ xor_(esi, esi); 5654 __ xor_(esi, esi);
5625 __ CallRuntimeSaveDoubles(Runtime::kLoadMutableDouble); 5655 __ CallRuntime(Runtime::kLoadMutableDouble);
5626 RecordSafepointWithRegisters( 5656 RecordSafepointWithRegisters(
5627 instr->pointer_map(), 2, Safepoint::kNoLazyDeopt); 5657 instr->pointer_map(), 2, Safepoint::kNoLazyDeopt);
5628 __ StoreToSafepointRegisterSlot(object, eax); 5658 __ StoreToSafepointRegisterSlot(object, eax);
5629 } 5659 }
5630 5660
5631 5661
5632 void LCodeGen::DoLoadFieldByIndex(LLoadFieldByIndex* instr) { 5662 void LCodeGen::DoLoadFieldByIndex(LLoadFieldByIndex* instr) {
5633 class DeferredLoadMutableDouble V8_FINAL : public LDeferredCode { 5663 class DeferredLoadMutableDouble V8_FINAL : public LDeferredCode {
5634 public: 5664 public:
5635 DeferredLoadMutableDouble(LCodeGen* codegen, 5665 DeferredLoadMutableDouble(LCodeGen* codegen,
5636 LLoadFieldByIndex* instr, 5666 LLoadFieldByIndex* instr,
5637 Register object, 5667 Register object,
5638 Register index) 5668 Register index,
5639 : LDeferredCode(codegen), 5669 const X87Stack& x87_stack)
5670 : LDeferredCode(codegen, x87_stack),
5640 instr_(instr), 5671 instr_(instr),
5641 object_(object), 5672 object_(object),
5642 index_(index) { 5673 index_(index) {
5643 } 5674 }
5644 virtual void Generate() V8_OVERRIDE { 5675 virtual void Generate() V8_OVERRIDE {
5645 codegen()->DoDeferredLoadMutableDouble(instr_, object_, index_); 5676 codegen()->DoDeferredLoadMutableDouble(instr_, object_, index_);
5646 } 5677 }
5647 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } 5678 virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
5648 private: 5679 private:
5649 LLoadFieldByIndex* instr_; 5680 LLoadFieldByIndex* instr_;
5650 Register object_; 5681 Register object_;
5651 Register index_; 5682 Register index_;
5652 }; 5683 };
5653 5684
5654 Register object = ToRegister(instr->object()); 5685 Register object = ToRegister(instr->object());
5655 Register index = ToRegister(instr->index()); 5686 Register index = ToRegister(instr->index());
5656 5687
5657 DeferredLoadMutableDouble* deferred; 5688 DeferredLoadMutableDouble* deferred;
5658 deferred = new(zone()) DeferredLoadMutableDouble( 5689 deferred = new(zone()) DeferredLoadMutableDouble(
5659 this, instr, object, index); 5690 this, instr, object, index, x87_stack_);
5660 5691
5661 Label out_of_object, done; 5692 Label out_of_object, done;
5662 __ test(index, Immediate(Smi::FromInt(1))); 5693 __ test(index, Immediate(Smi::FromInt(1)));
5663 __ j(not_zero, deferred->entry()); 5694 __ j(not_zero, deferred->entry());
5664 5695
5665 __ sar(index, 1); 5696 __ sar(index, 1);
5666 5697
5667 __ cmp(index, Immediate(0)); 5698 __ cmp(index, Immediate(0));
5668 __ j(less, &out_of_object, Label::kNear); 5699 __ j(less, &out_of_object, Label::kNear);
5669 __ mov(object, FieldOperand(object, 5700 __ mov(object, FieldOperand(object,
(...skipping 12 matching lines...) Expand all
5682 FixedArray::kHeaderSize - kPointerSize)); 5713 FixedArray::kHeaderSize - kPointerSize));
5683 __ bind(deferred->exit()); 5714 __ bind(deferred->exit());
5684 __ bind(&done); 5715 __ bind(&done);
5685 } 5716 }
5686 5717
5687 5718
5688 #undef __ 5719 #undef __
5689 5720
5690 } } // namespace v8::internal 5721 } } // namespace v8::internal
5691 5722
5692 #endif // V8_TARGET_ARCH_IA32 5723 #endif // V8_TARGET_ARCH_X87
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698