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

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

Issue 148153010: Synchronize with r15701. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ia32/lithium-codegen-ia32.h ('k') | src/ia32/lithium-gap-resolver-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after
346 current_instruction_, 346 current_instruction_,
347 instr->hydrogen_value()->id(), 347 instr->hydrogen_value()->id(),
348 instr->Mnemonic()); 348 instr->Mnemonic());
349 } 349 }
350 350
351 if (!CpuFeatures::IsSupported(SSE2)) FlushX87StackIfNecessary(instr); 351 if (!CpuFeatures::IsSupported(SSE2)) FlushX87StackIfNecessary(instr);
352 352
353 instr->CompileToNative(this); 353 instr->CompileToNative(this);
354 354
355 if (!CpuFeatures::IsSupported(SSE2)) { 355 if (!CpuFeatures::IsSupported(SSE2)) {
356 ASSERT(!instr->HasDoubleRegisterResult() || x87_stack_depth_ == 1);
357 if (FLAG_debug_code && FLAG_enable_slow_asserts) { 356 if (FLAG_debug_code && FLAG_enable_slow_asserts) {
358 __ VerifyX87StackDepth(x87_stack_depth_); 357 __ VerifyX87StackDepth(x87_stack_depth_);
359 } 358 }
360 } 359 }
361 } 360 }
362 EnsureSpaceForLazyDeopt(); 361 EnsureSpaceForLazyDeopt();
363 return !is_aborted(); 362 return !is_aborted();
364 } 363 }
365 364
366 365
367 bool LCodeGen::GenerateJumpTable() { 366 bool LCodeGen::GenerateJumpTable() {
368 Label needs_frame_not_call; 367 Label needs_frame;
369 Label needs_frame_is_call;
370 if (jump_table_.length() > 0) { 368 if (jump_table_.length() > 0) {
371 Comment(";;; -------------------- Jump table --------------------"); 369 Comment(";;; -------------------- Jump table --------------------");
372 } 370 }
373 for (int i = 0; i < jump_table_.length(); i++) { 371 for (int i = 0; i < jump_table_.length(); i++) {
374 __ bind(&jump_table_[i].label); 372 __ bind(&jump_table_[i].label);
375 Address entry = jump_table_[i].address; 373 Address entry = jump_table_[i].address;
376 Deoptimizer::BailoutType type = jump_table_[i].bailout_type; 374 Deoptimizer::BailoutType type = jump_table_[i].bailout_type;
377 int id = Deoptimizer::GetDeoptimizationId(isolate(), entry, type); 375 int id = Deoptimizer::GetDeoptimizationId(isolate(), entry, type);
378 if (id == Deoptimizer::kNotDeoptimizationEntry) { 376 if (id == Deoptimizer::kNotDeoptimizationEntry) {
379 Comment(";;; jump table entry %d.", i); 377 Comment(";;; jump table entry %d.", i);
380 } else { 378 } else {
381 Comment(";;; jump table entry %d: deoptimization bailout %d.", i, id); 379 Comment(";;; jump table entry %d: deoptimization bailout %d.", i, id);
382 } 380 }
383 if (jump_table_[i].needs_frame) { 381 if (jump_table_[i].needs_frame) {
384 __ push(Immediate(ExternalReference::ForDeoptEntry(entry))); 382 __ push(Immediate(ExternalReference::ForDeoptEntry(entry)));
385 if (type == Deoptimizer::LAZY) { 383 if (needs_frame.is_bound()) {
386 if (needs_frame_is_call.is_bound()) { 384 __ jmp(&needs_frame);
387 __ jmp(&needs_frame_is_call);
388 } else {
389 __ bind(&needs_frame_is_call);
390 __ push(MemOperand(ebp, StandardFrameConstants::kContextOffset));
391 // This variant of deopt can only be used with stubs. Since we don't
392 // have a function pointer to install in the stack frame that we're
393 // building, install a special marker there instead.
394 ASSERT(info()->IsStub());
395 __ push(Immediate(Smi::FromInt(StackFrame::STUB)));
396 // Push a PC inside the function so that the deopt code can find where
397 // the deopt comes from. It doesn't have to be the precise return
398 // address of a "calling" LAZY deopt, it only has to be somewhere
399 // inside the code body.
400 Label push_approx_pc;
401 __ call(&push_approx_pc);
402 __ bind(&push_approx_pc);
403 // Push the continuation which was stashed were the ebp should
404 // be. Replace it with the saved ebp.
405 __ push(MemOperand(esp, 3 * kPointerSize));
406 __ mov(MemOperand(esp, 4 * kPointerSize), ebp);
407 __ lea(ebp, MemOperand(esp, 4 * kPointerSize));
408 __ ret(0); // Call the continuation without clobbering registers.
409 }
410 } else { 385 } else {
411 if (needs_frame_not_call.is_bound()) { 386 __ bind(&needs_frame);
412 __ jmp(&needs_frame_not_call); 387 __ push(MemOperand(ebp, StandardFrameConstants::kContextOffset));
413 } else { 388 // This variant of deopt can only be used with stubs. Since we don't
414 __ bind(&needs_frame_not_call); 389 // have a function pointer to install in the stack frame that we're
415 __ push(MemOperand(ebp, StandardFrameConstants::kContextOffset)); 390 // building, install a special marker there instead.
416 // This variant of deopt can only be used with stubs. Since we don't 391 ASSERT(info()->IsStub());
417 // have a function pointer to install in the stack frame that we're 392 __ push(Immediate(Smi::FromInt(StackFrame::STUB)));
418 // building, install a special marker there instead. 393 // Push a PC inside the function so that the deopt code can find where
419 ASSERT(info()->IsStub()); 394 // the deopt comes from. It doesn't have to be the precise return
420 __ push(Immediate(Smi::FromInt(StackFrame::STUB))); 395 // address of a "calling" LAZY deopt, it only has to be somewhere
421 // Push the continuation which was stashed were the ebp should 396 // inside the code body.
422 // be. Replace it with the saved ebp. 397 Label push_approx_pc;
423 __ push(MemOperand(esp, 2 * kPointerSize)); 398 __ call(&push_approx_pc);
424 __ mov(MemOperand(esp, 3 * kPointerSize), ebp); 399 __ bind(&push_approx_pc);
425 __ lea(ebp, MemOperand(esp, 3 * kPointerSize)); 400 // Push the continuation which was stashed were the ebp should
426 __ ret(0); // Call the continuation without clobbering registers. 401 // be. Replace it with the saved ebp.
427 } 402 __ push(MemOperand(esp, 3 * kPointerSize));
403 __ mov(MemOperand(esp, 4 * kPointerSize), ebp);
404 __ lea(ebp, MemOperand(esp, 4 * kPointerSize));
405 __ ret(0); // Call the continuation without clobbering registers.
428 } 406 }
429 } else { 407 } else {
430 if (type == Deoptimizer::LAZY) { 408 __ call(entry, RelocInfo::RUNTIME_ENTRY);
431 __ call(entry, RelocInfo::RUNTIME_ENTRY);
432 } else {
433 __ jmp(entry, RelocInfo::RUNTIME_ENTRY);
434 }
435 } 409 }
436 } 410 }
437 return !is_aborted(); 411 return !is_aborted();
438 } 412 }
439 413
440 414
441 bool LCodeGen::GenerateDeferredCode() { 415 bool LCodeGen::GenerateDeferredCode() {
442 ASSERT(is_generating()); 416 ASSERT(is_generating());
443 if (deferred_.length() > 0) { 417 if (deferred_.length() > 0) {
444 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) { 418 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) {
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
494 safepoints_.Emit(masm(), GetStackSlotCount()); 468 safepoints_.Emit(masm(), GetStackSlotCount());
495 return !is_aborted(); 469 return !is_aborted();
496 } 470 }
497 471
498 472
499 Register LCodeGen::ToRegister(int index) const { 473 Register LCodeGen::ToRegister(int index) const {
500 return Register::FromAllocationIndex(index); 474 return Register::FromAllocationIndex(index);
501 } 475 }
502 476
503 477
478 X87Register LCodeGen::ToX87Register(int index) const {
479 return X87Register::FromAllocationIndex(index);
480 }
481
482
504 XMMRegister LCodeGen::ToDoubleRegister(int index) const { 483 XMMRegister LCodeGen::ToDoubleRegister(int index) const {
505 return XMMRegister::FromAllocationIndex(index); 484 return XMMRegister::FromAllocationIndex(index);
506 } 485 }
507 486
508 487
509 bool LCodeGen::IsX87TopOfStack(LOperand* op) const { 488 void LCodeGen::X87LoadForUsage(X87Register reg) {
510 return op->IsDoubleRegister(); 489 ASSERT(X87StackContains(reg));
490 X87Fxch(reg);
491 x87_stack_depth_--;
511 } 492 }
512 493
513 494
514 void LCodeGen::ReadX87Operand(Operand dst) { 495 void LCodeGen::X87Fxch(X87Register reg, int other_slot) {
515 ASSERT(x87_stack_depth_ == 1); 496 ASSERT(X87StackContains(reg) && x87_stack_depth_ > other_slot);
516 __ fst_d(dst); 497 int i = X87ArrayIndex(reg);
517 } 498 int st = x87_st2idx(i);
518 499 if (st != other_slot) {
519 500 int other_i = x87_st2idx(other_slot);
520 void LCodeGen::PushX87DoubleOperand(Operand src) { 501 X87Register other = x87_stack_[other_i];
521 ASSERT(x87_stack_depth_ == 0); 502 x87_stack_[other_i] = reg;
522 x87_stack_depth_++; 503 x87_stack_[i] = other;
523 __ fld_d(src); 504 if (st == 0) {
524 } 505 __ fxch(other_slot);
525 506 } else if (other_slot == 0) {
526 507 __ fxch(st);
527 void LCodeGen::PushX87FloatOperand(Operand src) { 508 } else {
528 ASSERT(x87_stack_depth_ == 0); 509 __ fxch(st);
529 x87_stack_depth_++; 510 __ fxch(other_slot);
530 __ fld_s(src); 511 __ fxch(st);
531 }
532
533
534 void LCodeGen::PopX87() {
535 ASSERT(x87_stack_depth_ == 1);
536 x87_stack_depth_--;
537 __ fstp(0);
538 }
539
540
541 void LCodeGen::CurrentInstructionReturnsX87Result() {
542 ASSERT(x87_stack_depth_ <= 1);
543 if (x87_stack_depth_ == 0) {
544 x87_stack_depth_ = 1;
545 }
546 }
547
548
549 void LCodeGen::FlushX87StackIfNecessary(LInstruction* instr) {
550 if (x87_stack_depth_ > 0) {
551 if ((instr->ClobbersDoubleRegisters() ||
552 instr->HasDoubleRegisterResult()) &&
553 !instr->HasDoubleRegisterInput()) {
554 PopX87();
555 } 512 }
556 } 513 }
557 } 514 }
558 515
559 516
517 int LCodeGen::x87_st2idx(int pos) {
518 return x87_stack_depth_ - pos - 1;
519 }
520
521
522 int LCodeGen::X87ArrayIndex(X87Register reg) {
523 for (int i = 0; i < x87_stack_depth_; i++) {
524 if (x87_stack_[i].is(reg)) return i;
525 }
526 UNREACHABLE();
527 return -1;
528 }
529
530
531 bool LCodeGen::X87StackContains(X87Register reg) {
532 for (int i = 0; i < x87_stack_depth_; i++) {
533 if (x87_stack_[i].is(reg)) return true;
534 }
535 return false;
536 }
537
538
539 void LCodeGen::X87Free(X87Register reg) {
540 ASSERT(X87StackContains(reg));
541 int i = X87ArrayIndex(reg);
542 int st = x87_st2idx(i);
543 if (st > 0) {
544 // keep track of how fstp(i) changes the order of elements
545 int tos_i = x87_st2idx(0);
546 x87_stack_[i] = x87_stack_[tos_i];
547 }
548 x87_stack_depth_--;
549 __ fstp(st);
550 }
551
552
553 void LCodeGen::X87Mov(X87Register dst, Operand src, X87OperandType opts) {
554 if (X87StackContains(dst)) {
555 X87Fxch(dst);
556 __ fstp(0);
557 } else {
558 ASSERT(x87_stack_depth_ < X87Register::kNumAllocatableRegisters);
559 x87_stack_[x87_stack_depth_] = dst;
560 x87_stack_depth_++;
561 }
562 X87Fld(src, opts);
563 }
564
565
566 void LCodeGen::X87Fld(Operand src, X87OperandType opts) {
567 if (opts == kX87DoubleOperand) {
568 __ fld_d(src);
569 } else if (opts == kX87FloatOperand) {
570 __ fld_s(src);
571 } else if (opts == kX87IntOperand) {
572 __ fild_s(src);
573 } else {
574 UNREACHABLE();
575 }
576 }
577
578
579 void LCodeGen::X87Mov(Operand dst, X87Register src) {
580 X87Fxch(src);
581 __ fst_d(dst);
582 }
583
584
585 void LCodeGen::X87PrepareToWrite(X87Register reg) {
586 if (X87StackContains(reg)) {
587 X87Free(reg);
588 }
589 // Mark this register as the next register to write to
590 x87_stack_[x87_stack_depth_] = reg;
591 }
592
593
594 void LCodeGen::X87CommitWrite(X87Register reg) {
595 // Assert the reg is prepared to write, but not on the virtual stack yet
596 ASSERT(!X87StackContains(reg) && x87_stack_[x87_stack_depth_].is(reg) &&
597 x87_stack_depth_ < X87Register::kNumAllocatableRegisters);
598 x87_stack_depth_++;
599 }
600
601
602 void LCodeGen::X87PrepareBinaryOp(
603 X87Register left, X87Register right, X87Register result) {
604 // You need to use DefineSameAsFirst for x87 instructions
605 ASSERT(result.is(left));
606 X87Fxch(right, 1);
607 X87Fxch(left);
608 }
609
610
611 void LCodeGen::FlushX87StackIfNecessary(LInstruction* instr) {
612 if (x87_stack_depth_ > 0 && instr->ClobbersDoubleRegisters()) {
613 bool double_inputs = instr->HasDoubleRegisterInput();
614
615 // Flush stack from tos down, since FreeX87() will mess with tos
616 for (int i = x87_stack_depth_-1; i >= 0; i--) {
617 X87Register reg = x87_stack_[i];
618 // Skip registers which contain the inputs for the next instruction
619 // when flushing the stack
620 if (double_inputs && instr->IsDoubleInput(reg, this)) {
621 continue;
622 }
623 X87Free(reg);
624 if (i < x87_stack_depth_-1) i++;
625 }
626 }
627 if (instr->IsReturn()) {
628 while (x87_stack_depth_ > 0) {
629 __ fstp(0);
630 x87_stack_depth_--;
631 }
632 }
633 }
634
635
636 void LCodeGen::EmitFlushX87ForDeopt() {
637 for (int i = 0; i < x87_stack_depth_; i++) __ fstp(0);
638 }
639
640
560 Register LCodeGen::ToRegister(LOperand* op) const { 641 Register LCodeGen::ToRegister(LOperand* op) const {
561 ASSERT(op->IsRegister()); 642 ASSERT(op->IsRegister());
562 return ToRegister(op->index()); 643 return ToRegister(op->index());
563 } 644 }
564 645
565 646
647 X87Register LCodeGen::ToX87Register(LOperand* op) const {
648 ASSERT(op->IsDoubleRegister());
649 return ToX87Register(op->index());
650 }
651
652
566 XMMRegister LCodeGen::ToDoubleRegister(LOperand* op) const { 653 XMMRegister LCodeGen::ToDoubleRegister(LOperand* op) const {
567 ASSERT(op->IsDoubleRegister()); 654 ASSERT(op->IsDoubleRegister());
568 return ToDoubleRegister(op->index()); 655 return ToDoubleRegister(op->index());
569 } 656 }
570 657
571 658
572 int LCodeGen::ToInteger32(LConstantOperand* op) const { 659 int LCodeGen::ToInteger32(LConstantOperand* op) const {
573 HConstant* constant = chunk_->LookupConstant(op); 660 HConstant* constant = chunk_->LookupConstant(op);
574 return constant->Integer32Value(); 661 return constant->Integer32Value();
575 } 662 }
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after
828 deoptimizations_.Add(environment, zone()); 915 deoptimizations_.Add(environment, zone());
829 } 916 }
830 } 917 }
831 918
832 919
833 void LCodeGen::DeoptimizeIf(Condition cc, 920 void LCodeGen::DeoptimizeIf(Condition cc,
834 LEnvironment* environment, 921 LEnvironment* environment,
835 Deoptimizer::BailoutType bailout_type) { 922 Deoptimizer::BailoutType bailout_type) {
836 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); 923 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
837 ASSERT(environment->HasBeenRegistered()); 924 ASSERT(environment->HasBeenRegistered());
838 // It's an error to deoptimize with the x87 fp stack in use.
839 ASSERT(x87_stack_depth_ == 0);
840 int id = environment->deoptimization_index(); 925 int id = environment->deoptimization_index();
841 ASSERT(info()->IsOptimizing() || info()->IsStub()); 926 ASSERT(info()->IsOptimizing() || info()->IsStub());
842 Address entry = 927 Address entry =
843 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type); 928 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type);
844 if (entry == NULL) { 929 if (entry == NULL) {
845 Abort("bailout was not prepared"); 930 Abort("bailout was not prepared");
846 return; 931 return;
847 } 932 }
848 933
849 if (FLAG_deopt_every_n_times != 0 && !info()->IsStub()) { 934 if (FLAG_deopt_every_n_times != 0 && !info()->IsStub()) {
850 Handle<SharedFunctionInfo> shared(info()->shared_info()); 935 Handle<SharedFunctionInfo> shared(info()->shared_info());
851 Label no_deopt; 936 Label no_deopt;
852 __ pushfd(); 937 __ pushfd();
853 __ push(eax); 938 __ push(eax);
854 __ push(ebx); 939 __ push(ebx);
855 __ mov(ebx, shared); 940 __ mov(ebx, shared);
856 __ mov(eax, 941 __ mov(eax,
857 FieldOperand(ebx, SharedFunctionInfo::kStressDeoptCounterOffset)); 942 FieldOperand(ebx, SharedFunctionInfo::kStressDeoptCounterOffset));
858 __ sub(Operand(eax), Immediate(Smi::FromInt(1))); 943 __ sub(Operand(eax), Immediate(Smi::FromInt(1)));
859 __ j(not_zero, &no_deopt, Label::kNear); 944 __ j(not_zero, &no_deopt, Label::kNear);
860 if (FLAG_trap_on_deopt) __ int3(); 945 if (FLAG_trap_on_deopt) __ int3();
861 __ mov(eax, Immediate(Smi::FromInt(FLAG_deopt_every_n_times))); 946 __ mov(eax, Immediate(Smi::FromInt(FLAG_deopt_every_n_times)));
862 __ mov(FieldOperand(ebx, SharedFunctionInfo::kStressDeoptCounterOffset), 947 __ mov(FieldOperand(ebx, SharedFunctionInfo::kStressDeoptCounterOffset),
863 eax); 948 eax);
864 __ pop(ebx); 949 __ pop(ebx);
865 __ pop(eax); 950 __ pop(eax);
866 __ popfd(); 951 __ popfd();
867 __ jmp(entry, RelocInfo::RUNTIME_ENTRY); 952 ASSERT(frame_is_built_);
953 __ call(entry, RelocInfo::RUNTIME_ENTRY);
868 954
869 __ bind(&no_deopt); 955 __ bind(&no_deopt);
870 __ mov(FieldOperand(ebx, SharedFunctionInfo::kStressDeoptCounterOffset), 956 __ mov(FieldOperand(ebx, SharedFunctionInfo::kStressDeoptCounterOffset),
871 eax); 957 eax);
872 __ pop(ebx); 958 __ pop(ebx);
873 __ pop(eax); 959 __ pop(eax);
874 __ popfd(); 960 __ popfd();
875 } 961 }
876 962
963 // Before Instructions which can deopt, we normally flush the x87 stack. But
964 // we can have inputs or outputs of the current instruction on the stack,
965 // thus we need to flush them here from the physical stack to leave it in a
966 // consistent state.
967 if (x87_stack_depth_ > 0) {
968 Label done;
969 if (cc != no_condition) __ j(NegateCondition(cc), &done, Label::kNear);
970 EmitFlushX87ForDeopt();
971 __ bind(&done);
972 }
973
877 if (FLAG_trap_on_deopt && info()->IsOptimizing()) { 974 if (FLAG_trap_on_deopt && info()->IsOptimizing()) {
878 Label done; 975 Label done;
879 if (cc != no_condition) { 976 if (cc != no_condition) __ j(NegateCondition(cc), &done, Label::kNear);
880 __ j(NegateCondition(cc), &done, Label::kNear);
881 }
882 __ int3(); 977 __ int3();
883 __ bind(&done); 978 __ bind(&done);
884 } 979 }
885 980
886 ASSERT(info()->IsStub() || frame_is_built_); 981 ASSERT(info()->IsStub() || frame_is_built_);
887 if (cc == no_condition && frame_is_built_) { 982 if (cc == no_condition && frame_is_built_) {
888 if (bailout_type == Deoptimizer::LAZY) { 983 __ call(entry, RelocInfo::RUNTIME_ENTRY);
889 __ call(entry, RelocInfo::RUNTIME_ENTRY);
890 } else {
891 __ jmp(entry, RelocInfo::RUNTIME_ENTRY);
892 }
893 } else { 984 } else {
894 // We often have several deopts to the same entry, reuse the last 985 // We often have several deopts to the same entry, reuse the last
895 // jump entry if this is the case. 986 // jump entry if this is the case.
896 if (jump_table_.is_empty() || 987 if (jump_table_.is_empty() ||
897 jump_table_.last().address != entry || 988 jump_table_.last().address != entry ||
898 jump_table_.last().needs_frame != !frame_is_built_ || 989 jump_table_.last().needs_frame != !frame_is_built_ ||
899 jump_table_.last().bailout_type != bailout_type) { 990 jump_table_.last().bailout_type != bailout_type) {
900 Deoptimizer::JumpTableEntry table_entry(entry, 991 Deoptimizer::JumpTableEntry table_entry(entry,
901 bailout_type, 992 bailout_type,
902 !frame_is_built_); 993 !frame_is_built_);
(...skipping 811 matching lines...) Expand 10 before | Expand all | Expand 10 after
1714 } 1805 }
1715 1806
1716 1807
1717 void LCodeGen::DoConstantD(LConstantD* instr) { 1808 void LCodeGen::DoConstantD(LConstantD* instr) {
1718 double v = instr->value(); 1809 double v = instr->value();
1719 uint64_t int_val = BitCast<uint64_t, double>(v); 1810 uint64_t int_val = BitCast<uint64_t, double>(v);
1720 int32_t lower = static_cast<int32_t>(int_val); 1811 int32_t lower = static_cast<int32_t>(int_val);
1721 int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt)); 1812 int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt));
1722 1813
1723 if (!CpuFeatures::IsSafeForSnapshot(SSE2)) { 1814 if (!CpuFeatures::IsSafeForSnapshot(SSE2)) {
1815 __ push(Immediate(upper));
1724 __ push(Immediate(lower)); 1816 __ push(Immediate(lower));
1725 __ push(Immediate(upper)); 1817 X87Mov(ToX87Register(instr->result()), Operand(esp, 0));
1726 PushX87DoubleOperand(Operand(esp, 0));
1727 __ add(Operand(esp), Immediate(kDoubleSize)); 1818 __ add(Operand(esp), Immediate(kDoubleSize));
1728 CurrentInstructionReturnsX87Result();
1729 } else { 1819 } else {
1730 CpuFeatureScope scope1(masm(), SSE2); 1820 CpuFeatureScope scope1(masm(), SSE2);
1731 ASSERT(instr->result()->IsDoubleRegister()); 1821 ASSERT(instr->result()->IsDoubleRegister());
1732 XMMRegister res = ToDoubleRegister(instr->result()); 1822 XMMRegister res = ToDoubleRegister(instr->result());
1733 if (int_val == 0) { 1823 if (int_val == 0) {
1734 __ xorps(res, res); 1824 __ xorps(res, res);
1735 } else { 1825 } else {
1736 Register temp = ToRegister(instr->temp()); 1826 Register temp = ToRegister(instr->temp());
1737 if (CpuFeatures::IsSupported(SSE4_1)) { 1827 if (CpuFeatures::IsSupported(SSE4_1)) {
1738 CpuFeatureScope scope2(masm(), SSE4_1); 1828 CpuFeatureScope scope2(masm(), SSE4_1);
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after
1983 __ j(parity_even, &return_left, Label::kNear); // left == NaN. 2073 __ j(parity_even, &return_left, Label::kNear); // left == NaN.
1984 __ bind(&return_right); 2074 __ bind(&return_right);
1985 __ movsd(left_reg, right_reg); 2075 __ movsd(left_reg, right_reg);
1986 2076
1987 __ bind(&return_left); 2077 __ bind(&return_left);
1988 } 2078 }
1989 } 2079 }
1990 2080
1991 2081
1992 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { 2082 void LCodeGen::DoArithmeticD(LArithmeticD* instr) {
1993 CpuFeatureScope scope(masm(), SSE2); 2083 if (CpuFeatures::IsSafeForSnapshot(SSE2)) {
1994 XMMRegister left = ToDoubleRegister(instr->left()); 2084 CpuFeatureScope scope(masm(), SSE2);
1995 XMMRegister right = ToDoubleRegister(instr->right()); 2085 XMMRegister left = ToDoubleRegister(instr->left());
1996 XMMRegister result = ToDoubleRegister(instr->result()); 2086 XMMRegister right = ToDoubleRegister(instr->right());
1997 // Modulo uses a fixed result register. 2087 XMMRegister result = ToDoubleRegister(instr->result());
1998 ASSERT(instr->op() == Token::MOD || left.is(result)); 2088 // Modulo uses a fixed result register.
1999 switch (instr->op()) { 2089 ASSERT(instr->op() == Token::MOD || left.is(result));
2000 case Token::ADD: 2090 switch (instr->op()) {
2001 __ addsd(left, right); 2091 case Token::ADD:
2002 break; 2092 __ addsd(left, right);
2003 case Token::SUB: 2093 break;
2004 __ subsd(left, right); 2094 case Token::SUB:
2005 break; 2095 __ subsd(left, right);
2006 case Token::MUL: 2096 break;
2007 __ mulsd(left, right); 2097 case Token::MUL:
2008 break; 2098 __ mulsd(left, right);
2009 case Token::DIV: 2099 break;
2010 __ divsd(left, right); 2100 case Token::DIV:
2011 // Don't delete this mov. It may improve performance on some CPUs, 2101 __ divsd(left, right);
2012 // when there is a mulsd depending on the result 2102 // Don't delete this mov. It may improve performance on some CPUs,
2013 __ movaps(left, left); 2103 // when there is a mulsd depending on the result
2014 break; 2104 __ movaps(left, left);
2015 case Token::MOD: { 2105 break;
2016 // Pass two doubles as arguments on the stack. 2106 case Token::MOD: {
2017 __ PrepareCallCFunction(4, eax); 2107 // Pass two doubles as arguments on the stack.
2018 __ movdbl(Operand(esp, 0 * kDoubleSize), left); 2108 __ PrepareCallCFunction(4, eax);
2019 __ movdbl(Operand(esp, 1 * kDoubleSize), right); 2109 __ movdbl(Operand(esp, 0 * kDoubleSize), left);
2020 __ CallCFunction( 2110 __ movdbl(Operand(esp, 1 * kDoubleSize), right);
2021 ExternalReference::double_fp_operation(Token::MOD, isolate()), 2111 __ CallCFunction(
2022 4); 2112 ExternalReference::double_fp_operation(Token::MOD, isolate()),
2113 4);
2023 2114
2024 // Return value is in st(0) on ia32. 2115 // Return value is in st(0) on ia32.
2025 // Store it into the (fixed) result register. 2116 // Store it into the (fixed) result register.
2026 __ sub(Operand(esp), Immediate(kDoubleSize)); 2117 __ sub(Operand(esp), Immediate(kDoubleSize));
2027 __ fstp_d(Operand(esp, 0)); 2118 __ fstp_d(Operand(esp, 0));
2028 __ movdbl(result, Operand(esp, 0)); 2119 __ movdbl(result, Operand(esp, 0));
2029 __ add(Operand(esp), Immediate(kDoubleSize)); 2120 __ add(Operand(esp), Immediate(kDoubleSize));
2030 break; 2121 break;
2122 }
2123 default:
2124 UNREACHABLE();
2125 break;
2031 } 2126 }
2032 default: 2127 } else {
2033 UNREACHABLE(); 2128 X87Register left = ToX87Register(instr->left());
2034 break; 2129 X87Register right = ToX87Register(instr->right());
2130 X87Register result = ToX87Register(instr->result());
2131 X87PrepareBinaryOp(left, right, result);
2132 switch (instr->op()) {
2133 case Token::MUL:
2134 __ fmul_i(1);
2135 break;
2136 default:
2137 UNREACHABLE();
2138 break;
2139 }
2035 } 2140 }
2036 } 2141 }
2037 2142
2038 2143
2039 void LCodeGen::DoNegateNoSSE2D(LNegateNoSSE2D* instr) {
2040 __ push(Immediate(-1));
2041 __ fild_s(Operand(esp, 0));
2042 __ add(esp, Immediate(kPointerSize));
2043 __ fmulp();
2044 CurrentInstructionReturnsX87Result();
2045 }
2046
2047
2048
2049 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { 2144 void LCodeGen::DoArithmeticT(LArithmeticT* instr) {
2050 ASSERT(ToRegister(instr->context()).is(esi)); 2145 ASSERT(ToRegister(instr->context()).is(esi));
2051 ASSERT(ToRegister(instr->left()).is(edx)); 2146 ASSERT(ToRegister(instr->left()).is(edx));
2052 ASSERT(ToRegister(instr->right()).is(eax)); 2147 ASSERT(ToRegister(instr->right()).is(eax));
2053 ASSERT(ToRegister(instr->result()).is(eax)); 2148 ASSERT(ToRegister(instr->result()).is(eax));
2054 2149
2055 BinaryOpStub stub(instr->op(), NO_OVERWRITE); 2150 BinaryOpStub stub(instr->op(), NO_OVERWRITE);
2056 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); 2151 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
2057 __ nop(); // Signals no inlined code. 2152 __ nop(); // Signals no inlined code.
2058 } 2153 }
(...skipping 897 matching lines...) Expand 10 before | Expand all | Expand 10 after
2956 HObjectAccess access = instr->hydrogen()->access(); 3051 HObjectAccess access = instr->hydrogen()->access();
2957 int offset = access.offset(); 3052 int offset = access.offset();
2958 Register object = ToRegister(instr->object()); 3053 Register object = ToRegister(instr->object());
2959 if (FLAG_track_double_fields && 3054 if (FLAG_track_double_fields &&
2960 instr->hydrogen()->representation().IsDouble()) { 3055 instr->hydrogen()->representation().IsDouble()) {
2961 if (CpuFeatures::IsSupported(SSE2)) { 3056 if (CpuFeatures::IsSupported(SSE2)) {
2962 CpuFeatureScope scope(masm(), SSE2); 3057 CpuFeatureScope scope(masm(), SSE2);
2963 XMMRegister result = ToDoubleRegister(instr->result()); 3058 XMMRegister result = ToDoubleRegister(instr->result());
2964 __ movdbl(result, FieldOperand(object, offset)); 3059 __ movdbl(result, FieldOperand(object, offset));
2965 } else { 3060 } else {
2966 PushX87DoubleOperand(FieldOperand(object, offset)); 3061 X87Mov(ToX87Register(instr->result()), FieldOperand(object, offset));
2967 CurrentInstructionReturnsX87Result();
2968 } 3062 }
2969 return; 3063 return;
2970 } 3064 }
2971 3065
2972 Register result = ToRegister(instr->result()); 3066 Register result = ToRegister(instr->result());
2973 if (access.IsInobject()) { 3067 if (access.IsInobject()) {
2974 __ mov(result, FieldOperand(object, offset)); 3068 __ mov(result, FieldOperand(object, offset));
2975 } else { 3069 } else {
2976 __ mov(result, FieldOperand(object, JSObject::kPropertiesOffset)); 3070 __ mov(result, FieldOperand(object, JSObject::kPropertiesOffset));
2977 __ mov(result, FieldOperand(result, offset)); 3071 __ mov(result, FieldOperand(result, offset));
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after
3202 elements_kind, 3296 elements_kind,
3203 0, 3297 0,
3204 instr->additional_index())); 3298 instr->additional_index()));
3205 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { 3299 if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
3206 if (CpuFeatures::IsSupported(SSE2)) { 3300 if (CpuFeatures::IsSupported(SSE2)) {
3207 CpuFeatureScope scope(masm(), SSE2); 3301 CpuFeatureScope scope(masm(), SSE2);
3208 XMMRegister result(ToDoubleRegister(instr->result())); 3302 XMMRegister result(ToDoubleRegister(instr->result()));
3209 __ movss(result, operand); 3303 __ movss(result, operand);
3210 __ cvtss2sd(result, result); 3304 __ cvtss2sd(result, result);
3211 } else { 3305 } else {
3212 PushX87FloatOperand(operand); 3306 X87Mov(ToX87Register(instr->result()), operand, kX87FloatOperand);
3213 CurrentInstructionReturnsX87Result();
3214 } 3307 }
3215 } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { 3308 } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
3216 if (CpuFeatures::IsSupported(SSE2)) { 3309 if (CpuFeatures::IsSupported(SSE2)) {
3217 CpuFeatureScope scope(masm(), SSE2); 3310 CpuFeatureScope scope(masm(), SSE2);
3218 __ movdbl(ToDoubleRegister(instr->result()), operand); 3311 __ movdbl(ToDoubleRegister(instr->result()), operand);
3219 } else { 3312 } else {
3220 PushX87DoubleOperand(operand); 3313 X87Mov(ToX87Register(instr->result()), operand);
3221 CurrentInstructionReturnsX87Result();
3222 } 3314 }
3223 } else { 3315 } else {
3224 Register result(ToRegister(instr->result())); 3316 Register result(ToRegister(instr->result()));
3225 switch (elements_kind) { 3317 switch (elements_kind) {
3226 case EXTERNAL_BYTE_ELEMENTS: 3318 case EXTERNAL_BYTE_ELEMENTS:
3227 __ movsx_b(result, operand); 3319 __ movsx_b(result, operand);
3228 break; 3320 break;
3229 case EXTERNAL_PIXEL_ELEMENTS: 3321 case EXTERNAL_PIXEL_ELEMENTS:
3230 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 3322 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
3231 __ movzx_b(result, operand); 3323 __ movzx_b(result, operand);
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
3282 instr->key(), 3374 instr->key(),
3283 instr->hydrogen()->key()->representation(), 3375 instr->hydrogen()->key()->representation(),
3284 FAST_DOUBLE_ELEMENTS, 3376 FAST_DOUBLE_ELEMENTS,
3285 FixedDoubleArray::kHeaderSize - kHeapObjectTag, 3377 FixedDoubleArray::kHeaderSize - kHeapObjectTag,
3286 instr->additional_index()); 3378 instr->additional_index());
3287 if (CpuFeatures::IsSupported(SSE2)) { 3379 if (CpuFeatures::IsSupported(SSE2)) {
3288 CpuFeatureScope scope(masm(), SSE2); 3380 CpuFeatureScope scope(masm(), SSE2);
3289 XMMRegister result = ToDoubleRegister(instr->result()); 3381 XMMRegister result = ToDoubleRegister(instr->result());
3290 __ movdbl(result, double_load_operand); 3382 __ movdbl(result, double_load_operand);
3291 } else { 3383 } else {
3292 PushX87DoubleOperand(double_load_operand); 3384 X87Mov(ToX87Register(instr->result()), double_load_operand);
3293 CurrentInstructionReturnsX87Result();
3294 } 3385 }
3295 } 3386 }
3296 3387
3297 3388
3298 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { 3389 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) {
3299 Register result = ToRegister(instr->result()); 3390 Register result = ToRegister(instr->result());
3300 3391
3301 // Load the result. 3392 // Load the result.
3302 __ mov(result, 3393 __ mov(result,
3303 BuildFastArrayOperand(instr->elements(), 3394 BuildFastArrayOperand(instr->elements(),
(...skipping 973 matching lines...) Expand 10 before | Expand all | Expand 10 after
4277 } 4368 }
4278 } else if (FLAG_track_double_fields && representation.IsDouble()) { 4369 } else if (FLAG_track_double_fields && representation.IsDouble()) {
4279 ASSERT(transition.is_null()); 4370 ASSERT(transition.is_null());
4280 ASSERT(access.IsInobject()); 4371 ASSERT(access.IsInobject());
4281 ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); 4372 ASSERT(!instr->hydrogen()->NeedsWriteBarrier());
4282 if (CpuFeatures::IsSupported(SSE2)) { 4373 if (CpuFeatures::IsSupported(SSE2)) {
4283 CpuFeatureScope scope(masm(), SSE2); 4374 CpuFeatureScope scope(masm(), SSE2);
4284 XMMRegister value = ToDoubleRegister(instr->value()); 4375 XMMRegister value = ToDoubleRegister(instr->value());
4285 __ movdbl(FieldOperand(object, offset), value); 4376 __ movdbl(FieldOperand(object, offset), value);
4286 } else { 4377 } else {
4287 __ fstp_d(FieldOperand(object, offset)); 4378 X87Register value = ToX87Register(instr->value());
4379 X87Mov(FieldOperand(object, offset), value);
4288 } 4380 }
4289 return; 4381 return;
4290 } 4382 }
4291 4383
4292 if (!transition.is_null()) { 4384 if (!transition.is_null()) {
4293 if (!instr->hydrogen()->NeedsWriteBarrierForMap()) { 4385 if (!instr->hydrogen()->NeedsWriteBarrierForMap()) {
4294 __ mov(FieldOperand(object, HeapObject::kMapOffset), transition); 4386 __ mov(FieldOperand(object, HeapObject::kMapOffset), transition);
4295 } else { 4387 } else {
4296 Register temp = ToRegister(instr->temp()); 4388 Register temp = ToRegister(instr->temp());
4297 Register temp_map = ToRegister(instr->temp_map()); 4389 Register temp_map = ToRegister(instr->temp_map());
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
4403 __ movss(operand, xmm0); 4495 __ movss(operand, xmm0);
4404 } else { 4496 } else {
4405 __ fld(0); 4497 __ fld(0);
4406 __ fstp_s(operand); 4498 __ fstp_s(operand);
4407 } 4499 }
4408 } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { 4500 } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
4409 if (CpuFeatures::IsSafeForSnapshot(SSE2)) { 4501 if (CpuFeatures::IsSafeForSnapshot(SSE2)) {
4410 CpuFeatureScope scope(masm(), SSE2); 4502 CpuFeatureScope scope(masm(), SSE2);
4411 __ movdbl(operand, ToDoubleRegister(instr->value())); 4503 __ movdbl(operand, ToDoubleRegister(instr->value()));
4412 } else { 4504 } else {
4413 __ fst_d(operand); 4505 X87Mov(operand, ToX87Register(instr->value()));
4414 } 4506 }
4415 } else { 4507 } else {
4416 Register value = ToRegister(instr->value()); 4508 Register value = ToRegister(instr->value());
4417 switch (elements_kind) { 4509 switch (elements_kind) {
4418 case EXTERNAL_PIXEL_ELEMENTS: 4510 case EXTERNAL_PIXEL_ELEMENTS:
4419 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 4511 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
4420 case EXTERNAL_BYTE_ELEMENTS: 4512 case EXTERNAL_BYTE_ELEMENTS:
4421 __ mov_b(operand, value); 4513 __ mov_b(operand, value);
4422 break; 4514 break;
4423 case EXTERNAL_SHORT_ELEMENTS: 4515 case EXTERNAL_SHORT_ELEMENTS:
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
4485 Operand double_store_operand2 = BuildFastArrayOperand( 4577 Operand double_store_operand2 = BuildFastArrayOperand(
4486 instr->elements(), 4578 instr->elements(),
4487 instr->key(), 4579 instr->key(),
4488 instr->hydrogen()->key()->representation(), 4580 instr->hydrogen()->key()->representation(),
4489 FAST_DOUBLE_ELEMENTS, 4581 FAST_DOUBLE_ELEMENTS,
4490 FixedDoubleArray::kHeaderSize - kHeapObjectTag + kPointerSize, 4582 FixedDoubleArray::kHeaderSize - kHeapObjectTag + kPointerSize,
4491 instr->additional_index()); 4583 instr->additional_index());
4492 __ mov(double_store_operand2, Immediate(upper)); 4584 __ mov(double_store_operand2, Immediate(upper));
4493 } else { 4585 } else {
4494 Label no_special_nan_handling; 4586 Label no_special_nan_handling;
4495 ASSERT(x87_stack_depth_ > 0); 4587 X87Register value = ToX87Register(instr->value());
4588 X87Fxch(value);
4496 4589
4497 if (instr->NeedsCanonicalization()) { 4590 if (instr->NeedsCanonicalization()) {
4498 __ fld(0); 4591 __ fld(0);
4499 __ fld(0); 4592 __ fld(0);
4500 __ FCmp(); 4593 __ FCmp();
4501 4594
4502 __ j(parity_odd, &no_special_nan_handling); 4595 __ j(parity_odd, &no_special_nan_handling);
4503 __ sub(esp, Immediate(kDoubleSize)); 4596 __ sub(esp, Immediate(kDoubleSize));
4504 __ fst_d(MemOperand(esp, 0)); 4597 __ fst_d(MemOperand(esp, 0));
4505 __ cmp(MemOperand(esp, sizeof(kHoleNanLower32)), 4598 __ cmp(MemOperand(esp, sizeof(kHoleNanLower32)),
(...skipping 449 matching lines...) Expand 10 before | Expand all | Expand 10 after
4955 5048
4956 Register reg = ToRegister(instr->result()); 5049 Register reg = ToRegister(instr->result());
4957 5050
4958 bool convert_hole = false; 5051 bool convert_hole = false;
4959 HValue* change_input = instr->hydrogen()->value(); 5052 HValue* change_input = instr->hydrogen()->value();
4960 if (change_input->IsLoadKeyed()) { 5053 if (change_input->IsLoadKeyed()) {
4961 HLoadKeyed* load = HLoadKeyed::cast(change_input); 5054 HLoadKeyed* load = HLoadKeyed::cast(change_input);
4962 convert_hole = load->UsesMustHandleHole(); 5055 convert_hole = load->UsesMustHandleHole();
4963 } 5056 }
4964 5057
5058 bool use_sse2 = CpuFeatures::IsSupported(SSE2);
5059 if (!use_sse2) {
5060 // Put the value to the top of stack
5061 X87Register src = ToX87Register(instr->value());
5062 X87LoadForUsage(src);
5063 }
5064
4965 Label no_special_nan_handling; 5065 Label no_special_nan_handling;
4966 Label done; 5066 Label done;
4967 if (convert_hole) { 5067 if (convert_hole) {
4968 bool use_sse2 = CpuFeatures::IsSupported(SSE2);
4969 if (use_sse2) { 5068 if (use_sse2) {
4970 CpuFeatureScope scope(masm(), SSE2); 5069 CpuFeatureScope scope(masm(), SSE2);
4971 XMMRegister input_reg = ToDoubleRegister(instr->value()); 5070 XMMRegister input_reg = ToDoubleRegister(instr->value());
4972 __ ucomisd(input_reg, input_reg); 5071 __ ucomisd(input_reg, input_reg);
4973 } else { 5072 } else {
4974 __ fld(0); 5073 __ fld(0);
4975 __ fld(0); 5074 __ fld(0);
4976 __ FCmp(); 5075 __ FCmp();
4977 } 5076 }
4978 5077
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
5012 5111
5013 __ bind(&no_special_nan_handling); 5112 __ bind(&no_special_nan_handling);
5014 DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr); 5113 DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr);
5015 if (FLAG_inline_new) { 5114 if (FLAG_inline_new) {
5016 Register tmp = ToRegister(instr->temp()); 5115 Register tmp = ToRegister(instr->temp());
5017 __ AllocateHeapNumber(reg, tmp, no_reg, deferred->entry()); 5116 __ AllocateHeapNumber(reg, tmp, no_reg, deferred->entry());
5018 } else { 5117 } else {
5019 __ jmp(deferred->entry()); 5118 __ jmp(deferred->entry());
5020 } 5119 }
5021 __ bind(deferred->exit()); 5120 __ bind(deferred->exit());
5022 if (CpuFeatures::IsSupported(SSE2)) { 5121 if (use_sse2) {
5023 CpuFeatureScope scope(masm(), SSE2); 5122 CpuFeatureScope scope(masm(), SSE2);
5024 XMMRegister input_reg = ToDoubleRegister(instr->value()); 5123 XMMRegister input_reg = ToDoubleRegister(instr->value());
5025 __ movdbl(FieldOperand(reg, HeapNumber::kValueOffset), input_reg); 5124 __ movdbl(FieldOperand(reg, HeapNumber::kValueOffset), input_reg);
5026 } else { 5125 } else {
5027 __ fst_d(FieldOperand(reg, HeapNumber::kValueOffset)); 5126 __ fstp_d(FieldOperand(reg, HeapNumber::kValueOffset));
5028 } 5127 }
5029 __ bind(&done); 5128 __ bind(&done);
5030 } 5129 }
5031 5130
5032 5131
5033 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { 5132 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) {
5034 // TODO(3095996): Get rid of this. For now, we need to make the 5133 // TODO(3095996): Get rid of this. For now, we need to make the
5035 // result register contain a valid pointer because it is already 5134 // result register contain a valid pointer because it is already
5036 // contained in the register pointer map. 5135 // contained in the register pointer map.
5037 Register reg = ToRegister(instr->result()); 5136 Register reg = ToRegister(instr->result());
(...skipping 30 matching lines...) Expand all
5068 DeoptimizeIf(not_zero, instr->environment()); 5167 DeoptimizeIf(not_zero, instr->environment());
5069 } else { 5168 } else {
5070 __ AssertSmi(result); 5169 __ AssertSmi(result);
5071 } 5170 }
5072 __ SmiUntag(result); 5171 __ SmiUntag(result);
5073 } 5172 }
5074 5173
5075 5174
5076 void LCodeGen::EmitNumberUntagDNoSSE2(Register input_reg, 5175 void LCodeGen::EmitNumberUntagDNoSSE2(Register input_reg,
5077 Register temp_reg, 5176 Register temp_reg,
5177 X87Register res_reg,
5078 bool allow_undefined_as_nan, 5178 bool allow_undefined_as_nan,
5079 bool deoptimize_on_minus_zero, 5179 bool deoptimize_on_minus_zero,
5080 LEnvironment* env, 5180 LEnvironment* env,
5081 NumberUntagDMode mode) { 5181 NumberUntagDMode mode) {
5082 Label load_smi, done; 5182 Label load_smi, done;
5083 5183
5184 X87PrepareToWrite(res_reg);
5084 STATIC_ASSERT(NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE > 5185 STATIC_ASSERT(NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE >
5085 NUMBER_CANDIDATE_IS_ANY_TAGGED); 5186 NUMBER_CANDIDATE_IS_ANY_TAGGED);
5086 if (mode >= NUMBER_CANDIDATE_IS_ANY_TAGGED) { 5187 if (mode >= NUMBER_CANDIDATE_IS_ANY_TAGGED) {
5087 // Smi check. 5188 // Smi check.
5088 __ JumpIfSmi(input_reg, &load_smi, Label::kNear); 5189 __ JumpIfSmi(input_reg, &load_smi, Label::kNear);
5089 5190
5090 // Heap number map check. 5191 // Heap number map check.
5091 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), 5192 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
5092 factory()->heap_number_map()); 5193 factory()->heap_number_map());
5093 if (!allow_undefined_as_nan) { 5194 if (!allow_undefined_as_nan) {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
5134 ASSERT(mode == NUMBER_CANDIDATE_IS_SMI); 5235 ASSERT(mode == NUMBER_CANDIDATE_IS_SMI);
5135 } 5236 }
5136 5237
5137 __ bind(&load_smi); 5238 __ bind(&load_smi);
5138 __ SmiUntag(input_reg); // Untag smi before converting to float. 5239 __ SmiUntag(input_reg); // Untag smi before converting to float.
5139 __ push(input_reg); 5240 __ push(input_reg);
5140 __ fild_s(Operand(esp, 0)); 5241 __ fild_s(Operand(esp, 0));
5141 __ pop(input_reg); 5242 __ pop(input_reg);
5142 __ SmiTag(input_reg); // Retag smi. 5243 __ SmiTag(input_reg); // Retag smi.
5143 __ bind(&done); 5244 __ bind(&done);
5245 X87CommitWrite(res_reg);
5144 } 5246 }
5145 5247
5146 5248
5147 void LCodeGen::EmitNumberUntagD(Register input_reg, 5249 void LCodeGen::EmitNumberUntagD(Register input_reg,
5148 Register temp_reg, 5250 Register temp_reg,
5149 XMMRegister result_reg, 5251 XMMRegister result_reg,
5150 bool allow_undefined_as_nan, 5252 bool allow_undefined_as_nan,
5151 bool deoptimize_on_minus_zero, 5253 bool deoptimize_on_minus_zero,
5152 LEnvironment* env, 5254 LEnvironment* env,
5153 NumberUntagDMode mode) { 5255 NumberUntagDMode mode) {
(...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after
5515 EmitNumberUntagD(input_reg, 5617 EmitNumberUntagD(input_reg,
5516 temp_reg, 5618 temp_reg,
5517 result_reg, 5619 result_reg,
5518 instr->hydrogen()->allow_undefined_as_nan(), 5620 instr->hydrogen()->allow_undefined_as_nan(),
5519 deoptimize_on_minus_zero, 5621 deoptimize_on_minus_zero,
5520 instr->environment(), 5622 instr->environment(),
5521 mode); 5623 mode);
5522 } else { 5624 } else {
5523 EmitNumberUntagDNoSSE2(input_reg, 5625 EmitNumberUntagDNoSSE2(input_reg,
5524 temp_reg, 5626 temp_reg,
5627 ToX87Register(instr->result()),
5525 instr->hydrogen()->allow_undefined_as_nan(), 5628 instr->hydrogen()->allow_undefined_as_nan(),
5526 deoptimize_on_minus_zero, 5629 deoptimize_on_minus_zero,
5527 instr->environment(), 5630 instr->environment(),
5528 mode); 5631 mode);
5529 CurrentInstructionReturnsX87Result();
5530 } 5632 }
5531 } 5633 }
5532 5634
5533 5635
5534 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { 5636 void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
5535 LOperand* input = instr->value(); 5637 LOperand* input = instr->value();
5536 ASSERT(input->IsDoubleRegister()); 5638 ASSERT(input->IsDoubleRegister());
5537 LOperand* result = instr->result(); 5639 LOperand* result = instr->result();
5538 ASSERT(result->IsRegister()); 5640 ASSERT(result->IsRegister());
5539 CpuFeatureScope scope(masm(), SSE2); 5641 CpuFeatureScope scope(masm(), SSE2);
5540 5642
5541 XMMRegister input_reg = ToDoubleRegister(input); 5643 XMMRegister input_reg = ToDoubleRegister(input);
5542 Register result_reg = ToRegister(result); 5644 Register result_reg = ToRegister(result);
5543 5645
5646 __ cvttsd2si(result_reg, Operand(input_reg));
5647
5544 if (instr->truncating()) { 5648 if (instr->truncating()) {
5545 // Performs a truncating conversion of a floating point number as used by 5649 // Performs a truncating conversion of a floating point number as used by
5546 // the JS bitwise operations. 5650 // the JS bitwise operations.
5547 __ cvttsd2si(result_reg, Operand(input_reg)); 5651 Label fast_case_succeeded;
5548 __ cmp(result_reg, 0x80000000u); 5652 __ cmp(result_reg, 0x80000000u);
5549 if (CpuFeatures::IsSupported(SSE3)) { 5653 __ j(not_equal, &fast_case_succeeded);
5550 // This will deoptimize if the exponent of the input in out of range. 5654 __ sub(esp, Immediate(kDoubleSize));
5551 CpuFeatureScope scope(masm(), SSE3); 5655 __ movdbl(MemOperand(esp, 0), input_reg);
5552 Label convert, done; 5656 DoubleToIStub stub(esp, result_reg, 0, true);
5553 __ j(not_equal, &done, Label::kNear); 5657 __ call(stub.GetCode(isolate()), RelocInfo::CODE_TARGET);
5554 __ sub(Operand(esp), Immediate(kDoubleSize)); 5658 __ add(esp, Immediate(kDoubleSize));
5555 __ movdbl(Operand(esp, 0), input_reg); 5659 __ bind(&fast_case_succeeded);
5556 // Get exponent alone and check for too-big exponent.
5557 __ mov(result_reg, Operand(esp, sizeof(int32_t)));
5558 __ and_(result_reg, HeapNumber::kExponentMask);
5559 const uint32_t kTooBigExponent =
5560 (HeapNumber::kExponentBias + 63) << HeapNumber::kExponentShift;
5561 __ cmp(Operand(result_reg), Immediate(kTooBigExponent));
5562 __ j(less, &convert, Label::kNear);
5563 __ add(Operand(esp), Immediate(kDoubleSize));
5564 DeoptimizeIf(no_condition, instr->environment());
5565 __ bind(&convert);
5566 // Do conversion, which cannot fail because we checked the exponent.
5567 __ fld_d(Operand(esp, 0));
5568 __ fisttp_d(Operand(esp, 0));
5569 __ mov(result_reg, Operand(esp, 0)); // Low word of answer is the result.
5570 __ add(Operand(esp), Immediate(kDoubleSize));
5571 __ bind(&done);
5572 } else {
5573 Label done;
5574 Register temp_reg = ToRegister(instr->temp());
5575 XMMRegister xmm_scratch = xmm0;
5576
5577 // If cvttsd2si succeeded, we're done. Otherwise, we attempt
5578 // manual conversion.
5579 __ j(not_equal, &done, Label::kNear);
5580
5581 // Get high 32 bits of the input in result_reg and temp_reg.
5582 __ pshufd(xmm_scratch, input_reg, 1);
5583 __ movd(Operand(temp_reg), xmm_scratch);
5584 __ mov(result_reg, temp_reg);
5585
5586 // Prepare negation mask in temp_reg.
5587 __ sar(temp_reg, kBitsPerInt - 1);
5588
5589 // Extract the exponent from result_reg and subtract adjusted
5590 // bias from it. The adjustment is selected in a way such that
5591 // when the difference is zero, the answer is in the low 32 bits
5592 // of the input, otherwise a shift has to be performed.
5593 __ shr(result_reg, HeapNumber::kExponentShift);
5594 __ and_(result_reg,
5595 HeapNumber::kExponentMask >> HeapNumber::kExponentShift);
5596 __ sub(Operand(result_reg),
5597 Immediate(HeapNumber::kExponentBias +
5598 HeapNumber::kExponentBits +
5599 HeapNumber::kMantissaBits));
5600 // Don't handle big (> kMantissaBits + kExponentBits == 63) or
5601 // special exponents.
5602 DeoptimizeIf(greater, instr->environment());
5603
5604 // Zero out the sign and the exponent in the input (by shifting
5605 // it to the left) and restore the implicit mantissa bit,
5606 // i.e. convert the input to unsigned int64 shifted left by
5607 // kExponentBits.
5608 ExternalReference minus_zero = ExternalReference::address_of_minus_zero();
5609 // Minus zero has the most significant bit set and the other
5610 // bits cleared.
5611 __ movdbl(xmm_scratch, Operand::StaticVariable(minus_zero));
5612 __ psllq(input_reg, HeapNumber::kExponentBits);
5613 __ por(input_reg, xmm_scratch);
5614
5615 // Get the amount to shift the input right in xmm_scratch.
5616 __ neg(result_reg);
5617 __ movd(xmm_scratch, Operand(result_reg));
5618
5619 // Shift the input right and extract low 32 bits.
5620 __ psrlq(input_reg, xmm_scratch);
5621 __ movd(Operand(result_reg), input_reg);
5622
5623 // Use the prepared mask in temp_reg to negate the result if necessary.
5624 __ xor_(result_reg, Operand(temp_reg));
5625 __ sub(result_reg, Operand(temp_reg));
5626 __ bind(&done);
5627 }
5628 } else { 5660 } else {
5629 Label done; 5661 Label done;
5630 __ cvttsd2si(result_reg, Operand(input_reg));
5631 __ cvtsi2sd(xmm0, Operand(result_reg)); 5662 __ cvtsi2sd(xmm0, Operand(result_reg));
5632 __ ucomisd(xmm0, input_reg); 5663 __ ucomisd(xmm0, input_reg);
5633 DeoptimizeIf(not_equal, instr->environment()); 5664 DeoptimizeIf(not_equal, instr->environment());
5634 DeoptimizeIf(parity_even, instr->environment()); // NaN. 5665 DeoptimizeIf(parity_even, instr->environment()); // NaN.
5635 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 5666 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
5636 // The integer converted back is equal to the original. We 5667 // The integer converted back is equal to the original. We
5637 // only have to test if we got -0 as an input. 5668 // only have to test if we got -0 as an input.
5638 __ test(result_reg, Operand(result_reg)); 5669 __ test(result_reg, Operand(result_reg));
5639 __ j(not_zero, &done, Label::kNear); 5670 __ j(not_zero, &done, Label::kNear);
5640 __ movmskpd(result_reg, input_reg); 5671 __ movmskpd(result_reg, input_reg);
(...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after
5969 6000
5970 if (!instr->hydrogen()->CanOmitPrototypeChecks()) { 6001 if (!instr->hydrogen()->CanOmitPrototypeChecks()) {
5971 for (int i = 0; i < prototypes->length(); i++) { 6002 for (int i = 0; i < prototypes->length(); i++) {
5972 __ LoadHeapObject(reg, prototypes->at(i)); 6003 __ LoadHeapObject(reg, prototypes->at(i));
5973 DoCheckMapCommon(reg, maps->at(i), instr); 6004 DoCheckMapCommon(reg, maps->at(i), instr);
5974 } 6005 }
5975 } 6006 }
5976 } 6007 }
5977 6008
5978 6009
5979 void LCodeGen::DoAllocateObject(LAllocateObject* instr) {
5980 class DeferredAllocateObject: public LDeferredCode {
5981 public:
5982 DeferredAllocateObject(LCodeGen* codegen, LAllocateObject* instr)
5983 : LDeferredCode(codegen), instr_(instr) { }
5984 virtual void Generate() { codegen()->DoDeferredAllocateObject(instr_); }
5985 virtual LInstruction* instr() { return instr_; }
5986 private:
5987 LAllocateObject* instr_;
5988 };
5989
5990 DeferredAllocateObject* deferred =
5991 new(zone()) DeferredAllocateObject(this, instr);
5992
5993 Register result = ToRegister(instr->result());
5994 Register scratch = ToRegister(instr->temp());
5995 Handle<JSFunction> constructor = instr->hydrogen()->constructor();
5996 Handle<Map> initial_map = instr->hydrogen()->constructor_initial_map();
5997 int instance_size = initial_map->instance_size();
5998 ASSERT(initial_map->pre_allocated_property_fields() +
5999 initial_map->unused_property_fields() -
6000 initial_map->inobject_properties() == 0);
6001
6002 __ Allocate(instance_size, result, no_reg, scratch, deferred->entry(),
6003 TAG_OBJECT);
6004
6005 __ bind(deferred->exit());
6006 if (FLAG_debug_code) {
6007 Label is_in_new_space;
6008 __ JumpIfInNewSpace(result, scratch, &is_in_new_space);
6009 __ Abort("Allocated object is not in new-space");
6010 __ bind(&is_in_new_space);
6011 }
6012
6013 // Load the initial map.
6014 Register map = scratch;
6015 __ LoadHeapObject(scratch, constructor);
6016 __ mov(map, FieldOperand(scratch, JSFunction::kPrototypeOrInitialMapOffset));
6017
6018 if (FLAG_debug_code) {
6019 __ AssertNotSmi(map);
6020 __ cmpb(FieldOperand(map, Map::kInstanceSizeOffset),
6021 instance_size >> kPointerSizeLog2);
6022 __ Assert(equal, "Unexpected instance size");
6023 __ cmpb(FieldOperand(map, Map::kPreAllocatedPropertyFieldsOffset),
6024 initial_map->pre_allocated_property_fields());
6025 __ Assert(equal, "Unexpected pre-allocated property fields count");
6026 __ cmpb(FieldOperand(map, Map::kUnusedPropertyFieldsOffset),
6027 initial_map->unused_property_fields());
6028 __ Assert(equal, "Unexpected unused property fields count");
6029 __ cmpb(FieldOperand(map, Map::kInObjectPropertiesOffset),
6030 initial_map->inobject_properties());
6031 __ Assert(equal, "Unexpected in-object property fields count");
6032 }
6033
6034 // Initialize map and fields of the newly allocated object.
6035 ASSERT(initial_map->instance_type() == JS_OBJECT_TYPE);
6036 __ mov(FieldOperand(result, JSObject::kMapOffset), map);
6037 __ mov(scratch, factory()->empty_fixed_array());
6038 __ mov(FieldOperand(result, JSObject::kElementsOffset), scratch);
6039 __ mov(FieldOperand(result, JSObject::kPropertiesOffset), scratch);
6040 if (initial_map->inobject_properties() != 0) {
6041 __ mov(scratch, factory()->undefined_value());
6042 for (int i = 0; i < initial_map->inobject_properties(); i++) {
6043 int property_offset = JSObject::kHeaderSize + i * kPointerSize;
6044 __ mov(FieldOperand(result, property_offset), scratch);
6045 }
6046 }
6047 }
6048
6049
6050 void LCodeGen::DoDeferredAllocateObject(LAllocateObject* instr) {
6051 Register result = ToRegister(instr->result());
6052 Handle<Map> initial_map = instr->hydrogen()->constructor_initial_map();
6053 int instance_size = initial_map->instance_size();
6054
6055 // TODO(3095996): Get rid of this. For now, we need to make the
6056 // result register contain a valid pointer because it is already
6057 // contained in the register pointer map.
6058 __ Set(result, Immediate(0));
6059
6060 PushSafepointRegistersScope scope(this);
6061 __ push(Immediate(Smi::FromInt(instance_size)));
6062 CallRuntimeFromDeferred(
6063 Runtime::kAllocateInNewSpace, 1, instr, instr->context());
6064 __ StoreToSafepointRegisterSlot(result, eax);
6065 }
6066
6067
6068 void LCodeGen::DoAllocate(LAllocate* instr) { 6010 void LCodeGen::DoAllocate(LAllocate* instr) {
6069 class DeferredAllocate: public LDeferredCode { 6011 class DeferredAllocate: public LDeferredCode {
6070 public: 6012 public:
6071 DeferredAllocate(LCodeGen* codegen, LAllocate* instr) 6013 DeferredAllocate(LCodeGen* codegen, LAllocate* instr)
6072 : LDeferredCode(codegen), instr_(instr) { } 6014 : LDeferredCode(codegen), instr_(instr) { }
6073 virtual void Generate() { codegen()->DoDeferredAllocate(instr_); } 6015 virtual void Generate() { codegen()->DoDeferredAllocate(instr_); }
6074 virtual LInstruction* instr() { return instr_; } 6016 virtual LInstruction* instr() { return instr_; }
6075 private: 6017 private:
6076 LAllocate* instr_; 6018 LAllocate* instr_;
6077 }; 6019 };
(...skipping 463 matching lines...) Expand 10 before | Expand all | Expand 10 after
6541 FixedArray::kHeaderSize - kPointerSize)); 6483 FixedArray::kHeaderSize - kPointerSize));
6542 __ bind(&done); 6484 __ bind(&done);
6543 } 6485 }
6544 6486
6545 6487
6546 #undef __ 6488 #undef __
6547 6489
6548 } } // namespace v8::internal 6490 } } // namespace v8::internal
6549 6491
6550 #endif // V8_TARGET_ARCH_IA32 6492 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/lithium-codegen-ia32.h ('k') | src/ia32/lithium-gap-resolver-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698