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

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

Issue 148573005: A64: Synchronize with r16249. (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.h » ('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 30 matching lines...) Expand all
41 41
42 42
43 static SaveFPRegsMode GetSaveFPRegsMode() { 43 static SaveFPRegsMode GetSaveFPRegsMode() {
44 // We don't need to save floating point regs when generating the snapshot 44 // We don't need to save floating point regs when generating the snapshot
45 return CpuFeatures::IsSafeForSnapshot(SSE2) ? kSaveFPRegs : kDontSaveFPRegs; 45 return CpuFeatures::IsSafeForSnapshot(SSE2) ? kSaveFPRegs : kDontSaveFPRegs;
46 } 46 }
47 47
48 48
49 // When invoking builtins, we need to record the safepoint in the middle of 49 // When invoking builtins, we need to record the safepoint in the middle of
50 // the invoke instruction sequence generated by the macro assembler. 50 // the invoke instruction sequence generated by the macro assembler.
51 class SafepointGenerator : public CallWrapper { 51 class SafepointGenerator V8_FINAL : public CallWrapper {
52 public: 52 public:
53 SafepointGenerator(LCodeGen* codegen, 53 SafepointGenerator(LCodeGen* codegen,
54 LPointerMap* pointers, 54 LPointerMap* pointers,
55 Safepoint::DeoptMode mode) 55 Safepoint::DeoptMode mode)
56 : codegen_(codegen), 56 : codegen_(codegen),
57 pointers_(pointers), 57 pointers_(pointers),
58 deopt_mode_(mode) {} 58 deopt_mode_(mode) {}
59 virtual ~SafepointGenerator() { } 59 virtual ~SafepointGenerator() {}
60 60
61 virtual void BeforeCall(int call_size) const {} 61 virtual void BeforeCall(int call_size) const V8_OVERRIDE {}
62 62
63 virtual void AfterCall() const { 63 virtual void AfterCall() const V8_OVERRIDE {
64 codegen_->RecordSafepoint(pointers_, deopt_mode_); 64 codegen_->RecordSafepoint(pointers_, deopt_mode_);
65 } 65 }
66 66
67 private: 67 private:
68 LCodeGen* codegen_; 68 LCodeGen* codegen_;
69 LPointerMap* pointers_; 69 LPointerMap* pointers_;
70 Safepoint::DeoptMode deopt_mode_; 70 Safepoint::DeoptMode deopt_mode_;
71 }; 71 };
72 72
73 73
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after
352 instr->hydrogen_value()->id(), 352 instr->hydrogen_value()->id(),
353 instr->Mnemonic()); 353 instr->Mnemonic());
354 } 354 }
355 355
356 if (!CpuFeatures::IsSupported(SSE2)) FlushX87StackIfNecessary(instr); 356 if (!CpuFeatures::IsSupported(SSE2)) FlushX87StackIfNecessary(instr);
357 357
358 RecordAndUpdatePosition(instr->position()); 358 RecordAndUpdatePosition(instr->position());
359 359
360 instr->CompileToNative(this); 360 instr->CompileToNative(this);
361 361
362 if (!CpuFeatures::IsSupported(SSE2)) { 362 if (!CpuFeatures::IsSupported(SSE2) &&
363 if (FLAG_debug_code && FLAG_enable_slow_asserts) { 363 FLAG_debug_code && FLAG_enable_slow_asserts) {
364 __ VerifyX87StackDepth(x87_stack_depth_); 364 __ VerifyX87StackDepth(x87_stack_.depth());
365 }
366 } 365 }
367 } 366 }
368 EnsureSpaceForLazyDeopt(); 367 EnsureSpaceForLazyDeopt();
369 return !is_aborted(); 368 return !is_aborted();
370 } 369 }
371 370
372 371
373 bool LCodeGen::GenerateJumpTable() { 372 bool LCodeGen::GenerateJumpTable() {
374 Label needs_frame; 373 Label needs_frame;
375 if (jump_table_.length() > 0) { 374 if (jump_table_.length() > 0) {
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
490 return X87Register::FromAllocationIndex(index); 489 return X87Register::FromAllocationIndex(index);
491 } 490 }
492 491
493 492
494 XMMRegister LCodeGen::ToDoubleRegister(int index) const { 493 XMMRegister LCodeGen::ToDoubleRegister(int index) const {
495 return XMMRegister::FromAllocationIndex(index); 494 return XMMRegister::FromAllocationIndex(index);
496 } 495 }
497 496
498 497
499 void LCodeGen::X87LoadForUsage(X87Register reg) { 498 void LCodeGen::X87LoadForUsage(X87Register reg) {
500 ASSERT(X87StackContains(reg)); 499 ASSERT(x87_stack_.Contains(reg));
501 X87Fxch(reg); 500 x87_stack_.Fxch(reg);
502 x87_stack_depth_--; 501 x87_stack_.pop();
503 } 502 }
504 503
505 504
506 void LCodeGen::X87Fxch(X87Register reg, int other_slot) { 505 void LCodeGen::X87Stack::Fxch(X87Register reg, int other_slot) {
507 ASSERT(X87StackContains(reg) && x87_stack_depth_ > other_slot); 506 ASSERT(Contains(reg) && stack_depth_ > other_slot);
508 int i = X87ArrayIndex(reg); 507 int i = ArrayIndex(reg);
509 int st = x87_st2idx(i); 508 int st = st2idx(i);
510 if (st != other_slot) { 509 if (st != other_slot) {
511 int other_i = x87_st2idx(other_slot); 510 int other_i = st2idx(other_slot);
512 X87Register other = x87_stack_[other_i]; 511 X87Register other = stack_[other_i];
513 x87_stack_[other_i] = reg; 512 stack_[other_i] = reg;
514 x87_stack_[i] = other; 513 stack_[i] = other;
515 if (st == 0) { 514 if (st == 0) {
516 __ fxch(other_slot); 515 __ fxch(other_slot);
517 } else if (other_slot == 0) { 516 } else if (other_slot == 0) {
518 __ fxch(st); 517 __ fxch(st);
519 } else { 518 } else {
520 __ fxch(st); 519 __ fxch(st);
521 __ fxch(other_slot); 520 __ fxch(other_slot);
522 __ fxch(st); 521 __ fxch(st);
523 } 522 }
524 } 523 }
525 } 524 }
526 525
527 526
528 int LCodeGen::x87_st2idx(int pos) { 527 int LCodeGen::X87Stack::st2idx(int pos) {
529 return x87_stack_depth_ - pos - 1; 528 return stack_depth_ - pos - 1;
530 } 529 }
531 530
532 531
533 int LCodeGen::X87ArrayIndex(X87Register reg) { 532 int LCodeGen::X87Stack::ArrayIndex(X87Register reg) {
534 for (int i = 0; i < x87_stack_depth_; i++) { 533 for (int i = 0; i < stack_depth_; i++) {
535 if (x87_stack_[i].is(reg)) return i; 534 if (stack_[i].is(reg)) return i;
536 } 535 }
537 UNREACHABLE(); 536 UNREACHABLE();
538 return -1; 537 return -1;
539 } 538 }
540 539
541 540
542 bool LCodeGen::X87StackContains(X87Register reg) { 541 bool LCodeGen::X87Stack::Contains(X87Register reg) {
543 for (int i = 0; i < x87_stack_depth_; i++) { 542 for (int i = 0; i < stack_depth_; i++) {
544 if (x87_stack_[i].is(reg)) return true; 543 if (stack_[i].is(reg)) return true;
545 } 544 }
546 return false; 545 return false;
547 } 546 }
548 547
549 548
550 void LCodeGen::X87Free(X87Register reg) { 549 void LCodeGen::X87Stack::Free(X87Register reg) {
551 ASSERT(X87StackContains(reg)); 550 ASSERT(Contains(reg));
552 int i = X87ArrayIndex(reg); 551 int i = ArrayIndex(reg);
553 int st = x87_st2idx(i); 552 int st = st2idx(i);
554 if (st > 0) { 553 if (st > 0) {
555 // keep track of how fstp(i) changes the order of elements 554 // keep track of how fstp(i) changes the order of elements
556 int tos_i = x87_st2idx(0); 555 int tos_i = st2idx(0);
557 x87_stack_[i] = x87_stack_[tos_i]; 556 stack_[i] = stack_[tos_i];
558 } 557 }
559 x87_stack_depth_--; 558 pop();
560 __ fstp(st); 559 __ fstp(st);
561 } 560 }
562 561
563 562
564 void LCodeGen::X87Mov(X87Register dst, Operand src, X87OperandType opts) { 563 void LCodeGen::X87Mov(X87Register dst, Operand src, X87OperandType opts) {
565 if (X87StackContains(dst)) { 564 if (x87_stack_.Contains(dst)) {
566 X87Fxch(dst); 565 x87_stack_.Fxch(dst);
567 __ fstp(0); 566 __ fstp(0);
568 } else { 567 } else {
569 ASSERT(x87_stack_depth_ < X87Register::kNumAllocatableRegisters); 568 x87_stack_.push(dst);
570 x87_stack_[x87_stack_depth_] = dst;
571 x87_stack_depth_++;
572 } 569 }
573 X87Fld(src, opts); 570 X87Fld(src, opts);
574 } 571 }
575 572
576 573
577 void LCodeGen::X87Fld(Operand src, X87OperandType opts) { 574 void LCodeGen::X87Fld(Operand src, X87OperandType opts) {
578 if (opts == kX87DoubleOperand) { 575 ASSERT(!src.is_reg_only());
579 __ fld_d(src); 576 switch (opts) {
580 } else if (opts == kX87FloatOperand) { 577 case kX87DoubleOperand:
581 __ fld_s(src); 578 __ fld_d(src);
582 } else if (opts == kX87IntOperand) { 579 break;
583 __ fild_s(src); 580 case kX87FloatOperand:
584 } else { 581 __ fld_s(src);
585 UNREACHABLE(); 582 break;
583 case kX87IntOperand:
584 __ fild_s(src);
585 break;
586 default:
587 UNREACHABLE();
586 } 588 }
587 } 589 }
588 590
589 591
590 void LCodeGen::X87Mov(Operand dst, X87Register src) { 592 void LCodeGen::X87Mov(Operand dst, X87Register src, X87OperandType opts) {
591 X87Fxch(src); 593 ASSERT(!dst.is_reg_only());
592 __ fst_d(dst); 594 x87_stack_.Fxch(src);
595 switch (opts) {
596 case kX87DoubleOperand:
597 __ fst_d(dst);
598 break;
599 case kX87IntOperand:
600 __ fist_s(dst);
601 break;
602 default:
603 UNREACHABLE();
604 }
593 } 605 }
594 606
595 607
596 void LCodeGen::X87PrepareToWrite(X87Register reg) { 608 void LCodeGen::X87Stack::PrepareToWrite(X87Register reg) {
597 if (X87StackContains(reg)) { 609 if (Contains(reg)) {
598 X87Free(reg); 610 Free(reg);
599 } 611 }
600 // Mark this register as the next register to write to 612 // Mark this register as the next register to write to
601 x87_stack_[x87_stack_depth_] = reg; 613 stack_[stack_depth_] = reg;
602 } 614 }
603 615
604 616
605 void LCodeGen::X87CommitWrite(X87Register reg) { 617 void LCodeGen::X87Stack::CommitWrite(X87Register reg) {
606 // Assert the reg is prepared to write, but not on the virtual stack yet 618 // Assert the reg is prepared to write, but not on the virtual stack yet
607 ASSERT(!X87StackContains(reg) && x87_stack_[x87_stack_depth_].is(reg) && 619 ASSERT(!Contains(reg) && stack_[stack_depth_].is(reg) &&
608 x87_stack_depth_ < X87Register::kNumAllocatableRegisters); 620 stack_depth_ < X87Register::kNumAllocatableRegisters);
609 x87_stack_depth_++; 621 stack_depth_++;
610 } 622 }
611 623
612 624
613 void LCodeGen::X87PrepareBinaryOp( 625 void LCodeGen::X87PrepareBinaryOp(
614 X87Register left, X87Register right, X87Register result) { 626 X87Register left, X87Register right, X87Register result) {
615 // You need to use DefineSameAsFirst for x87 instructions 627 // You need to use DefineSameAsFirst for x87 instructions
616 ASSERT(result.is(left)); 628 ASSERT(result.is(left));
617 X87Fxch(right, 1); 629 x87_stack_.Fxch(right, 1);
618 X87Fxch(left); 630 x87_stack_.Fxch(left);
619 } 631 }
620 632
621 633
622 void LCodeGen::FlushX87StackIfNecessary(LInstruction* instr) { 634 void LCodeGen::X87Stack::FlushIfNecessary(LInstruction* instr, LCodeGen* cgen) {
623 if (x87_stack_depth_ > 0 && instr->ClobbersDoubleRegisters()) { 635 if (stack_depth_ > 0 && instr->ClobbersDoubleRegisters()) {
624 bool double_inputs = instr->HasDoubleRegisterInput(); 636 bool double_inputs = instr->HasDoubleRegisterInput();
625 637
626 // Flush stack from tos down, since FreeX87() will mess with tos 638 // Flush stack from tos down, since FreeX87() will mess with tos
627 for (int i = x87_stack_depth_-1; i >= 0; i--) { 639 for (int i = stack_depth_-1; i >= 0; i--) {
628 X87Register reg = x87_stack_[i]; 640 X87Register reg = stack_[i];
629 // Skip registers which contain the inputs for the next instruction 641 // Skip registers which contain the inputs for the next instruction
630 // when flushing the stack 642 // when flushing the stack
631 if (double_inputs && instr->IsDoubleInput(reg, this)) { 643 if (double_inputs && instr->IsDoubleInput(reg, cgen)) {
632 continue; 644 continue;
633 } 645 }
634 X87Free(reg); 646 Free(reg);
635 if (i < x87_stack_depth_-1) i++; 647 if (i < stack_depth_-1) i++;
636 } 648 }
637 } 649 }
638 if (instr->IsReturn()) { 650 if (instr->IsReturn()) {
639 while (x87_stack_depth_ > 0) { 651 while (stack_depth_ > 0) {
640 __ fstp(0); 652 __ fstp(0);
641 x87_stack_depth_--; 653 stack_depth_--;
642 } 654 }
643 } 655 }
644 } 656 }
645 657
646 658
647 void LCodeGen::EmitFlushX87ForDeopt() { 659 void LCodeGen::EmitFlushX87ForDeopt() {
648 for (int i = 0; i < x87_stack_depth_; i++) __ fstp(0); 660 // The deoptimizer does not support X87 Registers. But as long as we
661 // deopt from a stub its not a problem, since we will re-materialize the
662 // original stub inputs, which can't be double registers.
663 ASSERT(info()->IsStub());
664 if (FLAG_debug_code && FLAG_enable_slow_asserts) {
665 __ pushfd();
666 __ VerifyX87StackDepth(x87_stack_.depth());
667 __ popfd();
668 }
669 for (int i = 0; i < x87_stack_.depth(); i++) __ fstp(0);
649 } 670 }
650 671
651 672
652 Register LCodeGen::ToRegister(LOperand* op) const { 673 Register LCodeGen::ToRegister(LOperand* op) const {
653 ASSERT(op->IsRegister()); 674 ASSERT(op->IsRegister());
654 return ToRegister(op->index()); 675 return ToRegister(op->index());
655 } 676 }
656 677
657 678
658 X87Register LCodeGen::ToX87Register(LOperand* op) const { 679 X87Register LCodeGen::ToX87Register(LOperand* op) const {
(...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after
996 __ bind(&no_deopt); 1017 __ bind(&no_deopt);
997 __ mov(Operand::StaticVariable(count), eax); 1018 __ mov(Operand::StaticVariable(count), eax);
998 __ pop(eax); 1019 __ pop(eax);
999 __ popfd(); 1020 __ popfd();
1000 } 1021 }
1001 1022
1002 // Before Instructions which can deopt, we normally flush the x87 stack. But 1023 // Before Instructions which can deopt, we normally flush the x87 stack. But
1003 // we can have inputs or outputs of the current instruction on the stack, 1024 // we can have inputs or outputs of the current instruction on the stack,
1004 // thus we need to flush them here from the physical stack to leave it in a 1025 // thus we need to flush them here from the physical stack to leave it in a
1005 // consistent state. 1026 // consistent state.
1006 if (x87_stack_depth_ > 0) { 1027 if (x87_stack_.depth() > 0) {
1007 Label done; 1028 Label done;
1008 if (cc != no_condition) __ j(NegateCondition(cc), &done, Label::kNear); 1029 if (cc != no_condition) __ j(NegateCondition(cc), &done, Label::kNear);
1009 EmitFlushX87ForDeopt(); 1030 EmitFlushX87ForDeopt();
1010 __ bind(&done); 1031 __ bind(&done);
1011 } 1032 }
1012 1033
1013 if (info()->ShouldTrapOnDeopt()) { 1034 if (info()->ShouldTrapOnDeopt()) {
1014 Label done; 1035 Label done;
1015 if (cc != no_condition) __ j(NegateCondition(cc), &done, Label::kNear); 1036 if (cc != no_condition) __ j(NegateCondition(cc), &done, Label::kNear);
1016 __ int3(); 1037 __ int3();
(...skipping 417 matching lines...) Expand 10 before | Expand all | Expand 10 after
1434 power = WhichPowerOf2(-divisor); 1455 power = WhichPowerOf2(-divisor);
1435 } 1456 }
1436 1457
1437 if (test_value != 0) { 1458 if (test_value != 0) {
1438 if (instr->hydrogen()->CheckFlag( 1459 if (instr->hydrogen()->CheckFlag(
1439 HInstruction::kAllUsesTruncatingToInt32)) { 1460 HInstruction::kAllUsesTruncatingToInt32)) {
1440 Label done, negative; 1461 Label done, negative;
1441 __ cmp(dividend, 0); 1462 __ cmp(dividend, 0);
1442 __ j(less, &negative, Label::kNear); 1463 __ j(less, &negative, Label::kNear);
1443 __ sar(dividend, power); 1464 __ sar(dividend, power);
1465 if (divisor < 0) __ neg(dividend);
1444 __ jmp(&done, Label::kNear); 1466 __ jmp(&done, Label::kNear);
1445 1467
1446 __ bind(&negative); 1468 __ bind(&negative);
1447 __ neg(dividend); 1469 __ neg(dividend);
1448 __ sar(dividend, power); 1470 __ sar(dividend, power);
1449 if (divisor > 0) __ neg(dividend); 1471 if (divisor > 0) __ neg(dividend);
1450 __ bind(&done); 1472 __ bind(&done);
1451 return; // Don't fall through to "__ neg" below. 1473 return; // Don't fall through to "__ neg" below.
1452 } else { 1474 } else {
1453 // Deoptimize if remainder is not 0. 1475 // Deoptimize if remainder is not 0.
(...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after
1858 void LCodeGen::DoConstantS(LConstantS* instr) { 1880 void LCodeGen::DoConstantS(LConstantS* instr) {
1859 __ Set(ToRegister(instr->result()), Immediate(instr->value())); 1881 __ Set(ToRegister(instr->result()), Immediate(instr->value()));
1860 } 1882 }
1861 1883
1862 1884
1863 void LCodeGen::DoConstantD(LConstantD* instr) { 1885 void LCodeGen::DoConstantD(LConstantD* instr) {
1864 double v = instr->value(); 1886 double v = instr->value();
1865 uint64_t int_val = BitCast<uint64_t, double>(v); 1887 uint64_t int_val = BitCast<uint64_t, double>(v);
1866 int32_t lower = static_cast<int32_t>(int_val); 1888 int32_t lower = static_cast<int32_t>(int_val);
1867 int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt)); 1889 int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt));
1890 ASSERT(instr->result()->IsDoubleRegister());
1868 1891
1869 if (!CpuFeatures::IsSafeForSnapshot(SSE2)) { 1892 if (!CpuFeatures::IsSafeForSnapshot(SSE2)) {
1870 __ push(Immediate(upper)); 1893 __ push(Immediate(upper));
1871 __ push(Immediate(lower)); 1894 __ push(Immediate(lower));
1872 X87Mov(ToX87Register(instr->result()), Operand(esp, 0)); 1895 X87Register reg = ToX87Register(instr->result());
1896 X87Mov(reg, Operand(esp, 0));
1873 __ add(Operand(esp), Immediate(kDoubleSize)); 1897 __ add(Operand(esp), Immediate(kDoubleSize));
1874 } else { 1898 } else {
1875 CpuFeatureScope scope1(masm(), SSE2); 1899 CpuFeatureScope scope1(masm(), SSE2);
1876 ASSERT(instr->result()->IsDoubleRegister());
1877 XMMRegister res = ToDoubleRegister(instr->result()); 1900 XMMRegister res = ToDoubleRegister(instr->result());
1878 if (int_val == 0) { 1901 if (int_val == 0) {
1879 __ xorps(res, res); 1902 __ xorps(res, res);
1880 } else { 1903 } else {
1881 Register temp = ToRegister(instr->temp()); 1904 Register temp = ToRegister(instr->temp());
1882 if (CpuFeatures::IsSupported(SSE4_1)) { 1905 if (CpuFeatures::IsSupported(SSE4_1)) {
1883 CpuFeatureScope scope2(masm(), SSE4_1); 1906 CpuFeatureScope scope2(masm(), SSE4_1);
1884 if (lower != 0) { 1907 if (lower != 0) {
1885 __ Set(temp, Immediate(lower)); 1908 __ Set(temp, Immediate(lower));
1886 __ movd(res, Operand(temp)); 1909 __ movd(res, Operand(temp));
(...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after
2226 __ j(NegateCondition(cc), chunk_->GetAssemblyLabel(right_block)); 2249 __ j(NegateCondition(cc), chunk_->GetAssemblyLabel(right_block));
2227 } else if (right_block == next_block) { 2250 } else if (right_block == next_block) {
2228 __ j(cc, chunk_->GetAssemblyLabel(left_block)); 2251 __ j(cc, chunk_->GetAssemblyLabel(left_block));
2229 } else { 2252 } else {
2230 __ j(cc, chunk_->GetAssemblyLabel(left_block)); 2253 __ j(cc, chunk_->GetAssemblyLabel(left_block));
2231 __ jmp(chunk_->GetAssemblyLabel(right_block)); 2254 __ jmp(chunk_->GetAssemblyLabel(right_block));
2232 } 2255 }
2233 } 2256 }
2234 2257
2235 2258
2259 template<class InstrType>
2260 void LCodeGen::EmitFalseBranch(InstrType instr, Condition cc) {
2261 int false_block = instr->FalseDestination(chunk_);
2262 if (cc == no_condition) {
2263 __ jmp(chunk_->GetAssemblyLabel(false_block));
2264 } else {
2265 __ j(cc, chunk_->GetAssemblyLabel(false_block));
2266 }
2267 }
2268
2269
2236 void LCodeGen::DoIsNumberAndBranch(LIsNumberAndBranch* instr) { 2270 void LCodeGen::DoIsNumberAndBranch(LIsNumberAndBranch* instr) {
2237 Representation r = instr->hydrogen()->value()->representation(); 2271 Representation r = instr->hydrogen()->value()->representation();
2238 if (r.IsSmiOrInteger32() || r.IsDouble()) { 2272 if (r.IsSmiOrInteger32() || r.IsDouble()) {
2239 EmitBranch(instr, no_condition); 2273 EmitBranch(instr, no_condition);
2240 } else { 2274 } else {
2241 ASSERT(r.IsTagged()); 2275 ASSERT(r.IsTagged());
2242 Register reg = ToRegister(instr->value()); 2276 Register reg = ToRegister(instr->value());
2243 HType type = instr->hydrogen()->value()->type(); 2277 HType type = instr->hydrogen()->value()->type();
2244 if (type.IsTaggedNumber()) { 2278 if (type.IsTaggedNumber()) {
2245 EmitBranch(instr, no_condition); 2279 EmitBranch(instr, no_condition);
2246 } 2280 }
2247 __ JumpIfSmi(reg, instr->TrueLabel(chunk_)); 2281 __ JumpIfSmi(reg, instr->TrueLabel(chunk_));
2248 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), 2282 __ cmp(FieldOperand(reg, HeapObject::kMapOffset),
2249 factory()->heap_number_map()); 2283 factory()->heap_number_map());
2250 EmitBranch(instr, equal); 2284 EmitBranch(instr, equal);
2251 } 2285 }
2252 } 2286 }
2253 2287
2254 2288
2255 void LCodeGen::DoBranch(LBranch* instr) { 2289 void LCodeGen::DoBranch(LBranch* instr) {
2256 Representation r = instr->hydrogen()->value()->representation(); 2290 Representation r = instr->hydrogen()->value()->representation();
2257 if (r.IsSmiOrInteger32()) { 2291 if (r.IsSmiOrInteger32()) {
2258 ASSERT(!info()->IsStub());
2259 Register reg = ToRegister(instr->value()); 2292 Register reg = ToRegister(instr->value());
2260 __ test(reg, Operand(reg)); 2293 __ test(reg, Operand(reg));
2261 EmitBranch(instr, not_zero); 2294 EmitBranch(instr, not_zero);
2262 } else if (r.IsDouble()) { 2295 } else if (r.IsDouble()) {
2263 ASSERT(!info()->IsStub()); 2296 ASSERT(!info()->IsStub());
2264 CpuFeatureScope scope(masm(), SSE2); 2297 CpuFeatureScope scope(masm(), SSE2);
2265 XMMRegister reg = ToDoubleRegister(instr->value()); 2298 XMMRegister reg = ToDoubleRegister(instr->value());
2266 __ xorps(xmm0, xmm0); 2299 __ xorps(xmm0, xmm0);
2267 __ ucomisd(reg, xmm0); 2300 __ ucomisd(reg, xmm0);
2268 EmitBranch(instr, not_equal); 2301 EmitBranch(instr, not_equal);
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
2476 Handle<Object> right = ToHandle(LConstantOperand::cast(instr->right())); 2509 Handle<Object> right = ToHandle(LConstantOperand::cast(instr->right()));
2477 __ CmpObject(left, right); 2510 __ CmpObject(left, right);
2478 } else { 2511 } else {
2479 Operand right = ToOperand(instr->right()); 2512 Operand right = ToOperand(instr->right());
2480 __ cmp(left, right); 2513 __ cmp(left, right);
2481 } 2514 }
2482 EmitBranch(instr, equal); 2515 EmitBranch(instr, equal);
2483 } 2516 }
2484 2517
2485 2518
2519 void LCodeGen::DoCmpHoleAndBranch(LCmpHoleAndBranch* instr) {
2520 if (instr->hydrogen()->representation().IsTagged()) {
2521 Register input_reg = ToRegister(instr->object());
2522 __ cmp(input_reg, factory()->the_hole_value());
2523 EmitBranch(instr, equal);
2524 return;
2525 }
2526
2527 bool use_sse2 = CpuFeatures::IsSupported(SSE2);
2528 if (use_sse2) {
2529 CpuFeatureScope scope(masm(), SSE2);
2530 XMMRegister input_reg = ToDoubleRegister(instr->object());
2531 __ ucomisd(input_reg, input_reg);
2532 EmitFalseBranch(instr, parity_odd);
2533 } else {
2534 // Put the value to the top of stack
2535 X87Register src = ToX87Register(instr->object());
2536 X87LoadForUsage(src);
2537 __ fld(0);
2538 __ fld(0);
2539 __ FCmp();
2540 Label ok;
2541 __ j(parity_even, &ok);
2542 __ fstp(0);
2543 EmitFalseBranch(instr, no_condition);
2544 __ bind(&ok);
2545 }
2546
2547
2548 __ sub(esp, Immediate(kDoubleSize));
2549 if (use_sse2) {
2550 CpuFeatureScope scope(masm(), SSE2);
2551 XMMRegister input_reg = ToDoubleRegister(instr->object());
2552 __ movdbl(MemOperand(esp, 0), input_reg);
2553 } else {
2554 __ fstp_d(MemOperand(esp, 0));
2555 }
2556
2557 __ add(esp, Immediate(kDoubleSize));
2558 int offset = sizeof(kHoleNanUpper32);
2559 __ cmp(MemOperand(esp, -offset), Immediate(kHoleNanUpper32));
2560 EmitBranch(instr, equal);
2561 }
2562
2563
2486 Condition LCodeGen::EmitIsObject(Register input, 2564 Condition LCodeGen::EmitIsObject(Register input,
2487 Register temp1, 2565 Register temp1,
2488 Label* is_not_object, 2566 Label* is_not_object,
2489 Label* is_object) { 2567 Label* is_object) {
2490 __ JumpIfSmi(input, is_not_object); 2568 __ JumpIfSmi(input, is_not_object);
2491 2569
2492 __ cmp(input, isolate()->factory()->null_value()); 2570 __ cmp(input, isolate()->factory()->null_value());
2493 __ j(equal, is_object); 2571 __ j(equal, is_object);
2494 2572
2495 __ mov(temp1, FieldOperand(input, HeapObject::kMapOffset)); 2573 __ mov(temp1, FieldOperand(input, HeapObject::kMapOffset));
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after
2753 __ j(zero, &true_value, Label::kNear); 2831 __ j(zero, &true_value, Label::kNear);
2754 __ mov(ToRegister(instr->result()), factory()->false_value()); 2832 __ mov(ToRegister(instr->result()), factory()->false_value());
2755 __ jmp(&done, Label::kNear); 2833 __ jmp(&done, Label::kNear);
2756 __ bind(&true_value); 2834 __ bind(&true_value);
2757 __ mov(ToRegister(instr->result()), factory()->true_value()); 2835 __ mov(ToRegister(instr->result()), factory()->true_value());
2758 __ bind(&done); 2836 __ bind(&done);
2759 } 2837 }
2760 2838
2761 2839
2762 void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { 2840 void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) {
2763 class DeferredInstanceOfKnownGlobal: public LDeferredCode { 2841 class DeferredInstanceOfKnownGlobal V8_FINAL : public LDeferredCode {
2764 public: 2842 public:
2765 DeferredInstanceOfKnownGlobal(LCodeGen* codegen, 2843 DeferredInstanceOfKnownGlobal(LCodeGen* codegen,
2766 LInstanceOfKnownGlobal* instr) 2844 LInstanceOfKnownGlobal* instr)
2767 : LDeferredCode(codegen), instr_(instr) { } 2845 : LDeferredCode(codegen), instr_(instr) { }
2768 virtual void Generate() { 2846 virtual void Generate() V8_OVERRIDE {
2769 codegen()->DoDeferredInstanceOfKnownGlobal(instr_, &map_check_); 2847 codegen()->DoDeferredInstanceOfKnownGlobal(instr_, &map_check_);
2770 } 2848 }
2771 virtual LInstruction* instr() { return instr_; } 2849 virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
2772 Label* map_check() { return &map_check_; } 2850 Label* map_check() { return &map_check_; }
2773 private: 2851 private:
2774 LInstanceOfKnownGlobal* instr_; 2852 LInstanceOfKnownGlobal* instr_;
2775 Label map_check_; 2853 Label map_check_;
2776 }; 2854 };
2777 2855
2778 DeferredInstanceOfKnownGlobal* deferred; 2856 DeferredInstanceOfKnownGlobal* deferred;
2779 deferred = new(zone()) DeferredInstanceOfKnownGlobal(this, instr); 2857 deferred = new(zone()) DeferredInstanceOfKnownGlobal(this, instr);
2780 2858
2781 Label done, false_result; 2859 Label done, false_result;
(...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after
3115 Register result = ToRegister(instr->result()); 3193 Register result = ToRegister(instr->result());
3116 if (access.IsInobject()) { 3194 if (access.IsInobject()) {
3117 __ mov(result, FieldOperand(object, offset)); 3195 __ mov(result, FieldOperand(object, offset));
3118 } else { 3196 } else {
3119 __ mov(result, FieldOperand(object, JSObject::kPropertiesOffset)); 3197 __ mov(result, FieldOperand(object, JSObject::kPropertiesOffset));
3120 __ mov(result, FieldOperand(result, offset)); 3198 __ mov(result, FieldOperand(result, offset));
3121 } 3199 }
3122 } 3200 }
3123 3201
3124 3202
3125 void LCodeGen::EmitLoadFieldOrConstant(Register result,
3126 Register object,
3127 Handle<Map> type,
3128 Handle<String> name,
3129 LEnvironment* env) {
3130 LookupResult lookup(isolate());
3131 type->LookupDescriptor(NULL, *name, &lookup);
3132 ASSERT(lookup.IsFound() || lookup.IsCacheable());
3133 if (lookup.IsField()) {
3134 int index = lookup.GetLocalFieldIndexFromMap(*type);
3135 int offset = index * kPointerSize;
3136 if (index < 0) {
3137 // Negative property indices are in-object properties, indexed
3138 // from the end of the fixed part of the object.
3139 __ mov(result, FieldOperand(object, offset + type->instance_size()));
3140 } else {
3141 // Non-negative property indices are in the properties array.
3142 __ mov(result, FieldOperand(object, JSObject::kPropertiesOffset));
3143 __ mov(result, FieldOperand(result, offset + FixedArray::kHeaderSize));
3144 }
3145 } else if (lookup.IsConstant()) {
3146 Handle<Object> constant(lookup.GetConstantFromMap(*type), isolate());
3147 __ LoadObject(result, constant);
3148 } else {
3149 // Negative lookup.
3150 // Check prototypes.
3151 Handle<HeapObject> current(HeapObject::cast((*type)->prototype()));
3152 Heap* heap = type->GetHeap();
3153 while (*current != heap->null_value()) {
3154 __ LoadHeapObject(result, current);
3155 __ cmp(FieldOperand(result, HeapObject::kMapOffset),
3156 Handle<Map>(current->map()));
3157 DeoptimizeIf(not_equal, env);
3158 current =
3159 Handle<HeapObject>(HeapObject::cast(current->map()->prototype()));
3160 }
3161 __ mov(result, factory()->undefined_value());
3162 }
3163 }
3164
3165
3166 void LCodeGen::EmitPushTaggedOperand(LOperand* operand) { 3203 void LCodeGen::EmitPushTaggedOperand(LOperand* operand) {
3167 ASSERT(!operand->IsDoubleRegister()); 3204 ASSERT(!operand->IsDoubleRegister());
3168 if (operand->IsConstantOperand()) { 3205 if (operand->IsConstantOperand()) {
3169 Handle<Object> object = ToHandle(LConstantOperand::cast(operand)); 3206 Handle<Object> object = ToHandle(LConstantOperand::cast(operand));
3170 AllowDeferredHandleDereference smi_check; 3207 AllowDeferredHandleDereference smi_check;
3171 if (object->IsSmi()) { 3208 if (object->IsSmi()) {
3172 __ Push(Handle<Smi>::cast(object)); 3209 __ Push(Handle<Smi>::cast(object));
3173 } else { 3210 } else {
3174 __ PushHeapObject(Handle<HeapObject>::cast(object)); 3211 __ PushHeapObject(Handle<HeapObject>::cast(object));
3175 } 3212 }
3176 } else if (operand->IsRegister()) { 3213 } else if (operand->IsRegister()) {
3177 __ push(ToRegister(operand)); 3214 __ push(ToRegister(operand));
3178 } else { 3215 } else {
3179 __ push(ToOperand(operand)); 3216 __ push(ToOperand(operand));
3180 } 3217 }
3181 } 3218 }
3182 3219
3183 3220
3184 // Check for cases where EmitLoadFieldOrConstantFunction needs to walk the
3185 // prototype chain, which causes unbounded code generation.
3186 static bool CompactEmit(SmallMapList* list,
3187 Handle<String> name,
3188 int i,
3189 Isolate* isolate) {
3190 Handle<Map> map = list->at(i);
3191 LookupResult lookup(isolate);
3192 map->LookupDescriptor(NULL, *name, &lookup);
3193 return lookup.IsField() || lookup.IsConstant();
3194 }
3195
3196
3197 void LCodeGen::DoLoadNamedFieldPolymorphic(LLoadNamedFieldPolymorphic* instr) {
3198 Register object = ToRegister(instr->object());
3199 Register result = ToRegister(instr->result());
3200
3201 int map_count = instr->hydrogen()->types()->length();
3202 bool need_generic = instr->hydrogen()->need_generic();
3203
3204 if (map_count == 0 && !need_generic) {
3205 DeoptimizeIf(no_condition, instr->environment());
3206 return;
3207 }
3208 Handle<String> name = instr->hydrogen()->name();
3209 Label done;
3210 bool all_are_compact = true;
3211 for (int i = 0; i < map_count; ++i) {
3212 if (!CompactEmit(instr->hydrogen()->types(), name, i, isolate())) {
3213 all_are_compact = false;
3214 break;
3215 }
3216 }
3217 for (int i = 0; i < map_count; ++i) {
3218 bool last = (i == map_count - 1);
3219 Handle<Map> map = instr->hydrogen()->types()->at(i);
3220 Label check_passed;
3221 __ CompareMap(object, map, &check_passed);
3222 if (last && !need_generic) {
3223 DeoptimizeIf(not_equal, instr->environment());
3224 __ bind(&check_passed);
3225 EmitLoadFieldOrConstant(result, object, map, name, instr->environment());
3226 } else {
3227 Label next;
3228 bool compact = all_are_compact ? true :
3229 CompactEmit(instr->hydrogen()->types(), name, i, isolate());
3230 __ j(not_equal, &next, compact ? Label::kNear : Label::kFar);
3231 __ bind(&check_passed);
3232 EmitLoadFieldOrConstant(result, object, map, name, instr->environment());
3233 __ jmp(&done, all_are_compact ? Label::kNear : Label::kFar);
3234 __ bind(&next);
3235 }
3236 }
3237 if (need_generic) {
3238 __ mov(ecx, name);
3239 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
3240 CallCode(ic, RelocInfo::CODE_TARGET, instr);
3241 }
3242 __ bind(&done);
3243 }
3244
3245
3246 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { 3221 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) {
3247 ASSERT(ToRegister(instr->context()).is(esi)); 3222 ASSERT(ToRegister(instr->context()).is(esi));
3248 ASSERT(ToRegister(instr->object()).is(edx)); 3223 ASSERT(ToRegister(instr->object()).is(edx));
3249 ASSERT(ToRegister(instr->result()).is(eax)); 3224 ASSERT(ToRegister(instr->result()).is(eax));
3250 3225
3251 __ mov(ecx, instr->name()); 3226 __ mov(ecx, instr->name());
3252 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); 3227 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
3253 CallCode(ic, RelocInfo::CODE_TARGET, instr); 3228 CallCode(ic, RelocInfo::CODE_TARGET, instr);
3254 } 3229 }
3255 3230
(...skipping 568 matching lines...) Expand 10 before | Expand all | Expand 10 after
3824 Label is_positive; 3799 Label is_positive;
3825 __ j(not_sign, &is_positive, Label::kNear); 3800 __ j(not_sign, &is_positive, Label::kNear);
3826 __ neg(input_reg); // Sets flags. 3801 __ neg(input_reg); // Sets flags.
3827 DeoptimizeIf(negative, instr->environment()); 3802 DeoptimizeIf(negative, instr->environment());
3828 __ bind(&is_positive); 3803 __ bind(&is_positive);
3829 } 3804 }
3830 3805
3831 3806
3832 void LCodeGen::DoMathAbs(LMathAbs* instr) { 3807 void LCodeGen::DoMathAbs(LMathAbs* instr) {
3833 // Class for deferred case. 3808 // Class for deferred case.
3834 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { 3809 class DeferredMathAbsTaggedHeapNumber V8_FINAL : public LDeferredCode {
3835 public: 3810 public:
3836 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, LMathAbs* instr) 3811 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, LMathAbs* instr)
3837 : LDeferredCode(codegen), instr_(instr) { } 3812 : LDeferredCode(codegen), instr_(instr) { }
3838 virtual void Generate() { 3813 virtual void Generate() V8_OVERRIDE {
3839 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); 3814 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_);
3840 } 3815 }
3841 virtual LInstruction* instr() { return instr_; } 3816 virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
3842 private: 3817 private:
3843 LMathAbs* instr_; 3818 LMathAbs* instr_;
3844 }; 3819 };
3845 3820
3846 ASSERT(instr->value()->Equals(instr->result())); 3821 ASSERT(instr->value()->Equals(instr->result()));
3847 Representation r = instr->hydrogen()->value()->representation(); 3822 Representation r = instr->hydrogen()->value()->representation();
3848 3823
3849 CpuFeatureScope scope(masm(), SSE2); 3824 CpuFeatureScope scope(masm(), SSE2);
3850 if (r.IsDouble()) { 3825 if (r.IsDouble()) {
3851 XMMRegister scratch = xmm0; 3826 XMMRegister scratch = xmm0;
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
4064 __ CallStub(&stub); 4039 __ CallStub(&stub);
4065 } else { 4040 } else {
4066 ASSERT(exponent_type.IsDouble()); 4041 ASSERT(exponent_type.IsDouble());
4067 MathPowStub stub(MathPowStub::DOUBLE); 4042 MathPowStub stub(MathPowStub::DOUBLE);
4068 __ CallStub(&stub); 4043 __ CallStub(&stub);
4069 } 4044 }
4070 } 4045 }
4071 4046
4072 4047
4073 void LCodeGen::DoRandom(LRandom* instr) { 4048 void LCodeGen::DoRandom(LRandom* instr) {
4074 class DeferredDoRandom: public LDeferredCode { 4049 class DeferredDoRandom V8_FINAL : public LDeferredCode {
4075 public: 4050 public:
4076 DeferredDoRandom(LCodeGen* codegen, LRandom* instr) 4051 DeferredDoRandom(LCodeGen* codegen, LRandom* instr)
4077 : LDeferredCode(codegen), instr_(instr) { } 4052 : LDeferredCode(codegen), instr_(instr) { }
4078 virtual void Generate() { codegen()->DoDeferredRandom(instr_); } 4053 virtual void Generate() V8_OVERRIDE { codegen()->DoDeferredRandom(instr_); }
4079 virtual LInstruction* instr() { return instr_; } 4054 virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
4080 private: 4055 private:
4081 LRandom* instr_; 4056 LRandom* instr_;
4082 }; 4057 };
4083 4058
4084 DeferredDoRandom* deferred = new(zone()) DeferredDoRandom(this, instr); 4059 DeferredDoRandom* deferred = new(zone()) DeferredDoRandom(this, instr);
4085 4060
4086 CpuFeatureScope scope(masm(), SSE2); 4061 CpuFeatureScope scope(masm(), SSE2);
4087 // Having marked this instruction as a call we can use any 4062 // Having marked this instruction as a call we can use any
4088 // registers. 4063 // registers.
4089 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); 4064 ASSERT(ToDoubleRegister(instr->result()).is(xmm1));
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
4188 XMMRegister result = ToDoubleRegister(instr->result()); 4163 XMMRegister result = ToDoubleRegister(instr->result());
4189 Register temp1 = ToRegister(instr->temp1()); 4164 Register temp1 = ToRegister(instr->temp1());
4190 Register temp2 = ToRegister(instr->temp2()); 4165 Register temp2 = ToRegister(instr->temp2());
4191 4166
4192 MathExpGenerator::EmitMathExp(masm(), input, result, xmm0, temp1, temp2); 4167 MathExpGenerator::EmitMathExp(masm(), input, result, xmm0, temp1, temp2);
4193 } 4168 }
4194 4169
4195 4170
4196 void LCodeGen::DoMathTan(LMathTan* instr) { 4171 void LCodeGen::DoMathTan(LMathTan* instr) {
4197 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); 4172 ASSERT(ToDoubleRegister(instr->result()).is(xmm1));
4173 // Set the context register to a GC-safe fake value. Clobbering it is
4174 // OK because this instruction is marked as a call.
4175 __ Set(esi, Immediate(0));
4198 TranscendentalCacheStub stub(TranscendentalCache::TAN, 4176 TranscendentalCacheStub stub(TranscendentalCache::TAN,
4199 TranscendentalCacheStub::UNTAGGED); 4177 TranscendentalCacheStub::UNTAGGED);
4200 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); 4178 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
4201 } 4179 }
4202 4180
4203 4181
4204 void LCodeGen::DoMathCos(LMathCos* instr) { 4182 void LCodeGen::DoMathCos(LMathCos* instr) {
4205 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); 4183 ASSERT(ToDoubleRegister(instr->result()).is(xmm1));
4184 // Set the context register to a GC-safe fake value. Clobbering it is
4185 // OK because this instruction is marked as a call.
4186 __ Set(esi, Immediate(0));
4206 TranscendentalCacheStub stub(TranscendentalCache::COS, 4187 TranscendentalCacheStub stub(TranscendentalCache::COS,
4207 TranscendentalCacheStub::UNTAGGED); 4188 TranscendentalCacheStub::UNTAGGED);
4208 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); 4189 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
4209 } 4190 }
4210 4191
4211 4192
4212 void LCodeGen::DoMathSin(LMathSin* instr) { 4193 void LCodeGen::DoMathSin(LMathSin* instr) {
4213 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); 4194 ASSERT(ToDoubleRegister(instr->result()).is(xmm1));
4195 // Set the context register to a GC-safe fake value. Clobbering it is
4196 // OK because this instruction is marked as a call.
4197 __ Set(esi, Immediate(0));
4214 TranscendentalCacheStub stub(TranscendentalCache::SIN, 4198 TranscendentalCacheStub stub(TranscendentalCache::SIN,
4215 TranscendentalCacheStub::UNTAGGED); 4199 TranscendentalCacheStub::UNTAGGED);
4216 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); 4200 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
4217 } 4201 }
4218 4202
4219 4203
4220 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { 4204 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) {
4221 ASSERT(ToRegister(instr->context()).is(esi)); 4205 ASSERT(ToRegister(instr->context()).is(esi));
4222 ASSERT(ToRegister(instr->function()).is(edi)); 4206 ASSERT(ToRegister(instr->function()).is(edi));
4223 ASSERT(instr->HasPointerMap()); 4207 ASSERT(instr->HasPointerMap());
(...skipping 566 matching lines...) Expand 10 before | Expand all | Expand 10 after
4790 TransitionElementsKindStub stub(from_kind, to_kind); 4774 TransitionElementsKindStub stub(from_kind, to_kind);
4791 __ CallStub(&stub); 4775 __ CallStub(&stub);
4792 RecordSafepointWithRegisters( 4776 RecordSafepointWithRegisters(
4793 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); 4777 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
4794 } 4778 }
4795 __ bind(&not_applicable); 4779 __ bind(&not_applicable);
4796 } 4780 }
4797 4781
4798 4782
4799 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { 4783 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) {
4800 class DeferredStringCharCodeAt: public LDeferredCode { 4784 class DeferredStringCharCodeAt V8_FINAL : public LDeferredCode {
4801 public: 4785 public:
4802 DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr) 4786 DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr)
4803 : LDeferredCode(codegen), instr_(instr) { } 4787 : LDeferredCode(codegen), instr_(instr) { }
4804 virtual void Generate() { codegen()->DoDeferredStringCharCodeAt(instr_); } 4788 virtual void Generate() V8_OVERRIDE {
4805 virtual LInstruction* instr() { return instr_; } 4789 codegen()->DoDeferredStringCharCodeAt(instr_);
4790 }
4791 virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
4806 private: 4792 private:
4807 LStringCharCodeAt* instr_; 4793 LStringCharCodeAt* instr_;
4808 }; 4794 };
4809 4795
4810 DeferredStringCharCodeAt* deferred = 4796 DeferredStringCharCodeAt* deferred =
4811 new(zone()) DeferredStringCharCodeAt(this, instr); 4797 new(zone()) DeferredStringCharCodeAt(this, instr);
4812 4798
4813 StringCharLoadGenerator::Generate(masm(), 4799 StringCharLoadGenerator::Generate(masm(),
4814 factory(), 4800 factory(),
4815 ToRegister(instr->string()), 4801 ToRegister(instr->string()),
(...skipping 29 matching lines...) Expand all
4845 } 4831 }
4846 CallRuntimeFromDeferred(Runtime::kStringCharCodeAt, 2, 4832 CallRuntimeFromDeferred(Runtime::kStringCharCodeAt, 2,
4847 instr, instr->context()); 4833 instr, instr->context());
4848 __ AssertSmi(eax); 4834 __ AssertSmi(eax);
4849 __ SmiUntag(eax); 4835 __ SmiUntag(eax);
4850 __ StoreToSafepointRegisterSlot(result, eax); 4836 __ StoreToSafepointRegisterSlot(result, eax);
4851 } 4837 }
4852 4838
4853 4839
4854 void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) { 4840 void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) {
4855 class DeferredStringCharFromCode: public LDeferredCode { 4841 class DeferredStringCharFromCode V8_FINAL : public LDeferredCode {
4856 public: 4842 public:
4857 DeferredStringCharFromCode(LCodeGen* codegen, LStringCharFromCode* instr) 4843 DeferredStringCharFromCode(LCodeGen* codegen, LStringCharFromCode* instr)
4858 : LDeferredCode(codegen), instr_(instr) { } 4844 : LDeferredCode(codegen), instr_(instr) { }
4859 virtual void Generate() { codegen()->DoDeferredStringCharFromCode(instr_); } 4845 virtual void Generate() V8_OVERRIDE {
4860 virtual LInstruction* instr() { return instr_; } 4846 codegen()->DoDeferredStringCharFromCode(instr_);
4847 }
4848 virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
4861 private: 4849 private:
4862 LStringCharFromCode* instr_; 4850 LStringCharFromCode* instr_;
4863 }; 4851 };
4864 4852
4865 DeferredStringCharFromCode* deferred = 4853 DeferredStringCharFromCode* deferred =
4866 new(zone()) DeferredStringCharFromCode(this, instr); 4854 new(zone()) DeferredStringCharFromCode(this, instr);
4867 4855
4868 ASSERT(instr->hydrogen()->value()->representation().IsInteger32()); 4856 ASSERT(instr->hydrogen()->value()->representation().IsInteger32());
4869 Register char_code = ToRegister(instr->char_code()); 4857 Register char_code = ToRegister(instr->char_code());
4870 Register result = ToRegister(instr->result()); 4858 Register result = ToRegister(instr->result());
(...skipping 30 matching lines...) Expand all
4901 4889
4902 void LCodeGen::DoStringAdd(LStringAdd* instr) { 4890 void LCodeGen::DoStringAdd(LStringAdd* instr) {
4903 EmitPushTaggedOperand(instr->left()); 4891 EmitPushTaggedOperand(instr->left());
4904 EmitPushTaggedOperand(instr->right()); 4892 EmitPushTaggedOperand(instr->right());
4905 StringAddStub stub(instr->hydrogen()->flags()); 4893 StringAddStub stub(instr->hydrogen()->flags());
4906 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); 4894 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
4907 } 4895 }
4908 4896
4909 4897
4910 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { 4898 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) {
4899 LOperand* input = instr->value();
4900 LOperand* output = instr->result();
4901 ASSERT(input->IsRegister() || input->IsStackSlot());
4902 ASSERT(output->IsDoubleRegister());
4911 if (CpuFeatures::IsSupported(SSE2)) { 4903 if (CpuFeatures::IsSupported(SSE2)) {
4912 CpuFeatureScope scope(masm(), SSE2); 4904 CpuFeatureScope scope(masm(), SSE2);
4913 LOperand* input = instr->value();
4914 ASSERT(input->IsRegister() || input->IsStackSlot());
4915 LOperand* output = instr->result();
4916 ASSERT(output->IsDoubleRegister());
4917 __ cvtsi2sd(ToDoubleRegister(output), ToOperand(input)); 4905 __ cvtsi2sd(ToDoubleRegister(output), ToOperand(input));
4906 } else if (input->IsRegister()) {
4907 Register input_reg = ToRegister(input);
4908 __ push(input_reg);
4909 X87Mov(ToX87Register(output), Operand(esp, 0), kX87IntOperand);
4910 __ pop(input_reg);
4918 } else { 4911 } else {
4919 UNREACHABLE(); 4912 X87Mov(ToX87Register(output), ToOperand(input), kX87IntOperand);
4920 } 4913 }
4921 } 4914 }
4922 4915
4923 4916
4924 void LCodeGen::DoInteger32ToSmi(LInteger32ToSmi* instr) { 4917 void LCodeGen::DoInteger32ToSmi(LInteger32ToSmi* instr) {
4925 Register input = ToRegister(instr->value()); 4918 Register input = ToRegister(instr->value());
4926 __ SmiTag(input); 4919 __ SmiTag(input);
4927 if (!instr->hydrogen()->value()->HasRange() || 4920 if (!instr->hydrogen()->value()->HasRange() ||
4928 !instr->hydrogen()->value()->range()->IsInSmiRange()) { 4921 !instr->hydrogen()->value()->range()->IsInSmiRange()) {
4929 DeoptimizeIf(overflow, instr->environment()); 4922 DeoptimizeIf(overflow, instr->environment());
4930 } 4923 }
4931 } 4924 }
4932 4925
4933 4926
4934 void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) { 4927 void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) {
4935 CpuFeatureScope scope(masm(), SSE2); 4928 CpuFeatureScope scope(masm(), SSE2);
4936 LOperand* input = instr->value(); 4929 LOperand* input = instr->value();
4937 LOperand* output = instr->result(); 4930 LOperand* output = instr->result();
4938 LOperand* temp = instr->temp(); 4931 LOperand* temp = instr->temp();
4939 4932
4940 __ LoadUint32(ToDoubleRegister(output), 4933 __ LoadUint32(ToDoubleRegister(output),
4941 ToRegister(input), 4934 ToRegister(input),
4942 ToDoubleRegister(temp)); 4935 ToDoubleRegister(temp));
4943 } 4936 }
4944 4937
4945 4938
4946 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { 4939 void LCodeGen::DoNumberTagI(LNumberTagI* instr) {
4947 class DeferredNumberTagI: public LDeferredCode { 4940 class DeferredNumberTagI V8_FINAL : public LDeferredCode {
4948 public: 4941 public:
4949 DeferredNumberTagI(LCodeGen* codegen, LNumberTagI* instr) 4942 DeferredNumberTagI(LCodeGen* codegen, LNumberTagI* instr)
4950 : LDeferredCode(codegen), instr_(instr) { } 4943 : LDeferredCode(codegen), instr_(instr) { }
4951 virtual void Generate() { 4944 virtual void Generate() V8_OVERRIDE {
4952 codegen()->DoDeferredNumberTagI(instr_, instr_->value(), SIGNED_INT32); 4945 codegen()->DoDeferredNumberTagI(instr_, instr_->value(), SIGNED_INT32);
4953 } 4946 }
4954 virtual LInstruction* instr() { return instr_; } 4947 virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
4955 private: 4948 private:
4956 LNumberTagI* instr_; 4949 LNumberTagI* instr_;
4957 }; 4950 };
4958 4951
4959 LOperand* input = instr->value(); 4952 LOperand* input = instr->value();
4960 ASSERT(input->IsRegister() && input->Equals(instr->result())); 4953 ASSERT(input->IsRegister() && input->Equals(instr->result()));
4961 Register reg = ToRegister(input); 4954 Register reg = ToRegister(input);
4962 4955
4963 DeferredNumberTagI* deferred = new(zone()) DeferredNumberTagI(this, instr); 4956 DeferredNumberTagI* deferred = new(zone()) DeferredNumberTagI(this, instr);
4964 __ SmiTag(reg); 4957 __ SmiTag(reg);
4965 __ j(overflow, deferred->entry()); 4958 __ j(overflow, deferred->entry());
4966 __ bind(deferred->exit()); 4959 __ bind(deferred->exit());
4967 } 4960 }
4968 4961
4969 4962
4970 void LCodeGen::DoNumberTagU(LNumberTagU* instr) { 4963 void LCodeGen::DoNumberTagU(LNumberTagU* instr) {
4971 class DeferredNumberTagU: public LDeferredCode { 4964 class DeferredNumberTagU V8_FINAL : public LDeferredCode {
4972 public: 4965 public:
4973 DeferredNumberTagU(LCodeGen* codegen, LNumberTagU* instr) 4966 DeferredNumberTagU(LCodeGen* codegen, LNumberTagU* instr)
4974 : LDeferredCode(codegen), instr_(instr) { } 4967 : LDeferredCode(codegen), instr_(instr) { }
4975 virtual void Generate() { 4968 virtual void Generate() V8_OVERRIDE {
4976 codegen()->DoDeferredNumberTagI(instr_, instr_->value(), UNSIGNED_INT32); 4969 codegen()->DoDeferredNumberTagI(instr_, instr_->value(), UNSIGNED_INT32);
4977 } 4970 }
4978 virtual LInstruction* instr() { return instr_; } 4971 virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
4979 private: 4972 private:
4980 LNumberTagU* instr_; 4973 LNumberTagU* instr_;
4981 }; 4974 };
4982 4975
4983 LOperand* input = instr->value(); 4976 LOperand* input = instr->value();
4984 ASSERT(input->IsRegister() && input->Equals(instr->result())); 4977 ASSERT(input->IsRegister() && input->Equals(instr->result()));
4985 Register reg = ToRegister(input); 4978 Register reg = ToRegister(input);
4986 4979
4987 DeferredNumberTagU* deferred = new(zone()) DeferredNumberTagU(this, instr); 4980 DeferredNumberTagU* deferred = new(zone()) DeferredNumberTagU(this, instr);
4988 __ cmp(reg, Immediate(Smi::kMaxValue)); 4981 __ cmp(reg, Immediate(Smi::kMaxValue));
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
5064 CpuFeatureScope feature_scope(masm(), SSE2); 5057 CpuFeatureScope feature_scope(masm(), SSE2);
5065 __ movdbl(FieldOperand(reg, HeapNumber::kValueOffset), xmm0); 5058 __ movdbl(FieldOperand(reg, HeapNumber::kValueOffset), xmm0);
5066 } else { 5059 } else {
5067 __ fstp_d(FieldOperand(reg, HeapNumber::kValueOffset)); 5060 __ fstp_d(FieldOperand(reg, HeapNumber::kValueOffset));
5068 } 5061 }
5069 __ StoreToSafepointRegisterSlot(reg, reg); 5062 __ StoreToSafepointRegisterSlot(reg, reg);
5070 } 5063 }
5071 5064
5072 5065
5073 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { 5066 void LCodeGen::DoNumberTagD(LNumberTagD* instr) {
5074 class DeferredNumberTagD: public LDeferredCode { 5067 class DeferredNumberTagD V8_FINAL : public LDeferredCode {
5075 public: 5068 public:
5076 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) 5069 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr)
5077 : LDeferredCode(codegen), instr_(instr) { } 5070 : LDeferredCode(codegen), instr_(instr) { }
5078 virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); } 5071 virtual void Generate() V8_OVERRIDE {
5079 virtual LInstruction* instr() { return instr_; } 5072 codegen()->DoDeferredNumberTagD(instr_);
5073 }
5074 virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
5080 private: 5075 private:
5081 LNumberTagD* instr_; 5076 LNumberTagD* instr_;
5082 }; 5077 };
5083 5078
5084 Register reg = ToRegister(instr->result()); 5079 Register reg = ToRegister(instr->result());
5085 5080
5086 bool convert_hole = false;
5087 HValue* change_input = instr->hydrogen()->value();
5088 if (change_input->IsLoadKeyed()) {
5089 HLoadKeyed* load = HLoadKeyed::cast(change_input);
5090 convert_hole = load->UsesMustHandleHole();
5091 }
5092
5093 bool use_sse2 = CpuFeatures::IsSupported(SSE2); 5081 bool use_sse2 = CpuFeatures::IsSupported(SSE2);
5094 if (!use_sse2) { 5082 if (!use_sse2) {
5095 // Put the value to the top of stack 5083 // Put the value to the top of stack
5096 X87Register src = ToX87Register(instr->value()); 5084 X87Register src = ToX87Register(instr->value());
5097 X87LoadForUsage(src); 5085 X87LoadForUsage(src);
5098 } 5086 }
5099 5087
5100 Label no_special_nan_handling;
5101 Label done;
5102 if (convert_hole) {
5103 if (use_sse2) {
5104 CpuFeatureScope scope(masm(), SSE2);
5105 XMMRegister input_reg = ToDoubleRegister(instr->value());
5106 __ ucomisd(input_reg, input_reg);
5107 } else {
5108 __ fld(0);
5109 __ fld(0);
5110 __ FCmp();
5111 }
5112
5113 __ j(parity_odd, &no_special_nan_handling);
5114 __ sub(esp, Immediate(kDoubleSize));
5115 if (use_sse2) {
5116 CpuFeatureScope scope(masm(), SSE2);
5117 XMMRegister input_reg = ToDoubleRegister(instr->value());
5118 __ movdbl(MemOperand(esp, 0), input_reg);
5119 } else {
5120 __ fld(0);
5121 __ fstp_d(MemOperand(esp, 0));
5122 }
5123 __ cmp(MemOperand(esp, sizeof(kHoleNanLower32)),
5124 Immediate(kHoleNanUpper32));
5125 Label canonicalize;
5126 __ j(not_equal, &canonicalize);
5127 __ add(esp, Immediate(kDoubleSize));
5128 __ mov(reg, factory()->the_hole_value());
5129 if (!use_sse2) {
5130 __ fstp(0);
5131 }
5132 __ jmp(&done);
5133 __ bind(&canonicalize);
5134 __ add(esp, Immediate(kDoubleSize));
5135 ExternalReference nan =
5136 ExternalReference::address_of_canonical_non_hole_nan();
5137 if (use_sse2) {
5138 CpuFeatureScope scope(masm(), SSE2);
5139 XMMRegister input_reg = ToDoubleRegister(instr->value());
5140 __ movdbl(input_reg, Operand::StaticVariable(nan));
5141 } else {
5142 __ fstp(0);
5143 __ fld_d(Operand::StaticVariable(nan));
5144 }
5145 }
5146
5147 __ bind(&no_special_nan_handling);
5148 DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr); 5088 DeferredNumberTagD* deferred = new(zone()) DeferredNumberTagD(this, instr);
5149 if (FLAG_inline_new) { 5089 if (FLAG_inline_new) {
5150 Register tmp = ToRegister(instr->temp()); 5090 Register tmp = ToRegister(instr->temp());
5151 __ AllocateHeapNumber(reg, tmp, no_reg, deferred->entry()); 5091 __ AllocateHeapNumber(reg, tmp, no_reg, deferred->entry());
5152 } else { 5092 } else {
5153 __ jmp(deferred->entry()); 5093 __ jmp(deferred->entry());
5154 } 5094 }
5155 __ bind(deferred->exit()); 5095 __ bind(deferred->exit());
5156 if (use_sse2) { 5096 if (use_sse2) {
5157 CpuFeatureScope scope(masm(), SSE2); 5097 CpuFeatureScope scope(masm(), SSE2);
5158 XMMRegister input_reg = ToDoubleRegister(instr->value()); 5098 XMMRegister input_reg = ToDoubleRegister(instr->value());
5159 __ movdbl(FieldOperand(reg, HeapNumber::kValueOffset), input_reg); 5099 __ movdbl(FieldOperand(reg, HeapNumber::kValueOffset), input_reg);
5160 } else { 5100 } else {
5161 __ fstp_d(FieldOperand(reg, HeapNumber::kValueOffset)); 5101 __ fstp_d(FieldOperand(reg, HeapNumber::kValueOffset));
5162 } 5102 }
5163 __ bind(&done);
5164 } 5103 }
5165 5104
5166 5105
5167 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { 5106 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) {
5168 // TODO(3095996): Get rid of this. For now, we need to make the 5107 // TODO(3095996): Get rid of this. For now, we need to make the
5169 // result register contain a valid pointer because it is already 5108 // result register contain a valid pointer because it is already
5170 // contained in the register pointer map. 5109 // contained in the register pointer map.
5171 Register reg = ToRegister(instr->result()); 5110 Register reg = ToRegister(instr->result());
5172 __ Set(reg, Immediate(0)); 5111 __ Set(reg, Immediate(0));
5173 5112
(...skipping 29 matching lines...) Expand all
5203 } else { 5142 } else {
5204 __ AssertSmi(result); 5143 __ AssertSmi(result);
5205 } 5144 }
5206 __ SmiUntag(result); 5145 __ SmiUntag(result);
5207 } 5146 }
5208 5147
5209 5148
5210 void LCodeGen::EmitNumberUntagDNoSSE2(Register input_reg, 5149 void LCodeGen::EmitNumberUntagDNoSSE2(Register input_reg,
5211 Register temp_reg, 5150 Register temp_reg,
5212 X87Register res_reg, 5151 X87Register res_reg,
5213 bool allow_undefined_as_nan, 5152 bool can_convert_undefined_to_nan,
5214 bool deoptimize_on_minus_zero, 5153 bool deoptimize_on_minus_zero,
5215 LEnvironment* env, 5154 LEnvironment* env,
5216 NumberUntagDMode mode) { 5155 NumberUntagDMode mode) {
5217 Label load_smi, done; 5156 Label load_smi, done;
5218 5157
5219 X87PrepareToWrite(res_reg); 5158 X87PrepareToWrite(res_reg);
5220 STATIC_ASSERT(NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE > 5159 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) {
5221 NUMBER_CANDIDATE_IS_ANY_TAGGED);
5222 if (mode >= NUMBER_CANDIDATE_IS_ANY_TAGGED) {
5223 // Smi check. 5160 // Smi check.
5224 __ JumpIfSmi(input_reg, &load_smi, Label::kNear); 5161 __ JumpIfSmi(input_reg, &load_smi, Label::kNear);
5225 5162
5226 // Heap number map check. 5163 // Heap number map check.
5227 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), 5164 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
5228 factory()->heap_number_map()); 5165 factory()->heap_number_map());
5229 if (!allow_undefined_as_nan) { 5166 if (!can_convert_undefined_to_nan) {
5230 DeoptimizeIf(not_equal, env); 5167 DeoptimizeIf(not_equal, env);
5231 } else { 5168 } else {
5232 Label heap_number, convert; 5169 Label heap_number, convert;
5233 __ j(equal, &heap_number, Label::kNear); 5170 __ j(equal, &heap_number, Label::kNear);
5234 5171
5235 // Convert undefined (or hole) to NaN. 5172 // Convert undefined (or hole) to NaN.
5236 __ cmp(input_reg, factory()->undefined_value()); 5173 __ cmp(input_reg, factory()->undefined_value());
5237 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE) {
5238 __ j(equal, &convert, Label::kNear);
5239 __ cmp(input_reg, factory()->the_hole_value());
5240 }
5241 DeoptimizeIf(not_equal, env); 5174 DeoptimizeIf(not_equal, env);
5242 5175
5243 __ bind(&convert); 5176 __ bind(&convert);
5244 ExternalReference nan = 5177 ExternalReference nan =
5245 ExternalReference::address_of_canonical_non_hole_nan(); 5178 ExternalReference::address_of_canonical_non_hole_nan();
5246 __ fld_d(Operand::StaticVariable(nan)); 5179 __ fld_d(Operand::StaticVariable(nan));
5247 __ jmp(&done, Label::kNear); 5180 __ jmp(&done, Label::kNear);
5248 5181
5249 __ bind(&heap_number); 5182 __ bind(&heap_number);
5250 } 5183 }
(...skipping 26 matching lines...) Expand all
5277 __ pop(input_reg); 5210 __ pop(input_reg);
5278 __ SmiTag(input_reg); // Retag smi. 5211 __ SmiTag(input_reg); // Retag smi.
5279 __ bind(&done); 5212 __ bind(&done);
5280 X87CommitWrite(res_reg); 5213 X87CommitWrite(res_reg);
5281 } 5214 }
5282 5215
5283 5216
5284 void LCodeGen::EmitNumberUntagD(Register input_reg, 5217 void LCodeGen::EmitNumberUntagD(Register input_reg,
5285 Register temp_reg, 5218 Register temp_reg,
5286 XMMRegister result_reg, 5219 XMMRegister result_reg,
5287 bool allow_undefined_as_nan, 5220 bool can_convert_undefined_to_nan,
5288 bool deoptimize_on_minus_zero, 5221 bool deoptimize_on_minus_zero,
5289 LEnvironment* env, 5222 LEnvironment* env,
5290 NumberUntagDMode mode) { 5223 NumberUntagDMode mode) {
5291 Label load_smi, done; 5224 Label load_smi, done;
5292 5225
5293 STATIC_ASSERT(NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE > 5226 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) {
5294 NUMBER_CANDIDATE_IS_ANY_TAGGED);
5295 if (mode >= NUMBER_CANDIDATE_IS_ANY_TAGGED) {
5296 // Smi check. 5227 // Smi check.
5297 __ JumpIfSmi(input_reg, &load_smi, Label::kNear); 5228 __ JumpIfSmi(input_reg, &load_smi, Label::kNear);
5298 5229
5299 // Heap number map check. 5230 // Heap number map check.
5300 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), 5231 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
5301 factory()->heap_number_map()); 5232 factory()->heap_number_map());
5302 if (!allow_undefined_as_nan) { 5233 if (!can_convert_undefined_to_nan) {
5303 DeoptimizeIf(not_equal, env); 5234 DeoptimizeIf(not_equal, env);
5304 } else { 5235 } else {
5305 Label heap_number, convert; 5236 Label heap_number, convert;
5306 __ j(equal, &heap_number, Label::kNear); 5237 __ j(equal, &heap_number, Label::kNear);
5307 5238
5308 // Convert undefined (and hole) to NaN. 5239 // Convert undefined (and hole) to NaN.
5309 __ cmp(input_reg, factory()->undefined_value()); 5240 __ cmp(input_reg, factory()->undefined_value());
5310 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE) {
5311 __ j(equal, &convert, Label::kNear);
5312 __ cmp(input_reg, factory()->the_hole_value());
5313 }
5314 DeoptimizeIf(not_equal, env); 5241 DeoptimizeIf(not_equal, env);
5315 5242
5316 __ bind(&convert); 5243 __ bind(&convert);
5317 ExternalReference nan = 5244 ExternalReference nan =
5318 ExternalReference::address_of_canonical_non_hole_nan(); 5245 ExternalReference::address_of_canonical_non_hole_nan();
5319 __ movdbl(result_reg, Operand::StaticVariable(nan)); 5246 __ movdbl(result_reg, Operand::StaticVariable(nan));
5320 __ jmp(&done, Label::kNear); 5247 __ jmp(&done, Label::kNear);
5321 5248
5322 __ bind(&heap_number); 5249 __ bind(&heap_number);
5323 } 5250 }
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
5431 DeoptimizeIf(not_zero, instr->environment()); 5358 DeoptimizeIf(not_zero, instr->environment());
5432 } 5359 }
5433 } else { 5360 } else {
5434 UNREACHABLE(); 5361 UNREACHABLE();
5435 } 5362 }
5436 __ bind(&done); 5363 __ bind(&done);
5437 } 5364 }
5438 5365
5439 5366
5440 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { 5367 void LCodeGen::DoTaggedToI(LTaggedToI* instr) {
5441 class DeferredTaggedToI: public LDeferredCode { 5368 class DeferredTaggedToI V8_FINAL : public LDeferredCode {
5442 public: 5369 public:
5443 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) 5370 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr)
5444 : LDeferredCode(codegen), instr_(instr) { } 5371 : LDeferredCode(codegen), instr_(instr) { }
5445 virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); } 5372 virtual void Generate() V8_OVERRIDE {
5446 virtual LInstruction* instr() { return instr_; } 5373 codegen()->DoDeferredTaggedToI(instr_);
5374 }
5375 virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
5447 private: 5376 private:
5448 LTaggedToI* instr_; 5377 LTaggedToI* instr_;
5449 }; 5378 };
5450 5379
5451 LOperand* input = instr->value(); 5380 LOperand* input = instr->value();
5452 ASSERT(input->IsRegister()); 5381 ASSERT(input->IsRegister());
5453 Register input_reg = ToRegister(input); 5382 Register input_reg = ToRegister(input);
5454 ASSERT(input_reg.is(ToRegister(instr->result()))); 5383 ASSERT(input_reg.is(ToRegister(instr->result())));
5455 5384
5456 DeferredTaggedToI* deferred = new(zone()) DeferredTaggedToI(this, instr); 5385 DeferredTaggedToI* deferred = new(zone()) DeferredTaggedToI(this, instr);
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
5590 DeoptimizeIf(zero, instr->environment()); 5519 DeoptimizeIf(zero, instr->environment());
5591 } 5520 }
5592 // If the negative subtraction overflows into a positive number, there was an 5521 // If the negative subtraction overflows into a positive number, there was an
5593 // overflow --> deopt. 5522 // overflow --> deopt.
5594 DeoptimizeIf(positive, instr->environment()); 5523 DeoptimizeIf(positive, instr->environment());
5595 __ bind(&done); 5524 __ bind(&done);
5596 } 5525 }
5597 5526
5598 5527
5599 void LCodeGen::DoTaggedToINoSSE2(LTaggedToINoSSE2* instr) { 5528 void LCodeGen::DoTaggedToINoSSE2(LTaggedToINoSSE2* instr) {
5600 class DeferredTaggedToINoSSE2: public LDeferredCode { 5529 class DeferredTaggedToINoSSE2 V8_FINAL : public LDeferredCode {
5601 public: 5530 public:
5602 DeferredTaggedToINoSSE2(LCodeGen* codegen, LTaggedToINoSSE2* instr) 5531 DeferredTaggedToINoSSE2(LCodeGen* codegen, LTaggedToINoSSE2* instr)
5603 : LDeferredCode(codegen), instr_(instr) { } 5532 : LDeferredCode(codegen), instr_(instr) { }
5604 virtual void Generate() { codegen()->DoDeferredTaggedToINoSSE2(instr_); } 5533 virtual void Generate() V8_OVERRIDE {
5605 virtual LInstruction* instr() { return instr_; } 5534 codegen()->DoDeferredTaggedToINoSSE2(instr_);
5535 }
5536 virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
5606 private: 5537 private:
5607 LTaggedToINoSSE2* instr_; 5538 LTaggedToINoSSE2* instr_;
5608 }; 5539 };
5609 5540
5610 LOperand* input = instr->value(); 5541 LOperand* input = instr->value();
5611 ASSERT(input->IsRegister()); 5542 ASSERT(input->IsRegister());
5612 Register input_reg = ToRegister(input); 5543 Register input_reg = ToRegister(input);
5613 ASSERT(input_reg.is(ToRegister(instr->result()))); 5544 ASSERT(input_reg.is(ToRegister(instr->result())));
5614 5545
5615 DeferredTaggedToINoSSE2* deferred = 5546 DeferredTaggedToINoSSE2* deferred =
(...skipping 12 matching lines...) Expand all
5628 LOperand* temp = instr->temp(); 5559 LOperand* temp = instr->temp();
5629 ASSERT(temp == NULL || temp->IsRegister()); 5560 ASSERT(temp == NULL || temp->IsRegister());
5630 LOperand* result = instr->result(); 5561 LOperand* result = instr->result();
5631 ASSERT(result->IsDoubleRegister()); 5562 ASSERT(result->IsDoubleRegister());
5632 5563
5633 Register input_reg = ToRegister(input); 5564 Register input_reg = ToRegister(input);
5634 bool deoptimize_on_minus_zero = 5565 bool deoptimize_on_minus_zero =
5635 instr->hydrogen()->deoptimize_on_minus_zero(); 5566 instr->hydrogen()->deoptimize_on_minus_zero();
5636 Register temp_reg = deoptimize_on_minus_zero ? ToRegister(temp) : no_reg; 5567 Register temp_reg = deoptimize_on_minus_zero ? ToRegister(temp) : no_reg;
5637 5568
5638 NumberUntagDMode mode = NUMBER_CANDIDATE_IS_ANY_TAGGED;
5639 HValue* value = instr->hydrogen()->value(); 5569 HValue* value = instr->hydrogen()->value();
5640 if (value->representation().IsSmi()) { 5570 NumberUntagDMode mode = value->representation().IsSmi()
5641 mode = NUMBER_CANDIDATE_IS_SMI; 5571 ? NUMBER_CANDIDATE_IS_SMI : NUMBER_CANDIDATE_IS_ANY_TAGGED;
5642 } else if (value->IsLoadKeyed()) {
5643 HLoadKeyed* load = HLoadKeyed::cast(value);
5644 if (load->UsesMustHandleHole()) {
5645 mode = NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE;
5646 }
5647 }
5648 5572
5649 if (CpuFeatures::IsSupported(SSE2)) { 5573 if (CpuFeatures::IsSupported(SSE2)) {
5650 CpuFeatureScope scope(masm(), SSE2); 5574 CpuFeatureScope scope(masm(), SSE2);
5651 XMMRegister result_reg = ToDoubleRegister(result); 5575 XMMRegister result_reg = ToDoubleRegister(result);
5652 EmitNumberUntagD(input_reg, 5576 EmitNumberUntagD(input_reg,
5653 temp_reg, 5577 temp_reg,
5654 result_reg, 5578 result_reg,
5655 instr->hydrogen()->allow_undefined_as_nan(), 5579 instr->hydrogen()->can_convert_undefined_to_nan(),
5656 deoptimize_on_minus_zero, 5580 deoptimize_on_minus_zero,
5657 instr->environment(), 5581 instr->environment(),
5658 mode); 5582 mode);
5659 } else { 5583 } else {
5660 EmitNumberUntagDNoSSE2(input_reg, 5584 EmitNumberUntagDNoSSE2(input_reg,
5661 temp_reg, 5585 temp_reg,
5662 ToX87Register(instr->result()), 5586 ToX87Register(instr->result()),
5663 instr->hydrogen()->allow_undefined_as_nan(), 5587 instr->hydrogen()->can_convert_undefined_to_nan(),
5664 deoptimize_on_minus_zero, 5588 deoptimize_on_minus_zero,
5665 instr->environment(), 5589 instr->environment(),
5666 mode); 5590 mode);
5667 } 5591 }
5668 } 5592 }
5669 5593
5670 5594
5671 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { 5595 void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
5672 LOperand* input = instr->value(); 5596 LOperand* input = instr->value();
5673 ASSERT(input->IsDoubleRegister()); 5597 ASSERT(input->IsDoubleRegister());
5674 LOperand* result = instr->result(); 5598 LOperand* result = instr->result();
5675 ASSERT(result->IsRegister()); 5599 ASSERT(result->IsRegister());
5676 CpuFeatureScope scope(masm(), SSE2);
5677
5678 XMMRegister input_reg = ToDoubleRegister(input);
5679 Register result_reg = ToRegister(result); 5600 Register result_reg = ToRegister(result);
5680 5601
5681 __ cvttsd2si(result_reg, Operand(input_reg)); 5602 Label done;
5603 if (CpuFeatures::IsSafeForSnapshot(SSE2)) {
5604 CpuFeatureScope scope(masm(), SSE2);
5682 5605
5683 if (instr->truncating()) { 5606 XMMRegister input_reg = ToDoubleRegister(input);
5684 // Performs a truncating conversion of a floating point number as used by 5607
5685 // the JS bitwise operations. 5608 __ cvttsd2si(result_reg, Operand(input_reg));
5686 Label fast_case_succeeded; 5609
5687 __ cmp(result_reg, 0x80000000u); 5610 if (instr->truncating()) {
5688 __ j(not_equal, &fast_case_succeeded); 5611 // Performs a truncating conversion of a floating point number as used by
5689 __ sub(esp, Immediate(kDoubleSize)); 5612 // the JS bitwise operations.
5690 __ movdbl(MemOperand(esp, 0), input_reg); 5613 Label fast_case_succeeded;
5691 DoubleToIStub stub(esp, result_reg, 0, true); 5614 __ cmp(result_reg, 0x80000000u);
5692 __ call(stub.GetCode(isolate()), RelocInfo::CODE_TARGET); 5615 __ j(not_equal, &fast_case_succeeded);
5693 __ add(esp, Immediate(kDoubleSize)); 5616 __ sub(esp, Immediate(kDoubleSize));
5694 __ bind(&fast_case_succeeded); 5617 __ movdbl(MemOperand(esp, 0), input_reg);
5618 DoubleToIStub stub(esp, result_reg, 0, true);
5619 __ call(stub.GetCode(isolate()), RelocInfo::CODE_TARGET);
5620 __ add(esp, Immediate(kDoubleSize));
5621 __ bind(&fast_case_succeeded);
5622 } else {
5623 __ cvtsi2sd(xmm0, Operand(result_reg));
5624 __ ucomisd(xmm0, input_reg);
5625 DeoptimizeIf(not_equal, instr->environment());
5626 DeoptimizeIf(parity_even, instr->environment()); // NaN.
5627 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
5628 // The integer converted back is equal to the original. We
5629 // only have to test if we got -0 as an input.
5630 __ test(result_reg, Operand(result_reg));
5631 __ j(not_zero, &done, Label::kNear);
5632 __ movmskpd(result_reg, input_reg);
5633 // Bit 0 contains the sign of the double in input_reg.
5634 // If input was positive, we are ok and return 0, otherwise
5635 // deoptimize.
5636 __ and_(result_reg, 1);
5637 DeoptimizeIf(not_zero, instr->environment());
5638 }
5639 __ bind(&done);
5640 }
5695 } else { 5641 } else {
5696 Label done; 5642 X87Register input_reg = ToX87Register(input);
5697 __ cvtsi2sd(xmm0, Operand(result_reg)); 5643 __ push(result_reg);
5698 __ ucomisd(xmm0, input_reg); 5644 X87Mov(Operand(esp, 0), input_reg, kX87IntOperand);
5699 DeoptimizeIf(not_equal, instr->environment()); 5645 if (instr->truncating()) {
5700 DeoptimizeIf(parity_even, instr->environment()); // NaN. 5646 __ pop(result_reg);
5647 } else {
5648 X87Fxch(input_reg);
5649 __ fld(0);
5650 __ fild_s(Operand(esp, 0));
5651 __ pop(result_reg);
5652 __ FCmp();
5653 DeoptimizeIf(not_equal, instr->environment());
5654 DeoptimizeIf(parity_even, instr->environment()); // NaN.
5655 }
5701 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 5656 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
5702 // The integer converted back is equal to the original. We
5703 // only have to test if we got -0 as an input.
5704 __ test(result_reg, Operand(result_reg)); 5657 __ test(result_reg, Operand(result_reg));
5705 __ j(not_zero, &done, Label::kNear); 5658 __ j(not_zero, &done, Label::kNear);
5706 __ movmskpd(result_reg, input_reg); 5659 // To check for minus zero, we load the value again as float, and check
5707 // Bit 0 contains the sign of the double in input_reg. 5660 // if that is still 0.
5708 // If input was positive, we are ok and return 0, otherwise 5661 X87Fxch(input_reg);
5709 // deoptimize. 5662 __ push(result_reg);
5710 __ and_(result_reg, 1); 5663 __ fst_s(Operand(esp, 0));
5664 __ pop(result_reg);
5665 __ test(result_reg, Operand(result_reg));
5711 DeoptimizeIf(not_zero, instr->environment()); 5666 DeoptimizeIf(not_zero, instr->environment());
5667 __ bind(&done);
5712 } 5668 }
5713 __ bind(&done);
5714 } 5669 }
5715 } 5670 }
5716 5671
5717 5672
5718 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) { 5673 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) {
5719 LOperand* input = instr->value(); 5674 LOperand* input = instr->value();
5720 ASSERT(input->IsDoubleRegister()); 5675 ASSERT(input->IsDoubleRegister());
5721 LOperand* result = instr->result(); 5676 LOperand* result = instr->result();
5722 ASSERT(result->IsRegister()); 5677 ASSERT(result->IsRegister());
5723 CpuFeatureScope scope(masm(), SSE2);
5724
5725 XMMRegister input_reg = ToDoubleRegister(input);
5726 Register result_reg = ToRegister(result); 5678 Register result_reg = ToRegister(result);
5727 5679
5728 Label done; 5680 Label done;
5729 __ cvttsd2si(result_reg, Operand(input_reg)); 5681 if (CpuFeatures::IsSafeForSnapshot(SSE2)) {
5730 __ cvtsi2sd(xmm0, Operand(result_reg)); 5682 CpuFeatureScope scope(masm(), SSE2);
5731 __ ucomisd(xmm0, input_reg);
5732 DeoptimizeIf(not_equal, instr->environment());
5733 DeoptimizeIf(parity_even, instr->environment()); // NaN.
5734 5683
5735 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 5684 XMMRegister input_reg = ToDoubleRegister(input);
5736 // The integer converted back is equal to the original. We 5685
5737 // only have to test if we got -0 as an input. 5686 __ cvttsd2si(result_reg, Operand(input_reg));
5738 __ test(result_reg, Operand(result_reg)); 5687 __ cvtsi2sd(xmm0, Operand(result_reg));
5739 __ j(not_zero, &done, Label::kNear); 5688 __ ucomisd(xmm0, input_reg);
5740 __ movmskpd(result_reg, input_reg); 5689 DeoptimizeIf(not_equal, instr->environment());
5741 // Bit 0 contains the sign of the double in input_reg. 5690 DeoptimizeIf(parity_even, instr->environment()); // NaN.
5742 // If input was positive, we are ok and return 0, otherwise 5691 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
5743 // deoptimize. 5692 // The integer converted back is equal to the original. We
5744 __ and_(result_reg, 1); 5693 // only have to test if we got -0 as an input.
5745 DeoptimizeIf(not_zero, instr->environment()); 5694 __ test(result_reg, Operand(result_reg));
5746 __ bind(&done); 5695 __ j(not_zero, &done, Label::kNear);
5696 __ movmskpd(result_reg, input_reg);
5697 // Bit 0 contains the sign of the double in input_reg.
5698 // If input was positive, we are ok and return 0, otherwise
5699 // deoptimize.
5700 __ and_(result_reg, 1);
5701 DeoptimizeIf(not_zero, instr->environment());
5702 __ bind(&done);
5703 }
5704 } else {
5705 X87Register input_reg = ToX87Register(input);
5706 X87Fxch(input_reg);
5707 __ push(result_reg);
5708 X87Mov(Operand(esp, 0), input_reg, kX87IntOperand);
5709 __ fld(0);
5710 __ fild_s(Operand(esp, 0));
5711 __ pop(result_reg);
5712 __ FCmp();
5713 DeoptimizeIf(not_equal, instr->environment());
5714 DeoptimizeIf(parity_even, instr->environment()); // NaN.
5715
5716 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
5717 __ test(result_reg, Operand(result_reg));
5718 __ j(not_zero, &done, Label::kNear);
5719 // To check for minus zero, we load the value again as float, and check
5720 // if that is still 0.
5721 __ push(result_reg);
5722 __ fst_s(Operand(esp, 0));
5723 __ pop(result_reg);
5724 __ test(result_reg, Operand(result_reg));
5725 DeoptimizeIf(not_zero, instr->environment());
5726 __ bind(&done);
5727 }
5747 } 5728 }
5748 __ SmiTag(result_reg); 5729 __ SmiTag(result_reg);
5749 DeoptimizeIf(overflow, instr->environment()); 5730 DeoptimizeIf(overflow, instr->environment());
5750 } 5731 }
5751 5732
5752 5733
5753 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { 5734 void LCodeGen::DoCheckSmi(LCheckSmi* instr) {
5754 LOperand* input = instr->value(); 5735 LOperand* input = instr->value();
5755 __ test(ToOperand(input), Immediate(kSmiTagMask)); 5736 __ test(ToOperand(input), Immediate(kSmiTagMask));
5756 DeoptimizeIf(not_zero, instr->environment()); 5737 DeoptimizeIf(not_zero, instr->environment());
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
5834 RecordSafepointWithRegisters( 5815 RecordSafepointWithRegisters(
5835 instr->pointer_map(), 1, Safepoint::kNoLazyDeopt); 5816 instr->pointer_map(), 1, Safepoint::kNoLazyDeopt);
5836 5817
5837 __ test(eax, Immediate(kSmiTagMask)); 5818 __ test(eax, Immediate(kSmiTagMask));
5838 } 5819 }
5839 DeoptimizeIf(zero, instr->environment()); 5820 DeoptimizeIf(zero, instr->environment());
5840 } 5821 }
5841 5822
5842 5823
5843 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { 5824 void LCodeGen::DoCheckMaps(LCheckMaps* instr) {
5844 class DeferredCheckMaps: public LDeferredCode { 5825 class DeferredCheckMaps V8_FINAL : public LDeferredCode {
5845 public: 5826 public:
5846 DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr, Register object) 5827 DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr, Register object)
5847 : LDeferredCode(codegen), instr_(instr), object_(object) { 5828 : LDeferredCode(codegen), instr_(instr), object_(object) {
5848 SetExit(check_maps()); 5829 SetExit(check_maps());
5849 } 5830 }
5850 virtual void Generate() { 5831 virtual void Generate() V8_OVERRIDE {
5851 codegen()->DoDeferredInstanceMigration(instr_, object_); 5832 codegen()->DoDeferredInstanceMigration(instr_, object_);
5852 } 5833 }
5853 Label* check_maps() { return &check_maps_; } 5834 Label* check_maps() { return &check_maps_; }
5854 virtual LInstruction* instr() { return instr_; } 5835 virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
5855 private: 5836 private:
5856 LCheckMaps* instr_; 5837 LCheckMaps* instr_;
5857 Label check_maps_; 5838 Label check_maps_;
5858 Register object_; 5839 Register object_;
5859 }; 5840 };
5860 5841
5861 if (instr->hydrogen()->CanOmitMapChecks()) return; 5842 if (instr->hydrogen()->CanOmitMapChecks()) return;
5862 5843
5863 LOperand* input = instr->value(); 5844 LOperand* input = instr->value();
5864 ASSERT(input->IsRegister()); 5845 ASSERT(input->IsRegister());
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after
6057 if (!input_reg.is(result_reg)) { 6038 if (!input_reg.is(result_reg)) {
6058 __ mov(result_reg, input_reg); 6039 __ mov(result_reg, input_reg);
6059 } 6040 }
6060 __ SmiUntag(result_reg); 6041 __ SmiUntag(result_reg);
6061 __ ClampUint8(result_reg); 6042 __ ClampUint8(result_reg);
6062 __ bind(&done); 6043 __ bind(&done);
6063 } 6044 }
6064 6045
6065 6046
6066 void LCodeGen::DoAllocate(LAllocate* instr) { 6047 void LCodeGen::DoAllocate(LAllocate* instr) {
6067 class DeferredAllocate: public LDeferredCode { 6048 class DeferredAllocate V8_FINAL : public LDeferredCode {
6068 public: 6049 public:
6069 DeferredAllocate(LCodeGen* codegen, LAllocate* instr) 6050 DeferredAllocate(LCodeGen* codegen, LAllocate* instr)
6070 : LDeferredCode(codegen), instr_(instr) { } 6051 : LDeferredCode(codegen), instr_(instr) { }
6071 virtual void Generate() { codegen()->DoDeferredAllocate(instr_); } 6052 virtual void Generate() V8_OVERRIDE {
6072 virtual LInstruction* instr() { return instr_; } 6053 codegen()->DoDeferredAllocate(instr_);
6054 }
6055 virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
6073 private: 6056 private:
6074 LAllocate* instr_; 6057 LAllocate* instr_;
6075 }; 6058 };
6076 6059
6077 DeferredAllocate* deferred = 6060 DeferredAllocate* deferred =
6078 new(zone()) DeferredAllocate(this, instr); 6061 new(zone()) DeferredAllocate(this, instr);
6079 6062
6080 Register result = ToRegister(instr->result()); 6063 Register result = ToRegister(instr->result());
6081 Register temp = ToRegister(instr->temp()); 6064 Register temp = ToRegister(instr->temp());
6082 6065
(...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after
6383 6366
6384 void LCodeGen::DoDeoptimize(LDeoptimize* instr) { 6367 void LCodeGen::DoDeoptimize(LDeoptimize* instr) {
6385 Deoptimizer::BailoutType type = instr->hydrogen()->type(); 6368 Deoptimizer::BailoutType type = instr->hydrogen()->type();
6386 // TODO(danno): Stubs expect all deopts to be lazy for historical reasons (the 6369 // TODO(danno): Stubs expect all deopts to be lazy for historical reasons (the
6387 // needed return address), even though the implementation of LAZY and EAGER is 6370 // needed return address), even though the implementation of LAZY and EAGER is
6388 // now identical. When LAZY is eventually completely folded into EAGER, remove 6371 // now identical. When LAZY is eventually completely folded into EAGER, remove
6389 // the special case below. 6372 // the special case below.
6390 if (info()->IsStub() && type == Deoptimizer::EAGER) { 6373 if (info()->IsStub() && type == Deoptimizer::EAGER) {
6391 type = Deoptimizer::LAZY; 6374 type = Deoptimizer::LAZY;
6392 } 6375 }
6376 Comment(";;; deoptimize: %s", instr->hydrogen()->reason());
6393 DeoptimizeIf(no_condition, instr->environment(), type); 6377 DeoptimizeIf(no_condition, instr->environment(), type);
6394 } 6378 }
6395 6379
6396 6380
6397 void LCodeGen::DoDummyUse(LDummyUse* instr) { 6381 void LCodeGen::DoDummyUse(LDummyUse* instr) {
6398 // Nothing to see here, move on! 6382 // Nothing to see here, move on!
6399 } 6383 }
6400 6384
6401 6385
6402 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) { 6386 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) {
6403 PushSafepointRegistersScope scope(this); 6387 PushSafepointRegistersScope scope(this);
6404 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 6388 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
6405 __ CallRuntimeSaveDoubles(Runtime::kStackGuard); 6389 __ CallRuntimeSaveDoubles(Runtime::kStackGuard);
6406 RecordSafepointWithLazyDeopt( 6390 RecordSafepointWithLazyDeopt(
6407 instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); 6391 instr, RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
6408 ASSERT(instr->HasEnvironment()); 6392 ASSERT(instr->HasEnvironment());
6409 LEnvironment* env = instr->environment(); 6393 LEnvironment* env = instr->environment();
6410 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); 6394 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
6411 } 6395 }
6412 6396
6413 6397
6414 void LCodeGen::DoStackCheck(LStackCheck* instr) { 6398 void LCodeGen::DoStackCheck(LStackCheck* instr) {
6415 class DeferredStackCheck: public LDeferredCode { 6399 class DeferredStackCheck V8_FINAL : public LDeferredCode {
6416 public: 6400 public:
6417 DeferredStackCheck(LCodeGen* codegen, LStackCheck* instr) 6401 DeferredStackCheck(LCodeGen* codegen, LStackCheck* instr)
6418 : LDeferredCode(codegen), instr_(instr) { } 6402 : LDeferredCode(codegen), instr_(instr) { }
6419 virtual void Generate() { codegen()->DoDeferredStackCheck(instr_); } 6403 virtual void Generate() V8_OVERRIDE {
6420 virtual LInstruction* instr() { return instr_; } 6404 codegen()->DoDeferredStackCheck(instr_);
6405 }
6406 virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
6421 private: 6407 private:
6422 LStackCheck* instr_; 6408 LStackCheck* instr_;
6423 }; 6409 };
6424 6410
6425 ASSERT(instr->HasEnvironment()); 6411 ASSERT(instr->HasEnvironment());
6426 LEnvironment* env = instr->environment(); 6412 LEnvironment* env = instr->environment();
6427 // There is no LLazyBailout instruction for stack-checks. We have to 6413 // There is no LLazyBailout instruction for stack-checks. We have to
6428 // prepare for lazy deoptimization explicitly here. 6414 // prepare for lazy deoptimization explicitly here.
6429 if (instr->hydrogen()->is_function_entry()) { 6415 if (instr->hydrogen()->is_function_entry()) {
6430 // Perform stack overflow check. 6416 // Perform stack overflow check.
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
6564 FixedArray::kHeaderSize - kPointerSize)); 6550 FixedArray::kHeaderSize - kPointerSize));
6565 __ bind(&done); 6551 __ bind(&done);
6566 } 6552 }
6567 6553
6568 6554
6569 #undef __ 6555 #undef __
6570 6556
6571 } } // namespace v8::internal 6557 } } // namespace v8::internal
6572 6558
6573 #endif // V8_TARGET_ARCH_IA32 6559 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/lithium-codegen-ia32.h ('k') | src/ia32/lithium-gap-resolver-ia32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698