Absolute File Name: | /home/opencoverage/opencoverage/guest-scripts/qtdeclarative/src/qtdeclarative/src/qml/jit/qv4assembler.cpp |
Source code | Switch to Preprocessed file |
Line | Source | Count | ||||||
---|---|---|---|---|---|---|---|---|
1 | /**************************************************************************** | - | ||||||
2 | ** | - | ||||||
3 | ** Copyright (C) 2017 The Qt Company Ltd. | - | ||||||
4 | ** Contact: https://www.qt.io/licensing/ | - | ||||||
5 | ** | - | ||||||
6 | ** This file is part of the QtQml module of the Qt Toolkit. | - | ||||||
7 | ** | - | ||||||
8 | ** $QT_BEGIN_LICENSE:LGPL$ | - | ||||||
9 | ** Commercial License Usage | - | ||||||
10 | ** Licensees holding valid commercial Qt licenses may use this file in | - | ||||||
11 | ** accordance with the commercial license agreement provided with the | - | ||||||
12 | ** Software or, alternatively, in accordance with the terms contained in | - | ||||||
13 | ** a written agreement between you and The Qt Company. For licensing terms | - | ||||||
14 | ** and conditions see https://www.qt.io/terms-conditions. For further | - | ||||||
15 | ** information use the contact form at https://www.qt.io/contact-us. | - | ||||||
16 | ** | - | ||||||
17 | ** GNU Lesser General Public License Usage | - | ||||||
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser | - | ||||||
19 | ** General Public License version 3 as published by the Free Software | - | ||||||
20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the | - | ||||||
21 | ** packaging of this file. Please review the following information to | - | ||||||
22 | ** ensure the GNU Lesser General Public License version 3 requirements | - | ||||||
23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. | - | ||||||
24 | ** | - | ||||||
25 | ** GNU General Public License Usage | - | ||||||
26 | ** Alternatively, this file may be used under the terms of the GNU | - | ||||||
27 | ** General Public License version 2.0 or (at your option) the GNU General | - | ||||||
28 | ** Public license version 3 or any later version approved by the KDE Free | - | ||||||
29 | ** Qt Foundation. The licenses are as published by the Free Software | - | ||||||
30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 | - | ||||||
31 | ** included in the packaging of this file. Please review the following | - | ||||||
32 | ** information to ensure the GNU General Public License requirements will | - | ||||||
33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and | - | ||||||
34 | ** https://www.gnu.org/licenses/gpl-3.0.html. | - | ||||||
35 | ** | - | ||||||
36 | ** $QT_END_LICENSE$ | - | ||||||
37 | ** | - | ||||||
38 | ****************************************************************************/ | - | ||||||
39 | - | |||||||
40 | #include <QBuffer> | - | ||||||
41 | #include <QFile> | - | ||||||
42 | - | |||||||
43 | #include "qv4engine_p.h" | - | ||||||
44 | #include "qv4assembler_p.h" | - | ||||||
45 | #include <private/qv4function_p.h> | - | ||||||
46 | #include <private/qv4runtime_p.h> | - | ||||||
47 | #include <private/qv4stackframe_p.h> | - | ||||||
48 | - | |||||||
49 | #include <wtf/Vector.h> | - | ||||||
50 | #include <assembler/MacroAssembler.h> | - | ||||||
51 | #include <assembler/MacroAssemblerCodeRef.h> | - | ||||||
52 | #include <assembler/LinkBuffer.h> | - | ||||||
53 | #include <WTFStubs.h> | - | ||||||
54 | - | |||||||
55 | #undef ENABLE_ALL_ASSEMBLERS_FOR_REFACTORING_PURPOSES | - | ||||||
56 | - | |||||||
57 | #ifdef V4_ENABLE_JIT | - | ||||||
58 | - | |||||||
59 | QT_BEGIN_NAMESPACE | - | ||||||
60 | namespace QV4 { | - | ||||||
61 | namespace JIT { | - | ||||||
62 | - | |||||||
63 | #define callHelper(x) PlatformAssemblerCommon::callRuntime(#x, reinterpret_cast<void *>(&x)) | - | ||||||
64 | - | |||||||
65 | const QV4::Value::ValueTypeInternal IntegerTag = QV4::Value::ValueTypeInternal::Integer; | - | ||||||
66 | - | |||||||
67 | static ReturnedValue toNumberHelper(ReturnedValue v) | - | ||||||
68 | { | - | ||||||
69 | return Encode(Value::fromReturnedValue(v).toNumber()); never executed: return Encode(Value::fromReturnedValue(v).toNumber()); | 0 | ||||||
70 | } | - | ||||||
71 | - | |||||||
72 | static ReturnedValue toInt32Helper(ReturnedValue v) | - | ||||||
73 | { | - | ||||||
74 | return Encode(Value::fromReturnedValue(v).toInt32()); executed 512 times by 1 test: return Encode(Value::fromReturnedValue(v).toInt32()); Executed by:
| 512 | ||||||
75 | } | - | ||||||
76 | - | |||||||
77 | #if defined(Q_PROCESSOR_X86_64) || defined(ENABLE_ALL_ASSEMBLERS_FOR_REFACTORING_PURPOSES) | - | ||||||
78 | #if defined(Q_OS_LINUX) || defined(Q_OS_QNX) || defined(Q_OS_FREEBSD) || defined(Q_OS_DARWIN) | - | ||||||
79 | - | |||||||
80 | struct PlatformAssembler_X86_64_SysV : JSC::MacroAssembler<JSC::MacroAssemblerX86_64> | - | ||||||
81 | { | - | ||||||
82 | static const RegisterID NoRegister = RegisterID(-1); | - | ||||||
83 | - | |||||||
84 | static const RegisterID ReturnValueRegister = RegisterID::eax; | - | ||||||
85 | static const RegisterID ReturnValueRegisterValue = ReturnValueRegister; | - | ||||||
86 | static const RegisterID AccumulatorRegister = RegisterID::eax; | - | ||||||
87 | static const RegisterID AccumulatorRegisterValue = AccumulatorRegister; | - | ||||||
88 | static const RegisterID ScratchRegister = RegisterID::r10; | - | ||||||
89 | static const RegisterID ScratchRegister2 = RegisterID::r9; // Note: overlaps with Arg5Reg, so do not use while setting up a call! | - | ||||||
90 | static const RegisterID JSStackFrameRegister = RegisterID::r12; | - | ||||||
91 | static const RegisterID CppStackFrameRegister = RegisterID::r13; | - | ||||||
92 | static const RegisterID EngineRegister = RegisterID::r14; | - | ||||||
93 | static const RegisterID StackPointerRegister = RegisterID::esp; | - | ||||||
94 | static const RegisterID FramePointerRegister = RegisterID::ebp; | - | ||||||
95 | static const FPRegisterID FPScratchRegister = FPRegisterID::xmm1; | - | ||||||
96 | - | |||||||
97 | static const RegisterID Arg0Reg = RegisterID::edi; | - | ||||||
98 | static const RegisterID Arg1Reg = RegisterID::esi; | - | ||||||
99 | static const RegisterID Arg2Reg = RegisterID::edx; | - | ||||||
100 | static const RegisterID Arg3Reg = RegisterID::ecx; | - | ||||||
101 | static const RegisterID Arg4Reg = RegisterID::r8; | - | ||||||
102 | static const RegisterID Arg5Reg = RegisterID::r9; | - | ||||||
103 | static const RegisterID Arg6Reg = NoRegister; | - | ||||||
104 | static const RegisterID Arg7Reg = NoRegister; | - | ||||||
105 | static const int ArgInRegCount = 6; | - | ||||||
106 | - | |||||||
107 | void popValue() | - | ||||||
108 | { | - | ||||||
109 | addPtr(TrustedImmPtr(sizeof(ReturnedValue)), StackPointerRegister); | - | ||||||
110 | } never executed: end of block | 0 | ||||||
111 | - | |||||||
112 | void generatePlatformFunctionEntry() | - | ||||||
113 | { | - | ||||||
114 | push(RegisterID::ebp); | - | ||||||
115 | move(RegisterID::esp, RegisterID::ebp); | - | ||||||
116 | move(TrustedImmPtr(nullptr), AccumulatorRegister); push(AccumulatorRegister); // exceptionHandler | - | ||||||
117 | push(JSStackFrameRegister); | - | ||||||
118 | push(CppStackFrameRegister); | - | ||||||
119 | push(EngineRegister); | - | ||||||
120 | move(Arg0Reg, CppStackFrameRegister); | - | ||||||
121 | move(Arg1Reg, EngineRegister); | - | ||||||
122 | } executed 13188 times by 64 tests: end of block Executed by:
| 13188 | ||||||
123 | - | |||||||
124 | void generatePlatformFunctionExit() | - | ||||||
125 | { | - | ||||||
126 | pop(EngineRegister); | - | ||||||
127 | pop(CppStackFrameRegister); | - | ||||||
128 | pop(JSStackFrameRegister); | - | ||||||
129 | pop(); // exceptionHandler | - | ||||||
130 | pop(RegisterID::ebp); | - | ||||||
131 | ret(); | - | ||||||
132 | } executed 13188 times by 64 tests: end of block Executed by:
| 13188 | ||||||
133 | - | |||||||
134 | void callAbsolute(const void *funcPtr) | - | ||||||
135 | { | - | ||||||
136 | move(TrustedImmPtr(funcPtr), ScratchRegister); | - | ||||||
137 | call(ScratchRegister); | - | ||||||
138 | } executed 83222 times by 64 tests: end of block Executed by:
| 83222 | ||||||
139 | - | |||||||
140 | void pushAligned(RegisterID reg) | - | ||||||
141 | { | - | ||||||
142 | subPtr(TrustedImm32(PointerSize), StackPointerRegister); | - | ||||||
143 | push(reg); | - | ||||||
144 | } executed 98 times by 10 tests: end of block Executed by:
| 98 | ||||||
145 | - | |||||||
146 | void popAligned(RegisterID reg) | - | ||||||
147 | { | - | ||||||
148 | pop(reg); | - | ||||||
149 | addPtr(TrustedImm32(PointerSize), StackPointerRegister); | - | ||||||
150 | } executed 28 times by 1 test: end of block Executed by:
| 28 | ||||||
151 | }; | - | ||||||
152 | - | |||||||
153 | typedef PlatformAssembler_X86_64_SysV PlatformAssemblerBase; | - | ||||||
154 | - | |||||||
155 | #endif | - | ||||||
156 | #if defined(Q_OS_WIN) | - | ||||||
157 | - | |||||||
158 | struct PlatformAssembler_Win64 : JSC::MacroAssembler<JSC::MacroAssemblerX86_64> | - | ||||||
159 | { | - | ||||||
160 | static const RegisterID NoRegister = RegisterID(-1); | - | ||||||
161 | - | |||||||
162 | static const RegisterID ReturnValueRegister = RegisterID::eax; | - | ||||||
163 | static const RegisterID ReturnValueRegisterValue = ReturnValueRegister; | - | ||||||
164 | static const RegisterID AccumulatorRegister = RegisterID::eax; | - | ||||||
165 | static const RegisterID AccumulatorRegisterValue = AccumulatorRegister; | - | ||||||
166 | static const RegisterID ScratchRegister = RegisterID::r10; | - | ||||||
167 | static const RegisterID ScratchRegister2 = RegisterID::r9; // Note: overlaps with Arg3Reg, so do not use while setting up a call! | - | ||||||
168 | static const RegisterID JSStackFrameRegister = RegisterID::r12; | - | ||||||
169 | static const RegisterID CppStackFrameRegister = RegisterID::r13; | - | ||||||
170 | static const RegisterID EngineRegister = RegisterID::r14; | - | ||||||
171 | static const RegisterID StackPointerRegister = RegisterID::esp; | - | ||||||
172 | static const RegisterID FramePointerRegister = RegisterID::ebp; | - | ||||||
173 | static const FPRegisterID FPScratchRegister = FPRegisterID::xmm1; | - | ||||||
174 | - | |||||||
175 | static const RegisterID Arg0Reg = RegisterID::ecx; | - | ||||||
176 | static const RegisterID Arg1Reg = RegisterID::edx; | - | ||||||
177 | static const RegisterID Arg2Reg = RegisterID::r8; | - | ||||||
178 | static const RegisterID Arg3Reg = RegisterID::r9; | - | ||||||
179 | static const RegisterID Arg4Reg = NoRegister; | - | ||||||
180 | static const RegisterID Arg5Reg = NoRegister; | - | ||||||
181 | static const RegisterID Arg6Reg = NoRegister; | - | ||||||
182 | static const RegisterID Arg7Reg = NoRegister; | - | ||||||
183 | static const int ArgInRegCount = 4; | - | ||||||
184 | - | |||||||
185 | void popValue() | - | ||||||
186 | { | - | ||||||
187 | addPtr(TrustedImmPtr(sizeof(ReturnedValue)), StackPointerRegister); | - | ||||||
188 | } | - | ||||||
189 | - | |||||||
190 | void generatePlatformFunctionEntry() | - | ||||||
191 | { | - | ||||||
192 | push(RegisterID::ebp); | - | ||||||
193 | move(RegisterID::esp, RegisterID::ebp); | - | ||||||
194 | move(TrustedImmPtr(nullptr), AccumulatorRegister); push(AccumulatorRegister); // exceptionHandler | - | ||||||
195 | push(JSStackFrameRegister); | - | ||||||
196 | push(CppStackFrameRegister); | - | ||||||
197 | push(EngineRegister); | - | ||||||
198 | move(Arg0Reg, CppStackFrameRegister); | - | ||||||
199 | move(Arg1Reg, EngineRegister); | - | ||||||
200 | } | - | ||||||
201 | - | |||||||
202 | void generatePlatformFunctionExit() | - | ||||||
203 | { | - | ||||||
204 | pop(EngineRegister); | - | ||||||
205 | pop(CppStackFrameRegister); | - | ||||||
206 | pop(JSStackFrameRegister); | - | ||||||
207 | pop(); // exceptionHandler | - | ||||||
208 | pop(RegisterID::ebp); | - | ||||||
209 | ret(); | - | ||||||
210 | } | - | ||||||
211 | - | |||||||
212 | void callAbsolute(const void *funcPtr) | - | ||||||
213 | { | - | ||||||
214 | move(TrustedImmPtr(funcPtr), ScratchRegister); | - | ||||||
215 | subPtr(TrustedImm32(4 * PointerSize), StackPointerRegister); | - | ||||||
216 | call(ScratchRegister); | - | ||||||
217 | addPtr(TrustedImm32(4 * PointerSize), StackPointerRegister); | - | ||||||
218 | } | - | ||||||
219 | - | |||||||
220 | void pushAligned(RegisterID reg) | - | ||||||
221 | { | - | ||||||
222 | subPtr(TrustedImm32(PointerSize), StackPointerRegister); | - | ||||||
223 | push(reg); | - | ||||||
224 | } | - | ||||||
225 | - | |||||||
226 | void popAligned(RegisterID reg) | - | ||||||
227 | { | - | ||||||
228 | pop(reg); | - | ||||||
229 | addPtr(TrustedImm32(PointerSize), StackPointerRegister); | - | ||||||
230 | } | - | ||||||
231 | }; | - | ||||||
232 | - | |||||||
233 | typedef PlatformAssembler_Win64 PlatformAssemblerBase; | - | ||||||
234 | - | |||||||
235 | #endif | - | ||||||
236 | #endif | - | ||||||
237 | - | |||||||
238 | #if (defined(Q_PROCESSOR_X86) && !defined(Q_PROCESSOR_X86_64)) || defined(ENABLE_ALL_ASSEMBLERS_FOR_REFACTORING_PURPOSES) | - | ||||||
239 | - | |||||||
240 | struct PlatformAssembler_X86_All : JSC::MacroAssembler<JSC::MacroAssemblerX86> | - | ||||||
241 | { | - | ||||||
242 | static const RegisterID NoRegister = RegisterID(-1); | - | ||||||
243 | - | |||||||
244 | static const RegisterID ReturnValueRegisterValue = RegisterID::eax; | - | ||||||
245 | static const RegisterID ReturnValueRegisterTag = RegisterID::edx; | - | ||||||
246 | static const RegisterID ScratchRegister = RegisterID::ecx; | - | ||||||
247 | static const RegisterID AccumulatorRegisterValue = ReturnValueRegisterValue; | - | ||||||
248 | static const RegisterID AccumulatorRegisterTag = ReturnValueRegisterTag; | - | ||||||
249 | static const RegisterID JSStackFrameRegister = RegisterID::ebx; | - | ||||||
250 | static const RegisterID CppStackFrameRegister = RegisterID::esi; | - | ||||||
251 | static const RegisterID EngineRegister = RegisterID::edi; | - | ||||||
252 | static const RegisterID StackPointerRegister = RegisterID::esp; | - | ||||||
253 | static const RegisterID FramePointerRegister = RegisterID::ebp; | - | ||||||
254 | static const FPRegisterID FPScratchRegister = FPRegisterID::xmm1; | - | ||||||
255 | - | |||||||
256 | static const RegisterID Arg0Reg = NoRegister; | - | ||||||
257 | static const RegisterID Arg1Reg = NoRegister; | - | ||||||
258 | static const RegisterID Arg2Reg = NoRegister; | - | ||||||
259 | static const RegisterID Arg3Reg = NoRegister; | - | ||||||
260 | static const RegisterID Arg4Reg = NoRegister; | - | ||||||
261 | static const RegisterID Arg5Reg = NoRegister; | - | ||||||
262 | static const RegisterID Arg6Reg = NoRegister; | - | ||||||
263 | static const RegisterID Arg7Reg = NoRegister; | - | ||||||
264 | static const int ArgInRegCount = 0; | - | ||||||
265 | - | |||||||
266 | void popValue() | - | ||||||
267 | { | - | ||||||
268 | addPtr(TrustedImmPtr(sizeof(ReturnedValue)), StackPointerRegister); | - | ||||||
269 | } | - | ||||||
270 | - | |||||||
271 | void generatePlatformFunctionEntry() | - | ||||||
272 | { | - | ||||||
273 | push(RegisterID::ebp); | - | ||||||
274 | move(RegisterID::esp, RegisterID::ebp); | - | ||||||
275 | move(TrustedImmPtr(nullptr), AccumulatorRegisterValue); push(AccumulatorRegisterValue); // exceptionHandler | - | ||||||
276 | push(JSStackFrameRegister); | - | ||||||
277 | push(CppStackFrameRegister); | - | ||||||
278 | push(EngineRegister); | - | ||||||
279 | // Ensure the stack is 16-byte aligned in order for compiler generated aligned SSE2 | - | ||||||
280 | // instructions to be able to target the stack. | - | ||||||
281 | subPtr(TrustedImm32(8), StackPointerRegister); | - | ||||||
282 | loadPtr(Address(FramePointerRegister, 2 * PointerSize), CppStackFrameRegister); | - | ||||||
283 | loadPtr(Address(FramePointerRegister, 3 * PointerSize), EngineRegister); | - | ||||||
284 | } | - | ||||||
285 | - | |||||||
286 | void generatePlatformFunctionExit() | - | ||||||
287 | { | - | ||||||
288 | addPtr(TrustedImm32(8), StackPointerRegister); | - | ||||||
289 | pop(EngineRegister); | - | ||||||
290 | pop(CppStackFrameRegister); | - | ||||||
291 | pop(JSStackFrameRegister); | - | ||||||
292 | pop(); // exceptionHandler | - | ||||||
293 | pop(RegisterID::ebp); | - | ||||||
294 | ret(); | - | ||||||
295 | } | - | ||||||
296 | - | |||||||
297 | void callAbsolute(const void *funcPtr) | - | ||||||
298 | { | - | ||||||
299 | move(TrustedImmPtr(funcPtr), ScratchRegister); | - | ||||||
300 | call(ScratchRegister); | - | ||||||
301 | } | - | ||||||
302 | - | |||||||
303 | void pushAligned(RegisterID reg) | - | ||||||
304 | { | - | ||||||
305 | subPtr(TrustedImm32(PointerSize), StackPointerRegister); | - | ||||||
306 | push(reg); | - | ||||||
307 | } | - | ||||||
308 | - | |||||||
309 | void popAligned(RegisterID reg) | - | ||||||
310 | { | - | ||||||
311 | pop(reg); | - | ||||||
312 | addPtr(TrustedImm32(PointerSize), StackPointerRegister); | - | ||||||
313 | } | - | ||||||
314 | }; | - | ||||||
315 | - | |||||||
316 | typedef PlatformAssembler_X86_All PlatformAssemblerBase; | - | ||||||
317 | - | |||||||
318 | #endif | - | ||||||
319 | - | |||||||
320 | #if defined(Q_PROCESSOR_ARM_64) || defined(ENABLE_ALL_ASSEMBLERS_FOR_REFACTORING_PURPOSES) | - | ||||||
321 | - | |||||||
322 | struct PlatformAssembler_ARM64 : JSC::MacroAssembler<JSC::MacroAssemblerARM64> | - | ||||||
323 | { | - | ||||||
324 | static const RegisterID NoRegister = RegisterID(-1); | - | ||||||
325 | - | |||||||
326 | static const RegisterID ReturnValueRegister = JSC::ARM64Registers::x0; | - | ||||||
327 | static const RegisterID ReturnValueRegisterValue = ReturnValueRegister; | - | ||||||
328 | static const RegisterID AccumulatorRegister = JSC::ARM64Registers::x9; | - | ||||||
329 | static const RegisterID AccumulatorRegisterValue = AccumulatorRegister; | - | ||||||
330 | static const RegisterID ScratchRegister = JSC::ARM64Registers::x10; | - | ||||||
331 | static const RegisterID ScratchRegister2 = JSC::ARM64Registers::x7; // Note: overlaps with Arg7Reg, so do not use while setting up a call! | - | ||||||
332 | static const RegisterID JSStackFrameRegister = JSC::ARM64Registers::x19; | - | ||||||
333 | static const RegisterID CppStackFrameRegister = JSC::ARM64Registers::x20; | - | ||||||
334 | static const RegisterID EngineRegister = JSC::ARM64Registers::x21; | - | ||||||
335 | static const RegisterID StackPointerRegister = JSC::ARM64Registers::sp; | - | ||||||
336 | static const RegisterID FramePointerRegister = JSC::ARM64Registers::fp; | - | ||||||
337 | static const FPRegisterID FPScratchRegister = JSC::ARM64Registers::q1; | - | ||||||
338 | - | |||||||
339 | static const RegisterID Arg0Reg = JSC::ARM64Registers::x0; | - | ||||||
340 | static const RegisterID Arg1Reg = JSC::ARM64Registers::x1; | - | ||||||
341 | static const RegisterID Arg2Reg = JSC::ARM64Registers::x2; | - | ||||||
342 | static const RegisterID Arg3Reg = JSC::ARM64Registers::x3; | - | ||||||
343 | static const RegisterID Arg4Reg = JSC::ARM64Registers::x4; | - | ||||||
344 | static const RegisterID Arg5Reg = JSC::ARM64Registers::x5; | - | ||||||
345 | static const RegisterID Arg6Reg = JSC::ARM64Registers::x6; | - | ||||||
346 | static const RegisterID Arg7Reg = JSC::ARM64Registers::x7; | - | ||||||
347 | static const int ArgInRegCount = 8; | - | ||||||
348 | - | |||||||
349 | void push(RegisterID src) | - | ||||||
350 | { | - | ||||||
351 | pushToSave(src); | - | ||||||
352 | } | - | ||||||
353 | - | |||||||
354 | void pop(RegisterID dest) | - | ||||||
355 | { | - | ||||||
356 | popToRestore(dest); | - | ||||||
357 | } | - | ||||||
358 | - | |||||||
359 | void pop() | - | ||||||
360 | { | - | ||||||
361 | add64(TrustedImm32(16), stackPointerRegister); | - | ||||||
362 | } | - | ||||||
363 | - | |||||||
364 | void popValue() | - | ||||||
365 | { | - | ||||||
366 | pop(); | - | ||||||
367 | } | - | ||||||
368 | - | |||||||
369 | void generatePlatformFunctionEntry() | - | ||||||
370 | { | - | ||||||
371 | pushPair(JSC::ARM64Registers::fp, JSC::ARM64Registers::lr); | - | ||||||
372 | move(RegisterID::sp, RegisterID::fp); | - | ||||||
373 | move(TrustedImmPtr(nullptr), AccumulatorRegister); // exceptionHandler | - | ||||||
374 | pushPair(JSStackFrameRegister, AccumulatorRegister); | - | ||||||
375 | pushPair(EngineRegister, CppStackFrameRegister); | - | ||||||
376 | move(Arg0Reg, CppStackFrameRegister); | - | ||||||
377 | move(Arg1Reg, EngineRegister); | - | ||||||
378 | } | - | ||||||
379 | - | |||||||
380 | void generatePlatformFunctionExit() | - | ||||||
381 | { | - | ||||||
382 | move(AccumulatorRegister, ReturnValueRegister); | - | ||||||
383 | popPair(EngineRegister, CppStackFrameRegister); | - | ||||||
384 | popPair(JSStackFrameRegister, AccumulatorRegister); | - | ||||||
385 | popPair(JSC::ARM64Registers::fp, JSC::ARM64Registers::lr); | - | ||||||
386 | ret(); | - | ||||||
387 | } | - | ||||||
388 | - | |||||||
389 | void callAbsolute(const void *funcPtr) | - | ||||||
390 | { | - | ||||||
391 | move(TrustedImmPtr(funcPtr), ScratchRegister); | - | ||||||
392 | call(ScratchRegister); | - | ||||||
393 | } | - | ||||||
394 | - | |||||||
395 | void pushAligned(RegisterID reg) | - | ||||||
396 | { | - | ||||||
397 | pushToSave(reg); | - | ||||||
398 | } | - | ||||||
399 | - | |||||||
400 | void popAligned(RegisterID reg) | - | ||||||
401 | { | - | ||||||
402 | popToRestore(reg); | - | ||||||
403 | } | - | ||||||
404 | }; | - | ||||||
405 | - | |||||||
406 | typedef PlatformAssembler_ARM64 PlatformAssemblerBase; | - | ||||||
407 | - | |||||||
408 | #endif | - | ||||||
409 | - | |||||||
410 | #if defined(Q_PROCESSOR_ARM_32) || defined(ENABLE_ALL_ASSEMBLERS_FOR_REFACTORING_PURPOSES) | - | ||||||
411 | - | |||||||
412 | struct PlatformAssembler_ARM32 : JSC::MacroAssembler<JSC::MacroAssemblerARMv7> | - | ||||||
413 | { | - | ||||||
414 | static const RegisterID NoRegister = RegisterID(-1); | - | ||||||
415 | - | |||||||
416 | static const RegisterID ReturnValueRegisterValue = JSC::ARMRegisters::r0; | - | ||||||
417 | static const RegisterID ReturnValueRegisterTag = JSC::ARMRegisters::r1; | - | ||||||
418 | static const RegisterID ScratchRegister = JSC::ARMRegisters::r2; | - | ||||||
419 | static const RegisterID AccumulatorRegisterValue = JSC::ARMRegisters::r4; | - | ||||||
420 | static const RegisterID AccumulatorRegisterTag = JSC::ARMRegisters::r5; | - | ||||||
421 | // r6 is used by MacroAssemblerARMv7 | - | ||||||
422 | static const RegisterID JSStackFrameRegister = JSC::ARMRegisters::r8; | - | ||||||
423 | static const RegisterID CppStackFrameRegister = JSC::ARMRegisters::r10; | - | ||||||
424 | #if CPU(ARM_THUMB2) || defined(V4_BOOTSTRAP) | - | ||||||
425 | static const RegisterID FramePointerRegister = JSC::ARMRegisters::r7; | - | ||||||
426 | static const RegisterID EngineRegister = JSC::ARMRegisters::r11; | - | ||||||
427 | #else // Thumbs down | - | ||||||
428 | static const RegisterID FramePointerRegister = JSC::ARMRegisters::r11; | - | ||||||
429 | static const RegisterID EngineRegister = JSC::ARMRegisters::r7; | - | ||||||
430 | #endif | - | ||||||
431 | static const RegisterID StackPointerRegister = JSC::ARMRegisters::r13; | - | ||||||
432 | static const FPRegisterID FPScratchRegister = JSC::ARMRegisters::d1; | - | ||||||
433 | - | |||||||
434 | static const RegisterID Arg0Reg = JSC::ARMRegisters::r0; | - | ||||||
435 | static const RegisterID Arg1Reg = JSC::ARMRegisters::r1; | - | ||||||
436 | static const RegisterID Arg2Reg = JSC::ARMRegisters::r2; | - | ||||||
437 | static const RegisterID Arg3Reg = JSC::ARMRegisters::r3; | - | ||||||
438 | static const RegisterID Arg4Reg = NoRegister; | - | ||||||
439 | static const RegisterID Arg5Reg = NoRegister; | - | ||||||
440 | static const RegisterID Arg6Reg = NoRegister; | - | ||||||
441 | static const RegisterID Arg7Reg = NoRegister; | - | ||||||
442 | static const int ArgInRegCount = 4; | - | ||||||
443 | - | |||||||
444 | void popValue() | - | ||||||
445 | { | - | ||||||
446 | addPtr(TrustedImm32(sizeof(ReturnedValue)), StackPointerRegister); | - | ||||||
447 | } | - | ||||||
448 | - | |||||||
449 | void generatePlatformFunctionEntry() | - | ||||||
450 | { | - | ||||||
451 | push(JSC::ARMRegisters::lr); | - | ||||||
452 | push(FramePointerRegister); | - | ||||||
453 | move(StackPointerRegister, FramePointerRegister); | - | ||||||
454 | push(TrustedImm32(0)); // exceptionHandler | - | ||||||
455 | push(AccumulatorRegisterValue); | - | ||||||
456 | push(AccumulatorRegisterTag); | - | ||||||
457 | push(addressTempRegister); | - | ||||||
458 | push(JSStackFrameRegister); | - | ||||||
459 | push(CppStackFrameRegister); | - | ||||||
460 | push(EngineRegister); | - | ||||||
461 | subPtr(TrustedImm32(4), StackPointerRegister); // stack alignment | - | ||||||
462 | move(Arg0Reg, CppStackFrameRegister); | - | ||||||
463 | move(Arg1Reg, EngineRegister); | - | ||||||
464 | } | - | ||||||
465 | - | |||||||
466 | void generatePlatformFunctionExit() | - | ||||||
467 | { | - | ||||||
468 | move(AccumulatorRegisterValue, ReturnValueRegisterValue); | - | ||||||
469 | move(AccumulatorRegisterTag, ReturnValueRegisterTag); | - | ||||||
470 | addPtr(TrustedImm32(4), StackPointerRegister); // stack alignment | - | ||||||
471 | pop(EngineRegister); | - | ||||||
472 | pop(CppStackFrameRegister); | - | ||||||
473 | pop(JSStackFrameRegister); | - | ||||||
474 | pop(addressTempRegister); | - | ||||||
475 | pop(AccumulatorRegisterTag); | - | ||||||
476 | pop(AccumulatorRegisterValue); | - | ||||||
477 | pop(); // exceptionHandler | - | ||||||
478 | pop(FramePointerRegister); | - | ||||||
479 | pop(JSC::ARMRegisters::lr); | - | ||||||
480 | ret(); | - | ||||||
481 | } | - | ||||||
482 | - | |||||||
483 | void callAbsolute(const void *funcPtr) | - | ||||||
484 | { | - | ||||||
485 | move(TrustedImmPtr(funcPtr), dataTempRegister); | - | ||||||
486 | call(dataTempRegister); | - | ||||||
487 | } | - | ||||||
488 | - | |||||||
489 | void pushAligned(RegisterID reg) | - | ||||||
490 | { | - | ||||||
491 | subPtr(TrustedImm32(PointerSize), StackPointerRegister); | - | ||||||
492 | push(reg); | - | ||||||
493 | } | - | ||||||
494 | - | |||||||
495 | void popAligned(RegisterID reg) | - | ||||||
496 | { | - | ||||||
497 | pop(reg); | - | ||||||
498 | addPtr(TrustedImm32(PointerSize), StackPointerRegister); | - | ||||||
499 | } | - | ||||||
500 | }; | - | ||||||
501 | - | |||||||
502 | typedef PlatformAssembler_ARM32 PlatformAssemblerBase; | - | ||||||
503 | - | |||||||
504 | #endif | - | ||||||
505 | - | |||||||
506 | struct PlatformAssemblerCommon : PlatformAssemblerBase | - | ||||||
507 | { | - | ||||||
508 | const Value* constantTable; | - | ||||||
509 | struct JumpTarget { JSC::MacroAssemblerBase::Jump jump; int offset; }; | - | ||||||
510 | std::vector<JumpTarget> patches; | - | ||||||
511 | struct ExceptionHanlderTarget { JSC::MacroAssemblerBase::DataLabelPtr label; int offset; }; | - | ||||||
512 | std::vector<ExceptionHanlderTarget> ehTargets; | - | ||||||
513 | QHash<int, JSC::MacroAssemblerBase::Label> labelsByOffset; | - | ||||||
514 | QHash<const void *, const char *> functions; | - | ||||||
515 | std::vector<Jump> catchyJumps; | - | ||||||
516 | Label functionExit; | - | ||||||
517 | - | |||||||
518 | Address exceptionHandlerAddress() const | - | ||||||
519 | { | - | ||||||
520 | return Address(FramePointerRegister, -1 * PointerSize); executed 13338 times by 64 tests: return Address(FramePointerRegister, -1 * PointerSize); Executed by:
| 13338 | ||||||
521 | } | - | ||||||
522 | - | |||||||
523 | Address contextAddress() const | - | ||||||
524 | { | - | ||||||
525 | return Address(JSStackFrameRegister, offsetof(CallData, context)); executed 50 times by 7 tests: return Address(JSStackFrameRegister, __builtin_offsetof ( CallData , context ) ); Executed by:
| 50 | ||||||
526 | } | - | ||||||
527 | - | |||||||
528 | RegisterID registerForArg(int arg) const | - | ||||||
529 | { | - | ||||||
530 | Q_ASSERT(arg >= 0); | - | ||||||
531 | Q_ASSERT(arg < ArgInRegCount); | - | ||||||
532 | switch (arg) { | - | ||||||
533 | case 0: return Arg0Reg; executed 83222 times by 64 tests: return Arg0Reg; Executed by:
executed 83222 times by 64 tests: case 0: Executed by:
| 83222 | ||||||
534 | case 1: return Arg1Reg; executed 52300 times by 64 tests: return Arg1Reg; Executed by:
executed 52300 times by 64 tests: case 1: Executed by:
| 52300 | ||||||
535 | case 2: return Arg2Reg; executed 33090 times by 61 tests: return Arg2Reg; Executed by:
executed 33090 times by 61 tests: case 2: Executed by:
| 33090 | ||||||
536 | case 3: return Arg3Reg; executed 10966 times by 54 tests: return Arg3Reg; Executed by:
executed 10966 times by 54 tests: case 3: Executed by:
| 10966 | ||||||
537 | case 4: return Arg4Reg; executed 4376 times by 34 tests: return Arg4Reg; Executed by:
executed 4376 times by 34 tests: case 4: Executed by:
| 4376 | ||||||
538 | case 5: return Arg5Reg; never executed: return Arg5Reg; never executed: case 5: | 0 | ||||||
539 | case 6: return Arg6Reg; never executed: return Arg6Reg; never executed: case 6: | 0 | ||||||
540 | case 7: return Arg7Reg; never executed: return Arg7Reg; never executed: case 7: | 0 | ||||||
541 | default: never executed: default: | 0 | ||||||
542 | Q_UNIMPLEMENTED(); | - | ||||||
543 | Q_UNREACHABLE(); | - | ||||||
544 | } never executed: end of block | 0 | ||||||
545 | } | - | ||||||
546 | - | |||||||
547 | void callRuntime(const char *functionName, const void *funcPtr) | - | ||||||
548 | { | - | ||||||
549 | functions.insert(funcPtr, functionName); | - | ||||||
550 | callAbsolute(funcPtr); | - | ||||||
551 | } executed 83222 times by 64 tests: end of block Executed by:
| 83222 | ||||||
552 | - | |||||||
553 | Address loadFunctionPtr(RegisterID target) | - | ||||||
554 | { | - | ||||||
555 | Address addr(CppStackFrameRegister, offsetof(CppStackFrame, v4Function)); | - | ||||||
556 | loadPtr(addr, target); | - | ||||||
557 | return Address(target); executed 4388 times by 40 tests: return Address(target); Executed by:
| 4388 | ||||||
558 | } | - | ||||||
559 | - | |||||||
560 | Address loadCompilationUnitPtr(RegisterID target) | - | ||||||
561 | { | - | ||||||
562 | Address addr = loadFunctionPtr(target); | - | ||||||
563 | addr.offset = offsetof(QV4::Function, compilationUnit); | - | ||||||
564 | loadPtr(addr, target); | - | ||||||
565 | return Address(target); executed 4348 times by 39 tests: return Address(target); Executed by:
| 4348 | ||||||
566 | } | - | ||||||
567 | - | |||||||
568 | Address loadConstAddress(int constIndex, RegisterID baseReg = ScratchRegister) | - | ||||||
569 | { | - | ||||||
570 | Address addr = loadCompilationUnitPtr(baseReg); | - | ||||||
571 | addr.offset = offsetof(QV4::CompiledData::CompilationUnitBase, constants); | - | ||||||
572 | loadPtr(addr, baseReg); | - | ||||||
573 | addr.offset = constIndex * int(sizeof(QV4::Value)); | - | ||||||
574 | return addr; executed 1062 times by 20 tests: return addr; Executed by:
| 1062 | ||||||
575 | } | - | ||||||
576 | - | |||||||
577 | Address loadStringAddress(int stringId) | - | ||||||
578 | { | - | ||||||
579 | Address addr = loadCompilationUnitPtr(ScratchRegister); | - | ||||||
580 | addr.offset = offsetof(QV4::CompiledData::CompilationUnitBase, runtimeStrings); | - | ||||||
581 | loadPtr(addr, ScratchRegister); | - | ||||||
582 | return Address(ScratchRegister, stringId * PointerSize); executed 3286 times by 31 tests: return Address(ScratchRegister, stringId * PointerSize); Executed by:
| 3286 | ||||||
583 | } | - | ||||||
584 | - | |||||||
585 | void passAsArg(RegisterID src, int arg) | - | ||||||
586 | { | - | ||||||
587 | move(src, registerForArg(arg)); | - | ||||||
588 | } executed 614 times by 15 tests: end of block Executed by:
| 614 | ||||||
589 | - | |||||||
590 | void generateCatchTrampoline(std::function<void()> loadUndefined) | - | ||||||
591 | { | - | ||||||
592 | for (Jump j : catchyJumps) | - | ||||||
593 | j.link(this); executed 52704 times by 63 tests: j.link(this); Executed by:
| 52704 | ||||||
594 | - | |||||||
595 | loadPtr(exceptionHandlerAddress(), ScratchRegister); | - | ||||||
596 | Jump exitFunction = branchPtr(Equal, ScratchRegister, TrustedImmPtr(0)); | - | ||||||
597 | jump(ScratchRegister); | - | ||||||
598 | exitFunction.link(this); | - | ||||||
599 | loadUndefined(); | - | ||||||
600 | - | |||||||
601 | if (functionExit.isSet())
| 0-13188 | ||||||
602 | jump(functionExit); executed 13188 times by 64 tests: jump(functionExit); Executed by:
| 13188 | ||||||
603 | else | - | ||||||
604 | generateFunctionExit(); never executed: generateFunctionExit(); | 0 | ||||||
605 | } | - | ||||||
606 | - | |||||||
607 | void addCatchyJump(Jump j) | - | ||||||
608 | { | - | ||||||
609 | Q_ASSERT(j.isSet()); | - | ||||||
610 | catchyJumps.push_back(j); | - | ||||||
611 | } executed 52704 times by 63 tests: end of block Executed by:
| 52704 | ||||||
612 | - | |||||||
613 | void generateFunctionEntry() | - | ||||||
614 | { | - | ||||||
615 | generatePlatformFunctionEntry(); | - | ||||||
616 | loadPtr(Address(CppStackFrameRegister, offsetof(CppStackFrame, jsFrame)), JSStackFrameRegister); | - | ||||||
617 | } executed 13188 times by 64 tests: end of block Executed by:
| 13188 | ||||||
618 | - | |||||||
619 | void generateFunctionExit() | - | ||||||
620 | { | - | ||||||
621 | if (functionExit.isSet()) {
| 216-13188 | ||||||
622 | jump(functionExit); | - | ||||||
623 | return; executed 216 times by 8 tests: return; Executed by:
| 216 | ||||||
624 | } | - | ||||||
625 | - | |||||||
626 | functionExit = label(); | - | ||||||
627 | generatePlatformFunctionExit(); | - | ||||||
628 | } executed 13188 times by 64 tests: end of block Executed by:
| 13188 | ||||||
629 | }; | - | ||||||
630 | - | |||||||
631 | #if QT_POINTER_SIZE == 8 || defined(ENABLE_ALL_ASSEMBLERS_FOR_REFACTORING_PURPOSES) | - | ||||||
632 | struct PlatformAssembler64 : PlatformAssemblerCommon | - | ||||||
633 | { | - | ||||||
634 | void callRuntime(const char *functionName, const void *funcPtr, | - | ||||||
635 | Assembler::CallResultDestination dest) | - | ||||||
636 | { | - | ||||||
637 | PlatformAssemblerCommon::callRuntime(functionName, funcPtr); | - | ||||||
638 | if (dest == Assembler::ResultInAccumulator)
| 1936-76834 | ||||||
639 | saveReturnValueInAccumulator(); executed 76834 times by 64 tests: saveReturnValueInAccumulator(); Executed by:
| 76834 | ||||||
640 | } executed 78770 times by 64 tests: end of block Executed by:
| 78770 | ||||||
641 | - | |||||||
642 | void saveReturnValueInAccumulator() | - | ||||||
643 | { | - | ||||||
644 | move(ReturnValueRegister, AccumulatorRegister); | - | ||||||
645 | } executed 77464 times by 64 tests: end of block Executed by:
| 77464 | ||||||
646 | - | |||||||
647 | void loadUndefined(RegisterID dest = AccumulatorRegister) | - | ||||||
648 | { | - | ||||||
649 | move(TrustedImm64(0), dest); | - | ||||||
650 | } executed 13216 times by 64 tests: end of block Executed by:
| 13216 | ||||||
651 | - | |||||||
652 | void copyConst(int constIndex, Address dest) | - | ||||||
653 | { | - | ||||||
654 | //### | - | ||||||
655 | if (constantTable[constIndex].isUndefined()) {
| 28-936 | ||||||
656 | loadUndefined(ScratchRegister); | - | ||||||
657 | } else { executed 28 times by 1 test: end of block Executed by:
| 28 | ||||||
658 | load64(loadConstAddress(constIndex, ScratchRegister), ScratchRegister); | - | ||||||
659 | } executed 936 times by 18 tests: end of block Executed by:
| 936 | ||||||
660 | store64(ScratchRegister, dest); | - | ||||||
661 | } executed 964 times by 18 tests: end of block Executed by:
| 964 | ||||||
662 | - | |||||||
663 | void copyReg(Address src, Address dst) | - | ||||||
664 | { | - | ||||||
665 | load64(src, ScratchRegister); | - | ||||||
666 | store64(ScratchRegister, dst); | - | ||||||
667 | } never executed: end of block | 0 | ||||||
668 | - | |||||||
669 | void loadPointerFromValue(Address addr, RegisterID dest = AccumulatorRegister) | - | ||||||
670 | { | - | ||||||
671 | load64(addr, dest); | - | ||||||
672 | } executed 610 times by 11 tests: end of block Executed by:
| 610 | ||||||
673 | - | |||||||
674 | void loadAccumulator(Address addr) | - | ||||||
675 | { | - | ||||||
676 | load64(addr, AccumulatorRegister); | - | ||||||
677 | } executed 6676 times by 43 tests: end of block Executed by:
| 6676 | ||||||
678 | - | |||||||
679 | void storeAccumulator(Address addr) | - | ||||||
680 | { | - | ||||||
681 | store64(AccumulatorRegister, addr); | - | ||||||
682 | } executed 79570 times by 64 tests: end of block Executed by:
| 79570 | ||||||
683 | - | |||||||
684 | void moveReg(Address sourceRegAddress, Address destRegAddress) | - | ||||||
685 | { | - | ||||||
686 | load64(sourceRegAddress, ScratchRegister); | - | ||||||
687 | store64(ScratchRegister, destRegAddress); | - | ||||||
688 | } executed 3186 times by 19 tests: end of block Executed by:
| 3186 | ||||||
689 | - | |||||||
690 | void loadString(int stringId) | - | ||||||
691 | { | - | ||||||
692 | loadAccumulator(loadStringAddress(stringId)); | - | ||||||
693 | } executed 3286 times by 31 tests: end of block Executed by:
| 3286 | ||||||
694 | - | |||||||
695 | void loadValue(ReturnedValue value) | - | ||||||
696 | { | - | ||||||
697 | move(TrustedImm64(value), AccumulatorRegister); | - | ||||||
698 | } executed 4828 times by 45 tests: end of block Executed by:
| 4828 | ||||||
699 | - | |||||||
700 | void storeHeapObject(RegisterID source, Address addr) | - | ||||||
701 | { | - | ||||||
702 | store64(source, addr); | - | ||||||
703 | } executed 154 times by 9 tests: end of block Executed by:
| 154 | ||||||
704 | - | |||||||
705 | void generateCatchTrampoline() | - | ||||||
706 | { | - | ||||||
707 | PlatformAssemblerCommon::generateCatchTrampoline([this](){loadUndefined();}); executed 13188 times by 64 tests: end of block Executed by:
| 13188 | ||||||
708 | } executed 13188 times by 64 tests: end of block Executed by:
| 13188 | ||||||
709 | - | |||||||
710 | void jumpNotUndefined(int offset) | - | ||||||
711 | { | - | ||||||
712 | auto jump = branch64(NotEqual, AccumulatorRegister, TrustedImm64(0)); | - | ||||||
713 | patches.push_back({ jump, offset }); | - | ||||||
714 | } never executed: end of block | 0 | ||||||
715 | - | |||||||
716 | Jump jumpEmpty() | - | ||||||
717 | { | - | ||||||
718 | return branch64(Equal, AccumulatorRegister, TrustedImm64(Primitive::emptyValue().asReturnedValue())); never executed: return branch64(Equal, AccumulatorRegister, TrustedImm64(Primitive::emptyValue().asReturnedValue())); | 0 | ||||||
719 | } | - | ||||||
720 | - | |||||||
721 | void toBoolean(std::function<void(RegisterID)> continuation) | - | ||||||
722 | { | - | ||||||
723 | urshift64(AccumulatorRegister, TrustedImm32(Value::IsIntegerConvertible_Shift), ScratchRegister); | - | ||||||
724 | auto needsConversion = branch32(NotEqual, TrustedImm32(1), ScratchRegister); | - | ||||||
725 | continuation(AccumulatorRegister); | - | ||||||
726 | Jump done = jump(); | - | ||||||
727 | - | |||||||
728 | // slow path: | - | ||||||
729 | needsConversion.link(this); | - | ||||||
730 | push(AccumulatorRegister); | - | ||||||
731 | move(AccumulatorRegister, registerForArg(0)); | - | ||||||
732 | callHelper(Value::toBooleanImpl); | - | ||||||
733 | and32(TrustedImm32(1), ReturnValueRegister, ScratchRegister); | - | ||||||
734 | pop(AccumulatorRegister); | - | ||||||
735 | continuation(ScratchRegister); | - | ||||||
736 | - | |||||||
737 | done.link(this); | - | ||||||
738 | } executed 3808 times by 38 tests: end of block Executed by:
| 3808 | ||||||
739 | - | |||||||
740 | void toNumber() | - | ||||||
741 | { | - | ||||||
742 | urshift64(AccumulatorRegister, TrustedImm32(Value::QuickType_Shift), ScratchRegister); | - | ||||||
743 | auto isNumber = branch32(GreaterThanOrEqual, ScratchRegister, TrustedImm32(Value::QT_Int)); | - | ||||||
744 | - | |||||||
745 | move(AccumulatorRegister, registerForArg(0)); | - | ||||||
746 | callHelper(toNumberHelper); | - | ||||||
747 | saveReturnValueInAccumulator(); | - | ||||||
748 | - | |||||||
749 | isNumber.link(this); | - | ||||||
750 | } executed 2 times by 1 test: end of block Executed by:
| 2 | ||||||
751 | - | |||||||
752 | void toInt32LhsAcc(Address lhs, RegisterID lhsTarget) | - | ||||||
753 | { | - | ||||||
754 | load64(lhs, lhsTarget); | - | ||||||
755 | urshift64(lhsTarget, TrustedImm32(Value::QuickType_Shift), ScratchRegister2); | - | ||||||
756 | auto lhsIsInt = branch32(Equal, TrustedImm32(Value::QT_Int), ScratchRegister2); | - | ||||||
757 | - | |||||||
758 | pushAligned(AccumulatorRegister); | - | ||||||
759 | move(lhsTarget, registerForArg(0)); | - | ||||||
760 | callHelper(toInt32Helper); | - | ||||||
761 | move(ReturnValueRegister, lhsTarget); | - | ||||||
762 | popAligned(AccumulatorRegister); | - | ||||||
763 | - | |||||||
764 | lhsIsInt.link(this); | - | ||||||
765 | urshift64(AccumulatorRegister, TrustedImm32(Value::QuickType_Shift), ScratchRegister2); | - | ||||||
766 | auto isInt = branch32(Equal, TrustedImm32(Value::QT_Int), ScratchRegister2); | - | ||||||
767 | - | |||||||
768 | pushAligned(lhsTarget); | - | ||||||
769 | move(AccumulatorRegister, registerForArg(0)); | - | ||||||
770 | callHelper(toInt32Helper); | - | ||||||
771 | saveReturnValueInAccumulator(); | - | ||||||
772 | popAligned(lhsTarget); | - | ||||||
773 | - | |||||||
774 | isInt.link(this); | - | ||||||
775 | } executed 14 times by 1 test: end of block Executed by:
| 14 | ||||||
776 | - | |||||||
777 | void toInt32() | - | ||||||
778 | { | - | ||||||
779 | urshift64(AccumulatorRegister, TrustedImm32(Value::QuickType_Shift), ScratchRegister2); | - | ||||||
780 | auto isInt = branch32(Equal, TrustedImm32(Value::QT_Int), ScratchRegister2); | - | ||||||
781 | - | |||||||
782 | move(AccumulatorRegister, registerForArg(0)); | - | ||||||
783 | callRuntime("toInt32Helper", reinterpret_cast<void *>(&toInt32Helper), | - | ||||||
784 | Assembler::ResultInAccumulator); | - | ||||||
785 | - | |||||||
786 | isInt.link(this); | - | ||||||
787 | } executed 4 times by 1 test: end of block Executed by:
| 4 | ||||||
788 | - | |||||||
789 | void regToInt32(Address srcReg, RegisterID targetReg) | - | ||||||
790 | { | - | ||||||
791 | load64(srcReg, targetReg); | - | ||||||
792 | urshift64(targetReg, TrustedImm32(Value::QuickType_Shift), ScratchRegister2); | - | ||||||
793 | auto isInt = branch32(Equal, TrustedImm32(Value::QT_Int), ScratchRegister2); | - | ||||||
794 | - | |||||||
795 | pushAligned(AccumulatorRegister); | - | ||||||
796 | move(targetReg, registerForArg(0)); | - | ||||||
797 | callHelper(toInt32Helper); | - | ||||||
798 | move(ReturnValueRegister, targetReg); | - | ||||||
799 | popAligned(AccumulatorRegister); | - | ||||||
800 | - | |||||||
801 | isInt.link(this); | - | ||||||
802 | } never executed: end of block | 0 | ||||||
803 | - | |||||||
804 | void isNullOrUndefined() | - | ||||||
805 | { | - | ||||||
806 | move(AccumulatorRegister, ScratchRegister); | - | ||||||
807 | compare64(Equal, ScratchRegister, TrustedImm32(0), AccumulatorRegister); | - | ||||||
808 | Jump isUndef = branch32(NotEqual, TrustedImm32(0), AccumulatorRegister); | - | ||||||
809 | - | |||||||
810 | // not undefined | - | ||||||
811 | rshift64(TrustedImm32(32), ScratchRegister); | - | ||||||
812 | compare32(Equal, ScratchRegister, TrustedImm32(int(QV4::Value::ValueTypeInternal::Null)), | - | ||||||
813 | AccumulatorRegister); | - | ||||||
814 | - | |||||||
815 | isUndef.link(this); | - | ||||||
816 | } executed 8 times by 1 test: end of block Executed by:
| 8 | ||||||
817 | - | |||||||
818 | Jump isIntOrBool() | - | ||||||
819 | { | - | ||||||
820 | urshift64(AccumulatorRegister, TrustedImm32(Value::IsIntegerOrBool_Shift), ScratchRegister); | - | ||||||
821 | return branch32(Equal, TrustedImm32(3), ScratchRegister); executed 70 times by 10 tests: return branch32(Equal, TrustedImm32(3), ScratchRegister); Executed by:
| 70 | ||||||
822 | } | - | ||||||
823 | - | |||||||
824 | void setAccumulatorTag(QV4::Value::ValueTypeInternal tag, RegisterID sourceReg = NoRegister) | - | ||||||
825 | { | - | ||||||
826 | if (sourceReg == NoRegister)
| 4326-4924 | ||||||
827 | or64(TrustedImm64(int64_t(tag) << 32), AccumulatorRegister); executed 4924 times by 34 tests: or64(TrustedImm64(int64_t(tag) << 32), AccumulatorRegister); Executed by:
| 4924 | ||||||
828 | else | - | ||||||
829 | or64(TrustedImm64(int64_t(tag) << 32), sourceReg, AccumulatorRegister); executed 4326 times by 39 tests: or64(TrustedImm64(int64_t(tag) << 32), sourceReg, AccumulatorRegister); Executed by:
| 4326 | ||||||
830 | } | - | ||||||
831 | - | |||||||
832 | void encodeDoubleIntoAccumulator(FPRegisterID src) | - | ||||||
833 | { | - | ||||||
834 | moveDoubleTo64(src, AccumulatorRegister); | - | ||||||
835 | move(TrustedImm64(Value::NaNEncodeMask), ScratchRegister); | - | ||||||
836 | xor64(ScratchRegister, AccumulatorRegister); | - | ||||||
837 | } never executed: end of block | 0 | ||||||
838 | - | |||||||
839 | void pushValueAligned(ReturnedValue v) | - | ||||||
840 | { | - | ||||||
841 | loadValue(v); | - | ||||||
842 | pushAligned(AccumulatorRegister); | - | ||||||
843 | } executed 70 times by 10 tests: end of block Executed by:
| 70 | ||||||
844 | - | |||||||
845 | void popValueAligned() | - | ||||||
846 | { | - | ||||||
847 | addPtr(TrustedImm32(2 * PointerSize), StackPointerRegister); | - | ||||||
848 | } executed 70 times by 10 tests: end of block Executed by:
| 70 | ||||||
849 | - | |||||||
850 | Jump binopBothIntPath(Address lhsAddr, std::function<Jump(void)> fastPath) | - | ||||||
851 | { | - | ||||||
852 | urshift64(AccumulatorRegister, TrustedImm32(32), ScratchRegister); | - | ||||||
853 | Jump accNotInt = branch32(NotEqual, TrustedImm32(int(IntegerTag)), ScratchRegister); | - | ||||||
854 | load64(lhsAddr, ScratchRegister); | - | ||||||
855 | urshift64(ScratchRegister, TrustedImm32(32), ScratchRegister2); | - | ||||||
856 | Jump lhsNotInt = branch32(NotEqual, TrustedImm32(int(IntegerTag)), ScratchRegister2); | - | ||||||
857 | - | |||||||
858 | // both integer | - | ||||||
859 | Jump failure = fastPath(); | - | ||||||
860 | Jump done = jump(); | - | ||||||
861 | - | |||||||
862 | // all other cases | - | ||||||
863 | if (failure.isSet())
| 2256-3712 | ||||||
864 | failure.link(this); executed 3712 times by 35 tests: failure.link(this); Executed by:
| 3712 | ||||||
865 | accNotInt.link(this); | - | ||||||
866 | lhsNotInt.link(this); | - | ||||||
867 | - | |||||||
868 | return done; executed 5968 times by 47 tests: return done; Executed by:
| 5968 | ||||||
869 | } | - | ||||||
870 | - | |||||||
871 | Jump unopIntPath(std::function<Jump(void)> fastPath) | - | ||||||
872 | { | - | ||||||
873 | urshift64(AccumulatorRegister, TrustedImm32(Value::IsIntegerConvertible_Shift), ScratchRegister); | - | ||||||
874 | Jump accNotIntConvertible = branch32(NotEqual, TrustedImm32(1), ScratchRegister); | - | ||||||
875 | - | |||||||
876 | // both integer | - | ||||||
877 | Jump failure = fastPath(); | - | ||||||
878 | Jump done = jump(); | - | ||||||
879 | - | |||||||
880 | // all other cases | - | ||||||
881 | if (failure.isSet())
| 0-614 | ||||||
882 | failure.link(this); executed 614 times by 15 tests: failure.link(this); Executed by:
| 614 | ||||||
883 | accNotIntConvertible.link(this); | - | ||||||
884 | - | |||||||
885 | return done; executed 614 times by 15 tests: return done; Executed by:
| 614 | ||||||
886 | } | - | ||||||
887 | - | |||||||
888 | void callWithAccumulatorByValueAsFirstArgument(std::function<void()> doCall) | - | ||||||
889 | { | - | ||||||
890 | passAsArg(AccumulatorRegister, 0); | - | ||||||
891 | doCall(); | - | ||||||
892 | } executed 614 times by 15 tests: end of block Executed by:
| 614 | ||||||
893 | }; | - | ||||||
894 | - | |||||||
895 | typedef PlatformAssembler64 PlatformAssembler; | - | ||||||
896 | #endif | - | ||||||
897 | - | |||||||
898 | #if QT_POINTER_SIZE == 4 || defined(ENABLE_ALL_ASSEMBLERS_FOR_REFACTORING_PURPOSES) | - | ||||||
899 | struct PlatformAssembler32 : PlatformAssemblerCommon | - | ||||||
900 | { | - | ||||||
901 | void callRuntime(const char *functionName, const void *funcPtr, | - | ||||||
902 | Assembler::CallResultDestination dest) | - | ||||||
903 | { | - | ||||||
904 | PlatformAssemblerCommon::callRuntime(functionName, funcPtr); | - | ||||||
905 | if (dest == Assembler::ResultInAccumulator) | - | ||||||
906 | saveReturnValueInAccumulator(); | - | ||||||
907 | } | - | ||||||
908 | - | |||||||
909 | void saveReturnValueInAccumulator() | - | ||||||
910 | { | - | ||||||
911 | move(ReturnValueRegisterValue, AccumulatorRegisterValue); | - | ||||||
912 | move(ReturnValueRegisterTag, AccumulatorRegisterTag); | - | ||||||
913 | } | - | ||||||
914 | - | |||||||
915 | void loadUndefined() | - | ||||||
916 | { | - | ||||||
917 | move(TrustedImm32(0), AccumulatorRegisterValue); | - | ||||||
918 | move(TrustedImm32(0), AccumulatorRegisterTag); | - | ||||||
919 | } | - | ||||||
920 | - | |||||||
921 | void copyConst(int constIndex, Address destRegAddr) | - | ||||||
922 | { | - | ||||||
923 | //### | - | ||||||
924 | if (constantTable[constIndex].isUndefined()) { | - | ||||||
925 | move(TrustedImm32(0), ScratchRegister); | - | ||||||
926 | store32(ScratchRegister, destRegAddr); | - | ||||||
927 | destRegAddr.offset += 4; | - | ||||||
928 | store32(ScratchRegister, destRegAddr); | - | ||||||
929 | } else { | - | ||||||
930 | Address src = loadConstAddress(constIndex); | - | ||||||
931 | loadDouble(src, FPScratchRegister); | - | ||||||
932 | storeDouble(FPScratchRegister, destRegAddr); | - | ||||||
933 | } | - | ||||||
934 | } | - | ||||||
935 | - | |||||||
936 | void copyReg(Address src, Address dest) | - | ||||||
937 | { | - | ||||||
938 | loadDouble(src, FPScratchRegister); | - | ||||||
939 | storeDouble(FPScratchRegister, dest); | - | ||||||
940 | } | - | ||||||
941 | - | |||||||
942 | void loadPointerFromValue(Address addr, RegisterID dest = AccumulatorRegisterValue) | - | ||||||
943 | { | - | ||||||
944 | load32(addr, dest); | - | ||||||
945 | } | - | ||||||
946 | - | |||||||
947 | void loadAccumulator(Address src) | - | ||||||
948 | { | - | ||||||
949 | load32(src, AccumulatorRegisterValue); | - | ||||||
950 | src.offset += 4; | - | ||||||
951 | load32(src, AccumulatorRegisterTag); | - | ||||||
952 | } | - | ||||||
953 | - | |||||||
954 | void storeAccumulator(Address addr) | - | ||||||
955 | { | - | ||||||
956 | store32(AccumulatorRegisterValue, addr); | - | ||||||
957 | addr.offset += 4; | - | ||||||
958 | store32(AccumulatorRegisterTag, addr); | - | ||||||
959 | } | - | ||||||
960 | - | |||||||
961 | void moveReg(Address sourceRegAddress, Address destRegAddress) | - | ||||||
962 | { | - | ||||||
963 | load32(sourceRegAddress, ReturnValueRegisterValue); | - | ||||||
964 | sourceRegAddress.offset += 4; | - | ||||||
965 | load32(sourceRegAddress, ReturnValueRegisterTag); | - | ||||||
966 | store32(ReturnValueRegisterValue, destRegAddress); | - | ||||||
967 | destRegAddress.offset += 4; | - | ||||||
968 | store32(ReturnValueRegisterTag, destRegAddress); | - | ||||||
969 | } | - | ||||||
970 | - | |||||||
971 | void loadString(int stringId) | - | ||||||
972 | { | - | ||||||
973 | load32(loadStringAddress(stringId), AccumulatorRegisterValue); | - | ||||||
974 | move(TrustedImm32(0), AccumulatorRegisterTag); | - | ||||||
975 | } | - | ||||||
976 | - | |||||||
977 | void loadValue(ReturnedValue value) | - | ||||||
978 | { | - | ||||||
979 | move(TrustedImm32(Value::fromReturnedValue(value).value()), AccumulatorRegisterValue); | - | ||||||
980 | move(TrustedImm32(Value::fromReturnedValue(value).tag()), AccumulatorRegisterTag); | - | ||||||
981 | } | - | ||||||
982 | - | |||||||
983 | void storeHeapObject(RegisterID source, Address addr) | - | ||||||
984 | { | - | ||||||
985 | store32(source, addr); | - | ||||||
986 | addr.offset += 4; | - | ||||||
987 | store32(TrustedImm32(0), addr); | - | ||||||
988 | } | - | ||||||
989 | - | |||||||
990 | - | |||||||
991 | void generateCatchTrampoline() | - | ||||||
992 | { | - | ||||||
993 | PlatformAssemblerCommon::generateCatchTrampoline([this](){loadUndefined();}); | - | ||||||
994 | } | - | ||||||
995 | - | |||||||
996 | void toNumber() | - | ||||||
997 | { | - | ||||||
998 | urshift32(AccumulatorRegisterTag, TrustedImm32(Value::QuickType_Shift - 32), ScratchRegister); | - | ||||||
999 | auto isNumber = branch32(GreaterThanOrEqual, ScratchRegister, TrustedImm32(Value::QT_Int)); | - | ||||||
1000 | - | |||||||
1001 | if (ArgInRegCount < 2) { | - | ||||||
1002 | push(AccumulatorRegisterTag); | - | ||||||
1003 | push(AccumulatorRegisterValue); | - | ||||||
1004 | } else { | - | ||||||
1005 | move(AccumulatorRegisterValue, registerForArg(0)); | - | ||||||
1006 | move(AccumulatorRegisterTag, registerForArg(1)); | - | ||||||
1007 | } | - | ||||||
1008 | callRuntime("toNumberHelper", reinterpret_cast<void *>(&toNumberHelper), | - | ||||||
1009 | Assembler::ResultInAccumulator); | - | ||||||
1010 | saveReturnValueInAccumulator(); | - | ||||||
1011 | if (ArgInRegCount < 2) | - | ||||||
1012 | addPtr(TrustedImm32(2 * PointerSize), StackPointerRegister); | - | ||||||
1013 | - | |||||||
1014 | isNumber.link(this); | - | ||||||
1015 | } | - | ||||||
1016 | - | |||||||
1017 | void toInt32LhsAcc(Address lhs, RegisterID lhsTarget) | - | ||||||
1018 | { | - | ||||||
1019 | bool accumulatorNeedsSaving = AccumulatorRegisterValue == ReturnValueRegisterValue | - | ||||||
1020 | || AccumulatorRegisterTag == ReturnValueRegisterTag; | - | ||||||
1021 | lhs.offset += 4; | - | ||||||
1022 | load32(lhs, lhsTarget); | - | ||||||
1023 | lhs.offset -= 4; | - | ||||||
1024 | auto lhsIsNotInt = branch32(NotEqual, TrustedImm32(int(IntegerTag)), lhsTarget); | - | ||||||
1025 | load32(lhs, lhsTarget); | - | ||||||
1026 | auto lhsIsInt = jump(); | - | ||||||
1027 | - | |||||||
1028 | lhsIsNotInt.link(this); | - | ||||||
1029 | if (accumulatorNeedsSaving) { | - | ||||||
1030 | push(AccumulatorRegisterTag); | - | ||||||
1031 | push(AccumulatorRegisterValue); | - | ||||||
1032 | } | - | ||||||
1033 | if (ArgInRegCount < 2) { | - | ||||||
1034 | push(lhsTarget); | - | ||||||
1035 | load32(lhs, lhsTarget); | - | ||||||
1036 | push(lhsTarget); | - | ||||||
1037 | } else { | - | ||||||
1038 | move(lhsTarget, registerForArg(1)); | - | ||||||
1039 | load32(lhs, registerForArg(0)); | - | ||||||
1040 | } | - | ||||||
1041 | callHelper(toInt32Helper); | - | ||||||
1042 | move(ReturnValueRegisterValue, lhsTarget); | - | ||||||
1043 | if (ArgInRegCount < 2) | - | ||||||
1044 | addPtr(TrustedImm32(2 * PointerSize), StackPointerRegister); | - | ||||||
1045 | if (accumulatorNeedsSaving) { | - | ||||||
1046 | pop(AccumulatorRegisterValue); | - | ||||||
1047 | pop(AccumulatorRegisterTag); | - | ||||||
1048 | } | - | ||||||
1049 | lhsIsInt.link(this); | - | ||||||
1050 | - | |||||||
1051 | auto rhsIsInt = branch32(Equal, TrustedImm32(int(IntegerTag)), AccumulatorRegisterTag); | - | ||||||
1052 | - | |||||||
1053 | pushAligned(lhsTarget); | - | ||||||
1054 | if (ArgInRegCount < 2) { | - | ||||||
1055 | push(AccumulatorRegisterTag); | - | ||||||
1056 | push(AccumulatorRegisterValue); | - | ||||||
1057 | } else { | - | ||||||
1058 | move(AccumulatorRegisterValue, registerForArg(0)); | - | ||||||
1059 | move(AccumulatorRegisterTag, registerForArg(1)); | - | ||||||
1060 | } | - | ||||||
1061 | callRuntime("toInt32Helper", reinterpret_cast<void *>(&toInt32Helper), | - | ||||||
1062 | Assembler::ResultInAccumulator); | - | ||||||
1063 | if (ArgInRegCount < 2) | - | ||||||
1064 | addPtr(TrustedImm32(2 * PointerSize), StackPointerRegister); | - | ||||||
1065 | popAligned(lhsTarget); | - | ||||||
1066 | - | |||||||
1067 | rhsIsInt.link(this); | - | ||||||
1068 | } | - | ||||||
1069 | - | |||||||
1070 | void toInt32() | - | ||||||
1071 | { | - | ||||||
1072 | urshift32(AccumulatorRegisterTag, TrustedImm32(Value::QuickType_Shift - 32), ScratchRegister); | - | ||||||
1073 | auto isInt = branch32(Equal, TrustedImm32(Value::QT_Int), ScratchRegister); | - | ||||||
1074 | - | |||||||
1075 | if (ArgInRegCount < 2) { | - | ||||||
1076 | push(AccumulatorRegisterTag); | - | ||||||
1077 | push(AccumulatorRegisterValue); | - | ||||||
1078 | } else { | - | ||||||
1079 | move(AccumulatorRegisterValue, registerForArg(0)); | - | ||||||
1080 | move(AccumulatorRegisterTag, registerForArg(1)); | - | ||||||
1081 | } | - | ||||||
1082 | callRuntime("toInt32Helper", reinterpret_cast<void *>(&toInt32Helper), | - | ||||||
1083 | Assembler::ResultInAccumulator); | - | ||||||
1084 | if (ArgInRegCount < 2) | - | ||||||
1085 | addPtr(TrustedImm32(2 * PointerSize), StackPointerRegister); | - | ||||||
1086 | - | |||||||
1087 | isInt.link(this); | - | ||||||
1088 | } | - | ||||||
1089 | - | |||||||
1090 | void regToInt32(Address srcReg, RegisterID targetReg) | - | ||||||
1091 | { | - | ||||||
1092 | bool accumulatorNeedsSaving = AccumulatorRegisterValue == ReturnValueRegisterValue | - | ||||||
1093 | || AccumulatorRegisterTag == ReturnValueRegisterTag; | - | ||||||
1094 | if (accumulatorNeedsSaving) { | - | ||||||
1095 | push(AccumulatorRegisterTag); | - | ||||||
1096 | push(AccumulatorRegisterValue); | - | ||||||
1097 | } | - | ||||||
1098 | if (ArgInRegCount < 2) { | - | ||||||
1099 | srcReg.offset += 4; | - | ||||||
1100 | load32(srcReg, targetReg); | - | ||||||
1101 | push(targetReg); | - | ||||||
1102 | srcReg.offset -= 4; | - | ||||||
1103 | load32(srcReg, targetReg); | - | ||||||
1104 | push(targetReg); | - | ||||||
1105 | } else { | - | ||||||
1106 | load32(srcReg, registerForArg(0)); | - | ||||||
1107 | srcReg.offset += 4; | - | ||||||
1108 | load32(srcReg, registerForArg(1)); | - | ||||||
1109 | } | - | ||||||
1110 | callHelper(toInt32Helper); | - | ||||||
1111 | move(ReturnValueRegisterValue, targetReg); | - | ||||||
1112 | if (ArgInRegCount < 2) | - | ||||||
1113 | addPtr(TrustedImm32(2 * PointerSize), StackPointerRegister); | - | ||||||
1114 | if (accumulatorNeedsSaving) { | - | ||||||
1115 | pop(AccumulatorRegisterValue); | - | ||||||
1116 | pop(AccumulatorRegisterTag); | - | ||||||
1117 | } | - | ||||||
1118 | } | - | ||||||
1119 | - | |||||||
1120 | void isNullOrUndefined() | - | ||||||
1121 | { | - | ||||||
1122 | Jump notUndefOrPtr = branch32(NotEqual, TrustedImm32(0), AccumulatorRegisterTag); | - | ||||||
1123 | compare32(Equal, AccumulatorRegisterValue, TrustedImm32(0), AccumulatorRegisterValue); | - | ||||||
1124 | auto done = jump(); | - | ||||||
1125 | - | |||||||
1126 | // not undefined or managed | - | ||||||
1127 | notUndefOrPtr.link(this); | - | ||||||
1128 | compare32(Equal, AccumulatorRegisterTag, TrustedImm32(int(QV4::Value::ValueTypeInternal::Null)), | - | ||||||
1129 | AccumulatorRegisterValue); | - | ||||||
1130 | - | |||||||
1131 | done.link(this); | - | ||||||
1132 | } | - | ||||||
1133 | - | |||||||
1134 | Jump isIntOrBool() | - | ||||||
1135 | { | - | ||||||
1136 | urshift32(AccumulatorRegisterTag, TrustedImm32(Value::IsIntegerOrBool_Shift - 32), ScratchRegister); | - | ||||||
1137 | return branch32(Equal, TrustedImm32(3), ScratchRegister); | - | ||||||
1138 | } | - | ||||||
1139 | - | |||||||
1140 | void pushValue(ReturnedValue v) | - | ||||||
1141 | { | - | ||||||
1142 | push(TrustedImm32(v >> 32)); | - | ||||||
1143 | push(TrustedImm32(v)); | - | ||||||
1144 | } | - | ||||||
1145 | - | |||||||
1146 | void jumpNotUndefined(int offset) | - | ||||||
1147 | { | - | ||||||
1148 | move(AccumulatorRegisterTag, ScratchRegister); | - | ||||||
1149 | or32(AccumulatorRegisterValue, ScratchRegister); | - | ||||||
1150 | auto jump = branch32(NotEqual, ScratchRegister, TrustedImm32(0)); | - | ||||||
1151 | patches.push_back({ jump, offset }); | - | ||||||
1152 | } | - | ||||||
1153 | - | |||||||
1154 | Jump jumpEmpty() | - | ||||||
1155 | { | - | ||||||
1156 | return branch32(Equal, AccumulatorRegisterTag, TrustedImm32(Primitive::emptyValue().asReturnedValue() >> 32)); | - | ||||||
1157 | } | - | ||||||
1158 | - | |||||||
1159 | void toBoolean(std::function<void(RegisterID)> continuation) | - | ||||||
1160 | { | - | ||||||
1161 | urshift32(AccumulatorRegisterTag, TrustedImm32(Value::IsIntegerConvertible_Shift - 32), | - | ||||||
1162 | ScratchRegister); | - | ||||||
1163 | auto needsConversion = branch32(NotEqual, TrustedImm32(1), ScratchRegister); | - | ||||||
1164 | continuation(AccumulatorRegisterValue); | - | ||||||
1165 | Jump done = jump(); | - | ||||||
1166 | - | |||||||
1167 | // slow path: | - | ||||||
1168 | needsConversion.link(this); | - | ||||||
1169 | - | |||||||
1170 | bool accumulatorNeedsSaving = AccumulatorRegisterValue == ReturnValueRegisterValue | - | ||||||
1171 | || AccumulatorRegisterTag == ReturnValueRegisterTag; | - | ||||||
1172 | if (accumulatorNeedsSaving) { | - | ||||||
1173 | push(AccumulatorRegisterTag); | - | ||||||
1174 | push(AccumulatorRegisterValue); | - | ||||||
1175 | } | - | ||||||
1176 | - | |||||||
1177 | if (ArgInRegCount < 2) { | - | ||||||
1178 | push(AccumulatorRegisterTag); | - | ||||||
1179 | push(AccumulatorRegisterValue); | - | ||||||
1180 | } else { | - | ||||||
1181 | move(AccumulatorRegisterValue, registerForArg(0)); | - | ||||||
1182 | move(AccumulatorRegisterTag, registerForArg(1)); | - | ||||||
1183 | } | - | ||||||
1184 | callHelper(Value::toBooleanImpl); | - | ||||||
1185 | if (ArgInRegCount < 2) | - | ||||||
1186 | addPtr(TrustedImm32(2 * PointerSize), StackPointerRegister); | - | ||||||
1187 | - | |||||||
1188 | and32(TrustedImm32(1), ReturnValueRegisterValue, ScratchRegister); | - | ||||||
1189 | if (accumulatorNeedsSaving) { | - | ||||||
1190 | pop(AccumulatorRegisterValue); | - | ||||||
1191 | pop(AccumulatorRegisterTag); | - | ||||||
1192 | } | - | ||||||
1193 | continuation(ScratchRegister); | - | ||||||
1194 | - | |||||||
1195 | done.link(this); | - | ||||||
1196 | } | - | ||||||
1197 | - | |||||||
1198 | void setAccumulatorTag(QV4::Value::ValueTypeInternal tag, RegisterID sourceReg = NoRegister) | - | ||||||
1199 | { | - | ||||||
1200 | if (sourceReg != NoRegister) | - | ||||||
1201 | move(sourceReg, AccumulatorRegisterValue); | - | ||||||
1202 | move(TrustedImm32(int(tag)), AccumulatorRegisterTag); | - | ||||||
1203 | } | - | ||||||
1204 | - | |||||||
1205 | void encodeDoubleIntoAccumulator(FPRegisterID src) | - | ||||||
1206 | { | - | ||||||
1207 | moveDoubleToInts(src, AccumulatorRegisterValue, AccumulatorRegisterTag); | - | ||||||
1208 | xor32(TrustedImm32(Value::NaNEncodeMask >> 32), AccumulatorRegisterTag); | - | ||||||
1209 | } | - | ||||||
1210 | - | |||||||
1211 | void pushValueAligned(ReturnedValue v) | - | ||||||
1212 | { | - | ||||||
1213 | pushValue(v); | - | ||||||
1214 | } | - | ||||||
1215 | - | |||||||
1216 | void popValueAligned() | - | ||||||
1217 | { | - | ||||||
1218 | popValue(); | - | ||||||
1219 | } | - | ||||||
1220 | - | |||||||
1221 | Jump binopBothIntPath(Address lhsAddr, std::function<Jump(void)> fastPath) | - | ||||||
1222 | { | - | ||||||
1223 | Jump accNotInt = branch32(NotEqual, TrustedImm32(int(IntegerTag)), AccumulatorRegisterTag); | - | ||||||
1224 | Address lhsAddrTag = lhsAddr; lhsAddrTag.offset += Value::tagOffset(); | - | ||||||
1225 | load32(lhsAddrTag, ScratchRegister); | - | ||||||
1226 | Jump lhsNotInt = branch32(NotEqual, TrustedImm32(int(IntegerTag)), ScratchRegister); | - | ||||||
1227 | - | |||||||
1228 | // both integer | - | ||||||
1229 | Address lhsAddrValue = lhsAddr; lhsAddrValue.offset += Value::valueOffset(); | - | ||||||
1230 | load32(lhsAddrValue, ScratchRegister); | - | ||||||
1231 | Jump failure = fastPath(); | - | ||||||
1232 | Jump done = jump(); | - | ||||||
1233 | - | |||||||
1234 | // all other cases | - | ||||||
1235 | if (failure.isSet()) | - | ||||||
1236 | failure.link(this); | - | ||||||
1237 | accNotInt.link(this); | - | ||||||
1238 | lhsNotInt.link(this); | - | ||||||
1239 | - | |||||||
1240 | return done; | - | ||||||
1241 | } | - | ||||||
1242 | - | |||||||
1243 | Jump unopIntPath(std::function<Jump(void)> fastPath) | - | ||||||
1244 | { | - | ||||||
1245 | Jump accNotInt = branch32(NotEqual, TrustedImm32(int(IntegerTag)), AccumulatorRegisterTag); | - | ||||||
1246 | - | |||||||
1247 | // both integer | - | ||||||
1248 | Jump failure = fastPath(); | - | ||||||
1249 | Jump done = jump(); | - | ||||||
1250 | - | |||||||
1251 | // all other cases | - | ||||||
1252 | if (failure.isSet()) | - | ||||||
1253 | failure.link(this); | - | ||||||
1254 | accNotInt.link(this); | - | ||||||
1255 | - | |||||||
1256 | return done; | - | ||||||
1257 | } | - | ||||||
1258 | - | |||||||
1259 | void callWithAccumulatorByValueAsFirstArgument(std::function<void()> doCall) | - | ||||||
1260 | { | - | ||||||
1261 | if (ArgInRegCount < 2) { | - | ||||||
1262 | push(AccumulatorRegisterTag); | - | ||||||
1263 | push(AccumulatorRegisterValue); | - | ||||||
1264 | } else { | - | ||||||
1265 | move(AccumulatorRegisterValue, registerForArg(0)); | - | ||||||
1266 | move(AccumulatorRegisterTag, registerForArg(1)); | - | ||||||
1267 | } | - | ||||||
1268 | doCall(); | - | ||||||
1269 | if (ArgInRegCount < 2) | - | ||||||
1270 | addPtr(TrustedImm32(2 * PointerSize), StackPointerRegister); | - | ||||||
1271 | } | - | ||||||
1272 | }; | - | ||||||
1273 | - | |||||||
1274 | typedef PlatformAssembler32 PlatformAssembler; | - | ||||||
1275 | #endif | - | ||||||
1276 | - | |||||||
1277 | typedef PlatformAssembler::TrustedImmPtr TrustedImmPtr; | - | ||||||
1278 | typedef PlatformAssembler::TrustedImm32 TrustedImm32; | - | ||||||
1279 | typedef PlatformAssembler::TrustedImm64 TrustedImm64; | - | ||||||
1280 | typedef PlatformAssembler::Address Address; | - | ||||||
1281 | typedef PlatformAssembler::RegisterID RegisterID; | - | ||||||
1282 | typedef PlatformAssembler::FPRegisterID FPRegisterID; | - | ||||||
1283 | - | |||||||
1284 | #define pasm() reinterpret_cast<PlatformAssembler *>(this->d) | - | ||||||
1285 | - | |||||||
1286 | static Address regAddr(int reg) | - | ||||||
1287 | { | - | ||||||
1288 | return Address(PlatformAssembler::JSStackFrameRegister, reg * int(sizeof(QV4::Value))); executed 71850 times by 64 tests: return Address(PlatformAssembler::JSStackFrameRegister, reg * int(sizeof(QV4::Value))); Executed by:
| 71850 | ||||||
1289 | } | - | ||||||
1290 | - | |||||||
1291 | Assembler::Assembler(const Value *constantTable) | - | ||||||
1292 | : d(new PlatformAssembler) | - | ||||||
1293 | { | - | ||||||
1294 | pasm()->constantTable = constantTable; | - | ||||||
1295 | } executed 13188 times by 64 tests: end of block Executed by:
| 13188 | ||||||
1296 | - | |||||||
1297 | Assembler::~Assembler() | - | ||||||
1298 | { | - | ||||||
1299 | delete pasm(); | - | ||||||
1300 | } executed 13188 times by 64 tests: end of block Executed by:
| 13188 | ||||||
1301 | - | |||||||
1302 | void Assembler::generatePrologue() | - | ||||||
1303 | { | - | ||||||
1304 | pasm()->generateFunctionEntry(); | - | ||||||
1305 | } executed 13188 times by 64 tests: end of block Executed by:
| 13188 | ||||||
1306 | - | |||||||
1307 | void Assembler::generateEpilogue() | - | ||||||
1308 | { | - | ||||||
1309 | pasm()->generateCatchTrampoline(); | - | ||||||
1310 | } executed 13188 times by 64 tests: end of block Executed by:
| 13188 | ||||||
1311 | - | |||||||
1312 | namespace { | - | ||||||
1313 | class QIODevicePrintStream: public FilePrintStream | - | ||||||
1314 | { | - | ||||||
1315 | Q_DISABLE_COPY(QIODevicePrintStream) | - | ||||||
1316 | - | |||||||
1317 | public: | - | ||||||
1318 | explicit QIODevicePrintStream(QIODevice *dest) | - | ||||||
1319 | : FilePrintStream(nullptr) | - | ||||||
1320 | , dest(dest) | - | ||||||
1321 | , buf(4096, '0') | - | ||||||
1322 | { | - | ||||||
1323 | Q_ASSERT(dest); | - | ||||||
1324 | } never executed: end of block | 0 | ||||||
1325 | - | |||||||
1326 | ~QIODevicePrintStream() | - | ||||||
1327 | {} | - | ||||||
1328 | - | |||||||
1329 | void vprintf(const char* format, va_list argList) WTF_ATTRIBUTE_PRINTF(2, 0) | - | ||||||
1330 | { | - | ||||||
1331 | const int written = qvsnprintf(buf.data(), buf.size(), format, argList); | - | ||||||
1332 | if (written > 0)
| 0 | ||||||
1333 | dest->write(buf.constData(), written); never executed: dest->write(buf.constData(), written); | 0 | ||||||
1334 | memset(buf.data(), 0, qMin(written, buf.size())); | - | ||||||
1335 | } never executed: end of block | 0 | ||||||
1336 | - | |||||||
1337 | void flush() | - | ||||||
1338 | {} | - | ||||||
1339 | - | |||||||
1340 | private: | - | ||||||
1341 | QIODevice *dest; | - | ||||||
1342 | QByteArray buf; | - | ||||||
1343 | }; | - | ||||||
1344 | } // anonymous namespace | - | ||||||
1345 | - | |||||||
1346 | static void printDisassembledOutputWithCalls(QByteArray processedOutput, | - | ||||||
1347 | const QHash<const void*, const char*>& functions) | - | ||||||
1348 | { | - | ||||||
1349 | for (QHash<const void*, const char*>::ConstIterator it = functions.begin(), end = functions.end(); | - | ||||||
1350 | it != end; ++it) {
| 0 | ||||||
1351 | const QByteArray ptrString = "0x" + QByteArray::number(quintptr(it.key()), 16); | - | ||||||
1352 | int idx = 0; | - | ||||||
1353 | while (idx >= 0) {
| 0 | ||||||
1354 | idx = processedOutput.indexOf(ptrString, idx); | - | ||||||
1355 | if (idx < 0)
| 0 | ||||||
1356 | break; never executed: break; | 0 | ||||||
1357 | idx = processedOutput.indexOf('\n', idx); | - | ||||||
1358 | if (idx < 0)
| 0 | ||||||
1359 | break; never executed: break; | 0 | ||||||
1360 | processedOutput = processedOutput.insert(idx, QByteArrayLiteral(" ; ") + it.value()); never executed: return ba; | 0 | ||||||
1361 | } never executed: end of block | 0 | ||||||
1362 | } never executed: end of block | 0 | ||||||
1363 | - | |||||||
1364 | qDebug("%s", processedOutput.constData()); | - | ||||||
1365 | } never executed: end of block | 0 | ||||||
1366 | - | |||||||
1367 | static QByteArray functionName(Function *function) | - | ||||||
1368 | { | - | ||||||
1369 | QByteArray name = function->name()->toQString().toUtf8(); | - | ||||||
1370 | if (name.isEmpty()) {
| 0-4 | ||||||
1371 | name = QByteArray::number(reinterpret_cast<quintptr>(function), 16); | - | ||||||
1372 | name.prepend("QV4::Function(0x"); | - | ||||||
1373 | name.append(')'); | - | ||||||
1374 | } never executed: end of block | 0 | ||||||
1375 | return name; executed 4 times by 1 test: return name; Executed by:
| 4 | ||||||
1376 | } | - | ||||||
1377 | - | |||||||
1378 | void Assembler::link(Function *function) | - | ||||||
1379 | { | - | ||||||
1380 | for (const auto &jumpTarget : pasm()->patches) | - | ||||||
1381 | jumpTarget.jump.linkTo(pasm()->labelsByOffset[jumpTarget.offset], pasm()); executed 9470 times by 38 tests: jumpTarget.jump.linkTo(reinterpret_cast<PlatformAssembler *>(this->d)->labelsByOffset[jumpTarget.offset], reinterpret_cast<PlatformAssembler *>(this->d)); Executed by:
| 9470 | ||||||
1382 | - | |||||||
1383 | JSC::JSGlobalData dummy(function->internalClass->engine->executableAllocator); | - | ||||||
1384 | JSC::LinkBuffer<PlatformAssembler::MacroAssembler> linkBuffer(dummy, pasm(), nullptr); | - | ||||||
1385 | - | |||||||
1386 | for (const auto &ehTarget : pasm()->ehTargets) { | - | ||||||
1387 | auto targetLabel = pasm()->labelsByOffset.value(ehTarget.offset); | - | ||||||
1388 | linkBuffer.patch(ehTarget.label, linkBuffer.locationOf(targetLabel)); | - | ||||||
1389 | } executed 100 times by 7 tests: end of block Executed by:
| 100 | ||||||
1390 | - | |||||||
1391 | JSC::MacroAssemblerCodeRef codeRef; | - | ||||||
1392 | - | |||||||
1393 | static const bool showCode = qEnvironmentVariableIsSet("QV4_SHOW_ASM"); | - | ||||||
1394 | if (showCode) {
| 0-13188 | ||||||
1395 | QBuffer buf; | - | ||||||
1396 | buf.open(QIODevice::WriteOnly); | - | ||||||
1397 | WTF::setDataFile(new QIODevicePrintStream(&buf)); | - | ||||||
1398 | - | |||||||
1399 | QByteArray name = functionName(function); | - | ||||||
1400 | codeRef = linkBuffer.finalizeCodeWithDisassembly("%s", name.data()); | - | ||||||
1401 | - | |||||||
1402 | WTF::setDataFile(stderr); | - | ||||||
1403 | printDisassembledOutputWithCalls(buf.data(), pasm()->functions); | - | ||||||
1404 | } else { never executed: end of block | 0 | ||||||
1405 | codeRef = linkBuffer.finalizeCodeWithoutDisassembly(); | - | ||||||
1406 | } executed 13188 times by 64 tests: end of block Executed by:
| 13188 | ||||||
1407 | - | |||||||
1408 | function->codeRef = new JSC::MacroAssemblerCodeRef(codeRef); | - | ||||||
1409 | function->jittedCode = reinterpret_cast<Function::JittedCode>(function->codeRef->code().executableAddress()); | - | ||||||
1410 | - | |||||||
1411 | // This implements writing of JIT'd addresses so that perf can find the | - | ||||||
1412 | // symbol names. | - | ||||||
1413 | // | - | ||||||
1414 | // Perf expects the mapping to be in a certain place and have certain | - | ||||||
1415 | // content, for more information, see: | - | ||||||
1416 | // https://github.com/torvalds/linux/blob/master/tools/perf/Documentation/jit-interface.txt | - | ||||||
1417 | static bool doProfile = !qEnvironmentVariableIsEmpty("QV4_PROFILE_WRITE_PERF_MAP"); | - | ||||||
1418 | if (Q_UNLIKELY(doProfile)) {
| 4-13184 | ||||||
1419 | static QFile perfMapFile(QString::fromLatin1("/tmp/perf-%1.map") | - | ||||||
1420 | .arg(QCoreApplication::applicationPid())); | - | ||||||
1421 | static const bool isOpen = perfMapFile.open(QIODevice::WriteOnly); | - | ||||||
1422 | if (!isOpen) {
| 0-4 | ||||||
1423 | qWarning("QV4::JIT::Assembler: Cannot write perf map file."); | - | ||||||
1424 | doProfile = false; | - | ||||||
1425 | } else { never executed: end of block | 0 | ||||||
1426 | perfMapFile.write(QByteArray::number(reinterpret_cast<quintptr>( | - | ||||||
1427 | codeRef.code().executableAddress()), 16)); | - | ||||||
1428 | perfMapFile.putChar(' '); | - | ||||||
1429 | perfMapFile.write(QByteArray::number(static_cast<qsizetype>(codeRef.size()), 16)); | - | ||||||
1430 | perfMapFile.putChar(' '); | - | ||||||
1431 | perfMapFile.write(functionName(function)); | - | ||||||
1432 | perfMapFile.putChar('\n'); | - | ||||||
1433 | perfMapFile.flush(); | - | ||||||
1434 | } executed 4 times by 1 test: end of block Executed by:
| 4 | ||||||
1435 | } | - | ||||||
1436 | } executed 13188 times by 64 tests: end of block Executed by:
| 13188 | ||||||
1437 | - | |||||||
1438 | void Assembler::addLabel(int offset) | - | ||||||
1439 | { | - | ||||||
1440 | pasm()->labelsByOffset[offset] = pasm()->label(); | - | ||||||
1441 | } executed 5472 times by 38 tests: end of block Executed by:
| 5472 | ||||||
1442 | - | |||||||
1443 | void Assembler::loadConst(int constIndex) | - | ||||||
1444 | { | - | ||||||
1445 | //### | - | ||||||
1446 | if (pasm()->constantTable[constIndex].isUndefined()) {
| 0-126 | ||||||
1447 | pasm()->loadUndefined(); | - | ||||||
1448 | } else { never executed: end of block | 0 | ||||||
1449 | pasm()->loadAccumulator(pasm()->loadConstAddress(constIndex)); | - | ||||||
1450 | } executed 126 times by 7 tests: end of block Executed by:
| 126 | ||||||
1451 | } | - | ||||||
1452 | - | |||||||
1453 | void Assembler::copyConst(int constIndex, int destReg) | - | ||||||
1454 | { | - | ||||||
1455 | pasm()->copyConst(constIndex, regAddr(destReg)); | - | ||||||
1456 | } executed 964 times by 18 tests: end of block Executed by:
| 964 | ||||||
1457 | - | |||||||
1458 | void Assembler::loadReg(int reg) | - | ||||||
1459 | { | - | ||||||
1460 | pasm()->loadAccumulator(regAddr(reg)); | - | ||||||
1461 | } executed 2654 times by 31 tests: end of block Executed by:
| 2654 | ||||||
1462 | - | |||||||
1463 | void JIT::Assembler::moveReg(int sourceReg, int destReg) | - | ||||||
1464 | { | - | ||||||
1465 | pasm()->moveReg(regAddr(sourceReg), regAddr(destReg)); | - | ||||||
1466 | } executed 3186 times by 19 tests: end of block Executed by:
| 3186 | ||||||
1467 | - | |||||||
1468 | void Assembler::storeReg(int reg) | - | ||||||
1469 | { | - | ||||||
1470 | pasm()->storeAccumulator(regAddr(reg)); | - | ||||||
1471 | } executed 54864 times by 63 tests: end of block Executed by:
| 54864 | ||||||
1472 | - | |||||||
1473 | void Assembler::loadLocal(int index, int level) | - | ||||||
1474 | { | - | ||||||
1475 | Heap::CallContext ctx; | - | ||||||
1476 | Q_UNUSED(ctx) | - | ||||||
1477 | pasm()->loadPointerFromValue(regAddr(CallData::Context), PlatformAssembler::ScratchRegister); | - | ||||||
1478 | while (level) {
| 40-406 | ||||||
1479 | pasm()->loadPtr(Address(PlatformAssembler::ScratchRegister, ctx.outer.offset), PlatformAssembler::ScratchRegister); | - | ||||||
1480 | --level; | - | ||||||
1481 | } executed 40 times by 3 tests: end of block Executed by:
| 40 | ||||||
1482 | pasm()->loadAccumulator(Address(PlatformAssembler::ScratchRegister, ctx.locals.offset + offsetof(ValueArray<0>, values) + sizeof(Value)*index)); | - | ||||||
1483 | } executed 406 times by 8 tests: end of block Executed by:
| 406 | ||||||
1484 | - | |||||||
1485 | void Assembler::storeLocal(int index, int level) | - | ||||||
1486 | { | - | ||||||
1487 | Heap::CallContext ctx; | - | ||||||
1488 | Q_UNUSED(ctx) | - | ||||||
1489 | pasm()->loadPtr(regAddr(CallData::Context), PlatformAssembler::ScratchRegister); | - | ||||||
1490 | while (level) {
| 0-46 | ||||||
1491 | pasm()->loadPtr(Address(PlatformAssembler::ScratchRegister, ctx.outer.offset), PlatformAssembler::ScratchRegister); | - | ||||||
1492 | --level; | - | ||||||
1493 | } never executed: end of block | 0 | ||||||
1494 | pasm()->storeAccumulator(Address(PlatformAssembler::ScratchRegister, ctx.locals.offset + offsetof(ValueArray<0>, values) + sizeof(Value)*index)); | - | ||||||
1495 | } executed 46 times by 4 tests: end of block Executed by:
| 46 | ||||||
1496 | - | |||||||
1497 | void Assembler::loadString(int stringId) | - | ||||||
1498 | { | - | ||||||
1499 | pasm()->loadString(stringId); | - | ||||||
1500 | } executed 3286 times by 31 tests: end of block Executed by:
| 3286 | ||||||
1501 | - | |||||||
1502 | void Assembler::loadValue(ReturnedValue value) | - | ||||||
1503 | { | - | ||||||
1504 | pasm()->loadValue(value); | - | ||||||
1505 | } executed 4758 times by 44 tests: end of block Executed by:
| 4758 | ||||||
1506 | - | |||||||
1507 | void JIT::Assembler::storeHeapObject(int reg) | - | ||||||
1508 | { | - | ||||||
1509 | pasm()->storeHeapObject(PlatformAssembler::ReturnValueRegisterValue, regAddr(reg)); | - | ||||||
1510 | } executed 154 times by 9 tests: end of block Executed by:
| 154 | ||||||
1511 | - | |||||||
1512 | void Assembler::toNumber() | - | ||||||
1513 | { | - | ||||||
1514 | pasm()->toNumber(); | - | ||||||
1515 | } executed 2 times by 1 test: end of block Executed by:
| 2 | ||||||
1516 | - | |||||||
1517 | void Assembler::uminus() | - | ||||||
1518 | { | - | ||||||
1519 | saveAccumulatorInFrame(); | - | ||||||
1520 | prepareCallWithArgCount(1); | - | ||||||
1521 | passAccumulatorAsArg(0); | - | ||||||
1522 | IN_JIT_GENERATE_RUNTIME_CALL(Runtime::method_uMinus, ResultInAccumulator); | - | ||||||
1523 | checkException(); | - | ||||||
1524 | } executed 26 times by 3 tests: end of block Executed by:
| 26 | ||||||
1525 | - | |||||||
1526 | void Assembler::ucompl() | - | ||||||
1527 | { | - | ||||||
1528 | pasm()->toInt32(); | - | ||||||
1529 | pasm()->xor32(TrustedImm32(-1), PlatformAssembler::AccumulatorRegisterValue); | - | ||||||
1530 | pasm()->setAccumulatorTag(IntegerTag); | - | ||||||
1531 | } never executed: end of block | 0 | ||||||
1532 | - | |||||||
1533 | static ReturnedValue incHelper(const Value v) | - | ||||||
1534 | { | - | ||||||
1535 | double d; | - | ||||||
1536 | if (Q_LIKELY(v.isDouble()))
| 0 | ||||||
1537 | d = v.doubleValue(); never executed: d = v.doubleValue(); | 0 | ||||||
1538 | else | - | ||||||
1539 | d = v.toNumberImpl(); never executed: d = v.toNumberImpl(); | 0 | ||||||
1540 | return Encode(d + 1.); never executed: return Encode(d + 1.); | 0 | ||||||
1541 | } | - | ||||||
1542 | - | |||||||
1543 | void Assembler::inc() | - | ||||||
1544 | { | - | ||||||
1545 | auto done = pasm()->unopIntPath([this](){ | - | ||||||
1546 | auto overflowed = pasm()->branchAdd32(PlatformAssembler::Overflow, | - | ||||||
1547 | PlatformAssembler::AccumulatorRegisterValue, | - | ||||||
1548 | TrustedImm32(1), | - | ||||||
1549 | PlatformAssembler::ScratchRegister); | - | ||||||
1550 | pasm()->setAccumulatorTag(IntegerTag, PlatformAssembler::ScratchRegister); | - | ||||||
1551 | return overflowed; executed 326 times by 13 tests: return overflowed; Executed by:
| 326 | ||||||
1552 | }); | - | ||||||
1553 | - | |||||||
1554 | // slow path: | - | ||||||
1555 | pasm()->callWithAccumulatorByValueAsFirstArgument([this]() { | - | ||||||
1556 | pasm()->callHelper(incHelper); | - | ||||||
1557 | pasm()->saveReturnValueInAccumulator(); | - | ||||||
1558 | }); executed 326 times by 13 tests: end of block Executed by:
| 326 | ||||||
1559 | checkException(); | - | ||||||
1560 | - | |||||||
1561 | // done. | - | ||||||
1562 | done.link(pasm()); | - | ||||||
1563 | } executed 326 times by 13 tests: end of block Executed by:
| 326 | ||||||
1564 | - | |||||||
1565 | static ReturnedValue decHelper(const Value v) | - | ||||||
1566 | { | - | ||||||
1567 | double d; | - | ||||||
1568 | if (Q_LIKELY(v.isDouble()))
| 44-464 | ||||||
1569 | d = v.doubleValue(); executed 44 times by 2 tests: d = v.doubleValue(); Executed by:
| 44 | ||||||
1570 | else | - | ||||||
1571 | d = v.toNumberImpl(); executed 464 times by 1 test: d = v.toNumberImpl(); Executed by:
| 464 | ||||||
1572 | return Encode(d - 1.); executed 508 times by 2 tests: return Encode(d - 1.); Executed by:
| 508 | ||||||
1573 | } | - | ||||||
1574 | - | |||||||
1575 | void Assembler::dec() | - | ||||||
1576 | { | - | ||||||
1577 | auto done = pasm()->unopIntPath([this](){ | - | ||||||
1578 | auto overflowed = pasm()->branchSub32(PlatformAssembler::Overflow, | - | ||||||
1579 | PlatformAssembler::AccumulatorRegisterValue, | - | ||||||
1580 | TrustedImm32(1), | - | ||||||
1581 | PlatformAssembler::ScratchRegister); | - | ||||||
1582 | pasm()->setAccumulatorTag(IntegerTag, PlatformAssembler::ScratchRegister); | - | ||||||
1583 | return overflowed; executed 288 times by 6 tests: return overflowed; Executed by:
| 288 | ||||||
1584 | }); | - | ||||||
1585 | - | |||||||
1586 | // slow path: | - | ||||||
1587 | pasm()->callWithAccumulatorByValueAsFirstArgument([this]() { | - | ||||||
1588 | pasm()->callHelper(decHelper); | - | ||||||
1589 | pasm()->saveReturnValueInAccumulator(); | - | ||||||
1590 | }); executed 288 times by 6 tests: end of block Executed by:
| 288 | ||||||
1591 | checkException(); | - | ||||||
1592 | - | |||||||
1593 | // done. | - | ||||||
1594 | done.link(pasm()); | - | ||||||
1595 | } executed 288 times by 6 tests: end of block Executed by:
| 288 | ||||||
1596 | - | |||||||
1597 | void Assembler::unot() | - | ||||||
1598 | { | - | ||||||
1599 | pasm()->toBoolean([this](PlatformAssembler::RegisterID resultReg){ | - | ||||||
1600 | pasm()->compare32(PlatformAssembler::Equal, resultReg, | - | ||||||
1601 | TrustedImm32(0), PlatformAssembler::AccumulatorRegisterValue); | - | ||||||
1602 | pasm()->setAccumulatorTag(QV4::Value::ValueTypeInternal::Boolean); | - | ||||||
1603 | }); executed 268 times by 10 tests: end of block Executed by:
| 268 | ||||||
1604 | } executed 134 times by 10 tests: end of block Executed by:
| 134 | ||||||
1605 | - | |||||||
1606 | void Assembler::add(int lhs) | - | ||||||
1607 | { | - | ||||||
1608 | auto done = pasm()->binopBothIntPath(regAddr(lhs), [this](){ | - | ||||||
1609 | auto overflowed = pasm()->branchAdd32(PlatformAssembler::Overflow, | - | ||||||
1610 | PlatformAssembler::AccumulatorRegisterValue, | - | ||||||
1611 | PlatformAssembler::ScratchRegister); | - | ||||||
1612 | pasm()->setAccumulatorTag(IntegerTag, | - | ||||||
1613 | PlatformAssembler::ScratchRegister); | - | ||||||
1614 | return overflowed; executed 2130 times by 29 tests: return overflowed; Executed by:
| 2130 | ||||||
1615 | }); | - | ||||||
1616 | - | |||||||
1617 | // slow path: | - | ||||||
1618 | saveAccumulatorInFrame(); | - | ||||||
1619 | prepareCallWithArgCount(3); | - | ||||||
1620 | passAccumulatorAsArg(2); | - | ||||||
1621 | passRegAsArg(lhs, 1); | - | ||||||
1622 | passEngineAsArg(0); | - | ||||||
1623 | IN_JIT_GENERATE_RUNTIME_CALL(Runtime::method_add, ResultInAccumulator); | - | ||||||
1624 | checkException(); | - | ||||||
1625 | - | |||||||
1626 | // done. | - | ||||||
1627 | done.link(pasm()); | - | ||||||
1628 | } executed 2130 times by 29 tests: end of block Executed by:
| 2130 | ||||||
1629 | - | |||||||
1630 | void Assembler::bitAnd(int lhs) | - | ||||||
1631 | { | - | ||||||
1632 | PlatformAssembler::Address lhsAddr = regAddr(lhs); | - | ||||||
1633 | pasm()->toInt32LhsAcc(lhsAddr, PlatformAssembler::ScratchRegister); | - | ||||||
1634 | pasm()->and32(PlatformAssembler::ScratchRegister, PlatformAssembler::AccumulatorRegisterValue); | - | ||||||
1635 | pasm()->setAccumulatorTag(IntegerTag); | - | ||||||
1636 | } never executed: end of block | 0 | ||||||
1637 | - | |||||||
1638 | void Assembler::bitOr(int lhs) | - | ||||||
1639 | { | - | ||||||
1640 | PlatformAssembler::Address lhsAddr = regAddr(lhs); | - | ||||||
1641 | pasm()->toInt32LhsAcc(lhsAddr, PlatformAssembler::ScratchRegister); | - | ||||||
1642 | pasm()->or32(PlatformAssembler::ScratchRegister, PlatformAssembler::AccumulatorRegisterValue); | - | ||||||
1643 | pasm()->setAccumulatorTag(IntegerTag); | - | ||||||
1644 | } executed 14 times by 1 test: end of block Executed by:
| 14 | ||||||
1645 | - | |||||||
1646 | void Assembler::bitXor(int lhs) | - | ||||||
1647 | { | - | ||||||
1648 | PlatformAssembler::Address lhsAddr = regAddr(lhs); | - | ||||||
1649 | pasm()->toInt32LhsAcc(lhsAddr, PlatformAssembler::ScratchRegister); | - | ||||||
1650 | pasm()->xor32(PlatformAssembler::ScratchRegister, PlatformAssembler::AccumulatorRegisterValue); | - | ||||||
1651 | pasm()->setAccumulatorTag(IntegerTag); | - | ||||||
1652 | } never executed: end of block | 0 | ||||||
1653 | - | |||||||
1654 | void Assembler::ushr(int lhs) | - | ||||||
1655 | { | - | ||||||
1656 | PlatformAssembler::Address lhsAddr = regAddr(lhs); | - | ||||||
1657 | pasm()->toInt32LhsAcc(lhsAddr, PlatformAssembler::ScratchRegister); | - | ||||||
1658 | pasm()->and32(TrustedImm32(0x1f), PlatformAssembler::AccumulatorRegisterValue); | - | ||||||
1659 | pasm()->urshift32(PlatformAssembler::AccumulatorRegisterValue, PlatformAssembler::ScratchRegister); | - | ||||||
1660 | pasm()->move(PlatformAssembler::ScratchRegister, PlatformAssembler::AccumulatorRegisterValue); | - | ||||||
1661 | auto doubleEncode = pasm()->branch32(PlatformAssembler::LessThan, | - | ||||||
1662 | PlatformAssembler::AccumulatorRegisterValue, | - | ||||||
1663 | TrustedImm32(0)); | - | ||||||
1664 | pasm()->setAccumulatorTag(IntegerTag); | - | ||||||
1665 | auto done = pasm()->jump(); | - | ||||||
1666 | - | |||||||
1667 | doubleEncode.link(pasm()); | - | ||||||
1668 | pasm()->convertUInt32ToDouble(PlatformAssembler::AccumulatorRegisterValue, | - | ||||||
1669 | PlatformAssembler::FPScratchRegister, | - | ||||||
1670 | PlatformAssembler::ScratchRegister); | - | ||||||
1671 | pasm()->encodeDoubleIntoAccumulator(PlatformAssembler::FPScratchRegister); | - | ||||||
1672 | done.link(pasm()); | - | ||||||
1673 | } never executed: end of block | 0 | ||||||
1674 | - | |||||||
1675 | void Assembler::shr(int lhs) | - | ||||||
1676 | { | - | ||||||
1677 | PlatformAssembler::Address lhsAddr = regAddr(lhs); | - | ||||||
1678 | pasm()->toInt32LhsAcc(lhsAddr, PlatformAssembler::ScratchRegister); | - | ||||||
1679 | pasm()->and32(TrustedImm32(0x1f), PlatformAssembler::AccumulatorRegisterValue); | - | ||||||
1680 | pasm()->rshift32(PlatformAssembler::AccumulatorRegisterValue, PlatformAssembler::ScratchRegister); | - | ||||||
1681 | pasm()->move(PlatformAssembler::ScratchRegister, PlatformAssembler::AccumulatorRegisterValue); | - | ||||||
1682 | pasm()->setAccumulatorTag(IntegerTag); | - | ||||||
1683 | } never executed: end of block | 0 | ||||||
1684 | - | |||||||
1685 | void Assembler::shl(int lhs) | - | ||||||
1686 | { | - | ||||||
1687 | PlatformAssembler::Address lhsAddr = regAddr(lhs); | - | ||||||
1688 | pasm()->toInt32LhsAcc(lhsAddr, PlatformAssembler::ScratchRegister); | - | ||||||
1689 | pasm()->and32(TrustedImm32(0x1f), PlatformAssembler::AccumulatorRegisterValue); | - | ||||||
1690 | pasm()->lshift32(PlatformAssembler::AccumulatorRegisterValue, PlatformAssembler::ScratchRegister); | - | ||||||
1691 | pasm()->move(PlatformAssembler::ScratchRegister, PlatformAssembler::AccumulatorRegisterValue); | - | ||||||
1692 | pasm()->setAccumulatorTag(IntegerTag); | - | ||||||
1693 | } never executed: end of block | 0 | ||||||
1694 | - | |||||||
1695 | void Assembler::bitAndConst(int rhs) | - | ||||||
1696 | { | - | ||||||
1697 | pasm()->toInt32(); | - | ||||||
1698 | pasm()->and32(TrustedImm32(rhs), PlatformAssembler::AccumulatorRegisterValue); | - | ||||||
1699 | pasm()->setAccumulatorTag(IntegerTag); | - | ||||||
1700 | } executed 4 times by 1 test: end of block Executed by:
| 4 | ||||||
1701 | - | |||||||
1702 | void Assembler::bitOrConst(int rhs) | - | ||||||
1703 | { | - | ||||||
1704 | pasm()->toInt32(); | - | ||||||
1705 | pasm()->or32(TrustedImm32(rhs), PlatformAssembler::AccumulatorRegisterValue); | - | ||||||
1706 | pasm()->setAccumulatorTag(IntegerTag); | - | ||||||
1707 | } never executed: end of block | 0 | ||||||
1708 | - | |||||||
1709 | void Assembler::bitXorConst(int rhs) | - | ||||||
1710 | { | - | ||||||
1711 | pasm()->toInt32(); | - | ||||||
1712 | pasm()->xor32(TrustedImm32(rhs), PlatformAssembler::AccumulatorRegisterValue); | - | ||||||
1713 | pasm()->setAccumulatorTag(IntegerTag); | - | ||||||
1714 | } never executed: end of block | 0 | ||||||
1715 | - | |||||||
1716 | void Assembler::ushrConst(int rhs) | - | ||||||
1717 | { | - | ||||||
1718 | rhs &= 0x1f; | - | ||||||
1719 | pasm()->toInt32(); | - | ||||||
1720 | if (rhs) {
| 0 | ||||||
1721 | // a non zero shift will always give a number encodable as an int | - | ||||||
1722 | pasm()->urshift32(TrustedImm32(rhs), PlatformAssembler::AccumulatorRegisterValue); | - | ||||||
1723 | pasm()->setAccumulatorTag(IntegerTag); | - | ||||||
1724 | } else { never executed: end of block | 0 | ||||||
1725 | // shift with 0 can lead to a negative result | - | ||||||
1726 | auto doubleEncode = pasm()->branch32(PlatformAssembler::LessThan, | - | ||||||
1727 | PlatformAssembler::AccumulatorRegisterValue, | - | ||||||
1728 | TrustedImm32(0)); | - | ||||||
1729 | pasm()->setAccumulatorTag(IntegerTag); | - | ||||||
1730 | auto done = pasm()->jump(); | - | ||||||
1731 | - | |||||||
1732 | doubleEncode.link(pasm()); | - | ||||||
1733 | pasm()->convertUInt32ToDouble(PlatformAssembler::AccumulatorRegisterValue, | - | ||||||
1734 | PlatformAssembler::FPScratchRegister, | - | ||||||
1735 | PlatformAssembler::ScratchRegister); | - | ||||||
1736 | pasm()->encodeDoubleIntoAccumulator(PlatformAssembler::FPScratchRegister); | - | ||||||
1737 | done.link(pasm()); | - | ||||||
1738 | } never executed: end of block | 0 | ||||||
1739 | } | - | ||||||
1740 | - | |||||||
1741 | void Assembler::shrConst(int rhs) | - | ||||||
1742 | { | - | ||||||
1743 | rhs &= 0x1f; | - | ||||||
1744 | pasm()->toInt32(); | - | ||||||
1745 | if (rhs)
| 0 | ||||||
1746 | pasm()->rshift32(TrustedImm32(rhs), PlatformAssembler::AccumulatorRegisterValue); never executed: reinterpret_cast<PlatformAssembler *>(this->d)->rshift32(TrustedImm32(rhs), PlatformAssembler::AccumulatorRegisterValue); | 0 | ||||||
1747 | pasm()->setAccumulatorTag(IntegerTag); | - | ||||||
1748 | } never executed: end of block | 0 | ||||||
1749 | - | |||||||
1750 | void Assembler::shlConst(int rhs) | - | ||||||
1751 | { | - | ||||||
1752 | rhs &= 0x1f; | - | ||||||
1753 | pasm()->toInt32(); | - | ||||||
1754 | if (rhs)
| 0 | ||||||
1755 | pasm()->lshift32(TrustedImm32(rhs), PlatformAssembler::AccumulatorRegisterValue); never executed: reinterpret_cast<PlatformAssembler *>(this->d)->lshift32(TrustedImm32(rhs), PlatformAssembler::AccumulatorRegisterValue); | 0 | ||||||
1756 | pasm()->setAccumulatorTag(IntegerTag); | - | ||||||
1757 | } never executed: end of block | 0 | ||||||
1758 | - | |||||||
1759 | void Assembler::mul(int lhs) | - | ||||||
1760 | { | - | ||||||
1761 | auto done = pasm()->binopBothIntPath(regAddr(lhs), [this](){ | - | ||||||
1762 | auto overflowed = pasm()->branchMul32(PlatformAssembler::Overflow, | - | ||||||
1763 | PlatformAssembler::AccumulatorRegisterValue, | - | ||||||
1764 | PlatformAssembler::ScratchRegister); | - | ||||||
1765 | pasm()->setAccumulatorTag(IntegerTag, | - | ||||||
1766 | PlatformAssembler::ScratchRegister); | - | ||||||
1767 | return overflowed; executed 896 times by 13 tests: return overflowed; Executed by:
| 896 | ||||||
1768 | }); | - | ||||||
1769 | - | |||||||
1770 | // slow path: | - | ||||||
1771 | saveAccumulatorInFrame(); | - | ||||||
1772 | prepareCallWithArgCount(2); | - | ||||||
1773 | passAccumulatorAsArg(1); | - | ||||||
1774 | passRegAsArg(lhs, 0); | - | ||||||
1775 | IN_JIT_GENERATE_RUNTIME_CALL(Runtime::method_mul, ResultInAccumulator); | - | ||||||
1776 | checkException(); | - | ||||||
1777 | - | |||||||
1778 | // done. | - | ||||||
1779 | done.link(pasm()); | - | ||||||
1780 | } executed 896 times by 13 tests: end of block Executed by:
| 896 | ||||||
1781 | - | |||||||
1782 | void Assembler::div(int lhs) | - | ||||||
1783 | { | - | ||||||
1784 | saveAccumulatorInFrame(); | - | ||||||
1785 | prepareCallWithArgCount(2); | - | ||||||
1786 | passAccumulatorAsArg(1); | - | ||||||
1787 | passRegAsArg(lhs, 0); | - | ||||||
1788 | IN_JIT_GENERATE_RUNTIME_CALL(Runtime::method_div, ResultInAccumulator); | - | ||||||
1789 | checkException(); | - | ||||||
1790 | } executed 468 times by 12 tests: end of block Executed by:
| 468 | ||||||
1791 | - | |||||||
1792 | void Assembler::mod(int lhs) | - | ||||||
1793 | { | - | ||||||
1794 | saveAccumulatorInFrame(); | - | ||||||
1795 | prepareCallWithArgCount(2); | - | ||||||
1796 | passAccumulatorAsArg(1); | - | ||||||
1797 | passRegAsArg(lhs, 0); | - | ||||||
1798 | IN_JIT_GENERATE_RUNTIME_CALL(Runtime::method_mod, ResultInAccumulator); | - | ||||||
1799 | checkException(); | - | ||||||
1800 | } executed 46 times by 5 tests: end of block Executed by:
| 46 | ||||||
1801 | - | |||||||
1802 | void Assembler::sub(int lhs) | - | ||||||
1803 | { | - | ||||||
1804 | auto done = pasm()->binopBothIntPath(regAddr(lhs), [this](){ | - | ||||||
1805 | auto overflowed = pasm()->branchSub32(PlatformAssembler::Overflow, | - | ||||||
1806 | PlatformAssembler::AccumulatorRegisterValue, | - | ||||||
1807 | PlatformAssembler::ScratchRegister); | - | ||||||
1808 | pasm()->setAccumulatorTag(IntegerTag, | - | ||||||
1809 | PlatformAssembler::ScratchRegister); | - | ||||||
1810 | return overflowed; executed 686 times by 20 tests: return overflowed; Executed by:
| 686 | ||||||
1811 | }); | - | ||||||
1812 | - | |||||||
1813 | // slow path: | - | ||||||
1814 | saveAccumulatorInFrame(); | - | ||||||
1815 | prepareCallWithArgCount(2); | - | ||||||
1816 | passAccumulatorAsArg(1); | - | ||||||
1817 | passRegAsArg(lhs, 0); | - | ||||||
1818 | IN_JIT_GENERATE_RUNTIME_CALL(Runtime::method_sub, ResultInAccumulator); | - | ||||||
1819 | checkException(); | - | ||||||
1820 | - | |||||||
1821 | // done. | - | ||||||
1822 | done.link(pasm()); | - | ||||||
1823 | } executed 686 times by 20 tests: end of block Executed by:
| 686 | ||||||
1824 | - | |||||||
1825 | void Assembler::cmpeqNull() | - | ||||||
1826 | { | - | ||||||
1827 | pasm()->isNullOrUndefined(); | - | ||||||
1828 | pasm()->setAccumulatorTag(QV4::Value::ValueTypeInternal::Boolean); | - | ||||||
1829 | } never executed: end of block | 0 | ||||||
1830 | - | |||||||
1831 | void Assembler::cmpneNull() | - | ||||||
1832 | { | - | ||||||
1833 | pasm()->isNullOrUndefined(); | - | ||||||
1834 | pasm()->xor32(TrustedImm32(1), PlatformAssembler::AccumulatorRegisterValue); | - | ||||||
1835 | pasm()->setAccumulatorTag(QV4::Value::ValueTypeInternal::Boolean); | - | ||||||
1836 | } executed 8 times by 1 test: end of block Executed by:
| 8 | ||||||
1837 | - | |||||||
1838 | void Assembler::cmpeqInt(int lhs) | - | ||||||
1839 | { | - | ||||||
1840 | auto isIntOrBool = pasm()->isIntOrBool(); | - | ||||||
1841 | saveAccumulatorInFrame(); | - | ||||||
1842 | pasm()->pushValueAligned(Encode(lhs)); | - | ||||||
1843 | if (PlatformAssembler::ArgInRegCount < 2)
| 0-40 | ||||||
1844 | pasm()->push(PlatformAssembler::StackPointerRegister); never executed: reinterpret_cast<PlatformAssembler *>(this->d)->push(PlatformAssembler::StackPointerRegister); | 0 | ||||||
1845 | else | - | ||||||
1846 | pasm()->move(PlatformAssembler::StackPointerRegister, pasm()->registerForArg(1)); executed 40 times by 8 tests: reinterpret_cast<PlatformAssembler *>(this->d)->move(PlatformAssembler::StackPointerRegister, reinterpret_cast<PlatformAssembler *>(this->d)->registerForArg(1)); Executed by:
| 40 | ||||||
1847 | passAccumulatorAsArg_internal(0, true); | - | ||||||
1848 | pasm()->callRuntime("Runtime::method_equal", (void*)Runtime::method_equal, ResultInAccumulator); | - | ||||||
1849 | if (PlatformAssembler::ArgInRegCount < 2)
| 0-40 | ||||||
1850 | pasm()->addPtr(TrustedImm32(2 * PlatformAssembler::PointerSize), PlatformAssembler::StackPointerRegister); never executed: reinterpret_cast<PlatformAssembler *>(this->d)->addPtr(TrustedImm32(2 * PlatformAssembler::PointerSize), PlatformAssembler::StackPointerRegister); | 0 | ||||||
1851 | pasm()->popValueAligned(); | - | ||||||
1852 | auto done = pasm()->jump(); | - | ||||||
1853 | isIntOrBool.link(pasm()); | - | ||||||
1854 | pasm()->compare32(PlatformAssembler::Equal, PlatformAssembler::AccumulatorRegisterValue, | - | ||||||
1855 | TrustedImm32(lhs), | - | ||||||
1856 | PlatformAssembler::AccumulatorRegisterValue); | - | ||||||
1857 | pasm()->setAccumulatorTag(QV4::Value::ValueTypeInternal::Boolean); | - | ||||||
1858 | done.link(pasm()); | - | ||||||
1859 | } executed 40 times by 8 tests: end of block Executed by:
| 40 | ||||||
1860 | - | |||||||
1861 | void Assembler::cmpneInt(int lhs) | - | ||||||
1862 | { | - | ||||||
1863 | auto isIntOrBool = pasm()->isIntOrBool(); | - | ||||||
1864 | saveAccumulatorInFrame(); | - | ||||||
1865 | pasm()->pushValueAligned(Encode(lhs)); | - | ||||||
1866 | if (PlatformAssembler::ArgInRegCount < 2)
| 0-30 | ||||||
1867 | pasm()->push(PlatformAssembler::StackPointerRegister); never executed: reinterpret_cast<PlatformAssembler *>(this->d)->push(PlatformAssembler::StackPointerRegister); | 0 | ||||||
1868 | else | - | ||||||
1869 | pasm()->move(PlatformAssembler::StackPointerRegister, pasm()->registerForArg(1)); executed 30 times by 3 tests: reinterpret_cast<PlatformAssembler *>(this->d)->move(PlatformAssembler::StackPointerRegister, reinterpret_cast<PlatformAssembler *>(this->d)->registerForArg(1)); Executed by:
| 30 | ||||||
1870 | passAccumulatorAsArg_internal(0, true); | - | ||||||
1871 | pasm()->callRuntime("Runtime::method_notEqual", (void*)Runtime::method_notEqual, ResultInAccumulator); | - | ||||||
1872 | if (PlatformAssembler::ArgInRegCount < 2)
| 0-30 | ||||||
1873 | pasm()->addPtr(TrustedImm32(2 * PlatformAssembler::PointerSize), PlatformAssembler::StackPointerRegister); never executed: reinterpret_cast<PlatformAssembler *>(this->d)->addPtr(TrustedImm32(2 * PlatformAssembler::PointerSize), PlatformAssembler::StackPointerRegister); | 0 | ||||||
1874 | pasm()->popValueAligned(); | - | ||||||
1875 | auto done = pasm()->jump(); | - | ||||||
1876 | isIntOrBool.link(pasm()); | - | ||||||
1877 | pasm()->compare32(PlatformAssembler::NotEqual, PlatformAssembler::AccumulatorRegisterValue, | - | ||||||
1878 | TrustedImm32(lhs), | - | ||||||
1879 | PlatformAssembler::AccumulatorRegisterValue); | - | ||||||
1880 | pasm()->setAccumulatorTag(QV4::Value::ValueTypeInternal::Boolean); | - | ||||||
1881 | done.link(pasm()); | - | ||||||
1882 | } executed 30 times by 3 tests: end of block Executed by:
| 30 | ||||||
1883 | - | |||||||
1884 | void Assembler::cmp(int cond, CmpFunc function, const char *functionName, int lhs) | - | ||||||
1885 | { | - | ||||||
1886 | auto c = static_cast<PlatformAssembler::RelationalCondition>(cond); | - | ||||||
1887 | auto done = pasm()->binopBothIntPath(regAddr(lhs), [this, c](){ | - | ||||||
1888 | pasm()->compare32(c, PlatformAssembler::ScratchRegister, | - | ||||||
1889 | PlatformAssembler::AccumulatorRegisterValue, | - | ||||||
1890 | PlatformAssembler::AccumulatorRegisterValue); | - | ||||||
1891 | pasm()->setAccumulatorTag(QV4::Value::ValueTypeInternal::Boolean); | - | ||||||
1892 | return PlatformAssembler::Jump(); executed 2256 times by 32 tests: return PlatformAssembler::Jump(); Executed by:
| 2256 | ||||||
1893 | }); | - | ||||||
1894 | - | |||||||
1895 | // slow path: | - | ||||||
1896 | saveAccumulatorInFrame(); | - | ||||||
1897 | prepareCallWithArgCount(2); | - | ||||||
1898 | passAccumulatorAsArg(1); | - | ||||||
1899 | passRegAsArg(lhs, 0); | - | ||||||
1900 | - | |||||||
1901 | callRuntime(functionName, reinterpret_cast<void*>(function), ResultInAccumulator); | - | ||||||
1902 | checkException(); | - | ||||||
1903 | pasm()->setAccumulatorTag(QV4::Value::ValueTypeInternal::Boolean); | - | ||||||
1904 | - | |||||||
1905 | // done. | - | ||||||
1906 | done.link(pasm()); | - | ||||||
1907 | } executed 2256 times by 32 tests: end of block Executed by:
| 2256 | ||||||
1908 | - | |||||||
1909 | void Assembler::cmpeq(int lhs) | - | ||||||
1910 | { | - | ||||||
1911 | cmp(PlatformAssembler::Equal, &Runtime::method_compareEqual, | - | ||||||
1912 | "Runtime::method_compareEqual", lhs); | - | ||||||
1913 | } executed 1042 times by 16 tests: end of block Executed by:
| 1042 | ||||||
1914 | - | |||||||
1915 | void Assembler::cmpne(int lhs) | - | ||||||
1916 | { | - | ||||||
1917 | cmp(PlatformAssembler::NotEqual, &Runtime::method_compareNotEqual, | - | ||||||
1918 | "Runtime::method_compareNotEqual", lhs); | - | ||||||
1919 | } executed 86 times by 7 tests: end of block Executed by:
| 86 | ||||||
1920 | - | |||||||
1921 | void Assembler::cmpgt(int lhs) | - | ||||||
1922 | { | - | ||||||
1923 | cmp(PlatformAssembler::GreaterThan, &Runtime::method_compareGreaterThan, | - | ||||||
1924 | "Runtime::method_compareGreaterThan", lhs); | - | ||||||
1925 | } executed 74 times by 10 tests: end of block Executed by:
| 74 | ||||||
1926 | - | |||||||
1927 | void Assembler::cmpge(int lhs) | - | ||||||
1928 | { | - | ||||||
1929 | cmp(PlatformAssembler::GreaterThanOrEqual, &Runtime::method_compareGreaterEqual, | - | ||||||
1930 | "Runtime::method_compareGreaterEqual", lhs); | - | ||||||
1931 | } executed 12 times by 3 tests: end of block Executed by:
| 12 | ||||||
1932 | - | |||||||
1933 | void Assembler::cmplt(int lhs) | - | ||||||
1934 | { | - | ||||||
1935 | cmp(PlatformAssembler::LessThan, &Runtime::method_compareLessThan, | - | ||||||
1936 | "Runtime::method_compareLessThan", lhs); | - | ||||||
1937 | } executed 336 times by 15 tests: end of block Executed by:
| 336 | ||||||
1938 | - | |||||||
1939 | void Assembler::cmple(int lhs) | - | ||||||
1940 | { | - | ||||||
1941 | cmp(PlatformAssembler::LessThanOrEqual, &Runtime::method_compareLessEqual, | - | ||||||
1942 | "Runtime::method_compareLessEqual", lhs); | - | ||||||
1943 | } executed 72 times by 5 tests: end of block Executed by:
| 72 | ||||||
1944 | - | |||||||
1945 | void Assembler::cmpStrictEqual(int lhs) | - | ||||||
1946 | { | - | ||||||
1947 | cmp(PlatformAssembler::Equal, &RuntimeHelpers::strictEqual, | - | ||||||
1948 | "RuntimeHelpers::strictEqual", lhs); | - | ||||||
1949 | } executed 586 times by 11 tests: end of block Executed by:
| 586 | ||||||
1950 | - | |||||||
1951 | void Assembler::cmpStrictNotEqual(int lhs) | - | ||||||
1952 | { | - | ||||||
1953 | cmp(PlatformAssembler::Equal, &RuntimeHelpers::strictEqual, | - | ||||||
1954 | "RuntimeHelpers::strictEqual", lhs); | - | ||||||
1955 | pasm()->xor32(TrustedImm32(1), PlatformAssembler::AccumulatorRegisterValue); | - | ||||||
1956 | pasm()->setAccumulatorTag(QV4::Value::ValueTypeInternal::Boolean); | - | ||||||
1957 | } executed 48 times by 6 tests: end of block Executed by:
| 48 | ||||||
1958 | - | |||||||
1959 | void Assembler::jump(int offset) | - | ||||||
1960 | { | - | ||||||
1961 | pasm()->patches.push_back({ pasm()->jump(), offset }); | - | ||||||
1962 | } executed 2072 times by 31 tests: end of block Executed by:
| 2072 | ||||||
1963 | - | |||||||
1964 | void Assembler::jumpTrue(int offset) | - | ||||||
1965 | { | - | ||||||
1966 | pasm()->toBoolean([this, offset](PlatformAssembler::RegisterID resultReg) { | - | ||||||
1967 | auto jump = pasm()->branch32(PlatformAssembler::NotEqual, TrustedImm32(0), resultReg); | - | ||||||
1968 | pasm()->patches.push_back({ jump, offset }); | - | ||||||
1969 | }); executed 496 times by 9 tests: end of block Executed by:
| 496 | ||||||
1970 | } executed 248 times by 9 tests: end of block Executed by:
| 248 | ||||||
1971 | - | |||||||
1972 | void Assembler::jumpFalse(int offset) | - | ||||||
1973 | { | - | ||||||
1974 | pasm()->toBoolean([this, offset](PlatformAssembler::RegisterID resultReg) { | - | ||||||
1975 | auto jump = pasm()->branch32(PlatformAssembler::Equal, TrustedImm32(0), resultReg); | - | ||||||
1976 | pasm()->patches.push_back({ jump, offset }); | - | ||||||
1977 | }); executed 6852 times by 37 tests: end of block Executed by:
| 6852 | ||||||
1978 | } executed 3426 times by 37 tests: end of block Executed by:
| 3426 | ||||||
1979 | - | |||||||
1980 | void Assembler::jumpNoException(int offset) | - | ||||||
1981 | { | - | ||||||
1982 | auto jump = pasm()->branch32( | - | ||||||
1983 | PlatformAssembler::Equal, | - | ||||||
1984 | PlatformAssembler::Address(PlatformAssembler::EngineRegister, | - | ||||||
1985 | offsetof(EngineBase, hasException)), | - | ||||||
1986 | TrustedImm32(0)); | - | ||||||
1987 | pasm()->patches.push_back({ jump, offset }); | - | ||||||
1988 | } executed 50 times by 7 tests: end of block Executed by:
| 50 | ||||||
1989 | - | |||||||
1990 | void Assembler::jumpNotUndefined(int offset) | - | ||||||
1991 | { | - | ||||||
1992 | pasm()->jumpNotUndefined(offset); | - | ||||||
1993 | } never executed: end of block | 0 | ||||||
1994 | - | |||||||
1995 | void Assembler::prepareCallWithArgCount(int argc) | - | ||||||
1996 | { | - | ||||||
1997 | #ifndef QT_NO_DEBUG | - | ||||||
1998 | Q_ASSERT(remainingArgcForCall == NoCall); | - | ||||||
1999 | remainingArgcForCall = argc; | - | ||||||
2000 | #endif | - | ||||||
2001 | - | |||||||
2002 | if (argc > PlatformAssembler::ArgInRegCount) {
| 0-78696 | ||||||
2003 | argcOnStackForCall = int(WTF::roundUpToMultipleOf(16, size_t(argc - PlatformAssembler::ArgInRegCount) * PlatformAssembler::PointerSize)); | - | ||||||
2004 | pasm()->subPtr(TrustedImm32(argcOnStackForCall), PlatformAssembler::StackPointerRegister); | - | ||||||
2005 | } never executed: end of block | 0 | ||||||
2006 | } executed 78696 times by 64 tests: end of block Executed by:
| 78696 | ||||||
2007 | - | |||||||
2008 | void Assembler::storeInstructionPointer(int instructionOffset) | - | ||||||
2009 | { | - | ||||||
2010 | PlatformAssembler::Address addr(PlatformAssembler::CppStackFrameRegister, | - | ||||||
2011 | offsetof(QV4::CppStackFrame, instructionPointer)); | - | ||||||
2012 | pasm()->store32(TrustedImm32(instructionOffset), addr); | - | ||||||
2013 | } executed 44894 times by 62 tests: end of block Executed by:
| 44894 | ||||||
2014 | - | |||||||
2015 | Address argStackAddress(int arg) | - | ||||||
2016 | { | - | ||||||
2017 | int offset = arg - PlatformAssembler::ArgInRegCount; | - | ||||||
2018 | Q_ASSERT(offset >= 0); | - | ||||||
2019 | return Address(PlatformAssembler::StackPointerRegister, offset * PlatformAssembler::PointerSize); never executed: return Address(PlatformAssembler::StackPointerRegister, offset * PlatformAssembler::PointerSize); | 0 | ||||||
2020 | } | - | ||||||
2021 | - | |||||||
2022 | void Assembler::passAccumulatorAsArg(int arg) | - | ||||||
2023 | { | - | ||||||
2024 | #ifndef QT_NO_DEBUG | - | ||||||
2025 | Q_ASSERT(arg < remainingArgcForCall); | - | ||||||
2026 | --remainingArgcForCall; | - | ||||||
2027 | #endif | - | ||||||
2028 | - | |||||||
2029 | passAccumulatorAsArg_internal(arg, false); | - | ||||||
2030 | } executed 24336 times by 58 tests: end of block Executed by:
| 24336 | ||||||
2031 | - | |||||||
2032 | void Assembler::passAccumulatorAsArg_internal(int arg, bool push) | - | ||||||
2033 | { | - | ||||||
2034 | if (arg < PlatformAssembler::ArgInRegCount) {
| 0-24406 | ||||||
2035 | pasm()->addPtr(TrustedImm32(offsetof(CallData, accumulator)), | - | ||||||
2036 | PlatformAssembler::JSStackFrameRegister, | - | ||||||
2037 | pasm()->registerForArg(arg)); | - | ||||||
2038 | } else { executed 24406 times by 58 tests: end of block Executed by:
| 24406 | ||||||
2039 | pasm()->addPtr(TrustedImm32(offsetof(CallData, accumulator)), | - | ||||||
2040 | PlatformAssembler::JSStackFrameRegister, | - | ||||||
2041 | PlatformAssembler::ScratchRegister); | - | ||||||
2042 | if (push)
| 0 | ||||||
2043 | pasm()->push(PlatformAssembler::ScratchRegister); never executed: reinterpret_cast<PlatformAssembler *>(this->d)->push(PlatformAssembler::ScratchRegister); | 0 | ||||||
2044 | else | - | ||||||
2045 | pasm()->storePtr(PlatformAssembler::ScratchRegister, never executed: reinterpret_cast<PlatformAssembler *>(this->d)->storePtr(PlatformAssembler::ScratchRegister, argStackAddress(arg)); | 0 | ||||||
2046 | argStackAddress(arg)); never executed: reinterpret_cast<PlatformAssembler *>(this->d)->storePtr(PlatformAssembler::ScratchRegister, argStackAddress(arg)); | 0 | ||||||
2047 | } | - | ||||||
2048 | } | - | ||||||
2049 | - | |||||||
2050 | void Assembler::passFunctionAsArg(int arg) | - | ||||||
2051 | { | - | ||||||
2052 | #ifndef QT_NO_DEBUG | - | ||||||
2053 | Q_ASSERT(arg < remainingArgcForCall); | - | ||||||
2054 | --remainingArgcForCall; | - | ||||||
2055 | #endif | - | ||||||
2056 | - | |||||||
2057 | if (arg < PlatformAssembler::ArgInRegCount) {
| 0-40 | ||||||
2058 | pasm()->loadFunctionPtr(pasm()->registerForArg(arg)); | - | ||||||
2059 | } else { executed 40 times by 3 tests: end of block Executed by:
| 40 | ||||||
2060 | pasm()->loadFunctionPtr(PlatformAssembler::ScratchRegister); | - | ||||||
2061 | pasm()->storePtr(PlatformAssembler::ScratchRegister, | - | ||||||
2062 | argStackAddress(arg)); | - | ||||||
2063 | } never executed: end of block | 0 | ||||||
2064 | } | - | ||||||
2065 | - | |||||||
2066 | void Assembler::passEngineAsArg(int arg) | - | ||||||
2067 | { | - | ||||||
2068 | #ifndef QT_NO_DEBUG | - | ||||||
2069 | Q_ASSERT(arg < remainingArgcForCall); | - | ||||||
2070 | --remainingArgcForCall; | - | ||||||
2071 | #endif | - | ||||||
2072 | - | |||||||
2073 | if (arg < PlatformAssembler::ArgInRegCount) {
| 0-74114 | ||||||
2074 | pasm()->move(PlatformAssembler::EngineRegister, pasm()->registerForArg(arg)); | - | ||||||
2075 | } else { executed 74114 times by 63 tests: end of block Executed by:
| 74114 | ||||||
2076 | pasm()->storePtr(PlatformAssembler::EngineRegister, argStackAddress(arg)); | - | ||||||
2077 | } never executed: end of block | 0 | ||||||
2078 | } | - | ||||||
2079 | - | |||||||
2080 | void Assembler::passRegAsArg(int reg, int arg) | - | ||||||
2081 | { | - | ||||||
2082 | #ifndef QT_NO_DEBUG | - | ||||||
2083 | Q_ASSERT(arg < remainingArgcForCall); | - | ||||||
2084 | --remainingArgcForCall; | - | ||||||
2085 | #endif | - | ||||||
2086 | - | |||||||
2087 | if (arg < PlatformAssembler::ArgInRegCount) {
| 0-27120 | ||||||
2088 | pasm()->addPtr(TrustedImm32(reg * int(sizeof(QV4::Value))), | - | ||||||
2089 | PlatformAssembler::JSStackFrameRegister, | - | ||||||
2090 | pasm()->registerForArg(arg)); | - | ||||||
2091 | } else { executed 27120 times by 59 tests: end of block Executed by:
| 27120 | ||||||
2092 | pasm()->addPtr(TrustedImm32(reg * int(sizeof(QV4::Value))), | - | ||||||
2093 | PlatformAssembler::JSStackFrameRegister, | - | ||||||
2094 | PlatformAssembler::ScratchRegister); | - | ||||||
2095 | pasm()->storePtr(PlatformAssembler::ScratchRegister, | - | ||||||
2096 | argStackAddress(arg)); | - | ||||||
2097 | } never executed: end of block | 0 | ||||||
2098 | } | - | ||||||
2099 | - | |||||||
2100 | void JIT::Assembler::passCppFrameAsArg(int arg) | - | ||||||
2101 | { | - | ||||||
2102 | #ifndef QT_NO_DEBUG | - | ||||||
2103 | Q_ASSERT(arg < remainingArgcForCall); | - | ||||||
2104 | --remainingArgcForCall; | - | ||||||
2105 | #endif | - | ||||||
2106 | - | |||||||
2107 | if (arg < PlatformAssembler::ArgInRegCount) {
| 0-154 | ||||||
2108 | pasm()->move(PlatformAssembler::CppStackFrameRegister, pasm()->registerForArg(arg)); | - | ||||||
2109 | } else { executed 154 times by 9 tests: end of block Executed by:
| 154 | ||||||
2110 | pasm()->store32(PlatformAssembler::CppStackFrameRegister, argStackAddress(arg)); | - | ||||||
2111 | } never executed: end of block | 0 | ||||||
2112 | } | - | ||||||
2113 | - | |||||||
2114 | void Assembler::passInt32AsArg(int value, int arg) | - | ||||||
2115 | { | - | ||||||
2116 | #ifndef QT_NO_DEBUG | - | ||||||
2117 | Q_ASSERT(arg < remainingArgcForCall); | - | ||||||
2118 | --remainingArgcForCall; | - | ||||||
2119 | #endif | - | ||||||
2120 | - | |||||||
2121 | if (arg < PlatformAssembler::ArgInRegCount) {
| 0-53594 | ||||||
2122 | pasm()->move(TrustedImm32(value), pasm()->registerForArg(arg)); | - | ||||||
2123 | } else { executed 53594 times by 63 tests: end of block Executed by:
| 53594 | ||||||
2124 | pasm()->store32(TrustedImm32(value), argStackAddress(arg)); | - | ||||||
2125 | } never executed: end of block | 0 | ||||||
2126 | } | - | ||||||
2127 | - | |||||||
2128 | void Assembler::callRuntime(const char *functionName, const void *funcPtr, | - | ||||||
2129 | Assembler::CallResultDestination dest) | - | ||||||
2130 | { | - | ||||||
2131 | #ifndef QT_NO_DEBUG | - | ||||||
2132 | Q_ASSERT(remainingArgcForCall == 0); | - | ||||||
2133 | remainingArgcForCall = NoCall; | - | ||||||
2134 | #endif | - | ||||||
2135 | pasm()->callRuntime(functionName, funcPtr, dest); | - | ||||||
2136 | if (argcOnStackForCall > 0) {
| 0-78696 | ||||||
2137 | pasm()->addPtr(TrustedImm32(argcOnStackForCall), PlatformAssembler::StackPointerRegister); | - | ||||||
2138 | argcOnStackForCall = 0; | - | ||||||
2139 | } never executed: end of block | 0 | ||||||
2140 | } executed 78696 times by 64 tests: end of block Executed by:
| 78696 | ||||||
2141 | - | |||||||
2142 | void Assembler::saveAccumulatorInFrame() | - | ||||||
2143 | { | - | ||||||
2144 | pasm()->storeAccumulator(PlatformAssembler::Address(PlatformAssembler::JSStackFrameRegister, | - | ||||||
2145 | offsetof(CallData, accumulator))); | - | ||||||
2146 | } executed 24406 times by 58 tests: end of block Executed by:
| 24406 | ||||||
2147 | - | |||||||
2148 | void Assembler::checkException() | - | ||||||
2149 | { | - | ||||||
2150 | pasm()->addCatchyJump( | - | ||||||
2151 | pasm()->branch32( | - | ||||||
2152 | PlatformAssembler::NotEqual, | - | ||||||
2153 | PlatformAssembler::Address(PlatformAssembler::EngineRegister, | - | ||||||
2154 | offsetof(EngineBase, hasException)), | - | ||||||
2155 | TrustedImm32(0))); | - | ||||||
2156 | } executed 52604 times by 63 tests: end of block Executed by:
| 52604 | ||||||
2157 | - | |||||||
2158 | void Assembler::gotoCatchException() | - | ||||||
2159 | { | - | ||||||
2160 | pasm()->addCatchyJump(pasm()->jump()); | - | ||||||
2161 | } executed 100 times by 8 tests: end of block Executed by:
| 100 | ||||||
2162 | - | |||||||
2163 | void Assembler::getException() | - | ||||||
2164 | { | - | ||||||
2165 | Q_STATIC_ASSERT(sizeof(QV4::EngineBase::hasException) == 1); | - | ||||||
2166 | - | |||||||
2167 | Address hasExceptionAddr(PlatformAssembler::EngineRegister, | - | ||||||
2168 | offsetof(EngineBase, hasException)); | - | ||||||
2169 | PlatformAssembler::Jump nope = pasm()->branch8(PlatformAssembler::Equal, | - | ||||||
2170 | hasExceptionAddr, | - | ||||||
2171 | TrustedImm32(0)); | - | ||||||
2172 | pasm()->loadPtr(Address(PlatformAssembler::EngineRegister, | - | ||||||
2173 | offsetof(EngineBase, exceptionValue)), | - | ||||||
2174 | PlatformAssembler::ScratchRegister); | - | ||||||
2175 | pasm()->loadAccumulator(Address(PlatformAssembler::ScratchRegister)); | - | ||||||
2176 | pasm()->store8(TrustedImm32(0), hasExceptionAddr); | - | ||||||
2177 | auto done = pasm()->jump(); | - | ||||||
2178 | nope.link(pasm()); | - | ||||||
2179 | pasm()->loadValue(Primitive::emptyValue().asReturnedValue()); | - | ||||||
2180 | - | |||||||
2181 | done.link(pasm()); | - | ||||||
2182 | } never executed: end of block | 0 | ||||||
2183 | - | |||||||
2184 | void Assembler::setException() | - | ||||||
2185 | { | - | ||||||
2186 | auto noException = pasm()->jumpEmpty(); | - | ||||||
2187 | Address addr(PlatformAssembler::EngineRegister, offsetof(EngineBase, exceptionValue)); | - | ||||||
2188 | pasm()->loadPtr(addr, PlatformAssembler::ScratchRegister); | - | ||||||
2189 | pasm()->storeAccumulator(Address(PlatformAssembler::ScratchRegister)); | - | ||||||
2190 | addr.offset = offsetof(EngineBase, hasException); | - | ||||||
2191 | Q_STATIC_ASSERT(sizeof(QV4::EngineBase::hasException) == 1); | - | ||||||
2192 | pasm()->store8(TrustedImm32(1), addr); | - | ||||||
2193 | noException.link(pasm()); | - | ||||||
2194 | } never executed: end of block | 0 | ||||||
2195 | - | |||||||
2196 | void Assembler::setUnwindHandler(int offset) | - | ||||||
2197 | { | - | ||||||
2198 | auto l = pasm()->storePtrWithPatch(TrustedImmPtr(nullptr), pasm()->exceptionHandlerAddress()); | - | ||||||
2199 | pasm()->ehTargets.push_back({ l, offset }); | - | ||||||
2200 | } executed 92 times by 7 tests: end of block Executed by:
| 92 | ||||||
2201 | - | |||||||
2202 | - | |||||||
2203 | void Assembler::clearUnwindHandler() | - | ||||||
2204 | { | - | ||||||
2205 | pasm()->storePtr(TrustedImmPtr(nullptr), pasm()->exceptionHandlerAddress()); | - | ||||||
2206 | } executed 58 times by 7 tests: end of block Executed by:
| 58 | ||||||
2207 | - | |||||||
2208 | void JIT::Assembler::unwindDispatch() | - | ||||||
2209 | { | - | ||||||
2210 | checkException(); | - | ||||||
2211 | pasm()->load32(Address(PlatformAssembler::CppStackFrameRegister, offsetof(CppStackFrame, unwindLevel)), PlatformAssembler::ScratchRegister); | - | ||||||
2212 | auto noUnwind = pasm()->branch32(PlatformAssembler::Equal, PlatformAssembler::ScratchRegister, TrustedImm32(0)); | - | ||||||
2213 | pasm()->sub32(TrustedImm32(1), PlatformAssembler::ScratchRegister); | - | ||||||
2214 | pasm()->store32(PlatformAssembler::ScratchRegister, Address(PlatformAssembler::CppStackFrameRegister, offsetof(CppStackFrame, unwindLevel))); | - | ||||||
2215 | auto jump = pasm()->branch32(PlatformAssembler::Equal, PlatformAssembler::ScratchRegister, TrustedImm32(0)); | - | ||||||
2216 | gotoCatchException(); | - | ||||||
2217 | jump.link(pasm()); | - | ||||||
2218 | - | |||||||
2219 | pasm()->loadPtr(Address(PlatformAssembler::CppStackFrameRegister, offsetof(CppStackFrame, unwindLabel)), PlatformAssembler::ScratchRegister); | - | ||||||
2220 | pasm()->jump(PlatformAssembler::ScratchRegister); | - | ||||||
2221 | - | |||||||
2222 | noUnwind.link(pasm()); | - | ||||||
2223 | } executed 50 times by 7 tests: end of block Executed by:
| 50 | ||||||
2224 | - | |||||||
2225 | void JIT::Assembler::unwindToLabel(int level, int offset) | - | ||||||
2226 | { | - | ||||||
2227 | auto l = pasm()->storePtrWithPatch(TrustedImmPtr(nullptr), Address(PlatformAssembler::CppStackFrameRegister, offsetof(CppStackFrame, unwindLabel))); | - | ||||||
2228 | pasm()->ehTargets.push_back({ l, offset }); | - | ||||||
2229 | pasm()->store32(TrustedImm32(level), Address(PlatformAssembler::CppStackFrameRegister, offsetof(CppStackFrame, unwindLevel))); | - | ||||||
2230 | gotoCatchException(); | - | ||||||
2231 | } executed 8 times by 1 test: end of block Executed by:
| 8 | ||||||
2232 | - | |||||||
2233 | void Assembler::pushCatchContext(int index, int name) | - | ||||||
2234 | { | - | ||||||
2235 | prepareCallWithArgCount(3); | - | ||||||
2236 | passInt32AsArg(name, 2); | - | ||||||
2237 | passInt32AsArg(index, 1); | - | ||||||
2238 | passRegAsArg(CallData::Context, 0); | - | ||||||
2239 | IN_JIT_GENERATE_RUNTIME_CALL(Runtime::method_createCatchContext, ResultInAccumulator); | - | ||||||
2240 | pasm()->storeAccumulator(pasm()->contextAddress()); | - | ||||||
2241 | } executed 50 times by 7 tests: end of block Executed by:
| 50 | ||||||
2242 | - | |||||||
2243 | void Assembler::popContext() | - | ||||||
2244 | { | - | ||||||
2245 | Heap::CallContext ctx; | - | ||||||
2246 | Q_UNUSED(ctx) | - | ||||||
2247 | pasm()->loadPointerFromValue(regAddr(CallData::Context), PlatformAssembler::ScratchRegister); | - | ||||||
2248 | pasm()->loadAccumulator(Address(PlatformAssembler::ScratchRegister, ctx.outer.offset)); | - | ||||||
2249 | pasm()->storeAccumulator(regAddr(CallData::Context)); | - | ||||||
2250 | } executed 204 times by 11 tests: end of block Executed by:
| 204 | ||||||
2251 | - | |||||||
2252 | void Assembler::ret() | - | ||||||
2253 | { | - | ||||||
2254 | pasm()->generateFunctionExit(); | - | ||||||
2255 | } executed 13404 times by 64 tests: end of block Executed by:
| 13404 | ||||||
2256 | - | |||||||
2257 | } // JIT namespace | - | ||||||
2258 | } // QV4 namepsace | - | ||||||
2259 | - | |||||||
2260 | QT_END_NAMESPACE | - | ||||||
2261 | - | |||||||
2262 | #endif // V4_ENABLE_JIT | - | ||||||
Source code | Switch to Preprocessed file |