| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 759 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 770 | 770 |
| 771 void LCodeGen::DeoptimizeIf(Condition cc, | 771 void LCodeGen::DeoptimizeIf(Condition cc, |
| 772 LEnvironment* environment) { | 772 LEnvironment* environment) { |
| 773 Deoptimizer::BailoutType bailout_type = info()->IsStub() | 773 Deoptimizer::BailoutType bailout_type = info()->IsStub() |
| 774 ? Deoptimizer::LAZY | 774 ? Deoptimizer::LAZY |
| 775 : Deoptimizer::EAGER; | 775 : Deoptimizer::EAGER; |
| 776 DeoptimizeIf(cc, environment, bailout_type); | 776 DeoptimizeIf(cc, environment, bailout_type); |
| 777 } | 777 } |
| 778 | 778 |
| 779 | 779 |
| 780 void LCodeGen::RegisterDependentCodeForEmbeddedMaps(Handle<Code> code) { | |
| 781 ZoneList<Handle<Map> > maps(1, zone()); | |
| 782 ZoneList<Handle<JSObject> > objects(1, zone()); | |
| 783 int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); | |
| 784 for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) { | |
| 785 if (Code::IsWeakEmbeddedObject(code->kind(), it.rinfo()->target_object())) { | |
| 786 if (it.rinfo()->target_object()->IsMap()) { | |
| 787 Handle<Map> map(Map::cast(it.rinfo()->target_object())); | |
| 788 maps.Add(map, zone()); | |
| 789 } else if (it.rinfo()->target_object()->IsJSObject()) { | |
| 790 Handle<JSObject> object(JSObject::cast(it.rinfo()->target_object())); | |
| 791 objects.Add(object, zone()); | |
| 792 } | |
| 793 } | |
| 794 } | |
| 795 #ifdef VERIFY_HEAP | |
| 796 // This disables verification of weak embedded objects after full GC. | |
| 797 // AddDependentCode can cause a GC, which would observe the state where | |
| 798 // this code is not yet in the depended code lists of the embedded maps. | |
| 799 NoWeakObjectVerificationScope disable_verification_of_embedded_objects; | |
| 800 #endif | |
| 801 for (int i = 0; i < maps.length(); i++) { | |
| 802 maps.at(i)->AddDependentCode(DependentCode::kWeaklyEmbeddedGroup, code); | |
| 803 } | |
| 804 for (int i = 0; i < objects.length(); i++) { | |
| 805 AddWeakObjectToCodeDependency(isolate()->heap(), objects.at(i), code); | |
| 806 } | |
| 807 } | |
| 808 | |
| 809 | |
| 810 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { | 780 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { |
| 811 int length = deoptimizations_.length(); | 781 int length = deoptimizations_.length(); |
| 812 if (length == 0) return; | 782 if (length == 0) return; |
| 813 Handle<DeoptimizationInputData> data = | 783 Handle<DeoptimizationInputData> data = |
| 814 factory()->NewDeoptimizationInputData(length, TENURED); | 784 factory()->NewDeoptimizationInputData(length, TENURED); |
| 815 | 785 |
| 816 Handle<ByteArray> translations = | 786 Handle<ByteArray> translations = |
| 817 translations_.CreateByteArray(isolate()->factory()); | 787 translations_.CreateByteArray(isolate()->factory()); |
| 818 data->SetTranslationByteArray(*translations); | 788 data->SetTranslationByteArray(*translations); |
| 819 data->SetInlinedFunctionCount(Smi::FromInt(inlined_function_count_)); | 789 data->SetInlinedFunctionCount(Smi::FromInt(inlined_function_count_)); |
| (...skipping 954 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1774 Comment("Unreachable code."); | 1744 Comment("Unreachable code."); |
| 1775 __ int3(); | 1745 __ int3(); |
| 1776 } | 1746 } |
| 1777 } | 1747 } |
| 1778 | 1748 |
| 1779 | 1749 |
| 1780 void LCodeGen::DoAddI(LAddI* instr) { | 1750 void LCodeGen::DoAddI(LAddI* instr) { |
| 1781 LOperand* left = instr->left(); | 1751 LOperand* left = instr->left(); |
| 1782 LOperand* right = instr->right(); | 1752 LOperand* right = instr->right(); |
| 1783 | 1753 |
| 1754 Representation target_rep = instr->hydrogen()->representation(); |
| 1755 bool is_q = target_rep.IsSmi() || target_rep.IsExternal(); |
| 1756 |
| 1784 if (LAddI::UseLea(instr->hydrogen()) && !left->Equals(instr->result())) { | 1757 if (LAddI::UseLea(instr->hydrogen()) && !left->Equals(instr->result())) { |
| 1785 if (right->IsConstantOperand()) { | 1758 if (right->IsConstantOperand()) { |
| 1786 int32_t offset = ToInteger32(LConstantOperand::cast(right)); | 1759 int32_t offset = ToInteger32(LConstantOperand::cast(right)); |
| 1787 __ leal(ToRegister(instr->result()), | 1760 if (is_q) { |
| 1788 MemOperand(ToRegister(left), offset)); | 1761 __ lea(ToRegister(instr->result()), |
| 1762 MemOperand(ToRegister(left), offset)); |
| 1763 } else { |
| 1764 __ leal(ToRegister(instr->result()), |
| 1765 MemOperand(ToRegister(left), offset)); |
| 1766 } |
| 1789 } else { | 1767 } else { |
| 1790 Operand address(ToRegister(left), ToRegister(right), times_1, 0); | 1768 Operand address(ToRegister(left), ToRegister(right), times_1, 0); |
| 1791 if (instr->hydrogen()->representation().IsSmi()) { | 1769 if (is_q) { |
| 1792 __ lea(ToRegister(instr->result()), address); | 1770 __ lea(ToRegister(instr->result()), address); |
| 1793 } else { | 1771 } else { |
| 1794 __ leal(ToRegister(instr->result()), address); | 1772 __ leal(ToRegister(instr->result()), address); |
| 1795 } | 1773 } |
| 1796 } | 1774 } |
| 1797 } else { | 1775 } else { |
| 1798 if (right->IsConstantOperand()) { | 1776 if (right->IsConstantOperand()) { |
| 1799 __ addl(ToRegister(left), | 1777 if (is_q) { |
| 1800 Immediate(ToInteger32(LConstantOperand::cast(right)))); | 1778 __ addq(ToRegister(left), |
| 1779 Immediate(ToInteger32(LConstantOperand::cast(right)))); |
| 1780 } else { |
| 1781 __ addl(ToRegister(left), |
| 1782 Immediate(ToInteger32(LConstantOperand::cast(right)))); |
| 1783 } |
| 1801 } else if (right->IsRegister()) { | 1784 } else if (right->IsRegister()) { |
| 1802 if (instr->hydrogen_value()->representation().IsSmi()) { | 1785 if (is_q) { |
| 1803 __ addq(ToRegister(left), ToRegister(right)); | 1786 __ addq(ToRegister(left), ToRegister(right)); |
| 1804 } else { | 1787 } else { |
| 1805 __ addl(ToRegister(left), ToRegister(right)); | 1788 __ addl(ToRegister(left), ToRegister(right)); |
| 1806 } | 1789 } |
| 1807 } else { | 1790 } else { |
| 1808 if (instr->hydrogen_value()->representation().IsSmi()) { | 1791 if (is_q) { |
| 1809 __ addq(ToRegister(left), ToOperand(right)); | 1792 __ addq(ToRegister(left), ToOperand(right)); |
| 1810 } else { | 1793 } else { |
| 1811 __ addl(ToRegister(left), ToOperand(right)); | 1794 __ addl(ToRegister(left), ToOperand(right)); |
| 1812 } | 1795 } |
| 1813 } | 1796 } |
| 1814 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | 1797 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
| 1815 DeoptimizeIf(overflow, instr->environment()); | 1798 DeoptimizeIf(overflow, instr->environment()); |
| 1816 } | 1799 } |
| 1817 } | 1800 } |
| 1818 } | 1801 } |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1931 } | 1914 } |
| 1932 } | 1915 } |
| 1933 | 1916 |
| 1934 | 1917 |
| 1935 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { | 1918 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { |
| 1936 ASSERT(ToRegister(instr->context()).is(rsi)); | 1919 ASSERT(ToRegister(instr->context()).is(rsi)); |
| 1937 ASSERT(ToRegister(instr->left()).is(rdx)); | 1920 ASSERT(ToRegister(instr->left()).is(rdx)); |
| 1938 ASSERT(ToRegister(instr->right()).is(rax)); | 1921 ASSERT(ToRegister(instr->right()).is(rax)); |
| 1939 ASSERT(ToRegister(instr->result()).is(rax)); | 1922 ASSERT(ToRegister(instr->result()).is(rax)); |
| 1940 | 1923 |
| 1941 BinaryOpStub stub(instr->op(), NO_OVERWRITE); | 1924 BinaryOpICStub stub(instr->op(), NO_OVERWRITE); |
| 1942 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 1925 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 1943 __ nop(); // Signals no inlined code. | 1926 __ nop(); // Signals no inlined code. |
| 1944 } | 1927 } |
| 1945 | 1928 |
| 1946 | 1929 |
| 1947 template<class InstrType> | 1930 template<class InstrType> |
| 1948 void LCodeGen::EmitBranch(InstrType instr, Condition cc) { | 1931 void LCodeGen::EmitBranch(InstrType instr, Condition cc) { |
| 1949 int left_block = instr->TrueDestination(chunk_); | 1932 int left_block = instr->TrueDestination(chunk_); |
| 1950 int right_block = instr->FalseDestination(chunk_); | 1933 int right_block = instr->FalseDestination(chunk_); |
| 1951 | 1934 |
| (...skipping 901 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2853 XMMRegister result = ToDoubleRegister(instr->result()); | 2836 XMMRegister result = ToDoubleRegister(instr->result()); |
| 2854 __ movsd(result, FieldOperand(object, offset)); | 2837 __ movsd(result, FieldOperand(object, offset)); |
| 2855 return; | 2838 return; |
| 2856 } | 2839 } |
| 2857 | 2840 |
| 2858 Register result = ToRegister(instr->result()); | 2841 Register result = ToRegister(instr->result()); |
| 2859 if (!access.IsInobject()) { | 2842 if (!access.IsInobject()) { |
| 2860 __ movq(result, FieldOperand(object, JSObject::kPropertiesOffset)); | 2843 __ movq(result, FieldOperand(object, JSObject::kPropertiesOffset)); |
| 2861 object = result; | 2844 object = result; |
| 2862 } | 2845 } |
| 2863 __ Load(result, FieldOperand(object, offset), access.representation()); | 2846 |
| 2847 Representation representation = access.representation(); |
| 2848 if (representation.IsSmi() && |
| 2849 instr->hydrogen()->representation().IsInteger32()) { |
| 2850 // Read int value directly from upper half of the smi. |
| 2851 STATIC_ASSERT(kSmiTag == 0); |
| 2852 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 32); |
| 2853 offset += kPointerSize / 2; |
| 2854 representation = Representation::Integer32(); |
| 2855 } |
| 2856 __ Load(result, FieldOperand(object, offset), representation); |
| 2864 } | 2857 } |
| 2865 | 2858 |
| 2866 | 2859 |
| 2867 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { | 2860 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { |
| 2868 ASSERT(ToRegister(instr->context()).is(rsi)); | 2861 ASSERT(ToRegister(instr->context()).is(rsi)); |
| 2869 ASSERT(ToRegister(instr->object()).is(rax)); | 2862 ASSERT(ToRegister(instr->object()).is(rax)); |
| 2870 ASSERT(ToRegister(instr->result()).is(rax)); | 2863 ASSERT(ToRegister(instr->result()).is(rax)); |
| 2871 | 2864 |
| 2872 __ Move(rcx, instr->name()); | 2865 __ Move(rcx, instr->name()); |
| 2873 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 2866 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
| (...skipping 883 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3757 __ movsd(Operand(rsp, 0), input_reg); | 3750 __ movsd(Operand(rsp, 0), input_reg); |
| 3758 __ fld_d(Operand(rsp, 0)); | 3751 __ fld_d(Operand(rsp, 0)); |
| 3759 __ fyl2x(); | 3752 __ fyl2x(); |
| 3760 __ fstp_d(Operand(rsp, 0)); | 3753 __ fstp_d(Operand(rsp, 0)); |
| 3761 __ movsd(input_reg, Operand(rsp, 0)); | 3754 __ movsd(input_reg, Operand(rsp, 0)); |
| 3762 __ addq(rsp, Immediate(kDoubleSize)); | 3755 __ addq(rsp, Immediate(kDoubleSize)); |
| 3763 __ bind(&done); | 3756 __ bind(&done); |
| 3764 } | 3757 } |
| 3765 | 3758 |
| 3766 | 3759 |
| 3767 void LCodeGen::DoMathTan(LMathTan* instr) { | |
| 3768 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); | |
| 3769 // Set the context register to a GC-safe fake value. Clobbering it is | |
| 3770 // OK because this instruction is marked as a call. | |
| 3771 __ Set(rsi, 0); | |
| 3772 TranscendentalCacheStub stub(TranscendentalCache::TAN, | |
| 3773 TranscendentalCacheStub::UNTAGGED); | |
| 3774 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | |
| 3775 } | |
| 3776 | |
| 3777 | |
| 3778 void LCodeGen::DoMathCos(LMathCos* instr) { | |
| 3779 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); | |
| 3780 // Set the context register to a GC-safe fake value. Clobbering it is | |
| 3781 // OK because this instruction is marked as a call. | |
| 3782 __ Set(rsi, 0); | |
| 3783 TranscendentalCacheStub stub(TranscendentalCache::COS, | |
| 3784 TranscendentalCacheStub::UNTAGGED); | |
| 3785 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | |
| 3786 } | |
| 3787 | |
| 3788 | |
| 3789 void LCodeGen::DoMathSin(LMathSin* instr) { | |
| 3790 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); | |
| 3791 // Set the context register to a GC-safe fake value. Clobbering it is | |
| 3792 // OK because this instruction is marked as a call. | |
| 3793 __ Set(rsi, 0); | |
| 3794 TranscendentalCacheStub stub(TranscendentalCache::SIN, | |
| 3795 TranscendentalCacheStub::UNTAGGED); | |
| 3796 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | |
| 3797 } | |
| 3798 | |
| 3799 | |
| 3800 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { | 3760 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { |
| 3801 ASSERT(ToRegister(instr->context()).is(rsi)); | 3761 ASSERT(ToRegister(instr->context()).is(rsi)); |
| 3802 ASSERT(ToRegister(instr->function()).is(rdi)); | 3762 ASSERT(ToRegister(instr->function()).is(rdi)); |
| 3803 ASSERT(instr->HasPointerMap()); | 3763 ASSERT(instr->HasPointerMap()); |
| 3804 | 3764 |
| 3805 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); | 3765 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); |
| 3806 if (known_function.is_null()) { | 3766 if (known_function.is_null()) { |
| 3807 LPointerMap* pointers = instr->pointer_map(); | 3767 LPointerMap* pointers = instr->pointer_map(); |
| 3808 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); | 3768 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); |
| 3809 ParameterCount count(instr->arity()); | 3769 ParameterCount count(instr->arity()); |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3952 Register function = ToRegister(instr->function()); | 3912 Register function = ToRegister(instr->function()); |
| 3953 Register code_object = ToRegister(instr->code_object()); | 3913 Register code_object = ToRegister(instr->code_object()); |
| 3954 __ lea(code_object, FieldOperand(code_object, Code::kHeaderSize)); | 3914 __ lea(code_object, FieldOperand(code_object, Code::kHeaderSize)); |
| 3955 __ movq(FieldOperand(function, JSFunction::kCodeEntryOffset), code_object); | 3915 __ movq(FieldOperand(function, JSFunction::kCodeEntryOffset), code_object); |
| 3956 } | 3916 } |
| 3957 | 3917 |
| 3958 | 3918 |
| 3959 void LCodeGen::DoInnerAllocatedObject(LInnerAllocatedObject* instr) { | 3919 void LCodeGen::DoInnerAllocatedObject(LInnerAllocatedObject* instr) { |
| 3960 Register result = ToRegister(instr->result()); | 3920 Register result = ToRegister(instr->result()); |
| 3961 Register base = ToRegister(instr->base_object()); | 3921 Register base = ToRegister(instr->base_object()); |
| 3962 __ lea(result, Operand(base, instr->offset())); | 3922 if (instr->offset()->IsConstantOperand()) { |
| 3923 LConstantOperand* offset = LConstantOperand::cast(instr->offset()); |
| 3924 __ lea(result, Operand(base, ToInteger32(offset))); |
| 3925 } else { |
| 3926 Register offset = ToRegister(instr->offset()); |
| 3927 __ lea(result, Operand(base, offset, times_1, 0)); |
| 3928 } |
| 3963 } | 3929 } |
| 3964 | 3930 |
| 3965 | 3931 |
| 3966 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { | 3932 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { |
| 3967 Representation representation = instr->representation(); | 3933 Representation representation = instr->representation(); |
| 3968 | 3934 |
| 3969 HObjectAccess access = instr->hydrogen()->access(); | 3935 HObjectAccess access = instr->hydrogen()->access(); |
| 3970 int offset = access.offset(); | 3936 int offset = access.offset(); |
| 3971 | 3937 |
| 3972 if (access.IsExternalMemory()) { | 3938 if (access.IsExternalMemory()) { |
| (...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4343 __ j(not_equal, ¬_applicable); | 4309 __ j(not_equal, ¬_applicable); |
| 4344 if (IsSimpleMapChangeTransition(from_kind, to_kind)) { | 4310 if (IsSimpleMapChangeTransition(from_kind, to_kind)) { |
| 4345 Register new_map_reg = ToRegister(instr->new_map_temp()); | 4311 Register new_map_reg = ToRegister(instr->new_map_temp()); |
| 4346 __ movq(new_map_reg, to_map, RelocInfo::EMBEDDED_OBJECT); | 4312 __ movq(new_map_reg, to_map, RelocInfo::EMBEDDED_OBJECT); |
| 4347 __ movq(FieldOperand(object_reg, HeapObject::kMapOffset), new_map_reg); | 4313 __ movq(FieldOperand(object_reg, HeapObject::kMapOffset), new_map_reg); |
| 4348 // Write barrier. | 4314 // Write barrier. |
| 4349 ASSERT_NE(instr->temp(), NULL); | 4315 ASSERT_NE(instr->temp(), NULL); |
| 4350 __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg, | 4316 __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg, |
| 4351 ToRegister(instr->temp()), kDontSaveFPRegs); | 4317 ToRegister(instr->temp()), kDontSaveFPRegs); |
| 4352 } else { | 4318 } else { |
| 4319 ASSERT(ToRegister(instr->context()).is(rsi)); |
| 4353 PushSafepointRegistersScope scope(this); | 4320 PushSafepointRegistersScope scope(this); |
| 4354 if (!object_reg.is(rax)) { | 4321 if (!object_reg.is(rax)) { |
| 4355 __ movq(rax, object_reg); | 4322 __ movq(rax, object_reg); |
| 4356 } | 4323 } |
| 4357 LoadContextFromDeferred(instr->context()); | |
| 4358 __ Move(rbx, to_map); | 4324 __ Move(rbx, to_map); |
| 4359 TransitionElementsKindStub stub(from_kind, to_kind); | 4325 TransitionElementsKindStub stub(from_kind, to_kind); |
| 4360 __ CallStub(&stub); | 4326 __ CallStub(&stub); |
| 4361 RecordSafepointWithRegisters( | 4327 RecordSafepointWithRegisters( |
| 4362 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); | 4328 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); |
| 4363 } | 4329 } |
| 4364 __ bind(¬_applicable); | 4330 __ bind(¬_applicable); |
| 4365 } | 4331 } |
| 4366 | 4332 |
| 4367 | 4333 |
| (...skipping 1258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5626 FixedArray::kHeaderSize - kPointerSize)); | 5592 FixedArray::kHeaderSize - kPointerSize)); |
| 5627 __ bind(&done); | 5593 __ bind(&done); |
| 5628 } | 5594 } |
| 5629 | 5595 |
| 5630 | 5596 |
| 5631 #undef __ | 5597 #undef __ |
| 5632 | 5598 |
| 5633 } } // namespace v8::internal | 5599 } } // namespace v8::internal |
| 5634 | 5600 |
| 5635 #endif // V8_TARGET_ARCH_X64 | 5601 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |