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

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

Issue 132373011: A64: Synchronize with r17635. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/x64/lithium-codegen-x64.h ('k') | src/x64/lithium-gap-resolver-x64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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(&not_applicable); 4391 __ bind(&not_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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/x64/lithium-codegen-x64.h ('k') | src/x64/lithium-gap-resolver-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698