| 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 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 82 GenerateDeferredCode() && | 82 GenerateDeferredCode() && |
| 83 GenerateJumpTable() && | 83 GenerateJumpTable() && |
| 84 GenerateSafepointTable(); | 84 GenerateSafepointTable(); |
| 85 } | 85 } |
| 86 | 86 |
| 87 | 87 |
| 88 void LCodeGen::FinishCode(Handle<Code> code) { | 88 void LCodeGen::FinishCode(Handle<Code> code) { |
| 89 ASSERT(is_done()); | 89 ASSERT(is_done()); |
| 90 code->set_stack_slots(GetStackSlotCount()); | 90 code->set_stack_slots(GetStackSlotCount()); |
| 91 code->set_safepoint_table_offset(safepoints_.GetCodeOffset()); | 91 code->set_safepoint_table_offset(safepoints_.GetCodeOffset()); |
| 92 if (FLAG_weak_embedded_maps_in_optimized_code) { | 92 RegisterDependentCodeForEmbeddedMaps(code); |
| 93 RegisterDependentCodeForEmbeddedMaps(code); | |
| 94 } | |
| 95 PopulateDeoptimizationData(code); | 93 PopulateDeoptimizationData(code); |
| 96 info()->CommitDependencies(code); | 94 info()->CommitDependencies(code); |
| 97 } | 95 } |
| 98 | 96 |
| 99 | 97 |
| 100 void LChunkBuilder::Abort(BailoutReason reason) { | 98 void LChunkBuilder::Abort(BailoutReason reason) { |
| 101 info()->set_bailout_reason(reason); | 99 info()->set_bailout_reason(reason); |
| 102 status_ = ABORTED; | 100 status_ = ABORTED; |
| 103 } | 101 } |
| 104 | 102 |
| 105 | 103 |
| 106 void LCodeGen::Comment(const char* format, ...) { | |
| 107 if (!FLAG_code_comments) return; | |
| 108 char buffer[4 * KB]; | |
| 109 StringBuilder builder(buffer, ARRAY_SIZE(buffer)); | |
| 110 va_list arguments; | |
| 111 va_start(arguments, format); | |
| 112 builder.AddFormattedList(format, arguments); | |
| 113 va_end(arguments); | |
| 114 | |
| 115 // Copy the string before recording it in the assembler to avoid | |
| 116 // issues when the stack allocated buffer goes out of scope. | |
| 117 int length = builder.position(); | |
| 118 Vector<char> copy = Vector<char>::New(length + 1); | |
| 119 OS::MemCopy(copy.start(), builder.Finalize(), copy.length()); | |
| 120 masm()->RecordComment(copy.start()); | |
| 121 } | |
| 122 | |
| 123 | |
| 124 #ifdef _MSC_VER | 104 #ifdef _MSC_VER |
| 125 void LCodeGen::MakeSureStackPagesMapped(int offset) { | 105 void LCodeGen::MakeSureStackPagesMapped(int offset) { |
| 126 const int kPageSize = 4 * KB; | 106 const int kPageSize = 4 * KB; |
| 127 for (offset -= kPageSize; offset > 0; offset -= kPageSize) { | 107 for (offset -= kPageSize; offset > 0; offset -= kPageSize) { |
| 128 __ movq(Operand(rsp, offset), rax); | 108 __ movq(Operand(rsp, offset), rax); |
| 129 } | 109 } |
| 130 } | 110 } |
| 131 #endif | 111 #endif |
| 132 | 112 |
| 133 | 113 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 145 #endif | 125 #endif |
| 146 | 126 |
| 147 // Strict mode functions need to replace the receiver with undefined | 127 // Strict mode functions need to replace the receiver with undefined |
| 148 // when called as functions (without an explicit receiver | 128 // when called as functions (without an explicit receiver |
| 149 // object). rcx is zero for method calls and non-zero for function | 129 // object). rcx is zero for method calls and non-zero for function |
| 150 // calls. | 130 // calls. |
| 151 if (!info_->is_classic_mode() || info_->is_native()) { | 131 if (!info_->is_classic_mode() || info_->is_native()) { |
| 152 Label ok; | 132 Label ok; |
| 153 __ testq(rcx, rcx); | 133 __ testq(rcx, rcx); |
| 154 __ j(zero, &ok, Label::kNear); | 134 __ j(zero, &ok, Label::kNear); |
| 155 // +1 for return address. | 135 StackArgumentsAccessor args(rsp, scope()->num_parameters()); |
| 156 int receiver_offset = (scope()->num_parameters() + 1) * kPointerSize; | |
| 157 __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex); | 136 __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex); |
| 158 __ movq(Operand(rsp, receiver_offset), kScratchRegister); | 137 __ movq(args.GetReceiverOperand(), kScratchRegister); |
| 159 __ bind(&ok); | 138 __ bind(&ok); |
| 160 } | 139 } |
| 161 } | 140 } |
| 162 | 141 |
| 163 info()->set_prologue_offset(masm_->pc_offset()); | 142 info()->set_prologue_offset(masm_->pc_offset()); |
| 164 if (NeedsEagerFrame()) { | 143 if (NeedsEagerFrame()) { |
| 165 ASSERT(!frame_is_built_); | 144 ASSERT(!frame_is_built_); |
| 166 frame_is_built_ = true; | 145 frame_is_built_ = true; |
| 167 __ push(rbp); // Caller's frame pointer. | 146 __ push(rbp); // Caller's frame pointer. |
| 168 __ movq(rbp, rsp); | 147 __ movq(rbp, rsp); |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 266 osr_pc_offset_ = masm()->pc_offset(); | 245 osr_pc_offset_ = masm()->pc_offset(); |
| 267 | 246 |
| 268 // Adjust the frame size, subsuming the unoptimized frame into the | 247 // Adjust the frame size, subsuming the unoptimized frame into the |
| 269 // optimized frame. | 248 // optimized frame. |
| 270 int slots = GetStackSlotCount() - graph()->osr()->UnoptimizedFrameSlots(); | 249 int slots = GetStackSlotCount() - graph()->osr()->UnoptimizedFrameSlots(); |
| 271 ASSERT(slots >= 0); | 250 ASSERT(slots >= 0); |
| 272 __ subq(rsp, Immediate(slots * kPointerSize)); | 251 __ subq(rsp, Immediate(slots * kPointerSize)); |
| 273 } | 252 } |
| 274 | 253 |
| 275 | 254 |
| 276 bool LCodeGen::GenerateBody() { | |
| 277 ASSERT(is_generating()); | |
| 278 bool emit_instructions = true; | |
| 279 for (current_instruction_ = 0; | |
| 280 !is_aborted() && current_instruction_ < instructions_->length(); | |
| 281 current_instruction_++) { | |
| 282 LInstruction* instr = instructions_->at(current_instruction_); | |
| 283 | |
| 284 // Don't emit code for basic blocks with a replacement. | |
| 285 if (instr->IsLabel()) { | |
| 286 emit_instructions = !LLabel::cast(instr)->HasReplacement(); | |
| 287 } | |
| 288 if (!emit_instructions) continue; | |
| 289 | |
| 290 if (FLAG_code_comments && instr->HasInterestingComment(this)) { | |
| 291 Comment(";;; <@%d,#%d> %s", | |
| 292 current_instruction_, | |
| 293 instr->hydrogen_value()->id(), | |
| 294 instr->Mnemonic()); | |
| 295 } | |
| 296 | |
| 297 RecordAndUpdatePosition(instr->position()); | |
| 298 | |
| 299 instr->CompileToNative(this); | |
| 300 } | |
| 301 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); | |
| 302 return !is_aborted(); | |
| 303 } | |
| 304 | |
| 305 | |
| 306 bool LCodeGen::GenerateJumpTable() { | 255 bool LCodeGen::GenerateJumpTable() { |
| 307 Label needs_frame; | 256 Label needs_frame; |
| 308 if (jump_table_.length() > 0) { | 257 if (jump_table_.length() > 0) { |
| 309 Comment(";;; -------------------- Jump table --------------------"); | 258 Comment(";;; -------------------- Jump table --------------------"); |
| 310 } | 259 } |
| 311 for (int i = 0; i < jump_table_.length(); i++) { | 260 for (int i = 0; i < jump_table_.length(); i++) { |
| 312 __ bind(&jump_table_[i].label); | 261 __ bind(&jump_table_[i].label); |
| 313 Address entry = jump_table_[i].address; | 262 Address entry = jump_table_[i].address; |
| 314 Deoptimizer::BailoutType type = jump_table_[i].bailout_type; | 263 Deoptimizer::BailoutType type = jump_table_[i].bailout_type; |
| 315 int id = Deoptimizer::GetDeoptimizationId(isolate(), entry, type); | 264 int id = Deoptimizer::GetDeoptimizationId(isolate(), entry, type); |
| (...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 630 | 579 |
| 631 void LCodeGen::CallCode(Handle<Code> code, | 580 void LCodeGen::CallCode(Handle<Code> code, |
| 632 RelocInfo::Mode mode, | 581 RelocInfo::Mode mode, |
| 633 LInstruction* instr) { | 582 LInstruction* instr) { |
| 634 CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT, 0); | 583 CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT, 0); |
| 635 } | 584 } |
| 636 | 585 |
| 637 | 586 |
| 638 void LCodeGen::CallRuntime(const Runtime::Function* function, | 587 void LCodeGen::CallRuntime(const Runtime::Function* function, |
| 639 int num_arguments, | 588 int num_arguments, |
| 640 LInstruction* instr) { | 589 LInstruction* instr, |
| 590 SaveFPRegsMode save_doubles) { |
| 641 ASSERT(instr != NULL); | 591 ASSERT(instr != NULL); |
| 642 ASSERT(instr->HasPointerMap()); | 592 ASSERT(instr->HasPointerMap()); |
| 643 LPointerMap* pointers = instr->pointer_map(); | 593 LPointerMap* pointers = instr->pointer_map(); |
| 644 RecordPosition(pointers->position()); | 594 RecordPosition(pointers->position()); |
| 645 | 595 |
| 646 __ CallRuntime(function, num_arguments); | 596 __ CallRuntime(function, num_arguments, save_doubles); |
| 597 |
| 647 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT, 0); | 598 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT, 0); |
| 648 } | 599 } |
| 649 | 600 |
| 650 | 601 |
| 651 void LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id, | 602 void LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id, |
| 652 int argc, | 603 int argc, |
| 653 LInstruction* instr) { | 604 LInstruction* instr) { |
| 654 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 605 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| 655 __ CallRuntimeSaveDoubles(id); | 606 __ CallRuntimeSaveDoubles(id); |
| 656 RecordSafepointWithRegisters( | 607 RecordSafepointWithRegisters( |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 747 LEnvironment* environment) { | 698 LEnvironment* environment) { |
| 748 Deoptimizer::BailoutType bailout_type = info()->IsStub() | 699 Deoptimizer::BailoutType bailout_type = info()->IsStub() |
| 749 ? Deoptimizer::LAZY | 700 ? Deoptimizer::LAZY |
| 750 : Deoptimizer::EAGER; | 701 : Deoptimizer::EAGER; |
| 751 DeoptimizeIf(cc, environment, bailout_type); | 702 DeoptimizeIf(cc, environment, bailout_type); |
| 752 } | 703 } |
| 753 | 704 |
| 754 | 705 |
| 755 void LCodeGen::RegisterDependentCodeForEmbeddedMaps(Handle<Code> code) { | 706 void LCodeGen::RegisterDependentCodeForEmbeddedMaps(Handle<Code> code) { |
| 756 ZoneList<Handle<Map> > maps(1, zone()); | 707 ZoneList<Handle<Map> > maps(1, zone()); |
| 708 ZoneList<Handle<JSObject> > objects(1, zone()); |
| 757 int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); | 709 int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT); |
| 758 for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) { | 710 for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) { |
| 759 RelocInfo::Mode mode = it.rinfo()->rmode(); | 711 if (Code::IsWeakEmbeddedObject(code->kind(), it.rinfo()->target_object())) { |
| 760 if (mode == RelocInfo::EMBEDDED_OBJECT && | 712 if (it.rinfo()->target_object()->IsMap()) { |
| 761 it.rinfo()->target_object()->IsMap()) { | 713 Handle<Map> map(Map::cast(it.rinfo()->target_object())); |
| 762 Handle<Map> map(Map::cast(it.rinfo()->target_object())); | |
| 763 if (map->CanTransition()) { | |
| 764 maps.Add(map, zone()); | 714 maps.Add(map, zone()); |
| 715 } else if (it.rinfo()->target_object()->IsJSObject()) { |
| 716 Handle<JSObject> object(JSObject::cast(it.rinfo()->target_object())); |
| 717 objects.Add(object, zone()); |
| 765 } | 718 } |
| 766 } | 719 } |
| 767 } | 720 } |
| 768 #ifdef VERIFY_HEAP | 721 #ifdef VERIFY_HEAP |
| 769 // This disables verification of weak embedded maps after full GC. | 722 // This disables verification of weak embedded objects after full GC. |
| 770 // AddDependentCode can cause a GC, which would observe the state where | 723 // AddDependentCode can cause a GC, which would observe the state where |
| 771 // this code is not yet in the depended code lists of the embedded maps. | 724 // this code is not yet in the depended code lists of the embedded maps. |
| 772 NoWeakEmbeddedMapsVerificationScope disable_verification_of_embedded_maps; | 725 NoWeakObjectVerificationScope disable_verification_of_embedded_objects; |
| 773 #endif | 726 #endif |
| 774 for (int i = 0; i < maps.length(); i++) { | 727 for (int i = 0; i < maps.length(); i++) { |
| 775 maps.at(i)->AddDependentCode(DependentCode::kWeaklyEmbeddedGroup, code); | 728 maps.at(i)->AddDependentCode(DependentCode::kWeaklyEmbeddedGroup, code); |
| 776 } | 729 } |
| 730 for (int i = 0; i < objects.length(); i++) { |
| 731 AddWeakObjectToCodeDependency(isolate()->heap(), objects.at(i), code); |
| 732 } |
| 777 } | 733 } |
| 778 | 734 |
| 779 | 735 |
| 780 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { | 736 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { |
| 781 int length = deoptimizations_.length(); | 737 int length = deoptimizations_.length(); |
| 782 if (length == 0) return; | 738 if (length == 0) return; |
| 783 Handle<DeoptimizationInputData> data = | 739 Handle<DeoptimizationInputData> data = |
| 784 factory()->NewDeoptimizationInputData(length, TENURED); | 740 factory()->NewDeoptimizationInputData(length, TENURED); |
| 785 | 741 |
| 786 Handle<ByteArray> translations = | 742 Handle<ByteArray> translations = |
| (...skipping 1108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1895 ASSERT(ToRegister(instr->left()).is(rdx)); | 1851 ASSERT(ToRegister(instr->left()).is(rdx)); |
| 1896 ASSERT(ToRegister(instr->right()).is(rax)); | 1852 ASSERT(ToRegister(instr->right()).is(rax)); |
| 1897 ASSERT(ToRegister(instr->result()).is(rax)); | 1853 ASSERT(ToRegister(instr->result()).is(rax)); |
| 1898 | 1854 |
| 1899 BinaryOpStub stub(instr->op(), NO_OVERWRITE); | 1855 BinaryOpStub stub(instr->op(), NO_OVERWRITE); |
| 1900 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 1856 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 1901 __ nop(); // Signals no inlined code. | 1857 __ nop(); // Signals no inlined code. |
| 1902 } | 1858 } |
| 1903 | 1859 |
| 1904 | 1860 |
| 1905 int LCodeGen::GetNextEmittedBlock() const { | |
| 1906 for (int i = current_block_ + 1; i < graph()->blocks()->length(); ++i) { | |
| 1907 if (!chunk_->GetLabel(i)->HasReplacement()) return i; | |
| 1908 } | |
| 1909 return -1; | |
| 1910 } | |
| 1911 | |
| 1912 | |
| 1913 template<class InstrType> | 1861 template<class InstrType> |
| 1914 void LCodeGen::EmitBranch(InstrType instr, Condition cc) { | 1862 void LCodeGen::EmitBranch(InstrType instr, Condition cc) { |
| 1915 int left_block = instr->TrueDestination(chunk_); | 1863 int left_block = instr->TrueDestination(chunk_); |
| 1916 int right_block = instr->FalseDestination(chunk_); | 1864 int right_block = instr->FalseDestination(chunk_); |
| 1917 | 1865 |
| 1918 int next_block = GetNextEmittedBlock(); | 1866 int next_block = GetNextEmittedBlock(); |
| 1919 | 1867 |
| 1920 if (right_block == left_block || cc == no_condition) { | 1868 if (right_block == left_block || cc == no_condition) { |
| 1921 EmitGoto(left_block); | 1869 EmitGoto(left_block); |
| 1922 } else if (left_block == next_block) { | 1870 } else if (left_block == next_block) { |
| (...skipping 850 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2773 | 2721 |
| 2774 __ bind(&skip_assignment); | 2722 __ bind(&skip_assignment); |
| 2775 } | 2723 } |
| 2776 | 2724 |
| 2777 | 2725 |
| 2778 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { | 2726 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { |
| 2779 HObjectAccess access = instr->hydrogen()->access(); | 2727 HObjectAccess access = instr->hydrogen()->access(); |
| 2780 int offset = access.offset(); | 2728 int offset = access.offset(); |
| 2781 | 2729 |
| 2782 if (access.IsExternalMemory()) { | 2730 if (access.IsExternalMemory()) { |
| 2783 ASSERT(!access.representation().IsInteger32()); | |
| 2784 Register result = ToRegister(instr->result()); | 2731 Register result = ToRegister(instr->result()); |
| 2785 if (instr->object()->IsConstantOperand()) { | 2732 if (instr->object()->IsConstantOperand()) { |
| 2786 ASSERT(result.is(rax)); | 2733 ASSERT(result.is(rax)); |
| 2787 __ load_rax(ToExternalReference(LConstantOperand::cast(instr->object()))); | 2734 __ load_rax(ToExternalReference(LConstantOperand::cast(instr->object()))); |
| 2788 } else { | 2735 } else { |
| 2789 Register object = ToRegister(instr->object()); | 2736 Register object = ToRegister(instr->object()); |
| 2790 __ movq(result, MemOperand(object, offset)); | 2737 __ Load(result, MemOperand(object, offset), access.representation()); |
| 2791 } | 2738 } |
| 2792 return; | 2739 return; |
| 2793 } | 2740 } |
| 2794 | 2741 |
| 2795 Register object = ToRegister(instr->object()); | 2742 Register object = ToRegister(instr->object()); |
| 2796 if (FLAG_track_double_fields && | 2743 if (FLAG_track_double_fields && |
| 2797 instr->hydrogen()->representation().IsDouble()) { | 2744 instr->hydrogen()->representation().IsDouble()) { |
| 2798 XMMRegister result = ToDoubleRegister(instr->result()); | 2745 XMMRegister result = ToDoubleRegister(instr->result()); |
| 2799 __ movsd(result, FieldOperand(object, offset)); | 2746 __ movsd(result, FieldOperand(object, offset)); |
| 2800 return; | 2747 return; |
| 2801 } | 2748 } |
| 2802 | 2749 |
| 2803 Register result = ToRegister(instr->result()); | 2750 Register result = ToRegister(instr->result()); |
| 2804 if (access.IsInobject()) { | 2751 if (!access.IsInobject()) { |
| 2805 if (access.representation().IsInteger32()) { | |
| 2806 __ movl(result, FieldOperand(object, offset)); | |
| 2807 } else { | |
| 2808 __ movq(result, FieldOperand(object, offset)); | |
| 2809 } | |
| 2810 } else { | |
| 2811 __ movq(result, FieldOperand(object, JSObject::kPropertiesOffset)); | 2752 __ movq(result, FieldOperand(object, JSObject::kPropertiesOffset)); |
| 2812 if (access.representation().IsInteger32()) { | 2753 object = result; |
| 2813 __ movl(result, FieldOperand(result, offset)); | |
| 2814 } else { | |
| 2815 __ movq(result, FieldOperand(result, offset)); | |
| 2816 } | |
| 2817 } | 2754 } |
| 2755 __ Load(result, FieldOperand(object, offset), access.representation()); |
| 2818 } | 2756 } |
| 2819 | 2757 |
| 2820 | 2758 |
| 2821 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { | 2759 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { |
| 2822 ASSERT(ToRegister(instr->object()).is(rax)); | 2760 ASSERT(ToRegister(instr->object()).is(rax)); |
| 2823 ASSERT(ToRegister(instr->result()).is(rax)); | 2761 ASSERT(ToRegister(instr->result()).is(rax)); |
| 2824 | 2762 |
| 2825 __ Move(rcx, instr->name()); | 2763 __ Move(rcx, instr->name()); |
| 2826 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 2764 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
| 2827 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2765 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2885 | 2823 |
| 2886 | 2824 |
| 2887 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { | 2825 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { |
| 2888 Register arguments = ToRegister(instr->arguments()); | 2826 Register arguments = ToRegister(instr->arguments()); |
| 2889 Register result = ToRegister(instr->result()); | 2827 Register result = ToRegister(instr->result()); |
| 2890 | 2828 |
| 2891 if (instr->length()->IsConstantOperand() && | 2829 if (instr->length()->IsConstantOperand() && |
| 2892 instr->index()->IsConstantOperand()) { | 2830 instr->index()->IsConstantOperand()) { |
| 2893 int32_t const_index = ToInteger32(LConstantOperand::cast(instr->index())); | 2831 int32_t const_index = ToInteger32(LConstantOperand::cast(instr->index())); |
| 2894 int32_t const_length = ToInteger32(LConstantOperand::cast(instr->length())); | 2832 int32_t const_length = ToInteger32(LConstantOperand::cast(instr->length())); |
| 2895 int index = (const_length - const_index) + 1; | 2833 StackArgumentsAccessor args(arguments, const_length, |
| 2896 __ movq(result, Operand(arguments, index * kPointerSize)); | 2834 ARGUMENTS_DONT_CONTAIN_RECEIVER); |
| 2835 __ movq(result, args.GetArgumentOperand(const_index)); |
| 2897 } else { | 2836 } else { |
| 2898 Register length = ToRegister(instr->length()); | 2837 Register length = ToRegister(instr->length()); |
| 2899 // There are two words between the frame pointer and the last argument. | 2838 // There are two words between the frame pointer and the last argument. |
| 2900 // Subtracting from length accounts for one of them add one more. | 2839 // Subtracting from length accounts for one of them add one more. |
| 2901 if (instr->index()->IsRegister()) { | 2840 if (instr->index()->IsRegister()) { |
| 2902 __ subl(length, ToRegister(instr->index())); | 2841 __ subl(length, ToRegister(instr->index())); |
| 2903 } else { | 2842 } else { |
| 2904 __ subl(length, ToOperand(instr->index())); | 2843 __ subl(length, ToOperand(instr->index())); |
| 2905 } | 2844 } |
| 2906 __ movq(result, | 2845 StackArgumentsAccessor args(arguments, length, |
| 2907 Operand(arguments, length, times_pointer_size, kPointerSize)); | 2846 ARGUMENTS_DONT_CONTAIN_RECEIVER); |
| 2847 __ movq(result, args.GetArgumentOperand(0)); |
| 2908 } | 2848 } |
| 2909 } | 2849 } |
| 2910 | 2850 |
| 2911 | 2851 |
| 2912 void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) { | 2852 void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) { |
| 2913 ElementsKind elements_kind = instr->elements_kind(); | 2853 ElementsKind elements_kind = instr->elements_kind(); |
| 2914 LOperand* key = instr->key(); | 2854 LOperand* key = instr->key(); |
| 2915 if (!key->IsConstantOperand()) { | 2855 if (!key->IsConstantOperand()) { |
| 2916 Register key_reg = ToRegister(key); | 2856 Register key_reg = ToRegister(key); |
| 2917 // Even though the HLoad/StoreKeyed (in this case) instructions force | 2857 // Even though the HLoad/StoreKeyed (in this case) instructions force |
| (...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3101 | 3041 |
| 3102 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 3042 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
| 3103 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 3043 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 3104 } | 3044 } |
| 3105 | 3045 |
| 3106 | 3046 |
| 3107 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { | 3047 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { |
| 3108 Register result = ToRegister(instr->result()); | 3048 Register result = ToRegister(instr->result()); |
| 3109 | 3049 |
| 3110 if (instr->hydrogen()->from_inlined()) { | 3050 if (instr->hydrogen()->from_inlined()) { |
| 3111 __ lea(result, Operand(rsp, -2 * kPointerSize)); | 3051 __ lea(result, Operand(rsp, -kFPOnStackSize + -kPCOnStackSize)); |
| 3112 } else { | 3052 } else { |
| 3113 // Check for arguments adapter frame. | 3053 // Check for arguments adapter frame. |
| 3114 Label done, adapted; | 3054 Label done, adapted; |
| 3115 __ movq(result, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); | 3055 __ movq(result, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); |
| 3116 __ Cmp(Operand(result, StandardFrameConstants::kContextOffset), | 3056 __ Cmp(Operand(result, StandardFrameConstants::kContextOffset), |
| 3117 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); | 3057 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); |
| 3118 __ j(equal, &adapted, Label::kNear); | 3058 __ j(equal, &adapted, Label::kNear); |
| 3119 | 3059 |
| 3120 // No arguments adaptor frame. | 3060 // No arguments adaptor frame. |
| 3121 __ movq(result, rbp); | 3061 __ movq(result, rbp); |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3223 __ push(receiver); | 3163 __ push(receiver); |
| 3224 __ movq(receiver, length); | 3164 __ movq(receiver, length); |
| 3225 | 3165 |
| 3226 // Loop through the arguments pushing them onto the execution | 3166 // Loop through the arguments pushing them onto the execution |
| 3227 // stack. | 3167 // stack. |
| 3228 Label invoke, loop; | 3168 Label invoke, loop; |
| 3229 // length is a small non-negative integer, due to the test above. | 3169 // length is a small non-negative integer, due to the test above. |
| 3230 __ testl(length, length); | 3170 __ testl(length, length); |
| 3231 __ j(zero, &invoke, Label::kNear); | 3171 __ j(zero, &invoke, Label::kNear); |
| 3232 __ bind(&loop); | 3172 __ bind(&loop); |
| 3233 __ push(Operand(elements, length, times_pointer_size, 1 * kPointerSize)); | 3173 StackArgumentsAccessor args(elements, length, |
| 3174 ARGUMENTS_DONT_CONTAIN_RECEIVER); |
| 3175 __ push(args.GetArgumentOperand(0)); |
| 3234 __ decl(length); | 3176 __ decl(length); |
| 3235 __ j(not_zero, &loop); | 3177 __ j(not_zero, &loop); |
| 3236 | 3178 |
| 3237 // Invoke the function. | 3179 // Invoke the function. |
| 3238 __ bind(&invoke); | 3180 __ bind(&invoke); |
| 3239 ASSERT(instr->HasPointerMap()); | 3181 ASSERT(instr->HasPointerMap()); |
| 3240 LPointerMap* pointers = instr->pointer_map(); | 3182 LPointerMap* pointers = instr->pointer_map(); |
| 3241 RecordPosition(pointers->position()); | 3183 RecordPosition(pointers->position()); |
| 3242 SafepointGenerator safepoint_generator( | 3184 SafepointGenerator safepoint_generator( |
| 3243 this, pointers, Safepoint::kLazyDeopt); | 3185 this, pointers, Safepoint::kLazyDeopt); |
| (...skipping 655 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3899 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); | 3841 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); |
| 3900 __ bind(&done); | 3842 __ bind(&done); |
| 3901 } else { | 3843 } else { |
| 3902 ArrayNArgumentsConstructorStub stub(kind, context_mode, override_mode); | 3844 ArrayNArgumentsConstructorStub stub(kind, context_mode, override_mode); |
| 3903 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); | 3845 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); |
| 3904 } | 3846 } |
| 3905 } | 3847 } |
| 3906 | 3848 |
| 3907 | 3849 |
| 3908 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { | 3850 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { |
| 3909 CallRuntime(instr->function(), instr->arity(), instr); | 3851 CallRuntime(instr->function(), instr->arity(), instr, instr->save_doubles()); |
| 3910 } | 3852 } |
| 3911 | 3853 |
| 3912 | 3854 |
| 3913 void LCodeGen::DoStoreCodeEntry(LStoreCodeEntry* instr) { | 3855 void LCodeGen::DoStoreCodeEntry(LStoreCodeEntry* instr) { |
| 3914 Register function = ToRegister(instr->function()); | 3856 Register function = ToRegister(instr->function()); |
| 3915 Register code_object = ToRegister(instr->code_object()); | 3857 Register code_object = ToRegister(instr->code_object()); |
| 3916 __ lea(code_object, FieldOperand(code_object, Code::kHeaderSize)); | 3858 __ lea(code_object, FieldOperand(code_object, Code::kHeaderSize)); |
| 3917 __ movq(FieldOperand(function, JSFunction::kCodeEntryOffset), code_object); | 3859 __ movq(FieldOperand(function, JSFunction::kCodeEntryOffset), code_object); |
| 3918 } | 3860 } |
| 3919 | 3861 |
| 3920 | 3862 |
| 3921 void LCodeGen::DoInnerAllocatedObject(LInnerAllocatedObject* instr) { | 3863 void LCodeGen::DoInnerAllocatedObject(LInnerAllocatedObject* instr) { |
| 3922 Register result = ToRegister(instr->result()); | 3864 Register result = ToRegister(instr->result()); |
| 3923 Register base = ToRegister(instr->base_object()); | 3865 Register base = ToRegister(instr->base_object()); |
| 3924 __ lea(result, Operand(base, instr->offset())); | 3866 __ lea(result, Operand(base, instr->offset())); |
| 3925 } | 3867 } |
| 3926 | 3868 |
| 3927 | 3869 |
| 3928 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { | 3870 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { |
| 3929 Representation representation = instr->representation(); | 3871 Representation representation = instr->representation(); |
| 3930 | 3872 |
| 3931 HObjectAccess access = instr->hydrogen()->access(); | 3873 HObjectAccess access = instr->hydrogen()->access(); |
| 3932 int offset = access.offset(); | 3874 int offset = access.offset(); |
| 3933 | 3875 |
| 3934 if (access.IsExternalMemory()) { | 3876 if (access.IsExternalMemory()) { |
| 3935 ASSERT(!access.representation().IsInteger32()); | |
| 3936 ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); | 3877 ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); |
| 3937 Register value = ToRegister(instr->value()); | 3878 Register value = ToRegister(instr->value()); |
| 3938 if (instr->object()->IsConstantOperand()) { | 3879 if (instr->object()->IsConstantOperand()) { |
| 3939 ASSERT(value.is(rax)); | 3880 ASSERT(value.is(rax)); |
| 3881 ASSERT(!access.representation().IsSpecialization()); |
| 3940 LConstantOperand* object = LConstantOperand::cast(instr->object()); | 3882 LConstantOperand* object = LConstantOperand::cast(instr->object()); |
| 3941 __ store_rax(ToExternalReference(object)); | 3883 __ store_rax(ToExternalReference(object)); |
| 3942 } else { | 3884 } else { |
| 3943 Register object = ToRegister(instr->object()); | 3885 Register object = ToRegister(instr->object()); |
| 3944 __ movq(MemOperand(object, offset), value); | 3886 __ Store(MemOperand(object, offset), value, representation); |
| 3945 } | 3887 } |
| 3946 return; | 3888 return; |
| 3947 } | 3889 } |
| 3948 | 3890 |
| 3949 Register object = ToRegister(instr->object()); | 3891 Register object = ToRegister(instr->object()); |
| 3950 Handle<Map> transition = instr->transition(); | 3892 Handle<Map> transition = instr->transition(); |
| 3951 | 3893 |
| 3952 if (FLAG_track_fields && representation.IsSmi()) { | 3894 if (FLAG_track_fields && representation.IsSmi()) { |
| 3953 if (instr->value()->IsConstantOperand()) { | 3895 if (instr->value()->IsConstantOperand()) { |
| 3954 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); | 3896 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4003 | 3945 |
| 4004 Register write_register = object; | 3946 Register write_register = object; |
| 4005 if (!access.IsInobject()) { | 3947 if (!access.IsInobject()) { |
| 4006 write_register = ToRegister(instr->temp()); | 3948 write_register = ToRegister(instr->temp()); |
| 4007 __ movq(write_register, FieldOperand(object, JSObject::kPropertiesOffset)); | 3949 __ movq(write_register, FieldOperand(object, JSObject::kPropertiesOffset)); |
| 4008 } | 3950 } |
| 4009 | 3951 |
| 4010 if (instr->value()->IsConstantOperand()) { | 3952 if (instr->value()->IsConstantOperand()) { |
| 4011 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); | 3953 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); |
| 4012 if (operand_value->IsRegister()) { | 3954 if (operand_value->IsRegister()) { |
| 4013 if (access.representation().IsInteger32()) { | 3955 Register value = ToRegister(operand_value); |
| 4014 __ movl(FieldOperand(write_register, offset), | 3956 __ Store(FieldOperand(write_register, offset), value, representation); |
| 4015 ToRegister(operand_value)); | |
| 4016 } else { | |
| 4017 __ movq(FieldOperand(write_register, offset), | |
| 4018 ToRegister(operand_value)); | |
| 4019 } | |
| 4020 } else { | 3957 } else { |
| 4021 Handle<Object> handle_value = ToHandle(operand_value); | 3958 Handle<Object> handle_value = ToHandle(operand_value); |
| 4022 ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); | 3959 ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); |
| 4023 __ Move(FieldOperand(write_register, offset), handle_value); | 3960 __ Move(FieldOperand(write_register, offset), handle_value); |
| 4024 } | 3961 } |
| 4025 } else { | 3962 } else { |
| 4026 if (access.representation().IsInteger32()) { | 3963 Register value = ToRegister(instr->value()); |
| 4027 __ movl(FieldOperand(write_register, offset), ToRegister(instr->value())); | 3964 __ Store(FieldOperand(write_register, offset), value, representation); |
| 4028 } else { | |
| 4029 __ movq(FieldOperand(write_register, offset), ToRegister(instr->value())); | |
| 4030 } | |
| 4031 } | 3965 } |
| 4032 | 3966 |
| 4033 if (instr->hydrogen()->NeedsWriteBarrier()) { | 3967 if (instr->hydrogen()->NeedsWriteBarrier()) { |
| 4034 Register value = ToRegister(instr->value()); | 3968 Register value = ToRegister(instr->value()); |
| 4035 Register temp = access.IsInobject() ? ToRegister(instr->temp()) : object; | 3969 Register temp = access.IsInobject() ? ToRegister(instr->temp()) : object; |
| 4036 // Update the write barrier for the object for in-object properties. | 3970 // Update the write barrier for the object for in-object properties. |
| 4037 __ RecordWriteField(write_register, | 3971 __ RecordWriteField(write_register, |
| 4038 offset, | 3972 offset, |
| 4039 value, | 3973 value, |
| 4040 temp, | 3974 temp, |
| (...skipping 1471 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5512 FixedArray::kHeaderSize - kPointerSize)); | 5446 FixedArray::kHeaderSize - kPointerSize)); |
| 5513 __ bind(&done); | 5447 __ bind(&done); |
| 5514 } | 5448 } |
| 5515 | 5449 |
| 5516 | 5450 |
| 5517 #undef __ | 5451 #undef __ |
| 5518 | 5452 |
| 5519 } } // namespace v8::internal | 5453 } } // namespace v8::internal |
| 5520 | 5454 |
| 5521 #endif // V8_TARGET_ARCH_X64 | 5455 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |