| 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted by: 
 | 78770 | ||||||
| 641 | - | |||||||
| 642 | void saveReturnValueInAccumulator() | - | ||||||
| 643 | { | - | ||||||
| 644 | move(ReturnValueRegister, AccumulatorRegister); | - | ||||||
| 645 | } executed 77464 times by 64 tests:  end of blockExecuted by: 
 | 77464 | ||||||
| 646 | - | |||||||
| 647 | void loadUndefined(RegisterID dest = AccumulatorRegister) | - | ||||||
| 648 | { | - | ||||||
| 649 | move(TrustedImm64(0), dest); | - | ||||||
| 650 | } executed 13216 times by 64 tests:  end of blockExecuted 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 blockExecuted by: 
 | 28 | ||||||
| 658 | load64(loadConstAddress(constIndex, ScratchRegister), ScratchRegister); | - | ||||||
| 659 | } executed 936 times by 18 tests:  end of blockExecuted by: 
 | 936 | ||||||
| 660 | store64(ScratchRegister, dest); | - | ||||||
| 661 | } executed 964 times by 18 tests:  end of blockExecuted 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 blockExecuted by: 
 | 610 | ||||||
| 673 | - | |||||||
| 674 | void loadAccumulator(Address addr) | - | ||||||
| 675 | { | - | ||||||
| 676 | load64(addr, AccumulatorRegister); | - | ||||||
| 677 | } executed 6676 times by 43 tests:  end of blockExecuted by: 
 | 6676 | ||||||
| 678 | - | |||||||
| 679 | void storeAccumulator(Address addr) | - | ||||||
| 680 | { | - | ||||||
| 681 | store64(AccumulatorRegister, addr); | - | ||||||
| 682 | } executed 79570 times by 64 tests:  end of blockExecuted 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 blockExecuted by: 
 | 3186 | ||||||
| 689 | - | |||||||
| 690 | void loadString(int stringId) | - | ||||||
| 691 | { | - | ||||||
| 692 | loadAccumulator(loadStringAddress(stringId)); | - | ||||||
| 693 | } executed 3286 times by 31 tests:  end of blockExecuted by: 
 | 3286 | ||||||
| 694 | - | |||||||
| 695 | void loadValue(ReturnedValue value) | - | ||||||
| 696 | { | - | ||||||
| 697 | move(TrustedImm64(value), AccumulatorRegister); | - | ||||||
| 698 | } executed 4828 times by 45 tests:  end of blockExecuted by: 
 | 4828 | ||||||
| 699 | - | |||||||
| 700 | void storeHeapObject(RegisterID source, Address addr) | - | ||||||
| 701 | { | - | ||||||
| 702 | store64(source, addr); | - | ||||||
| 703 | } executed 154 times by 9 tests:  end of blockExecuted by: 
 | 154 | ||||||
| 704 | - | |||||||
| 705 | void generateCatchTrampoline() | - | ||||||
| 706 | { | - | ||||||
| 707 | PlatformAssemblerCommon::generateCatchTrampoline([this](){loadUndefined();}); executed 13188 times by 64 tests:  end of blockExecuted by: 
 | 13188 | ||||||
| 708 | } executed 13188 times by 64 tests:  end of blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted by: 
 | 70 | ||||||
| 844 | - | |||||||
| 845 | void popValueAligned() | - | ||||||
| 846 | { | - | ||||||
| 847 | addPtr(TrustedImm32(2 * PointerSize), StackPointerRegister); | - | ||||||
| 848 | } executed 70 times by 10 tests:  end of blockExecuted 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 blockExecuted 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 blockExecuted by: 
 | 13188 | ||||||
| 1296 | - | |||||||
| 1297 | Assembler::~Assembler() | - | ||||||
| 1298 | { | - | ||||||
| 1299 | delete pasm(); | - | ||||||
| 1300 | } executed 13188 times by 64 tests:  end of blockExecuted by: 
 | 13188 | ||||||
| 1301 | - | |||||||
| 1302 | void Assembler::generatePrologue() | - | ||||||
| 1303 | { | - | ||||||
| 1304 | pasm()->generateFunctionEntry(); | - | ||||||
| 1305 | } executed 13188 times by 64 tests:  end of blockExecuted by: 
 | 13188 | ||||||
| 1306 | - | |||||||
| 1307 | void Assembler::generateEpilogue() | - | ||||||
| 1308 | { | - | ||||||
| 1309 | pasm()->generateCatchTrampoline(); | - | ||||||
| 1310 | } executed 13188 times by 64 tests:  end of blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted by: 
 | 4 | ||||||
| 1435 | } | - | ||||||
| 1436 | } executed 13188 times by 64 tests:  end of blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted by: 
 | 964 | ||||||
| 1457 | - | |||||||
| 1458 | void Assembler::loadReg(int reg) | - | ||||||
| 1459 | { | - | ||||||
| 1460 | pasm()->loadAccumulator(regAddr(reg)); | - | ||||||
| 1461 | } executed 2654 times by 31 tests:  end of blockExecuted 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 blockExecuted by: 
 | 3186 | ||||||
| 1467 | - | |||||||
| 1468 | void Assembler::storeReg(int reg) | - | ||||||
| 1469 | { | - | ||||||
| 1470 | pasm()->storeAccumulator(regAddr(reg)); | - | ||||||
| 1471 | } executed 54864 times by 63 tests:  end of blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted by: 
 | 46 | ||||||
| 1496 | - | |||||||
| 1497 | void Assembler::loadString(int stringId) | - | ||||||
| 1498 | { | - | ||||||
| 1499 | pasm()->loadString(stringId); | - | ||||||
| 1500 | } executed 3286 times by 31 tests:  end of blockExecuted by: 
 | 3286 | ||||||
| 1501 | - | |||||||
| 1502 | void Assembler::loadValue(ReturnedValue value) | - | ||||||
| 1503 | { | - | ||||||
| 1504 | pasm()->loadValue(value); | - | ||||||
| 1505 | } executed 4758 times by 44 tests:  end of blockExecuted 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 blockExecuted by: 
 | 154 | ||||||
| 1511 | - | |||||||
| 1512 | void Assembler::toNumber() | - | ||||||
| 1513 | { | - | ||||||
| 1514 | pasm()->toNumber(); | - | ||||||
| 1515 | } executed 2 times by 1 test:  end of blockExecuted 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 blockExecuted 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 blockExecuted by: 
 | 326 | ||||||
| 1559 | checkException(); | - | ||||||
| 1560 | - | |||||||
| 1561 | // done. | - | ||||||
| 1562 | done.link(pasm()); | - | ||||||
| 1563 | } executed 326 times by 13 tests:  end of blockExecuted 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 blockExecuted by: 
 | 288 | ||||||
| 1591 | checkException(); | - | ||||||
| 1592 | - | |||||||
| 1593 | // done. | - | ||||||
| 1594 | done.link(pasm()); | - | ||||||
| 1595 | } executed 288 times by 6 tests:  end of blockExecuted 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 blockExecuted by: 
 | 268 | ||||||
| 1604 | } executed 134 times by 10 tests:  end of blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted by: 
 | 496 | ||||||
| 1970 | } executed 248 times by 9 tests:  end of blockExecuted 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 blockExecuted by: 
 | 6852 | ||||||
| 1978 | } executed 3426 times by 37 tests:  end of blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted by: 
 | 52604 | ||||||
| 2157 | - | |||||||
| 2158 | void Assembler::gotoCatchException() | - | ||||||
| 2159 | { | - | ||||||
| 2160 | pasm()->addCatchyJump(pasm()->jump()); | - | ||||||
| 2161 | } executed 100 times by 8 tests:  end of blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted by: 
 | 204 | ||||||
| 2251 | - | |||||||
| 2252 | void Assembler::ret() | - | ||||||
| 2253 | { | - | ||||||
| 2254 | pasm()->generateFunctionExit(); | - | ||||||
| 2255 | } executed 13404 times by 64 tests:  end of blockExecuted 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 |