aboutsummaryrefslogtreecommitdiffstats
path: root/src/qmlcompiler/qqmljsbasicblocks.cpp
Commit message (Collapse)AuthorAgeFilesLines
* qqmljsbasicblocks: escape <> when dumping dot filesSami Shalayel2025-04-041-0/+1
| | | | | | | | It turns out that <> characters need to be escaped in the dot format. They are emitted by the `SetUnwindHandler <null>` instruction. Change-Id: I279cd29cde8501007e388b027c4fe2e9e18ce38c Reviewed-by: Olivier De Cannière <[email protected]>
* Compiler: Fix various clazy warningsOlivier De Cannière2025-03-211-3/+3
| | | | | Change-Id: Ib83c8d3452d5a0521295750f068f429b414da6ff Reviewed-by: Fabian Kosmale <[email protected]>
* QtQml: Add some consistency to QV4::RegExpUlf Hermann2024-12-121-2/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | The RegExp JIT should behave the same as the V4 JIT. In particular, it should honor the same JIT call threshold and not second guess any manually set thresholds. To do this we need to store the match count in 32 bits. In turn we can store the 5 flags we may have in 8 bits. To make this safe, pass typed flags to the initialization functions. Also, consider the flags when calculating hash values. Finally, in the init() function, we don't need to initialize members to zero, since that is already guaranteed by the memory manager. And we can delete the flagsAsString() method since it's unused. This requires shuffling some #includes into the places where they actually belong. [ChangeLog][QtQml] The JavaScript regular expression engine now honors QV4_JIT_CALL_THRESHOLD for its own JIT. If QV4_JIT_CALL_THRESHOLD is not set, it uses the JIT after 3 interpreted matches for any regular expression, rather than the previous 5. Matching a regular expression on a string longer than 1024 bytes counts as 3 matches. This is to retain the default behavior of JIT'ing regular expressions right away when encountering long strings. Task-number: QTBUG-131957 Change-Id: I269ccea55d34b191ef18d7cd5fccd4cad8aec7cd Reviewed-by: Sami Shalayel <[email protected]> Reviewed-by: Fabian Kosmale <[email protected]>
* Compiler: Don't copy bytecode unnecesarillyOlivier De Cannière2024-08-011-1/+1
| | | | | Change-Id: I02a67c7ecf2345a026b42d1c1b5092e99b80e654 Reviewed-by: Fabian Kosmale <[email protected]>
* QmlCompiler: Remove unused QQmlJSCompilePass::readTypesUlf Hermann2024-06-161-4/+0
| | | | | | Change-Id: Ib3cb24e750c9bfdbcc21b781f0b3de92ee074c92 Reviewed-by: Fabian Kosmale <[email protected]> Reviewed-by: Olivier De Cannière <[email protected]>
* QmlCompiler: fix unity buildsTim Blechmann2024-04-301-10/+2
| | | | | | | | | | `deduplicate` was declared in two translation units, which is breaking unity builds. Moving the definition to QQmlJSUtils fixes the builds and makes the code more robust towards potential ODR violations in case the function is ever changed in one TU, but not in the other. Change-Id: I57627399d50d284ce031af245fd4ad5aa1ab6405 Reviewed-by: Ulf Hermann <[email protected]>
* Compiler: Extract Basic blocks generation into its own compiler passOlivier De Cannière2024-04-191-522/+11
| | | | | | | | | | | | | | | The old basic blocks pass was responsible for two things: the basic blocks generation and dead code analysis/type adjustments based on those blocks and the type propagation performed earlier. Now the basic blocks get generated first, even before the type propagation and the dead code analysis and type adjustments are now grouped in a pass called QQmlJSOptimizations. The rest of the passes remain unchanged. Change-Id: I7b4303eaf67c761a49b82ab194e5d035d24d2615 Reviewed-by: Fabian Kosmale <[email protected]> Reviewed-by: Ulf Hermann <[email protected]>
* QmlCompiler: Use a hash set for the list of conversionsUlf Hermann2024-01-201-17/+21
| | | | | | | | | | | | There can be a lot of them and we don't want quadratic behavior. It might be possible to further improve on this using e.g. sorted lists and algorithms provided by the STL. However, such an implementation would be more complicated and would require weighing several trade-offs. Pick-to: 6.7 6.6 6.5 Fixes: QTBUG-121139 Change-Id: I717b49bd4af97abcaae9ae78d1e1b31d5d462952 Reviewed-by: Fabian Kosmale <[email protected]> Reviewed-by: Marc Mutz <[email protected]>
* QmlCompiler: Do not adjust renamesUlf Hermann2023-12-071-0/+5
| | | | | | | | | | | | A rename always produces a register with exactly one tracked type, but we do not want to use it as base for the type adjustments. We want to adjust based on the original location and its readers (which includes any renames). Pick-to: 6.6 6.5 Change-Id: Iaefdf56992c7c101a35a056fb93c49ade5ccf393 Reviewed-by: Fabian Kosmale <[email protected]> Reviewed-by: Sami Shalayel <[email protected]>
* Compiler: Add initial support for optional chainingOlivier De Cannière2023-11-241-0/+6
| | | | | | | | | | This patch implements the GetOptionalLookup instruction in the compiler. This enables the use of optional chains. Fixes: QTBUG-111283 Change-Id: I265f611415a946468b828b9d41f549acfcc76233 Reviewed-by: Qt CI Bot <[email protected]> Reviewed-by: Fabian Kosmale <[email protected]>
* QmlCompiler: Implement GetIterator and IteratorNextUlf Hermann2023-09-211-0/+6
| | | | | | | | | | | | | | | | | | | | | | | | Each GetIterator generates * A unique iterator variable that keeps track of the current index * In the case of for...of a copy of reference to the list being iterated The result register holds a pointer to the unique iterator so that it can be loaded and stored without resetting it. In order to do anything meaningful with iterators (in the tests) we also need to allow LoadElement with our "optional" types. That is a conversion of undefined and some other type to QVariant or QJSPrimitiveValue. This follows the same pattern as the other "optional"s we already have. For...of is currently not testable because it requires exception handlers. The tests will be added once we get exception handlers. Task-number: QTBUG-116725 Change-Id: I167fe16b983dc34bf86e1840dfcbf2bf682eecc1 Reviewed-by: Qt CI Bot <[email protected]> Reviewed-by: Fabian Kosmale <[email protected]>
* QmlCompiler: Allow creation of actual QVariantMaps from object literalsUlf Hermann2023-08-251-4/+10
| | | | | | | | | | | | | | There are places where we need this: a, If the method in question actually takes a QVariantMap as argument. b, If the resulting value can be shadowed. In that case we expect a QVariant. The engine has to internally convert to the expected type then. Change-Id: Ic5b3faab4578d64ca757de644fe69660fd70e52a Reviewed-by: Fabian Kosmale <[email protected]> Reviewed-by: Sami Shalayel <[email protected]> Reviewed-by: Qt CI Bot <[email protected]>
* QmlCompiler: Allow construction of Array objectsUlf Hermann2023-08-221-10/+40
| | | | | | | | | | Currently, only the constructor form of the Array function is compiled. We only compile construction of Array objects if we can determine that they are immediately assigned to a typed list. Consequently, we don't have to deal with sparse arrays. Change-Id: I2abd15139eb9a0d530ad49df7313b8dba415ae77 Reviewed-by: Fabian Kosmale <[email protected]>
* QmlCompiler: Use reference rather than copy in for loopUlf Hermann2023-08-081-1/+1
| | | | | | Coverity-Id: 416461 Change-Id: Ibdb8de5a2491dfb7c688022d4f4b419876267d4d Reviewed-by: Fabian Kosmale <[email protected]>
* Compiler: Separate function prolog block and add validation of blocksOlivier De Cannière2023-08-041-37/+106
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The function prolog logic is now separated in its own basic block. The first "real" block with user code starts at offset 0. Having the function prolog as a hidden part of the first block caused some inconsistencies in block generation and would create empty blocks. This happened for example when a back edge of a loop would target offset 0 in code where a loop condition is the very first set of instructions that are run. This is because the target block offset didn't exist due to it being part of the hidden prolog block. Validation for the basic blocks was also added. This checks for three things at the moment: 1. That return and throw blocks don't have jump targets. 2. That the basic blocks graph is connected. 3. That jump targets are the first offset of a block. Test tst_QmlCppCodegen::basicBlocksWithBackJump_infinite() is expected to fail because it contains an infinite loop and the basic blocks that are generated for it are inconsistent due to dead-code elimination happening earlier in compilation. Debug outputs for dumping basic blocks were also adapted to reflect these changes. Change-Id: I513f73856412d488d443c2b47a052b0023d45496 Reviewed-by: Qt CI Bot <[email protected]> Reviewed-by: Fabian Kosmale <[email protected]>
* QmlCompiler: Refrain from converting when merging equal typesUlf Hermann2023-07-281-7/+10
| | | | | | | | Creating a conversion always loses some information and adds overhead. We can avoid it if both types are the same anyway. Change-Id: Ib32104f949704341c33033d6a5f36a705b6c2022 Reviewed-by: Fabian Kosmale <[email protected]>
* QmlCompiler: Avoid unnecessary copy in loopUlf Hermann2023-07-241-1/+1
| | | | | | | Coverity-Id: 415934 Change-Id: Id531c432b38b98060522f15f5546e335f35ba160 Reviewed-by: Fabian Kosmale <[email protected]> Reviewed-by: Olivier De Cannière <[email protected]>
* QmlCompiler: Avoid dereferencing past-end iteratorUlf Hermann2023-07-241-9/+7
| | | | | | | Coverity-Id: 415935 Change-Id: I5871c6aaa0985b7b36913aa27434e55a50245677 Reviewed-by: Fabian Kosmale <[email protected]> Reviewed-by: Olivier De Cannière <[email protected]>
* Compiler: Allow dumping the basic blocks for visualization and debuggingOlivier De Cannière2023-07-101-0/+103
| | | | | | | | | | | | | | | | | | | | If the QV4_DUMP_BASIC_BLOCKS environment variable is set, the compiler will output the details of the basic blocks of the compiled functions to the console. It will also generate a control flow graph containing the byte code in DOT format for easier visualization and debugging of the program execution and of the structure of the generated code. The value of QV4_DUMP_BASIC_BLOCKS will be used as the path to the folder in which to output the DOT files. If the path is any of ["-", "1", "true"] or if files can't be opened, it will be dumped to stdout instead. The logic in dumpByteCode has been adapted to use a QTextStream. This way it can continue to be used to dump the byte code of the whole program as before and also to construct the CFG. Change-Id: If398d795e4fc0950b5fa8ee1349e80b1ae262deb Reviewed-by: Ulf Hermann <[email protected]>
* QmlCompiler: Allow creation of structured value typesUlf Hermann2023-07-061-13/+90
| | | | | | | | | | | | | | | | With this change, qmlcachegen can populate structured value types from object literals. Also fix the construction of value types via Q_INVOKABLE ctors. We don't need to wrap the ctor argument in QVariant if we can store the original type, and we should always look at the base type for the creatable flag, not the extension. Task-number: QTBUG-107469 Task-number: QTBUG-112485 Change-Id: I9f3db13f00466dc9d87237bdf0b380d6eeb58a10 Reviewed-by: Sami Shalayel <[email protected]> Reviewed-by: Fabian Kosmale <[email protected]>
* QmlCompiler: Properly reset before re-running basic blocks passUlf Hermann2023-06-211-0/+2
| | | | | | | | | | | If we were within dead code at the end of the previous run we need to reset the "skip until next label" flag. Otherwise we still assume we're in dead code at the beginning of the function, with interesting effects. Pick-to: 6.5 6.6 Fixes: QTBUG-114476 Change-Id: Ib6e3d6c81aad4c8aaac12accdb3936e4136235fc Reviewed-by: Fabian Kosmale <[email protected]>
* QmlCachegen: Avoid adding a block's jumpOrigin a second timeOlivier De Cannière2023-06-201-1/+1
| | | | | | | | | | | | | | | | | | Each code block is reached either by a jump or simply by a fallthrough when the next instruction is executed. To model code flow, the origins of jumps (explicit or falltrough) to each block are recorded. The fallthrough jumpOrigins were added in two places: processJump and endInstruction. In some situations both would add the origin leading to duplication. Instead, have endInstruction be the only place where origins are added. And only have processJump add the block to m_basicBlocks to ensure it can be found by endInstruction. Change-Id: Ic5e4d7ab7c80f1f97f8373db9bf4b300f0f0ebd1 Reviewed-by: Qt CI Bot <[email protected]> Reviewed-by: Ulf Hermann <[email protected]>
* QmlCompiler: Remove emptyListTypeUlf Hermann2023-04-281-0/+1
| | | | | | | | | | | | It was a stop-gap solution on the way to actual list type support. It creates problems because it's a sequence type but doesn't have a value type. Add an assert to catch related problems earlier in the future. Fixes: QTBUG-113265 Change-Id: Iae955ab6c5ca41113095b523a5d6b9bcfd4d2396 Reviewed-by: Fabian Kosmale <[email protected]>
* QmlCompiler: Enforce sanity of type adjustments in basic blocks passUlf Hermann2023-03-111-12/+44
| | | | | | | | | | | | If we cannot properly adjust the types, the result will probably be garbage and we should not try to generate any code. We are double checking the actually received type in the code generator, but if we get a different type at code generation time than we "ordered" at type propagation time, that's not great. The type propagator should already have checked that the types are convertible, after all. Change-Id: I9c20dbd6b4cc8214e780dad9eb4302ca6ef81bac Reviewed-by: Fabian Kosmale <[email protected]>
* qmlcompiler: Deduplicate instructionManipulatesContext()Ulf Hermann2023-02-071-25/+0
| | | | | | | | | | We use it in three different compile passes, so it should be a member of QQmlJSCompilePass. Pick-to: 6.5 Change-Id: Ibc46ceb7ab05839b0a573c8ab3ee2acf4a6de154 Reviewed-by: Sami Shalayel <[email protected]> Reviewed-by: Fabian Kosmale <[email protected]>
* QmlCompiler: std::move() registers where possibleUlf Hermann2022-12-231-19/+46
| | | | | | | | | | | | In the common case that we read a register only once, in the same basic block, generate a std::move() in order to move it into place. Especially for QVariants holding large internal objects, this should help performance. Fixes: QTBUG-101452 Change-Id: I015892e1046ca7b739dbd296756f3f012dba5f9b Reviewed-by: Sami Shalayel <[email protected]>
* Port from qAsConst() to std::as_const()Marc Mutz2022-10-071-2/+2
| | | | | | | | | | | | | | We've been requiring C++17 since Qt 6.0, and our qAsConst use finally starts to bother us (QTBUG-99313), so time to port away from it now. Since qAsConst has exactly the same semantics as std::as_const (down to rvalue treatment, constexpr'ness and noexcept'ness), there's really nothing more to it than a global search-and-replace. Task-number: QTBUG-99313 Change-Id: I601bf70f020f511019ed28731ba53b14b765dbf0 Reviewed-by: Shawn Rutledge <[email protected]>
* Port from container::count() and length() to size()Marc Mutz2022-10-071-6/+6
| | | | | | | | | | | | | | | | | | | | This is a semantic patch using ClangTidyTransformator as in qtbase/df9d882d41b741fef7c5beeddb0abe9d904443d8: auto QtContainerClass = anyOf( expr(hasType(cxxRecordDecl(isSameOrDerivedFrom(hasAnyName(classes))))).bind(o), expr(hasType(namedDecl(hasAnyName(<classes>)))).bind(o)); makeRule(cxxMemberCallExpr(on(QtContainerClass), callee(cxxMethodDecl(hasAnyName({"count", "length"), parameterCountIs(0))))), changeTo(cat(access(o, cat("size"), "()"))), cat("use 'size()' instead of 'count()/length()'")) a.k.a qt-port-to-std-compatible-api with config Scope: 'Container', with the extended set of container classes recognized. Change-Id: Idb1f75dfe2323bd1d9e8b4d58d54f1b4b80c7ed7 Reviewed-by: Fabian Kosmale <[email protected]>
* QmlCompiler: Initialize registers with undefined where necessaryUlf Hermann2022-07-051-0/+8
| | | | | | | | | | | If we read the initial state of a register, we need to make sure it actually exists at that point. Uninitialized variables are implicitly undefined in JavaScript. Pick-to: 6.4 Task-number: QTBUG-104687 Change-Id: Ide4fe429b10ec28dcf267e7d34c6316355b16baa Reviewed-by: Fabian Kosmale <[email protected]>
* QmlCompiler: Really fix writing into argument valuesUlf Hermann2022-07-051-1/+9
| | | | | | | | | | | | | | | | | | | | | | Arguments are now treated as registers "written" at the beginning of the first basic block. By modeling them this way, we can avoid all the complicated logic on whether to use a local or the arguments array when accessing any particular one of them. Furthermore, we can detect whether they are overwritten or not. If they are not overwritten, we can initialize them as a const reference into the arguments array. This way we save a copy. Treating the arguments as generic registers causes the basic blocks pass to aggressively adjust their types, pushing some conversions back into the QML engine. This is good. Unused arguments become void, for example, and don't have to be passed at all. However, we also need a special case for QJSPrimitiveValue arguments now. Pick-to: 6.4 Fixes: QTBUG-104462 Change-Id: I994bea0929bd508aa41db58dee4a7f12cd20f053 Reviewed-by: Fabian Kosmale <[email protected]> Reviewed-by: Sami Shalayel <[email protected]>
* QmlCompiler: Fix register propagation in basic blocks passUlf Hermann2022-07-051-43/+72
| | | | | | | | | | | | | a, We were recording too many jump origins and targets. That messed up the basic blocks ordering logic. b, In the presence of backward jumps, we need to revisit earlier basic blocks if additional writes are discovered. Otherwise the type adjustment will optimize "dead" type conversions out. Pick-to: 6.4 Fixes: QTBUG-104665 Change-Id: I7219f85625761817ae4f63582d80d247a85df73b Reviewed-by: Fabian Kosmale <[email protected]>
* Use SPDX license identifiersLucie Gérard2022-06-111-27/+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 <[email protected]>
* QmlCompiler: Analyze type conversions before reads in basic blocksUlf Hermann2022-04-061-5/+5
| | | | | | | | | | The type conversions happen before the value is read. Therefore, we need to record them in this order. Otherwise, we may lose a type conversion if the instruction writes the same register as it reads. Fixes: QTBUG-102281 Change-Id: Id63a69f86af90c8dc987c0301db3958322c006a1 Reviewed-by: Fabian Kosmale <[email protected]>
* QmlCompiler: Implement generate_DefineArrayUlf Hermann2022-03-141-0/+41
| | | | | | | | | | | Using the type cloning and adaption mechanism we can now determine what kind of list we have to create in order to avoid a later conversion. We can even propagate the type adjustment into the element types we read. Fixes: QTBUG-100157 Change-Id: Ia2f160ebae56f39ee5946f49d2f8c5b4986a6b77 Reviewed-by: Qt CI Bot <[email protected]> Reviewed-by: Fabian Kosmale <[email protected]>
* QmlCompiler: Add register tracking to basic blocks passUlf Hermann2022-03-121-35/+105
| | | | | | | | This way we can detect dead LoadReg and StoreReg instructions. This is a precondition to removing the basic blocks pass in the code generator. Change-Id: Iab1ed60c1aa56a15935a35507f5ac67292aa56b3 Reviewed-by: Fabian Kosmale <[email protected]>
* QmlCompiler: Add basic block analysis passUlf Hermann2022-03-091-0/+397
This basic block analysis pass uses the tracked types to determine dead stores. This is better than the one we already have in the code generator because it also tracks dead stores through renames and it allows removal of lookup results. Furthermore, it adjusts each store to write the type most favorable to its readers. This avoids unnecessary conversions at run time. It cannot replace the other dead store elimination, yet, because it doesn't see whether the results of rename operations are read after the rename. This capability will be added in a separate change that also tracks the register numbers. Once this is in place, we can delete the other basic blocks pass. Task-number: QTBUG-100157 Change-Id: I766c919412b6cf43befa7bdb1a6e5e11b41fe55b Reviewed-by: Fabian Kosmale <[email protected]>