aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jit/qv4baselineassembler.cpp
Commit message (Collapse)AuthorAgeFilesLines
* Mark the JIT related code as security criticalFabian Kosmale2025-07-071-0/+1
| | | | | | | | | | | | | | Anything emitting executable code at runtime obviously ought to be under utmost scrutinity, so mark most of the JIT related files as critical. Two of the three headers don't contain any actual logic, they get the (default) significant label. Fixes: QTBUG-138341 Pick-to: 6.10 6.9 6.8 QUIP: 23 Change-Id: I80a39a0154d176c58dee1d865e33cf32149b3a82 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* JIT: storeLocal needs to go through WriteBarrierFabian Kosmale2024-06-181-0/+14
| | | | | | | | | | | | | | The interpreter already has the necessary setup, but the JIT did simply write the value without marking so far. We fix this by adding a new runtime function call, which simply uses QV4::WriteBarrier::markCustom to mark the given value. Both the StoreLocal and StoreScopedLocal bytecode instructions are handled by adding the code to BaselineAssembler::storeLocal. Pick-to: 6.8 Change-Id: I4b9226848bff029a076c0cfa6daf899ca9b84622 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* QtQml: Move engine-specific data out of base compilation unitUlf Hermann2024-01-081-1/+1
| | | | | | | | | | We want to re-use the base compilation unit for different engines. To do that, we cannot have data in there that belongs to a specific engine. Pick-to: 6.7 Task-number: QTBUG-120189 Change-Id: I8e43e7ec6c1cd33249dc4ed15fec16babc6d06fb Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* JIT: Fix isNullOrUndefined bad logicOlivier De Cannière2023-02-151-2/+1
| | | | | | | | | | | | | | | | | | | A logic error was left over in isNullOrUndefined that didn't actually check for null of undefined after a change of encoding. tst_qqmllanguage::isNullOrUndefined() was added to check the bug doesn't happen anymore. Two cases are tested. The first is intended to run on the interpreter. It was fine before this change and should be fine afterwards. The second one calls the same function many times for JIT optimizations to kick in and compile the function. This should ensure the broken '??' and '?.' operators are fixed when running on the JIT. Amends c7722d4ed61d6a887e9f6c403ffa10b2048de2a4. Fixes: QTBUG-111088 Pick-to: 6.5 Change-Id: I0e6d77363770e801aa586588e242220dec9d5e0a Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* Change value encoding scheme to make space for larger pointersUlf Hermann2023-01-121-12/+23
| | | | | | | | | | | | | | | | | | On android and on some other platforms, the upper bits of a pointer are significant. We need to store them in our JS value encoding. Shift the bits around to make this happen. We now can store pointers of up to 57 bits. That's enough for everything we've seen so far. Fixes: QTBUG-101686 Fixes: QTBUG-91150 Pick-to: 6.5 Change-Id: I72e0fe63b27fca94840f82963e4d3936b3581b28 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Sami Shalayel <sami.shalayel@qt.io> Reviewed-by: Ville Voutilainen <ville.voutilainen@qt.io>
* Use SPDX license identifiersLucie Gérard2022-06-111-38/+2
| | | | | | | | | | | | Replace the current license disclaimer in files by a SPDX-License-Identifier. Files that have to be modified by hand are modified. License files are organized under LICENSES directory. Pick-to: 6.4 Task-number: QTBUG-67283 Change-Id: I63563bbeb6f60f89d2c99660400dca7fab78a294 Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
* Implement optional chainingMaximilian Goldstein2021-04-131-0/+17
| | | | | | | | | | | | | | | | | This change implements optional chaining (https://github.com/tc39/proposal-optional-chaining) by adding a new type of optional lookup with an offset to the end of a chain. If `undefined` or `null` is encountered during an access marked as optional, we jump to that end offset. Features: - Full support for all kinds of optional chain - With some codegen overhead but zero overhead during normal non-optional FieldMemberExpression resolution - Properly retains this contexts and does not need to resolve anything twice (this has been an issue previously) - No extra AST structures, just flags for existing ones [ChangeLog][QtQml] Added support for optional chaining (https://github.com/tc39/proposal-optional-chaining) Fixes: QTBUG-77926 Change-Id: I9a41cdc4ca272066c79c72b9b22206498a546843 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* CMake: Disable JIT for arm64 when doing macOS universal buildsAlexandru Croitor2021-04-031-0/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Our current approach to building universal macOS Qt is to pass 2 -arch flags to clang, which underneath spawn 2 clang invocations with each separate arch and lipo-s the result together. This approah also meanss that we do only one set of config tests for the main (first) architecture. Currently Qml doesn't support JITing for macOS on Apple Silicon (arm64), but if the first architecture is x86_64, the qml_jit feature will be set to 'true', and cause compilation errors when trying to build the arm slice of the jit source files. To circumvent that, and allow skipping compilation of JIT specific code, we have to apply the same trick we do in qtbase, which is to set a compile definition that takes the current architecture into account, and surround all relevant code with an #if block taking to account both the feature and current architecture. Use a custom hacky qt_extra_definition call to redefine the value of QT_FEATURE_qml_jit based on the original feature value and the current architecture. Additionally, surround the jit source files with #if QT_CONFIG(qml_jit). Amends 561a2cec9b95b22783a00b48078b532010357066 Task-number: QTBUG-85447 Change-Id: I28b286d218333076223177c456175f180888a667 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* Optimize stack frame setup for AOT compiled functionsUlf Hermann2021-03-231-6/+6
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | When called via the metaobject system, parameters and return values are passed as void*, with accompanying type information in the form of QMetaType. The same format is expected when calling an AOT compiled function. Previously, we would first convert all the parameters to QV4::Value, just to convert them back the moment we notice that there is an AOT compiled function. This is wasteful. This change provides a second call infrastructure that accepts void* and QMetaType as parameter and return value format, and passes them as-is all the way to any AOT compiled functions. If there is no AOT compiled function, the conversion is done when detecting this, rather than when initiating the call. This also passes the information "ignore return value" all the way down to the actual function call. If the caller is not interested in the return value, we don't have to marshal it back at all. For now, we only add the extra "callWithMetaTypes" vtable entry to ArrowFunction. However, other callables could also receive variants optimized for calling with void*/int rather than V4 values. This required changing the way how function arguments are stored in the property cache. We squeeze the return type into QQmlPropertyCacheMethodArguments now, and we use QMetaType instead of integers. In turn, we remove some unused bits. Change-Id: I946e603e623d9d985c54d3a15f6f4b7c7b7d8c60 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* Add ; to Q_UNUSED and UNUSED_PARAMLars Schmertmann2020-06-261-3/+3
| | | | | | | | | This is required to remove the ; from the macro with Qt 6. Task-number: QTBUG-82978 Change-Id: Iead53d18fd790fb2d870d80ef2db79666f0d2392 Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io> Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* Fix failing assertion in the GC with the JITSimon Hausmann2020-04-221-0/+4
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Commit db3dd029d7cd911712102efd5ea71868494f9f6f introduced the saving of the accumulator register on the JS stack in more situations. This unveiled another bug: When the physical ACC register contains garbage, we may end up saving it on the stack and thus making it visible to the GC. That one may trip with the infamous Q_ASSERT(m->inUse()) assertion failing when the value looks like a managed pointer but in fact isn't. So the question is: How can garbage end up in the physical ACC register? Thanks to a detailed bug report from David Faure, KDE's ktexteditor kateindenttest (testCstyle:comma6 in particular) triggered this situation when run with aggressive GC, where the prologue of a generated constructor function started with two instructions CreateCallContext ConvertThisToObject The first instruction is a call into the run-time with CallResultDestination::Ignore - it's a "void" call. The second instruction starts with STORE_ACC and also ends up allocating memory, triggering the GC when run with aggressive mode enabled. The problem here is the ::Ignore option for the return value. It means that the ReturnValueRegister is clobbered and may contain anything. If the ReturnValueRegister is the same as the AccumulatorRegister, then the STORE_ACC call later will end up writing "garbage" into the JS stack. As a remedy, this patch treats the ::Ignore case special and loads undefined into the ACC when the return value register and the ACC register are the same. Change-Id: I82c7a3456125f9c87e83abb9eb54465106873560 Task-number: QTBUG-83384 Pick-to: 5.15 Pick-to: 5.12 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
* JSRuntime: Provide an optional symbol tableUlf Hermann2019-10-161-35/+27
| | | | | | | | | | The method names are only used for debugging purposes. We don't need to pass them through production code. Centralize the names of all the runtime methods in a symbol table and only look them up when actually printing them. Change-Id: I0d9d7db04b961841242acdbaaa7a2ba29b1f4ff2 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Merge remote-tracking branch 'origin/5.13' into 5.14Qt Forward Merge Bot2019-09-171-1/+6
|\ | | | | | | | | | | | | | | | | Conflicts: src/qml/jit/qv4baselinejit.cpp src/qml/jsruntime/qv4vme_moth.cpp tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp Change-Id: Iec7cd27ddad0281bd3b7833fb6b252f66a6ae5d6
| * Merge remote-tracking branch 'origin/5.12' into 5.13Qt Forward Merge Bot2019-09-121-1/+6
| |\ | | | | | | | | | Change-Id: I6472cd72b27c69257efe54376e428274ebf68050
| | * Fix various accumulator-saving problemsUlf Hermann2019-09-031-1/+6
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | We need to keep the accumulator alive across function calls. This requires: 1, Saving the accumulator on the stack if the function might allocate, to protect it from the garbage collector. However, we don't need to do that if the result of the function is to be saved in the accumulator and the function itself doesn't use the accumulator as argument. In this case the previous value becomes unaccessible and we might as well GC it. 2, In the JIT, restoring the accumulator from the stack after the function call if we want to ignore the return value. 3, Therefore, also saving the accumulator on the stack before calling in case of 2. We assume that we don't need to keep the accumulator alive across the jump to the exception handler. Saving the accumulator more often than necessary is detrimental for performance. To make sure the assumption holds, explicitly load the accumulator with undefined _before_ jumping to any exception handler. Change-Id: I78cbc42847b8885a0659b23f3b81655b7f1a0bc4 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* | | Transform V4_ENABLE_JIT into a featureUlf Hermann2019-04-251-4/+0
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This way you can enable or disable the JIT when configuring Qt. The conditions for the availability of the JIT have also been cleaned up. There is no reason anymore to artificially restrict availability on x86 and x86_64. The reason for the existence of those clauses are old problems on windows that have been fixed by now. However, on arm and arm64, we need a specialization of the cacheFlush() function for each OS to be supported. Therefore, restrict to the systems for which such a specialization exists. iOS and tvOS are technically supported and you can enable the JIT via the feature flag now. Due to Apple's policy we disable it by default, though. Change-Id: I5fe2a2bf6799b2d11b7ae7c7a85962bcbf44f919 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* | | Merge remote-tracking branch 'origin/5.13' into HEADUlf Hermann2019-03-221-16/+16
|\| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Conflicts: src/qml/compiler/qv4compileddata_p.h src/qml/jit/qv4baselinejit.cpp src/qml/jit/qv4jithelpers.cpp src/qml/jsruntime/qv4lookup.cpp src/qml/jsruntime/qv4runtime.cpp src/qml/jsruntime/qv4runtimeapi_p.h src/qml/jsruntime/qv4vme_moth.cpp src/qml/qml/qqmltypemodule_p.h Change-Id: If28793e9e08418457a11fc2c5832f03cab2fcc76
| * | Merge remote-tracking branch 'origin/5.12' into 5.13Qt Forward Merge Bot2019-03-211-16/+16
| |\| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Conflicts: src/qml/compiler/qqmltypecompiler.cpp src/qml/compiler/qv4bytecodehandler.cpp src/qml/compiler/qv4codegen.cpp src/qml/compiler/qv4compileddata_p.h src/qml/compiler/qv4compiler.cpp src/qml/compiler/qv4instr_moth.cpp src/qml/compiler/qv4instr_moth_p.h src/qml/jit/qv4baselinejit.cpp src/qml/jit/qv4baselinejit_p.h src/qml/jsruntime/qv4function.cpp src/qml/jsruntime/qv4vme_moth.cpp Change-Id: I8fb4d6f19677bcec0a4593b250f2eda5ae85e3d2
| | * Baseline JIT: Save accumulator in toInt32LhsAcc()Ulf Hermann2019-03-191-16/+16
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | toInt32LhsAcc convertes both the lhs and the accumulator to int32. If the accumulator is not saved, a GC run during the conversion of the lhs might trash its value. Fixes: QTBUG-74058 Change-Id: Ic42693061c7d483bb430d77bcc095de6ff9a6843 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* | | V4: Clean up the runtime functions declarationsErik Verbruggen2019-02-051-32/+28
|/ / | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The declarations and usage of runtime functions have seen a number of changes: - we don't use the array of method pointers anymore because we don't use cross-platform AOT JITting - the check if a method can throw a JS exception was invalid, and was not used anymore - value-pointer vs. const-value-ref was inconsistent This patch cleans that up. By fixing the exception checking, we can now use it in the baseline JIT to automatically insert those checks. To make that work correctly, all runtime methods are in a struct, which gets annotated to indicate if that method throws. (The old way of checking which type of engine was used is fragile: some non-throwing methods do not take an engine parameter at all, and those got flagged as throwing). By using a struct, we can also get rid of a bunch of interesting macros. The flags in the struct (as mentioned above) can later be extended to capture more information, e.g. if a method will change the context. Change-Id: I1e0b9ba62a0bf538eb728b4378e2678136e29a64 Reviewed-by: Lars Knoll <lars.knoll@qt.io>
* | V4: Generate labels for backward jumpsErik Verbruggen2019-01-311-7/+14
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | When analyzing the bytecode from top-to-bottom in a single pass, we don't know when a jump back to previously seen code occurs. For example, in the baseline JIT we would already have generated code for some bytecode when we see a jump back (like at the end of a loop body), and we can't go back and insert a label to jump to. As JavaScript has no goto's, the only backward jumps are at the end of loops, so there are very few cases where we need to actually generate labels. This was previously handled by analyzing the bytecode twice: once to collect all jump targets, and then second pass over the bytecode to do the actual JITting (which would use the jump targets to insert labels). We can now do that with one single pass. So the trade-off is to store 4 bytes more per function plus 4 bytes for each loop, instead of having to analyze all functions only to find where all jumps are each time that function is JITted. Change-Id: I3abfcb69f65851a397dbd4a9762ea5e9e57495f6 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* | V4: Collect trace information in the interpreterErik Verbruggen2019-01-251-0/+5
|/ | | | | | | | | | | | | | | Collect type information about values used in a function. These include all parameters, and the results of many bytecode instructions. For array loads/stores, it also tracks if the access is in-bounds of a SimpleArrayData. Collection is only enabled when the qml-tracing feature is turned on while configuring. In subsequent patches this is used to generated optimized JITted code. Change-Id: I63985c334c3fdc55fca7fb4addfe3e535989aac5 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* V4: Fix stack alignment in JITted codeErik Verbruggen2019-01-101-11/+31
| | | | | | | | | | | Helper calls done for to-integer and to-number conversions did not align the stack on 16byte boundaries, which could lead to crashes if somewhere in that call a vector instruction is used that expects such alignment. Task-number: QTBUG-71325 Change-Id: Ieec05a93a1f69b538e6c8930b8eb64cbe85c35d4 Reviewed-by: Jüri Valdmann <juri.valdmann@qt.io> Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* V4: Fix 32bit moveReg to not use the return value registersErik Verbruggen2018-11-061-4/+4
| | | | | | | | | | | As with the 64bit implementation: use the scratch register. The return value register is used to hold the newly allocated space on the JS stack. Fixes: QTBUG-71319 Change-Id: Ia924ad24ff7f4fbf5ec21b6e6237cce7d907bf3e Reviewed-by: Simon Hausmann <simon.hausmann@qt.io> Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
* Revert "BaselineJIT: slightly improve arm codegen for shifts"Lars Knoll2018-10-151-3/+6
| | | | | | | | | This reverts commit 41e15cb21c2f8924eee56aacc4ba8aace950cae5. The patch causes us to hit assertions in the x86/x64 JIT. Somehow this slipped through CI. Change-Id: Ia77ecb956472172bf5543c01fdccd6dddedba168 Reviewed-by: Erik Verbruggen <erik.verbruggen@qt.io>
* BaselineJIT: slightly improve arm codegen for shiftsv5.12.0-beta2Erik Verbruggen2018-10-121-6/+3
| | | | | Change-Id: I7327f982d11a0d2942750ebfbc9f0d379093b87e Reviewed-by: Lars Knoll <lars.knoll@qt.io>
* ES7: Implement Tail Position Calls in the runtimeErik Verbruggen2018-10-051-1/+23
| | | | | Change-Id: If1629109722496b3fd10b36b2376548440f2fee9 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* Remove unused variable 'EmptyTag'Liang Qi2018-09-271-1/+0
| | | | | Change-Id: I5970e3261a8a0891965c99d4d8c352ebf4cc6681 Reviewed-by: Erik Verbruggen <erik.verbruggen@qt.io>
* Cleanups in Value/PrimitiveLars Knoll2018-09-171-5/+5
| | | | | | | | | | | | Get rid of Primitive and move the corresponding methods directly into Value. Mark many methods in Value as constexpr and turn Value into a POD type again. Keep Primitive as a pure alias to Value for source compatibility of other modules that might be using it. Change-Id: Icb47458947dd3482c8852e95782123ea4346f5ec Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
* V4: Add JIT kind to disassemblyErik Verbruggen2018-08-301-1/+1
| | | | | Change-Id: I6dd1cd6f795a93a186e84f5ab1c606f7e23fb85d Reviewed-by: Lars Knoll <lars.knoll@qt.io>
* Implement the dead temporal zoneSimon Hausmann2018-08-281-0/+24
| | | | | | | | | | | | | | With const and let it is possible to access the declared member before initialization. This is expected to throw a type reference error at run-time. We initialize such variables with the empty value when entering their scope and check upon access for that. For locals we place the lexically scoped variables at the end. For register allocated lexical variables we group them into one batch and remember the index/size. Change-Id: Icb493ee0de0525bb682e1bc58981a4dfd33f750e Reviewed-by: Lars Knoll <lars.knoll@qt.io>
* V4: Split PlatformAssemblerCommon (and base classes) in its own fileErik Verbruggen2018-08-271-0/+1551
This makes it easier to re-use them later on, without inheriting all extra stuff that the baseline JIT needs. Change-Id: I9368b16017b8b9d99f8c005a5b47ec9f9ed09fb0 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>