| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 696 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 707 case CodeStub::RegExpExec: { | 707 case CodeStub::RegExpExec: { |
| 708 RegExpExecStub stub; | 708 RegExpExecStub stub; |
| 709 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 709 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 710 break; | 710 break; |
| 711 } | 711 } |
| 712 case CodeStub::SubString: { | 712 case CodeStub::SubString: { |
| 713 SubStringStub stub; | 713 SubStringStub stub; |
| 714 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 714 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 715 break; | 715 break; |
| 716 } | 716 } |
| 717 case CodeStub::StringCharAt: { | |
| 718 StringCharAtStub stub; | |
| 719 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | |
| 720 break; | |
| 721 } | |
| 722 case CodeStub::NumberToString: { | 717 case CodeStub::NumberToString: { |
| 723 NumberToStringStub stub; | 718 NumberToStringStub stub; |
| 724 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 719 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 725 break; | 720 break; |
| 726 } | 721 } |
| 727 case CodeStub::StringAdd: { | 722 case CodeStub::StringAdd: { |
| 728 StringAddStub stub(NO_STRING_ADD_FLAGS); | 723 StringAddStub stub(NO_STRING_ADD_FLAGS); |
| 729 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 724 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 730 break; | 725 break; |
| 731 } | 726 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 745 } | 740 } |
| 746 } | 741 } |
| 747 | 742 |
| 748 | 743 |
| 749 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { | 744 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { |
| 750 // Nothing to do. | 745 // Nothing to do. |
| 751 } | 746 } |
| 752 | 747 |
| 753 | 748 |
| 754 void LCodeGen::DoModI(LModI* instr) { | 749 void LCodeGen::DoModI(LModI* instr) { |
| 755 LOperand* right = instr->InputAt(1); | 750 if (instr->hydrogen()->HasPowerOf2Divisor()) { |
| 756 ASSERT(ToRegister(instr->result()).is(rdx)); | 751 Register dividend = ToRegister(instr->InputAt(0)); |
| 757 ASSERT(ToRegister(instr->InputAt(0)).is(rax)); | |
| 758 ASSERT(!ToRegister(instr->InputAt(1)).is(rax)); | |
| 759 ASSERT(!ToRegister(instr->InputAt(1)).is(rdx)); | |
| 760 | 752 |
| 761 Register right_reg = ToRegister(right); | 753 int32_t divisor = |
| 754 HConstant::cast(instr->hydrogen()->right())->Integer32Value(); |
| 762 | 755 |
| 763 // Check for x % 0. | 756 if (divisor < 0) divisor = -divisor; |
| 764 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { | |
| 765 __ testl(right_reg, right_reg); | |
| 766 DeoptimizeIf(zero, instr->environment()); | |
| 767 } | |
| 768 | 757 |
| 769 // Sign extend eax to edx. (We are using only the low 32 bits of the values.) | 758 NearLabel positive_dividend, done; |
| 770 __ cdq(); | 759 __ testl(dividend, dividend); |
| 771 | 760 __ j(not_sign, &positive_dividend); |
| 772 // Check for (0 % -x) that will produce negative zero. | 761 __ negl(dividend); |
| 773 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 762 __ andl(dividend, Immediate(divisor - 1)); |
| 774 NearLabel positive_left; | 763 __ negl(dividend); |
| 775 NearLabel done; | 764 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 776 __ testl(rax, rax); | 765 __ j(not_zero, &done); |
| 777 __ j(not_sign, &positive_left); | 766 DeoptimizeIf(no_condition, instr->environment()); |
| 778 __ idivl(right_reg); | 767 } |
| 779 | 768 __ bind(&positive_dividend); |
| 780 // Test the remainder for 0, because then the result would be -0. | 769 __ andl(dividend, Immediate(divisor - 1)); |
| 781 __ testl(rdx, rdx); | |
| 782 __ j(not_zero, &done); | |
| 783 | |
| 784 DeoptimizeIf(no_condition, instr->environment()); | |
| 785 __ bind(&positive_left); | |
| 786 __ idivl(right_reg); | |
| 787 __ bind(&done); | 770 __ bind(&done); |
| 788 } else { | 771 } else { |
| 789 __ idivl(right_reg); | 772 LOperand* right = instr->InputAt(1); |
| 773 Register right_reg = ToRegister(right); |
| 774 |
| 775 ASSERT(ToRegister(instr->result()).is(rdx)); |
| 776 ASSERT(ToRegister(instr->InputAt(0)).is(rax)); |
| 777 ASSERT(!right_reg.is(rax)); |
| 778 ASSERT(!right_reg.is(rdx)); |
| 779 |
| 780 // Check for x % 0. |
| 781 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { |
| 782 __ testl(right_reg, right_reg); |
| 783 DeoptimizeIf(zero, instr->environment()); |
| 784 } |
| 785 |
| 786 // Sign extend eax to edx. |
| 787 // (We are using only the low 32 bits of the values.) |
| 788 __ cdq(); |
| 789 |
| 790 // Check for (0 % -x) that will produce negative zero. |
| 791 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 792 NearLabel positive_left; |
| 793 NearLabel done; |
| 794 __ testl(rax, rax); |
| 795 __ j(not_sign, &positive_left); |
| 796 __ idivl(right_reg); |
| 797 |
| 798 // Test the remainder for 0, because then the result would be -0. |
| 799 __ testl(rdx, rdx); |
| 800 __ j(not_zero, &done); |
| 801 |
| 802 DeoptimizeIf(no_condition, instr->environment()); |
| 803 __ bind(&positive_left); |
| 804 __ idivl(right_reg); |
| 805 __ bind(&done); |
| 806 } else { |
| 807 __ idivl(right_reg); |
| 808 } |
| 790 } | 809 } |
| 791 } | 810 } |
| 792 | 811 |
| 793 | 812 |
| 794 void LCodeGen::DoDivI(LDivI* instr) { | 813 void LCodeGen::DoDivI(LDivI* instr) { |
| 795 LOperand* right = instr->InputAt(1); | 814 LOperand* right = instr->InputAt(1); |
| 796 ASSERT(ToRegister(instr->result()).is(rax)); | 815 ASSERT(ToRegister(instr->result()).is(rax)); |
| 797 ASSERT(ToRegister(instr->InputAt(0)).is(rax)); | 816 ASSERT(ToRegister(instr->InputAt(0)).is(rax)); |
| 798 ASSERT(!ToRegister(instr->InputAt(1)).is(rax)); | 817 ASSERT(!ToRegister(instr->InputAt(1)).is(rax)); |
| 799 ASSERT(!ToRegister(instr->InputAt(1)).is(rdx)); | 818 ASSERT(!ToRegister(instr->InputAt(1)).is(rdx)); |
| (...skipping 418 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1218 } else { | 1237 } else { |
| 1219 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 1238 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
| 1220 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1239 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
| 1221 | 1240 |
| 1222 __ CompareRoot(reg, Heap::kUndefinedValueRootIndex); | 1241 __ CompareRoot(reg, Heap::kUndefinedValueRootIndex); |
| 1223 __ j(equal, false_label); | 1242 __ j(equal, false_label); |
| 1224 __ CompareRoot(reg, Heap::kTrueValueRootIndex); | 1243 __ CompareRoot(reg, Heap::kTrueValueRootIndex); |
| 1225 __ j(equal, true_label); | 1244 __ j(equal, true_label); |
| 1226 __ CompareRoot(reg, Heap::kFalseValueRootIndex); | 1245 __ CompareRoot(reg, Heap::kFalseValueRootIndex); |
| 1227 __ j(equal, false_label); | 1246 __ j(equal, false_label); |
| 1228 __ SmiCompare(reg, Smi::FromInt(0)); | 1247 __ Cmp(reg, Smi::FromInt(0)); |
| 1229 __ j(equal, false_label); | 1248 __ j(equal, false_label); |
| 1230 __ JumpIfSmi(reg, true_label); | 1249 __ JumpIfSmi(reg, true_label); |
| 1231 | 1250 |
| 1232 // Test for double values. Plus/minus zero and NaN are false. | 1251 // Test for double values. Plus/minus zero and NaN are false. |
| 1233 NearLabel call_stub; | 1252 NearLabel call_stub; |
| 1234 __ CompareRoot(FieldOperand(reg, HeapObject::kMapOffset), | 1253 __ CompareRoot(FieldOperand(reg, HeapObject::kMapOffset), |
| 1235 Heap::kHeapNumberMapRootIndex); | 1254 Heap::kHeapNumberMapRootIndex); |
| 1236 __ j(not_equal, &call_stub); | 1255 __ j(not_equal, &call_stub); |
| 1237 | 1256 |
| 1238 // HeapNumber => false iff +0, -0, or NaN. These three cases set the | 1257 // HeapNumber => false iff +0, -0, or NaN. These three cases set the |
| (...skipping 932 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2171 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2190 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 2172 } | 2191 } |
| 2173 | 2192 |
| 2174 | 2193 |
| 2175 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { | 2194 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { |
| 2176 Register result = ToRegister(instr->result()); | 2195 Register result = ToRegister(instr->result()); |
| 2177 | 2196 |
| 2178 // Check for arguments adapter frame. | 2197 // Check for arguments adapter frame. |
| 2179 NearLabel done, adapted; | 2198 NearLabel done, adapted; |
| 2180 __ movq(result, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); | 2199 __ movq(result, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); |
| 2181 __ SmiCompare(Operand(result, StandardFrameConstants::kContextOffset), | 2200 __ Cmp(Operand(result, StandardFrameConstants::kContextOffset), |
| 2182 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); | 2201 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); |
| 2183 __ j(equal, &adapted); | 2202 __ j(equal, &adapted); |
| 2184 | 2203 |
| 2185 // No arguments adaptor frame. | 2204 // No arguments adaptor frame. |
| 2186 __ movq(result, rbp); | 2205 __ movq(result, rbp); |
| 2187 __ jmp(&done); | 2206 __ jmp(&done); |
| 2188 | 2207 |
| 2189 // Arguments adaptor frame present. | 2208 // Arguments adaptor frame present. |
| 2190 __ bind(&adapted); | 2209 __ bind(&adapted); |
| 2191 __ movq(result, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); | 2210 __ movq(result, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); |
| 2192 | 2211 |
| (...skipping 783 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2976 instr->pointer_map(), 2, Safepoint::kNoDeoptimizationIndex); | 2995 instr->pointer_map(), 2, Safepoint::kNoDeoptimizationIndex); |
| 2977 if (FLAG_debug_code) { | 2996 if (FLAG_debug_code) { |
| 2978 __ AbortIfNotSmi(rax); | 2997 __ AbortIfNotSmi(rax); |
| 2979 } | 2998 } |
| 2980 __ SmiToInteger32(rax, rax); | 2999 __ SmiToInteger32(rax, rax); |
| 2981 __ StoreToSafepointRegisterSlot(result, rax); | 3000 __ StoreToSafepointRegisterSlot(result, rax); |
| 2982 __ PopSafepointRegisters(); | 3001 __ PopSafepointRegisters(); |
| 2983 } | 3002 } |
| 2984 | 3003 |
| 2985 | 3004 |
| 3005 void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) { |
| 3006 class DeferredStringCharFromCode: public LDeferredCode { |
| 3007 public: |
| 3008 DeferredStringCharFromCode(LCodeGen* codegen, LStringCharFromCode* instr) |
| 3009 : LDeferredCode(codegen), instr_(instr) { } |
| 3010 virtual void Generate() { codegen()->DoDeferredStringCharFromCode(instr_); } |
| 3011 private: |
| 3012 LStringCharFromCode* instr_; |
| 3013 }; |
| 3014 |
| 3015 DeferredStringCharFromCode* deferred = |
| 3016 new DeferredStringCharFromCode(this, instr); |
| 3017 |
| 3018 ASSERT(instr->hydrogen()->value()->representation().IsInteger32()); |
| 3019 Register char_code = ToRegister(instr->char_code()); |
| 3020 Register result = ToRegister(instr->result()); |
| 3021 ASSERT(!char_code.is(result)); |
| 3022 |
| 3023 __ cmpl(char_code, Immediate(String::kMaxAsciiCharCode)); |
| 3024 __ j(above, deferred->entry()); |
| 3025 __ LoadRoot(result, Heap::kSingleCharacterStringCacheRootIndex); |
| 3026 __ movq(result, FieldOperand(result, |
| 3027 char_code, times_pointer_size, |
| 3028 FixedArray::kHeaderSize)); |
| 3029 __ CompareRoot(result, Heap::kUndefinedValueRootIndex); |
| 3030 __ j(equal, deferred->entry()); |
| 3031 __ bind(deferred->exit()); |
| 3032 } |
| 3033 |
| 3034 |
| 3035 void LCodeGen::DoDeferredStringCharFromCode(LStringCharFromCode* instr) { |
| 3036 Register char_code = ToRegister(instr->char_code()); |
| 3037 Register result = ToRegister(instr->result()); |
| 3038 |
| 3039 // TODO(3095996): Get rid of this. For now, we need to make the |
| 3040 // result register contain a valid pointer because it is already |
| 3041 // contained in the register pointer map. |
| 3042 __ Set(result, 0); |
| 3043 |
| 3044 __ PushSafepointRegisters(); |
| 3045 __ Integer32ToSmi(char_code, char_code); |
| 3046 __ push(char_code); |
| 3047 __ CallRuntimeSaveDoubles(Runtime::kCharFromCode); |
| 3048 RecordSafepointWithRegisters( |
| 3049 instr->pointer_map(), 1, Safepoint::kNoDeoptimizationIndex); |
| 3050 __ StoreToSafepointRegisterSlot(result, rax); |
| 3051 __ PopSafepointRegisters(); |
| 3052 } |
| 3053 |
| 3054 |
| 2986 void LCodeGen::DoStringLength(LStringLength* instr) { | 3055 void LCodeGen::DoStringLength(LStringLength* instr) { |
| 2987 Register string = ToRegister(instr->string()); | 3056 Register string = ToRegister(instr->string()); |
| 2988 Register result = ToRegister(instr->result()); | 3057 Register result = ToRegister(instr->result()); |
| 2989 __ movq(result, FieldOperand(string, String::kLengthOffset)); | 3058 __ movq(result, FieldOperand(string, String::kLengthOffset)); |
| 2990 } | 3059 } |
| 2991 | 3060 |
| 2992 | 3061 |
| 2993 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { | 3062 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { |
| 2994 LOperand* input = instr->InputAt(0); | 3063 LOperand* input = instr->InputAt(0); |
| 2995 ASSERT(input->IsRegister() || input->IsStackSlot()); | 3064 ASSERT(input->IsRegister() || input->IsStackSlot()); |
| (...skipping 613 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3609 EmitBranch(true_block, false_block, equal); | 3678 EmitBranch(true_block, false_block, equal); |
| 3610 } | 3679 } |
| 3611 | 3680 |
| 3612 | 3681 |
| 3613 void LCodeGen::EmitIsConstructCall(Register temp) { | 3682 void LCodeGen::EmitIsConstructCall(Register temp) { |
| 3614 // Get the frame pointer for the calling frame. | 3683 // Get the frame pointer for the calling frame. |
| 3615 __ movq(temp, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); | 3684 __ movq(temp, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); |
| 3616 | 3685 |
| 3617 // Skip the arguments adaptor frame if it exists. | 3686 // Skip the arguments adaptor frame if it exists. |
| 3618 NearLabel check_frame_marker; | 3687 NearLabel check_frame_marker; |
| 3619 __ SmiCompare(Operand(temp, StandardFrameConstants::kContextOffset), | 3688 __ Cmp(Operand(temp, StandardFrameConstants::kContextOffset), |
| 3620 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); | 3689 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); |
| 3621 __ j(not_equal, &check_frame_marker); | 3690 __ j(not_equal, &check_frame_marker); |
| 3622 __ movq(temp, Operand(rax, StandardFrameConstants::kCallerFPOffset)); | 3691 __ movq(temp, Operand(rax, StandardFrameConstants::kCallerFPOffset)); |
| 3623 | 3692 |
| 3624 // Check the marker in the calling frame. | 3693 // Check the marker in the calling frame. |
| 3625 __ bind(&check_frame_marker); | 3694 __ bind(&check_frame_marker); |
| 3626 __ SmiCompare(Operand(temp, StandardFrameConstants::kMarkerOffset), | 3695 __ Cmp(Operand(temp, StandardFrameConstants::kMarkerOffset), |
| 3627 Smi::FromInt(StackFrame::CONSTRUCT)); | 3696 Smi::FromInt(StackFrame::CONSTRUCT)); |
| 3628 } | 3697 } |
| 3629 | 3698 |
| 3630 | 3699 |
| 3631 void LCodeGen::DoLazyBailout(LLazyBailout* instr) { | 3700 void LCodeGen::DoLazyBailout(LLazyBailout* instr) { |
| 3632 // No code for lazy bailout instruction. Used to capture environment after a | 3701 // No code for lazy bailout instruction. Used to capture environment after a |
| 3633 // call for populating the safepoint data with deoptimization data. | 3702 // call for populating the safepoint data with deoptimization data. |
| 3634 } | 3703 } |
| 3635 | 3704 |
| 3636 | 3705 |
| 3637 void LCodeGen::DoDeoptimize(LDeoptimize* instr) { | 3706 void LCodeGen::DoDeoptimize(LDeoptimize* instr) { |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3699 RegisterEnvironmentForDeoptimization(environment); | 3768 RegisterEnvironmentForDeoptimization(environment); |
| 3700 ASSERT(osr_pc_offset_ == -1); | 3769 ASSERT(osr_pc_offset_ == -1); |
| 3701 osr_pc_offset_ = masm()->pc_offset(); | 3770 osr_pc_offset_ = masm()->pc_offset(); |
| 3702 } | 3771 } |
| 3703 | 3772 |
| 3704 #undef __ | 3773 #undef __ |
| 3705 | 3774 |
| 3706 } } // namespace v8::internal | 3775 } } // namespace v8::internal |
| 3707 | 3776 |
| 3708 #endif // V8_TARGET_ARCH_X64 | 3777 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |