| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 150 // Reserve space for the stack slots needed by the code. | 150 // Reserve space for the stack slots needed by the code. |
| 151 int slots = GetStackSlotCount(); | 151 int slots = GetStackSlotCount(); |
| 152 if (slots > 0) { | 152 if (slots > 0) { |
| 153 if (FLAG_debug_code) { | 153 if (FLAG_debug_code) { |
| 154 __ subq(rsp, Immediate(slots * kPointerSize)); | 154 __ subq(rsp, Immediate(slots * kPointerSize)); |
| 155 #ifdef _MSC_VER | 155 #ifdef _MSC_VER |
| 156 MakeSureStackPagesMapped(slots * kPointerSize); | 156 MakeSureStackPagesMapped(slots * kPointerSize); |
| 157 #endif | 157 #endif |
| 158 __ push(rax); | 158 __ push(rax); |
| 159 __ Set(rax, slots); | 159 __ Set(rax, slots); |
| 160 __ movq(kScratchRegister, kSlotsZapValue, RelocInfo::NONE64); | 160 __ movq(kScratchRegister, kSlotsZapValue); |
| 161 Label loop; | 161 Label loop; |
| 162 __ bind(&loop); | 162 __ bind(&loop); |
| 163 __ movq(MemOperand(rsp, rax, times_pointer_size, 0), | 163 __ movq(MemOperand(rsp, rax, times_pointer_size, 0), |
| 164 kScratchRegister); | 164 kScratchRegister); |
| 165 __ decl(rax); | 165 __ decl(rax); |
| 166 __ j(not_zero, &loop); | 166 __ j(not_zero, &loop); |
| 167 __ pop(rax); | 167 __ pop(rax); |
| 168 } else { | 168 } else { |
| 169 __ subq(rsp, Immediate(slots * kPointerSize)); | 169 __ subq(rsp, Immediate(slots * kPointerSize)); |
| 170 #ifdef _MSC_VER | 170 #ifdef _MSC_VER |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 254 __ bind(&jump_table_[i].label); | 254 __ bind(&jump_table_[i].label); |
| 255 Address entry = jump_table_[i].address; | 255 Address entry = jump_table_[i].address; |
| 256 Deoptimizer::BailoutType type = jump_table_[i].bailout_type; | 256 Deoptimizer::BailoutType type = jump_table_[i].bailout_type; |
| 257 int id = Deoptimizer::GetDeoptimizationId(isolate(), entry, type); | 257 int id = Deoptimizer::GetDeoptimizationId(isolate(), entry, type); |
| 258 if (id == Deoptimizer::kNotDeoptimizationEntry) { | 258 if (id == Deoptimizer::kNotDeoptimizationEntry) { |
| 259 Comment(";;; jump table entry %d.", i); | 259 Comment(";;; jump table entry %d.", i); |
| 260 } else { | 260 } else { |
| 261 Comment(";;; jump table entry %d: deoptimization bailout %d.", i, id); | 261 Comment(";;; jump table entry %d: deoptimization bailout %d.", i, id); |
| 262 } | 262 } |
| 263 if (jump_table_[i].needs_frame) { | 263 if (jump_table_[i].needs_frame) { |
| 264 __ movq(kScratchRegister, ExternalReference::ForDeoptEntry(entry)); | 264 __ Move(kScratchRegister, ExternalReference::ForDeoptEntry(entry)); |
| 265 if (needs_frame.is_bound()) { | 265 if (needs_frame.is_bound()) { |
| 266 __ jmp(&needs_frame); | 266 __ jmp(&needs_frame); |
| 267 } else { | 267 } else { |
| 268 __ bind(&needs_frame); | 268 __ bind(&needs_frame); |
| 269 __ movq(rsi, MemOperand(rbp, StandardFrameConstants::kContextOffset)); |
| 269 __ push(rbp); | 270 __ push(rbp); |
| 270 __ movq(rbp, rsp); | 271 __ movq(rbp, rsp); |
| 271 __ push(rsi); | 272 __ push(rsi); |
| 272 // This variant of deopt can only be used with stubs. Since we don't | 273 // This variant of deopt can only be used with stubs. Since we don't |
| 273 // have a function pointer to install in the stack frame that we're | 274 // have a function pointer to install in the stack frame that we're |
| 274 // building, install a special marker there instead. | 275 // building, install a special marker there instead. |
| 275 ASSERT(info()->IsStub()); | 276 ASSERT(info()->IsStub()); |
| 276 __ Move(rsi, Smi::FromInt(StackFrame::STUB)); | 277 __ Move(rsi, Smi::FromInt(StackFrame::STUB)); |
| 277 __ push(rsi); | 278 __ push(rsi); |
| 278 __ movq(rsi, MemOperand(rsp, kPointerSize)); | 279 __ movq(rsi, MemOperand(rsp, kPointerSize)); |
| (...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 582 SaveFPRegsMode save_doubles) { | 583 SaveFPRegsMode save_doubles) { |
| 583 ASSERT(instr != NULL); | 584 ASSERT(instr != NULL); |
| 584 ASSERT(instr->HasPointerMap()); | 585 ASSERT(instr->HasPointerMap()); |
| 585 | 586 |
| 586 __ CallRuntime(function, num_arguments, save_doubles); | 587 __ CallRuntime(function, num_arguments, save_doubles); |
| 587 | 588 |
| 588 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT, 0); | 589 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT, 0); |
| 589 } | 590 } |
| 590 | 591 |
| 591 | 592 |
| 593 void LCodeGen::LoadContextFromDeferred(LOperand* context) { |
| 594 if (context->IsRegister()) { |
| 595 if (!ToRegister(context).is(rsi)) { |
| 596 __ movq(rsi, ToRegister(context)); |
| 597 } |
| 598 } else if (context->IsStackSlot()) { |
| 599 __ movq(rsi, ToOperand(context)); |
| 600 } else if (context->IsConstantOperand()) { |
| 601 HConstant* constant = |
| 602 chunk_->LookupConstant(LConstantOperand::cast(context)); |
| 603 __ Move(rsi, Handle<Object>::cast(constant->handle(isolate()))); |
| 604 } else { |
| 605 UNREACHABLE(); |
| 606 } |
| 607 } |
| 608 |
| 609 |
| 610 |
| 592 void LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id, | 611 void LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id, |
| 593 int argc, | 612 int argc, |
| 594 LInstruction* instr) { | 613 LInstruction* instr, |
| 595 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 614 LOperand* context) { |
| 615 LoadContextFromDeferred(context); |
| 616 |
| 596 __ CallRuntimeSaveDoubles(id); | 617 __ CallRuntimeSaveDoubles(id); |
| 597 RecordSafepointWithRegisters( | 618 RecordSafepointWithRegisters( |
| 598 instr->pointer_map(), argc, Safepoint::kNoLazyDeopt); | 619 instr->pointer_map(), argc, Safepoint::kNoLazyDeopt); |
| 599 } | 620 } |
| 600 | 621 |
| 601 | 622 |
| 602 void LCodeGen::RegisterEnvironmentForDeoptimization(LEnvironment* environment, | 623 void LCodeGen::RegisterEnvironmentForDeoptimization(LEnvironment* environment, |
| 603 Safepoint::DeoptMode mode) { | 624 Safepoint::DeoptMode mode) { |
| 604 if (!environment->HasBeenRegistered()) { | 625 if (!environment->HasBeenRegistered()) { |
| 605 // Physical stack frame layout: | 626 // Physical stack frame layout: |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 642 ASSERT(environment->HasBeenRegistered()); | 663 ASSERT(environment->HasBeenRegistered()); |
| 643 int id = environment->deoptimization_index(); | 664 int id = environment->deoptimization_index(); |
| 644 ASSERT(info()->IsOptimizing() || info()->IsStub()); | 665 ASSERT(info()->IsOptimizing() || info()->IsStub()); |
| 645 Address entry = | 666 Address entry = |
| 646 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type); | 667 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type); |
| 647 if (entry == NULL) { | 668 if (entry == NULL) { |
| 648 Abort(kBailoutWasNotPrepared); | 669 Abort(kBailoutWasNotPrepared); |
| 649 return; | 670 return; |
| 650 } | 671 } |
| 651 | 672 |
| 652 ASSERT(FLAG_deopt_every_n_times == 0); // Not yet implemented on x64. | 673 if (DeoptEveryNTimes()) { |
| 674 ExternalReference count = ExternalReference::stress_deopt_count(isolate()); |
| 675 Label no_deopt; |
| 676 __ pushfq(); |
| 677 __ push(rax); |
| 678 Operand count_operand = masm()->ExternalOperand(count, kScratchRegister); |
| 679 __ movl(rax, count_operand); |
| 680 __ subl(rax, Immediate(1)); |
| 681 __ j(not_zero, &no_deopt, Label::kNear); |
| 682 if (FLAG_trap_on_deopt) __ int3(); |
| 683 __ movl(rax, Immediate(FLAG_deopt_every_n_times)); |
| 684 __ movl(count_operand, rax); |
| 685 __ pop(rax); |
| 686 __ popfq(); |
| 687 ASSERT(frame_is_built_); |
| 688 __ call(entry, RelocInfo::RUNTIME_ENTRY); |
| 689 __ bind(&no_deopt); |
| 690 __ movl(count_operand, rax); |
| 691 __ pop(rax); |
| 692 __ popfq(); |
| 693 } |
| 653 | 694 |
| 654 if (info()->ShouldTrapOnDeopt()) { | 695 if (info()->ShouldTrapOnDeopt()) { |
| 655 Label done; | 696 Label done; |
| 656 if (cc != no_condition) { | 697 if (cc != no_condition) { |
| 657 __ j(NegateCondition(cc), &done, Label::kNear); | 698 __ j(NegateCondition(cc), &done, Label::kNear); |
| 658 } | 699 } |
| 659 __ int3(); | 700 __ int3(); |
| 660 __ bind(&done); | 701 __ bind(&done); |
| 661 } | 702 } |
| 662 | 703 |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 809 Safepoint safepoint = safepoints_.DefineSafepoint(masm(), | 850 Safepoint safepoint = safepoints_.DefineSafepoint(masm(), |
| 810 kind, arguments, deopt_mode); | 851 kind, arguments, deopt_mode); |
| 811 for (int i = 0; i < operands->length(); i++) { | 852 for (int i = 0; i < operands->length(); i++) { |
| 812 LOperand* pointer = operands->at(i); | 853 LOperand* pointer = operands->at(i); |
| 813 if (pointer->IsStackSlot()) { | 854 if (pointer->IsStackSlot()) { |
| 814 safepoint.DefinePointerSlot(pointer->index(), zone()); | 855 safepoint.DefinePointerSlot(pointer->index(), zone()); |
| 815 } else if (pointer->IsRegister() && (kind & Safepoint::kWithRegisters)) { | 856 } else if (pointer->IsRegister() && (kind & Safepoint::kWithRegisters)) { |
| 816 safepoint.DefinePointerRegister(ToRegister(pointer), zone()); | 857 safepoint.DefinePointerRegister(ToRegister(pointer), zone()); |
| 817 } | 858 } |
| 818 } | 859 } |
| 819 if (kind & Safepoint::kWithRegisters) { | |
| 820 // Register rsi always contains a pointer to the context. | |
| 821 safepoint.DefinePointerRegister(rsi, zone()); | |
| 822 } | |
| 823 } | 860 } |
| 824 | 861 |
| 825 | 862 |
| 826 void LCodeGen::RecordSafepoint(LPointerMap* pointers, | 863 void LCodeGen::RecordSafepoint(LPointerMap* pointers, |
| 827 Safepoint::DeoptMode deopt_mode) { | 864 Safepoint::DeoptMode deopt_mode) { |
| 828 RecordSafepoint(pointers, Safepoint::kSimple, 0, deopt_mode); | 865 RecordSafepoint(pointers, Safepoint::kSimple, 0, deopt_mode); |
| 829 } | 866 } |
| 830 | 867 |
| 831 | 868 |
| 832 void LCodeGen::RecordSafepoint(Safepoint::DeoptMode deopt_mode) { | 869 void LCodeGen::RecordSafepoint(Safepoint::DeoptMode deopt_mode) { |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 888 DoGap(instr); | 925 DoGap(instr); |
| 889 } | 926 } |
| 890 | 927 |
| 891 | 928 |
| 892 void LCodeGen::DoParameter(LParameter* instr) { | 929 void LCodeGen::DoParameter(LParameter* instr) { |
| 893 // Nothing to do. | 930 // Nothing to do. |
| 894 } | 931 } |
| 895 | 932 |
| 896 | 933 |
| 897 void LCodeGen::DoCallStub(LCallStub* instr) { | 934 void LCodeGen::DoCallStub(LCallStub* instr) { |
| 935 ASSERT(ToRegister(instr->context()).is(rsi)); |
| 898 ASSERT(ToRegister(instr->result()).is(rax)); | 936 ASSERT(ToRegister(instr->result()).is(rax)); |
| 899 switch (instr->hydrogen()->major_key()) { | 937 switch (instr->hydrogen()->major_key()) { |
| 900 case CodeStub::RegExpConstructResult: { | 938 case CodeStub::RegExpConstructResult: { |
| 901 RegExpConstructResultStub stub; | 939 RegExpConstructResultStub stub; |
| 902 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 940 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 903 break; | 941 break; |
| 904 } | 942 } |
| 905 case CodeStub::RegExpExec: { | 943 case CodeStub::RegExpExec: { |
| 906 RegExpExecStub stub; | 944 RegExpExecStub stub; |
| 907 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 945 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| (...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1116 // The multiplier is a uint32. | 1154 // The multiplier is a uint32. |
| 1117 ASSERT(multiplier > 0 && | 1155 ASSERT(multiplier > 0 && |
| 1118 multiplier < (static_cast<int64_t>(1) << 32)); | 1156 multiplier < (static_cast<int64_t>(1) << 32)); |
| 1119 // The multiply is int64, so sign-extend to r64. | 1157 // The multiply is int64, so sign-extend to r64. |
| 1120 __ movsxlq(reg1, dividend); | 1158 __ movsxlq(reg1, dividend); |
| 1121 if (divisor < 0 && | 1159 if (divisor < 0 && |
| 1122 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1160 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1123 __ neg(reg1); | 1161 __ neg(reg1); |
| 1124 DeoptimizeIf(zero, instr->environment()); | 1162 DeoptimizeIf(zero, instr->environment()); |
| 1125 } | 1163 } |
| 1126 __ movq(reg2, multiplier, RelocInfo::NONE64); | 1164 __ Set(reg2, multiplier); |
| 1127 // Result just fit in r64, because it's int32 * uint32. | 1165 // Result just fit in r64, because it's int32 * uint32. |
| 1128 __ imul(reg2, reg1); | 1166 __ imul(reg2, reg1); |
| 1129 | 1167 |
| 1130 __ addq(reg2, Immediate(1 << 30)); | 1168 __ addq(reg2, Immediate(1 << 30)); |
| 1131 __ sar(reg2, Immediate(shift)); | 1169 __ sar(reg2, Immediate(shift)); |
| 1132 } | 1170 } |
| 1133 } | 1171 } |
| 1134 | 1172 |
| 1135 | 1173 |
| 1136 void LCodeGen::DoDivI(LDivI* instr) { | 1174 void LCodeGen::DoDivI(LDivI* instr) { |
| (...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1612 } else { | 1650 } else { |
| 1613 if (index->value() < JSDate::kFirstUncachedField) { | 1651 if (index->value() < JSDate::kFirstUncachedField) { |
| 1614 ExternalReference stamp = ExternalReference::date_cache_stamp(isolate()); | 1652 ExternalReference stamp = ExternalReference::date_cache_stamp(isolate()); |
| 1615 Operand stamp_operand = __ ExternalOperand(stamp); | 1653 Operand stamp_operand = __ ExternalOperand(stamp); |
| 1616 __ movq(kScratchRegister, stamp_operand); | 1654 __ movq(kScratchRegister, stamp_operand); |
| 1617 __ cmpq(kScratchRegister, FieldOperand(object, | 1655 __ cmpq(kScratchRegister, FieldOperand(object, |
| 1618 JSDate::kCacheStampOffset)); | 1656 JSDate::kCacheStampOffset)); |
| 1619 __ j(not_equal, &runtime, Label::kNear); | 1657 __ j(not_equal, &runtime, Label::kNear); |
| 1620 __ movq(result, FieldOperand(object, JSDate::kValueOffset + | 1658 __ movq(result, FieldOperand(object, JSDate::kValueOffset + |
| 1621 kPointerSize * index->value())); | 1659 kPointerSize * index->value())); |
| 1622 __ jmp(&done); | 1660 __ jmp(&done, Label::kNear); |
| 1623 } | 1661 } |
| 1624 __ bind(&runtime); | 1662 __ bind(&runtime); |
| 1625 __ PrepareCallCFunction(2); | 1663 __ PrepareCallCFunction(2); |
| 1626 __ movq(arg_reg_1, object); | 1664 __ movq(arg_reg_1, object); |
| 1627 __ movq(arg_reg_2, index, RelocInfo::NONE64); | 1665 __ movq(arg_reg_2, index, RelocInfo::NONE64); |
| 1628 __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2); | 1666 __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2); |
| 1629 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | |
| 1630 __ bind(&done); | 1667 __ bind(&done); |
| 1631 } | 1668 } |
| 1632 } | 1669 } |
| 1633 | 1670 |
| 1634 | 1671 |
| 1635 Operand LCodeGen::BuildSeqStringOperand(Register string, | 1672 Operand LCodeGen::BuildSeqStringOperand(Register string, |
| 1636 LOperand* index, | 1673 LOperand* index, |
| 1637 String::Encoding encoding) { | 1674 String::Encoding encoding) { |
| 1638 if (index->IsConstantOperand()) { | 1675 if (index->IsConstantOperand()) { |
| 1639 int offset = ToInteger32(LConstantOperand::cast(index)); | 1676 int offset = ToInteger32(LConstantOperand::cast(index)); |
| 1640 if (encoding == String::TWO_BYTE_ENCODING) { | 1677 if (encoding == String::TWO_BYTE_ENCODING) { |
| 1641 offset *= kUC16Size; | 1678 offset *= kUC16Size; |
| 1642 } | 1679 } |
| 1643 STATIC_ASSERT(kCharSize == 1); | 1680 STATIC_ASSERT(kCharSize == 1); |
| 1644 return FieldOperand(string, SeqString::kHeaderSize + offset); | 1681 return FieldOperand(string, SeqString::kHeaderSize + offset); |
| 1645 } | 1682 } |
| 1646 return FieldOperand( | 1683 return FieldOperand( |
| 1647 string, ToRegister(index), | 1684 string, ToRegister(index), |
| 1648 encoding == String::ONE_BYTE_ENCODING ? times_1 : times_2, | 1685 encoding == String::ONE_BYTE_ENCODING ? times_1 : times_2, |
| 1649 SeqString::kHeaderSize); | 1686 SeqString::kHeaderSize); |
| 1650 } | 1687 } |
| 1651 | 1688 |
| 1652 | 1689 |
| 1690 void LCodeGen::DoSeqStringGetChar(LSeqStringGetChar* instr) { |
| 1691 String::Encoding encoding = instr->hydrogen()->encoding(); |
| 1692 Register result = ToRegister(instr->result()); |
| 1693 Register string = ToRegister(instr->string()); |
| 1694 |
| 1695 if (FLAG_debug_code) { |
| 1696 __ push(string); |
| 1697 __ movq(string, FieldOperand(string, HeapObject::kMapOffset)); |
| 1698 __ movzxbq(string, FieldOperand(string, Map::kInstanceTypeOffset)); |
| 1699 |
| 1700 __ andb(string, Immediate(kStringRepresentationMask | kStringEncodingMask)); |
| 1701 static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag; |
| 1702 static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag; |
| 1703 __ cmpq(string, Immediate(encoding == String::ONE_BYTE_ENCODING |
| 1704 ? one_byte_seq_type : two_byte_seq_type)); |
| 1705 __ Check(equal, kUnexpectedStringType); |
| 1706 __ pop(string); |
| 1707 } |
| 1708 |
| 1709 Operand operand = BuildSeqStringOperand(string, instr->index(), encoding); |
| 1710 if (encoding == String::ONE_BYTE_ENCODING) { |
| 1711 __ movzxbl(result, operand); |
| 1712 } else { |
| 1713 __ movzxwl(result, operand); |
| 1714 } |
| 1715 } |
| 1716 |
| 1717 |
| 1653 void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) { | 1718 void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) { |
| 1654 String::Encoding encoding = instr->hydrogen()->encoding(); | 1719 String::Encoding encoding = instr->hydrogen()->encoding(); |
| 1655 Register string = ToRegister(instr->string()); | 1720 Register string = ToRegister(instr->string()); |
| 1656 | 1721 |
| 1657 if (FLAG_debug_code) { | 1722 if (FLAG_debug_code) { |
| 1658 __ push(string); | 1723 __ push(string); |
| 1659 __ movq(string, FieldOperand(string, HeapObject::kMapOffset)); | 1724 __ movq(string, FieldOperand(string, HeapObject::kMapOffset)); |
| 1660 __ movzxbq(string, FieldOperand(string, Map::kInstanceTypeOffset)); | 1725 __ movzxbq(string, FieldOperand(string, Map::kInstanceTypeOffset)); |
| 1661 | 1726 |
| 1662 __ andb(string, Immediate(kStringRepresentationMask | kStringEncodingMask)); | 1727 __ andb(string, Immediate(kStringRepresentationMask | kStringEncodingMask)); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1685 __ movb(operand, value); | 1750 __ movb(operand, value); |
| 1686 } else { | 1751 } else { |
| 1687 __ movw(operand, value); | 1752 __ movw(operand, value); |
| 1688 } | 1753 } |
| 1689 } | 1754 } |
| 1690 } | 1755 } |
| 1691 | 1756 |
| 1692 | 1757 |
| 1693 void LCodeGen::DoThrow(LThrow* instr) { | 1758 void LCodeGen::DoThrow(LThrow* instr) { |
| 1694 __ push(ToRegister(instr->value())); | 1759 __ push(ToRegister(instr->value())); |
| 1760 ASSERT(ToRegister(instr->context()).is(rsi)); |
| 1695 CallRuntime(Runtime::kThrow, 1, instr); | 1761 CallRuntime(Runtime::kThrow, 1, instr); |
| 1696 | 1762 |
| 1697 if (FLAG_debug_code) { | 1763 if (FLAG_debug_code) { |
| 1698 Comment("Unreachable code."); | 1764 Comment("Unreachable code."); |
| 1699 __ int3(); | 1765 __ int3(); |
| 1700 } | 1766 } |
| 1701 } | 1767 } |
| 1702 | 1768 |
| 1703 | 1769 |
| 1704 void LCodeGen::DoAddI(LAddI* instr) { | 1770 void LCodeGen::DoAddI(LAddI* instr) { |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1839 // when there is a mulsd depending on the result | 1905 // when there is a mulsd depending on the result |
| 1840 __ movaps(left, left); | 1906 __ movaps(left, left); |
| 1841 break; | 1907 break; |
| 1842 case Token::MOD: { | 1908 case Token::MOD: { |
| 1843 XMMRegister xmm_scratch = double_scratch0(); | 1909 XMMRegister xmm_scratch = double_scratch0(); |
| 1844 __ PrepareCallCFunction(2); | 1910 __ PrepareCallCFunction(2); |
| 1845 __ movaps(xmm_scratch, left); | 1911 __ movaps(xmm_scratch, left); |
| 1846 ASSERT(right.is(xmm1)); | 1912 ASSERT(right.is(xmm1)); |
| 1847 __ CallCFunction( | 1913 __ CallCFunction( |
| 1848 ExternalReference::double_fp_operation(Token::MOD, isolate()), 2); | 1914 ExternalReference::double_fp_operation(Token::MOD, isolate()), 2); |
| 1849 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | |
| 1850 __ movaps(result, xmm_scratch); | 1915 __ movaps(result, xmm_scratch); |
| 1851 break; | 1916 break; |
| 1852 } | 1917 } |
| 1853 default: | 1918 default: |
| 1854 UNREACHABLE(); | 1919 UNREACHABLE(); |
| 1855 break; | 1920 break; |
| 1856 } | 1921 } |
| 1857 } | 1922 } |
| 1858 | 1923 |
| 1859 | 1924 |
| 1860 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { | 1925 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { |
| 1926 ASSERT(ToRegister(instr->context()).is(rsi)); |
| 1861 ASSERT(ToRegister(instr->left()).is(rdx)); | 1927 ASSERT(ToRegister(instr->left()).is(rdx)); |
| 1862 ASSERT(ToRegister(instr->right()).is(rax)); | 1928 ASSERT(ToRegister(instr->right()).is(rax)); |
| 1863 ASSERT(ToRegister(instr->result()).is(rax)); | 1929 ASSERT(ToRegister(instr->result()).is(rax)); |
| 1864 | 1930 |
| 1865 BinaryOpStub stub(instr->op(), NO_OVERWRITE); | 1931 BinaryOpStub stub(instr->op(), NO_OVERWRITE); |
| 1866 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 1932 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 1867 __ nop(); // Signals no inlined code. | 1933 __ nop(); // Signals no inlined code. |
| 1868 } | 1934 } |
| 1869 | 1935 |
| 1870 | 1936 |
| (...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2265 __ JumpIfSmi(input, instr->FalseLabel(chunk_)); | 2331 __ JumpIfSmi(input, instr->FalseLabel(chunk_)); |
| 2266 } | 2332 } |
| 2267 __ movq(temp, FieldOperand(input, HeapObject::kMapOffset)); | 2333 __ movq(temp, FieldOperand(input, HeapObject::kMapOffset)); |
| 2268 __ testb(FieldOperand(temp, Map::kBitFieldOffset), | 2334 __ testb(FieldOperand(temp, Map::kBitFieldOffset), |
| 2269 Immediate(1 << Map::kIsUndetectable)); | 2335 Immediate(1 << Map::kIsUndetectable)); |
| 2270 EmitBranch(instr, not_zero); | 2336 EmitBranch(instr, not_zero); |
| 2271 } | 2337 } |
| 2272 | 2338 |
| 2273 | 2339 |
| 2274 void LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) { | 2340 void LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) { |
| 2341 ASSERT(ToRegister(instr->context()).is(rsi)); |
| 2275 Token::Value op = instr->op(); | 2342 Token::Value op = instr->op(); |
| 2276 | 2343 |
| 2277 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); | 2344 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); |
| 2278 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2345 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 2279 | 2346 |
| 2280 Condition condition = TokenToCondition(op, false); | 2347 Condition condition = TokenToCondition(op, false); |
| 2281 __ testq(rax, rax); | 2348 __ testq(rax, rax); |
| 2282 | 2349 |
| 2283 EmitBranch(instr, condition); | 2350 EmitBranch(instr, condition); |
| 2284 } | 2351 } |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2421 | 2488 |
| 2422 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { | 2489 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { |
| 2423 Register reg = ToRegister(instr->value()); | 2490 Register reg = ToRegister(instr->value()); |
| 2424 | 2491 |
| 2425 __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map()); | 2492 __ Cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map()); |
| 2426 EmitBranch(instr, equal); | 2493 EmitBranch(instr, equal); |
| 2427 } | 2494 } |
| 2428 | 2495 |
| 2429 | 2496 |
| 2430 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { | 2497 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { |
| 2498 ASSERT(ToRegister(instr->context()).is(rsi)); |
| 2431 InstanceofStub stub(InstanceofStub::kNoFlags); | 2499 InstanceofStub stub(InstanceofStub::kNoFlags); |
| 2432 __ push(ToRegister(instr->left())); | 2500 __ push(ToRegister(instr->left())); |
| 2433 __ push(ToRegister(instr->right())); | 2501 __ push(ToRegister(instr->right())); |
| 2434 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 2502 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 2435 Label true_value, done; | 2503 Label true_value, done; |
| 2436 __ testq(rax, rax); | 2504 __ testq(rax, rax); |
| 2437 __ j(zero, &true_value, Label::kNear); | 2505 __ j(zero, &true_value, Label::kNear); |
| 2438 __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex); | 2506 __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex); |
| 2439 __ jmp(&done, Label::kNear); | 2507 __ jmp(&done, Label::kNear); |
| 2440 __ bind(&true_value); | 2508 __ bind(&true_value); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2452 virtual void Generate() V8_OVERRIDE { | 2520 virtual void Generate() V8_OVERRIDE { |
| 2453 codegen()->DoDeferredInstanceOfKnownGlobal(instr_, &map_check_); | 2521 codegen()->DoDeferredInstanceOfKnownGlobal(instr_, &map_check_); |
| 2454 } | 2522 } |
| 2455 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } | 2523 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
| 2456 Label* map_check() { return &map_check_; } | 2524 Label* map_check() { return &map_check_; } |
| 2457 private: | 2525 private: |
| 2458 LInstanceOfKnownGlobal* instr_; | 2526 LInstanceOfKnownGlobal* instr_; |
| 2459 Label map_check_; | 2527 Label map_check_; |
| 2460 }; | 2528 }; |
| 2461 | 2529 |
| 2462 | 2530 ASSERT(ToRegister(instr->context()).is(rsi)); |
| 2463 DeferredInstanceOfKnownGlobal* deferred; | 2531 DeferredInstanceOfKnownGlobal* deferred; |
| 2464 deferred = new(zone()) DeferredInstanceOfKnownGlobal(this, instr); | 2532 deferred = new(zone()) DeferredInstanceOfKnownGlobal(this, instr); |
| 2465 | 2533 |
| 2466 Label done, false_result; | 2534 Label done, false_result; |
| 2467 Register object = ToRegister(instr->value()); | 2535 Register object = ToRegister(instr->value()); |
| 2468 | 2536 |
| 2469 // A Smi is not an instance of anything. | 2537 // A Smi is not an instance of anything. |
| 2470 __ JumpIfSmi(object, &false_result); | 2538 __ JumpIfSmi(object, &false_result, Label::kNear); |
| 2471 | 2539 |
| 2472 // This is the inlined call site instanceof cache. The two occurences of the | 2540 // This is the inlined call site instanceof cache. The two occurences of the |
| 2473 // hole value will be patched to the last map/result pair generated by the | 2541 // hole value will be patched to the last map/result pair generated by the |
| 2474 // instanceof stub. | 2542 // instanceof stub. |
| 2475 Label cache_miss; | 2543 Label cache_miss; |
| 2476 // Use a temp register to avoid memory operands with variable lengths. | 2544 // Use a temp register to avoid memory operands with variable lengths. |
| 2477 Register map = ToRegister(instr->temp()); | 2545 Register map = ToRegister(instr->temp()); |
| 2478 __ movq(map, FieldOperand(object, HeapObject::kMapOffset)); | 2546 __ movq(map, FieldOperand(object, HeapObject::kMapOffset)); |
| 2479 __ bind(deferred->map_check()); // Label for calculating code patching. | 2547 __ bind(deferred->map_check()); // Label for calculating code patching. |
| 2480 Handle<Cell> cache_cell = factory()->NewCell(factory()->the_hole_value()); | 2548 Handle<Cell> cache_cell = factory()->NewCell(factory()->the_hole_value()); |
| 2481 __ movq(kScratchRegister, cache_cell, RelocInfo::CELL); | 2549 __ movq(kScratchRegister, cache_cell, RelocInfo::CELL); |
| 2482 __ cmpq(map, Operand(kScratchRegister, 0)); | 2550 __ cmpq(map, Operand(kScratchRegister, 0)); |
| 2483 __ j(not_equal, &cache_miss, Label::kNear); | 2551 __ j(not_equal, &cache_miss, Label::kNear); |
| 2484 // Patched to load either true or false. | 2552 // Patched to load either true or false. |
| 2485 __ LoadRoot(ToRegister(instr->result()), Heap::kTheHoleValueRootIndex); | 2553 __ LoadRoot(ToRegister(instr->result()), Heap::kTheHoleValueRootIndex); |
| 2486 #ifdef DEBUG | 2554 #ifdef DEBUG |
| 2487 // Check that the code size between patch label and patch sites is invariant. | 2555 // Check that the code size between patch label and patch sites is invariant. |
| 2488 Label end_of_patched_code; | 2556 Label end_of_patched_code; |
| 2489 __ bind(&end_of_patched_code); | 2557 __ bind(&end_of_patched_code); |
| 2490 ASSERT(true); | 2558 ASSERT(true); |
| 2491 #endif | 2559 #endif |
| 2492 __ jmp(&done); | 2560 __ jmp(&done, Label::kNear); |
| 2493 | 2561 |
| 2494 // The inlined call site cache did not match. Check for null and string | 2562 // The inlined call site cache did not match. Check for null and string |
| 2495 // before calling the deferred code. | 2563 // before calling the deferred code. |
| 2496 __ bind(&cache_miss); // Null is not an instance of anything. | 2564 __ bind(&cache_miss); // Null is not an instance of anything. |
| 2497 __ CompareRoot(object, Heap::kNullValueRootIndex); | 2565 __ CompareRoot(object, Heap::kNullValueRootIndex); |
| 2498 __ j(equal, &false_result, Label::kNear); | 2566 __ j(equal, &false_result, Label::kNear); |
| 2499 | 2567 |
| 2500 // String values are not instances of anything. | 2568 // String values are not instances of anything. |
| 2501 __ JumpIfNotString(object, kScratchRegister, deferred->entry()); | 2569 __ JumpIfNotString(object, kScratchRegister, deferred->entry()); |
| 2502 | 2570 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2537 ASSERT(delta == masm_->SizeOfCodeGeneratedSince(map_check)); | 2605 ASSERT(delta == masm_->SizeOfCodeGeneratedSince(map_check)); |
| 2538 LEnvironment* env = instr->GetDeferredLazyDeoptimizationEnvironment(); | 2606 LEnvironment* env = instr->GetDeferredLazyDeoptimizationEnvironment(); |
| 2539 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); | 2607 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); |
| 2540 // Move result to a register that survives the end of the | 2608 // Move result to a register that survives the end of the |
| 2541 // PushSafepointRegisterScope. | 2609 // PushSafepointRegisterScope. |
| 2542 __ movq(kScratchRegister, rax); | 2610 __ movq(kScratchRegister, rax); |
| 2543 } | 2611 } |
| 2544 __ testq(kScratchRegister, kScratchRegister); | 2612 __ testq(kScratchRegister, kScratchRegister); |
| 2545 Label load_false; | 2613 Label load_false; |
| 2546 Label done; | 2614 Label done; |
| 2547 __ j(not_zero, &load_false); | 2615 __ j(not_zero, &load_false, Label::kNear); |
| 2548 __ LoadRoot(rax, Heap::kTrueValueRootIndex); | 2616 __ LoadRoot(rax, Heap::kTrueValueRootIndex); |
| 2549 __ jmp(&done); | 2617 __ jmp(&done, Label::kNear); |
| 2550 __ bind(&load_false); | 2618 __ bind(&load_false); |
| 2551 __ LoadRoot(rax, Heap::kFalseValueRootIndex); | 2619 __ LoadRoot(rax, Heap::kFalseValueRootIndex); |
| 2552 __ bind(&done); | 2620 __ bind(&done); |
| 2553 } | 2621 } |
| 2554 | 2622 |
| 2555 | 2623 |
| 2556 void LCodeGen::DoCmpT(LCmpT* instr) { | 2624 void LCodeGen::DoCmpT(LCmpT* instr) { |
| 2625 ASSERT(ToRegister(instr->context()).is(rsi)); |
| 2557 Token::Value op = instr->op(); | 2626 Token::Value op = instr->op(); |
| 2558 | 2627 |
| 2559 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); | 2628 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); |
| 2560 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2629 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 2561 | 2630 |
| 2562 Condition condition = TokenToCondition(op, false); | 2631 Condition condition = TokenToCondition(op, false); |
| 2563 Label true_value, done; | 2632 Label true_value, done; |
| 2564 __ testq(rax, rax); | 2633 __ testq(rax, rax); |
| 2565 __ j(condition, &true_value, Label::kNear); | 2634 __ j(condition, &true_value, Label::kNear); |
| 2566 __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex); | 2635 __ LoadRoot(ToRegister(instr->result()), Heap::kFalseValueRootIndex); |
| 2567 __ jmp(&done, Label::kNear); | 2636 __ jmp(&done, Label::kNear); |
| 2568 __ bind(&true_value); | 2637 __ bind(&true_value); |
| 2569 __ LoadRoot(ToRegister(instr->result()), Heap::kTrueValueRootIndex); | 2638 __ LoadRoot(ToRegister(instr->result()), Heap::kTrueValueRootIndex); |
| 2570 __ bind(&done); | 2639 __ bind(&done); |
| 2571 } | 2640 } |
| 2572 | 2641 |
| 2573 | 2642 |
| 2574 void LCodeGen::DoReturn(LReturn* instr) { | 2643 void LCodeGen::DoReturn(LReturn* instr) { |
| 2575 if (FLAG_trace && info()->IsOptimizing()) { | 2644 if (FLAG_trace && info()->IsOptimizing()) { |
| 2576 // Preserve the return value on the stack and rely on the runtime | 2645 // Preserve the return value on the stack and rely on the runtime call |
| 2577 // call to return the value in the same register. | 2646 // to return the value in the same register. We're leaving the code |
| 2647 // managed by the register allocator and tearing down the frame, it's |
| 2648 // safe to write to the context register. |
| 2578 __ push(rax); | 2649 __ push(rax); |
| 2650 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 2579 __ CallRuntime(Runtime::kTraceExit, 1); | 2651 __ CallRuntime(Runtime::kTraceExit, 1); |
| 2580 } | 2652 } |
| 2581 if (info()->saves_caller_doubles()) { | 2653 if (info()->saves_caller_doubles()) { |
| 2582 ASSERT(NeedsEagerFrame()); | 2654 ASSERT(NeedsEagerFrame()); |
| 2583 BitVector* doubles = chunk()->allocated_double_registers(); | 2655 BitVector* doubles = chunk()->allocated_double_registers(); |
| 2584 BitVector::Iterator save_iterator(doubles); | 2656 BitVector::Iterator save_iterator(doubles); |
| 2585 int count = 0; | 2657 int count = 0; |
| 2586 while (!save_iterator.Done()) { | 2658 while (!save_iterator.Done()) { |
| 2587 __ movsd(XMMRegister::FromAllocationIndex(save_iterator.Current()), | 2659 __ movsd(XMMRegister::FromAllocationIndex(save_iterator.Current()), |
| 2588 MemOperand(rsp, count * kDoubleSize)); | 2660 MemOperand(rsp, count * kDoubleSize)); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 2619 Register result = ToRegister(instr->result()); | 2691 Register result = ToRegister(instr->result()); |
| 2620 __ LoadGlobalCell(result, instr->hydrogen()->cell().handle()); | 2692 __ LoadGlobalCell(result, instr->hydrogen()->cell().handle()); |
| 2621 if (instr->hydrogen()->RequiresHoleCheck()) { | 2693 if (instr->hydrogen()->RequiresHoleCheck()) { |
| 2622 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); | 2694 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); |
| 2623 DeoptimizeIf(equal, instr->environment()); | 2695 DeoptimizeIf(equal, instr->environment()); |
| 2624 } | 2696 } |
| 2625 } | 2697 } |
| 2626 | 2698 |
| 2627 | 2699 |
| 2628 void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { | 2700 void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { |
| 2701 ASSERT(ToRegister(instr->context()).is(rsi)); |
| 2629 ASSERT(ToRegister(instr->global_object()).is(rax)); | 2702 ASSERT(ToRegister(instr->global_object()).is(rax)); |
| 2630 ASSERT(ToRegister(instr->result()).is(rax)); | 2703 ASSERT(ToRegister(instr->result()).is(rax)); |
| 2631 | 2704 |
| 2632 __ Move(rcx, instr->name()); | 2705 __ Move(rcx, instr->name()); |
| 2633 RelocInfo::Mode mode = instr->for_typeof() ? RelocInfo::CODE_TARGET : | 2706 RelocInfo::Mode mode = instr->for_typeof() ? RelocInfo::CODE_TARGET : |
| 2634 RelocInfo::CODE_TARGET_CONTEXT; | 2707 RelocInfo::CODE_TARGET_CONTEXT; |
| 2635 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 2708 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
| 2636 CallCode(ic, mode, instr); | 2709 CallCode(ic, mode, instr); |
| 2637 } | 2710 } |
| 2638 | 2711 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 2657 } else { | 2730 } else { |
| 2658 // Store the value. | 2731 // Store the value. |
| 2659 __ movq(kScratchRegister, cell_handle, RelocInfo::CELL); | 2732 __ movq(kScratchRegister, cell_handle, RelocInfo::CELL); |
| 2660 __ movq(Operand(kScratchRegister, 0), value); | 2733 __ movq(Operand(kScratchRegister, 0), value); |
| 2661 } | 2734 } |
| 2662 // Cells are always rescanned, so no write barrier here. | 2735 // Cells are always rescanned, so no write barrier here. |
| 2663 } | 2736 } |
| 2664 | 2737 |
| 2665 | 2738 |
| 2666 void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) { | 2739 void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) { |
| 2740 ASSERT(ToRegister(instr->context()).is(rsi)); |
| 2667 ASSERT(ToRegister(instr->global_object()).is(rdx)); | 2741 ASSERT(ToRegister(instr->global_object()).is(rdx)); |
| 2668 ASSERT(ToRegister(instr->value()).is(rax)); | 2742 ASSERT(ToRegister(instr->value()).is(rax)); |
| 2669 | 2743 |
| 2670 __ Move(rcx, instr->name()); | 2744 __ Move(rcx, instr->name()); |
| 2671 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) | 2745 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) |
| 2672 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 2746 ? isolate()->builtins()->StoreIC_Initialize_Strict() |
| 2673 : isolate()->builtins()->StoreIC_Initialize(); | 2747 : isolate()->builtins()->StoreIC_Initialize(); |
| 2674 CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr); | 2748 CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr); |
| 2675 } | 2749 } |
| 2676 | 2750 |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2756 Register result = ToRegister(instr->result()); | 2830 Register result = ToRegister(instr->result()); |
| 2757 if (!access.IsInobject()) { | 2831 if (!access.IsInobject()) { |
| 2758 __ movq(result, FieldOperand(object, JSObject::kPropertiesOffset)); | 2832 __ movq(result, FieldOperand(object, JSObject::kPropertiesOffset)); |
| 2759 object = result; | 2833 object = result; |
| 2760 } | 2834 } |
| 2761 __ Load(result, FieldOperand(object, offset), access.representation()); | 2835 __ Load(result, FieldOperand(object, offset), access.representation()); |
| 2762 } | 2836 } |
| 2763 | 2837 |
| 2764 | 2838 |
| 2765 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { | 2839 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { |
| 2840 ASSERT(ToRegister(instr->context()).is(rsi)); |
| 2766 ASSERT(ToRegister(instr->object()).is(rax)); | 2841 ASSERT(ToRegister(instr->object()).is(rax)); |
| 2767 ASSERT(ToRegister(instr->result()).is(rax)); | 2842 ASSERT(ToRegister(instr->result()).is(rax)); |
| 2768 | 2843 |
| 2769 __ Move(rcx, instr->name()); | 2844 __ Move(rcx, instr->name()); |
| 2770 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 2845 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
| 2771 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2846 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 2772 } | 2847 } |
| 2773 | 2848 |
| 2774 | 2849 |
| 2775 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { | 2850 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { |
| (...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3035 ScaleFactor scale_factor = static_cast<ScaleFactor>(shift_size); | 3110 ScaleFactor scale_factor = static_cast<ScaleFactor>(shift_size); |
| 3036 return Operand(elements_pointer_reg, | 3111 return Operand(elements_pointer_reg, |
| 3037 ToRegister(key), | 3112 ToRegister(key), |
| 3038 scale_factor, | 3113 scale_factor, |
| 3039 offset + (additional_index << shift_size)); | 3114 offset + (additional_index << shift_size)); |
| 3040 } | 3115 } |
| 3041 } | 3116 } |
| 3042 | 3117 |
| 3043 | 3118 |
| 3044 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { | 3119 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { |
| 3120 ASSERT(ToRegister(instr->context()).is(rsi)); |
| 3045 ASSERT(ToRegister(instr->object()).is(rdx)); | 3121 ASSERT(ToRegister(instr->object()).is(rdx)); |
| 3046 ASSERT(ToRegister(instr->key()).is(rax)); | 3122 ASSERT(ToRegister(instr->key()).is(rax)); |
| 3047 | 3123 |
| 3048 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 3124 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
| 3049 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 3125 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 3050 } | 3126 } |
| 3051 | 3127 |
| 3052 | 3128 |
| 3053 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { | 3129 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { |
| 3054 Register result = ToRegister(instr->result()); | 3130 Register result = ToRegister(instr->result()); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3104 | 3180 |
| 3105 | 3181 |
| 3106 void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) { | 3182 void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) { |
| 3107 Register receiver = ToRegister(instr->receiver()); | 3183 Register receiver = ToRegister(instr->receiver()); |
| 3108 Register function = ToRegister(instr->function()); | 3184 Register function = ToRegister(instr->function()); |
| 3109 | 3185 |
| 3110 // If the receiver is null or undefined, we have to pass the global | 3186 // If the receiver is null or undefined, we have to pass the global |
| 3111 // object as a receiver to normal functions. Values have to be | 3187 // object as a receiver to normal functions. Values have to be |
| 3112 // passed unchanged to builtins and strict-mode functions. | 3188 // passed unchanged to builtins and strict-mode functions. |
| 3113 Label global_object, receiver_ok; | 3189 Label global_object, receiver_ok; |
| 3190 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear; |
| 3114 | 3191 |
| 3115 // Do not transform the receiver to object for strict mode | 3192 // Do not transform the receiver to object for strict mode |
| 3116 // functions. | 3193 // functions. |
| 3117 __ movq(kScratchRegister, | 3194 __ movq(kScratchRegister, |
| 3118 FieldOperand(function, JSFunction::kSharedFunctionInfoOffset)); | 3195 FieldOperand(function, JSFunction::kSharedFunctionInfoOffset)); |
| 3119 __ testb(FieldOperand(kScratchRegister, | 3196 __ testb(FieldOperand(kScratchRegister, |
| 3120 SharedFunctionInfo::kStrictModeByteOffset), | 3197 SharedFunctionInfo::kStrictModeByteOffset), |
| 3121 Immediate(1 << SharedFunctionInfo::kStrictModeBitWithinByte)); | 3198 Immediate(1 << SharedFunctionInfo::kStrictModeBitWithinByte)); |
| 3122 __ j(not_equal, &receiver_ok, Label::kNear); | 3199 __ j(not_equal, &receiver_ok, dist); |
| 3123 | 3200 |
| 3124 // Do not transform the receiver to object for builtins. | 3201 // Do not transform the receiver to object for builtins. |
| 3125 __ testb(FieldOperand(kScratchRegister, | 3202 __ testb(FieldOperand(kScratchRegister, |
| 3126 SharedFunctionInfo::kNativeByteOffset), | 3203 SharedFunctionInfo::kNativeByteOffset), |
| 3127 Immediate(1 << SharedFunctionInfo::kNativeBitWithinByte)); | 3204 Immediate(1 << SharedFunctionInfo::kNativeBitWithinByte)); |
| 3128 __ j(not_equal, &receiver_ok, Label::kNear); | 3205 __ j(not_equal, &receiver_ok, dist); |
| 3129 | 3206 |
| 3130 // Normal function. Replace undefined or null with global receiver. | 3207 // Normal function. Replace undefined or null with global receiver. |
| 3131 __ CompareRoot(receiver, Heap::kNullValueRootIndex); | 3208 __ CompareRoot(receiver, Heap::kNullValueRootIndex); |
| 3132 __ j(equal, &global_object, Label::kNear); | 3209 __ j(equal, &global_object, Label::kNear); |
| 3133 __ CompareRoot(receiver, Heap::kUndefinedValueRootIndex); | 3210 __ CompareRoot(receiver, Heap::kUndefinedValueRootIndex); |
| 3134 __ j(equal, &global_object, Label::kNear); | 3211 __ j(equal, &global_object, Label::kNear); |
| 3135 | 3212 |
| 3136 // The receiver should be a JS object. | 3213 // The receiver should be a JS object. |
| 3137 Condition is_smi = __ CheckSmi(receiver); | 3214 Condition is_smi = __ CheckSmi(receiver); |
| 3138 DeoptimizeIf(is_smi, instr->environment()); | 3215 DeoptimizeIf(is_smi, instr->environment()); |
| 3139 __ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, kScratchRegister); | 3216 __ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, kScratchRegister); |
| 3140 DeoptimizeIf(below, instr->environment()); | 3217 DeoptimizeIf(below, instr->environment()); |
| 3141 __ jmp(&receiver_ok, Label::kNear); | 3218 __ jmp(&receiver_ok, Label::kNear); |
| 3142 | 3219 |
| 3143 __ bind(&global_object); | 3220 __ bind(&global_object); |
| 3144 // TODO(kmillikin): We have a hydrogen value for the global object. See | 3221 // TODO(kmillikin): We have a hydrogen value for the global object. See |
| 3145 // if it's better to use it than to explicitly fetch it from the context | 3222 // if it's better to use it than to explicitly fetch it from the context |
| 3146 // here. | 3223 // here. |
| 3147 __ movq(receiver, ContextOperand(rsi, Context::GLOBAL_OBJECT_INDEX)); | 3224 __ movq(receiver, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 3225 __ movq(receiver, ContextOperand(receiver, Context::GLOBAL_OBJECT_INDEX)); |
| 3148 __ movq(receiver, | 3226 __ movq(receiver, |
| 3149 FieldOperand(receiver, JSGlobalObject::kGlobalReceiverOffset)); | 3227 FieldOperand(receiver, JSGlobalObject::kGlobalReceiverOffset)); |
| 3150 __ bind(&receiver_ok); | 3228 __ bind(&receiver_ok); |
| 3151 } | 3229 } |
| 3152 | 3230 |
| 3153 | 3231 |
| 3154 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { | 3232 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { |
| 3155 Register receiver = ToRegister(instr->receiver()); | 3233 Register receiver = ToRegister(instr->receiver()); |
| 3156 Register function = ToRegister(instr->function()); | 3234 Register function = ToRegister(instr->function()); |
| 3157 Register length = ToRegister(instr->length()); | 3235 Register length = ToRegister(instr->length()); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 3184 | 3262 |
| 3185 // Invoke the function. | 3263 // Invoke the function. |
| 3186 __ bind(&invoke); | 3264 __ bind(&invoke); |
| 3187 ASSERT(instr->HasPointerMap()); | 3265 ASSERT(instr->HasPointerMap()); |
| 3188 LPointerMap* pointers = instr->pointer_map(); | 3266 LPointerMap* pointers = instr->pointer_map(); |
| 3189 SafepointGenerator safepoint_generator( | 3267 SafepointGenerator safepoint_generator( |
| 3190 this, pointers, Safepoint::kLazyDeopt); | 3268 this, pointers, Safepoint::kLazyDeopt); |
| 3191 ParameterCount actual(rax); | 3269 ParameterCount actual(rax); |
| 3192 __ InvokeFunction(function, actual, CALL_FUNCTION, | 3270 __ InvokeFunction(function, actual, CALL_FUNCTION, |
| 3193 safepoint_generator, CALL_AS_METHOD); | 3271 safepoint_generator, CALL_AS_METHOD); |
| 3194 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | |
| 3195 } | 3272 } |
| 3196 | 3273 |
| 3197 | 3274 |
| 3198 void LCodeGen::DoPushArgument(LPushArgument* instr) { | 3275 void LCodeGen::DoPushArgument(LPushArgument* instr) { |
| 3199 LOperand* argument = instr->value(); | 3276 LOperand* argument = instr->value(); |
| 3200 EmitPushTaggedOperand(argument); | 3277 EmitPushTaggedOperand(argument); |
| 3201 } | 3278 } |
| 3202 | 3279 |
| 3203 | 3280 |
| 3204 void LCodeGen::DoDrop(LDrop* instr) { | 3281 void LCodeGen::DoDrop(LDrop* instr) { |
| 3205 __ Drop(instr->count()); | 3282 __ Drop(instr->count()); |
| 3206 } | 3283 } |
| 3207 | 3284 |
| 3208 | 3285 |
| 3209 void LCodeGen::DoThisFunction(LThisFunction* instr) { | 3286 void LCodeGen::DoThisFunction(LThisFunction* instr) { |
| 3210 Register result = ToRegister(instr->result()); | 3287 Register result = ToRegister(instr->result()); |
| 3211 __ movq(result, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); | 3288 __ movq(result, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); |
| 3212 } | 3289 } |
| 3213 | 3290 |
| 3214 | 3291 |
| 3215 void LCodeGen::DoContext(LContext* instr) { | 3292 void LCodeGen::DoContext(LContext* instr) { |
| 3216 Register result = ToRegister(instr->result()); | 3293 Register result = ToRegister(instr->result()); |
| 3217 __ movq(result, rsi); | 3294 if (info()->IsOptimizing()) { |
| 3295 __ movq(result, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 3296 } else { |
| 3297 // If there is no frame, the context must be in rsi. |
| 3298 ASSERT(result.is(rsi)); |
| 3299 } |
| 3218 } | 3300 } |
| 3219 | 3301 |
| 3220 | 3302 |
| 3221 void LCodeGen::DoOuterContext(LOuterContext* instr) { | 3303 void LCodeGen::DoOuterContext(LOuterContext* instr) { |
| 3222 Register context = ToRegister(instr->context()); | 3304 Register context = ToRegister(instr->context()); |
| 3223 Register result = ToRegister(instr->result()); | 3305 Register result = ToRegister(instr->result()); |
| 3224 __ movq(result, | 3306 __ movq(result, |
| 3225 Operand(context, Context::SlotOffset(Context::PREVIOUS_INDEX))); | 3307 Operand(context, Context::SlotOffset(Context::PREVIOUS_INDEX))); |
| 3226 } | 3308 } |
| 3227 | 3309 |
| 3228 | 3310 |
| 3229 void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) { | 3311 void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) { |
| 3312 ASSERT(ToRegister(instr->context()).is(rsi)); |
| 3230 __ push(rsi); // The context is the first argument. | 3313 __ push(rsi); // The context is the first argument. |
| 3231 __ Push(instr->hydrogen()->pairs()); | 3314 __ Push(instr->hydrogen()->pairs()); |
| 3232 __ Push(Smi::FromInt(instr->hydrogen()->flags())); | 3315 __ Push(Smi::FromInt(instr->hydrogen()->flags())); |
| 3233 CallRuntime(Runtime::kDeclareGlobals, 3, instr); | 3316 CallRuntime(Runtime::kDeclareGlobals, 3, instr); |
| 3234 } | 3317 } |
| 3235 | 3318 |
| 3236 | 3319 |
| 3237 void LCodeGen::DoGlobalObject(LGlobalObject* instr) { | 3320 void LCodeGen::DoGlobalObject(LGlobalObject* instr) { |
| 3321 Register context = ToRegister(instr->context()); |
| 3238 Register result = ToRegister(instr->result()); | 3322 Register result = ToRegister(instr->result()); |
| 3239 __ movq(result, GlobalObjectOperand()); | 3323 __ movq(result, |
| 3324 Operand(context, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); |
| 3240 } | 3325 } |
| 3241 | 3326 |
| 3242 | 3327 |
| 3243 void LCodeGen::DoGlobalReceiver(LGlobalReceiver* instr) { | 3328 void LCodeGen::DoGlobalReceiver(LGlobalReceiver* instr) { |
| 3244 Register global = ToRegister(instr->global()); | 3329 Register global = ToRegister(instr->global()); |
| 3245 Register result = ToRegister(instr->result()); | 3330 Register result = ToRegister(instr->result()); |
| 3246 __ movq(result, FieldOperand(global, GlobalObject::kGlobalReceiverOffset)); | 3331 __ movq(result, FieldOperand(global, GlobalObject::kGlobalReceiverOffset)); |
| 3247 } | 3332 } |
| 3248 | 3333 |
| 3249 | 3334 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3286 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT, 0); | 3371 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT, 0); |
| 3287 } else { | 3372 } else { |
| 3288 // We need to adapt arguments. | 3373 // We need to adapt arguments. |
| 3289 SafepointGenerator generator( | 3374 SafepointGenerator generator( |
| 3290 this, pointers, Safepoint::kLazyDeopt); | 3375 this, pointers, Safepoint::kLazyDeopt); |
| 3291 ParameterCount count(arity); | 3376 ParameterCount count(arity); |
| 3292 ParameterCount expected(formal_parameter_count); | 3377 ParameterCount expected(formal_parameter_count); |
| 3293 __ InvokeFunction( | 3378 __ InvokeFunction( |
| 3294 function, expected, count, CALL_FUNCTION, generator, call_kind); | 3379 function, expected, count, CALL_FUNCTION, generator, call_kind); |
| 3295 } | 3380 } |
| 3296 | |
| 3297 // Restore context. | |
| 3298 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | |
| 3299 } | 3381 } |
| 3300 | 3382 |
| 3301 | 3383 |
| 3302 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { | 3384 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { |
| 3303 ASSERT(ToRegister(instr->result()).is(rax)); | 3385 ASSERT(ToRegister(instr->result()).is(rax)); |
| 3304 CallKnownFunction(instr->hydrogen()->function(), | 3386 CallKnownFunction(instr->hydrogen()->function(), |
| 3305 instr->hydrogen()->formal_parameter_count(), | 3387 instr->hydrogen()->formal_parameter_count(), |
| 3306 instr->arity(), | 3388 instr->arity(), |
| 3307 instr, | 3389 instr, |
| 3308 CALL_AS_METHOD, | 3390 CALL_AS_METHOD, |
| (...skipping 20 matching lines...) Expand all Loading... |
| 3329 // |result| are the same register and |input| will be restored | 3411 // |result| are the same register and |input| will be restored |
| 3330 // unchanged by popping safepoint registers. | 3412 // unchanged by popping safepoint registers. |
| 3331 __ testl(tmp, Immediate(HeapNumber::kSignMask)); | 3413 __ testl(tmp, Immediate(HeapNumber::kSignMask)); |
| 3332 __ j(zero, &done); | 3414 __ j(zero, &done); |
| 3333 | 3415 |
| 3334 __ AllocateHeapNumber(tmp, tmp2, &slow); | 3416 __ AllocateHeapNumber(tmp, tmp2, &slow); |
| 3335 __ jmp(&allocated, Label::kNear); | 3417 __ jmp(&allocated, Label::kNear); |
| 3336 | 3418 |
| 3337 // Slow case: Call the runtime system to do the number allocation. | 3419 // Slow case: Call the runtime system to do the number allocation. |
| 3338 __ bind(&slow); | 3420 __ bind(&slow); |
| 3339 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); | 3421 CallRuntimeFromDeferred( |
| 3422 Runtime::kAllocateHeapNumber, 0, instr, instr->context()); |
| 3340 // Set the pointer to the new heap number in tmp. | 3423 // Set the pointer to the new heap number in tmp. |
| 3341 if (!tmp.is(rax)) __ movq(tmp, rax); | 3424 if (!tmp.is(rax)) __ movq(tmp, rax); |
| 3342 // Restore input_reg after call to runtime. | 3425 // Restore input_reg after call to runtime. |
| 3343 __ LoadFromSafepointRegisterSlot(input_reg, input_reg); | 3426 __ LoadFromSafepointRegisterSlot(input_reg, input_reg); |
| 3344 | 3427 |
| 3345 __ bind(&allocated); | 3428 __ bind(&allocated); |
| 3346 __ MoveDouble(tmp2, FieldOperand(input_reg, HeapNumber::kValueOffset)); | 3429 __ MoveDouble(tmp2, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
| 3347 __ shl(tmp2, Immediate(1)); | 3430 __ shl(tmp2, Immediate(1)); |
| 3348 __ shr(tmp2, Immediate(1)); | 3431 __ shr(tmp2, Immediate(1)); |
| 3349 __ MoveDouble(FieldOperand(tmp, HeapNumber::kValueOffset), tmp2); | 3432 __ MoveDouble(FieldOperand(tmp, HeapNumber::kValueOffset), tmp2); |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3440 __ j(below, &negative_sign, Label::kNear); | 3523 __ j(below, &negative_sign, Label::kNear); |
| 3441 | 3524 |
| 3442 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3525 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 3443 // Check for negative zero. | 3526 // Check for negative zero. |
| 3444 Label positive_sign; | 3527 Label positive_sign; |
| 3445 __ j(above, &positive_sign, Label::kNear); | 3528 __ j(above, &positive_sign, Label::kNear); |
| 3446 __ movmskpd(output_reg, input_reg); | 3529 __ movmskpd(output_reg, input_reg); |
| 3447 __ testq(output_reg, Immediate(1)); | 3530 __ testq(output_reg, Immediate(1)); |
| 3448 DeoptimizeIf(not_zero, instr->environment()); | 3531 DeoptimizeIf(not_zero, instr->environment()); |
| 3449 __ Set(output_reg, 0); | 3532 __ Set(output_reg, 0); |
| 3450 __ jmp(&done); | 3533 __ jmp(&done, Label::kNear); |
| 3451 __ bind(&positive_sign); | 3534 __ bind(&positive_sign); |
| 3452 } | 3535 } |
| 3453 | 3536 |
| 3454 // Use truncating instruction (OK because input is positive). | 3537 // Use truncating instruction (OK because input is positive). |
| 3455 __ cvttsd2si(output_reg, input_reg); | 3538 __ cvttsd2si(output_reg, input_reg); |
| 3456 // Overflow is signalled with minint. | 3539 // Overflow is signalled with minint. |
| 3457 __ cmpl(output_reg, Immediate(0x80000000)); | 3540 __ cmpl(output_reg, Immediate(0x80000000)); |
| 3458 DeoptimizeIf(equal, instr->environment()); | 3541 DeoptimizeIf(equal, instr->environment()); |
| 3459 __ jmp(&done, Label::kNear); | 3542 __ jmp(&done, Label::kNear); |
| 3460 | 3543 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 3474 | 3557 |
| 3475 | 3558 |
| 3476 void LCodeGen::DoMathRound(LMathRound* instr) { | 3559 void LCodeGen::DoMathRound(LMathRound* instr) { |
| 3477 const XMMRegister xmm_scratch = double_scratch0(); | 3560 const XMMRegister xmm_scratch = double_scratch0(); |
| 3478 Register output_reg = ToRegister(instr->result()); | 3561 Register output_reg = ToRegister(instr->result()); |
| 3479 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 3562 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
| 3480 static int64_t one_half = V8_INT64_C(0x3FE0000000000000); // 0.5 | 3563 static int64_t one_half = V8_INT64_C(0x3FE0000000000000); // 0.5 |
| 3481 static int64_t minus_one_half = V8_INT64_C(0xBFE0000000000000); // -0.5 | 3564 static int64_t minus_one_half = V8_INT64_C(0xBFE0000000000000); // -0.5 |
| 3482 | 3565 |
| 3483 Label done, round_to_zero, below_one_half, do_not_compensate, restore; | 3566 Label done, round_to_zero, below_one_half, do_not_compensate, restore; |
| 3484 __ movq(kScratchRegister, one_half, RelocInfo::NONE64); | 3567 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear; |
| 3568 __ movq(kScratchRegister, one_half); |
| 3485 __ movq(xmm_scratch, kScratchRegister); | 3569 __ movq(xmm_scratch, kScratchRegister); |
| 3486 __ ucomisd(xmm_scratch, input_reg); | 3570 __ ucomisd(xmm_scratch, input_reg); |
| 3487 __ j(above, &below_one_half); | 3571 __ j(above, &below_one_half, Label::kNear); |
| 3488 | 3572 |
| 3489 // CVTTSD2SI rounds towards zero, since 0.5 <= x, we use floor(0.5 + x). | 3573 // CVTTSD2SI rounds towards zero, since 0.5 <= x, we use floor(0.5 + x). |
| 3490 __ addsd(xmm_scratch, input_reg); | 3574 __ addsd(xmm_scratch, input_reg); |
| 3491 __ cvttsd2si(output_reg, xmm_scratch); | 3575 __ cvttsd2si(output_reg, xmm_scratch); |
| 3492 // Overflow is signalled with minint. | 3576 // Overflow is signalled with minint. |
| 3493 __ cmpl(output_reg, Immediate(0x80000000)); | 3577 __ cmpl(output_reg, Immediate(0x80000000)); |
| 3494 __ RecordComment("D2I conversion overflow"); | 3578 __ RecordComment("D2I conversion overflow"); |
| 3495 DeoptimizeIf(equal, instr->environment()); | 3579 DeoptimizeIf(equal, instr->environment()); |
| 3496 __ jmp(&done); | 3580 __ jmp(&done, dist); |
| 3497 | 3581 |
| 3498 __ bind(&below_one_half); | 3582 __ bind(&below_one_half); |
| 3499 __ movq(kScratchRegister, minus_one_half, RelocInfo::NONE64); | 3583 __ movq(kScratchRegister, minus_one_half); |
| 3500 __ movq(xmm_scratch, kScratchRegister); | 3584 __ movq(xmm_scratch, kScratchRegister); |
| 3501 __ ucomisd(xmm_scratch, input_reg); | 3585 __ ucomisd(xmm_scratch, input_reg); |
| 3502 __ j(below_equal, &round_to_zero); | 3586 __ j(below_equal, &round_to_zero, Label::kNear); |
| 3503 | 3587 |
| 3504 // CVTTSD2SI rounds towards zero, we use ceil(x - (-0.5)) and then | 3588 // CVTTSD2SI rounds towards zero, we use ceil(x - (-0.5)) and then |
| 3505 // compare and compensate. | 3589 // compare and compensate. |
| 3506 __ movq(kScratchRegister, input_reg); // Back up input_reg. | 3590 __ movq(kScratchRegister, input_reg); // Back up input_reg. |
| 3507 __ subsd(input_reg, xmm_scratch); | 3591 __ subsd(input_reg, xmm_scratch); |
| 3508 __ cvttsd2si(output_reg, input_reg); | 3592 __ cvttsd2si(output_reg, input_reg); |
| 3509 // Catch minint due to overflow, and to prevent overflow when compensating. | 3593 // Catch minint due to overflow, and to prevent overflow when compensating. |
| 3510 __ cmpl(output_reg, Immediate(0x80000000)); | 3594 __ cmpl(output_reg, Immediate(0x80000000)); |
| 3511 __ RecordComment("D2I conversion overflow"); | 3595 __ RecordComment("D2I conversion overflow"); |
| 3512 DeoptimizeIf(equal, instr->environment()); | 3596 DeoptimizeIf(equal, instr->environment()); |
| 3513 | 3597 |
| 3514 __ Cvtlsi2sd(xmm_scratch, output_reg); | 3598 __ Cvtlsi2sd(xmm_scratch, output_reg); |
| 3515 __ ucomisd(input_reg, xmm_scratch); | 3599 __ ucomisd(input_reg, xmm_scratch); |
| 3516 __ j(equal, &restore, Label::kNear); | 3600 __ j(equal, &restore, Label::kNear); |
| 3517 __ subl(output_reg, Immediate(1)); | 3601 __ subl(output_reg, Immediate(1)); |
| 3518 // No overflow because we already ruled out minint. | 3602 // No overflow because we already ruled out minint. |
| 3519 __ bind(&restore); | 3603 __ bind(&restore); |
| 3520 __ movq(input_reg, kScratchRegister); // Restore input_reg. | 3604 __ movq(input_reg, kScratchRegister); // Restore input_reg. |
| 3521 __ jmp(&done); | 3605 __ jmp(&done, dist); |
| 3522 | 3606 |
| 3523 __ bind(&round_to_zero); | 3607 __ bind(&round_to_zero); |
| 3524 // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if | 3608 // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if |
| 3525 // we can ignore the difference between a result of -0 and +0. | 3609 // we can ignore the difference between a result of -0 and +0. |
| 3526 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3610 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 3527 __ movq(output_reg, input_reg); | 3611 __ movq(output_reg, input_reg); |
| 3528 __ testq(output_reg, output_reg); | 3612 __ testq(output_reg, output_reg); |
| 3529 __ RecordComment("Minus zero"); | 3613 __ RecordComment("Minus zero"); |
| 3530 DeoptimizeIf(negative, instr->environment()); | 3614 DeoptimizeIf(negative, instr->environment()); |
| 3531 } | 3615 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 3545 XMMRegister xmm_scratch = double_scratch0(); | 3629 XMMRegister xmm_scratch = double_scratch0(); |
| 3546 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 3630 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
| 3547 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); | 3631 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); |
| 3548 | 3632 |
| 3549 // Note that according to ECMA-262 15.8.2.13: | 3633 // Note that according to ECMA-262 15.8.2.13: |
| 3550 // Math.pow(-Infinity, 0.5) == Infinity | 3634 // Math.pow(-Infinity, 0.5) == Infinity |
| 3551 // Math.sqrt(-Infinity) == NaN | 3635 // Math.sqrt(-Infinity) == NaN |
| 3552 Label done, sqrt; | 3636 Label done, sqrt; |
| 3553 // Check base for -Infinity. According to IEEE-754, double-precision | 3637 // Check base for -Infinity. According to IEEE-754, double-precision |
| 3554 // -Infinity has the highest 12 bits set and the lowest 52 bits cleared. | 3638 // -Infinity has the highest 12 bits set and the lowest 52 bits cleared. |
| 3555 __ movq(kScratchRegister, V8_INT64_C(0xFFF0000000000000), RelocInfo::NONE64); | 3639 __ movq(kScratchRegister, V8_INT64_C(0xFFF0000000000000)); |
| 3556 __ movq(xmm_scratch, kScratchRegister); | 3640 __ movq(xmm_scratch, kScratchRegister); |
| 3557 __ ucomisd(xmm_scratch, input_reg); | 3641 __ ucomisd(xmm_scratch, input_reg); |
| 3558 // Comparing -Infinity with NaN results in "unordered", which sets the | 3642 // Comparing -Infinity with NaN results in "unordered", which sets the |
| 3559 // zero flag as if both were equal. However, it also sets the carry flag. | 3643 // zero flag as if both were equal. However, it also sets the carry flag. |
| 3560 __ j(not_equal, &sqrt, Label::kNear); | 3644 __ j(not_equal, &sqrt, Label::kNear); |
| 3561 __ j(carry, &sqrt, Label::kNear); | 3645 __ j(carry, &sqrt, Label::kNear); |
| 3562 // If input is -Infinity, return Infinity. | 3646 // If input is -Infinity, return Infinity. |
| 3563 __ xorps(input_reg, input_reg); | 3647 __ xorps(input_reg, input_reg); |
| 3564 __ subsd(input_reg, xmm_scratch); | 3648 __ subsd(input_reg, xmm_scratch); |
| 3565 __ jmp(&done, Label::kNear); | 3649 __ jmp(&done, Label::kNear); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 3584 ASSERT(!instr->right()->IsDoubleRegister() || | 3668 ASSERT(!instr->right()->IsDoubleRegister() || |
| 3585 ToDoubleRegister(instr->right()).is(xmm1)); | 3669 ToDoubleRegister(instr->right()).is(xmm1)); |
| 3586 ASSERT(ToDoubleRegister(instr->left()).is(xmm2)); | 3670 ASSERT(ToDoubleRegister(instr->left()).is(xmm2)); |
| 3587 ASSERT(ToDoubleRegister(instr->result()).is(xmm3)); | 3671 ASSERT(ToDoubleRegister(instr->result()).is(xmm3)); |
| 3588 | 3672 |
| 3589 if (exponent_type.IsSmi()) { | 3673 if (exponent_type.IsSmi()) { |
| 3590 MathPowStub stub(MathPowStub::TAGGED); | 3674 MathPowStub stub(MathPowStub::TAGGED); |
| 3591 __ CallStub(&stub); | 3675 __ CallStub(&stub); |
| 3592 } else if (exponent_type.IsTagged()) { | 3676 } else if (exponent_type.IsTagged()) { |
| 3593 Label no_deopt; | 3677 Label no_deopt; |
| 3594 __ JumpIfSmi(exponent, &no_deopt); | 3678 __ JumpIfSmi(exponent, &no_deopt, Label::kNear); |
| 3595 __ CmpObjectType(exponent, HEAP_NUMBER_TYPE, rcx); | 3679 __ CmpObjectType(exponent, HEAP_NUMBER_TYPE, rcx); |
| 3596 DeoptimizeIf(not_equal, instr->environment()); | 3680 DeoptimizeIf(not_equal, instr->environment()); |
| 3597 __ bind(&no_deopt); | 3681 __ bind(&no_deopt); |
| 3598 MathPowStub stub(MathPowStub::TAGGED); | 3682 MathPowStub stub(MathPowStub::TAGGED); |
| 3599 __ CallStub(&stub); | 3683 __ CallStub(&stub); |
| 3600 } else if (exponent_type.IsInteger32()) { | 3684 } else if (exponent_type.IsInteger32()) { |
| 3601 MathPowStub stub(MathPowStub::INTEGER); | 3685 MathPowStub stub(MathPowStub::INTEGER); |
| 3602 __ CallStub(&stub); | 3686 __ CallStub(&stub); |
| 3603 } else { | 3687 } else { |
| 3604 ASSERT(exponent_type.IsDouble()); | 3688 ASSERT(exponent_type.IsDouble()); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3653 Register random = state0; | 3737 Register random = state0; |
| 3654 __ shll(random, Immediate(14)); | 3738 __ shll(random, Immediate(14)); |
| 3655 __ andl(state1, Immediate(0x3FFFF)); | 3739 __ andl(state1, Immediate(0x3FFFF)); |
| 3656 __ addl(random, state1); | 3740 __ addl(random, state1); |
| 3657 | 3741 |
| 3658 // Convert 32 random bits in rax to 0.(32 random bits) in a double | 3742 // Convert 32 random bits in rax to 0.(32 random bits) in a double |
| 3659 // by computing: | 3743 // by computing: |
| 3660 // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)). | 3744 // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)). |
| 3661 XMMRegister result = ToDoubleRegister(instr->result()); | 3745 XMMRegister result = ToDoubleRegister(instr->result()); |
| 3662 XMMRegister scratch4 = double_scratch0(); | 3746 XMMRegister scratch4 = double_scratch0(); |
| 3663 __ movq(scratch3, V8_INT64_C(0x4130000000000000), | 3747 __ movq(scratch3, V8_INT64_C(0x4130000000000000)); // 1.0 x 2^20 as double |
| 3664 RelocInfo::NONE64); // 1.0 x 2^20 as double | |
| 3665 __ movq(scratch4, scratch3); | 3748 __ movq(scratch4, scratch3); |
| 3666 __ movd(result, random); | 3749 __ movd(result, random); |
| 3667 __ xorps(result, scratch4); | 3750 __ xorps(result, scratch4); |
| 3668 __ subsd(result, scratch4); | 3751 __ subsd(result, scratch4); |
| 3669 } | 3752 } |
| 3670 | 3753 |
| 3671 | 3754 |
| 3672 void LCodeGen::DoMathExp(LMathExp* instr) { | 3755 void LCodeGen::DoMathExp(LMathExp* instr) { |
| 3673 XMMRegister input = ToDoubleRegister(instr->value()); | 3756 XMMRegister input = ToDoubleRegister(instr->value()); |
| 3674 XMMRegister result = ToDoubleRegister(instr->result()); | 3757 XMMRegister result = ToDoubleRegister(instr->result()); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3708 __ fyl2x(); | 3791 __ fyl2x(); |
| 3709 __ fstp_d(Operand(rsp, 0)); | 3792 __ fstp_d(Operand(rsp, 0)); |
| 3710 __ movsd(input_reg, Operand(rsp, 0)); | 3793 __ movsd(input_reg, Operand(rsp, 0)); |
| 3711 __ addq(rsp, Immediate(kDoubleSize)); | 3794 __ addq(rsp, Immediate(kDoubleSize)); |
| 3712 __ bind(&done); | 3795 __ bind(&done); |
| 3713 } | 3796 } |
| 3714 | 3797 |
| 3715 | 3798 |
| 3716 void LCodeGen::DoMathTan(LMathTan* instr) { | 3799 void LCodeGen::DoMathTan(LMathTan* instr) { |
| 3717 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); | 3800 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); |
| 3801 // Set the context register to a GC-safe fake value. Clobbering it is |
| 3802 // OK because this instruction is marked as a call. |
| 3803 __ Set(rsi, 0); |
| 3718 TranscendentalCacheStub stub(TranscendentalCache::TAN, | 3804 TranscendentalCacheStub stub(TranscendentalCache::TAN, |
| 3719 TranscendentalCacheStub::UNTAGGED); | 3805 TranscendentalCacheStub::UNTAGGED); |
| 3720 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 3806 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 3721 } | 3807 } |
| 3722 | 3808 |
| 3723 | 3809 |
| 3724 void LCodeGen::DoMathCos(LMathCos* instr) { | 3810 void LCodeGen::DoMathCos(LMathCos* instr) { |
| 3725 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); | 3811 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); |
| 3812 // Set the context register to a GC-safe fake value. Clobbering it is |
| 3813 // OK because this instruction is marked as a call. |
| 3814 __ Set(rsi, 0); |
| 3726 TranscendentalCacheStub stub(TranscendentalCache::COS, | 3815 TranscendentalCacheStub stub(TranscendentalCache::COS, |
| 3727 TranscendentalCacheStub::UNTAGGED); | 3816 TranscendentalCacheStub::UNTAGGED); |
| 3728 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 3817 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 3729 } | 3818 } |
| 3730 | 3819 |
| 3731 | 3820 |
| 3732 void LCodeGen::DoMathSin(LMathSin* instr) { | 3821 void LCodeGen::DoMathSin(LMathSin* instr) { |
| 3733 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); | 3822 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); |
| 3823 // Set the context register to a GC-safe fake value. Clobbering it is |
| 3824 // OK because this instruction is marked as a call. |
| 3825 __ Set(rsi, 0); |
| 3734 TranscendentalCacheStub stub(TranscendentalCache::SIN, | 3826 TranscendentalCacheStub stub(TranscendentalCache::SIN, |
| 3735 TranscendentalCacheStub::UNTAGGED); | 3827 TranscendentalCacheStub::UNTAGGED); |
| 3736 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 3828 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 3737 } | 3829 } |
| 3738 | 3830 |
| 3739 | 3831 |
| 3740 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { | 3832 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { |
| 3833 ASSERT(ToRegister(instr->context()).is(rsi)); |
| 3741 ASSERT(ToRegister(instr->function()).is(rdi)); | 3834 ASSERT(ToRegister(instr->function()).is(rdi)); |
| 3742 ASSERT(instr->HasPointerMap()); | 3835 ASSERT(instr->HasPointerMap()); |
| 3743 | 3836 |
| 3744 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); | 3837 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); |
| 3745 if (known_function.is_null()) { | 3838 if (known_function.is_null()) { |
| 3746 LPointerMap* pointers = instr->pointer_map(); | 3839 LPointerMap* pointers = instr->pointer_map(); |
| 3747 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); | 3840 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); |
| 3748 ParameterCount count(instr->arity()); | 3841 ParameterCount count(instr->arity()); |
| 3749 __ InvokeFunction(rdi, count, CALL_FUNCTION, generator, CALL_AS_METHOD); | 3842 __ InvokeFunction(rdi, count, CALL_FUNCTION, generator, CALL_AS_METHOD); |
| 3750 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | |
| 3751 } else { | 3843 } else { |
| 3752 CallKnownFunction(known_function, | 3844 CallKnownFunction(known_function, |
| 3753 instr->hydrogen()->formal_parameter_count(), | 3845 instr->hydrogen()->formal_parameter_count(), |
| 3754 instr->arity(), | 3846 instr->arity(), |
| 3755 instr, | 3847 instr, |
| 3756 CALL_AS_METHOD, | 3848 CALL_AS_METHOD, |
| 3757 RDI_CONTAINS_TARGET); | 3849 RDI_CONTAINS_TARGET); |
| 3758 } | 3850 } |
| 3759 } | 3851 } |
| 3760 | 3852 |
| 3761 | 3853 |
| 3762 void LCodeGen::DoCallKeyed(LCallKeyed* instr) { | 3854 void LCodeGen::DoCallKeyed(LCallKeyed* instr) { |
| 3855 ASSERT(ToRegister(instr->context()).is(rsi)); |
| 3763 ASSERT(ToRegister(instr->key()).is(rcx)); | 3856 ASSERT(ToRegister(instr->key()).is(rcx)); |
| 3764 ASSERT(ToRegister(instr->result()).is(rax)); | 3857 ASSERT(ToRegister(instr->result()).is(rax)); |
| 3765 | 3858 |
| 3766 int arity = instr->arity(); | 3859 int arity = instr->arity(); |
| 3767 Handle<Code> ic = | 3860 Handle<Code> ic = |
| 3768 isolate()->stub_cache()->ComputeKeyedCallInitialize(arity); | 3861 isolate()->stub_cache()->ComputeKeyedCallInitialize(arity); |
| 3769 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 3862 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 3770 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | |
| 3771 } | 3863 } |
| 3772 | 3864 |
| 3773 | 3865 |
| 3774 void LCodeGen::DoCallNamed(LCallNamed* instr) { | 3866 void LCodeGen::DoCallNamed(LCallNamed* instr) { |
| 3867 ASSERT(ToRegister(instr->context()).is(rsi)); |
| 3775 ASSERT(ToRegister(instr->result()).is(rax)); | 3868 ASSERT(ToRegister(instr->result()).is(rax)); |
| 3776 | 3869 |
| 3777 int arity = instr->arity(); | 3870 int arity = instr->arity(); |
| 3778 RelocInfo::Mode mode = RelocInfo::CODE_TARGET; | 3871 RelocInfo::Mode mode = RelocInfo::CODE_TARGET; |
| 3779 Handle<Code> ic = | 3872 Handle<Code> ic = |
| 3780 isolate()->stub_cache()->ComputeCallInitialize(arity, mode); | 3873 isolate()->stub_cache()->ComputeCallInitialize(arity, mode); |
| 3781 __ Move(rcx, instr->name()); | 3874 __ Move(rcx, instr->name()); |
| 3782 CallCode(ic, mode, instr); | 3875 CallCode(ic, mode, instr); |
| 3783 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | |
| 3784 } | 3876 } |
| 3785 | 3877 |
| 3786 | 3878 |
| 3787 void LCodeGen::DoCallFunction(LCallFunction* instr) { | 3879 void LCodeGen::DoCallFunction(LCallFunction* instr) { |
| 3880 ASSERT(ToRegister(instr->context()).is(rsi)); |
| 3788 ASSERT(ToRegister(instr->function()).is(rdi)); | 3881 ASSERT(ToRegister(instr->function()).is(rdi)); |
| 3789 ASSERT(ToRegister(instr->result()).is(rax)); | 3882 ASSERT(ToRegister(instr->result()).is(rax)); |
| 3790 | 3883 |
| 3791 int arity = instr->arity(); | 3884 int arity = instr->arity(); |
| 3792 CallFunctionStub stub(arity, NO_CALL_FUNCTION_FLAGS); | 3885 CallFunctionStub stub(arity, NO_CALL_FUNCTION_FLAGS); |
| 3793 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 3886 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 3794 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | |
| 3795 } | 3887 } |
| 3796 | 3888 |
| 3797 | 3889 |
| 3798 void LCodeGen::DoCallGlobal(LCallGlobal* instr) { | 3890 void LCodeGen::DoCallGlobal(LCallGlobal* instr) { |
| 3891 ASSERT(ToRegister(instr->context()).is(rsi)); |
| 3799 ASSERT(ToRegister(instr->result()).is(rax)); | 3892 ASSERT(ToRegister(instr->result()).is(rax)); |
| 3800 int arity = instr->arity(); | 3893 int arity = instr->arity(); |
| 3801 RelocInfo::Mode mode = RelocInfo::CODE_TARGET_CONTEXT; | 3894 RelocInfo::Mode mode = RelocInfo::CODE_TARGET_CONTEXT; |
| 3802 Handle<Code> ic = | 3895 Handle<Code> ic = |
| 3803 isolate()->stub_cache()->ComputeCallInitialize(arity, mode); | 3896 isolate()->stub_cache()->ComputeCallInitialize(arity, mode); |
| 3804 __ Move(rcx, instr->name()); | 3897 __ Move(rcx, instr->name()); |
| 3805 CallCode(ic, mode, instr); | 3898 CallCode(ic, mode, instr); |
| 3806 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | |
| 3807 } | 3899 } |
| 3808 | 3900 |
| 3809 | 3901 |
| 3810 void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) { | 3902 void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) { |
| 3811 ASSERT(ToRegister(instr->result()).is(rax)); | 3903 ASSERT(ToRegister(instr->result()).is(rax)); |
| 3812 CallKnownFunction(instr->hydrogen()->target(), | 3904 CallKnownFunction(instr->hydrogen()->target(), |
| 3813 instr->hydrogen()->formal_parameter_count(), | 3905 instr->hydrogen()->formal_parameter_count(), |
| 3814 instr->arity(), | 3906 instr->arity(), |
| 3815 instr, | 3907 instr, |
| 3816 CALL_AS_FUNCTION, | 3908 CALL_AS_FUNCTION, |
| 3817 RDI_UNINITIALIZED); | 3909 RDI_UNINITIALIZED); |
| 3818 } | 3910 } |
| 3819 | 3911 |
| 3820 | 3912 |
| 3821 void LCodeGen::DoCallNew(LCallNew* instr) { | 3913 void LCodeGen::DoCallNew(LCallNew* instr) { |
| 3914 ASSERT(ToRegister(instr->context()).is(rsi)); |
| 3822 ASSERT(ToRegister(instr->constructor()).is(rdi)); | 3915 ASSERT(ToRegister(instr->constructor()).is(rdi)); |
| 3823 ASSERT(ToRegister(instr->result()).is(rax)); | 3916 ASSERT(ToRegister(instr->result()).is(rax)); |
| 3824 | 3917 |
| 3825 __ Set(rax, instr->arity()); | 3918 __ Set(rax, instr->arity()); |
| 3826 // No cell in ebx for construct type feedback in optimized code | 3919 // No cell in ebx for construct type feedback in optimized code |
| 3827 Handle<Object> undefined_value(isolate()->factory()->undefined_value()); | 3920 Handle<Object> undefined_value(isolate()->factory()->undefined_value()); |
| 3828 __ Move(rbx, undefined_value); | 3921 __ Move(rbx, undefined_value); |
| 3829 CallConstructStub stub(NO_CALL_FUNCTION_FLAGS); | 3922 CallConstructStub stub(NO_CALL_FUNCTION_FLAGS); |
| 3830 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); | 3923 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); |
| 3831 } | 3924 } |
| 3832 | 3925 |
| 3833 | 3926 |
| 3834 void LCodeGen::DoCallNewArray(LCallNewArray* instr) { | 3927 void LCodeGen::DoCallNewArray(LCallNewArray* instr) { |
| 3928 ASSERT(ToRegister(instr->context()).is(rsi)); |
| 3835 ASSERT(ToRegister(instr->constructor()).is(rdi)); | 3929 ASSERT(ToRegister(instr->constructor()).is(rdi)); |
| 3836 ASSERT(ToRegister(instr->result()).is(rax)); | 3930 ASSERT(ToRegister(instr->result()).is(rax)); |
| 3837 | 3931 |
| 3838 __ Set(rax, instr->arity()); | 3932 __ Set(rax, instr->arity()); |
| 3839 __ Move(rbx, instr->hydrogen()->property_cell()); | 3933 __ Move(rbx, instr->hydrogen()->property_cell()); |
| 3840 ElementsKind kind = instr->hydrogen()->elements_kind(); | 3934 ElementsKind kind = instr->hydrogen()->elements_kind(); |
| 3841 AllocationSiteOverrideMode override_mode = | 3935 AllocationSiteOverrideMode override_mode = |
| 3842 (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE) | 3936 (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE) |
| 3843 ? DISABLE_ALLOCATION_SITES | 3937 ? DISABLE_ALLOCATION_SITES |
| 3844 : DONT_OVERRIDE; | 3938 : DONT_OVERRIDE; |
| 3845 ContextCheckMode context_mode = CONTEXT_CHECK_NOT_REQUIRED; | 3939 ContextCheckMode context_mode = CONTEXT_CHECK_NOT_REQUIRED; |
| 3846 | 3940 |
| 3847 if (instr->arity() == 0) { | 3941 if (instr->arity() == 0) { |
| 3848 ArrayNoArgumentConstructorStub stub(kind, context_mode, override_mode); | 3942 ArrayNoArgumentConstructorStub stub(kind, context_mode, override_mode); |
| 3849 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); | 3943 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); |
| 3850 } else if (instr->arity() == 1) { | 3944 } else if (instr->arity() == 1) { |
| 3851 Label done; | 3945 Label done; |
| 3852 if (IsFastPackedElementsKind(kind)) { | 3946 if (IsFastPackedElementsKind(kind)) { |
| 3853 Label packed_case; | 3947 Label packed_case; |
| 3854 // We might need a change here | 3948 // We might need a change here |
| 3855 // look at the first argument | 3949 // look at the first argument |
| 3856 __ movq(rcx, Operand(rsp, 0)); | 3950 __ movq(rcx, Operand(rsp, 0)); |
| 3857 __ testq(rcx, rcx); | 3951 __ testq(rcx, rcx); |
| 3858 __ j(zero, &packed_case); | 3952 __ j(zero, &packed_case, Label::kNear); |
| 3859 | 3953 |
| 3860 ElementsKind holey_kind = GetHoleyElementsKind(kind); | 3954 ElementsKind holey_kind = GetHoleyElementsKind(kind); |
| 3861 ArraySingleArgumentConstructorStub stub(holey_kind, context_mode, | 3955 ArraySingleArgumentConstructorStub stub(holey_kind, context_mode, |
| 3862 override_mode); | 3956 override_mode); |
| 3863 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); | 3957 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); |
| 3864 __ jmp(&done); | 3958 __ jmp(&done, Label::kNear); |
| 3865 __ bind(&packed_case); | 3959 __ bind(&packed_case); |
| 3866 } | 3960 } |
| 3867 | 3961 |
| 3868 ArraySingleArgumentConstructorStub stub(kind, context_mode, override_mode); | 3962 ArraySingleArgumentConstructorStub stub(kind, context_mode, override_mode); |
| 3869 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); | 3963 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); |
| 3870 __ bind(&done); | 3964 __ bind(&done); |
| 3871 } else { | 3965 } else { |
| 3872 ArrayNArgumentsConstructorStub stub(kind, context_mode, override_mode); | 3966 ArrayNArgumentsConstructorStub stub(kind, context_mode, override_mode); |
| 3873 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); | 3967 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); |
| 3874 } | 3968 } |
| 3875 } | 3969 } |
| 3876 | 3970 |
| 3877 | 3971 |
| 3878 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { | 3972 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { |
| 3973 ASSERT(ToRegister(instr->context()).is(rsi)); |
| 3879 CallRuntime(instr->function(), instr->arity(), instr, instr->save_doubles()); | 3974 CallRuntime(instr->function(), instr->arity(), instr, instr->save_doubles()); |
| 3880 } | 3975 } |
| 3881 | 3976 |
| 3882 | 3977 |
| 3883 void LCodeGen::DoStoreCodeEntry(LStoreCodeEntry* instr) { | 3978 void LCodeGen::DoStoreCodeEntry(LStoreCodeEntry* instr) { |
| 3884 Register function = ToRegister(instr->function()); | 3979 Register function = ToRegister(instr->function()); |
| 3885 Register code_object = ToRegister(instr->code_object()); | 3980 Register code_object = ToRegister(instr->code_object()); |
| 3886 __ lea(code_object, FieldOperand(code_object, Code::kHeaderSize)); | 3981 __ lea(code_object, FieldOperand(code_object, Code::kHeaderSize)); |
| 3887 __ movq(FieldOperand(function, JSFunction::kCodeEntryOffset), code_object); | 3982 __ movq(FieldOperand(function, JSFunction::kCodeEntryOffset), code_object); |
| 3888 } | 3983 } |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3975 if (!access.IsInobject()) { | 4070 if (!access.IsInobject()) { |
| 3976 write_register = ToRegister(instr->temp()); | 4071 write_register = ToRegister(instr->temp()); |
| 3977 __ movq(write_register, FieldOperand(object, JSObject::kPropertiesOffset)); | 4072 __ movq(write_register, FieldOperand(object, JSObject::kPropertiesOffset)); |
| 3978 } | 4073 } |
| 3979 | 4074 |
| 3980 if (instr->value()->IsConstantOperand()) { | 4075 if (instr->value()->IsConstantOperand()) { |
| 3981 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); | 4076 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); |
| 3982 if (operand_value->IsRegister()) { | 4077 if (operand_value->IsRegister()) { |
| 3983 Register value = ToRegister(operand_value); | 4078 Register value = ToRegister(operand_value); |
| 3984 __ Store(FieldOperand(write_register, offset), value, representation); | 4079 __ Store(FieldOperand(write_register, offset), value, representation); |
| 4080 } else if (representation.IsInteger32()) { |
| 4081 int32_t value = ToInteger32(operand_value); |
| 4082 ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); |
| 4083 __ movl(FieldOperand(write_register, offset), Immediate(value)); |
| 3985 } else { | 4084 } else { |
| 3986 Handle<Object> handle_value = ToHandle(operand_value); | 4085 Handle<Object> handle_value = ToHandle(operand_value); |
| 3987 ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); | 4086 ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); |
| 3988 __ Move(FieldOperand(write_register, offset), handle_value); | 4087 __ Move(FieldOperand(write_register, offset), handle_value); |
| 3989 } | 4088 } |
| 3990 } else { | 4089 } else { |
| 3991 Register value = ToRegister(instr->value()); | 4090 Register value = ToRegister(instr->value()); |
| 3992 __ Store(FieldOperand(write_register, offset), value, representation); | 4091 __ Store(FieldOperand(write_register, offset), value, representation); |
| 3993 } | 4092 } |
| 3994 | 4093 |
| 3995 if (instr->hydrogen()->NeedsWriteBarrier()) { | 4094 if (instr->hydrogen()->NeedsWriteBarrier()) { |
| 3996 Register value = ToRegister(instr->value()); | 4095 Register value = ToRegister(instr->value()); |
| 3997 Register temp = access.IsInobject() ? ToRegister(instr->temp()) : object; | 4096 Register temp = access.IsInobject() ? ToRegister(instr->temp()) : object; |
| 3998 // Update the write barrier for the object for in-object properties. | 4097 // Update the write barrier for the object for in-object properties. |
| 3999 __ RecordWriteField(write_register, | 4098 __ RecordWriteField(write_register, |
| 4000 offset, | 4099 offset, |
| 4001 value, | 4100 value, |
| 4002 temp, | 4101 temp, |
| 4003 kSaveFPRegs, | 4102 kSaveFPRegs, |
| 4004 EMIT_REMEMBERED_SET, | 4103 EMIT_REMEMBERED_SET, |
| 4005 check_needed); | 4104 check_needed); |
| 4006 } | 4105 } |
| 4007 } | 4106 } |
| 4008 | 4107 |
| 4009 | 4108 |
| 4010 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { | 4109 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { |
| 4110 ASSERT(ToRegister(instr->context()).is(rsi)); |
| 4011 ASSERT(ToRegister(instr->object()).is(rdx)); | 4111 ASSERT(ToRegister(instr->object()).is(rdx)); |
| 4012 ASSERT(ToRegister(instr->value()).is(rax)); | 4112 ASSERT(ToRegister(instr->value()).is(rax)); |
| 4013 | 4113 |
| 4014 __ Move(rcx, instr->hydrogen()->name()); | 4114 __ Move(rcx, instr->hydrogen()->name()); |
| 4015 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) | 4115 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) |
| 4016 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 4116 ? isolate()->builtins()->StoreIC_Initialize_Strict() |
| 4017 : isolate()->builtins()->StoreIC_Initialize(); | 4117 : isolate()->builtins()->StoreIC_Initialize(); |
| 4018 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 4118 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 4019 } | 4119 } |
| 4020 | 4120 |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4150 // Sign extend key because it could be a 32 bit negative value | 4250 // Sign extend key because it could be a 32 bit negative value |
| 4151 // and the dehoisted address computation happens in 64 bits | 4251 // and the dehoisted address computation happens in 64 bits |
| 4152 __ movsxlq(key_reg, key_reg); | 4252 __ movsxlq(key_reg, key_reg); |
| 4153 } | 4253 } |
| 4154 } | 4254 } |
| 4155 | 4255 |
| 4156 if (instr->NeedsCanonicalization()) { | 4256 if (instr->NeedsCanonicalization()) { |
| 4157 Label have_value; | 4257 Label have_value; |
| 4158 | 4258 |
| 4159 __ ucomisd(value, value); | 4259 __ ucomisd(value, value); |
| 4160 __ j(parity_odd, &have_value); // NaN. | 4260 __ j(parity_odd, &have_value, Label::kNear); // NaN. |
| 4161 | 4261 |
| 4162 __ Set(kScratchRegister, BitCast<uint64_t>( | 4262 __ Set(kScratchRegister, BitCast<uint64_t>( |
| 4163 FixedDoubleArray::canonical_not_the_hole_nan_as_double())); | 4263 FixedDoubleArray::canonical_not_the_hole_nan_as_double())); |
| 4164 __ movq(value, kScratchRegister); | 4264 __ movq(value, kScratchRegister); |
| 4165 | 4265 |
| 4166 __ bind(&have_value); | 4266 __ bind(&have_value); |
| 4167 } | 4267 } |
| 4168 | 4268 |
| 4169 Operand double_store_operand = BuildFastArrayOperand( | 4269 Operand double_store_operand = BuildFastArrayOperand( |
| 4170 instr->elements(), | 4270 instr->elements(), |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4238 DoStoreKeyedExternalArray(instr); | 4338 DoStoreKeyedExternalArray(instr); |
| 4239 } else if (instr->hydrogen()->value()->representation().IsDouble()) { | 4339 } else if (instr->hydrogen()->value()->representation().IsDouble()) { |
| 4240 DoStoreKeyedFixedDoubleArray(instr); | 4340 DoStoreKeyedFixedDoubleArray(instr); |
| 4241 } else { | 4341 } else { |
| 4242 DoStoreKeyedFixedArray(instr); | 4342 DoStoreKeyedFixedArray(instr); |
| 4243 } | 4343 } |
| 4244 } | 4344 } |
| 4245 | 4345 |
| 4246 | 4346 |
| 4247 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { | 4347 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { |
| 4348 ASSERT(ToRegister(instr->context()).is(rsi)); |
| 4248 ASSERT(ToRegister(instr->object()).is(rdx)); | 4349 ASSERT(ToRegister(instr->object()).is(rdx)); |
| 4249 ASSERT(ToRegister(instr->key()).is(rcx)); | 4350 ASSERT(ToRegister(instr->key()).is(rcx)); |
| 4250 ASSERT(ToRegister(instr->value()).is(rax)); | 4351 ASSERT(ToRegister(instr->value()).is(rax)); |
| 4251 | 4352 |
| 4252 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) | 4353 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) |
| 4253 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 4354 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() |
| 4254 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 4355 : isolate()->builtins()->KeyedStoreIC_Initialize(); |
| 4255 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 4356 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 4256 } | 4357 } |
| 4257 | 4358 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 4273 __ movq(FieldOperand(object_reg, HeapObject::kMapOffset), new_map_reg); | 4374 __ movq(FieldOperand(object_reg, HeapObject::kMapOffset), new_map_reg); |
| 4274 // Write barrier. | 4375 // Write barrier. |
| 4275 ASSERT_NE(instr->temp(), NULL); | 4376 ASSERT_NE(instr->temp(), NULL); |
| 4276 __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg, | 4377 __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg, |
| 4277 ToRegister(instr->temp()), kDontSaveFPRegs); | 4378 ToRegister(instr->temp()), kDontSaveFPRegs); |
| 4278 } else { | 4379 } else { |
| 4279 PushSafepointRegistersScope scope(this); | 4380 PushSafepointRegistersScope scope(this); |
| 4280 if (!object_reg.is(rax)) { | 4381 if (!object_reg.is(rax)) { |
| 4281 __ movq(rax, object_reg); | 4382 __ movq(rax, object_reg); |
| 4282 } | 4383 } |
| 4384 LoadContextFromDeferred(instr->context()); |
| 4283 __ Move(rbx, to_map); | 4385 __ Move(rbx, to_map); |
| 4284 TransitionElementsKindStub stub(from_kind, to_kind); | 4386 TransitionElementsKindStub stub(from_kind, to_kind); |
| 4285 __ CallStub(&stub); | 4387 __ CallStub(&stub); |
| 4286 RecordSafepointWithRegisters( | 4388 RecordSafepointWithRegisters( |
| 4287 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); | 4389 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); |
| 4288 } | 4390 } |
| 4289 __ bind(¬_applicable); | 4391 __ bind(¬_applicable); |
| 4290 } | 4392 } |
| 4291 | 4393 |
| 4292 | 4394 |
| 4293 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { | 4395 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { |
| 4294 Register object = ToRegister(instr->object()); | 4396 Register object = ToRegister(instr->object()); |
| 4295 Register temp = ToRegister(instr->temp()); | 4397 Register temp = ToRegister(instr->temp()); |
| 4296 Label no_memento_found; | 4398 Label no_memento_found; |
| 4297 __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found); | 4399 __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found); |
| 4298 DeoptimizeIf(equal, instr->environment()); | 4400 DeoptimizeIf(equal, instr->environment()); |
| 4299 __ bind(&no_memento_found); | 4401 __ bind(&no_memento_found); |
| 4300 } | 4402 } |
| 4301 | 4403 |
| 4302 | 4404 |
| 4303 void LCodeGen::DoStringAdd(LStringAdd* instr) { | 4405 void LCodeGen::DoStringAdd(LStringAdd* instr) { |
| 4304 EmitPushTaggedOperand(instr->left()); | 4406 ASSERT(ToRegister(instr->context()).is(rsi)); |
| 4305 EmitPushTaggedOperand(instr->right()); | 4407 if (FLAG_new_string_add) { |
| 4306 StringAddStub stub(instr->hydrogen()->flags()); | 4408 ASSERT(ToRegister(instr->left()).is(rdx)); |
| 4307 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 4409 ASSERT(ToRegister(instr->right()).is(rax)); |
| 4410 NewStringAddStub stub(instr->hydrogen()->flags(), |
| 4411 isolate()->heap()->GetPretenureMode()); |
| 4412 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 4413 } else { |
| 4414 EmitPushTaggedOperand(instr->left()); |
| 4415 EmitPushTaggedOperand(instr->right()); |
| 4416 StringAddStub stub(instr->hydrogen()->flags()); |
| 4417 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 4418 } |
| 4308 } | 4419 } |
| 4309 | 4420 |
| 4310 | 4421 |
| 4311 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { | 4422 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { |
| 4312 class DeferredStringCharCodeAt V8_FINAL : public LDeferredCode { | 4423 class DeferredStringCharCodeAt V8_FINAL : public LDeferredCode { |
| 4313 public: | 4424 public: |
| 4314 DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr) | 4425 DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr) |
| 4315 : LDeferredCode(codegen), instr_(instr) { } | 4426 : LDeferredCode(codegen), instr_(instr) { } |
| 4316 virtual void Generate() V8_OVERRIDE { | 4427 virtual void Generate() V8_OVERRIDE { |
| 4317 codegen()->DoDeferredStringCharCodeAt(instr_); | 4428 codegen()->DoDeferredStringCharCodeAt(instr_); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 4348 // DoStringCharCodeAt above. | 4459 // DoStringCharCodeAt above. |
| 4349 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue); | 4460 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue); |
| 4350 if (instr->index()->IsConstantOperand()) { | 4461 if (instr->index()->IsConstantOperand()) { |
| 4351 int32_t const_index = ToInteger32(LConstantOperand::cast(instr->index())); | 4462 int32_t const_index = ToInteger32(LConstantOperand::cast(instr->index())); |
| 4352 __ Push(Smi::FromInt(const_index)); | 4463 __ Push(Smi::FromInt(const_index)); |
| 4353 } else { | 4464 } else { |
| 4354 Register index = ToRegister(instr->index()); | 4465 Register index = ToRegister(instr->index()); |
| 4355 __ Integer32ToSmi(index, index); | 4466 __ Integer32ToSmi(index, index); |
| 4356 __ push(index); | 4467 __ push(index); |
| 4357 } | 4468 } |
| 4358 CallRuntimeFromDeferred(Runtime::kStringCharCodeAt, 2, instr); | 4469 CallRuntimeFromDeferred( |
| 4470 Runtime::kStringCharCodeAt, 2, instr, instr->context()); |
| 4359 __ AssertSmi(rax); | 4471 __ AssertSmi(rax); |
| 4360 __ SmiToInteger32(rax, rax); | 4472 __ SmiToInteger32(rax, rax); |
| 4361 __ StoreToSafepointRegisterSlot(result, rax); | 4473 __ StoreToSafepointRegisterSlot(result, rax); |
| 4362 } | 4474 } |
| 4363 | 4475 |
| 4364 | 4476 |
| 4365 void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) { | 4477 void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) { |
| 4366 class DeferredStringCharFromCode V8_FINAL : public LDeferredCode { | 4478 class DeferredStringCharFromCode V8_FINAL : public LDeferredCode { |
| 4367 public: | 4479 public: |
| 4368 DeferredStringCharFromCode(LCodeGen* codegen, LStringCharFromCode* instr) | 4480 DeferredStringCharFromCode(LCodeGen* codegen, LStringCharFromCode* instr) |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4401 Register result = ToRegister(instr->result()); | 4513 Register result = ToRegister(instr->result()); |
| 4402 | 4514 |
| 4403 // TODO(3095996): Get rid of this. For now, we need to make the | 4515 // TODO(3095996): Get rid of this. For now, we need to make the |
| 4404 // result register contain a valid pointer because it is already | 4516 // result register contain a valid pointer because it is already |
| 4405 // contained in the register pointer map. | 4517 // contained in the register pointer map. |
| 4406 __ Set(result, 0); | 4518 __ Set(result, 0); |
| 4407 | 4519 |
| 4408 PushSafepointRegistersScope scope(this); | 4520 PushSafepointRegistersScope scope(this); |
| 4409 __ Integer32ToSmi(char_code, char_code); | 4521 __ Integer32ToSmi(char_code, char_code); |
| 4410 __ push(char_code); | 4522 __ push(char_code); |
| 4411 CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr); | 4523 CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr, instr->context()); |
| 4412 __ StoreToSafepointRegisterSlot(result, rax); | 4524 __ StoreToSafepointRegisterSlot(result, rax); |
| 4413 } | 4525 } |
| 4414 | 4526 |
| 4415 | 4527 |
| 4416 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { | 4528 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { |
| 4417 LOperand* input = instr->value(); | 4529 LOperand* input = instr->value(); |
| 4418 ASSERT(input->IsRegister() || input->IsStackSlot()); | 4530 ASSERT(input->IsRegister() || input->IsStackSlot()); |
| 4419 LOperand* output = instr->result(); | 4531 LOperand* output = instr->result(); |
| 4420 ASSERT(output->IsDoubleRegister()); | 4532 ASSERT(output->IsDoubleRegister()); |
| 4421 if (input->IsRegister()) { | 4533 if (input->IsRegister()) { |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4521 } | 4633 } |
| 4522 | 4634 |
| 4523 // Slow case: Call the runtime system to do the number allocation. | 4635 // Slow case: Call the runtime system to do the number allocation. |
| 4524 __ bind(&slow); | 4636 __ bind(&slow); |
| 4525 | 4637 |
| 4526 // Put a valid pointer value in the stack slot where the result | 4638 // Put a valid pointer value in the stack slot where the result |
| 4527 // register is stored, as this register is in the pointer map, but contains an | 4639 // register is stored, as this register is in the pointer map, but contains an |
| 4528 // integer value. | 4640 // integer value. |
| 4529 __ StoreToSafepointRegisterSlot(reg, Immediate(0)); | 4641 __ StoreToSafepointRegisterSlot(reg, Immediate(0)); |
| 4530 | 4642 |
| 4531 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); | 4643 // NumberTagU uses the context from the frame, rather than |
| 4644 // the environment's HContext or HInlinedContext value. |
| 4645 // They only call Runtime::kAllocateHeapNumber. |
| 4646 // The corresponding HChange instructions are added in a phase that does |
| 4647 // not have easy access to the local context. |
| 4648 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 4649 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); |
| 4650 RecordSafepointWithRegisters( |
| 4651 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); |
| 4652 |
| 4532 if (!reg.is(rax)) __ movq(reg, rax); | 4653 if (!reg.is(rax)) __ movq(reg, rax); |
| 4533 | 4654 |
| 4534 // Done. Put the value in temp_xmm into the value of the allocated heap | 4655 // Done. Put the value in temp_xmm into the value of the allocated heap |
| 4535 // number. | 4656 // number. |
| 4536 __ bind(&done); | 4657 __ bind(&done); |
| 4537 __ movsd(FieldOperand(reg, HeapNumber::kValueOffset), temp_xmm); | 4658 __ movsd(FieldOperand(reg, HeapNumber::kValueOffset), temp_xmm); |
| 4538 __ StoreToSafepointRegisterSlot(reg, reg); | 4659 __ StoreToSafepointRegisterSlot(reg, reg); |
| 4539 } | 4660 } |
| 4540 | 4661 |
| 4541 | 4662 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 4569 | 4690 |
| 4570 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { | 4691 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { |
| 4571 // TODO(3095996): Get rid of this. For now, we need to make the | 4692 // TODO(3095996): Get rid of this. For now, we need to make the |
| 4572 // result register contain a valid pointer because it is already | 4693 // result register contain a valid pointer because it is already |
| 4573 // contained in the register pointer map. | 4694 // contained in the register pointer map. |
| 4574 Register reg = ToRegister(instr->result()); | 4695 Register reg = ToRegister(instr->result()); |
| 4575 __ Move(reg, Smi::FromInt(0)); | 4696 __ Move(reg, Smi::FromInt(0)); |
| 4576 | 4697 |
| 4577 { | 4698 { |
| 4578 PushSafepointRegistersScope scope(this); | 4699 PushSafepointRegistersScope scope(this); |
| 4579 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); | 4700 // NumberTagD uses the context from the frame, rather than |
| 4580 // Ensure that value in rax survives popping registers. | 4701 // the environment's HContext or HInlinedContext value. |
| 4702 // They only call Runtime::kAllocateHeapNumber. |
| 4703 // The corresponding HChange instructions are added in a phase that does |
| 4704 // not have easy access to the local context. |
| 4705 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 4706 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); |
| 4707 RecordSafepointWithRegisters( |
| 4708 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); |
| 4581 __ movq(kScratchRegister, rax); | 4709 __ movq(kScratchRegister, rax); |
| 4582 } | 4710 } |
| 4583 __ movq(reg, kScratchRegister); | 4711 __ movq(reg, kScratchRegister); |
| 4584 } | 4712 } |
| 4585 | 4713 |
| 4586 | 4714 |
| 4587 void LCodeGen::DoSmiTag(LSmiTag* instr) { | 4715 void LCodeGen::DoSmiTag(LSmiTag* instr) { |
| 4588 ASSERT(instr->value()->Equals(instr->result())); | 4716 ASSERT(instr->value()->Equals(instr->result())); |
| 4589 Register input = ToRegister(instr->value()); | 4717 Register input = ToRegister(instr->value()); |
| 4590 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)); | 4718 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 4619 | 4747 |
| 4620 // Heap number map check. | 4748 // Heap number map check. |
| 4621 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), | 4749 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), |
| 4622 Heap::kHeapNumberMapRootIndex); | 4750 Heap::kHeapNumberMapRootIndex); |
| 4623 | 4751 |
| 4624 // On x64 it is safe to load at heap number offset before evaluating the map | 4752 // On x64 it is safe to load at heap number offset before evaluating the map |
| 4625 // check, since all heap objects are at least two words long. | 4753 // check, since all heap objects are at least two words long. |
| 4626 __ movsd(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset)); | 4754 __ movsd(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
| 4627 | 4755 |
| 4628 if (can_convert_undefined_to_nan) { | 4756 if (can_convert_undefined_to_nan) { |
| 4629 __ j(not_equal, &convert); | 4757 __ j(not_equal, &convert, Label::kNear); |
| 4630 } else { | 4758 } else { |
| 4631 DeoptimizeIf(not_equal, env); | 4759 DeoptimizeIf(not_equal, env); |
| 4632 } | 4760 } |
| 4633 | 4761 |
| 4634 if (deoptimize_on_minus_zero) { | 4762 if (deoptimize_on_minus_zero) { |
| 4635 XMMRegister xmm_scratch = double_scratch0(); | 4763 XMMRegister xmm_scratch = double_scratch0(); |
| 4636 __ xorps(xmm_scratch, xmm_scratch); | 4764 __ xorps(xmm_scratch, xmm_scratch); |
| 4637 __ ucomisd(xmm_scratch, result_reg); | 4765 __ ucomisd(xmm_scratch, result_reg); |
| 4638 __ j(not_equal, &done, Label::kNear); | 4766 __ j(not_equal, &done, Label::kNear); |
| 4639 __ movmskpd(kScratchRegister, result_reg); | 4767 __ movmskpd(kScratchRegister, result_reg); |
| (...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4876 Register reg = ToRegister(instr->value()); | 5004 Register reg = ToRegister(instr->value()); |
| 4877 __ Cmp(reg, instr->hydrogen()->object().handle()); | 5005 __ Cmp(reg, instr->hydrogen()->object().handle()); |
| 4878 DeoptimizeIf(not_equal, instr->environment()); | 5006 DeoptimizeIf(not_equal, instr->environment()); |
| 4879 } | 5007 } |
| 4880 | 5008 |
| 4881 | 5009 |
| 4882 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) { | 5010 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) { |
| 4883 { | 5011 { |
| 4884 PushSafepointRegistersScope scope(this); | 5012 PushSafepointRegistersScope scope(this); |
| 4885 __ push(object); | 5013 __ push(object); |
| 4886 CallRuntimeFromDeferred(Runtime::kMigrateInstance, 1, instr); | 5014 __ Set(rsi, 0); |
| 5015 __ CallRuntimeSaveDoubles(Runtime::kMigrateInstance); |
| 5016 RecordSafepointWithRegisters( |
| 5017 instr->pointer_map(), 1, Safepoint::kNoLazyDeopt); |
| 5018 |
| 4887 __ testq(rax, Immediate(kSmiTagMask)); | 5019 __ testq(rax, Immediate(kSmiTagMask)); |
| 4888 } | 5020 } |
| 4889 DeoptimizeIf(zero, instr->environment()); | 5021 DeoptimizeIf(zero, instr->environment()); |
| 4890 } | 5022 } |
| 4891 | 5023 |
| 4892 | 5024 |
| 4893 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { | 5025 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { |
| 4894 class DeferredCheckMaps V8_FINAL : public LDeferredCode { | 5026 class DeferredCheckMaps V8_FINAL : public LDeferredCode { |
| 4895 public: | 5027 public: |
| 4896 DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr, Register object) | 5028 DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr, Register object) |
| (...skipping 20 matching lines...) Expand all Loading... |
| 4917 DeferredCheckMaps* deferred = NULL; | 5049 DeferredCheckMaps* deferred = NULL; |
| 4918 if (instr->hydrogen()->has_migration_target()) { | 5050 if (instr->hydrogen()->has_migration_target()) { |
| 4919 deferred = new(zone()) DeferredCheckMaps(this, instr, reg); | 5051 deferred = new(zone()) DeferredCheckMaps(this, instr, reg); |
| 4920 __ bind(deferred->check_maps()); | 5052 __ bind(deferred->check_maps()); |
| 4921 } | 5053 } |
| 4922 | 5054 |
| 4923 UniqueSet<Map> map_set = instr->hydrogen()->map_set(); | 5055 UniqueSet<Map> map_set = instr->hydrogen()->map_set(); |
| 4924 Label success; | 5056 Label success; |
| 4925 for (int i = 0; i < map_set.size() - 1; i++) { | 5057 for (int i = 0; i < map_set.size() - 1; i++) { |
| 4926 Handle<Map> map = map_set.at(i).handle(); | 5058 Handle<Map> map = map_set.at(i).handle(); |
| 4927 __ CompareMap(reg, map, &success); | 5059 __ CompareMap(reg, map); |
| 4928 __ j(equal, &success); | 5060 __ j(equal, &success, Label::kNear); |
| 4929 } | 5061 } |
| 4930 | 5062 |
| 4931 Handle<Map> map = map_set.at(map_set.size() - 1).handle(); | 5063 Handle<Map> map = map_set.at(map_set.size() - 1).handle(); |
| 4932 __ CompareMap(reg, map, &success); | 5064 __ CompareMap(reg, map); |
| 4933 if (instr->hydrogen()->has_migration_target()) { | 5065 if (instr->hydrogen()->has_migration_target()) { |
| 4934 __ j(not_equal, deferred->entry()); | 5066 __ j(not_equal, deferred->entry()); |
| 4935 } else { | 5067 } else { |
| 4936 DeoptimizeIf(not_equal, instr->environment()); | 5068 DeoptimizeIf(not_equal, instr->environment()); |
| 4937 } | 5069 } |
| 4938 | 5070 |
| 4939 __ bind(&success); | 5071 __ bind(&success); |
| 4940 } | 5072 } |
| 4941 | 5073 |
| 4942 | 5074 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 4954 __ ClampUint8(value_reg); | 5086 __ ClampUint8(value_reg); |
| 4955 } | 5087 } |
| 4956 | 5088 |
| 4957 | 5089 |
| 4958 void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) { | 5090 void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) { |
| 4959 ASSERT(instr->unclamped()->Equals(instr->result())); | 5091 ASSERT(instr->unclamped()->Equals(instr->result())); |
| 4960 Register input_reg = ToRegister(instr->unclamped()); | 5092 Register input_reg = ToRegister(instr->unclamped()); |
| 4961 XMMRegister temp_xmm_reg = ToDoubleRegister(instr->temp_xmm()); | 5093 XMMRegister temp_xmm_reg = ToDoubleRegister(instr->temp_xmm()); |
| 4962 XMMRegister xmm_scratch = double_scratch0(); | 5094 XMMRegister xmm_scratch = double_scratch0(); |
| 4963 Label is_smi, done, heap_number; | 5095 Label is_smi, done, heap_number; |
| 4964 | 5096 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear; |
| 4965 __ JumpIfSmi(input_reg, &is_smi); | 5097 __ JumpIfSmi(input_reg, &is_smi, dist); |
| 4966 | 5098 |
| 4967 // Check for heap number | 5099 // Check for heap number |
| 4968 __ Cmp(FieldOperand(input_reg, HeapObject::kMapOffset), | 5100 __ Cmp(FieldOperand(input_reg, HeapObject::kMapOffset), |
| 4969 factory()->heap_number_map()); | 5101 factory()->heap_number_map()); |
| 4970 __ j(equal, &heap_number, Label::kNear); | 5102 __ j(equal, &heap_number, Label::kNear); |
| 4971 | 5103 |
| 4972 // Check for undefined. Undefined is converted to zero for clamping | 5104 // Check for undefined. Undefined is converted to zero for clamping |
| 4973 // conversions. | 5105 // conversions. |
| 4974 __ Cmp(input_reg, factory()->undefined_value()); | 5106 __ Cmp(input_reg, factory()->undefined_value()); |
| 4975 DeoptimizeIf(not_equal, instr->environment()); | 5107 DeoptimizeIf(not_equal, instr->environment()); |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5068 __ Integer32ToSmi(size, size); | 5200 __ Integer32ToSmi(size, size); |
| 5069 __ push(size); | 5201 __ push(size); |
| 5070 } else { | 5202 } else { |
| 5071 int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); | 5203 int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); |
| 5072 __ Push(Smi::FromInt(size)); | 5204 __ Push(Smi::FromInt(size)); |
| 5073 } | 5205 } |
| 5074 | 5206 |
| 5075 if (instr->hydrogen()->IsOldPointerSpaceAllocation()) { | 5207 if (instr->hydrogen()->IsOldPointerSpaceAllocation()) { |
| 5076 ASSERT(!instr->hydrogen()->IsOldDataSpaceAllocation()); | 5208 ASSERT(!instr->hydrogen()->IsOldDataSpaceAllocation()); |
| 5077 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); | 5209 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); |
| 5078 CallRuntimeFromDeferred(Runtime::kAllocateInOldPointerSpace, 1, instr); | 5210 CallRuntimeFromDeferred( |
| 5211 Runtime::kAllocateInOldPointerSpace, 1, instr, instr->context()); |
| 5079 } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) { | 5212 } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) { |
| 5080 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); | 5213 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); |
| 5081 CallRuntimeFromDeferred(Runtime::kAllocateInOldDataSpace, 1, instr); | 5214 CallRuntimeFromDeferred( |
| 5215 Runtime::kAllocateInOldDataSpace, 1, instr, instr->context()); |
| 5082 } else { | 5216 } else { |
| 5083 CallRuntimeFromDeferred(Runtime::kAllocateInNewSpace, 1, instr); | 5217 CallRuntimeFromDeferred( |
| 5218 Runtime::kAllocateInNewSpace, 1, instr, instr->context()); |
| 5084 } | 5219 } |
| 5085 __ StoreToSafepointRegisterSlot(result, rax); | 5220 __ StoreToSafepointRegisterSlot(result, rax); |
| 5086 } | 5221 } |
| 5087 | 5222 |
| 5088 | 5223 |
| 5089 void LCodeGen::DoToFastProperties(LToFastProperties* instr) { | 5224 void LCodeGen::DoToFastProperties(LToFastProperties* instr) { |
| 5090 ASSERT(ToRegister(instr->value()).is(rax)); | 5225 ASSERT(ToRegister(instr->value()).is(rax)); |
| 5091 __ push(rax); | 5226 __ push(rax); |
| 5092 CallRuntime(Runtime::kToFastProperties, 1, instr); | 5227 CallRuntime(Runtime::kToFastProperties, 1, instr); |
| 5093 } | 5228 } |
| 5094 | 5229 |
| 5095 | 5230 |
| 5096 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { | 5231 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { |
| 5232 ASSERT(ToRegister(instr->context()).is(rsi)); |
| 5097 Label materialized; | 5233 Label materialized; |
| 5098 // Registers will be used as follows: | 5234 // Registers will be used as follows: |
| 5099 // rcx = literals array. | 5235 // rcx = literals array. |
| 5100 // rbx = regexp literal. | 5236 // rbx = regexp literal. |
| 5101 // rax = regexp literal clone. | 5237 // rax = regexp literal clone. |
| 5102 int literal_offset = | 5238 int literal_offset = |
| 5103 FixedArray::OffsetOfElementAt(instr->hydrogen()->literal_index()); | 5239 FixedArray::OffsetOfElementAt(instr->hydrogen()->literal_index()); |
| 5104 __ Move(rcx, instr->hydrogen()->literals()); | 5240 __ Move(rcx, instr->hydrogen()->literals()); |
| 5105 __ movq(rbx, FieldOperand(rcx, literal_offset)); | 5241 __ movq(rbx, FieldOperand(rcx, literal_offset)); |
| 5106 __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex); | 5242 __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex); |
| 5107 __ j(not_equal, &materialized, Label::kNear); | 5243 __ j(not_equal, &materialized, Label::kNear); |
| 5108 | 5244 |
| 5109 // Create regexp literal using runtime function | 5245 // Create regexp literal using runtime function |
| 5110 // Result will be in rax. | 5246 // Result will be in rax. |
| 5111 __ push(rcx); | 5247 __ push(rcx); |
| 5112 __ Push(Smi::FromInt(instr->hydrogen()->literal_index())); | 5248 __ Push(Smi::FromInt(instr->hydrogen()->literal_index())); |
| 5113 __ Push(instr->hydrogen()->pattern()); | 5249 __ Push(instr->hydrogen()->pattern()); |
| 5114 __ Push(instr->hydrogen()->flags()); | 5250 __ Push(instr->hydrogen()->flags()); |
| 5115 CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr); | 5251 CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr); |
| 5116 __ movq(rbx, rax); | 5252 __ movq(rbx, rax); |
| 5117 | 5253 |
| 5118 __ bind(&materialized); | 5254 __ bind(&materialized); |
| 5119 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; | 5255 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; |
| 5120 Label allocated, runtime_allocate; | 5256 Label allocated, runtime_allocate; |
| 5121 __ Allocate(size, rax, rcx, rdx, &runtime_allocate, TAG_OBJECT); | 5257 __ Allocate(size, rax, rcx, rdx, &runtime_allocate, TAG_OBJECT); |
| 5122 __ jmp(&allocated); | 5258 __ jmp(&allocated, Label::kNear); |
| 5123 | 5259 |
| 5124 __ bind(&runtime_allocate); | 5260 __ bind(&runtime_allocate); |
| 5125 __ push(rbx); | 5261 __ push(rbx); |
| 5126 __ Push(Smi::FromInt(size)); | 5262 __ Push(Smi::FromInt(size)); |
| 5127 CallRuntime(Runtime::kAllocateInNewSpace, 1, instr); | 5263 CallRuntime(Runtime::kAllocateInNewSpace, 1, instr); |
| 5128 __ pop(rbx); | 5264 __ pop(rbx); |
| 5129 | 5265 |
| 5130 __ bind(&allocated); | 5266 __ bind(&allocated); |
| 5131 // Copy the content into the newly allocated memory. | 5267 // Copy the content into the newly allocated memory. |
| 5132 // (Unroll copy loop once for better throughput). | 5268 // (Unroll copy loop once for better throughput). |
| 5133 for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) { | 5269 for (int i = 0; i < size - kPointerSize; i += 2 * kPointerSize) { |
| 5134 __ movq(rdx, FieldOperand(rbx, i)); | 5270 __ movq(rdx, FieldOperand(rbx, i)); |
| 5135 __ movq(rcx, FieldOperand(rbx, i + kPointerSize)); | 5271 __ movq(rcx, FieldOperand(rbx, i + kPointerSize)); |
| 5136 __ movq(FieldOperand(rax, i), rdx); | 5272 __ movq(FieldOperand(rax, i), rdx); |
| 5137 __ movq(FieldOperand(rax, i + kPointerSize), rcx); | 5273 __ movq(FieldOperand(rax, i + kPointerSize), rcx); |
| 5138 } | 5274 } |
| 5139 if ((size % (2 * kPointerSize)) != 0) { | 5275 if ((size % (2 * kPointerSize)) != 0) { |
| 5140 __ movq(rdx, FieldOperand(rbx, size - kPointerSize)); | 5276 __ movq(rdx, FieldOperand(rbx, size - kPointerSize)); |
| 5141 __ movq(FieldOperand(rax, size - kPointerSize), rdx); | 5277 __ movq(FieldOperand(rax, size - kPointerSize), rdx); |
| 5142 } | 5278 } |
| 5143 } | 5279 } |
| 5144 | 5280 |
| 5145 | 5281 |
| 5146 void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) { | 5282 void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) { |
| 5283 ASSERT(ToRegister(instr->context()).is(rsi)); |
| 5147 // Use the fast case closure allocation code that allocates in new | 5284 // Use the fast case closure allocation code that allocates in new |
| 5148 // space for nested functions that don't need literals cloning. | 5285 // space for nested functions that don't need literals cloning. |
| 5149 bool pretenure = instr->hydrogen()->pretenure(); | 5286 bool pretenure = instr->hydrogen()->pretenure(); |
| 5150 if (!pretenure && instr->hydrogen()->has_no_literals()) { | 5287 if (!pretenure && instr->hydrogen()->has_no_literals()) { |
| 5151 FastNewClosureStub stub(instr->hydrogen()->language_mode(), | 5288 FastNewClosureStub stub(instr->hydrogen()->language_mode(), |
| 5152 instr->hydrogen()->is_generator()); | 5289 instr->hydrogen()->is_generator()); |
| 5153 __ Move(rbx, instr->hydrogen()->shared_info()); | 5290 __ Move(rbx, instr->hydrogen()->shared_info()); |
| 5154 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 5291 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 5155 } else { | 5292 } else { |
| 5156 __ push(rsi); | 5293 __ push(rsi); |
| 5157 __ Push(instr->hydrogen()->shared_info()); | 5294 __ Push(instr->hydrogen()->shared_info()); |
| 5158 __ PushRoot(pretenure ? Heap::kTrueValueRootIndex : | 5295 __ PushRoot(pretenure ? Heap::kTrueValueRootIndex : |
| 5159 Heap::kFalseValueRootIndex); | 5296 Heap::kFalseValueRootIndex); |
| 5160 CallRuntime(Runtime::kNewClosure, 3, instr); | 5297 CallRuntime(Runtime::kNewClosure, 3, instr); |
| 5161 } | 5298 } |
| 5162 } | 5299 } |
| 5163 | 5300 |
| 5164 | 5301 |
| 5165 void LCodeGen::DoTypeof(LTypeof* instr) { | 5302 void LCodeGen::DoTypeof(LTypeof* instr) { |
| 5303 ASSERT(ToRegister(instr->context()).is(rsi)); |
| 5166 LOperand* input = instr->value(); | 5304 LOperand* input = instr->value(); |
| 5167 EmitPushTaggedOperand(input); | 5305 EmitPushTaggedOperand(input); |
| 5168 CallRuntime(Runtime::kTypeof, 1, instr); | 5306 CallRuntime(Runtime::kTypeof, 1, instr); |
| 5169 } | 5307 } |
| 5170 | 5308 |
| 5171 | 5309 |
| 5172 void LCodeGen::EmitPushTaggedOperand(LOperand* operand) { | 5310 void LCodeGen::EmitPushTaggedOperand(LOperand* operand) { |
| 5173 ASSERT(!operand->IsDoubleRegister()); | 5311 ASSERT(!operand->IsDoubleRegister()); |
| 5174 if (operand->IsConstantOperand()) { | 5312 if (operand->IsConstantOperand()) { |
| 5175 __ Push(ToHandle(LConstantOperand::cast(operand))); | 5313 __ Push(ToHandle(LConstantOperand::cast(operand))); |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5325 // the special case below. | 5463 // the special case below. |
| 5326 if (info()->IsStub() && type == Deoptimizer::EAGER) { | 5464 if (info()->IsStub() && type == Deoptimizer::EAGER) { |
| 5327 type = Deoptimizer::LAZY; | 5465 type = Deoptimizer::LAZY; |
| 5328 } | 5466 } |
| 5329 | 5467 |
| 5330 Comment(";;; deoptimize: %s", instr->hydrogen()->reason()); | 5468 Comment(";;; deoptimize: %s", instr->hydrogen()->reason()); |
| 5331 DeoptimizeIf(no_condition, instr->environment(), type); | 5469 DeoptimizeIf(no_condition, instr->environment(), type); |
| 5332 } | 5470 } |
| 5333 | 5471 |
| 5334 | 5472 |
| 5473 void LCodeGen::DoDummy(LDummy* instr) { |
| 5474 // Nothing to see here, move on! |
| 5475 } |
| 5476 |
| 5477 |
| 5335 void LCodeGen::DoDummyUse(LDummyUse* instr) { | 5478 void LCodeGen::DoDummyUse(LDummyUse* instr) { |
| 5336 // Nothing to see here, move on! | 5479 // Nothing to see here, move on! |
| 5337 } | 5480 } |
| 5338 | 5481 |
| 5339 | 5482 |
| 5340 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) { | 5483 void LCodeGen::DoDeferredStackCheck(LStackCheck* instr) { |
| 5341 PushSafepointRegistersScope scope(this); | 5484 PushSafepointRegistersScope scope(this); |
| 5342 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 5485 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 5343 __ CallRuntimeSaveDoubles(Runtime::kStackGuard); | 5486 __ CallRuntimeSaveDoubles(Runtime::kStackGuard); |
| 5344 RecordSafepointWithLazyDeopt(instr, RECORD_SAFEPOINT_WITH_REGISTERS, 0); | 5487 RecordSafepointWithLazyDeopt(instr, RECORD_SAFEPOINT_WITH_REGISTERS, 0); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 5363 | 5506 |
| 5364 ASSERT(instr->HasEnvironment()); | 5507 ASSERT(instr->HasEnvironment()); |
| 5365 LEnvironment* env = instr->environment(); | 5508 LEnvironment* env = instr->environment(); |
| 5366 // There is no LLazyBailout instruction for stack-checks. We have to | 5509 // There is no LLazyBailout instruction for stack-checks. We have to |
| 5367 // prepare for lazy deoptimization explicitly here. | 5510 // prepare for lazy deoptimization explicitly here. |
| 5368 if (instr->hydrogen()->is_function_entry()) { | 5511 if (instr->hydrogen()->is_function_entry()) { |
| 5369 // Perform stack overflow check. | 5512 // Perform stack overflow check. |
| 5370 Label done; | 5513 Label done; |
| 5371 __ CompareRoot(rsp, Heap::kStackLimitRootIndex); | 5514 __ CompareRoot(rsp, Heap::kStackLimitRootIndex); |
| 5372 __ j(above_equal, &done, Label::kNear); | 5515 __ j(above_equal, &done, Label::kNear); |
| 5516 |
| 5517 ASSERT(instr->context()->IsRegister()); |
| 5518 ASSERT(ToRegister(instr->context()).is(rsi)); |
| 5373 CallCode(isolate()->builtins()->StackCheck(), | 5519 CallCode(isolate()->builtins()->StackCheck(), |
| 5374 RelocInfo::CODE_TARGET, | 5520 RelocInfo::CODE_TARGET, |
| 5375 instr); | 5521 instr); |
| 5376 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); | 5522 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); |
| 5377 last_lazy_deopt_pc_ = masm()->pc_offset(); | 5523 last_lazy_deopt_pc_ = masm()->pc_offset(); |
| 5378 __ bind(&done); | 5524 __ bind(&done); |
| 5379 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); | 5525 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); |
| 5380 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); | 5526 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); |
| 5381 } else { | 5527 } else { |
| 5382 ASSERT(instr->hydrogen()->is_backwards_branch()); | 5528 ASSERT(instr->hydrogen()->is_backwards_branch()); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 5406 // If the environment were already registered, we would have no way of | 5552 // If the environment were already registered, we would have no way of |
| 5407 // backpatching it with the spill slot operands. | 5553 // backpatching it with the spill slot operands. |
| 5408 ASSERT(!environment->HasBeenRegistered()); | 5554 ASSERT(!environment->HasBeenRegistered()); |
| 5409 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); | 5555 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); |
| 5410 | 5556 |
| 5411 GenerateOsrPrologue(); | 5557 GenerateOsrPrologue(); |
| 5412 } | 5558 } |
| 5413 | 5559 |
| 5414 | 5560 |
| 5415 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { | 5561 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { |
| 5562 ASSERT(ToRegister(instr->context()).is(rsi)); |
| 5416 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); | 5563 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); |
| 5417 DeoptimizeIf(equal, instr->environment()); | 5564 DeoptimizeIf(equal, instr->environment()); |
| 5418 | 5565 |
| 5419 Register null_value = rdi; | 5566 Register null_value = rdi; |
| 5420 __ LoadRoot(null_value, Heap::kNullValueRootIndex); | 5567 __ LoadRoot(null_value, Heap::kNullValueRootIndex); |
| 5421 __ cmpq(rax, null_value); | 5568 __ cmpq(rax, null_value); |
| 5422 DeoptimizeIf(equal, instr->environment()); | 5569 DeoptimizeIf(equal, instr->environment()); |
| 5423 | 5570 |
| 5424 Condition cc = masm()->CheckSmi(rax); | 5571 Condition cc = masm()->CheckSmi(rax); |
| 5425 DeoptimizeIf(cc, instr->environment()); | 5572 DeoptimizeIf(cc, instr->environment()); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 5445 __ bind(&use_cache); | 5592 __ bind(&use_cache); |
| 5446 } | 5593 } |
| 5447 | 5594 |
| 5448 | 5595 |
| 5449 void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) { | 5596 void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) { |
| 5450 Register map = ToRegister(instr->map()); | 5597 Register map = ToRegister(instr->map()); |
| 5451 Register result = ToRegister(instr->result()); | 5598 Register result = ToRegister(instr->result()); |
| 5452 Label load_cache, done; | 5599 Label load_cache, done; |
| 5453 __ EnumLength(result, map); | 5600 __ EnumLength(result, map); |
| 5454 __ Cmp(result, Smi::FromInt(0)); | 5601 __ Cmp(result, Smi::FromInt(0)); |
| 5455 __ j(not_equal, &load_cache); | 5602 __ j(not_equal, &load_cache, Label::kNear); |
| 5456 __ LoadRoot(result, Heap::kEmptyFixedArrayRootIndex); | 5603 __ LoadRoot(result, Heap::kEmptyFixedArrayRootIndex); |
| 5457 __ jmp(&done); | 5604 __ jmp(&done, Label::kNear); |
| 5458 __ bind(&load_cache); | 5605 __ bind(&load_cache); |
| 5459 __ LoadInstanceDescriptors(map, result); | 5606 __ LoadInstanceDescriptors(map, result); |
| 5460 __ movq(result, | 5607 __ movq(result, |
| 5461 FieldOperand(result, DescriptorArray::kEnumCacheOffset)); | 5608 FieldOperand(result, DescriptorArray::kEnumCacheOffset)); |
| 5462 __ movq(result, | 5609 __ movq(result, |
| 5463 FieldOperand(result, FixedArray::SizeFor(instr->idx()))); | 5610 FieldOperand(result, FixedArray::SizeFor(instr->idx()))); |
| 5464 __ bind(&done); | 5611 __ bind(&done); |
| 5465 Condition cc = masm()->CheckSmi(result); | 5612 Condition cc = masm()->CheckSmi(result); |
| 5466 DeoptimizeIf(cc, instr->environment()); | 5613 DeoptimizeIf(cc, instr->environment()); |
| 5467 } | 5614 } |
| 5468 | 5615 |
| 5469 | 5616 |
| 5470 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) { | 5617 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) { |
| 5471 Register object = ToRegister(instr->value()); | 5618 Register object = ToRegister(instr->value()); |
| 5472 __ cmpq(ToRegister(instr->map()), | 5619 __ cmpq(ToRegister(instr->map()), |
| 5473 FieldOperand(object, HeapObject::kMapOffset)); | 5620 FieldOperand(object, HeapObject::kMapOffset)); |
| 5474 DeoptimizeIf(not_equal, instr->environment()); | 5621 DeoptimizeIf(not_equal, instr->environment()); |
| 5475 } | 5622 } |
| 5476 | 5623 |
| 5477 | 5624 |
| 5478 void LCodeGen::DoLoadFieldByIndex(LLoadFieldByIndex* instr) { | 5625 void LCodeGen::DoLoadFieldByIndex(LLoadFieldByIndex* instr) { |
| 5479 Register object = ToRegister(instr->object()); | 5626 Register object = ToRegister(instr->object()); |
| 5480 Register index = ToRegister(instr->index()); | 5627 Register index = ToRegister(instr->index()); |
| 5481 | 5628 |
| 5482 Label out_of_object, done; | 5629 Label out_of_object, done; |
| 5483 __ SmiToInteger32(index, index); | 5630 __ SmiToInteger32(index, index); |
| 5484 __ cmpl(index, Immediate(0)); | 5631 __ cmpl(index, Immediate(0)); |
| 5485 __ j(less, &out_of_object); | 5632 __ j(less, &out_of_object, Label::kNear); |
| 5486 __ movq(object, FieldOperand(object, | 5633 __ movq(object, FieldOperand(object, |
| 5487 index, | 5634 index, |
| 5488 times_pointer_size, | 5635 times_pointer_size, |
| 5489 JSObject::kHeaderSize)); | 5636 JSObject::kHeaderSize)); |
| 5490 __ jmp(&done, Label::kNear); | 5637 __ jmp(&done, Label::kNear); |
| 5491 | 5638 |
| 5492 __ bind(&out_of_object); | 5639 __ bind(&out_of_object); |
| 5493 __ movq(object, FieldOperand(object, JSObject::kPropertiesOffset)); | 5640 __ movq(object, FieldOperand(object, JSObject::kPropertiesOffset)); |
| 5494 __ negl(index); | 5641 __ negl(index); |
| 5495 // Index is now equal to out of object property index plus 1. | 5642 // Index is now equal to out of object property index plus 1. |
| 5496 __ movq(object, FieldOperand(object, | 5643 __ movq(object, FieldOperand(object, |
| 5497 index, | 5644 index, |
| 5498 times_pointer_size, | 5645 times_pointer_size, |
| 5499 FixedArray::kHeaderSize - kPointerSize)); | 5646 FixedArray::kHeaderSize - kPointerSize)); |
| 5500 __ bind(&done); | 5647 __ bind(&done); |
| 5501 } | 5648 } |
| 5502 | 5649 |
| 5503 | 5650 |
| 5504 #undef __ | 5651 #undef __ |
| 5505 | 5652 |
| 5506 } } // namespace v8::internal | 5653 } } // namespace v8::internal |
| 5507 | 5654 |
| 5508 #endif // V8_TARGET_ARCH_X64 | 5655 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |