| 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 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 96 | 96 |
| 97 | 97 |
| 98 void MacroAssembler::Jump(Handle<Code> code, RelocInfo::Mode rmode, | 98 void MacroAssembler::Jump(Handle<Code> code, RelocInfo::Mode rmode, |
| 99 Condition cond) { | 99 Condition cond) { |
| 100 ASSERT(RelocInfo::IsCodeTarget(rmode)); | 100 ASSERT(RelocInfo::IsCodeTarget(rmode)); |
| 101 // 'code' is always generated ARM code, never THUMB code | 101 // 'code' is always generated ARM code, never THUMB code |
| 102 Jump(reinterpret_cast<intptr_t>(code.location()), rmode, cond); | 102 Jump(reinterpret_cast<intptr_t>(code.location()), rmode, cond); |
| 103 } | 103 } |
| 104 | 104 |
| 105 | 105 |
| 106 int MacroAssembler::CallSize(Register target, Condition cond) { |
| 107 #if USE_BLX |
| 108 return kInstrSize; |
| 109 #else |
| 110 return 2 * kInstrSize; |
| 111 #endif |
| 112 } |
| 113 |
| 114 |
| 106 void MacroAssembler::Call(Register target, Condition cond) { | 115 void MacroAssembler::Call(Register target, Condition cond) { |
| 116 // Block constant pool for the call instruction sequence. |
| 117 BlockConstPoolScope block_const_pool(this); |
| 118 #ifdef DEBUG |
| 119 int pre_position = pc_offset(); |
| 120 #endif |
| 121 |
| 107 #if USE_BLX | 122 #if USE_BLX |
| 108 blx(target, cond); | 123 blx(target, cond); |
| 109 #else | 124 #else |
| 110 // set lr for return at current pc + 8 | 125 // set lr for return at current pc + 8 |
| 111 mov(lr, Operand(pc), LeaveCC, cond); | 126 mov(lr, Operand(pc), LeaveCC, cond); |
| 112 mov(pc, Operand(target), LeaveCC, cond); | 127 mov(pc, Operand(target), LeaveCC, cond); |
| 113 #endif | 128 #endif |
| 129 |
| 130 #ifdef DEBUG |
| 131 int post_position = pc_offset(); |
| 132 CHECK_EQ(pre_position + CallSize(target, cond), post_position); |
| 133 #endif |
| 114 } | 134 } |
| 115 | 135 |
| 116 | 136 |
| 117 void MacroAssembler::Call(intptr_t target, RelocInfo::Mode rmode, | 137 int MacroAssembler::CallSize( |
| 118 Condition cond) { | 138 intptr_t target, RelocInfo::Mode rmode, Condition cond) { |
| 139 int size = 2 * kInstrSize; |
| 140 Instr mov_instr = cond | MOV | LeaveCC; |
| 141 if (!Operand(target, rmode).is_single_instruction(mov_instr)) { |
| 142 size += kInstrSize; |
| 143 } |
| 144 return size; |
| 145 } |
| 146 |
| 147 |
| 148 void MacroAssembler::Call( |
| 149 intptr_t target, RelocInfo::Mode rmode, Condition cond) { |
| 150 // Block constant pool for the call instruction sequence. |
| 151 BlockConstPoolScope block_const_pool(this); |
| 152 #ifdef DEBUG |
| 153 int pre_position = pc_offset(); |
| 154 #endif |
| 155 |
| 119 #if USE_BLX | 156 #if USE_BLX |
| 120 // On ARMv5 and after the recommended call sequence is: | 157 // On ARMv5 and after the recommended call sequence is: |
| 121 // ldr ip, [pc, #...] | 158 // ldr ip, [pc, #...] |
| 122 // blx ip | 159 // blx ip |
| 123 | 160 |
| 124 // The two instructions (ldr and blx) could be separated by a constant | 161 // Statement positions are expected to be recorded when the target |
| 125 // pool and the code would still work. The issue comes from the | 162 // address is loaded. The mov method will automatically record |
| 126 // patching code which expect the ldr to be just above the blx. | 163 // positions when pc is the target, since this is not the case here |
| 127 { BlockConstPoolScope block_const_pool(this); | 164 // we have to do it explicitly. |
| 128 // Statement positions are expected to be recorded when the target | 165 positions_recorder()->WriteRecordedPositions(); |
| 129 // address is loaded. The mov method will automatically record | |
| 130 // positions when pc is the target, since this is not the case here | |
| 131 // we have to do it explicitly. | |
| 132 positions_recorder()->WriteRecordedPositions(); | |
| 133 | 166 |
| 134 mov(ip, Operand(target, rmode), LeaveCC, cond); | 167 mov(ip, Operand(target, rmode), LeaveCC, cond); |
| 135 blx(ip, cond); | 168 blx(ip, cond); |
| 136 } | |
| 137 | 169 |
| 138 ASSERT(kCallTargetAddressOffset == 2 * kInstrSize); | 170 ASSERT(kCallTargetAddressOffset == 2 * kInstrSize); |
| 139 #else | 171 #else |
| 140 // Set lr for return at current pc + 8. | 172 // Set lr for return at current pc + 8. |
| 141 mov(lr, Operand(pc), LeaveCC, cond); | 173 mov(lr, Operand(pc), LeaveCC, cond); |
| 142 // Emit a ldr<cond> pc, [pc + offset of target in constant pool]. | 174 // Emit a ldr<cond> pc, [pc + offset of target in constant pool]. |
| 143 mov(pc, Operand(target, rmode), LeaveCC, cond); | 175 mov(pc, Operand(target, rmode), LeaveCC, cond); |
| 176 ASSERT(kCallTargetAddressOffset == kInstrSize); |
| 177 #endif |
| 144 | 178 |
| 145 ASSERT(kCallTargetAddressOffset == kInstrSize); | 179 #ifdef DEBUG |
| 180 int post_position = pc_offset(); |
| 181 CHECK_EQ(pre_position + CallSize(target, rmode, cond), post_position); |
| 146 #endif | 182 #endif |
| 147 } | 183 } |
| 148 | 184 |
| 149 | 185 |
| 150 void MacroAssembler::Call(byte* target, RelocInfo::Mode rmode, | 186 int MacroAssembler::CallSize( |
| 151 Condition cond) { | 187 byte* target, RelocInfo::Mode rmode, Condition cond) { |
| 152 ASSERT(!RelocInfo::IsCodeTarget(rmode)); | 188 return CallSize(reinterpret_cast<intptr_t>(target), rmode); |
| 153 Call(reinterpret_cast<intptr_t>(target), rmode, cond); | |
| 154 } | 189 } |
| 155 | 190 |
| 156 | 191 |
| 157 void MacroAssembler::Call(Handle<Code> code, RelocInfo::Mode rmode, | 192 void MacroAssembler::Call( |
| 158 Condition cond) { | 193 byte* target, RelocInfo::Mode rmode, Condition cond) { |
| 194 #ifdef DEBUG |
| 195 int pre_position = pc_offset(); |
| 196 #endif |
| 197 |
| 198 ASSERT(!RelocInfo::IsCodeTarget(rmode)); |
| 199 Call(reinterpret_cast<intptr_t>(target), rmode, cond); |
| 200 |
| 201 #ifdef DEBUG |
| 202 int post_position = pc_offset(); |
| 203 CHECK_EQ(pre_position + CallSize(target, rmode, cond), post_position); |
| 204 #endif |
| 205 } |
| 206 |
| 207 |
| 208 int MacroAssembler::CallSize( |
| 209 Handle<Code> code, RelocInfo::Mode rmode, Condition cond) { |
| 210 return CallSize(reinterpret_cast<intptr_t>(code.location()), rmode, cond); |
| 211 } |
| 212 |
| 213 |
| 214 void MacroAssembler::Call( |
| 215 Handle<Code> code, RelocInfo::Mode rmode, Condition cond) { |
| 216 #ifdef DEBUG |
| 217 int pre_position = pc_offset(); |
| 218 #endif |
| 219 |
| 159 ASSERT(RelocInfo::IsCodeTarget(rmode)); | 220 ASSERT(RelocInfo::IsCodeTarget(rmode)); |
| 160 // 'code' is always generated ARM code, never THUMB code | 221 // 'code' is always generated ARM code, never THUMB code |
| 161 Call(reinterpret_cast<intptr_t>(code.location()), rmode, cond); | 222 Call(reinterpret_cast<intptr_t>(code.location()), rmode, cond); |
| 223 |
| 224 #ifdef DEBUG |
| 225 int post_position = pc_offset(); |
| 226 CHECK_EQ(pre_position + CallSize(code, rmode, cond), post_position); |
| 227 #endif |
| 162 } | 228 } |
| 163 | 229 |
| 164 | 230 |
| 165 void MacroAssembler::Ret(Condition cond) { | 231 void MacroAssembler::Ret(Condition cond) { |
| 166 #if USE_BX | 232 #if USE_BX |
| 167 bx(lr, cond); | 233 bx(lr, cond); |
| 168 #else | 234 #else |
| 169 mov(pc, Operand(lr), LeaveCC, cond); | 235 mov(pc, Operand(lr), LeaveCC, cond); |
| 170 #endif | 236 #endif |
| 171 } | 237 } |
| (...skipping 605 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 777 #endif | 843 #endif |
| 778 } | 844 } |
| 779 | 845 |
| 780 | 846 |
| 781 void MacroAssembler::InvokePrologue(const ParameterCount& expected, | 847 void MacroAssembler::InvokePrologue(const ParameterCount& expected, |
| 782 const ParameterCount& actual, | 848 const ParameterCount& actual, |
| 783 Handle<Code> code_constant, | 849 Handle<Code> code_constant, |
| 784 Register code_reg, | 850 Register code_reg, |
| 785 Label* done, | 851 Label* done, |
| 786 InvokeFlag flag, | 852 InvokeFlag flag, |
| 787 PostCallGenerator* post_call_generator) { | 853 CallWrapper* call_wrapper) { |
| 788 bool definitely_matches = false; | 854 bool definitely_matches = false; |
| 789 Label regular_invoke; | 855 Label regular_invoke; |
| 790 | 856 |
| 791 // Check whether the expected and actual arguments count match. If not, | 857 // Check whether the expected and actual arguments count match. If not, |
| 792 // setup registers according to contract with ArgumentsAdaptorTrampoline: | 858 // setup registers according to contract with ArgumentsAdaptorTrampoline: |
| 793 // r0: actual arguments count | 859 // r0: actual arguments count |
| 794 // r1: function (passed through to callee) | 860 // r1: function (passed through to callee) |
| 795 // r2: expected arguments count | 861 // r2: expected arguments count |
| 796 // r3: callee code entry | 862 // r3: callee code entry |
| 797 | 863 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 832 | 898 |
| 833 if (!definitely_matches) { | 899 if (!definitely_matches) { |
| 834 if (!code_constant.is_null()) { | 900 if (!code_constant.is_null()) { |
| 835 mov(r3, Operand(code_constant)); | 901 mov(r3, Operand(code_constant)); |
| 836 add(r3, r3, Operand(Code::kHeaderSize - kHeapObjectTag)); | 902 add(r3, r3, Operand(Code::kHeaderSize - kHeapObjectTag)); |
| 837 } | 903 } |
| 838 | 904 |
| 839 Handle<Code> adaptor = | 905 Handle<Code> adaptor = |
| 840 Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)); | 906 Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline)); |
| 841 if (flag == CALL_FUNCTION) { | 907 if (flag == CALL_FUNCTION) { |
| 908 if (call_wrapper != NULL) { |
| 909 call_wrapper->BeforeCall(CallSize(adaptor, RelocInfo::CODE_TARGET)); |
| 910 } |
| 842 Call(adaptor, RelocInfo::CODE_TARGET); | 911 Call(adaptor, RelocInfo::CODE_TARGET); |
| 843 if (post_call_generator != NULL) post_call_generator->Generate(); | 912 if (call_wrapper != NULL) call_wrapper->AfterCall(); |
| 844 b(done); | 913 b(done); |
| 845 } else { | 914 } else { |
| 846 Jump(adaptor, RelocInfo::CODE_TARGET); | 915 Jump(adaptor, RelocInfo::CODE_TARGET); |
| 847 } | 916 } |
| 848 bind(®ular_invoke); | 917 bind(®ular_invoke); |
| 849 } | 918 } |
| 850 } | 919 } |
| 851 | 920 |
| 852 | 921 |
| 853 void MacroAssembler::InvokeCode(Register code, | 922 void MacroAssembler::InvokeCode(Register code, |
| 854 const ParameterCount& expected, | 923 const ParameterCount& expected, |
| 855 const ParameterCount& actual, | 924 const ParameterCount& actual, |
| 856 InvokeFlag flag, | 925 InvokeFlag flag, |
| 857 PostCallGenerator* post_call_generator) { | 926 CallWrapper* call_wrapper) { |
| 858 Label done; | 927 Label done; |
| 859 | 928 |
| 860 InvokePrologue(expected, actual, Handle<Code>::null(), code, &done, flag, | 929 InvokePrologue(expected, actual, Handle<Code>::null(), code, &done, flag, |
| 861 post_call_generator); | 930 call_wrapper); |
| 862 if (flag == CALL_FUNCTION) { | 931 if (flag == CALL_FUNCTION) { |
| 932 if (call_wrapper != NULL) call_wrapper->BeforeCall(CallSize(code)); |
| 863 Call(code); | 933 Call(code); |
| 864 if (post_call_generator != NULL) post_call_generator->Generate(); | 934 if (call_wrapper != NULL) call_wrapper->AfterCall(); |
| 865 } else { | 935 } else { |
| 866 ASSERT(flag == JUMP_FUNCTION); | 936 ASSERT(flag == JUMP_FUNCTION); |
| 867 Jump(code); | 937 Jump(code); |
| 868 } | 938 } |
| 869 | 939 |
| 870 // Continue here if InvokePrologue does handle the invocation due to | 940 // Continue here if InvokePrologue does handle the invocation due to |
| 871 // mismatched parameter counts. | 941 // mismatched parameter counts. |
| 872 bind(&done); | 942 bind(&done); |
| 873 } | 943 } |
| 874 | 944 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 889 | 959 |
| 890 // Continue here if InvokePrologue does handle the invocation due to | 960 // Continue here if InvokePrologue does handle the invocation due to |
| 891 // mismatched parameter counts. | 961 // mismatched parameter counts. |
| 892 bind(&done); | 962 bind(&done); |
| 893 } | 963 } |
| 894 | 964 |
| 895 | 965 |
| 896 void MacroAssembler::InvokeFunction(Register fun, | 966 void MacroAssembler::InvokeFunction(Register fun, |
| 897 const ParameterCount& actual, | 967 const ParameterCount& actual, |
| 898 InvokeFlag flag, | 968 InvokeFlag flag, |
| 899 PostCallGenerator* post_call_generator) { | 969 CallWrapper* call_wrapper) { |
| 900 // Contract with called JS functions requires that function is passed in r1. | 970 // Contract with called JS functions requires that function is passed in r1. |
| 901 ASSERT(fun.is(r1)); | 971 ASSERT(fun.is(r1)); |
| 902 | 972 |
| 903 Register expected_reg = r2; | 973 Register expected_reg = r2; |
| 904 Register code_reg = r3; | 974 Register code_reg = r3; |
| 905 | 975 |
| 906 ldr(code_reg, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); | 976 ldr(code_reg, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); |
| 907 ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); | 977 ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); |
| 908 ldr(expected_reg, | 978 ldr(expected_reg, |
| 909 FieldMemOperand(code_reg, | 979 FieldMemOperand(code_reg, |
| 910 SharedFunctionInfo::kFormalParameterCountOffset)); | 980 SharedFunctionInfo::kFormalParameterCountOffset)); |
| 911 mov(expected_reg, Operand(expected_reg, ASR, kSmiTagSize)); | 981 mov(expected_reg, Operand(expected_reg, ASR, kSmiTagSize)); |
| 912 ldr(code_reg, | 982 ldr(code_reg, |
| 913 FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); | 983 FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); |
| 914 | 984 |
| 915 ParameterCount expected(expected_reg); | 985 ParameterCount expected(expected_reg); |
| 916 InvokeCode(code_reg, expected, actual, flag, post_call_generator); | 986 InvokeCode(code_reg, expected, actual, flag, call_wrapper); |
| 917 } | 987 } |
| 918 | 988 |
| 919 | 989 |
| 920 void MacroAssembler::InvokeFunction(JSFunction* function, | 990 void MacroAssembler::InvokeFunction(JSFunction* function, |
| 921 const ParameterCount& actual, | 991 const ParameterCount& actual, |
| 922 InvokeFlag flag) { | 992 InvokeFlag flag) { |
| 923 ASSERT(function->is_compiled()); | 993 ASSERT(function->is_compiled()); |
| 924 | 994 |
| 925 // Get the function and setup the context. | 995 // Get the function and setup the context. |
| 926 mov(r1, Operand(Handle<JSFunction>(function))); | 996 mov(r1, Operand(Handle<JSFunction>(function))); |
| (...skipping 1149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2076 ASSERT((reinterpret_cast<intptr_t>(builtin.address()) & 1) == 1); | 2146 ASSERT((reinterpret_cast<intptr_t>(builtin.address()) & 1) == 1); |
| 2077 #endif | 2147 #endif |
| 2078 mov(r1, Operand(builtin)); | 2148 mov(r1, Operand(builtin)); |
| 2079 CEntryStub stub(1); | 2149 CEntryStub stub(1); |
| 2080 return TryTailCallStub(&stub); | 2150 return TryTailCallStub(&stub); |
| 2081 } | 2151 } |
| 2082 | 2152 |
| 2083 | 2153 |
| 2084 void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, | 2154 void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, |
| 2085 InvokeJSFlags flags, | 2155 InvokeJSFlags flags, |
| 2086 PostCallGenerator* post_call_generator) { | 2156 CallWrapper* call_wrapper) { |
| 2087 GetBuiltinEntry(r2, id); | 2157 GetBuiltinEntry(r2, id); |
| 2088 if (flags == CALL_JS) { | 2158 if (flags == CALL_JS) { |
| 2159 if (call_wrapper != NULL) call_wrapper->BeforeCall(CallSize(r2)); |
| 2089 Call(r2); | 2160 Call(r2); |
| 2090 if (post_call_generator != NULL) post_call_generator->Generate(); | 2161 if (call_wrapper != NULL) call_wrapper->AfterCall(); |
| 2091 } else { | 2162 } else { |
| 2092 ASSERT(flags == JUMP_JS); | 2163 ASSERT(flags == JUMP_JS); |
| 2093 Jump(r2); | 2164 Jump(r2); |
| 2094 } | 2165 } |
| 2095 } | 2166 } |
| 2096 | 2167 |
| 2097 | 2168 |
| 2098 void MacroAssembler::GetBuiltinFunction(Register target, | 2169 void MacroAssembler::GetBuiltinFunction(Register target, |
| 2099 Builtins::JavaScript id) { | 2170 Builtins::JavaScript id) { |
| 2100 // Load the builtins object into target register. | 2171 // Load the builtins object into target register. |
| (...skipping 599 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2700 void CodePatcher::EmitCondition(Condition cond) { | 2771 void CodePatcher::EmitCondition(Condition cond) { |
| 2701 Instr instr = Assembler::instr_at(masm_.pc_); | 2772 Instr instr = Assembler::instr_at(masm_.pc_); |
| 2702 instr = (instr & ~kCondMask) | cond; | 2773 instr = (instr & ~kCondMask) | cond; |
| 2703 masm_.emit(instr); | 2774 masm_.emit(instr); |
| 2704 } | 2775 } |
| 2705 | 2776 |
| 2706 | 2777 |
| 2707 } } // namespace v8::internal | 2778 } } // namespace v8::internal |
| 2708 | 2779 |
| 2709 #endif // V8_TARGET_ARCH_ARM | 2780 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |