| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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(¬_applicable); | 4779 __ bind(¬_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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |