Consider:
function f() {
var a;
a();
}
Here the constant propagation will propagate the value for a (undefined)
to the call site. This was not yet handled, resulting in Q_UNIMPLEMENTED
warnings when running a debug build.
Change-Id: I5f85f681d975b54df7a9e00bd5b50e6f4350139a
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
There are a couple of reasons to split the temporaries off from the
arguments and locals:
Temporaries are invisible, and changes to them cannot be observed.
On the other hand, arguments and locals are visible, and writes to them
can be seen from other places (nested functions), or by using the
arguments array. So, in practice these correspond to memory locations.
(One could argue that if neither nested functions, nor eval(), nor
arguments[] is used, the loads/stores are invisible too. But that's an
optimization, and changing locals/arguments to temporaries can be done
in a separate pass.)
Because of the "volatile" nature of arguments and locals, their usage
cannot be optimized. All optimizations (SSA construction, register
allocation, copy elimination, etc.) work on temporaries. Being able to
easily ignore all non-temporaries has the benefit that optimizations can
be faster.
Previously, Temps were not uniquely numbered: argument 1, local 1, and
temporary 1 all had the same number and were distinguishable by their
type. So, for any mapping from Temp to something else, a QHash was used.
Now that Temps only hold proper temporaries, the indexes do uniquely
identify them. Add to that the fact that after transforming to SSA form
all temporaries are renumbered starting from 0 and without any holes in
the numbering, many of those datastructures can be changed to simple
vectors. That change gives a noticeable performance improvement.
One implication of this change is that a number of functions that took
a Temp as their argument, now need to take Temp-or-ArgLocal, so Expr.
However, it turns out that there are very few places where that applies,
as many of those places also need to take constants or names. However,
explicitly separating memory loads/stores for arguments/locals from
temporaries adds the benefit that it's now easier to do a peep-hole
optimizer for those load/store operations in the future: when a load is
directly preceded by a store, it can be eliminated if the value is
still available in a temporary.
Change-Id: I4114006b076795d9ea9fe3649cdb3b9d7b7508f0
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
This allows for overriding methods to customize the printing of nodes.
It also removes some duplicate code.
Change-Id: Ieb9eec2fa7d4e211932d7772586a1d62b119a90a
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
This is among other things needed to fix the qml import scanner to detect
dependencies from .js files correctly.
The patch also fixes the use of Q_QML_EXPORT towards Q_QML_PRIVATE_EXPORT
where appropriate and corrects the wrong include path for the double conversion
code to actually be relative to the file it is included from. This worked by
accident because of other include paths present in the build.
Change-Id: I338583dad2f76300819af8ab0dae8e5724c84430
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Properly convert the argument to an object if
it's not null or undefined as mandated by the
standard.
Add a similar test case for the with statement.
Change-Id: Idd8e245e8dae4803eb0e2010e3d43bb912670444
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
If QQmlCompiledData gets destroyed while somebody still has refcount on the
QV4::CompiledData::CompilationUnit, then unit's _data_ would be freed already
by ~QQmlCompiledData. Given that compilationUnit->data is pointing to the same
malloc'ed address as QQmlCompiledData::qmlUnit, we can just let the
CompilationUnit always own the data.
Fixes tst_qquickloader and makes it possible to run the qquickcomponent tests.
Change-Id: Ie3f3e5335139236d7c2524a327665bda0a9cc847
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
The base for an indexed access can be a constant.
Change-Id: Icc529c02fb0ff2ac30d6f40088781b6ecfba81fc
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Reviewed-by: Erik Verbruggen <erik.verbruggen@digia.com>
* Object literals with array indices are now created with one
run-time call, instead of an initial one for non-integral keys
followed by sub-sequent define_builtin_property calls.
* Cleaned up propert name retrieval. Instead of using a visitor,
it's easier to define a virtual method on the PropertyName type. The visitor
doesn't buy us much as it's not possible to recurse within property names, and
this way we can use it also from the function scanner to correctly determine
the number of arguments needed for object literal initalizations.
* Similarly the duplicated/common name member for all property assignments
has been moved into PropertyName, for convenient access without AST casts.
* Removed now unused builtin_define_property/settergetter functions from IR,
run-time and moth.
Change-Id: I90d54c81ea5f3f500f4f4a9c14f7caf5135e7f9f
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Statically initializing QObjects will cause e.g. the main
thread pointer in QCoreApplication to be set when the library
is loading. On Android, this is never the real main thread.
The effect was a warning about QApplication not being initialized
on main thread, and a race condition which sometimes caused
apps to hang on startup.
[ChangeLog][Android] Fixed possible hang on startup for Qt Quick
applications.
Task-number: QTBUG-36426
Change-Id: I7bd8a8f35ef1a2548949978563e3157f8dc854c7
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
As a follow-up to the previous commit, this patch cleans up the data structures
used to track dependencies of QML binding expressions and functions to context
and scope properties, determined at compile time.
Instead of "collecting" these depending properties upfront (codegen time), we
propagate the information that a property is a context or scope property into
the IR at codegen time and later in the isel collect these properties and their
notify signal index in a hash in the IR functions. The CompileData structure
generator then can read these hashes directly when writing out the dependency
information.
Change-Id: I32134706e2d24bf63d1b1abad0259ab072460173
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
We were incorrectly calculating writing to a context or scope property as a
dependency for an expression. We don't know whether a property is being written
only or also being read from at lookup time, but we can make that decision in
the isel then when generating the move instructions.
So initially context and scope properties end up in a candidate set first
and get promoted to real dependencies when they're being used in reading
moves.
Task-number: QTBUG-35210
Change-Id: Ia67057abafc2d611e1e6605327b4965ebe91cbed
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Both the base and the index of a subscript can (and are allowed to) be
other things than temporaries.
Change-Id: If073e262712bab488f18eac5ebe097be99c40359
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
* Resolve lookups in namespaces at compile time and instruct the SSA optimizer
to eliminate reads from the namespace (QQmlTypeWrapper) if possible. For example
access to attached properties of types (i.e. MyNameSpace.ListView.isCurrentItem)
requires neither reading the namespace nor the type.
* Add support for accelerated lookup of attached properties
Change-Id: Ib0b66404ed7e70e1d4a46a1ac8218743a4cc8608
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
With this patch we determine the meta-object of singletons, propagate it into
the IR and load them separately using a dedicated run-time function. In
addition enums in singletons and QML types are resolved at compile time.
Change-Id: I01ce1288391b476d1c9af669cb2987a44c885703
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
...instead of a special MEMBER type. This allows removing the
type member from V4IR::Member altogether (and thus unshadow from
V4IR::Expr::type). By not requiring the base of a id lookup
member expression to be a NAME, we can also speed up repeated
id lookups by fetching the id object array wrapper only once
per function.
Change-Id: I3e9b8f498d32ace4a0cc2254f49e02ecc124f79c
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
It is technically redundant to the Member::property field.
Change-Id: If0ee35b2c94a2c9373784d36a1f8dfe8ad7dcfb3
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
The previous approach of collecting the dependencies through an IR visitor
doesn't work, because it relies on a fixed structure - for example MEMBER(NAME,
prop) - which we can't guarantee (it's usually MEMBER(TEMP, prop)). But it
turns out that we can only pre-calculate dependencies for context, scope or id
properties, so we can do that right away in the QML specific JS codegen, store
that information in the IR function and use it from there in the data structure
generator as well as in the isel as a parameter to getQObjectProperty to tell
the run-time whether capture is required or not.
Change-Id: I33711c3420d6534c653c2a6a4284f0fc12e941cf
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
When a non strict mode function uses the this object, we
need to make sure it's being correctly converted into a
object before being accessed. So far this was being done
by ScriptFunction::call. Move this into the generated code to
avoid overhead for methods not using 'this', and simplify our
ScriptFunction::call() implementation.
Change-Id: I739f4a89d29ed8082ce59e48d1523776224fc29d
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
The QQmlContextData stores the JS objects of imported scripts in a
QList<PersistentValue>. Instead of indexing into that list, this patch changes
ctxt->importedScripts to be a JavaScript array, that in the IR we can index via
subscript.
Change-Id: Ie2c35fb5294a20a0b7084bb51d19671a27195fec
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
We can resolve the use of names that refer to imported scripts at compile
time and load them at run-time by index through context->importedScripts.
Change-Id: I681b19e7d68dbf3b9a68af00b4cea2a9254c2d78
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
After the resolution of a property, we can set it by index at run-time instead
of via name resolution.
Change-Id: I479599dabe343cf9e6582dcda12291aebfcce418
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
This avoids having to do a string lookup for ids and in the import cache at
run-time, before we can do a string hash lookup in the property cache. Instead
we resolve final properties in the context and scope object at compile time and
look them up at run-time using their index instead. The dependencies to these
properties are also tracked separately and recorded in the compiled data.
This is merely the initial patch. There's a lot left to do, such as having
specialized getter and setters for specific property types. Setters are missing
altogether right now and will fall back to name lookup.
Change-Id: If3cb4e7c9454ef4850a615f0935b311c9395b165
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
We can resolve lookups for objects referenced by id at QML compile time
and use a run-time helper to extract the id object out of the QML context
data by index instead of name.
Dependencies to id objects are also tracked at compile time and registered
separately before entering the generated function code.
The lookup of id objects is encoded in the IR as special member lookups.
Members will also then in the future be used to for property lookups in context
and scope properties, as well as any other property lookups in QObjects where
we can determine the meta-object.
Change-Id: I36cf3ceb11b51a983da6cad5b61c3bf574acc20a
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Simplify the generated code. Add a special block to catch
exceptions thrown inside a catch() statement.
store the exception on the stack when entering finally and
rethrow it at the end. This ensure correct behavior for
break/continue/return statements inside finally.
Don't check for exceptions after calling push_catch_scope
and pop_scope in the JIT'ed code. This can lead to infinite
loops when throwing inside an exception handler.
Change-Id: I67e9325794e2fd25b0773b21e02fbaadb43faab0
Change-Id: Ic1ea9c0c43eec1d49177dc1ab4552a1da04e96fe
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Start the work to remove c++ exceptions from our JS
exception handling. Rather rely on engine->hasException.
Check the flag after we return from any runtime call in the
JIT.
Implement new try/catch handling code in qv4codegen and
for the JIT that doesn't rely on exceptions. As an added
bonus, we can remove the Try statement in the IR.
Change-Id: Ic95addd6ae03371c43c47e04cac26afdce23a061
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
* Run the binding expressions, functions and signal handlers through
the V4 codegen _per_ component, and run the isel at the end for the
entire file. We need to do per-component codegen because we want to
set up the correct id and object scopes, which are different for the
root component and anonymous components.
* Changed V4IR::Module to allow for the concept of "qml modules" where
there is no root function defined. This is a logical consequence of
running v4 codegen multiple times with different input but the same
V4IR::Module.
Change-Id: Ib3a719f83507cbab7c2e4e145ccad5b663c795cf
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Inplace operations are expanded when building the IR, so the neither the
IR, nor the instruction selection backends or runtime need to handle
them.
Change-Id: Id01f9544e137dd52364cf2ed2c10931c31ddfff3
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
We generate lower level code in codegen and don't use these
runtime methods anymore.
Change-Id: If1023ce5295431305f4528839bcf2a3031fa7ad2
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Our synthetic exception unwind table for ARM is located at
(char *)codeStart + function->codeSize;
This relies on function->codeSize to contain the number of bytes of
instructions the function has, not the size of the MacroAssemblerCodeRef
(which contains the size of the entire area).
This patch fixes the calculation of function->codeSize and also replaces
the QHash for the IR::Function* -> CodeRef mapping in the masm backend
with a simple vector that's perfectly sufficient.
Bug spotted by Petr Nejedly
Change-Id: I78a53599085c613c6d97aa2490922f54e0bb4f63
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
The goal is to parse QML and JavaScript binding expressions/functions in one
go and generate data structures that allow for the parsing to happen in a thread
and the instantiation of the object tree in another thread, just reading from
the generated data structures. This will replace qqmlcompiler and the VME.
This new way of loading QML is currently hidden behind the QML_NEW_COMPILER=1
environment variable. There's lots of work left to fill in the gaps in object
construction, Component support, Component.onComplete, error messages, etc. etc.
Change-Id: I5e40643cff169f469f0b6ce151584ffee5ca5e90
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
This is needed for QML unit generation, when we share the JS generator
for QML types/strings and JS code.
Change-Id: I50f0c1fa6721d6e3e59417c6c256c82aec124e8f
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Enable the register allocator for X86_64 on Linux and MacOS. The
implications are:
- handle as much as possible with current code with as few changes as
possible
- temporarily force the register allocator to spill unop/binop arguments
to the stack by doing a call in the implementation (as is the current
case), so no change is needed here
- only have loadThis and loadConst handle registers
- have any method that might need to handle registrers actually cope
with them
- the inline versions of binops are not generated, as they cannot cope
with registers. This will change when ISel for binops is added in the
next patch.
This means that we are still running with the handbrakes on, but allow
for full-throttle in certain/limited cases.
Note about the changed test: multiplication always returns a Number
(double), so the operands are passed as doubles, so __qmljs_mul will
return a double. For addition this is different: because it might return
a Number or a String, the operands are passed as whatever fits best. So
__qmljs_add will return an int when both operands are ints. Hence the
change to the tests.
Change-Id: If5bd7dffca8f7de5ba45af700b9c7bb568fc74b7
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
So far we've been creating the arguments object at runtime
in initCallContext(). It's much more efficient to simply add
arguments as a local variable in qv4codegen if it's being used
and initialize it through a builtin method.
Change-Id: I6913f3565adf3aa1917adae8dceef9f50ecf1722
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>