aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/3rdparty/masm/assembler/ARMAssembler.h4
-rw-r--r--src/3rdparty/masm/assembler/MacroAssemblerARMv7.h2
-rw-r--r--src/3rdparty/masm/stubs/WTFStubs.cpp6
-rw-r--r--src/3rdparty/masm/stubs/WTFStubs.h2
-rw-r--r--src/3rdparty/masm/wtf/DataLog.h2
-rw-r--r--src/3rdparty/masm/wtf/OSAllocator.h2
-rw-r--r--src/3rdparty/masm/wtf/OSAllocatorPosix.cpp5
-rw-r--r--src/3rdparty/masm/wtf/OSAllocatorWin.cpp14
-rw-r--r--src/3rdparty/masm/wtf/OSAllocatorWinRT.cpp2
-rw-r--r--src/3rdparty/masm/wtf/PageAllocation.h16
-rw-r--r--src/3rdparty/masm/wtf/PageAllocationAligned.cpp9
-rw-r--r--src/3rdparty/masm/wtf/PageBlock.h7
-rw-r--r--src/3rdparty/masm/wtf/PageReservation.h14
-rw-r--r--src/3rdparty/masm/yarr/YarrJIT.cpp8
-rw-r--r--src/imports/localstorage/plugin.cpp178
-rw-r--r--src/imports/statemachine/signaltransition.cpp6
-rw-r--r--src/imports/testlib/TestCase.qml36
-rw-r--r--src/imports/xmllistmodel/qqmlxmllistmodel.cpp2
-rw-r--r--src/particles/qquickcustomaffector.cpp2
-rw-r--r--src/particles/qquickparticleemitter.cpp2
-rw-r--r--src/particles/qquickparticlesystem.cpp23
-rw-r--r--src/particles/qquicktrailemitter.cpp2
-rw-r--r--src/particles/qquickv4particledata.cpp43
-rw-r--r--src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp17
-rw-r--r--src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.h4
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp319
-rw-r--r--src/qml/compiler/qqmlirbuilder_p.h16
-rw-r--r--src/qml/compiler/qqmltypecompiler.cpp25
-rw-r--r--src/qml/compiler/qv4codegen.cpp9
-rw-r--r--src/qml/compiler/qv4codegen_p.h10
-rw-r--r--src/qml/compiler/qv4compileddata.cpp16
-rw-r--r--src/qml/compiler/qv4compileddata_p.h8
-rw-r--r--src/qml/compiler/qv4isel_moth.cpp10
-rw-r--r--src/qml/compiler/qv4isel_p.cpp16
-rw-r--r--src/qml/compiler/qv4jsir.cpp25
-rw-r--r--src/qml/compiler/qv4jsir_p.h23
-rw-r--r--src/qml/compiler/qv4ssa.cpp389
-rw-r--r--src/qml/compiler/qv4ssa_p.h2
-rw-r--r--src/qml/debugger/qqmldebug.h2
-rw-r--r--src/qml/debugger/qqmldebugserver.cpp152
-rw-r--r--src/qml/debugger/qqmldebugserver_p.h5
-rw-r--r--src/qml/debugger/qqmldebugserverconnection_p.h3
-rw-r--r--src/qml/debugger/qqmlprofilerdefinitions_p.h26
-rw-r--r--src/qml/debugger/qv4debugservice.cpp36
-rw-r--r--src/qml/doc/src/cppintegration/data.qdoc27
-rw-r--r--src/qml/doc/src/javascript/date.qdoc19
-rw-r--r--src/qml/doc/src/javascript/qmlglobalobject.qdoc1
-rw-r--r--src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc4
-rw-r--r--src/qml/jit/qv4assembler.cpp22
-rw-r--r--src/qml/jit/qv4assembler_p.h29
-rw-r--r--src/qml/jit/qv4binop.cpp2
-rw-r--r--src/qml/jit/qv4isel_masm.cpp175
-rw-r--r--src/qml/jit/qv4regalloc.cpp90
-rw-r--r--src/qml/jit/qv4targetplatform_p.h10
-rw-r--r--src/qml/jsapi/qjsengine.cpp80
-rw-r--r--src/qml/jsapi/qjsengine.h2
-rw-r--r--src/qml/jsapi/qjsengine_p.h134
-rw-r--r--src/qml/jsapi/qjsvalue.cpp127
-rw-r--r--src/qml/jsapi/qjsvalueiterator.cpp24
-rw-r--r--src/qml/jsapi/qjsvalueiterator_p.h2
-rw-r--r--src/qml/jsruntime/jsruntime.pri10
-rw-r--r--src/qml/jsruntime/qv4argumentsobject.cpp105
-rw-r--r--src/qml/jsruntime/qv4argumentsobject_p.h89
-rw-r--r--src/qml/jsruntime/qv4arraybuffer.cpp164
-rw-r--r--src/qml/jsruntime/qv4arraybuffer_p.h (renamed from src/quick/accessible/qqmlaccessible_p.h)81
-rw-r--r--src/qml/jsruntime/qv4arraydata.cpp496
-rw-r--r--src/qml/jsruntime/qv4arraydata_p.h242
-rw-r--r--src/qml/jsruntime/qv4arrayobject.cpp144
-rw-r--r--src/qml/jsruntime/qv4arrayobject_p.h14
-rw-r--r--src/qml/jsruntime/qv4booleanobject.cpp10
-rw-r--r--src/qml/jsruntime/qv4booleanobject_p.h14
-rw-r--r--src/qml/jsruntime/qv4context.cpp419
-rw-r--r--src/qml/jsruntime/qv4context_p.h258
-rw-r--r--src/qml/jsruntime/qv4dataview.cpp316
-rw-r--r--src/qml/jsruntime/qv4dataview_p.h (renamed from src/qml/qml/v8/qv8debug_p.h)67
-rw-r--r--src/qml/jsruntime/qv4dateobject.cpp72
-rw-r--r--src/qml/jsruntime/qv4dateobject_p.h46
-rw-r--r--src/qml/jsruntime/qv4debugging.cpp96
-rw-r--r--src/qml/jsruntime/qv4debugging_p.h4
-rw-r--r--src/qml/jsruntime/qv4engine.cpp1331
-rw-r--r--src/qml/jsruntime/qv4engine_p.h254
-rw-r--r--src/qml/jsruntime/qv4errorobject.cpp146
-rw-r--r--src/qml/jsruntime/qv4errorobject_p.h173
-rw-r--r--src/qml/jsruntime/qv4function.cpp14
-rw-r--r--src/qml/jsruntime/qv4function_p.h40
-rw-r--r--src/qml/jsruntime/qv4functionobject.cpp372
-rw-r--r--src/qml/jsruntime/qv4functionobject_p.h225
-rw-r--r--src/qml/jsruntime/qv4global_p.h54
-rw-r--r--src/qml/jsruntime/qv4globalobject.cpp54
-rw-r--r--src/qml/jsruntime/qv4globalobject_p.h14
-rw-r--r--src/qml/jsruntime/qv4identifier.cpp2
-rw-r--r--src/qml/jsruntime/qv4identifier_p.h6
-rw-r--r--src/qml/jsruntime/qv4identifiertable.cpp64
-rw-r--r--src/qml/jsruntime/qv4identifiertable_p.h27
-rw-r--r--src/qml/jsruntime/qv4include.cpp54
-rw-r--r--src/qml/jsruntime/qv4include_p.h2
-rw-r--r--src/qml/jsruntime/qv4internalclass.cpp202
-rw-r--r--src/qml/jsruntime/qv4internalclass_p.h31
-rw-r--r--src/qml/jsruntime/qv4jsonobject.cpp104
-rw-r--r--src/qml/jsruntime/qv4jsonobject_p.h16
-rw-r--r--src/qml/jsruntime/qv4lookup.cpp423
-rw-r--r--src/qml/jsruntime/qv4lookup_p.h82
-rw-r--r--src/qml/jsruntime/qv4managed.cpp18
-rw-r--r--src/qml/jsruntime/qv4managed_p.h118
-rw-r--r--src/qml/jsruntime/qv4mathobject.cpp42
-rw-r--r--src/qml/jsruntime/qv4mathobject_p.h14
-rw-r--r--src/qml/jsruntime/qv4memberdata.cpp36
-rw-r--r--src/qml/jsruntime/qv4memberdata_p.h45
-rw-r--r--src/qml/jsruntime/qv4mm.cpp274
-rw-r--r--src/qml/jsruntime/qv4mm_p.h57
-rw-r--r--src/qml/jsruntime/qv4numberobject.cpp56
-rw-r--r--src/qml/jsruntime/qv4numberobject_p.h13
-rw-r--r--src/qml/jsruntime/qv4object.cpp365
-rw-r--r--src/qml/jsruntime/qv4object_p.h267
-rw-r--r--src/qml/jsruntime/qv4objectiterator.cpp89
-rw-r--r--src/qml/jsruntime/qv4objectiterator_p.h50
-rw-r--r--src/qml/jsruntime/qv4objectproto.cpp330
-rw-r--r--src/qml/jsruntime/qv4objectproto_p.h19
-rw-r--r--src/qml/jsruntime/qv4persistent.cpp104
-rw-r--r--src/qml/jsruntime/qv4persistent_p.h41
-rw-r--r--src/qml/jsruntime/qv4profiling_p.h10
-rw-r--r--src/qml/jsruntime/qv4property_p.h46
-rw-r--r--src/qml/jsruntime/qv4qmlextensions_p.h5
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp434
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper_p.h80
-rw-r--r--src/qml/jsruntime/qv4regexp.cpp28
-rw-r--r--src/qml/jsruntime/qv4regexp_p.h45
-rw-r--r--src/qml/jsruntime/qv4regexpobject.cpp131
-rw-r--r--src/qml/jsruntime/qv4regexpobject_p.h72
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp559
-rw-r--r--src/qml/jsruntime/qv4runtime_p.h161
-rw-r--r--src/qml/jsruntime/qv4scopedvalue_p.h230
-rw-r--r--src/qml/jsruntime/qv4script.cpp189
-rw-r--r--src/qml/jsruntime/qv4script_p.h74
-rw-r--r--src/qml/jsruntime/qv4sequenceobject.cpp124
-rw-r--r--src/qml/jsruntime/qv4sequenceobject_p.h3
-rw-r--r--src/qml/jsruntime/qv4serialize.cpp65
-rw-r--r--src/qml/jsruntime/qv4serialize_p.h8
-rw-r--r--src/qml/jsruntime/qv4string.cpp264
-rw-r--r--src/qml/jsruntime/qv4string_p.h165
-rw-r--r--src/qml/jsruntime/qv4stringobject.cpp107
-rw-r--r--src/qml/jsruntime/qv4stringobject_p.h41
-rw-r--r--src/qml/jsruntime/qv4typedarray.cpp572
-rw-r--r--src/qml/jsruntime/qv4typedarray_p.h143
-rw-r--r--src/qml/jsruntime/qv4value.cpp33
-rw-r--r--src/qml/jsruntime/qv4value_inl_p.h37
-rw-r--r--src/qml/jsruntime/qv4value_p.h175
-rw-r--r--src/qml/jsruntime/qv4variantobject.cpp41
-rw-r--r--src/qml/jsruntime/qv4variantobject_p.h35
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp211
-rw-r--r--src/qml/jsruntime/qv4vme_moth_p.h4
-rw-r--r--src/qml/parser/qqmljsengine_p.cpp8
-rw-r--r--src/qml/parser/qqmljsengine_p.h5
-rw-r--r--src/qml/parser/qqmljslexer.cpp162
-rw-r--r--src/qml/parser/qqmljslexer_p.h11
-rw-r--r--src/qml/parser/qqmljsparser.cpp19
-rw-r--r--src/qml/qml/ftw/ftw.pri2
-rw-r--r--src/qml/qml/ftw/qqmltrace.cpp147
-rw-r--r--src/qml/qml/ftw/qqmltrace_p.h286
-rw-r--r--src/qml/qml/qml.pri2
-rw-r--r--src/qml/qml/qqmlabstractbinding.cpp18
-rw-r--r--src/qml/qml/qqmlbinding.cpp30
-rw-r--r--src/qml/qml/qqmlboundsignal.cpp32
-rw-r--r--src/qml/qml/qqmlboundsignal_p.h4
-rw-r--r--src/qml/qml/qqmlbundle.cpp310
-rw-r--r--src/qml/qml/qqmlbundle_p.h119
-rw-r--r--src/qml/qml/qqmlcompiler_p.h2
-rw-r--r--src/qml/qml/qqmlcomponent.cpp146
-rw-r--r--src/qml/qml/qqmlcontextwrapper.cpp105
-rw-r--r--src/qml/qml/qqmlcontextwrapper_p.h56
-rw-r--r--src/qml/qml/qqmldata_p.h2
-rw-r--r--src/qml/qml/qqmldirparser.cpp98
-rw-r--r--src/qml/qml/qqmlengine.cpp63
-rw-r--r--src/qml/qml/qqmlengine_p.h113
-rw-r--r--src/qml/qml/qqmlexpression.cpp11
-rw-r--r--src/qml/qml/qqmlfile.cpp276
-rw-r--r--src/qml/qml/qqmlfile.h15
-rw-r--r--src/qml/qml/qqmlglobal.cpp14
-rw-r--r--src/qml/qml/qqmlglobal_p.h10
-rw-r--r--src/qml/qml/qqmlimport.cpp67
-rw-r--r--src/qml/qml/qqmlimport_p.h6
-rw-r--r--src/qml/qml/qqmljavascriptexpression.cpp29
-rw-r--r--src/qml/qml/qqmljavascriptexpression_p.h6
-rw-r--r--src/qml/qml/qqmllistwrapper.cpp40
-rw-r--r--src/qml/qml/qqmllistwrapper_p.h32
-rw-r--r--src/qml/qml/qqmllocale.cpp60
-rw-r--r--src/qml/qml/qqmllocale_p.h45
-rw-r--r--src/qml/qml/qqmlmetatype.cpp4
-rw-r--r--src/qml/qml/qqmlmetatype_p.h2
-rw-r--r--src/qml/qml/qqmlnotifier_p.h3
-rw-r--r--src/qml/qml/qqmlobjectcreator.cpp36
-rw-r--r--src/qml/qml/qqmlopenmetaobject.cpp3
-rw-r--r--src/qml/qml/qqmlproperty.cpp52
-rw-r--r--src/qml/qml/qqmlpropertycache.cpp408
-rw-r--r--src/qml/qml/qqmlpropertycache_p.h79
-rw-r--r--src/qml/qml/qqmltypeloader.cpp351
-rw-r--r--src/qml/qml/qqmltypeloader_p.h119
-rw-r--r--src/qml/qml/qqmltypewrapper.cpp61
-rw-r--r--src/qml/qml/qqmltypewrapper_p.h47
-rw-r--r--src/qml/qml/qqmlvaluetype.cpp166
-rw-r--r--src/qml/qml/qqmlvaluetype_p.h170
-rw-r--r--src/qml/qml/qqmlvaluetypeproxybinding.cpp3
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper.cpp454
-rw-r--r--src/qml/qml/qqmlvaluetypewrapper_p.h35
-rw-r--r--src/qml/qml/qqmlvme_p.h1
-rw-r--r--src/qml/qml/qqmlvmemetaobject.cpp19
-rw-r--r--src/qml/qml/qqmlvmemetaobject_p.h12
-rw-r--r--src/qml/qml/qqmlxmlhttprequest.cpp648
-rw-r--r--src/qml/qml/qqmlxmlhttprequest_p.h5
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions.cpp274
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions_p.h50
-rw-r--r--src/qml/qml/v8/qv4domerrors.cpp4
-rw-r--r--src/qml/qml/v8/qv4domerrors_p.h6
-rw-r--r--src/qml/qml/v8/qv4sqlerrors.cpp4
-rw-r--r--src/qml/qml/v8/qv8engine.cpp706
-rw-r--r--src/qml/qml/v8/qv8engine_p.h51
-rw-r--r--src/qml/qml/v8/v8.pri1
-rw-r--r--src/qml/types/qqmldelegatemodel.cpp205
-rw-r--r--src/qml/types/qqmldelegatemodel_p_p.h33
-rw-r--r--src/qml/types/qqmllistmodel.cpp116
-rw-r--r--src/qml/types/qqmllistmodel_p.h8
-rw-r--r--src/qml/types/qqmllistmodel_p_p.h20
-rw-r--r--src/qml/types/qqmllistmodelworkeragent.cpp2
-rw-r--r--src/qml/types/qqmllistmodelworkeragent_p.h2
-rw-r--r--src/qml/types/qquickworkerscript.cpp38
-rw-r--r--src/qml/util/qqmladaptormodel.cpp59
-rw-r--r--src/qmltest/quicktest.cpp7
-rw-r--r--src/qmltest/quicktestresult.cpp5
-rw-r--r--src/quick/accessible/accessible.pri2
-rw-r--r--src/quick/accessible/qaccessiblequickitem.cpp121
-rw-r--r--src/quick/accessible/qaccessiblequickitem_p.h4
-rw-r--r--src/quick/accessible/qaccessiblequickview.cpp1
-rw-r--r--src/quick/accessible/qqmlaccessible.cpp195
-rw-r--r--src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc18
-rw-r--r--src/quick/items/context2d/qquickcanvascontext_p.h2
-rw-r--r--src/quick/items/context2d/qquickcanvasitem.cpp4
-rw-r--r--src/quick/items/context2d/qquickcanvasitem_p.h12
-rw-r--r--src/quick/items/context2d/qquickcontext2d.cpp265
-rw-r--r--src/quick/items/context2d/qquickcontext2d_p.h4
-rw-r--r--src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp8
-rw-r--r--src/quick/items/qquickaccessibleattached.cpp79
-rw-r--r--src/quick/items/qquickaccessibleattached_p.h12
-rw-r--r--src/quick/items/qquickanchors_p_p.h4
-rw-r--r--src/quick/items/qquickanimatedimage_p.h6
-rw-r--r--src/quick/items/qquickanimatedsprite.cpp53
-rw-r--r--src/quick/items/qquickanimatedsprite_p.h4
-rw-r--r--src/quick/items/qquickborderimage_p.h10
-rw-r--r--src/quick/items/qquickdrag.cpp2
-rw-r--r--src/quick/items/qquickdroparea_p.h8
-rw-r--r--src/quick/items/qquickflickable.cpp2
-rw-r--r--src/quick/items/qquickflickable_p.h20
-rw-r--r--src/quick/items/qquickflickable_p_p.h4
-rw-r--r--src/quick/items/qquickflipable.cpp4
-rw-r--r--src/quick/items/qquickflipable_p.h2
-rw-r--r--src/quick/items/qquickframebufferobject.h2
-rw-r--r--src/quick/items/qquickgridview.cpp84
-rw-r--r--src/quick/items/qquickgridview_p.h12
-rw-r--r--src/quick/items/qquickimage_p.h12
-rw-r--r--src/quick/items/qquickimagebase_p.h2
-rw-r--r--src/quick/items/qquickimplicitsizeitem_p_p.h4
-rw-r--r--src/quick/items/qquickitem.cpp72
-rw-r--r--src/quick/items/qquickitem.h2
-rw-r--r--src/quick/items/qquickitem_p.h70
-rw-r--r--src/quick/items/qquickitemanimation.cpp2
-rw-r--r--src/quick/items/qquickitemanimation_p.h12
-rw-r--r--src/quick/items/qquickitemview_p.h22
-rw-r--r--src/quick/items/qquickitemview_p_p.h6
-rw-r--r--src/quick/items/qquickitemviewtransition.cpp2
-rw-r--r--src/quick/items/qquicklistview.cpp92
-rw-r--r--src/quick/items/qquicklistview_p.h12
-rw-r--r--src/quick/items/qquickloader.cpp6
-rw-r--r--src/quick/items/qquickloader_p.h4
-rw-r--r--src/quick/items/qquickloader_p_p.h14
-rw-r--r--src/quick/items/qquickmultipointtoucharea_p.h20
-rw-r--r--src/quick/items/qquickpainteditem.h2
-rw-r--r--src/quick/items/qquickpathview_p.h14
-rw-r--r--src/quick/items/qquickpathview_p_p.h2
-rw-r--r--src/quick/items/qquickpincharea_p.h14
-rw-r--r--src/quick/items/qquickpositioners_p.h22
-rw-r--r--src/quick/items/qquickpositioners_p_p.h10
-rw-r--r--src/quick/items/qquickrectangle_p.h2
-rw-r--r--src/quick/items/qquickrendercontrol.cpp16
-rw-r--r--src/quick/items/qquickrendercontrol.h2
-rw-r--r--src/quick/items/qquickrepeater.cpp4
-rw-r--r--src/quick/items/qquickrepeater_p.h4
-rw-r--r--src/quick/items/qquickscreen.cpp4
-rw-r--r--src/quick/items/qquickshadereffect.cpp38
-rw-r--r--src/quick/items/qquickshadereffect_p.h10
-rw-r--r--src/quick/items/qquickshadereffectmesh.cpp2
-rw-r--r--src/quick/items/qquickshadereffectmesh_p.h4
-rw-r--r--src/quick/items/qquickshadereffectnode.cpp32
-rw-r--r--src/quick/items/qquickshadereffectnode_p.h10
-rw-r--r--src/quick/items/qquickshadereffectsource_p.h12
-rw-r--r--src/quick/items/qquicksprite_p.h2
-rw-r--r--src/quick/items/qquickspriteengine.cpp22
-rw-r--r--src/quick/items/qquickspriteengine_p.h4
-rw-r--r--src/quick/items/qquickspritesequence.cpp12
-rw-r--r--src/quick/items/qquickspritesequence_p.h2
-rw-r--r--src/quick/items/qquickstateoperations_p.h46
-rw-r--r--src/quick/items/qquicktext_p.h30
-rw-r--r--src/quick/items/qquicktext_p_p.h6
-rw-r--r--src/quick/items/qquicktextcontrol_p.h4
-rw-r--r--src/quick/items/qquicktextedit.cpp16
-rw-r--r--src/quick/items/qquicktextedit_p.h52
-rw-r--r--src/quick/items/qquicktextedit_p_p.h4
-rw-r--r--src/quick/items/qquicktextinput.cpp28
-rw-r--r--src/quick/items/qquicktextinput_p.h53
-rw-r--r--src/quick/items/qquicktextinput_p_p.h4
-rw-r--r--src/quick/items/qquicktextnodeengine.cpp13
-rw-r--r--src/quick/items/qquicktranslate_p.h8
-rw-r--r--src/quick/items/qquickview.cpp12
-rw-r--r--src/quick/items/qquickview.h16
-rw-r--r--src/quick/items/qquickview_p.h41
-rw-r--r--src/quick/items/qquickwindow.cpp344
-rw-r--r--src/quick/items/qquickwindow.h31
-rw-r--r--src/quick/items/qquickwindow_p.h9
-rw-r--r--src/quick/items/qquickwindowattached.cpp18
-rw-r--r--src/quick/items/qquickwindowattached_p.h6
-rw-r--r--src/quick/items/qquickwindowmodule.cpp6
-rw-r--r--src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp150
-rw-r--r--src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h150
-rw-r--r--src/quick/scenegraph/coreapi/qsgnode.cpp15
-rw-r--r--src/quick/scenegraph/coreapi/qsgnode.h1
-rw-r--r--src/quick/scenegraph/coreapi/qsgrenderer.cpp19
-rw-r--r--src/quick/scenegraph/qsgadaptationlayer.cpp11
-rw-r--r--src/quick/scenegraph/qsgcontext.cpp4
-rw-r--r--src/quick/scenegraph/qsgcontext_p.h2
-rw-r--r--src/quick/scenegraph/qsgdefaultlayer.cpp2
-rw-r--r--src/quick/scenegraph/qsgdefaultlayer_p.h2
-rw-r--r--src/quick/scenegraph/qsgrenderloop.cpp28
-rw-r--r--src/quick/scenegraph/qsgrenderloop_p.h1
-rw-r--r--src/quick/scenegraph/qsgthreadedrenderloop.cpp97
-rw-r--r--src/quick/scenegraph/qsgthreadedrenderloop_p.h5
-rw-r--r--src/quick/scenegraph/qsgwindowsrenderloop.cpp39
-rw-r--r--src/quick/scenegraph/shaders/visualization.frag4
-rw-r--r--src/quick/scenegraph/shaders/visualization.vert6
-rw-r--r--src/quick/scenegraph/util/qsgatlastexture.cpp16
-rw-r--r--src/quick/scenegraph/util/qsgengine_p.h2
-rw-r--r--src/quick/scenegraph/util/qsgsimpletexturenode.cpp59
-rw-r--r--src/quick/scenegraph/util/qsgsimpletexturenode.h4
-rw-r--r--src/quick/scenegraph/util/qsgtexture.cpp21
-rw-r--r--src/quick/scenegraph/util/qsgvertexcolormaterial.cpp9
-rw-r--r--src/quick/util/qquickanimatorjob.cpp30
-rw-r--r--src/quick/util/qquickglobal.cpp68
-rw-r--r--src/quick/util/qquickpixmapcache.cpp4
-rw-r--r--src/quick/util/qquickprofiler.cpp2
-rw-r--r--src/quick/util/qquickprofiler_p.h126
-rw-r--r--src/quick/util/qquickvaluetypes.cpp111
-rw-r--r--src/quick/util/qquickvaluetypes_p.h74
-rw-r--r--src/quickwidgets/qquickwidget.h1
350 files changed, 12652 insertions, 11937 deletions
diff --git a/src/3rdparty/masm/assembler/ARMAssembler.h b/src/3rdparty/masm/assembler/ARMAssembler.h
index 3888226b21..16cc25d4db 100644
--- a/src/3rdparty/masm/assembler/ARMAssembler.h
+++ b/src/3rdparty/masm/assembler/ARMAssembler.h
@@ -41,10 +41,10 @@ namespace JSC {
r0 = 0,
r1,
r2,
- r3, S0 = r3, /* Same as thumb assembler. */
+ r3,
r4,
r5,
- r6,
+ r6, S0 = r6,
r7,
r8,
r9,
diff --git a/src/3rdparty/masm/assembler/MacroAssemblerARMv7.h b/src/3rdparty/masm/assembler/MacroAssemblerARMv7.h
index 15e427bbff..85cd6c27b9 100644
--- a/src/3rdparty/masm/assembler/MacroAssemblerARMv7.h
+++ b/src/3rdparty/masm/assembler/MacroAssemblerARMv7.h
@@ -40,7 +40,7 @@ protected: // the YarrJIT needs know about addressTempRegister in order to push
// - dTR is likely used more than aTR, and we'll get better instruction
// encoding if it's in the low 8 registers.
static const RegisterID dataTempRegister = ARMRegisters::ip;
- static const RegisterID addressTempRegister = ARMRegisters::r10;
+ static const RegisterID addressTempRegister = ARMRegisters::r6;
static const ARMRegisters::FPDoubleRegisterID fpTempRegister = ARMRegisters::d7;
inline ARMRegisters::FPSingleRegisterID fpTempRegisterAsSingle() { return ARMRegisters::asSingle(fpTempRegister); }
diff --git a/src/3rdparty/masm/stubs/WTFStubs.cpp b/src/3rdparty/masm/stubs/WTFStubs.cpp
index 7e6ba9b81d..2650f1d36a 100644
--- a/src/3rdparty/masm/stubs/WTFStubs.cpp
+++ b/src/3rdparty/masm/stubs/WTFStubs.cpp
@@ -60,9 +60,9 @@ uint32_t cryptographicallyRandomNumber()
return 0;
}
-static PrintStream* s_dataFile;
+static FilePrintStream* s_dataFile;
-void setDataFile(PrintStream *ps)
+void setDataFile(FilePrintStream *ps)
{
delete s_dataFile;
s_dataFile = ps;
@@ -74,7 +74,7 @@ void setDataFile(FILE* f)
s_dataFile = new FilePrintStream(f, FilePrintStream::Borrow);
}
-PrintStream& dataFile()
+FilePrintStream& dataFile()
{
if (!s_dataFile)
s_dataFile = new FilePrintStream(stderr, FilePrintStream::Borrow);
diff --git a/src/3rdparty/masm/stubs/WTFStubs.h b/src/3rdparty/masm/stubs/WTFStubs.h
index 397aed5f16..2b3236553a 100644
--- a/src/3rdparty/masm/stubs/WTFStubs.h
+++ b/src/3rdparty/masm/stubs/WTFStubs.h
@@ -36,7 +36,7 @@
namespace WTF {
void setDataFile(FILE* f);
-void setDataFile(class PrintStream *);
+void setDataFile(class FilePrintStream *);
}
diff --git a/src/3rdparty/masm/wtf/DataLog.h b/src/3rdparty/masm/wtf/DataLog.h
index 2b3df09970..0bd8efe727 100644
--- a/src/3rdparty/masm/wtf/DataLog.h
+++ b/src/3rdparty/masm/wtf/DataLog.h
@@ -34,7 +34,7 @@
namespace WTF {
-WTF_EXPORT_PRIVATE PrintStream &dataFile();
+WTF_EXPORT_PRIVATE FilePrintStream& dataFile();
WTF_EXPORT_PRIVATE void dataLogFV(const char* format, va_list) WTF_ATTRIBUTE_PRINTF(1, 0);
WTF_EXPORT_PRIVATE void dataLogF(const char* format, ...) WTF_ATTRIBUTE_PRINTF(1, 2);
diff --git a/src/3rdparty/masm/wtf/OSAllocator.h b/src/3rdparty/masm/wtf/OSAllocator.h
index a12a467497..494f8bc3c7 100644
--- a/src/3rdparty/masm/wtf/OSAllocator.h
+++ b/src/3rdparty/masm/wtf/OSAllocator.h
@@ -45,7 +45,7 @@ public:
// These methods are symmetric; reserveUncommitted allocates VM in an uncommitted state,
// releaseDecommitted should be called on a region of VM allocated by a single reservation,
// the memory must all currently be in a decommitted state.
- static void* reserveUncommitted(size_t, Usage = UnknownUsage, bool writable = true, bool executable = false, bool includesGuardPages = false);
+ static void* reserveUncommitted(size_t, Usage = UnknownUsage, bool writable = true, bool executable = false);
WTF_EXPORT_PRIVATE static void releaseDecommitted(void*, size_t);
// These methods are symmetric; they commit or decommit a region of VM (uncommitted VM should
diff --git a/src/3rdparty/masm/wtf/OSAllocatorPosix.cpp b/src/3rdparty/masm/wtf/OSAllocatorPosix.cpp
index d8c8e0378f..f52c22f7fa 100644
--- a/src/3rdparty/masm/wtf/OSAllocatorPosix.cpp
+++ b/src/3rdparty/masm/wtf/OSAllocatorPosix.cpp
@@ -38,7 +38,7 @@
namespace WTF {
-void* OSAllocator::reserveUncommitted(size_t bytes, Usage usage, bool writable, bool executable, bool includesGuardPages)
+void* OSAllocator::reserveUncommitted(size_t bytes, Usage usage, bool writable, bool executable)
{
#if OS(QNX)
// Reserve memory with PROT_NONE and MAP_LAZY so it isn't committed now.
@@ -49,14 +49,13 @@ void* OSAllocator::reserveUncommitted(size_t bytes, Usage usage, bool writable,
UNUSED_PARAM(usage);
UNUSED_PARAM(writable);
UNUSED_PARAM(executable);
- UNUSED_PARAM(includesGuardPages);
void* result = mmap(0, bytes, PROT_NONE, MAP_NORESERVE | MAP_PRIVATE | MAP_ANON, -1, 0);
if (result == MAP_FAILED)
CRASH();
madvise(result, bytes, MADV_DONTNEED);
#else
- void* result = reserveAndCommit(bytes, usage, writable, executable, includesGuardPages);
+ void* result = reserveAndCommit(bytes, usage, writable, executable);
#if HAVE(MADV_FREE_REUSE)
// To support the "reserve then commit" model, we have to initially decommit.
while (madvise(result, bytes, MADV_FREE_REUSABLE) == -1 && errno == EAGAIN) { }
diff --git a/src/3rdparty/masm/wtf/OSAllocatorWin.cpp b/src/3rdparty/masm/wtf/OSAllocatorWin.cpp
index f95a4841c6..259fc67324 100644
--- a/src/3rdparty/masm/wtf/OSAllocatorWin.cpp
+++ b/src/3rdparty/masm/wtf/OSAllocatorWin.cpp
@@ -25,6 +25,7 @@
#include "config.h"
#include "OSAllocator.h"
+#include "PageBlock.h"
#if OS(WINDOWS)
@@ -40,7 +41,7 @@ static inline DWORD protection(bool writable, bool executable)
(writable ? PAGE_READWRITE : PAGE_READONLY);
}
-void* OSAllocator::reserveUncommitted(size_t bytes, Usage, bool writable, bool executable, bool)
+void* OSAllocator::reserveUncommitted(size_t bytes, Usage, bool writable, bool executable)
{
void* result = VirtualAlloc(0, bytes, MEM_RESERVE, protection(writable, executable));
if (!result)
@@ -48,11 +49,20 @@ void* OSAllocator::reserveUncommitted(size_t bytes, Usage, bool writable, bool e
return result;
}
-void* OSAllocator::reserveAndCommit(size_t bytes, Usage, bool writable, bool executable, bool)
+void* OSAllocator::reserveAndCommit(size_t bytes, Usage, bool writable, bool executable,
+ bool includesGuardPages)
{
void* result = VirtualAlloc(0, bytes, MEM_RESERVE | MEM_COMMIT, protection(writable, executable));
if (!result)
CRASH();
+ if (includesGuardPages) {
+ size_t guardSize = pageSize();
+ DWORD oldProtect;
+ if (!VirtualProtect(result, guardSize, protection(false, false), &oldProtect) ||
+ !VirtualProtect(static_cast<char*>(result) + bytes - guardSize, guardSize,
+ protection(false, false), &oldProtect))
+ CRASH();
+ }
return result;
}
diff --git a/src/3rdparty/masm/wtf/OSAllocatorWinRT.cpp b/src/3rdparty/masm/wtf/OSAllocatorWinRT.cpp
index 7ed9f539e5..9b8f5bf46b 100644
--- a/src/3rdparty/masm/wtf/OSAllocatorWinRT.cpp
+++ b/src/3rdparty/masm/wtf/OSAllocatorWinRT.cpp
@@ -33,7 +33,7 @@
namespace WTF {
-void* OSAllocator::reserveUncommitted(size_t bytes, Usage, bool, bool, bool)
+void* OSAllocator::reserveUncommitted(size_t bytes, Usage, bool, bool)
{
void* result = _aligned_malloc(bytes, 16);
if (!result)
diff --git a/src/3rdparty/masm/wtf/PageAllocation.h b/src/3rdparty/masm/wtf/PageAllocation.h
index 18d31880c0..db4e230e03 100644
--- a/src/3rdparty/masm/wtf/PageAllocation.h
+++ b/src/3rdparty/masm/wtf/PageAllocation.h
@@ -86,11 +86,17 @@ public:
// control warning when a client tries to use operator bool exposed above via "using PageBlock::operator bool".
operator bool() const { return PageBlock::operator bool(); }
#endif
+ bool operator<(const PageAllocation &b) { return base() < b.base(); }
- static PageAllocation allocate(size_t size, OSAllocator::Usage usage = OSAllocator::UnknownUsage, bool writable = true, bool executable = false)
+ static PageAllocation allocate(size_t size,
+ OSAllocator::Usage usage = OSAllocator::UnknownUsage,
+ bool writable = true, bool executable = false,
+ bool includesGuardPages = false)
{
ASSERT(isPageAligned(size));
- return PageAllocation(OSAllocator::reserveAndCommit(size, usage, writable, executable), size);
+ return PageAllocation(OSAllocator::reserveAndCommit(size, usage, writable, executable,
+ includesGuardPages), size,
+ includesGuardPages);
}
void deallocate()
@@ -103,12 +109,12 @@ public:
ASSERT(tmp);
ASSERT(!*this);
- OSAllocator::decommitAndRelease(tmp.base(), tmp.size());
+ OSAllocator::decommitAndRelease(tmp.realBase(), tmp.realSize());
}
private:
- PageAllocation(void* base, size_t size)
- : PageBlock(base, size, false)
+ PageAllocation(void* base, size_t size, bool includesGuardPages = false)
+ : PageBlock(base, size, includesGuardPages)
{
}
};
diff --git a/src/3rdparty/masm/wtf/PageAllocationAligned.cpp b/src/3rdparty/masm/wtf/PageAllocationAligned.cpp
index bdb976b1b7..90c2fd61db 100644
--- a/src/3rdparty/masm/wtf/PageAllocationAligned.cpp
+++ b/src/3rdparty/masm/wtf/PageAllocationAligned.cpp
@@ -52,7 +52,7 @@ PageAllocationAligned PageAllocationAligned::allocate(size_t size, size_t alignm
// Resererve with suffcient additional VM to correctly align.
size_t reservationSize = size + alignmentDelta;
- void* reservationBase = OSAllocator::reserveUncommitted(reservationSize, usage, writable, false);
+ void* reservationBase = OSAllocator::reserveUncommitted(reservationSize, usage, writable);
// Select an aligned region within the reservation and commit.
void* alignedBase = reinterpret_cast<uintptr_t>(reservationBase) & alignmentMask
@@ -75,10 +75,11 @@ void PageAllocationAligned::deallocate()
ASSERT(!*this);
#if OS(DARWIN)
- vm_deallocate(current_task(), reinterpret_cast<vm_address_t>(tmp.base()), tmp.size());
+ vm_deallocate(current_task(), reinterpret_cast<vm_address_t>(tmp.realBase()), tmp.realSize());
#else
- ASSERT(tmp.m_reservation.contains(tmp.base(), tmp.size()));
- OSAllocator::decommitAndRelease(tmp.m_reservation.base(), tmp.m_reservation.size(), tmp.base(), tmp.size());
+ ASSERT(tmp.m_reservation.contains(tmp.realBase(), tmp.realSize()));
+ OSAllocator::decommitAndRelease(tmp.m_reservation.realBase(), tmp.m_reservation.realSize(),
+ tmp.realBase(), tmp.realSize());
#endif
}
diff --git a/src/3rdparty/masm/wtf/PageBlock.h b/src/3rdparty/masm/wtf/PageBlock.h
index 56e5570178..4d408e1c91 100644
--- a/src/3rdparty/masm/wtf/PageBlock.h
+++ b/src/3rdparty/masm/wtf/PageBlock.h
@@ -40,8 +40,13 @@ public:
PageBlock(const PageBlock&);
PageBlock(void*, size_t, bool hasGuardPages);
+ void* realBase() const { return m_realBase; }
void* base() const { return m_base; }
- size_t size() const { return m_size; }
+ size_t size() const
+ {
+ return m_size - 2 * (static_cast<char *>(m_base) - static_cast<char *>(m_realBase));
+ }
+ size_t realSize() const { return m_size; }
operator bool() const { return !!m_realBase; }
diff --git a/src/3rdparty/masm/wtf/PageReservation.h b/src/3rdparty/masm/wtf/PageReservation.h
index 77783ebcc4..74a136168c 100644
--- a/src/3rdparty/masm/wtf/PageReservation.h
+++ b/src/3rdparty/masm/wtf/PageReservation.h
@@ -104,13 +104,7 @@ public:
static PageReservation reserve(size_t size, OSAllocator::Usage usage = OSAllocator::UnknownUsage, bool writable = true, bool executable = false)
{
ASSERT(isPageAligned(size));
- return PageReservation(OSAllocator::reserveUncommitted(size, usage, writable, executable), size, writable, executable, false);
- }
-
- static PageReservation reserveWithGuardPages(size_t size, OSAllocator::Usage usage = OSAllocator::UnknownUsage, bool writable = true, bool executable = false)
- {
- ASSERT(isPageAligned(size));
- return PageReservation(OSAllocator::reserveUncommitted(size + pageSize() * 2, usage, writable, executable, true), size, writable, executable, true);
+ return PageReservation(OSAllocator::reserveUncommitted(size, usage, writable, executable), size, writable, executable);
}
void deallocate()
@@ -125,12 +119,12 @@ public:
ASSERT(tmp);
ASSERT(!*this);
- OSAllocator::releaseDecommitted(tmp.base(), tmp.size());
+ OSAllocator::releaseDecommitted(tmp.realBase(), tmp.realSize());
}
private:
- PageReservation(void* base, size_t size, bool writable, bool executable, bool hasGuardPages)
- : PageBlock(base, size, hasGuardPages)
+ PageReservation(void* base, size_t size, bool writable, bool executable)
+ : PageBlock(base, size, false)
, m_committed(0)
, m_writable(writable)
, m_executable(executable)
diff --git a/src/3rdparty/masm/yarr/YarrJIT.cpp b/src/3rdparty/masm/yarr/YarrJIT.cpp
index 94a72a57c7..ce18b3ab4f 100644
--- a/src/3rdparty/masm/yarr/YarrJIT.cpp
+++ b/src/3rdparty/masm/yarr/YarrJIT.cpp
@@ -46,10 +46,10 @@ class YarrGenerator : private MacroAssembler {
static const RegisterID input = ARMRegisters::r0;
static const RegisterID index = ARMRegisters::r1;
static const RegisterID length = ARMRegisters::r2;
- static const RegisterID output = ARMRegisters::r4;
+ static const RegisterID output = ARMRegisters::r3;
- static const RegisterID regT0 = ARMRegisters::r5;
- static const RegisterID regT1 = ARMRegisters::r6;
+ static const RegisterID regT0 = ARMRegisters::r4;
+ static const RegisterID regT1 = ARMRegisters::r5;
static const RegisterID returnRegister = ARMRegisters::r0;
static const RegisterID returnRegister2 = ARMRegisters::r1;
@@ -2561,7 +2561,6 @@ class YarrGenerator : private MacroAssembler {
#if CPU(ARM_TRADITIONAL)
push(ARMRegisters::r8); // scratch register
#endif
- push(addressTempRegister);
if (compileMode == IncludeSubpatterns)
move(ARMRegisters::r3, output);
#elif CPU(SH4)
@@ -2589,7 +2588,6 @@ class YarrGenerator : private MacroAssembler {
pop(X86Registers::ebx);
pop(X86Registers::ebp);
#elif CPU(ARM)
- pop(addressTempRegister);
#if CPU(ARM_TRADITIONAL)
pop(ARMRegisters::r8); // scratch register
#endif
diff --git a/src/imports/localstorage/plugin.cpp b/src/imports/localstorage/plugin.cpp
index 8b90f5a685..84b0b2387a 100644
--- a/src/imports/localstorage/plugin.cpp
+++ b/src/imports/localstorage/plugin.cpp
@@ -52,28 +52,29 @@
#include <private/qv4functionobject_p.h>
#include <private/qv4objectproto_p.h>
#include <private/qv4scopedvalue_p.h>
+#include <private/qv4objectiterator_p.h>
-using namespace QV4;
+QT_BEGIN_NAMESPACE
#define V4THROW_SQL(error, desc) { \
- QV4::Scoped<String> v(scope, scope.engine->newString(desc)); \
- QV4::Scoped<Object> ex(scope, scope.engine->newErrorObject(v)); \
+ QV4::ScopedString v(scope, scope.engine->newString(desc)); \
+ QV4::ScopedObject ex(scope, scope.engine->newErrorObject(v)); \
ex->put(QV4::ScopedString(scope, scope.engine->newIdentifier(QStringLiteral("code"))).getPointer(), QV4::ScopedValue(scope, Primitive::fromInt32(error))); \
- ctx->throwError(ex); \
+ ctx->engine()->throwError(ex); \
return Encode::undefined(); \
}
#define V4THROW_SQL2(error, desc) { \
- QV4::Scoped<String> v(scope, scope.engine->newString(desc)); \
- QV4::Scoped<Object> ex(scope, scope.engine->newErrorObject(v)); \
+ QV4::ScopedString v(scope, scope.engine->newString(desc)); \
+ QV4::ScopedObject ex(scope, scope.engine->newErrorObject(v)); \
ex->put(QV4::ScopedString(scope, scope.engine->newIdentifier(QStringLiteral("code"))).getPointer(), QV4::ScopedValue(scope, Primitive::fromInt32(error))); \
- args->setReturnValue(ctx->throwError(ex)); \
+ args->setReturnValue(ctx->engine()->throwError(ex)); \
return; \
}
#define V4THROW_REFERENCE(string) { \
- QV4::Scoped<String> v(scope, scope.engine->newString(string)); \
- ctx->throwReferenceError(v); \
+ QV4::ScopedString v(scope, scope.engine->newString(string)); \
+ ctx->engine()->throwReferenceError(v); \
return Encode::undefined(); \
}
@@ -81,27 +82,22 @@ using namespace QV4;
class QQmlSqlDatabaseData : public QV8Engine::Deletable
{
public:
- QQmlSqlDatabaseData(QV8Engine *engine);
+ QQmlSqlDatabaseData(QV4::ExecutionEngine *engine);
~QQmlSqlDatabaseData();
- PersistentValue databaseProto;
- PersistentValue queryProto;
- PersistentValue rowsProto;
+ QV4::PersistentValue databaseProto;
+ QV4::PersistentValue queryProto;
+ QV4::PersistentValue rowsProto;
};
-V8_DEFINE_EXTENSION(QQmlSqlDatabaseData, databaseData)
+V4_DEFINE_EXTENSION(QQmlSqlDatabaseData, databaseData)
-class QQmlSqlDatabaseWrapper : public Object
-{
-public:
- enum Type { Database, Query, Rows };
- struct Data : Object::Data {
- Data(ExecutionEngine *e)
- : Object::Data(e)
- {
- setVTable(staticVTable());
- type = Database;
- }
+namespace QV4 {
+
+namespace Heap {
+ struct QQmlSqlDatabaseWrapper : public Object {
+ enum Type { Database, Query, Rows };
+ QQmlSqlDatabaseWrapper(ExecutionEngine *e);
Type type;
QSqlDatabase database;
@@ -114,30 +110,43 @@ public:
QSqlQuery sqlQuery; // type == Rows
bool forwardOnly; // type == Rows
};
- V4_OBJECT(Object)
+}
+
+class QQmlSqlDatabaseWrapper : public Object
+{
+public:
+ V4_OBJECT2(QQmlSqlDatabaseWrapper, Object)
+ V4_NEEDS_DESTROY
- static QQmlSqlDatabaseWrapper *create(QV8Engine *engine)
+ static Heap::QQmlSqlDatabaseWrapper *create(QV4::ExecutionEngine *engine)
{
- QV4::ExecutionEngine *e = QV8Engine::getV4(engine);
- return e->memoryManager->alloc<QQmlSqlDatabaseWrapper>(e);
+ return engine->memoryManager->alloc<QQmlSqlDatabaseWrapper>(engine);
}
~QQmlSqlDatabaseWrapper() {
}
static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty);
- static void destroy(Managed *that) {
- static_cast<QQmlSqlDatabaseWrapper *>(that)->~QQmlSqlDatabaseWrapper();
- }
};
-DEFINE_OBJECT_VTABLE(QQmlSqlDatabaseWrapper);
+}
+
+using namespace QV4;
+
+DEFINE_OBJECT_VTABLE(QV4::QQmlSqlDatabaseWrapper);
+
+QV4::Heap::QQmlSqlDatabaseWrapper::QQmlSqlDatabaseWrapper(ExecutionEngine *e)
+ : QV4::Heap::Object(e)
+{
+ setVTable(QV4::QQmlSqlDatabaseWrapper::staticVTable());
+ type = Database;
+}
static ReturnedValue qmlsqldatabase_version(CallContext *ctx)
{
QV4::Scope scope(ctx);
QV4::Scoped<QQmlSqlDatabaseWrapper> r(scope, ctx->d()->callData->thisObject.as<QQmlSqlDatabaseWrapper>());
- if (!r || r->d()->type != QQmlSqlDatabaseWrapper::Database)
+ if (!r || r->d()->type != Heap::QQmlSqlDatabaseWrapper::Database)
V4THROW_REFERENCE("Not a SQLDatabase object");
return Encode(scope.engine->newString(r->d()->version));
@@ -147,7 +156,7 @@ static ReturnedValue qmlsqldatabase_rows_length(CallContext *ctx)
{
QV4::Scope scope(ctx);
QV4::Scoped<QQmlSqlDatabaseWrapper> r(scope, ctx->d()->callData->thisObject.as<QQmlSqlDatabaseWrapper>());
- if (!r || r->d()->type != QQmlSqlDatabaseWrapper::Rows)
+ if (!r || r->d()->type != Heap::QQmlSqlDatabaseWrapper::Rows)
V4THROW_REFERENCE("Not a SQLDatabase::Rows object");
int s = r->d()->sqlQuery.size();
@@ -166,7 +175,7 @@ static ReturnedValue qmlsqldatabase_rows_forwardOnly(CallContext *ctx)
{
QV4::Scope scope(ctx);
QV4::Scoped<QQmlSqlDatabaseWrapper> r(scope, ctx->d()->callData->thisObject.as<QQmlSqlDatabaseWrapper>());
- if (!r || r->d()->type != QQmlSqlDatabaseWrapper::Rows)
+ if (!r || r->d()->type != Heap::QQmlSqlDatabaseWrapper::Rows)
V4THROW_REFERENCE("Not a SQLDatabase::Rows object");
return Encode(r->d()->sqlQuery.isForwardOnly());
}
@@ -175,10 +184,10 @@ static ReturnedValue qmlsqldatabase_rows_setForwardOnly(CallContext *ctx)
{
QV4::Scope scope(ctx);
QV4::Scoped<QQmlSqlDatabaseWrapper> r(scope, ctx->d()->callData->thisObject.as<QQmlSqlDatabaseWrapper>());
- if (!r || r->d()->type != QQmlSqlDatabaseWrapper::Rows)
+ if (!r || r->d()->type != Heap::QQmlSqlDatabaseWrapper::Rows)
V4THROW_REFERENCE("Not a SQLDatabase::Rows object");
if (ctx->d()->callData->argc < 1)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
r->d()->sqlQuery.setForwardOnly(ctx->d()->callData->args[0].toBoolean());
return Encode::undefined();
@@ -188,20 +197,20 @@ QQmlSqlDatabaseData::~QQmlSqlDatabaseData()
{
}
-static QString qmlsqldatabase_databasesPath(QV8Engine *engine)
+static QString qmlsqldatabase_databasesPath(QV4::ExecutionEngine *engine)
{
- return engine->engine()->offlineStoragePath() +
+ return engine->qmlEngine()->offlineStoragePath() +
QDir::separator() + QLatin1String("Databases");
}
-static void qmlsqldatabase_initDatabasesPath(QV8Engine *engine)
+static void qmlsqldatabase_initDatabasesPath(QV4::ExecutionEngine *engine)
{
QString databasesPath = qmlsqldatabase_databasesPath(engine);
if (!QDir().mkpath(databasesPath))
qWarning() << "LocalStorage: can't create path - " << databasesPath;
}
-static QString qmlsqldatabase_databaseFile(const QString& connectionName, QV8Engine *engine)
+static QString qmlsqldatabase_databaseFile(const QString& connectionName, QV4::ExecutionEngine *engine)
{
return qmlsqldatabase_databasesPath(engine) + QDir::separator() + connectionName;
}
@@ -209,16 +218,15 @@ static QString qmlsqldatabase_databaseFile(const QString& connectionName, QV8Eng
static ReturnedValue qmlsqldatabase_rows_index(QQmlSqlDatabaseWrapper *r, ExecutionEngine *v4, quint32 index, bool *hasProperty = 0)
{
Scope scope(v4);
- QV8Engine *v8 = v4->v8Engine;
if (r->d()->sqlQuery.at() == (int)index || r->d()->sqlQuery.seek(index)) {
QSqlRecord record = r->d()->sqlQuery.record();
// XXX optimize
- Scoped<Object> row(scope, v4->newObject());
+ ScopedObject row(scope, v4->newObject());
for (int ii = 0; ii < record.count(); ++ii) {
QVariant v = record.value(ii);
ScopedString s(scope, v4->newIdentifier(record.fieldName(ii)));
- ScopedValue val(scope, v.isNull() ? Encode::null() : v8->fromVariant(v));
+ ScopedValue val(scope, v.isNull() ? Encode::null() : v4->fromVariant(v));
row->put(s.getPointer(), val);
}
if (hasProperty)
@@ -236,7 +244,7 @@ ReturnedValue QQmlSqlDatabaseWrapper::getIndexed(Managed *m, uint index, bool *h
QV4::Scope scope(m->engine());
Q_ASSERT(m->as<QQmlSqlDatabaseWrapper>());
QV4::Scoped<QQmlSqlDatabaseWrapper> r(scope, static_cast<QQmlSqlDatabaseWrapper *>(m));
- if (!r || r->d()->type != QQmlSqlDatabaseWrapper::Rows)
+ if (!r || r->d()->type != Heap::QQmlSqlDatabaseWrapper::Rows)
return Object::getIndexed(m, index, hasProperty);
return qmlsqldatabase_rows_index(r, m->engine(), index, hasProperty);
@@ -246,7 +254,7 @@ static ReturnedValue qmlsqldatabase_rows_item(CallContext *ctx)
{
QV4::Scope scope(ctx);
QV4::Scoped<QQmlSqlDatabaseWrapper> r(scope, ctx->d()->callData->thisObject.as<QQmlSqlDatabaseWrapper>());
- if (!r || r->d()->type != QQmlSqlDatabaseWrapper::Rows)
+ if (!r || r->d()->type != Heap::QQmlSqlDatabaseWrapper::Rows)
V4THROW_REFERENCE("Not a SQLDatabase::Rows object");
return qmlsqldatabase_rows_index(r, scope.engine, ctx->d()->callData->argc ? ctx->d()->callData->args[0].toUInt32() : 0);
@@ -256,11 +264,9 @@ static ReturnedValue qmlsqldatabase_executeSql(CallContext *ctx)
{
QV4::Scope scope(ctx);
QV4::Scoped<QQmlSqlDatabaseWrapper> r(scope, ctx->d()->callData->thisObject.as<QQmlSqlDatabaseWrapper>());
- if (!r || r->d()->type != QQmlSqlDatabaseWrapper::Query)
+ if (!r || r->d()->type != Heap::QQmlSqlDatabaseWrapper::Query)
V4THROW_REFERENCE("Not a SQLDatabase::Query object");
- QV8Engine *engine = scope.engine->v8Engine;
-
if (!r->d()->inTransaction)
V4THROW_SQL(SQLEXCEPTION_DATABASE_ERR,QQmlEngine::tr("executeSql called outside transaction()"));
@@ -285,7 +291,7 @@ static ReturnedValue qmlsqldatabase_executeSql(CallContext *ctx)
quint32 size = array->getLength();
QV4::ScopedValue v(scope);
for (quint32 ii = 0; ii < size; ++ii)
- query.bindValue(ii, engine->toVariant((v = array->getIndexed(ii)), -1));
+ query.bindValue(ii, scope.engine->toVariant((v = array->getIndexed(ii)), -1));
} else if (values->asObject()) {
ScopedObject object(scope, values);
ObjectIterator it(scope, object, ObjectIterator::WithProtoChain|ObjectIterator::EnumerableOnly);
@@ -295,7 +301,7 @@ static ReturnedValue qmlsqldatabase_executeSql(CallContext *ctx)
key = it.nextPropertyName(val);
if (key->isNull())
break;
- QVariant v = engine->toVariant(val, -1);
+ QVariant v = scope.engine->toVariant(val, -1);
if (key->isString()) {
query.bindValue(key->stringValue()->toQString(), v);
} else {
@@ -304,24 +310,24 @@ static ReturnedValue qmlsqldatabase_executeSql(CallContext *ctx)
}
}
} else {
- query.bindValue(0, engine->toVariant(values, -1));
+ query.bindValue(0, scope.engine->toVariant(values, -1));
}
}
if (query.exec()) {
- QV4::Scoped<QQmlSqlDatabaseWrapper> rows(scope, QQmlSqlDatabaseWrapper::create(engine));
- QV4::ScopedObject p(scope, databaseData(engine)->rowsProto.value());
+ QV4::Scoped<QQmlSqlDatabaseWrapper> rows(scope, QQmlSqlDatabaseWrapper::create(scope.engine));
+ QV4::ScopedObject p(scope, databaseData(scope.engine)->rowsProto.value());
rows->setPrototype(p.getPointer());
- rows->d()->type = QQmlSqlDatabaseWrapper::Rows;
+ rows->d()->type = Heap::QQmlSqlDatabaseWrapper::Rows;
rows->d()->database = db;
rows->d()->sqlQuery = query;
- Scoped<Object> resultObject(scope, scope.engine->newObject());
+ ScopedObject resultObject(scope, scope.engine->newObject());
result = resultObject.asReturnedValue();
// XXX optimize
ScopedString s(scope);
ScopedValue v(scope);
resultObject->put((s = scope.engine->newIdentifier("rowsAffected")).getPointer(), (v = Primitive::fromInt32(query.numRowsAffected())));
- resultObject->put((s = scope.engine->newIdentifier("insertId")).getPointer(), (v = engine->toString(query.lastInsertId().toString())));
+ resultObject->put((s = scope.engine->newIdentifier("insertId")).getPointer(), (v = scope.engine->newString(query.lastInsertId().toString())));
resultObject->put((s = scope.engine->newIdentifier("rows")).getPointer(), rows);
} else {
err = true;
@@ -372,23 +378,21 @@ static ReturnedValue qmlsqldatabase_changeVersion(CallContext *ctx)
Scope scope(ctx);
Scoped<QQmlSqlDatabaseWrapper> r(scope, ctx->d()->callData->thisObject);
- if (!r || r->d()->type != QQmlSqlDatabaseWrapper::Database)
+ if (!r || r->d()->type != Heap::QQmlSqlDatabaseWrapper::Database)
V4THROW_REFERENCE("Not a SQLDatabase object");
- QV8Engine *engine = scope.engine->v8Engine;
-
QSqlDatabase db = r->d()->database;
QString from_version = ctx->d()->callData->args[0].toQString();
QString to_version = ctx->d()->callData->args[1].toQString();
- Scoped<FunctionObject> callback(scope, ctx->argument(2));
+ ScopedFunctionObject callback(scope, ctx->argument(2));
if (from_version != r->d()->version)
V4THROW_SQL(SQLEXCEPTION_VERSION_ERR, QQmlEngine::tr("Version mismatch: expected %1, found %2").arg(from_version).arg(r->d()->version));
- Scoped<QQmlSqlDatabaseWrapper> w(scope, QQmlSqlDatabaseWrapper::create(engine));
- ScopedObject p(scope, databaseData(engine)->queryProto.value());
+ Scoped<QQmlSqlDatabaseWrapper> w(scope, QQmlSqlDatabaseWrapper::create(scope.engine));
+ ScopedObject p(scope, databaseData(scope.engine)->queryProto.value());
w->setPrototype(p.getPointer());
- w->d()->type = QQmlSqlDatabaseWrapper::Query;
+ w->d()->type = Heap::QQmlSqlDatabaseWrapper::Query;
w->d()->database = db;
w->d()->version = r->d()->version;
@@ -398,7 +402,7 @@ static ReturnedValue qmlsqldatabase_changeVersion(CallContext *ctx)
db.transaction();
ScopedCallData callData(scope, 1);
- callData->thisObject = engine->global();
+ callData->thisObject = scope.engine->globalObject();
callData->args[0] = w;
TransactionRollback rollbackOnException(&db, &w->d()->inTransaction);
@@ -415,7 +419,7 @@ static ReturnedValue qmlsqldatabase_changeVersion(CallContext *ctx)
if (ok) {
w->d()->version = to_version;
#ifndef QT_NO_SETTINGS
- QSettings ini(qmlsqldatabase_databaseFile(db.connectionName(),engine) + QLatin1String(".ini"), QSettings::IniFormat);
+ QSettings ini(qmlsqldatabase_databaseFile(db.connectionName(), scope.engine) + QLatin1String(".ini"), QSettings::IniFormat);
ini.setValue(QLatin1String("Version"), to_version);
#endif
}
@@ -427,21 +431,19 @@ static ReturnedValue qmlsqldatabase_transaction_shared(CallContext *ctx, bool re
{
QV4::Scope scope(ctx);
QV4::Scoped<QQmlSqlDatabaseWrapper> r(scope, ctx->d()->callData->thisObject.as<QQmlSqlDatabaseWrapper>());
- if (!r || r->d()->type != QQmlSqlDatabaseWrapper::Database)
+ if (!r || r->d()->type != Heap::QQmlSqlDatabaseWrapper::Database)
V4THROW_REFERENCE("Not a SQLDatabase object");
- QV8Engine *engine = scope.engine->v8Engine;
-
FunctionObject *callback = ctx->d()->callData->argc ? ctx->d()->callData->args[0].asFunctionObject() : 0;
if (!callback)
V4THROW_SQL(SQLEXCEPTION_UNKNOWN_ERR, QQmlEngine::tr("transaction: missing callback"));
QSqlDatabase db = r->d()->database;
- Scoped<QQmlSqlDatabaseWrapper> w(scope, QQmlSqlDatabaseWrapper::create(engine));
- QV4::ScopedObject p(scope, databaseData(engine)->queryProto.value());
+ Scoped<QQmlSqlDatabaseWrapper> w(scope, QQmlSqlDatabaseWrapper::create(scope.engine));
+ QV4::ScopedObject p(scope, databaseData(scope.engine)->queryProto.value());
w->setPrototype(p.getPointer());
- w->d()->type = QQmlSqlDatabaseWrapper::Query;
+ w->d()->type = Heap::QQmlSqlDatabaseWrapper::Query;
w->d()->database = db;
w->d()->version = r->d()->version;
w->d()->readonly = readOnly;
@@ -449,7 +451,7 @@ static ReturnedValue qmlsqldatabase_transaction_shared(CallContext *ctx, bool re
db.transaction();
if (callback) {
ScopedCallData callData(scope, 1);
- callData->thisObject = engine->global();
+ callData->thisObject = scope.engine->globalObject();
callData->args[0] = w;
TransactionRollback rollbackOnException(&db, &w->d()->inTransaction);
callback->call(callData);
@@ -472,12 +474,11 @@ static ReturnedValue qmlsqldatabase_read_transaction(CallContext *ctx)
return qmlsqldatabase_transaction_shared(ctx, true);
}
-QQmlSqlDatabaseData::QQmlSqlDatabaseData(QV8Engine *engine)
+QQmlSqlDatabaseData::QQmlSqlDatabaseData(ExecutionEngine *v4)
{
- ExecutionEngine *v4 = QV8Engine::getV4(engine);
Scope scope(v4);
{
- Scoped<Object> proto(scope, v4->newObject());
+ ScopedObject proto(scope, v4->newObject());
proto->defineDefaultProperty(QStringLiteral("transaction"), qmlsqldatabase_transaction);
proto->defineDefaultProperty(QStringLiteral("readTransaction"), qmlsqldatabase_read_transaction);
proto->defineAccessorProperty(QStringLiteral("version"), qmlsqldatabase_version, 0);
@@ -486,12 +487,12 @@ QQmlSqlDatabaseData::QQmlSqlDatabaseData(QV8Engine *engine)
}
{
- Scoped<Object> proto(scope, v4->newObject());
+ ScopedObject proto(scope, v4->newObject());
proto->defineDefaultProperty(QStringLiteral("executeSql"), qmlsqldatabase_executeSql);
queryProto = proto;
}
{
- Scoped<Object> proto(scope, v4->newObject());
+ ScopedObject proto(scope, v4->newObject());
proto->defineDefaultProperty(QStringLiteral("item"), qmlsqldatabase_rows_item);
proto->defineAccessorProperty(QStringLiteral("length"), qmlsqldatabase_rows_length, 0);
proto->defineAccessorProperty(QStringLiteral("forwardOnly"),
@@ -659,13 +660,12 @@ public:
void QQuickLocalStorage::openDatabaseSync(QQmlV4Function *args)
{
#ifndef QT_NO_SETTINGS
- QV8Engine *engine = args->engine();
- QV4::ExecutionContext *ctx = args->v4engine()->currentContext();
- QV4::Scope scope(ctx);
- if (engine->engine()->offlineStoragePath().isEmpty())
+ QV4::Scope scope(args->v4engine());
+ QV4::ScopedContext ctx(scope, args->v4engine()->currentContext());
+ if (scope.engine->qmlEngine()->offlineStoragePath().isEmpty())
V4THROW_SQL2(SQLEXCEPTION_DATABASE_ERR, QQmlEngine::tr("SQL: can't create database, offline storage is disabled."));
- qmlsqldatabase_initDatabasesPath(engine);
+ qmlsqldatabase_initDatabasesPath(scope.engine);
QSqlDatabase database;
@@ -680,7 +680,7 @@ void QQuickLocalStorage::openDatabaseSync(QQmlV4Function *args)
md5.addData(dbname.toUtf8());
QString dbid(QLatin1String(md5.result().toHex()));
- QString basename = qmlsqldatabase_databaseFile(dbid, engine);
+ QString basename = qmlsqldatabase_databaseFile(dbid, scope.engine);
bool created = false;
QString version = dbversion;
@@ -716,8 +716,8 @@ void QQuickLocalStorage::openDatabaseSync(QQmlV4Function *args)
database.open();
}
- QV4::Scoped<QQmlSqlDatabaseWrapper> db(scope, QQmlSqlDatabaseWrapper::create(engine));
- QV4::ScopedObject p(scope, databaseData(engine)->databaseProto.value());
+ QV4::Scoped<QQmlSqlDatabaseWrapper> db(scope, QQmlSqlDatabaseWrapper::create(scope.engine));
+ QV4::ScopedObject p(scope, databaseData(scope.engine)->databaseProto.value());
db->setPrototype(p.getPointer());
db->d()->database = database;
db->d()->version = version;
@@ -725,7 +725,7 @@ void QQuickLocalStorage::openDatabaseSync(QQmlV4Function *args)
if (created && dbcreationCallback) {
Scope scope(ctx);
ScopedCallData callData(scope, 1);
- callData->thisObject = engine->global();
+ callData->thisObject = scope.engine->globalObject();
callData->args[0] = db;
dbcreationCallback->call(callData);
}
@@ -760,4 +760,6 @@ public:
}
};
+QT_END_NAMESPACE
+
#include "plugin.moc"
diff --git a/src/imports/statemachine/signaltransition.cpp b/src/imports/statemachine/signaltransition.cpp
index 37edd6eb87..41286d84c8 100644
--- a/src/imports/statemachine/signaltransition.cpp
+++ b/src/imports/statemachine/signaltransition.cpp
@@ -44,6 +44,7 @@
#include <private/qv8engine_p.h>
#include <private/qjsvalue_p.h>
#include <private/qv4scopedvalue_p.h>
+#include <private/qqmlcontext_p.h>
SignalTransition::SignalTransition(QState *parent)
: QSignalTransition(this, SIGNAL(invokeYourself()), parent)
@@ -60,7 +61,10 @@ bool SignalTransition::eventTest(QEvent *event)
if (m_guard.isEmpty())
return true;
- QQmlContext context(QQmlEngine::contextForObject(this));
+ QQmlContext *outerContext = QQmlEngine::contextForObject(this);
+ QQmlContext context(outerContext);
+ QQmlContextData::get(outerContext)->imports->addref();
+ QQmlContextData::get(&context)->imports = QQmlContextData::get(outerContext)->imports;
QStateMachine::SignalEvent *e = static_cast<QStateMachine::SignalEvent*>(event);
diff --git a/src/imports/testlib/TestCase.qml b/src/imports/testlib/TestCase.qml
index 160e0bdb62..8425b0641c 100644
--- a/src/imports/testlib/TestCase.qml
+++ b/src/imports/testlib/TestCase.qml
@@ -846,6 +846,8 @@ Item {
function waitForRendering(item, timeout) {
if (timeout === undefined)
timeout = 5000
+ if (!item)
+ qtest_fail("No item given to waitForRendering", 1)
return qtest_results.waitForRendering(item, timeout)
}
@@ -932,12 +934,13 @@ Item {
}
/*!
- \qmlmethod TestCase::mousePress(item, x, y, button = Qt.LeftButton, modifiers = Qt.NoModifier, delay = -1)
+ \qmlmethod TestCase::mousePress(item, x = item.width / 2, y = item.height / 2, button = Qt.LeftButton, modifiers = Qt.NoModifier, delay = -1)
Simulates pressing a mouse \a button with an optional \a modifier
- on an \a item. The position is defined by \a x and \a y. If \a delay is
- specified, the test will wait for the specified amount of milliseconds
- before the press.
+ on an \a item. The position is defined by \a x and \a y.
+ If \a x or \a y are not defined the position will be the center of \a item.
+ If \a delay is specified, the test will wait for the specified amount of
+ milliseconds before the press.
The position given by \a x and \a y is transformed from the co-ordinate
system of \a item into window co-ordinates and then delivered.
@@ -953,15 +956,20 @@ Item {
modifiers = Qt.NoModifier
if (delay == undefined)
delay = -1
+ if (x === undefined)
+ x = item.width / 2
+ if (y === undefined)
+ y = item.height / 2
if (!qtest_events.mousePress(item, x, y, button, modifiers, delay))
qtest_fail("window not shown", 2)
}
/*!
- \qmlmethod TestCase::mouseRelease(item, x, y, button = Qt.LeftButton, modifiers = Qt.NoModifier, delay = -1)
+ \qmlmethod TestCase::mouseRelease(item, x = item.width / 2, y = item.height / 2, button = Qt.LeftButton, modifiers = Qt.NoModifier, delay = -1)
Simulates releasing a mouse \a button with an optional \a modifier
on an \a item. The position of the release is defined by \a x and \a y.
+ If \a x or \a y are not defined the position will be the center of \a item.
If \a delay is specified, the test will wait for the specified amount of
milliseconds before releasing the button.
@@ -979,6 +987,10 @@ Item {
modifiers = Qt.NoModifier
if (delay == undefined)
delay = -1
+ if (x === undefined)
+ x = item.width / 2
+ if (y === undefined)
+ y = item.height / 2
if (!qtest_events.mouseRelease(item, x, y, button, modifiers, delay))
qtest_fail("window not shown", 2)
}
@@ -1033,10 +1045,11 @@ Item {
}
/*!
- \qmlmethod TestCase::mouseClick(item, x, y, button = Qt.LeftButton, modifiers = Qt.NoModifier, delay = -1)
+ \qmlmethod TestCase::mouseClick(item, x = item.width / 2, y = item.height / 2, button = Qt.LeftButton, modifiers = Qt.NoModifier, delay = -1)
Simulates clicking a mouse \a button with an optional \a modifier
on an \a item. The position of the click is defined by \a x and \a y.
+ If \a x and \a y are not defined the position will be the center of \a item.
If \a delay is specified, the test will wait for the specified amount of
milliseconds before pressing and before releasing the button.
@@ -1054,15 +1067,20 @@ Item {
modifiers = Qt.NoModifier
if (delay == undefined)
delay = -1
+ if (x === undefined)
+ x = item.width / 2
+ if (y === undefined)
+ y = item.height / 2
if (!qtest_events.mouseClick(item, x, y, button, modifiers, delay))
qtest_fail("window not shown", 2)
}
/*!
- \qmlmethod TestCase::mouseDoubleClick(item, x, y, button = Qt.LeftButton, modifiers = Qt.NoModifier, delay = -1)
+ \qmlmethod TestCase::mouseDoubleClick(item, x = item.width / 2, y = item.height / 2, button = Qt.LeftButton, modifiers = Qt.NoModifier, delay = -1)
Simulates double-clicking a mouse \a button with an optional \a modifier
on an \a item. The position of the click is defined by \a x and \a y.
+ If \a x and \a y are not defined the position will be the center of \a item.
If \a delay is specified, the test will wait for the specified amount of
milliseconds before pressing and before releasing the button.
@@ -1080,6 +1098,10 @@ Item {
modifiers = Qt.NoModifier
if (delay == undefined)
delay = -1
+ if (x === undefined)
+ x = item.width / 2
+ if (y === undefined)
+ y = item.height / 2
if (!qtest_events.mouseDoubleClick(item, x, y, button, modifiers, delay))
qtest_fail("window not shown", 2)
}
diff --git a/src/imports/xmllistmodel/qqmlxmllistmodel.cpp b/src/imports/xmllistmodel/qqmlxmllistmodel.cpp
index 225eedb578..824703e033 100644
--- a/src/imports/xmllistmodel/qqmlxmllistmodel.cpp
+++ b/src/imports/xmllistmodel/qqmlxmllistmodel.cpp
@@ -925,7 +925,7 @@ QQmlV4Handle QQuickXmlListModel::get(int index) const
ScopedValue value(scope);
for (int ii = 0; ii < d->roleObjects.count(); ++ii) {
name = v4engine->newIdentifier(d->roleObjects[ii]->name());
- value = v8engine->fromVariant(d->data.value(ii).value(index));
+ value = v4engine->fromVariant(d->data.value(ii).value(index));
o->insertMember(name.getPointer(), value);
}
diff --git a/src/particles/qquickcustomaffector.cpp b/src/particles/qquickcustomaffector.cpp
index 874371632e..3fecc83a4e 100644
--- a/src/particles/qquickcustomaffector.cpp
+++ b/src/particles/qquickcustomaffector.cpp
@@ -141,7 +141,7 @@ void QQuickCustomAffector::affectSystem(qreal dt)
QV4::ExecutionEngine *v4 = QV8Engine::getV4(qmlEngine->handle());
QV4::Scope scope(v4);
- QV4::Scoped<QV4::ArrayObject> array(scope, v4->newArrayObject(toAffect.size()));
+ QV4::ScopedArrayObject array(scope, v4->newArrayObject(toAffect.size()));
QV4::ScopedValue v(scope);
for (int i=0; i<toAffect.size(); i++)
array->putIndexed(i, (v = toAffect[i]->v4Value()));
diff --git a/src/particles/qquickparticleemitter.cpp b/src/particles/qquickparticleemitter.cpp
index 9c7d9facf3..b76e917069 100644
--- a/src/particles/qquickparticleemitter.cpp
+++ b/src/particles/qquickparticleemitter.cpp
@@ -479,7 +479,7 @@ void QQuickParticleEmitter::emitWindow(int timeStamp)
//Done after emitParticle so that the Painter::load is done first, this allows you to customize its static variables
//We then don't need to request another reload, because the first reload isn't scheduled until we get back to the render thread
- QV4::Scoped<QV4::ArrayObject> array(scope, v4->newArrayObject(toEmit.size()));
+ QV4::ScopedArrayObject array(scope, v4->newArrayObject(toEmit.size()));
QV4::ScopedValue v(scope);
for (int i=0; i<toEmit.size(); i++)
array->putIndexed(i, (v = toEmit[i]->v4Value()));
diff --git a/src/particles/qquickparticlesystem.cpp b/src/particles/qquickparticlesystem.cpp
index 51a92de00f..edd85721f1 100644
--- a/src/particles/qquickparticlesystem.cpp
+++ b/src/particles/qquickparticlesystem.cpp
@@ -931,19 +931,26 @@ void QQuickParticleSystem::emittersChanged()
if (!m_componentComplete)
return;
- m_emitters.removeAll(0);
-
-
- QList<int> previousSizes;
- QList<int> newSizes;
+ QVector<int> previousSizes;
+ QVector<int> newSizes;
+ previousSizes.reserve(m_nextGroupId);
+ newSizes.reserve(m_nextGroupId);
for (int i=0; i<m_nextGroupId; i++) {
previousSizes << groupData[i]->size();
newSizes << 0;
}
- foreach (QQuickParticleEmitter* e, m_emitters) {//Populate groups and set sizes.
- if (!groupIds.contains(e->group())
- || (!e->group().isEmpty() && !groupIds[e->group()])) {//or it was accidentally inserted by a failed lookup earlier
+ // Populate groups and set sizes.
+ for (int i = 0; i < m_emitters.count(); ++i) {
+ QQuickParticleEmitter *e = m_emitters.at(i);
+ if (!e) {
+ m_emitters.removeAt(i);
+ i--;
+ continue;
+ }
+
+ if (!e->group().isEmpty() &&
+ !groupIds.contains(e->group())) {
int id = m_nextGroupId++;
QQuickParticleGroupData* gd = new QQuickParticleGroupData(id, this);
groupIds.insert(e->group(), id);
diff --git a/src/particles/qquicktrailemitter.cpp b/src/particles/qquicktrailemitter.cpp
index d948f21820..f27a566653 100644
--- a/src/particles/qquicktrailemitter.cpp
+++ b/src/particles/qquicktrailemitter.cpp
@@ -264,7 +264,7 @@ void QQuickTrailEmitter::emitWindow(int timeStamp)
QV4::ExecutionEngine *v4 = QV8Engine::getV4(qmlEngine->handle());
QV4::Scope scope(v4);
- QV4::Scoped<QV4::ArrayObject> array(scope, v4->newArrayObject(toEmit.size()));
+ QV4::ScopedArrayObject array(scope, v4->newArrayObject(toEmit.size()));
QV4::ScopedValue v(scope);
for (int i=0; i<toEmit.size(); i++)
array->putIndexed(i, (v = toEmit[i]->v4Value()));
diff --git a/src/particles/qquickv4particledata.cpp b/src/particles/qquickv4particledata.cpp
index 4bac87eda4..b9cf926052 100644
--- a/src/particles/qquickv4particledata.cpp
+++ b/src/particles/qquickv4particledata.cpp
@@ -267,7 +267,7 @@ struct QV4ParticleData : public QV4::Object
{
struct Data : QV4::Object::Data {
Data(QV4::ExecutionEngine *engine, QQuickParticleData *datum)
- : Object::Data(engine)
+ : QV4::Heap::Object(engine)
, datum(datum)
{
setVTable(QV4ParticleData::staticVTable());
@@ -279,11 +279,11 @@ struct QV4ParticleData : public QV4::Object
DEFINE_OBJECT_VTABLE(QV4ParticleData);
-class QV8ParticleDataDeletable : public QV8Engine::Deletable
+class QV4ParticleDataDeletable : public QV8Engine::Deletable
{
public:
- QV8ParticleDataDeletable(QV8Engine *engine);
- ~QV8ParticleDataDeletable();
+ QV4ParticleDataDeletable(QV4::ExecutionEngine *engine);
+ ~QV4ParticleDataDeletable();
QV4::PersistentValue proto;
};
@@ -294,7 +294,7 @@ static QV4::ReturnedValue particleData_discard(QV4::CallContext *ctx)
QV4::Scoped<QV4ParticleData> r(scope, ctx->d()->callData->thisObject);
if (!r || !r->d()->datum)
- return ctx->throwError(QStringLiteral("Not a valid ParticleData object"));
+ return ctx->engine()->throwError(QStringLiteral("Not a valid ParticleData object"));
r->d()->datum->lifeSpan = 0; //Don't kill(), because it could still be in the middle of being created
return QV4::Encode::undefined();
@@ -306,7 +306,7 @@ static QV4::ReturnedValue particleData_lifeLeft(QV4::CallContext *ctx)
QV4::Scoped<QV4ParticleData> r(scope, ctx->d()->callData->thisObject);
if (!r || !r->d()->datum)
- return ctx->throwError(QStringLiteral("Not a valid ParticleData object"));
+ return ctx->engine()->throwError(QStringLiteral("Not a valid ParticleData object"));
return QV4::Encode(r->d()->datum->lifeLeft());
}
@@ -317,7 +317,7 @@ static QV4::ReturnedValue particleData_curSize(QV4::CallContext *ctx)
QV4::Scoped<QV4ParticleData> r(scope, ctx->d()->callData->thisObject);
if (!r || !r->d()->datum)
- return ctx->throwError(QStringLiteral("Not a valid ParticleData object"));
+ return ctx->engine()->throwError(QStringLiteral("Not a valid ParticleData object"));
return QV4::Encode(r->d()->datum->curSize());
}
@@ -326,7 +326,7 @@ static QV4::ReturnedValue particleData_curSize(QV4::CallContext *ctx)
QV4::Scope scope(ctx); \
QV4::Scoped<QV4ParticleData> r(scope, ctx->d()->callData->thisObject); \
if (!r || !r->d()->datum) \
- ctx->throwError(QStringLiteral("Not a valid ParticleData object")); \
+ ctx->engine()->throwError(QStringLiteral("Not a valid ParticleData object")); \
\
return QV4::Encode((r->d()->datum->color. VAR )/255.0);\
}\
@@ -336,7 +336,7 @@ static QV4::ReturnedValue particleData_set_ ## NAME (QV4::CallContext *ctx)\
QV4::Scope scope(ctx); \
QV4::Scoped<QV4ParticleData> r(scope, ctx->d()->callData->thisObject); \
if (!r || !r->d()->datum)\
- ctx->throwError(QStringLiteral("Not a valid ParticleData object"));\
+ ctx->engine()->throwError(QStringLiteral("Not a valid ParticleData object"));\
\
double d = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toNumber() : 0; \
r->d()->datum->color. VAR = qMin(255, qMax(0, (int)floor(d * 255.0)));\
@@ -349,7 +349,7 @@ static QV4::ReturnedValue particleData_set_ ## NAME (QV4::CallContext *ctx)\
QV4::Scope scope(ctx); \
QV4::Scoped<QV4ParticleData> r(scope, ctx->d()->callData->thisObject); \
if (!r || !r->d()->datum) \
- ctx->throwError(QStringLiteral("Not a valid ParticleData object")); \
+ ctx->engine()->throwError(QStringLiteral("Not a valid ParticleData object")); \
\
return QV4::Encode(r->d()->datum-> VARIABLE);\
}\
@@ -359,7 +359,7 @@ static QV4::ReturnedValue particleData_set_ ## VARIABLE (QV4::CallContext *ctx)\
QV4::Scope scope(ctx); \
QV4::Scoped<QV4ParticleData> r(scope, ctx->d()->callData->thisObject); \
if (!r || !r->d()->datum)\
- ctx->throwError(QStringLiteral("Not a valid ParticleData object"));\
+ ctx->engine()->throwError(QStringLiteral("Not a valid ParticleData object"));\
\
r->d()->datum-> VARIABLE = (ctx->d()->callData->argc && ctx->d()->callData->args[0].toBoolean()) ? 1.0 : 0.0;\
return QV4::Encode::undefined(); \
@@ -370,7 +370,7 @@ static QV4::ReturnedValue particleData_set_ ## VARIABLE (QV4::CallContext *ctx)\
QV4::Scope scope(ctx); \
QV4::Scoped<QV4ParticleData> r(scope, ctx->d()->callData->thisObject); \
if (!r || !r->d()->datum) \
- ctx->throwError(QStringLiteral("Not a valid ParticleData object")); \
+ ctx->engine()->throwError(QStringLiteral("Not a valid ParticleData object")); \
\
return QV4::Encode(r->d()->datum-> VARIABLE);\
}\
@@ -380,7 +380,7 @@ static QV4::ReturnedValue particleData_set_ ## VARIABLE (QV4::CallContext *ctx)\
QV4::Scope scope(ctx); \
QV4::Scoped<QV4ParticleData> r(scope, ctx->d()->callData->thisObject); \
if (!r || !r->d()->datum)\
- ctx->throwError(QStringLiteral("Not a valid ParticleData object"));\
+ ctx->engine()->throwError(QStringLiteral("Not a valid ParticleData object"));\
\
r->d()->datum-> VARIABLE = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toNumber() : qSNaN();\
return QV4::Encode::undefined(); \
@@ -391,7 +391,7 @@ static QV4::ReturnedValue particleData_set_ ## VARIABLE (QV4::CallContext *ctx)\
QV4::Scope scope(ctx); \
QV4::Scoped<QV4ParticleData> r(scope, ctx->d()->callData->thisObject); \
if (!r || !r->d()->datum) \
- ctx->throwError(QStringLiteral("Not a valid ParticleData object")); \
+ ctx->engine()->throwError(QStringLiteral("Not a valid ParticleData object")); \
\
return QV4::Encode(r->d()->datum-> GETTER ());\
}\
@@ -401,7 +401,7 @@ static QV4::ReturnedValue particleData_set_ ## VARIABLE (QV4::CallContext *ctx)\
QV4::Scope scope(ctx); \
QV4::Scoped<QV4ParticleData> r(scope, ctx->d()->callData->thisObject); \
if (!r || !r->d()->datum)\
- ctx->throwError(QStringLiteral("Not a valid ParticleData object"));\
+ ctx->engine()->throwError(QStringLiteral("Not a valid ParticleData object"));\
\
r->d()->datum-> SETTER (ctx->d()->callData->argc ? ctx->d()->callData->args[0].toNumber() : qSNaN());\
return QV4::Encode::undefined(); \
@@ -445,11 +445,10 @@ FAKE_FLOAT_GETTER_AND_SETTER(curY, curY, setInstantaneousY)
FAKE_FLOAT_GETTER_AND_SETTER(curVY, curVY, setInstantaneousVY)
FAKE_FLOAT_GETTER_AND_SETTER(curAY, curAY, setInstantaneousAY)
-QV8ParticleDataDeletable::QV8ParticleDataDeletable(QV8Engine *engine)
+QV4ParticleDataDeletable::QV4ParticleDataDeletable(QV4::ExecutionEngine *v4)
{
- QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
QV4::Scope scope(v4);
- QV4::Scoped<QV4::Object> p(scope, v4->newObject());
+ QV4::ScopedObject p(scope, v4->newObject());
p->defineDefaultProperty(QStringLiteral("discard"), particleData_discard);
p->defineDefaultProperty(QStringLiteral("lifeLeft"), particleData_lifeLeft);
@@ -493,11 +492,11 @@ QV8ParticleDataDeletable::QV8ParticleDataDeletable(QV8Engine *engine)
proto = p;
}
-QV8ParticleDataDeletable::~QV8ParticleDataDeletable()
+QV4ParticleDataDeletable::~QV4ParticleDataDeletable()
{
}
-V8_DEFINE_EXTENSION(QV8ParticleDataDeletable, particleV8Data);
+V4_DEFINE_EXTENSION(QV4ParticleDataDeletable, particleV4Data);
QQuickV4ParticleData::QQuickV4ParticleData(QV8Engine* engine, QQuickParticleData* datum)
@@ -505,12 +504,12 @@ QQuickV4ParticleData::QQuickV4ParticleData(QV8Engine* engine, QQuickParticleData
if (!engine || !datum)
return;
- QV8ParticleDataDeletable *d = particleV8Data(engine);
QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
QV4::Scope scope(v4);
+ QV4ParticleDataDeletable *d = particleV4Data(scope.engine);
QV4::ScopedObject o(scope, v4->memoryManager->alloc<QV4ParticleData>(v4, datum));
QV4::ScopedObject p(scope, d->proto.value());
- o->setPrototype(p.getPointer());
+ o->setPrototype(p);
m_v4Value = o;
}
diff --git a/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp b/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp
index 4388fa7eb1..810f8d18e8 100644
--- a/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp
+++ b/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.cpp
@@ -134,7 +134,7 @@ bool QTcpServerConnection::waitForMessage()
return d->protocol->waitForReadyRead(-1);
}
-void QTcpServerConnection::setPortRange(int portFrom, int portTo, bool block,
+bool QTcpServerConnection::setPortRange(int portFrom, int portTo, bool block,
const QString &hostaddress)
{
Q_D(QTcpServerConnection);
@@ -143,12 +143,16 @@ void QTcpServerConnection::setPortRange(int portFrom, int portTo, bool block,
d->block = block;
d->hostaddress = hostaddress;
- listen();
- if (block)
- d->tcpServer->waitForNewConnection(-1);
+ return listen();
}
-void QTcpServerConnection::listen()
+void QTcpServerConnection::waitForConnection()
+{
+ Q_D(QTcpServerConnection);
+ d->tcpServer->waitForNewConnection(-1);
+}
+
+bool QTcpServerConnection::listen()
{
Q_D(QTcpServerConnection);
@@ -177,6 +181,9 @@ void QTcpServerConnection::listen()
qWarning("QML Debugger: Unable to listen to port %d.", d->portFrom);
else
qWarning("QML Debugger: Unable to listen to ports %d - %d.", d->portFrom, d->portTo);
+ return false;
+ } else {
+ return true;
}
}
diff --git a/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.h b/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.h
index 1b339f1239..66a9c59b26 100644
--- a/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.h
+++ b/src/plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.h
@@ -53,14 +53,14 @@ public:
~QTcpServerConnection();
void setServer(QQmlDebugServer *server);
- void setPortRange(int portFrom, int portTo, bool bock, const QString &hostaddress);
+ bool setPortRange(int portFrom, int portTo, bool bock, const QString &hostaddress);
bool isConnected() const;
void send(const QList<QByteArray> &messages);
void disconnect();
bool waitForMessage();
- void listen();
+ bool listen();
void waitForConnection();
private Q_SLOTS:
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp
index 339278fbe8..45edbb67fa 100644
--- a/src/qml/compiler/qqmlirbuilder.cpp
+++ b/src/qml/compiler/qqmlirbuilder.cpp
@@ -216,60 +216,6 @@ static void replaceWithSpace(QString &str, int idx, int n)
*data++ = space;
}
-#define CHECK_LINE if (l.tokenStartLine() != startLine) return;
-#define CHECK_TOKEN(t) if (token != QQmlJSGrammar:: t) return;
-
-static const int uriTokens[] = {
- QQmlJSGrammar::T_IDENTIFIER,
- QQmlJSGrammar::T_PROPERTY,
- QQmlJSGrammar::T_SIGNAL,
- QQmlJSGrammar::T_READONLY,
- QQmlJSGrammar::T_ON,
- QQmlJSGrammar::T_BREAK,
- QQmlJSGrammar::T_CASE,
- QQmlJSGrammar::T_CATCH,
- QQmlJSGrammar::T_CONTINUE,
- QQmlJSGrammar::T_DEFAULT,
- QQmlJSGrammar::T_DELETE,
- QQmlJSGrammar::T_DO,
- QQmlJSGrammar::T_ELSE,
- QQmlJSGrammar::T_FALSE,
- QQmlJSGrammar::T_FINALLY,
- QQmlJSGrammar::T_FOR,
- QQmlJSGrammar::T_FUNCTION,
- QQmlJSGrammar::T_IF,
- QQmlJSGrammar::T_IN,
- QQmlJSGrammar::T_INSTANCEOF,
- QQmlJSGrammar::T_NEW,
- QQmlJSGrammar::T_NULL,
- QQmlJSGrammar::T_RETURN,
- QQmlJSGrammar::T_SWITCH,
- QQmlJSGrammar::T_THIS,
- QQmlJSGrammar::T_THROW,
- QQmlJSGrammar::T_TRUE,
- QQmlJSGrammar::T_TRY,
- QQmlJSGrammar::T_TYPEOF,
- QQmlJSGrammar::T_VAR,
- QQmlJSGrammar::T_VOID,
- QQmlJSGrammar::T_WHILE,
- QQmlJSGrammar::T_CONST,
- QQmlJSGrammar::T_DEBUGGER,
- QQmlJSGrammar::T_RESERVED_WORD,
- QQmlJSGrammar::T_WITH,
-
- QQmlJSGrammar::EOF_SYMBOL
-};
-static inline bool isUriToken(int token)
-{
- const int *current = uriTokens;
- while (*current != QQmlJSGrammar::EOF_SYMBOL) {
- if (*current == token)
- return true;
- ++current;
- }
- return false;
-}
-
void Document::collectTypeReferences()
{
foreach (Object *obj, objects) {
@@ -296,198 +242,6 @@ void Document::collectTypeReferences()
}
}
-void Document::extractScriptMetaData(QString &script, QQmlJS::DiagnosticMessage *error)
-{
- Q_ASSERT(error);
-
- const QString js(QLatin1String(".js"));
- const QString library(QLatin1String("library"));
-
- QQmlJS::MemoryPool *pool = jsParserEngine.pool();
-
- QQmlJS::Lexer l(0);
- l.setCode(script, 0);
-
- int token = l.lex();
-
- while (true) {
- if (token != QQmlJSGrammar::T_DOT)
- return;
-
- int startOffset = l.tokenOffset();
- int startLine = l.tokenStartLine();
- int startColumn = l.tokenStartColumn();
-
- error->loc.startLine = startLine + 1; // 0-based, adjust to be 1-based
-
- token = l.lex();
-
- CHECK_LINE;
-
- if (token == QQmlJSGrammar::T_IMPORT) {
-
- // .import <URI> <Version> as <Identifier>
- // .import <file.js> as <Identifier>
-
- token = l.lex();
-
- CHECK_LINE;
- QV4::CompiledData::Import *import = pool->New<QV4::CompiledData::Import>();
-
- if (token == QQmlJSGrammar::T_STRING_LITERAL) {
-
- QString file = l.tokenText();
-
- if (!file.endsWith(js)) {
- error->message = QCoreApplication::translate("QQmlParser","Imported file must be a script");
- error->loc.startColumn = l.tokenStartColumn();
- return;
- }
-
- bool invalidImport = false;
-
- token = l.lex();
-
- if ((token != QQmlJSGrammar::T_AS) || (l.tokenStartLine() != startLine)) {
- invalidImport = true;
- } else {
- token = l.lex();
-
- if ((token != QQmlJSGrammar::T_IDENTIFIER) || (l.tokenStartLine() != startLine))
- invalidImport = true;
- }
-
-
- if (invalidImport) {
- error->message = QCoreApplication::translate("QQmlParser","File import requires a qualifier");
- error->loc.startColumn = l.tokenStartColumn();
- return;
- }
-
- int endOffset = l.tokenLength() + l.tokenOffset();
-
- QString importId = script.mid(l.tokenOffset(), l.tokenLength());
-
- token = l.lex();
-
- if (!importId.at(0).isUpper() || (l.tokenStartLine() == startLine)) {
- error->message = QCoreApplication::translate("QQmlParser","Invalid import qualifier");
- error->loc.startColumn = l.tokenStartColumn();
- return;
- }
-
- replaceWithSpace(script, startOffset, endOffset - startOffset);
-
- import->type = QV4::CompiledData::Import::ImportScript;
- import->uriIndex = registerString(file);
- import->qualifierIndex = registerString(importId);
- import->location.line = startLine;
- import->location.column = startColumn;
- imports << import;
- } else {
- // URI
- QString uri;
-
- while (true) {
- if (!isUriToken(token)) {
- error->message = QCoreApplication::translate("QQmlParser","Invalid module URI");
- error->loc.startColumn = l.tokenStartColumn();
- return;
- }
-
- uri.append(l.tokenText());
-
- token = l.lex();
- CHECK_LINE;
- if (token != QQmlJSGrammar::T_DOT)
- break;
-
- uri.append(QLatin1Char('.'));
-
- token = l.lex();
- CHECK_LINE;
- }
-
- if (token != QQmlJSGrammar::T_NUMERIC_LITERAL) {
- error->message = QCoreApplication::translate("QQmlParser","Module import requires a version");
- error->loc.startColumn = l.tokenStartColumn();
- return;
- }
-
- int vmaj, vmin;
- IRBuilder::extractVersion(QStringRef(&script, l.tokenOffset(), l.tokenLength()),
- &vmaj, &vmin);
-
- bool invalidImport = false;
-
- token = l.lex();
-
- if ((token != QQmlJSGrammar::T_AS) || (l.tokenStartLine() != startLine)) {
- invalidImport = true;
- } else {
- token = l.lex();
-
- if ((token != QQmlJSGrammar::T_IDENTIFIER) || (l.tokenStartLine() != startLine))
- invalidImport = true;
- }
-
-
- if (invalidImport) {
- error->message = QCoreApplication::translate("QQmlParser","Module import requires a qualifier");
- error->loc.startColumn = l.tokenStartColumn();
- return;
- }
-
- int endOffset = l.tokenLength() + l.tokenOffset();
-
- QString importId = script.mid(l.tokenOffset(), l.tokenLength());
-
- token = l.lex();
-
- if (!importId.at(0).isUpper() || (l.tokenStartLine() == startLine)) {
- error->message = QCoreApplication::translate("QQmlParser","Invalid import qualifier");
- error->loc.startColumn = l.tokenStartColumn();
- return;
- }
-
- replaceWithSpace(script, startOffset, endOffset - startOffset);
-
- import->type = QV4::CompiledData::Import::ImportLibrary;
- import->uriIndex = registerString(uri);
- import->majorVersion = vmaj;
- import->minorVersion = vmin;
- import->qualifierIndex = registerString(importId);
- import->location.line = startLine;
- import->location.column = startColumn;
- imports << import;
- }
- } else if (token == QQmlJSGrammar::T_PRAGMA) {
- token = l.lex();
-
- CHECK_TOKEN(T_IDENTIFIER);
- CHECK_LINE;
-
- QString pragmaValue = script.mid(l.tokenOffset(), l.tokenLength());
- int endOffset = l.tokenLength() + l.tokenOffset();
-
- if (pragmaValue == library) {
- unitFlags |= QV4::CompiledData::Unit::IsSharedLibrary;
- replaceWithSpace(script, startOffset, endOffset - startOffset);
- } else {
- return;
- }
-
- token = l.lex();
- if (l.tokenStartLine() == startLine)
- return;
-
- } else {
- return;
- }
- }
- return;
-}
-
void Document::removeScriptPragmas(QString &script)
{
const QString pragma(QLatin1String("pragma"));
@@ -541,6 +295,45 @@ Document::Document(bool debugMode)
{
}
+ScriptDirectivesCollector::ScriptDirectivesCollector(QQmlJS::Engine *engine, QV4::Compiler::JSUnitGenerator *unitGenerator)
+ : engine(engine)
+ , jsGenerator(unitGenerator)
+ , hasPragmaLibrary(false)
+{
+}
+
+void ScriptDirectivesCollector::pragmaLibrary()
+{
+ hasPragmaLibrary = true;
+}
+
+void ScriptDirectivesCollector::importFile(const QString &jsfile, const QString &module, int lineNumber, int column)
+{
+ QV4::CompiledData::Import *import = engine->pool()->New<QV4::CompiledData::Import>();
+ import->type = QV4::CompiledData::Import::ImportScript;
+ import->uriIndex = jsGenerator->registerString(jsfile);
+ import->qualifierIndex = jsGenerator->registerString(module);
+ import->location.line = lineNumber;
+ import->location.column = column;
+ imports << import;
+}
+
+void ScriptDirectivesCollector::importModule(const QString &uri, const QString &version, const QString &module, int lineNumber, int column)
+{
+ QV4::CompiledData::Import *import = engine->pool()->New<QV4::CompiledData::Import>();
+ import->type = QV4::CompiledData::Import::ImportLibrary;
+ import->uriIndex = jsGenerator->registerString(uri);
+ int vmaj;
+ int vmin;
+ IRBuilder::extractVersion(QStringRef(&version), &vmaj, &vmin);
+ import->majorVersion = vmaj;
+ import->minorVersion = vmin;
+ import->qualifierIndex = jsGenerator->registerString(module);
+ import->location.line = lineNumber;
+ import->location.column = column;
+ imports << import;
+}
+
IRBuilder::IRBuilder(const QSet<QString> &illegalNames)
: illegalNames(illegalNames)
, _object(0)
@@ -1780,8 +1573,6 @@ QQmlPropertyData *JSCodeGen::lookupQmlCompliantProperty(QQmlPropertyCache *cache
return pd;
}
-static void initMetaObjectResolver(QV4::IR::MemberExpressionResolver *resolver, QQmlPropertyCache *metaObject);
-
enum MetaObjectResolverFlags {
AllPropertiesAreFinal = 0x1,
LookupsIncludeEnums = 0x2,
@@ -1837,6 +1628,8 @@ static QV4::IR::Type resolveQmlType(QQmlEnginePrivate *qmlEngine, QV4::IR::Membe
static void initQmlTypeResolver(QV4::IR::MemberExpressionResolver *resolver, QQmlType *qmlType)
{
+ Q_ASSERT(resolver);
+
resolver->resolveMember = &resolveQmlType;
resolver->data = qmlType;
resolver->extraData = 0;
@@ -1941,8 +1734,8 @@ static QV4::IR::Type resolveMetaObjectProperty(QQmlEnginePrivate *qmlEngine, QV4
initMetaObjectResolver(resolver, cache);
return QV4::IR::QObjectType;
}
- } else if (QQmlValueType *valueType = QQmlValueTypeFactory::valueType(property->propType)) {
- if (QQmlPropertyCache *cache = qmlEngine->cache(valueType->metaObject())) {
+ } else if (const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(property->propType)) {
+ if (QQmlPropertyCache *cache = qmlEngine->cache(valueTypeMetaObject)) {
initMetaObjectResolver(resolver, cache);
resolver->flags |= ResolveTypeInformationOnly;
return QV4::IR::QObjectType;
@@ -1958,10 +1751,11 @@ static QV4::IR::Type resolveMetaObjectProperty(QQmlEnginePrivate *qmlEngine, QV4
static void initMetaObjectResolver(QV4::IR::MemberExpressionResolver *resolver, QQmlPropertyCache *metaObject)
{
+ Q_ASSERT(resolver);
+
resolver->resolveMember = &resolveMetaObjectProperty;
resolver->data = metaObject;
resolver->flags = 0;
- resolver->isQObjectResolver = true;
}
#endif // V4_BOOTSTRAP
@@ -1975,11 +1769,13 @@ void JSCodeGen::beginFunctionBodyHook()
#ifndef V4_BOOTSTRAP
QV4::IR::Temp *temp = _block->TEMP(_contextObjectTemp);
- initMetaObjectResolver(&temp->memberResolver, _contextObject);
+ temp->memberResolver = _function->New<QV4::IR::MemberExpressionResolver>();
+ initMetaObjectResolver(temp->memberResolver, _contextObject);
move(temp, _block->NAME(QV4::IR::Name::builtin_qml_context_object, 0, 0));
temp = _block->TEMP(_scopeObjectTemp);
- initMetaObjectResolver(&temp->memberResolver, _scopeObject);
+ temp->memberResolver = _function->New<QV4::IR::MemberExpressionResolver>();
+ initMetaObjectResolver(temp->memberResolver, _scopeObject);
move(temp, _block->NAME(QV4::IR::Name::builtin_qml_scope_object, 0, 0));
move(_block->TEMP(_importedScriptsTemp), _block->NAME(QV4::IR::Name::builtin_qml_imported_scripts_object, 0, 0));
@@ -2014,8 +1810,9 @@ QV4::IR::Expr *JSCodeGen::fallbackNameLookup(const QString &name, int line, int
_block->MOVE(result, s);
result = _block->TEMP(result->index);
if (mapping.type) {
- initMetaObjectResolver(&result->memberResolver, mapping.type);
- result->memberResolver.flags |= AllPropertiesAreFinal;
+ result->memberResolver = _function->New<QV4::IR::MemberExpressionResolver>();
+ initMetaObjectResolver(result->memberResolver, mapping.type);
+ result->memberResolver->flags |= AllPropertiesAreFinal;
}
result->isReadOnly = true; // don't allow use as lvalue
return result;
@@ -2035,14 +1832,16 @@ QV4::IR::Expr *JSCodeGen::fallbackNameLookup(const QString &name, int line, int
_block->MOVE(result, typeName);
result = _block->TEMP(result->index);
- initQmlTypeResolver(&result->memberResolver, r.type);
+ result->memberResolver = _function->New<QV4::IR::MemberExpressionResolver>();
+ initQmlTypeResolver(result->memberResolver, r.type);
return result;
} else {
Q_ASSERT(r.importNamespace);
QV4::IR::Name *namespaceName = _block->NAME(name, line, col);
namespaceName->freeOfSideEffects = true;
QV4::IR::Temp *result = _block->TEMP(_block->newTemp());
- initImportNamespaceResolver(&result->memberResolver, imports, r.importNamespace);
+ result->memberResolver = _function->New<QV4::IR::MemberExpressionResolver>();
+ initImportNamespaceResolver(result->memberResolver, imports, r.importNamespace);
_block->MOVE(result, namespaceName);
return _block->TEMP(result->index);
@@ -2057,7 +1856,8 @@ QV4::IR::Expr *JSCodeGen::fallbackNameLookup(const QString &name, int line, int
return 0;
if (pd) {
QV4::IR::Temp *base = _block->TEMP(_scopeObjectTemp);
- initMetaObjectResolver(&base->memberResolver, _scopeObject);
+ base->memberResolver = _function->New<QV4::IR::MemberExpressionResolver>();
+ initMetaObjectResolver(base->memberResolver, _scopeObject);
return _block->MEMBER(base, _function->newString(name), pd, QV4::IR::Member::MemberOfQmlScopeObject);
}
}
@@ -2069,7 +1869,8 @@ QV4::IR::Expr *JSCodeGen::fallbackNameLookup(const QString &name, int line, int
return 0;
if (pd) {
QV4::IR::Temp *base = _block->TEMP(_contextObjectTemp);
- initMetaObjectResolver(&base->memberResolver, _contextObject);
+ base->memberResolver = _function->New<QV4::IR::MemberExpressionResolver>();
+ initMetaObjectResolver(base->memberResolver, _contextObject);
return _block->MEMBER(base, _function->newString(name), pd, QV4::IR::Member::MemberOfQmlContextObject);
}
}
diff --git a/src/qml/compiler/qqmlirbuilder_p.h b/src/qml/compiler/qqmlirbuilder_p.h
index cc22023f8e..6177b96878 100644
--- a/src/qml/compiler/qqmlirbuilder_p.h
+++ b/src/qml/compiler/qqmlirbuilder_p.h
@@ -41,6 +41,7 @@
#include <private/qqmljsmemorypool_p.h>
#include <private/qv4codegen_p.h>
#include <private/qv4compiler_p.h>
+#include <private/qqmljslexer_p.h>
#include <QTextStream>
#include <QCoreApplication>
@@ -326,10 +327,23 @@ struct Q_QML_PRIVATE_EXPORT Document
int registerString(const QString &str) { return jsGenerator.registerString(str); }
QString stringAt(int index) const { return jsGenerator.stringForIndex(index); }
- void extractScriptMetaData(QString &script, QQmlJS::DiagnosticMessage *error);
static void removeScriptPragmas(QString &script);
};
+struct Q_QML_PRIVATE_EXPORT ScriptDirectivesCollector : public QQmlJS::Directives
+{
+ ScriptDirectivesCollector(QQmlJS::Engine *engine, QV4::Compiler::JSUnitGenerator *unitGenerator);
+
+ QQmlJS::Engine *engine;
+ QV4::Compiler::JSUnitGenerator *jsGenerator;
+ QList<const QV4::CompiledData::Import *> imports;
+ bool hasPragmaLibrary;
+
+ virtual void pragmaLibrary();
+ virtual void importFile(const QString &jsfile, const QString &module, int lineNumber, int column);
+ virtual void importModule(const QString &uri, const QString &version, const QString &module, int lineNumber, int column);
+};
+
struct Q_QML_PRIVATE_EXPORT IRBuilder : public QQmlJS::AST::Visitor
{
Q_DECLARE_TR_FUNCTIONS(QQmlCodeGenerator)
diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp
index 2c7414db14..84e6c76cc4 100644
--- a/src/qml/compiler/qqmltypecompiler.cpp
+++ b/src/qml/compiler/qqmltypecompiler.cpp
@@ -463,8 +463,8 @@ bool QQmlPropertyCacheCreator::buildMetaObjectRecursively(int objectIndex, int r
if (instantiatingProperty->isQObject()) {
baseTypeCache = enginePrivate->rawPropertyCacheForType(instantiatingProperty->propType);
Q_ASSERT(baseTypeCache);
- } else if (QQmlValueType *vt = QQmlValueTypeFactory::valueType(instantiatingProperty->propType)) {
- baseTypeCache = enginePrivate->cache(vt->metaObject());
+ } else if (const QMetaObject *vtmo = QQmlValueTypeFactory::metaObjectForMetaType(instantiatingProperty->propType)) {
+ baseTypeCache = enginePrivate->cache(vtmo);
Q_ASSERT(baseTypeCache);
}
}
@@ -559,8 +559,7 @@ bool QQmlPropertyCacheCreator::ensureMetaObject(int objectIndex)
bool QQmlPropertyCacheCreator::createMetaObject(int objectIndex, const QmlIR::Object *obj, QQmlPropertyCache *baseTypeCache)
{
- QQmlPropertyCache *cache = baseTypeCache->copyAndReserve(QQmlEnginePrivate::get(enginePrivate),
- obj->propertyCount(),
+ QQmlPropertyCache *cache = baseTypeCache->copyAndReserve(obj->propertyCount(),
obj->functionCount() + obj->propertyCount() + obj->signalCount(),
obj->signalCount() + obj->propertyCount());
propertyCaches[objectIndex] = cache;
@@ -1630,8 +1629,8 @@ bool QQmlComponentAndAliasResolver::resolveAliases()
notifySignal = targetProperty->notifyIndex;
if (!subProperty.isEmpty()) {
- QQmlValueType *valueType = QQmlValueTypeFactory::valueType(type);
- if (!valueType) {
+ const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(type);
+ if (!valueTypeMetaObject) {
recordError(p->aliasLocation, tr("Invalid alias location"));
return false;
}
@@ -1639,18 +1638,18 @@ bool QQmlComponentAndAliasResolver::resolveAliases()
propType = type;
int valueTypeIndex =
- valueType->metaObject()->indexOfProperty(subProperty.toString().toUtf8().constData());
+ valueTypeMetaObject->indexOfProperty(subProperty.toString().toUtf8().constData());
if (valueTypeIndex == -1) {
recordError(p->aliasLocation, tr("Invalid alias location"));
return false;
}
Q_ASSERT(valueTypeIndex <= 0x0000FFFF);
- propIdx |= (valueTypeIndex << 16);
- if (valueType->metaObject()->property(valueTypeIndex).isEnumType())
+ propIdx = QQmlPropertyData::encodeValueTypePropertyIndex(propIdx, valueTypeIndex);
+ if (valueTypeMetaObject->property(valueTypeIndex).isEnumType())
type = QVariant::Int;
else
- type = valueType->metaObject()->property(valueTypeIndex).userType();
+ type = valueTypeMetaObject->property(valueTypeIndex).userType();
} else {
if (targetProperty->isEnum()) {
@@ -1887,7 +1886,7 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD
if (binding->type >= QV4::CompiledData::Binding::Type_Object && !customParser) {
qSwap(_seenObjectWithId, seenSubObjectWithId);
- const bool subObjectValid = validateObject(binding->value.objectIndex, binding, pd && QQmlValueTypeFactory::valueType(pd->propType));
+ const bool subObjectValid = validateObject(binding->value.objectIndex, binding, pd && QQmlValueTypeFactory::metaObjectForMetaType(pd->propType));
qSwap(_seenObjectWithId, seenSubObjectWithId);
if (!subObjectValid)
return false;
@@ -1961,7 +1960,7 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD
return false;
} else if (binding->isGroupProperty()) {
if (QQmlValueTypeFactory::isValueType(pd->propType)) {
- if (QQmlValueTypeFactory::valueType(pd->propType)) {
+ if (QQmlValueTypeFactory::metaObjectForMetaType(pd->propType)) {
if (!pd->isWritable()) {
recordError(binding->location, tr("Invalid property assignment: \"%1\" is a read-only property").arg(name));
return false;
@@ -2347,7 +2346,7 @@ bool QQmlPropertyValidator::validateObjectBinding(QQmlPropertyData *property, co
if (!QQmlMetaType::isInterface(listType)) {
QQmlPropertyCache *source = propertyCaches.at(binding->value.objectIndex);
if (!canCoerce(listType, source)) {
- recordError(binding->valueLocation, tr("Cannot assign object to list"));
+ recordError(binding->valueLocation, tr("Cannot assign object to list property \"%1\"").arg(propertyName));
return false;
}
}
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index a7b5326861..ba4c450aae 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -2841,6 +2841,11 @@ QList<QQmlJS::DiagnosticMessage> Codegen::errors() const
QList<QQmlError> Codegen::qmlErrors() const
{
QList<QQmlError> qmlErrors;
+
+ // Short circuit to avoid costly (de)heap allocation of QUrl if there are no errors.
+ if (_errors.size() == 0)
+ return qmlErrors;
+
qmlErrors.reserve(_errors.size());
QUrl url(_fileNameIsUrl ? QUrl(_module->fileName) : QUrl::fromLocalFile(_module->fileName));
@@ -2861,7 +2866,7 @@ void RuntimeCodegen::throwSyntaxError(const AST::SourceLocation &loc, const QStr
if (hasError)
return;
hasError = true;
- context->throwSyntaxError(detail, _module->fileName, loc.startLine, loc.startColumn);
+ engine->throwSyntaxError(detail, _module->fileName, loc.startLine, loc.startColumn);
}
void RuntimeCodegen::throwReferenceError(const AST::SourceLocation &loc, const QString &detail)
@@ -2869,7 +2874,7 @@ void RuntimeCodegen::throwReferenceError(const AST::SourceLocation &loc, const Q
if (hasError)
return;
hasError = true;
- context->throwReferenceError(detail, _module->fileName, loc.startLine, loc.startColumn);
+ engine->throwReferenceError(detail, _module->fileName, loc.startLine, loc.startColumn);
}
#endif // V4_BOOTSTRAP
diff --git a/src/qml/compiler/qv4codegen_p.h b/src/qml/compiler/qv4codegen_p.h
index 323cd27aa9..8f528df7a1 100644
--- a/src/qml/compiler/qv4codegen_p.h
+++ b/src/qml/compiler/qv4codegen_p.h
@@ -47,10 +47,6 @@
QT_BEGIN_NAMESPACE
-namespace QV4 {
-struct ExecutionContext;
-}
-
namespace QQmlJS {
namespace AST {
class UiParameterList;
@@ -526,15 +522,15 @@ protected:
class RuntimeCodegen : public Codegen
{
public:
- RuntimeCodegen(QV4::ExecutionContext *ctx, bool strict)
+ RuntimeCodegen(QV4::ExecutionEngine *engine, bool strict)
: Codegen(strict)
- , context(ctx)
+ , engine(engine)
{}
virtual void throwSyntaxError(const AST::SourceLocation &loc, const QString &detail);
virtual void throwReferenceError(const AST::SourceLocation &loc, const QString &detail);
private:
- QV4::ExecutionContext *context;
+ QV4::ExecutionEngine *engine;
};
#endif // V4_BOOTSTRAP
diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp
index d242fb7b3a..65a14a302a 100644
--- a/src/qml/compiler/qv4compileddata.cpp
+++ b/src/qml/compiler/qv4compileddata.cpp
@@ -65,9 +65,9 @@ QV4::Function *CompilationUnit::linkToEngine(ExecutionEngine *engine)
Q_ASSERT(!runtimeStrings);
Q_ASSERT(data);
- runtimeStrings = (QV4::StringValue *)malloc(data->stringTableSize * sizeof(QV4::StringValue));
+ runtimeStrings = (QV4::Heap::String **)malloc(data->stringTableSize * sizeof(QV4::Heap::String*));
// memset the strings to 0 in case a GC run happens while we're within the loop below
- memset(runtimeStrings, 0, data->stringTableSize * sizeof(QV4::StringValue));
+ memset(runtimeStrings, 0, data->stringTableSize * sizeof(QV4::Heap::String*));
for (uint i = 0; i < data->stringTableSize; ++i)
runtimeStrings[i] = engine->newIdentifier(data->stringAt(i));
@@ -109,7 +109,7 @@ QV4::Function *CompilationUnit::linkToEngine(ExecutionEngine *engine)
l->classList[j] = 0;
l->level = -1;
l->index = UINT_MAX;
- l->name = runtimeStrings[compiledLookups[i].nameIndex].asString();
+ l->nameIndex = compiledLookups[i].nameIndex;
if (type == CompiledData::Lookup::Type_IndexedGetter || type == CompiledData::Lookup::Type_IndexedSetter)
l->engine = engine;
}
@@ -117,13 +117,12 @@ QV4::Function *CompilationUnit::linkToEngine(ExecutionEngine *engine)
if (data->jsClassTableSize) {
runtimeClasses = (QV4::InternalClass**)malloc(data->jsClassTableSize * sizeof(QV4::InternalClass*));
-
for (uint i = 0; i < data->jsClassTableSize; ++i) {
int memberCount = 0;
const CompiledData::JSClassMember *member = data->jsClassAt(i, &memberCount);
QV4::InternalClass *klass = engine->objectClass;
for (int j = 0; j < memberCount; ++j, ++member)
- klass = klass->addMember(runtimeStrings[member->nameOffset].asString(), member->isAccessor ? QV4::Attr_Accessor : QV4::Attr_Data);
+ klass = klass->addMember(runtimeStrings[member->nameOffset]->identifier, member->isAccessor ? QV4::Attr_Accessor : QV4::Attr_Data);
runtimeClasses[i] = klass;
}
@@ -166,15 +165,12 @@ void CompilationUnit::unlink()
void CompilationUnit::markObjects(QV4::ExecutionEngine *e)
{
for (uint i = 0; i < data->stringTableSize; ++i)
- runtimeStrings[i].mark(e);
+ if (runtimeStrings[i])
+ runtimeStrings[i]->mark(e);
if (runtimeRegularExpressions) {
for (uint i = 0; i < data->regexpTableSize; ++i)
runtimeRegularExpressions[i].mark(e);
}
- if (runtimeLookups) {
- for (uint i = 0; i < data->lookupTableSize; ++i)
- runtimeLookups[i].name->mark(e);
- }
}
#endif // V4_BOOTSTRAP
diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h
index 6791970461..30e7795bb3 100644
--- a/src/qml/compiler/qv4compileddata_p.h
+++ b/src/qml/compiler/qv4compileddata_p.h
@@ -37,9 +37,12 @@
#include <QVector>
#include <QStringList>
#include <QHash>
+#include <QUrl>
+
#include <private/qv4value_p.h>
#include <private/qv4executableallocator_p.h>
#include <private/qqmlrefcount_p.h>
+#include <private/qqmlnullablevalue_p_p.h>
QT_BEGIN_NAMESPACE
@@ -53,7 +56,6 @@ struct Function;
}
struct Function;
-struct ExecutionContext;
namespace CompiledData {
@@ -587,12 +589,14 @@ struct Q_QML_PRIVATE_EXPORT CompilationUnit : public QQmlRefCount
#ifndef V4_BOOTSTRAP
ExecutionEngine *engine;
QString fileName() const { return data->stringAt(data->sourceFileIndex); }
+ QUrl url() const { if (m_url.isNull) m_url = QUrl(fileName()); return m_url; }
- QV4::StringValue *runtimeStrings; // Array
+ QV4::Heap::String **runtimeStrings; // Array
QV4::Lookup *runtimeLookups;
QV4::Value *runtimeRegularExpressions;
QV4::InternalClass **runtimeClasses;
QVector<QV4::Function *> runtimeFunctions;
+ mutable QQmlNullableValue<QUrl> m_url;
QV4::Function *linkToEngine(QV4::ExecutionEngine *engine);
void unlink();
diff --git a/src/qml/compiler/qv4isel_moth.cpp b/src/qml/compiler/qv4isel_moth.cpp
index 39977375c4..8f411bfbc6 100644
--- a/src/qml/compiler/qv4isel_moth.cpp
+++ b/src/qml/compiler/qv4isel_moth.cpp
@@ -188,15 +188,9 @@ public:
void forFunction(IR::Function *function)
{
- IR::Optimizer::showMeTheCode(function);
+ IR::Optimizer::showMeTheCode(function, "Before stack slot allocation");
_function = function;
toStackSlots(function);
-
-// QTextStream os(stdout, QIODevice::WriteOnly);
-// os << "Frame layout:" << endl;
-// foreach (int t, _stackSlotForTemp.keys()) {
-// os << "\t" << t << " -> " << _stackSlotForTemp[t] << endl;
-// }
}
protected:
@@ -364,7 +358,7 @@ void InstructionSelection::run(int functionIndex)
opt.convertOutOfSSA();
ConvertTemps().toStackSlots(_function);
}
- opt.showMeTheCode(_function);
+ opt.showMeTheCode(_function, "After stack slot allocation");
} else {
ConvertTemps().toStackSlots(_function);
}
diff --git a/src/qml/compiler/qv4isel_p.cpp b/src/qml/compiler/qv4isel_p.cpp
index e419084238..167ea8337c 100644
--- a/src/qml/compiler/qv4isel_p.cpp
+++ b/src/qml/compiler/qv4isel_p.cpp
@@ -31,6 +31,8 @@
**
****************************************************************************/
+#include <QtCore/QDebug>
+#include <QtCore/QBuffer>
#include "qv4jsir_p.h"
#include "qv4isel_p.h"
#include "qv4isel_util_p.h"
@@ -41,11 +43,6 @@
#include <QString>
-namespace {
-Q_GLOBAL_STATIC_WITH_ARGS(QTextStream, qout, (stderr, QIODevice::WriteOnly));
-#define qout *qout()
-} // anonymous namespace
-
using namespace QV4;
using namespace QV4::IR;
@@ -218,8 +215,12 @@ void IRDecoder::visitMove(IR::Move *s)
// For anything else...:
Q_UNIMPLEMENTED();
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream qout(&buf);
IRPrinter(&qout).print(s);
qout << endl;
+ qDebug("%s", buf.data().constData());
Q_ASSERT(!"TODO");
}
@@ -398,7 +399,10 @@ void IRDecoder::callBuiltin(IR::Call *call, Expr *result)
}
Q_UNIMPLEMENTED();
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream qout(&buf);
IRPrinter(&qout).print(call); qout << endl;
- Q_ASSERT(!"TODO!");
+ qDebug("%s", buf.data().constData());
Q_UNREACHABLE();
}
diff --git a/src/qml/compiler/qv4jsir.cpp b/src/qml/compiler/qv4jsir.cpp
index e23ca1d516..fbfcf31aa0 100644
--- a/src/qml/compiler/qv4jsir.cpp
+++ b/src/qml/compiler/qv4jsir.cpp
@@ -44,6 +44,8 @@
#include <QtCore/qset.h>
#include <cmath>
+#include <vector>
+
#ifdef CONST
#undef CONST
#endif
@@ -152,7 +154,7 @@ AluOp binaryOperator(int op)
struct RemoveSharedExpressions: IR::StmtVisitor, IR::ExprVisitor
{
CloneExpr clone;
- QSet<Expr *> subexpressions; // contains all the non-cloned subexpressions in the given function
+ std::vector<Expr *> subexpressions; // contains all the non-cloned subexpressions in the given function. sorted using std::lower_bound.
Expr *uniqueExpr;
RemoveSharedExpressions(): uniqueExpr(0) {}
@@ -176,18 +178,19 @@ struct RemoveSharedExpressions: IR::StmtVisitor, IR::ExprVisitor
template <typename _Expr>
_Expr *cleanup(_Expr *expr)
{
- if (subexpressions.contains(expr)) {
- // the cloned expression is unique by definition
- // so we don't need to add it to `subexpressions'.
- return clone(expr);
+ std::vector<Expr *>::iterator it = std::lower_bound(subexpressions.begin(), subexpressions.end(), expr);
+ if (it == subexpressions.end() || *it != expr) {
+ subexpressions.insert(it, expr);
+ IR::Expr *e = expr;
+ qSwap(uniqueExpr, e);
+ expr->accept(this);
+ qSwap(uniqueExpr, e);
+ return static_cast<_Expr *>(e);
}
- subexpressions.insert(expr);
- IR::Expr *e = expr;
- qSwap(uniqueExpr, e);
- expr->accept(this);
- qSwap(uniqueExpr, e);
- return static_cast<_Expr *>(e);
+ // the cloned expression is unique by definition
+ // so we don't need to add it to `subexpressions'.
+ return clone(expr);
}
// statements
diff --git a/src/qml/compiler/qv4jsir_p.h b/src/qml/compiler/qv4jsir_p.h
index 66528e8bc1..c6a192e14a 100644
--- a/src/qml/compiler/qv4jsir_p.h
+++ b/src/qml/compiler/qv4jsir_p.h
@@ -70,10 +70,6 @@ class QQmlPropertyCache;
class QQmlEnginePrivate;
namespace QV4 {
-struct ExecutionContext;
-}
-
-namespace QV4 {
inline bool isNegative(double d)
{
@@ -230,7 +226,7 @@ struct MemberExpressionResolver
typedef Type (*ResolveFunction)(QQmlEnginePrivate *engine, MemberExpressionResolver *resolver, Member *member);
MemberExpressionResolver()
- : resolveMember(0), data(0), extraData(0), flags(0), isQObjectResolver(false) {}
+ : resolveMember(0), data(0), extraData(0), flags(0) {}
bool isValid() const { return !!resolveMember; }
void clear() { *this = MemberExpressionResolver(); }
@@ -238,8 +234,7 @@ struct MemberExpressionResolver
ResolveFunction resolveMember;
void *data; // Could be pointer to meta object, importNameSpace, etc. - depends on resolveMember implementation
void *extraData; // Could be QQmlTypeNameCache
- unsigned int flags : 31;
- unsigned int isQObjectResolver; // neede for IR dump helpers
+ unsigned int flags;
};
struct Q_AUTOTEST_EXPORT Expr {
@@ -373,23 +368,25 @@ struct Q_AUTOTEST_EXPORT Temp: Expr {
StackSlot
};
+ // Used when temp is used as base in member expression
+ MemberExpressionResolver *memberResolver;
+
unsigned index : 28;
- unsigned kind : 3;
unsigned isReadOnly : 1;
- // Used when temp is used as base in member expression
- MemberExpressionResolver memberResolver;
+ unsigned kind : 3;
Temp()
- : index((1 << 28) - 1)
- , kind(Invalid)
+ : memberResolver(0)
+ , index((1 << 28) - 1)
, isReadOnly(0)
+ , kind(Invalid)
{}
void init(unsigned kind, unsigned index)
{
- this->kind = kind;
this->index = index;
this->isReadOnly = false;
+ this->kind = kind;
}
bool isInvalid() const { return kind == Invalid; }
diff --git a/src/qml/compiler/qv4ssa.cpp b/src/qml/compiler/qv4ssa.cpp
index 5861138dbe..c0a14a5c80 100644
--- a/src/qml/compiler/qv4ssa.cpp
+++ b/src/qml/compiler/qv4ssa.cpp
@@ -40,6 +40,7 @@
#include "qv4isel_util_p.h"
#include "qv4util_p.h"
+#include <QtCore/QBuffer>
#include <QtCore/QCoreApplication>
#include <QtCore/QStringList>
#include <QtCore/QSet>
@@ -51,9 +52,6 @@
#include <cassert>
#include <algorithm>
-#undef SHOW_SSA
-#undef DEBUG_MOVEMAPPING
-
QT_USE_NAMESPACE
using namespace QV4;
@@ -61,21 +59,25 @@ using namespace IR;
namespace {
+enum { DebugMoveMapping = 0 };
+
#ifdef QT_NO_DEBUG
enum { DoVerification = 0 };
#else
enum { DoVerification = 1 };
#endif
-Q_GLOBAL_STATIC_WITH_ARGS(QTextStream, qout, (stderr, QIODevice::WriteOnly));
-#define qout *qout()
-
-void showMeTheCode(IR::Function *function)
+static void showMeTheCode(IR::Function *function, const char *marker)
{
static bool showCode = !qgetenv("QV4_SHOW_IR").isNull();
if (showCode) {
- IRPrinter(&qout).print(function);
- qout << endl;
+ qDebug() << marker;
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream stream(&buf);
+ IRPrinter(&stream).print(function);
+ stream << endl;
+ qDebug("%s", buf.data().constData());
}
}
@@ -104,10 +106,9 @@ public:
class BasicBlockSet
{
- typedef std::vector<int> Numbers;
typedef std::vector<bool> Flags;
- Numbers *blockNumbers;
+ QVarLengthArray<int, 8> blockNumbers;
Flags *blockFlags;
IR::Function *function;
enum { MaxVectorCapacity = 8 };
@@ -117,7 +118,7 @@ public:
{
const BasicBlockSet &set;
// ### These two members could go into a union, but clang won't compile (https://codereview.qt-project.org/#change,74259)
- Numbers::const_iterator numberIt;
+ QVarLengthArray<int, 8>::const_iterator numberIt;
size_t flagIt;
friend class BasicBlockSet;
@@ -125,13 +126,13 @@ public:
: set(set)
{
if (end || !set.function) {
- if (set.blockNumbers)
- numberIt = set.blockNumbers->end();
+ if (!set.blockFlags)
+ numberIt = set.blockNumbers.end();
else
flagIt = set.blockFlags->size();
} else {
- if (set.blockNumbers)
- numberIt = set.blockNumbers->begin();
+ if (!set.blockFlags)
+ numberIt = set.blockNumbers.begin();
else
findNextWithFlags(0);
}
@@ -161,8 +162,7 @@ public:
public:
BasicBlock *operator*() const
{
-
- if (set.blockNumbers) {
+ if (!set.blockFlags) {
return set.function->basicBlock(*numberIt);
} else {
Q_ASSERT(flagIt <= static_cast<size_t>(set.function->basicBlockCount()));
@@ -174,7 +174,7 @@ public:
{
if (&set != &other.set)
return false;
- if (set.blockNumbers)
+ if (!set.blockFlags)
return numberIt == other.numberIt;
else
return flagIt == other.flagIt;
@@ -185,7 +185,7 @@ public:
const_iterator &operator++()
{
- if (set.blockNumbers)
+ if (!set.blockFlags)
++numberIt;
else
findNextWithFlags(flagIt + 1);
@@ -197,14 +197,14 @@ public:
friend class const_iterator;
public:
- BasicBlockSet(IR::Function *f = 0): blockNumbers(0), blockFlags(0), function(0)
+ BasicBlockSet(IR::Function *f = 0): blockFlags(0), function(0)
{
if (f)
init(f);
}
#ifdef Q_COMPILER_RVALUE_REFS
- BasicBlockSet(BasicBlockSet &&other): blockNumbers(0), blockFlags(0)
+ BasicBlockSet(BasicBlockSet &&other): blockFlags(0)
{
std::swap(blockNumbers, other.blockNumbers);
std::swap(blockFlags, other.blockFlags);
@@ -213,14 +213,12 @@ public:
#endif // Q_COMPILER_RVALUE_REFS
BasicBlockSet(const BasicBlockSet &other)
- : blockNumbers(0)
- , blockFlags(0)
+ : blockFlags(0)
, function(other.function)
{
if (other.blockFlags)
blockFlags = new Flags(*other.blockFlags);
- else if (other.blockNumbers)
- blockNumbers = new Numbers(*other.blockNumbers);
+ blockNumbers = other.blockNumbers;
}
BasicBlockSet &operator=(const BasicBlockSet &other)
@@ -228,27 +226,24 @@ public:
if (blockFlags) {
delete blockFlags;
blockFlags = 0;
- } else {
- delete blockNumbers;
- blockNumbers = 0;
}
function = other.function;
if (other.blockFlags)
blockFlags = new Flags(*other.blockFlags);
- else if (other.blockNumbers)
- blockNumbers = new Numbers(*other.blockNumbers);
+ blockNumbers = other.blockNumbers;
return *this;
}
- ~BasicBlockSet() { delete blockNumbers; delete blockFlags; }
+ ~BasicBlockSet()
+ {
+ delete blockFlags;
+ }
void init(IR::Function *f)
{
Q_ASSERT(!function);
Q_ASSERT(f);
function = f;
- blockNumbers = new Numbers;
- blockNumbers->reserve(MaxVectorCapacity);
}
bool empty() const
@@ -265,21 +260,20 @@ public:
return;
}
- for (std::vector<int>::const_iterator i = blockNumbers->begin(), ei = blockNumbers->end();
- i != ei; ++i)
- if (*i == bb->index())
+ for (int i = 0; i < blockNumbers.size(); ++i) {
+ if (blockNumbers[i] == bb->index())
return;
+ }
- if (blockNumbers->size() == MaxVectorCapacity) {
+ if (blockNumbers.size() == MaxVectorCapacity) {
blockFlags = new Flags(function->basicBlockCount(), false);
- for (std::vector<int>::const_iterator i = blockNumbers->begin(), ei = blockNumbers->end();
- i != ei; ++i)
- blockFlags->operator[](*i) = true;
- delete blockNumbers;
- blockNumbers = 0;
+ for (int i = 0; i < blockNumbers.size(); ++i) {
+ blockFlags->operator[](blockNumbers[i]) = true;
+ }
+ blockNumbers.clear();
blockFlags->operator[](bb->index()) = true;
} else {
- blockNumbers->push_back(bb->index());
+ blockNumbers.append(bb->index());
}
}
@@ -292,9 +286,9 @@ public:
return;
}
- for (std::vector<int>::iterator i = blockNumbers->begin(), ei = blockNumbers->end(); i != ei; ++i) {
- if (*i == bb->index()) {
- blockNumbers->erase(i);
+ for (int i = 0; i < blockNumbers.size(); ++i) {
+ if (blockNumbers[i] == bb->index()) {
+ blockNumbers.remove(i);
return;
}
}
@@ -318,8 +312,8 @@ public:
if (blockFlags)
return (*blockFlags)[bb->index()];
- for (std::vector<int>::const_iterator i = blockNumbers->begin(), ei = blockNumbers->end(); i != ei; ++i) {
- if (*i == bb->index())
+ for (int i = 0; i < blockNumbers.size(); ++i) {
+ if (blockNumbers[i] == bb->index())
return true;
}
@@ -402,11 +396,6 @@ class DominatorTree
todo = worklist.back();
worklist.pop_back();
}
-
-#if defined(SHOW_SSA)
- for (int i = 0; i < nodes.size(); ++i)
- qDebug("\tL%d: dfnum = %d, parent = %d", i, dfnum[i], parent[i]);
-#endif // SHOW_SSA
}
BasicBlockIndex ancestorWithLowestSemi(BasicBlockIndex v, std::vector<BasicBlockIndex> &worklist) {
@@ -592,6 +581,9 @@ public:
}
if (DebugDominatorFrontiers) {
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream qout(&buf);
qout << "Dominator Frontiers:" << endl;
foreach (BasicBlock *n, function->basicBlocks()) {
if (n->isRemoved())
@@ -606,6 +598,7 @@ public:
}
qout << "}" << endl;
}
+ qDebug("%s", buf.data().constData());
}
if (DebugDominatorFrontiers && DebugCodeCanUseLotsOfCpu) {
@@ -624,7 +617,7 @@ public:
}
}
if (!hasDominatedSucc) {
- qout << fBlock << " in DF[" << n->index() << "] has no dominated predecessors" << endl;
+ qDebug("%d in DF[%d] has no dominated predecessors", fBlock->index(), n->index());
}
Q_ASSERT(hasDominatedSucc);
}
@@ -646,6 +639,9 @@ public:
void dumpImmediateDominators() const
{
if (DebugImmediateDominators) {
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream qout(&buf);
qout << "Immediate dominators:" << endl;
foreach (BasicBlock *to, function->basicBlocks()) {
if (to->isRemoved())
@@ -659,6 +655,7 @@ public:
qout << "(none)";
qout << " -> " << to->index() << endl;
}
+ qDebug("%s", buf.data().constData());
}
}
@@ -953,10 +950,6 @@ public:
for (int i = 0, ei = A_orig.size(); i != ei; ++i)
A_orig[i].reserve(8);
-#if defined(SHOW_SSA)
- qout << "Variables collected:" << endl;
-#endif // SHOW_SSA
-
foreach (BasicBlock *bb, function->basicBlocks()) {
if (bb->isRemoved())
continue;
@@ -966,17 +959,6 @@ public:
foreach (Stmt *s, bb->statements())
s->accept(this);
}
-
-#if defined(SHOW_SSA)
- qout << "Non-locals:" << endl;
- foreach (const Temp &nonLocal, nonLocals) {
- qout << "\t";
- nonLocal.dump(qout);
- qout << endl;
- }
-
- qout << "end collected variables." << endl;
-#endif // SHOW_SSA
}
const std::vector<Temp> &allTemps() const
@@ -1038,12 +1020,6 @@ protected:
addTemp(t);
if (isCollectable(t)) {
-#if defined(SHOW_SSA)
- qout << '\t';
- t->dump(qout);
- qout << " -> L" << currentBB->index << endl;
-#endif // SHOW_SSA
-
_defsites[t->index].insert(currentBB);
addDefInCurrentBlock(t);
@@ -1161,9 +1137,10 @@ public:
defUse.blockOfStatement = defBlock;
}
- QList<UntypedTemp> defsUntyped() const
+ QVector<UntypedTemp> defsUntyped() const
{
- QList<UntypedTemp> res;
+ QVector<UntypedTemp> res;
+ res.reserve(tempCount());
foreach (const DefUse &du, _defUses)
if (du.isValid())
res.append(UntypedTemp(du.temp));
@@ -1274,6 +1251,9 @@ public:
void dump() const
{
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream qout(&buf);
qout << "Defines and uses:" << endl;
foreach (const DefUse &du, _defUses) {
if (!du.isValid())
@@ -1294,16 +1274,11 @@ public:
qout << ' ' << t.index;
qout << endl;
}
+ qDebug("%s", buf.data().constData());
}
};
void insertPhiNode(const Temp &a, BasicBlock *y, IR::Function *f) {
-#if defined(SHOW_SSA)
- qout << "-> inserted phi node for variable ";
- a.dump(qout);
- qout << " in block " << y->index << endl;
-#endif
-
Phi *phiNode = f->NewStmt<Phi>();
phiNode->d = new Stmt::Data;
phiNode->targetTemp = f->New<Temp>();
@@ -1643,15 +1618,6 @@ protected:
// see [Appel]. For the changes needed for semi-pruned SSA form, and for its advantages, see [Briggs].
void convertToSSA(IR::Function *function, const DominatorTree &df, DefUses &defUses)
{
-#if defined(SHOW_SSA)
- qout << "Converting function ";
- if (function->name)
- qout << *function->name;
- else
- qout << "<no name>";
- qout << " to SSA..." << endl;
-#endif // SHOW_SSA
-
// Collect all applicable variables:
VariableCollector variables(function);
@@ -2113,12 +2079,15 @@ protected:
struct DiscoveredType {
int type;
- MemberExpressionResolver memberResolver;
+ MemberExpressionResolver *memberResolver;
- DiscoveredType() : type(UnknownType) {}
- DiscoveredType(Type t) : type(t) { Q_ASSERT(type != QObjectType); }
- explicit DiscoveredType(int t) : type(t) { Q_ASSERT(type != QObjectType); }
- explicit DiscoveredType(MemberExpressionResolver memberResolver) : type(QObjectType), memberResolver(memberResolver) {}
+ DiscoveredType() : type(UnknownType), memberResolver(0) {}
+ DiscoveredType(Type t) : type(t), memberResolver(0) { Q_ASSERT(type != QObjectType); }
+ explicit DiscoveredType(int t) : type(t), memberResolver(0) { Q_ASSERT(type != QObjectType); }
+ explicit DiscoveredType(MemberExpressionResolver *memberResolver)
+ : type(QObjectType)
+ , memberResolver(memberResolver)
+ { Q_ASSERT(memberResolver); }
bool test(Type t) const { return type & t; }
bool isNumber() const { return (type & NumberType) && !(type & ~NumberType); }
@@ -2223,7 +2192,7 @@ class TypeInference: public StmtVisitor, public ExprVisitor
this->type = type;
fullyTyped = type.type != UnknownType;
}
- explicit TypingResult(MemberExpressionResolver memberResolver)
+ explicit TypingResult(MemberExpressionResolver *memberResolver)
: type(memberResolver)
, fullyTyped(true)
{}
@@ -2248,23 +2217,32 @@ public:
continue;
if (DebugTypeInference) {
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream qout(&buf);
qout<<"Typing stmt ";
IRPrinter(&qout).print(s);
- qout<<endl;
+ qDebug("%s", buf.data().constData());
}
if (!run(s)) {
*_worklist += s;
if (DebugTypeInference) {
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream qout(&buf);
qout<<"Pushing back stmt: ";
IRPrinter(&qout).print(s);
- qout<<endl;
+ qDebug("%s", buf.data().constData());
}
} else {
if (DebugTypeInference) {
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream qout(&buf);
qout<<"Finished: ";
IRPrinter(&qout).print(s);
- qout<<endl;
+ qDebug("%s", buf.data().constData());
}
}
}
@@ -2306,9 +2284,9 @@ private:
void setType(Expr *e, DiscoveredType ty) {
if (Temp *t = e->asTemp()) {
if (DebugTypeInference)
- qout << "Setting type for temp " << t->index
- << " to " << typeName(Type(ty.type)) << " (" << ty.type << ")"
- << endl;
+ qDebug() << "Setting type for temp" << t->index
+ << " to " << typeName(Type(ty.type)) << "(" << ty.type << ")"
+ << endl;
DiscoveredType &it = _tempTypes[t->index];
if (it != ty) {
@@ -2316,9 +2294,12 @@ private:
if (DebugTypeInference) {
foreach (Stmt *s, _defUses.uses(*t)) {
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream qout(&buf);
qout << "Pushing back dependent stmt: ";
IRPrinter(&qout).print(s);
- qout<<endl;
+ qDebug("%s", buf.data().constData());
}
}
@@ -2345,7 +2326,7 @@ protected:
virtual void visitRegExp(IR::RegExp *) { _ty = TypingResult(VarType); }
virtual void visitName(Name *) { _ty = TypingResult(VarType); }
virtual void visitTemp(Temp *e) {
- if (e->memberResolver.isValid())
+ if (e->memberResolver && e->memberResolver->isValid())
_ty = TypingResult(e->memberResolver);
else
_ty = TypingResult(_tempTypes[e->index]);
@@ -2456,9 +2437,9 @@ protected:
virtual void visitMember(Member *e) {
_ty = run(e->base);
- if (_ty.fullyTyped && _ty.type.memberResolver.isValid()) {
- MemberExpressionResolver &resolver = _ty.type.memberResolver;
- _ty.type.type = resolver.resolveMember(qmlEngine, &resolver, e);
+ if (_ty.fullyTyped && _ty.type.memberResolver && _ty.type.memberResolver->isValid()) {
+ MemberExpressionResolver *resolver = _ty.type.memberResolver;
+ _ty.type.type = resolver->resolveMember(qmlEngine, resolver, e);
} else
_ty.type = VarType;
}
@@ -2492,8 +2473,8 @@ protected:
}
_ty.type.type |= ty.type.type;
_ty.fullyTyped &= ty.fullyTyped;
- if (_ty.type.test(QObjectType))
- _ty.type.memberResolver.clear(); // ### TODO: find common ancestor meta-object
+ if (_ty.type.test(QObjectType) && _ty.type.memberResolver)
+ _ty.type.memberResolver->clear(); // ### TODO: find common ancestor meta-object
}
switch (_ty.type.type) {
@@ -2539,7 +2520,7 @@ public:
Q_UNUSED(f);
QVector<UntypedTemp> knownOk;
- QList<UntypedTemp> candidates = _defUses.defsUntyped();
+ QVector<UntypedTemp> candidates = _defUses.defsUntyped();
while (!candidates.isEmpty()) {
UntypedTemp temp = candidates.last();
candidates.removeLast();
@@ -2711,15 +2692,6 @@ class TypePropagation: public StmtVisitor, public ExprVisitor {
if (requestedType != UnknownType) {
if (e->type != requestedType) {
if (requestedType & NumberType || requestedType == BoolType) {
-#ifdef SHOW_SSA
- QTextStream os(stdout, QIODevice::WriteOnly);
- os << "adding conversion from " << typeName(e->type)
- << " to " << typeName(requestedType) << " for expression ";
- e->dump(os);
- os << " in statement ";
- _currStmt->dump(os);
- os << endl;
-#endif
if (insertConversion)
addConversion(e, requestedType);
return true;
@@ -3416,15 +3388,9 @@ public:
QHash<BasicBlock *, BasicBlock *> go()
{
- showMeTheCode(function);
+ showMeTheCode(function, "Before block scheduling");
schedule(function->basicBlock(0));
-#if defined(SHOW_SSA)
- qDebug() << "Block sequence:";
- foreach (BasicBlock *bb, sequence)
- qDebug("\tL%d", bb->index());
-#endif // SHOW_SSA
-
Q_ASSERT(function->liveBasicBlocksCount() == sequence.size());
function->setScheduledBlocks(sequence);
function->renumberBasicBlocks();
@@ -3438,8 +3404,8 @@ void checkCriticalEdges(QVector<BasicBlock *> basicBlocks) {
if (bb && bb->out.size() > 1) {
foreach (BasicBlock *bb2, bb->out) {
if (bb2 && bb2->in.size() > 1) {
- qout << "found critical edge between block "
- << bb->index() << " and block " << bb2->index();
+ qDebug() << "found critical edge between block"
+ << bb->index() << "and block" << bb2->index();
Q_ASSERT(false);
}
}
@@ -3450,14 +3416,13 @@ void checkCriticalEdges(QVector<BasicBlock *> basicBlocks) {
void cleanupBasicBlocks(IR::Function *function)
{
- showMeTheCode(function);
+ showMeTheCode(function, "Before basic block cleanup");
// Algorithm: this is the iterative version of a depth-first search for all blocks that are
// reachable through outgoing edges, starting with the start block and all exception handler
// blocks.
QBitArray reachableBlocks(function->basicBlockCount());
- QVector<BasicBlock *> postponed;
- postponed.reserve(16);
+ QVarLengthArray<BasicBlock *, 16> postponed;
for (int i = 0, ei = function->basicBlockCount(); i != ei; ++i) {
BasicBlock *bb = function->basicBlock(i);
if (i == 0 || bb->isExceptionHandler())
@@ -3503,7 +3468,7 @@ void cleanupBasicBlocks(IR::Function *function)
function->removeBasicBlock(bb);
}
- showMeTheCode(function);
+ showMeTheCode(function, "After basic block cleanup");
}
inline Const *isConstPhi(Phi *phi)
@@ -3836,8 +3801,14 @@ void cfg2dot(IR::Function *f, const QVector<LoopDetection::LoopInfo *> &loops =
if (!showCode)
return;
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream qout(&buf);
+
struct Util {
- static void genLoop(LoopDetection::LoopInfo *loop)
+ QTextStream &qout;
+ Util(QTextStream &qout): qout(qout) {}
+ void genLoop(LoopDetection::LoopInfo *loop)
{
qout << " subgraph \"cluster" << quint64(loop) << "\" {\n";
qout << " L" << loop->loopHeader->index() << ";\n";
@@ -3856,7 +3827,7 @@ void cfg2dot(IR::Function *f, const QVector<LoopDetection::LoopInfo *> &loops =
foreach (LoopDetection::LoopInfo *l, loops) {
if (l->parentLoop == 0)
- Util::genLoop(l);
+ Util(qout).genLoop(l);
}
foreach (BasicBlock *bb, f->basicBlocks()) {
@@ -3874,7 +3845,8 @@ void cfg2dot(IR::Function *f, const QVector<LoopDetection::LoopInfo *> &loops =
qout << " L" << idx << " -> L" << out->index() << "\n";
}
- qout << "}\n" << flush;
+ qout << "}\n";
+ qDebug("%s", buf.data().constData());
}
} // anonymous namespace
@@ -4307,6 +4279,10 @@ public:
void dump() const
{
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream qout(&buf);
+
qout << "Life ranges:" << endl;
qout << "Intervals:" << endl;
foreach (const LifeTimeInterval *range, _sortedIntervals->intervals()) {
@@ -4327,6 +4303,7 @@ public:
}
qout << endl;
}
+ qDebug("%s", buf.data().constData());
}
private:
@@ -5074,12 +5051,7 @@ Optimizer::Optimizer(IR::Function *function)
void Optimizer::run(QQmlEnginePrivate *qmlEngine, bool doTypeInference, bool peelLoops)
{
-#if defined(SHOW_SSA)
- qout << "##### NOW IN FUNCTION " << (function->name ? qPrintable(*function->name) : "anonymous!")
- << " with " << function->basicBlocks.size() << " basic blocks." << endl << flush;
-#endif
-
-// showMeTheCode(function);
+ showMeTheCode(function, "Before running the optimizer");
cleanupBasicBlocks(function);
@@ -5093,7 +5065,7 @@ void Optimizer::run(QQmlEnginePrivate *qmlEngine, bool doTypeInference, bool pee
// qout << "SSA for " << (function->name ? qPrintable(*function->name) : "<anonymous>") << endl;
ConvertArgLocals(function).toTemps();
- showMeTheCode(function);
+ showMeTheCode(function, "After converting arguments to locals");
// Calculate the dominator tree:
DominatorTree df(function);
@@ -5105,7 +5077,7 @@ void Optimizer::run(QQmlEnginePrivate *qmlEngine, bool doTypeInference, bool pee
LoopDetection loopDetection(df);
loopDetection.run(function);
- showMeTheCode(function);
+ showMeTheCode(function, "After loop detection");
// cfg2dot(function, loopDetection.allLoops());
if (peelLoops) {
@@ -5113,7 +5085,7 @@ void Optimizer::run(QQmlEnginePrivate *qmlEngine, bool doTypeInference, bool pee
LoopPeeling(df).run(innerLoops);
// cfg2dot(function, loopDetection.allLoops());
- showMeTheCode(function);
+ showMeTheCode(function, "After loop peeling");
if (!innerLoops.isEmpty())
verifyImmediateDominators(df, function);
}
@@ -5136,14 +5108,14 @@ void Optimizer::run(QQmlEnginePrivate *qmlEngine, bool doTypeInference, bool pee
// qout << "Cleaning up phi nodes..." << endl;
cleanupPhis(defUses);
- showMeTheCode(function);
+ showMeTheCode(function, "After cleaning up phi-nodes");
StatementWorklist worklist(function);
if (doTypeInference) {
// qout << "Running type inference..." << endl;
TypeInference(qmlEngine, defUses).run(worklist);
- showMeTheCode(function);
+ showMeTheCode(function, "After type inference");
// qout << "Doing reverse inference..." << endl;
ReverseInference(defUses).run(function);
@@ -5160,7 +5132,7 @@ void Optimizer::run(QQmlEnginePrivate *qmlEngine, bool doTypeInference, bool pee
// qout << "Running SSA optimization..." << endl;
worklist.reset();
optimizeSSA(worklist, defUses, df);
- showMeTheCode(function);
+ showMeTheCode(function, "After optimization");
verifyImmediateDominators(df, function);
verifyCFG(function);
@@ -5186,7 +5158,7 @@ void Optimizer::run(QQmlEnginePrivate *qmlEngine, bool doTypeInference, bool pee
// qout << "Doing block scheduling..." << endl;
// df.dumpImmediateDominators();
startEndLoops = BlockScheduler(function, df).go();
- showMeTheCode(function);
+ showMeTheCode(function, "After basic block scheduling");
// cfg2dot(function);
#ifndef QT_NO_DEBUG
@@ -5223,16 +5195,19 @@ void Optimizer::convertOutOfSSA() {
}
}
- #if defined(DEBUG_MOVEMAPPING)
- QTextStream os(stdout, QIODevice::WriteOnly);
- os << "Move mapping for function ";
- if (function->name)
- os << *function->name;
- else
- os << (void *) function;
- os << " on basic-block L" << bb->index << ":" << endl;
- moves.dump();
- #endif // DEBUG_MOVEMAPPING
+ if (DebugMoveMapping) {
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream os(&buf);
+ os << "Move mapping for function ";
+ if (function->name)
+ os << *function->name;
+ else
+ os << (void *) function;
+ os << " on basic-block L" << bb->index() << ":" << endl;
+ moves.dump();
+ qDebug("%s", buf.data().constData());
+ }
moves.order();
@@ -5288,22 +5263,12 @@ QSet<Jump *> Optimizer::calculateOptionalJumps()
reachableWithoutJump.insert(bb);
}
-#if 0
- QTextStream out(stdout, QIODevice::WriteOnly);
- out << "Jumps to ignore:" << endl;
- foreach (Jump *j, removed) {
- out << "\t" << j->id << ": ";
- j->dump(out, Stmt::MIR);
- out << endl;
- }
-#endif
-
return optional;
}
-void Optimizer::showMeTheCode(IR::Function *function)
+void Optimizer::showMeTheCode(IR::Function *function, const char *marker)
{
- ::showMeTheCode(function);
+ ::showMeTheCode(function, marker);
}
static inline bool overlappingStorage(const Temp &t1, const Temp &t2)
@@ -5345,14 +5310,17 @@ void MoveMapping::add(Expr *from, Temp *to) {
if (Temp *t = from->asTemp()) {
if (overlappingStorage(*t, *to)) {
// assignments like fp1 = fp1 or var{&1} = double{&1} can safely be skipped.
-#if defined(DEBUG_MOVEMAPPING)
- QTextStream os(stderr, QIODevice::WriteOnly);
- os << "Skipping ";
- to->dump(os);
- os << " <- ";
- from->dump(os);
- os << endl;
-#endif // DEBUG_MOVEMAPPING
+ if (DebugMoveMapping) {
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream os(&buf);
+ IRPrinter printer(&os);
+ os << "Skipping ";
+ printer.print(to);
+ os << " <- ";
+ printer.print(from);
+ qDebug("%s", buf.data().constData());
+ }
return;
}
}
@@ -5403,20 +5371,24 @@ QList<IR::Move *> MoveMapping::insertMoves(BasicBlock *bb, IR::Function *functio
void MoveMapping::dump() const
{
-#if defined(DEBUG_MOVEMAPPING)
- QTextStream os(stdout, QIODevice::WriteOnly);
- os << "Move mapping has " << _moves.size() << " moves..." << endl;
- foreach (const Move &m, _moves) {
- os << "\t";
- m.to->dump(os);
- if (m.needsSwap)
- os << " <-> ";
- else
- os << " <-- ";
- m.from->dump(os);
- os << endl;
+ if (DebugMoveMapping) {
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream os(&buf);
+ IRPrinter printer(&os);
+ os << "Move mapping has " << _moves.size() << " moves..." << endl;
+ foreach (const Move &m, _moves) {
+ os << "\t";
+ printer.print(m.to);
+ if (m.needsSwap)
+ os << " <-> ";
+ else
+ os << " <-- ";
+ printer.print(m.from);
+ os << endl;
+ }
+ qDebug("%s", buf.data().constData());
}
-#endif // DEBUG_MOVEMAPPING
}
MoveMapping::Action MoveMapping::schedule(const Move &m, QList<Move> &todo, QList<Move> &delayed,
@@ -5427,19 +5399,24 @@ MoveMapping::Action MoveMapping::schedule(const Move &m, QList<Move> &todo, QLis
if (!output.contains(dependency)) {
if (delayed.contains(dependency)) {
// We have a cycle! Break it by swapping instead of assigning.
-#if defined(DEBUG_MOVEMAPPING)
- delayed+=m;
- QTextStream out(stderr, QIODevice::WriteOnly);
- out<<"we have a cycle! temps:" << endl;
- foreach (const Move &m, delayed) {
- out<<"\t";
- m.to->dump(out);
- out<<" <- ";
- m.from->dump(out);
- out<<endl;
+ if (DebugMoveMapping) {
+ delayed += m;
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream out(&buf);
+ IRPrinter printer(&out);
+ out<<"we have a cycle! temps:" << endl;
+ foreach (const Move &m, delayed) {
+ out<<"\t";
+ printer.print(m.to);
+ out<<" <- ";
+ printer.print(m.from);
+ out<<endl;
+ }
+ qDebug("%s", buf.data().constData());
+ delayed.removeOne(m);
}
- delayed.removeOne(m);
-#endif // DEBUG_MOVEMAPPING
+
return NeedsSwap;
} else {
delayed.append(m);
diff --git a/src/qml/compiler/qv4ssa_p.h b/src/qml/compiler/qv4ssa_p.h
index 21a5b038b6..93bf62ad40 100644
--- a/src/qml/compiler/qv4ssa_p.h
+++ b/src/qml/compiler/qv4ssa_p.h
@@ -219,7 +219,7 @@ public:
QSet<IR::Jump *> calculateOptionalJumps();
- static void showMeTheCode(Function *function);
+ static void showMeTheCode(Function *function, const char *marker);
private:
Function *function;
diff --git a/src/qml/debugger/qqmldebug.h b/src/qml/debugger/qqmldebug.h
index 876d0683ce..fc22b295a6 100644
--- a/src/qml/debugger/qqmldebug.h
+++ b/src/qml/debugger/qqmldebug.h
@@ -42,6 +42,8 @@ QT_BEGIN_NAMESPACE
struct Q_QML_EXPORT QQmlDebuggingEnabler
{
QQmlDebuggingEnabler(bool printWarning = true);
+ static bool startTcpDebugServer(int port, bool block = false,
+ const QString &hostName = QString());
};
// Execute code in constructor before first QQmlEngine is instantiated
diff --git a/src/qml/debugger/qqmldebugserver.cpp b/src/qml/debugger/qqmldebugserver.cpp
index 2a2ce663bc..cbed6151bf 100644
--- a/src/qml/debugger/qqmldebugserver.cpp
+++ b/src/qml/debugger/qqmldebugserver.cpp
@@ -51,7 +51,7 @@
#include <private/qobject_p.h>
#include <private/qcoreapplication_p.h>
-#if defined(QT_STATIC) && ! defined(QT_QML_NO_DEBUGGER)
+#if defined(QT_STATIC) && ! defined(QT_NO_QML_DEBUGGER)
#include "../../plugins/qmltooling/qmldbg_tcp/qtcpserverconnection.h"
#endif
@@ -104,6 +104,8 @@ class QQmlDebugServerPrivate : public QObjectPrivate
public:
QQmlDebugServerPrivate();
+ bool start(int portFrom, int portTo, bool block, const QString &hostAddress,
+ const QString &pluginName);
void advertisePlugins();
void cleanup();
QQmlDebugServerConnection *loadConnectionPlugin(const QString &pluginName);
@@ -142,6 +144,7 @@ private:
void _q_changeServiceState(const QString &serviceName,
QQmlDebugService::State newState);
void _q_sendMessages(const QList<QByteArray> &messages);
+ void _q_removeThread();
};
void QQmlDebugServerInstanceWrapper::cleanup()
@@ -154,7 +157,7 @@ public:
m_pluginName = pluginName;
}
- void setPortRange(int portFrom, int portTo, bool block, QString &hostAddress) {
+ void setPortRange(int portFrom, int portTo, bool block, const QString &hostAddress) {
m_portFrom = portFrom;
m_portTo = portTo;
m_block = block;
@@ -226,12 +229,13 @@ void QQmlDebugServerPrivate::cleanup()
while (!changeServiceStateCalls.testAndSetOrdered(0, 0))
loop.processEvents();
- // Stop the thread while the application is still there.
- if (thread) {
- thread->exit();
- thread->wait();
- delete thread;
- thread = 0;
+ // Stop the thread while the application is still there. Copy here as the thread will set itself
+ // to 0 when it stops. It will also do deleteLater, but as long as we don't allow the GUI
+ // thread's event loop to run we're safe from that.
+ QThread *threadCopy = thread;
+ if (threadCopy) {
+ threadCopy->exit();
+ threadCopy->wait();
}
}
@@ -252,6 +256,7 @@ QQmlDebugServerConnection *QQmlDebugServerPrivate::loadConnectionPlugin(
}
}
+ QQmlDebugServerConnection *loadedConnection = 0;
foreach (const QString &pluginPath, pluginCandidates) {
if (qmlDebugVerbose())
qDebug() << "QML Debugger: Trying to load plugin " << pluginPath << "...";
@@ -263,13 +268,13 @@ QQmlDebugServerConnection *QQmlDebugServerPrivate::loadConnectionPlugin(
continue;
}
if (QObject *instance = loader.instance())
- connection = qobject_cast<QQmlDebugServerConnection*>(instance);
+ loadedConnection = qobject_cast<QQmlDebugServerConnection*>(instance);
- if (connection) {
+ if (loadedConnection) {
if (qmlDebugVerbose())
qDebug() << "QML Debugger: Plugin successfully loaded.";
- return connection;
+ return loadedConnection;
}
if (qmlDebugVerbose())
@@ -286,21 +291,25 @@ void QQmlDebugServerThread::run()
QQmlDebugServerInstanceWrapper *wrapper = debugServerInstance();
Q_ASSERT_X(wrapper != 0, Q_FUNC_INFO, "There should always be a debug server available here.");
QQmlDebugServer *server = &wrapper->m_instance;
-#if defined(QT_STATIC) && ! defined(QT_QML_NO_DEBUGGER)
+#if defined(QT_STATIC) && ! defined(QT_NO_QML_DEBUGGER)
QQmlDebugServerConnection *connection
= new QTcpServerConnection;
- server->d_func()->connection = connection;
#else
QQmlDebugServerConnection *connection
= server->d_func()->loadConnectionPlugin(m_pluginName);
#endif
if (connection) {
connection->setServer(server);
- connection->setPortRange(m_portFrom, m_portTo, m_block, m_hostAddress);
+ if (!connection->setPortRange(m_portFrom, m_portTo, m_block, m_hostAddress)) {
+ delete connection;
+ return;
+ }
+ server->d_func()->connection = connection;
+ if (m_block)
+ connection->waitForConnection();
} else {
- QCoreApplicationPrivate *appD = static_cast<QCoreApplicationPrivate*>(QObjectPrivate::get(qApp));
- qWarning() << QString(QLatin1String("QML Debugger: Ignoring \"-qmljsdebugger=%1\". "
- "Remote debugger plugin has not been found.")).arg(appD->qmljsDebugArgumentsString());
+ qWarning() << "QML Debugger: Couldn't load plugin" << m_pluginName;
+ return;
}
exec();
@@ -318,6 +327,18 @@ bool QQmlDebugServer::hasDebuggingClient() const
&& d->gotHello;
}
+bool QQmlDebugServer::hasThread() const
+{
+ Q_D(const QQmlDebugServer);
+ return d->thread != 0;
+}
+
+bool QQmlDebugServer::hasConnection() const
+{
+ Q_D(const QQmlDebugServer);
+ return d->connection != 0;
+}
+
bool QQmlDebugServer::blockingMode() const
{
Q_D(const QQmlDebugServer);
@@ -339,19 +360,48 @@ QQmlDebugServer *QQmlDebugServer::instance()
}
}
-static void cleanup()
+static void cleanupOnShutdown()
{
QQmlDebugServerInstanceWrapper *wrapper = debugServerInstance();
if (wrapper)
wrapper->cleanup();
}
+bool QQmlDebugServerPrivate::start(int portFrom, int portTo, bool block, const QString &hostAddress,
+ const QString &pluginName)
+{
+ if (!QQmlEnginePrivate::qml_debugging_enabled)
+ return false;
+ if (thread)
+ return false;
+ static bool postRoutineAdded = false;
+ if (!postRoutineAdded) {
+ qAddPostRoutine(cleanupOnShutdown);
+ postRoutineAdded = true;
+ }
+ Q_Q(QQmlDebugServer);
+ thread = new QQmlDebugServerThread;
+ q->moveToThread(thread);
+
+ // Remove the thread immmediately when it finishes, so that we don't have to wait for the event
+ // loop to signal that.
+ QObject::connect(thread, SIGNAL(finished()), q, SLOT(_q_removeThread()), Qt::DirectConnection);
+
+ thread->setObjectName(QStringLiteral("QQmlDebugServerThread"));
+ thread->setPluginName(pluginName);
+ thread->setPortRange(portFrom, portTo == -1 ? portFrom : portTo, block, hostAddress);
+ blockingMode = block;
+ thread->start();
+ return true;
+}
QQmlDebugServer::QQmlDebugServer()
: QObject(*(new QQmlDebugServerPrivate))
{
+ if (qApp == 0)
+ return;
QCoreApplicationPrivate *appD = static_cast<QCoreApplicationPrivate*>(QObjectPrivate::get(qApp));
-#ifndef QT_QML_NO_DEBUGGER
+#ifndef QT_NO_QML_DEBUGGER
// ### remove port definition when protocol is changed
int portFrom = 0;
int portTo = 0;
@@ -400,17 +450,8 @@ QQmlDebugServer::QQmlDebugServer()
}
if (ok) {
- qAddPostRoutine(cleanup);
Q_D(QQmlDebugServer);
- d->thread = new QQmlDebugServerThread;
- moveToThread(d->thread);
- d->thread->setObjectName(QStringLiteral("QQmlDebugServerThread"));
- d->thread->setPluginName(pluginName);
- d->thread->setPortRange(portFrom, portTo, block, hostAddress);
-
- d->blockingMode = block;
- d->thread->start();
-
+ d->start(portFrom, portTo, block, hostAddress, pluginName);
} else {
qWarning() << QString(QLatin1String(
"QML Debugger: Ignoring \"-qmljsdebugger=%1\". "
@@ -419,7 +460,6 @@ QQmlDebugServer::QQmlDebugServer()
}
}
#else
- Q_UNUSED(&cleanup)
if (!appD->qmljsDebugArgumentsString().isEmpty()) {
qWarning() << QString(QLatin1String(
"QML Debugger: Ignoring \"-qmljsdebugger=%1\". "
@@ -429,15 +469,6 @@ QQmlDebugServer::QQmlDebugServer()
#endif
}
-// called from GUI thread!
-QQmlDebugServer::~QQmlDebugServer()
-{
- Q_D(QQmlDebugServer);
-
- delete d->thread;
- delete d->connection;
-}
-
void QQmlDebugServer::receiveMessage(const QByteArray &message)
{
// to be executed in debugger thread
@@ -575,6 +606,24 @@ void QQmlDebugServerPrivate::_q_sendMessages(const QList<QByteArray> &messages)
connection->send(messages);
}
+void QQmlDebugServerPrivate::_q_removeThread()
+{
+ Q_ASSERT(thread->isFinished());
+ Q_ASSERT(QThread::currentThread() == thread);
+
+ QThread *parentThread = thread->thread();
+
+ // We cannot delete it right away as it will access its data after the finished() signal.
+ thread->deleteLater();
+ thread = 0;
+
+ delete connection;
+ connection = 0;
+
+ // Move it back to the parent thread so that we can potentially restart it on a new thread.
+ q_func()->moveToThread(parentThread);
+}
+
QList<QQmlDebugService*> QQmlDebugServer::services() const
{
Q_D(const QQmlDebugServer);
@@ -681,6 +730,31 @@ void QQmlDebugServer::sendMessages(QQmlDebugService *service,
Q_ARG(QList<QByteArray>, prefixedMessages));
}
+bool QQmlDebugServer::enable(int portFrom, int portTo, bool block, const QString &hostAddress)
+{
+#ifndef QT_NO_QML_DEBUGGER
+ QQmlDebugServerInstanceWrapper *wrapper = debugServerInstance();
+ if (!wrapper)
+ return false;
+ QQmlDebugServerPrivate *d = wrapper->m_instance.d_func();
+ if (d->thread)
+ return false;
+ if (!d->start(portFrom, portTo, block, hostAddress, QLatin1String("qmldbg_tcp")))
+ return false;
+ while (!wrapper->m_instance.hasConnection()) {
+ if (!wrapper->m_instance.hasThread())
+ return false;
+ }
+ return true;
+#else
+ Q_UNUSED(portFrom);
+ Q_UNUSED(portTo);
+ Q_UNUSED(block);
+ Q_UNUSED(hostAddress);
+ return false;
+#endif
+}
+
void QQmlDebugServer::wakeEngine(QQmlEngine *engine)
{
// to be executed in debugger thread
diff --git a/src/qml/debugger/qqmldebugserver_p.h b/src/qml/debugger/qqmldebugserver_p.h
index 4ea71fb769..ede7f68a09 100644
--- a/src/qml/debugger/qqmldebugserver_p.h
+++ b/src/qml/debugger/qqmldebugserver_p.h
@@ -59,10 +59,11 @@ class Q_QML_PRIVATE_EXPORT QQmlDebugServer : public QObject
Q_DECLARE_PRIVATE(QQmlDebugServer)
Q_DISABLE_COPY(QQmlDebugServer)
public:
- ~QQmlDebugServer();
static QQmlDebugServer *instance();
+ bool hasThread() const;
+ bool hasConnection() const;
bool hasDebuggingClient() const;
bool blockingMode() const;
@@ -78,6 +79,7 @@ public:
void receiveMessage(const QByteArray &message);
void sendMessages(QQmlDebugService *service, const QList<QByteArray> &messages);
+ static bool enable(int portFrom, int portTo, bool block, const QString &hostAddress);
private slots:
void wakeEngine(QQmlEngine *engine);
@@ -91,6 +93,7 @@ private:
Q_PRIVATE_SLOT(d_func(), void _q_changeServiceState(const QString &serviceName,
QQmlDebugService::State state))
Q_PRIVATE_SLOT(d_func(), void _q_sendMessages(QList<QByteArray>))
+ Q_PRIVATE_SLOT(d_func(), void _q_removeThread())
public:
static int s_dataStreamVersion;
diff --git a/src/qml/debugger/qqmldebugserverconnection_p.h b/src/qml/debugger/qqmldebugserverconnection_p.h
index 18a01544f3..fecb2d8c26 100644
--- a/src/qml/debugger/qqmldebugserverconnection_p.h
+++ b/src/qml/debugger/qqmldebugserverconnection_p.h
@@ -59,10 +59,11 @@ public:
virtual ~QQmlDebugServerConnection() {}
virtual void setServer(QQmlDebugServer *server) = 0;
- virtual void setPortRange(int portFrom, int portTo, bool bock, const QString &hostaddress) = 0;
+ virtual bool setPortRange(int portFrom, int portTo, bool bock, const QString &hostaddress) = 0;
virtual bool isConnected() const = 0;
virtual void send(const QList<QByteArray> &messages) = 0;
virtual void disconnect() = 0;
+ virtual void waitForConnection() = 0;
virtual bool waitForMessage() = 0;
};
diff --git a/src/qml/debugger/qqmlprofilerdefinitions_p.h b/src/qml/debugger/qqmlprofilerdefinitions_p.h
index e8ee98433d..713134f394 100644
--- a/src/qml/debugger/qqmlprofilerdefinitions_p.h
+++ b/src/qml/debugger/qqmlprofilerdefinitions_p.h
@@ -107,18 +107,20 @@ struct QQmlProfilerDefinitions {
};
enum SceneGraphFrameType {
- SceneGraphRendererFrame,
- SceneGraphAdaptationLayerFrame,
- SceneGraphContextFrame,
- SceneGraphRenderLoopFrame,
- SceneGraphTexturePrepare,
- SceneGraphTextureDeletion,
- SceneGraphPolishAndSync,
- SceneGraphWindowsRenderShow,
- SceneGraphWindowsAnimations,
- SceneGraphPolishFrame,
-
- MaximumSceneGraphFrameType
+ SceneGraphRendererFrame, // Render Thread
+ SceneGraphAdaptationLayerFrame, // Render Thread
+ SceneGraphContextFrame, // Render Thread
+ SceneGraphRenderLoopFrame, // Render Thread
+ SceneGraphTexturePrepare, // Render Thread
+ SceneGraphTextureDeletion, // Render Thread
+ SceneGraphPolishAndSync, // GUI Thread
+ SceneGraphWindowsRenderShow, // Unused
+ SceneGraphWindowsAnimations, // GUI Thread
+ SceneGraphPolishFrame, // GUI Thread
+
+ MaximumSceneGraphFrameType,
+ NumRenderThreadFrameTypes = SceneGraphPolishAndSync,
+ NumGUIThreadFrameTypes = MaximumSceneGraphFrameType - NumRenderThreadFrameTypes
};
typedef QV4::Profiling::MemoryType MemoryType;
diff --git a/src/qml/debugger/qv4debugservice.cpp b/src/qml/debugger/qv4debugservice.cpp
index b0cac272aa..79c384ead9 100644
--- a/src/qml/debugger/qv4debugservice.cpp
+++ b/src/qml/debugger/qv4debugservice.cpp
@@ -62,8 +62,8 @@ const char *V4_LINENUMBER = "linenumber";
#ifdef NO_PROTOCOL_TRACING
# define TRACE_PROTOCOL(x)
#else
+#include <QtCore/QDebug>
# define TRACE_PROTOCOL(x) x
-static QTextStream debug(stderr, QIODevice::WriteOnly);
#endif
QT_BEGIN_NAMESPACE
@@ -232,12 +232,12 @@ protected:
QV4::Scope scope(engine());
QV4::ScopedObject obj(scope, value->asObject());
- int ref = cachedObjectRef(obj.getPointer());
+ int ref = cachedObjectRef(obj);
if (ref != -1) {
addNameRefPair(name, ref);
} else {
int ref = newRefId();
- cacheObjectRef(obj.getPointer(), ref);
+ cacheObjectRef(obj, ref);
QJsonArray properties, *prev = &properties;
QSet<int> used;
@@ -378,7 +378,7 @@ public:
QByteArray responseData = doc.toJson(QJsonDocument::Indented);
#endif
- TRACE_PROTOCOL(debug << "sending response for: " << responseData << endl);
+ TRACE_PROTOCOL(qDebug() << "sending response for:" << responseData << endl);
q_func()->sendMessage(packMessage("v8message", responseData));
}
@@ -422,7 +422,7 @@ public:
QJsonArray scopes;
// Only type and index are used by Qt Creator, so we keep it easy:
- QVector<QV4::ExecutionContext::ContextType> scopeTypes = debugger->getScopeTypes(frameNr);
+ QVector<QV4::Heap::ExecutionContext::ContextType> scopeTypes = debugger->getScopeTypes(frameNr);
for (int i = 0, ei = scopeTypes.count(); i != ei; ++i) {
int type = encodeScopeType(scopeTypes[i]);
if (type == -1)
@@ -438,23 +438,23 @@ public:
return frame;
}
- int encodeScopeType(QV4::ExecutionContext::ContextType scopeType)
+ int encodeScopeType(QV4::Heap::ExecutionContext::ContextType scopeType)
{
switch (scopeType) {
- case QV4::ExecutionContext::Type_GlobalContext:
+ case QV4::Heap::ExecutionContext::Type_GlobalContext:
return 0;
break;
- case QV4::ExecutionContext::Type_CatchContext:
+ case QV4::Heap::ExecutionContext::Type_CatchContext:
return 4;
break;
- case QV4::ExecutionContext::Type_WithContext:
+ case QV4::Heap::ExecutionContext::Type_WithContext:
return 2;
break;
- case QV4::ExecutionContext::Type_SimpleCallContext:
- case QV4::ExecutionContext::Type_CallContext:
+ case QV4::Heap::ExecutionContext::Type_SimpleCallContext:
+ case QV4::Heap::ExecutionContext::Type_CallContext:
return 1;
break;
- case QV4::ExecutionContext::Type_QmlContext:
+ case QV4::Heap::ExecutionContext::Type_QmlContext:
default:
return -1;
}
@@ -470,7 +470,7 @@ public:
QJsonObject anonymous;
anonymous[QLatin1String("properties")] = properties;
- QVector<QV4::ExecutionContext::ContextType> scopeTypes = debugger->getScopeTypes(frameNr);
+ QVector<QV4::Heap::ExecutionContext::ContextType> scopeTypes = debugger->getScopeTypes(frameNr);
scope[QLatin1String("type")] = encodeScopeType(scopeTypes[scopeNr]);
scope[QLatin1String("index")] = scopeNr;
scope[QLatin1String("frameIndex")] = frameNr;
@@ -523,7 +523,7 @@ public:
void handle(const QJsonObject &request, QQmlDebugService *s, QV4DebugServicePrivate *p)
{
- TRACE_PROTOCOL(debug << "handling command " << command() << "..." << endl);
+ TRACE_PROTOCOL(qDebug() << "handling command" << command() << "...");
req = request;
seq = req.value(QStringLiteral("seq"));
@@ -1137,13 +1137,13 @@ void QV4DebugService::messageReceived(const QByteArray &message)
QByteArray header;
ms >> header;
- TRACE_PROTOCOL(debug << "received message with header " << header << endl);
+ TRACE_PROTOCOL(qDebug() << "received message with header" << header);
if (header == "V8DEBUG") {
QByteArray type;
QByteArray payload;
ms >> type >> payload;
- TRACE_PROTOCOL(debug << "... type: "<<type << endl);
+ TRACE_PROTOCOL(qDebug() << "... type:" << type);
if (type == V4_CONNECT) {
sendMessage(d->packMessage(type));
@@ -1164,7 +1164,7 @@ void QV4DebugService::messageReceived(const QByteArray &message)
} else if (type == "v8request") {
handleV8Request(payload);
} else if (type == V4_DISCONNECT) {
- TRACE_PROTOCOL(debug << "... payload:"<<payload << endl);
+ TRACE_PROTOCOL(qDebug() << "... payload:" << payload);
handleV8Request(payload);
} else {
sendSomethingToSomebody(type, 0);
@@ -1249,7 +1249,7 @@ void QV4DebugService::handleV8Request(const QByteArray &payload)
{
Q_D(QV4DebugService);
- TRACE_PROTOCOL(debug << "v8request, payload: " << payload << endl);
+ TRACE_PROTOCOL(qDebug() << "v8request, payload:" << payload);
QJsonDocument request = QJsonDocument::fromJson(payload);
QJsonObject o = request.object();
diff --git a/src/qml/doc/src/cppintegration/data.qdoc b/src/qml/doc/src/cppintegration/data.qdoc
index c083d63e51..26d3060318 100644
--- a/src/qml/doc/src/cppintegration/data.qdoc
+++ b/src/qml/doc/src/cppintegration/data.qdoc
@@ -307,6 +307,33 @@ them with default constructed values, do not use the indexed delete operator
("delete sequence[i]") but instead use the \c {splice} function
("sequence.splice(startIndex, deleteCount)").
+\section2 Value types
+
+Some value types in Qt such as QPoint are represented in JavaScript as objects
+that have the same properties and functions like in the C++ API. The same
+representation is possible with custom C++ value types. To enable a custom
+value type with the QML engine, the class declaration needs to be annotated
+with \c{Q_GADGET}. Properties that are intended to be visible in the JavaScript
+representation need to be declared with \c Q_PROPERTY. Similarly functions need
+to be marked with \c Q_INVOKABLE. This is the same with QObject based C++ APIs.
+For example, the \c Actor class below is annotated as gadget and has
+properties:
+
+\code
+ class Actor
+ {
+ Q_GADGET
+ Q_PROPERTY(QString name READ name WRITE setName)
+ public:
+ QString name() const { return m_name; }
+ void setName(const QString &name) { m_name = name; }
+
+ private:
+ QString m_name;
+ }
+
+ Q_DECLARE_METATYPE(Actor)
+\endcode
\section1 Enumeration Types
diff --git a/src/qml/doc/src/javascript/date.qdoc b/src/qml/doc/src/javascript/date.qdoc
index 4f897af928..4e1e3e55f5 100644
--- a/src/qml/doc/src/javascript/date.qdoc
+++ b/src/qml/doc/src/javascript/date.qdoc
@@ -132,6 +132,25 @@
hour, if DST is currently in effect, while it was not for the time specified, or
vice versa.
+ Note: There are different date formats with different understandings of negative years. Common
+ human language does not have a year 0. The year after 1BC is 1AD. This understanding is
+ reflected when printing or parsing dates in one of the formats not standardized by ECMAScript.
+ That is: toString(), toLocaleString(), toUTCString() and friends. ECMAScript does standardize
+ one format: ISO 8601. This is what you get when you call toISOString(). This format does include
+ a year 0, which is 1BC in other formats. Thus you get different years when printing negative
+ dates with toISOString() and toString().
+
+ When setting the year using the Date constructor or set(UTC)FullYear(), the convention set by
+ ISO 8601 is used and 0 is a valid year. This means negative years set with the constructor or
+ set(UTC)FullYear() are zero-based and thus offset by one year from what is printed with
+ toString() and friends. Parsing the output of any of the to*String() methods will yield the same
+ date value you printed from. Date.parse() will recognize the different formats and their
+ convention on the existence of year 0.
+
+ Note that all this is different from what you get in other JavaScript implementations which
+ usually treat year 0 as valid in all string representations. As the date formats are
+ "implementation-dependent" in the ECMAScript standard, this is still valid, though.
+
\sa {QtQml::Locale}{Locale}
*/
diff --git a/src/qml/doc/src/javascript/qmlglobalobject.qdoc b/src/qml/doc/src/javascript/qmlglobalobject.qdoc
index 62ec296178..fd702cd879 100644
--- a/src/qml/doc/src/javascript/qmlglobalobject.qdoc
+++ b/src/qml/doc/src/javascript/qmlglobalobject.qdoc
@@ -57,7 +57,6 @@ The XMLHttpRequest API implements the same \l {http://www.w3.org/TR/XMLHttpReque
as many popular web browsers with following exceptions:
\list
\li QML's XMLHttpRequest does not enforce the same origin policy.
-\li QML's XMLHttpRequest does not support \e synchronous requests.
\endlist
Additionally, the \c responseXML XML DOM tree currently supported by QML is a reduced subset
diff --git a/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc b/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc
index dd42e251c2..2fa1d567c6 100644
--- a/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc
+++ b/src/qml/doc/src/qmllanguageref/syntax/objectattributes.qdoc
@@ -590,8 +590,8 @@ Item {
}
\endqml
-\note A read-only property cannot also be a \l{Default Properties}{default} or
-\l {Property Aliases}{alias} property.
+\note A read-only property cannot also be a \l{Default Properties}{default}
+property.
\section3 Property Modifier Objects
diff --git a/src/qml/jit/qv4assembler.cpp b/src/qml/jit/qv4assembler.cpp
index ed342740ac..e0fe31d6cf 100644
--- a/src/qml/jit/qv4assembler.cpp
+++ b/src/qml/jit/qv4assembler.cpp
@@ -68,7 +68,7 @@ void CompilationUnit::linkBackendToEngine(ExecutionEngine *engine)
const CompiledData::Function *compiledFunction = data->functionAt(i);
QV4::Function *runtimeFunction = new QV4::Function(engine, this, compiledFunction,
- (ReturnedValue (*)(QV4::ExecutionContext *, const uchar *)) codeRefs[i].code().executableAddress());
+ (ReturnedValue (*)(QV4::ExecutionEngine *, const uchar *)) codeRefs[i].code().executableAddress());
runtimeFunctions[i] = runtimeFunction;
}
}
@@ -182,25 +182,24 @@ Assembler::Pointer Assembler::loadArgLocalAddress(RegisterID baseReg, IR::ArgLoc
{
int32_t offset = 0;
int scope = al->scope;
- RegisterID context = ContextRegister;
+ loadPtr(Address(EngineRegister, qOffsetOf(ExecutionEngine, current)), baseReg);
if (scope) {
- loadPtr(Address(ContextRegister, qOffsetOf(ExecutionContext::Data, outer)), baseReg);
+ loadPtr(Address(baseReg, qOffsetOf(ExecutionContext::Data, outer)), baseReg);
--scope;
- context = baseReg;
while (scope) {
- loadPtr(Address(context, qOffsetOf(ExecutionContext::Data, outer)), context);
+ loadPtr(Address(baseReg, qOffsetOf(ExecutionContext::Data, outer)), baseReg);
--scope;
}
}
switch (al->kind) {
case IR::ArgLocal::Formal:
case IR::ArgLocal::ScopedFormal: {
- loadPtr(Address(context, qOffsetOf(ExecutionContext::Data, callData)), baseReg);
+ loadPtr(Address(baseReg, qOffsetOf(ExecutionContext::Data, callData)), baseReg);
offset = sizeof(CallData) + (al->index - 1) * sizeof(Value);
} break;
case IR::ArgLocal::Local:
case IR::ArgLocal::ScopedLocal: {
- loadPtr(Address(context, qOffsetOf(CallContext::Data, locals)), baseReg);
+ loadPtr(Address(baseReg, qOffsetOf(CallContext::Data, locals)), baseReg);
offset = al->index * sizeof(Value);
} break;
default:
@@ -211,18 +210,17 @@ Assembler::Pointer Assembler::loadArgLocalAddress(RegisterID baseReg, IR::ArgLoc
Assembler::Pointer Assembler::loadStringAddress(RegisterID reg, const QString &string)
{
- loadPtr(Address(Assembler::ContextRegister, qOffsetOf(QV4::ExecutionContext::Data, compilationUnit)), Assembler::ScratchRegister);
+ loadPtr(Address(Assembler::EngineRegister, qOffsetOf(QV4::ExecutionEngine, current)), Assembler::ScratchRegister);
+ loadPtr(Address(Assembler::ScratchRegister, qOffsetOf(QV4::Heap::ExecutionContext, compilationUnit)), Assembler::ScratchRegister);
loadPtr(Address(Assembler::ScratchRegister, qOffsetOf(QV4::CompiledData::CompilationUnit, runtimeStrings)), reg);
const int id = _isel->registerString(string);
- return Pointer(reg, id * sizeof(QV4::StringValue));
+ return Pointer(reg, id * sizeof(QV4::String*));
}
void Assembler::loadStringRef(RegisterID reg, const QString &string)
{
- loadPtr(Address(Assembler::ContextRegister, qOffsetOf(QV4::ExecutionContext::Data, compilationUnit)), reg);
- loadPtr(Address(reg, qOffsetOf(QV4::CompiledData::CompilationUnit, runtimeStrings)), reg);
const int id = _isel->registerString(string);
- loadPtr(Address(reg, id * sizeof(QV4::StringValue)), reg);
+ move(TrustedImm32(id), reg);
}
void Assembler::storeValue(QV4::Primitive value, IR::Expr *destination)
diff --git a/src/qml/jit/qv4assembler_p.h b/src/qml/jit/qv4assembler_p.h
index 87875f1120..a143690793 100644
--- a/src/qml/jit/qv4assembler_p.h
+++ b/src/qml/jit/qv4assembler_p.h
@@ -101,27 +101,27 @@ struct ExceptionCheck {
};
// push_catch and pop context methods shouldn't check for exceptions
template <>
-struct ExceptionCheck<QV4::ExecutionContext *(*)(QV4::ExecutionContext *)> {
+struct ExceptionCheck<void (*)(QV4::ExecutionEngine *)> {
enum { NeedsCheck = 0 };
};
template <typename A>
-struct ExceptionCheck<QV4::ExecutionContext *(*)(QV4::ExecutionContext *, A)> {
+struct ExceptionCheck<void (*)(A, QV4::NoThrowEngine)> {
enum { NeedsCheck = 0 };
};
template <>
-struct ExceptionCheck<QV4::ReturnedValue (*)(QV4::NoThrowContext *)> {
+struct ExceptionCheck<QV4::ReturnedValue (*)(QV4::NoThrowEngine *)> {
enum { NeedsCheck = 0 };
};
template <typename A>
-struct ExceptionCheck<QV4::ReturnedValue (*)(QV4::NoThrowContext *, A)> {
+struct ExceptionCheck<QV4::ReturnedValue (*)(QV4::NoThrowEngine *, A)> {
enum { NeedsCheck = 0 };
};
template <typename A, typename B>
-struct ExceptionCheck<QV4::ReturnedValue (*)(QV4::NoThrowContext *, A, B)> {
+struct ExceptionCheck<QV4::ReturnedValue (*)(QV4::NoThrowEngine *, A, B)> {
enum { NeedsCheck = 0 };
};
template <typename A, typename B, typename C>
-struct ExceptionCheck<void (*)(QV4::NoThrowContext *, A, B, C)> {
+struct ExceptionCheck<void (*)(QV4::NoThrowEngine *, A, B, C)> {
enum { NeedsCheck = 0 };
};
@@ -316,8 +316,8 @@ public:
{}
IR::Expr *value;
};
- struct PointerToString {
- explicit PointerToString(const QString &string) : string(string) {}
+ struct StringToIndex {
+ explicit StringToIndex(const QString &string) : string(string) {}
QString string;
};
struct Reference {
@@ -446,7 +446,7 @@ public:
loadArgumentInRegister(addr, dest, argumentNumber);
}
}
- void loadArgumentInRegister(PointerToString temp, RegisterID dest, int argumentNumber)
+ void loadArgumentInRegister(StringToIndex temp, RegisterID dest, int argumentNumber)
{
Q_UNUSED(argumentNumber);
loadStringRef(dest, temp.string);
@@ -662,7 +662,7 @@ public:
}
template <int StackSlot>
- void loadArgumentOnStack(PointerToString temp, int argumentNumber)
+ void loadArgumentOnStack(StringToIndex temp, int argumentNumber)
{
Q_UNUSED(argumentNumber);
loadStringRef(ScratchRegister, temp.string);
@@ -797,8 +797,7 @@ public:
const RegisterInformation &fpRegistersToSave);
void checkException() {
- loadPtr(Address(ContextRegister, qOffsetOf(QV4::ExecutionContext::Data, engine)), ScratchRegister);
- load32(Address(ScratchRegister, qOffsetOf(QV4::ExecutionEngine, hasException)), ScratchRegister);
+ load32(Address(EngineRegister, qOffsetOf(QV4::ExecutionEngine, hasException)), ScratchRegister);
Jump exceptionThrown = branch32(NotEqual, ScratchRegister, TrustedImm32(0));
if (catchBlock)
addPatch(catchBlock, exceptionThrown);
@@ -1226,7 +1225,8 @@ template <typename T> inline bool prepareCall(T &, Assembler *)
template <> inline bool prepareCall(RelativeCall &relativeCall, Assembler *as)
{
- as->loadPtr(Assembler::Address(Assembler::ContextRegister, qOffsetOf(QV4::ExecutionContext::Data, lookups)),
+ as->loadPtr(Assembler::Address(Assembler::EngineRegister, qOffsetOf(QV4::ExecutionEngine, current)), Assembler::ScratchRegister);
+ as->loadPtr(Assembler::Address(Assembler::ScratchRegister, qOffsetOf(QV4::Heap::ExecutionContext, lookups)),
relativeCall.addr.base);
return true;
}
@@ -1236,7 +1236,8 @@ template <> inline bool prepareCall(LookupCall &lookupCall, Assembler *as)
// IMPORTANT! See generateLookupCall in qv4isel_masm_p.h for details!
// same as prepareCall(RelativeCall ....) : load the table from the context
- as->loadPtr(Assembler::Address(Assembler::ContextRegister, qOffsetOf(QV4::ExecutionContext::Data, lookups)),
+ as->loadPtr(Assembler::Address(Assembler::EngineRegister, qOffsetOf(QV4::ExecutionEngine, current)), Assembler::ScratchRegister);
+ as->loadPtr(Assembler::Address(Assembler::ScratchRegister, qOffsetOf(QV4::Heap::ExecutionContext, lookups)),
lookupCall.addr.base);
// pre-calculate the indirect address for the lookupCall table:
if (lookupCall.addr.offset)
diff --git a/src/qml/jit/qv4binop.cpp b/src/qml/jit/qv4binop.cpp
index a2d4815cf2..0dce879fa1 100644
--- a/src/qml/jit/qv4binop.cpp
+++ b/src/qml/jit/qv4binop.cpp
@@ -125,7 +125,7 @@ void Binop::generate(IR::Expr *lhs, IR::Expr *rhs, IR::Expr *target)
Assembler::PointerToValue(rhs));
} else if (info.contextImplementation) {
as->generateFunctionCallImp(target, info.name, info.contextImplementation,
- Assembler::ContextRegister,
+ Assembler::EngineRegister,
Assembler::PointerToValue(lhs),
Assembler::PointerToValue(rhs));
} else {
diff --git a/src/qml/jit/qv4isel_masm.cpp b/src/qml/jit/qv4isel_masm.cpp
index f4a1ec5f69..64b65c6092 100644
--- a/src/qml/jit/qv4isel_masm.cpp
+++ b/src/qml/jit/qv4isel_masm.cpp
@@ -69,13 +69,14 @@ inline bool isPregOrConst(IR::Expr *e)
return e->asConst() != 0;
}
-class QIODevicePrintStream: public PrintStream
+class QIODevicePrintStream: public FilePrintStream
{
Q_DISABLE_COPY(QIODevicePrintStream)
public:
explicit QIODevicePrintStream(QIODevice *dest)
- : dest(dest)
+ : FilePrintStream(0)
+ , dest(dest)
, buf(4096, '0')
{
Q_ASSERT(dest);
@@ -115,8 +116,8 @@ static void printDisassembledOutputWithCalls(QByteArray processedOutput, const Q
continue;
processedOutput = processedOutput.insert(idx, QByteArrayLiteral(" ; call ") + it.value());
}
- fprintf(stderr, "%s\n", processedOutput.constData());
- fflush(stderr);
+
+ qDebug("%s", processedOutput.constData());
}
JSC::MacroAssemblerCodeRef Assembler::link(int *codeSize)
@@ -225,7 +226,7 @@ void InstructionSelection::run(int functionIndex)
// No register allocator available for this platform, or env. var was set, so:
opt.convertOutOfSSA();
ConvertTemps().toStackSlots(_function);
- IR::Optimizer::showMeTheCode(_function);
+ IR::Optimizer::showMeTheCode(_function, "After stack slot allocation");
calculateRegistersToSave(Assembler::getRegisterInfo()); // FIXME: this saves all registers. We can probably do with a subset: those that are not used by the register allocator.
}
QSet<IR::Jump *> removableJumps = opt.calculateOptionalJumps();
@@ -239,16 +240,36 @@ void InstructionSelection::run(int functionIndex)
_as->enterStandardStackFrame(regularRegistersToSave, fpRegistersToSave);
#ifdef ARGUMENTS_IN_REGISTERS
- _as->move(_as->registerForArgument(0), Assembler::ContextRegister);
+ _as->move(_as->registerForArgument(0), Assembler::EngineRegister);
#else
- _as->loadPtr(addressForArgument(0), Assembler::ContextRegister);
+ _as->loadPtr(addressForArgument(0), Assembler::EngineRegister);
#endif
const int locals = _as->stackLayout().calculateJSStackFrameSize();
- _as->loadPtr(Address(Assembler::ContextRegister, qOffsetOf(ExecutionContext::Data, engine)), Assembler::ScratchRegister);
- _as->loadPtr(Address(Assembler::ScratchRegister, qOffsetOf(ExecutionEngine, jsStackTop)), Assembler::LocalsRegister);
- _as->addPtr(Assembler::TrustedImm32(sizeof(QV4::Value)*locals), Assembler::LocalsRegister);
- _as->storePtr(Assembler::LocalsRegister, Address(Assembler::ScratchRegister, qOffsetOf(ExecutionEngine, jsStackTop)));
+ if (locals > 0) {
+ _as->loadPtr(Address(Assembler::EngineRegister, qOffsetOf(ExecutionEngine, jsStackTop)), Assembler::LocalsRegister);
+#ifdef VALUE_FITS_IN_REGISTER
+ _as->move(Assembler::TrustedImm64(0), Assembler::ReturnValueRegister);
+ _as->move(Assembler::TrustedImm32(locals), Assembler::ScratchRegister);
+ Assembler::Label loop = _as->label();
+ _as->store64(Assembler::ReturnValueRegister, Assembler::Address(Assembler::LocalsRegister));
+ _as->add64(Assembler::TrustedImm32(8), Assembler::LocalsRegister);
+ Assembler::Jump jump = _as->branchSub32(Assembler::NonZero, Assembler::TrustedImm32(1), Assembler::ScratchRegister);
+ jump.linkTo(loop, _as);
+#else
+ _as->move(Assembler::TrustedImm32(0), Assembler::ReturnValueRegister);
+ _as->move(Assembler::TrustedImm32(locals), Assembler::ScratchRegister);
+ Assembler::Label loop = _as->label();
+ _as->store32(Assembler::ReturnValueRegister, Assembler::Address(Assembler::LocalsRegister));
+ _as->add32(Assembler::TrustedImm32(4), Assembler::LocalsRegister);
+ _as->store32(Assembler::ReturnValueRegister, Assembler::Address(Assembler::LocalsRegister));
+ _as->add32(Assembler::TrustedImm32(4), Assembler::LocalsRegister);
+ Assembler::Jump jump = _as->branchSub32(Assembler::NonZero, Assembler::TrustedImm32(1), Assembler::ScratchRegister);
+ jump.linkTo(loop, _as);
+#endif
+ _as->storePtr(Assembler::LocalsRegister, Address(Assembler::EngineRegister, qOffsetOf(ExecutionEngine, jsStackTop)));
+ }
+
int lastLine = 0;
for (int i = 0, ei = _function->basicBlockCount(); i != ei; ++i) {
@@ -261,7 +282,8 @@ void InstructionSelection::run(int functionIndex)
foreach (IR::Stmt *s, _block->statements()) {
if (s->location.isValid()) {
if (int(s->location.startLine) != lastLine) {
- Assembler::Address lineAddr(Assembler::ContextRegister, qOffsetOf(QV4::ExecutionContext::Data, lineNumber));
+ _as->loadPtr(Address(Assembler::EngineRegister, qOffsetOf(QV4::ExecutionEngine, current)), Assembler::ScratchRegister);
+ Assembler::Address lineAddr(Assembler::ScratchRegister, qOffsetOf(QV4::ExecutionContext::Data, lineNumber));
_as->store32(Assembler::TrustedImm32(s->location.startLine), lineAddr);
lastLine = s->location.startLine;
}
@@ -307,13 +329,13 @@ void InstructionSelection::callBuiltinInvalid(IR::Name *func, IR::ExprList *args
if (useFastLookups && func->global) {
uint index = registerGlobalGetterLookup(*func->id);
generateFunctionCall(result, Runtime::callGlobalLookup,
- Assembler::ContextRegister,
+ Assembler::EngineRegister,
Assembler::TrustedImm32(index),
baseAddressForCallData());
} else {
generateFunctionCall(result, Runtime::callActivationProperty,
- Assembler::ContextRegister,
- Assembler::PointerToString(*func->id),
+ Assembler::EngineRegister,
+ Assembler::StringToIndex(*func->id),
baseAddressForCallData());
}
}
@@ -321,47 +343,47 @@ void InstructionSelection::callBuiltinInvalid(IR::Name *func, IR::ExprList *args
void InstructionSelection::callBuiltinTypeofMember(IR::Expr *base, const QString &name,
IR::Expr *result)
{
- generateFunctionCall(result, Runtime::typeofMember, Assembler::ContextRegister,
- Assembler::PointerToValue(base), Assembler::PointerToString(name));
+ generateFunctionCall(result, Runtime::typeofMember, Assembler::EngineRegister,
+ Assembler::PointerToValue(base), Assembler::StringToIndex(name));
}
void InstructionSelection::callBuiltinTypeofSubscript(IR::Expr *base, IR::Expr *index,
IR::Expr *result)
{
generateFunctionCall(result, Runtime::typeofElement,
- Assembler::ContextRegister,
+ Assembler::EngineRegister,
Assembler::PointerToValue(base), Assembler::PointerToValue(index));
}
void InstructionSelection::callBuiltinTypeofName(const QString &name, IR::Expr *result)
{
- generateFunctionCall(result, Runtime::typeofName, Assembler::ContextRegister,
- Assembler::PointerToString(name));
+ generateFunctionCall(result, Runtime::typeofName, Assembler::EngineRegister,
+ Assembler::StringToIndex(name));
}
void InstructionSelection::callBuiltinTypeofValue(IR::Expr *value, IR::Expr *result)
{
- generateFunctionCall(result, Runtime::typeofValue, Assembler::ContextRegister,
+ generateFunctionCall(result, Runtime::typeofValue, Assembler::EngineRegister,
Assembler::PointerToValue(value));
}
void InstructionSelection::callBuiltinDeleteMember(IR::Expr *base, const QString &name, IR::Expr *result)
{
- generateFunctionCall(result, Runtime::deleteMember, Assembler::ContextRegister,
- Assembler::Reference(base), Assembler::PointerToString(name));
+ generateFunctionCall(result, Runtime::deleteMember, Assembler::EngineRegister,
+ Assembler::Reference(base), Assembler::StringToIndex(name));
}
void InstructionSelection::callBuiltinDeleteSubscript(IR::Expr *base, IR::Expr *index,
IR::Expr *result)
{
- generateFunctionCall(result, Runtime::deleteElement, Assembler::ContextRegister,
+ generateFunctionCall(result, Runtime::deleteElement, Assembler::EngineRegister,
Assembler::Reference(base), Assembler::PointerToValue(index));
}
void InstructionSelection::callBuiltinDeleteName(const QString &name, IR::Expr *result)
{
- generateFunctionCall(result, Runtime::deleteName, Assembler::ContextRegister,
- Assembler::PointerToString(name));
+ generateFunctionCall(result, Runtime::deleteName, Assembler::EngineRegister,
+ Assembler::StringToIndex(name));
}
void InstructionSelection::callBuiltinDeleteValue(IR::Expr *result)
@@ -371,7 +393,7 @@ void InstructionSelection::callBuiltinDeleteValue(IR::Expr *result)
void InstructionSelection::callBuiltinThrow(IR::Expr *arg)
{
- generateFunctionCall(Assembler::ReturnValueRegister, Runtime::throwException, Assembler::ContextRegister,
+ generateFunctionCall(Assembler::ReturnValueRegister, Runtime::throwException, Assembler::EngineRegister,
Assembler::PointerToValue(arg));
}
@@ -382,13 +404,13 @@ void InstructionSelection::callBuiltinReThrow()
void InstructionSelection::callBuiltinUnwindException(IR::Expr *result)
{
- generateFunctionCall(result, Runtime::unwindException, Assembler::ContextRegister);
+ generateFunctionCall(result, Runtime::unwindException, Assembler::EngineRegister);
}
void InstructionSelection::callBuiltinPushCatchScope(const QString &exceptionName)
{
- generateFunctionCall(Assembler::ContextRegister, Runtime::pushCatchScope, Assembler::ContextRegister, Assembler::PointerToString(exceptionName));
+ generateFunctionCall(Assembler::Void, Runtime::pushCatchScope, Assembler::EngineRegister, Assembler::StringToIndex(exceptionName));
}
void InstructionSelection::callBuiltinForeachIteratorObject(IR::Expr *arg, IR::Expr *result)
@@ -396,7 +418,7 @@ void InstructionSelection::callBuiltinForeachIteratorObject(IR::Expr *arg, IR::E
Q_ASSERT(arg);
Q_ASSERT(result);
- generateFunctionCall(result, Runtime::foreachIterator, Assembler::ContextRegister, Assembler::PointerToValue(arg));
+ generateFunctionCall(result, Runtime::foreachIterator, Assembler::EngineRegister, Assembler::PointerToValue(arg));
}
void InstructionSelection::callBuiltinForeachNextPropertyname(IR::Expr *arg, IR::Expr *result)
@@ -411,18 +433,18 @@ void InstructionSelection::callBuiltinPushWithScope(IR::Expr *arg)
{
Q_ASSERT(arg);
- generateFunctionCall(Assembler::ContextRegister, Runtime::pushWithScope, Assembler::Reference(arg), Assembler::ContextRegister);
+ generateFunctionCall(Assembler::Void, Runtime::pushWithScope, Assembler::Reference(arg), Assembler::EngineRegister);
}
void InstructionSelection::callBuiltinPopScope()
{
- generateFunctionCall(Assembler::ContextRegister, Runtime::popScope, Assembler::ContextRegister);
+ generateFunctionCall(Assembler::Void, Runtime::popScope, Assembler::EngineRegister);
}
void InstructionSelection::callBuiltinDeclareVar(bool deletable, const QString &name)
{
- generateFunctionCall(Assembler::Void, Runtime::declareVar, Assembler::ContextRegister,
- Assembler::TrustedImm32(deletable), Assembler::PointerToString(name));
+ generateFunctionCall(Assembler::Void, Runtime::declareVar, Assembler::EngineRegister,
+ Assembler::TrustedImm32(deletable), Assembler::StringToIndex(name));
}
void InstructionSelection::callBuiltinDefineArray(IR::Expr *result, IR::ExprList *args)
@@ -430,7 +452,7 @@ void InstructionSelection::callBuiltinDefineArray(IR::Expr *result, IR::ExprList
Q_ASSERT(result);
int length = prepareVariableArguments(args);
- generateFunctionCall(result, Runtime::arrayLiteral, Assembler::ContextRegister,
+ generateFunctionCall(result, Runtime::arrayLiteral, Assembler::EngineRegister,
baseAddressForCallArguments(), Assembler::TrustedImm32(length));
}
@@ -510,19 +532,19 @@ void InstructionSelection::callBuiltinDefineObjectLiteral(IR::Expr *result, int
it = it->next;
}
- generateFunctionCall(result, Runtime::objectLiteral, Assembler::ContextRegister,
+ generateFunctionCall(result, Runtime::objectLiteral, Assembler::EngineRegister,
baseAddressForCallArguments(), Assembler::TrustedImm32(classId),
Assembler::TrustedImm32(arrayValueCount), Assembler::TrustedImm32(arrayGetterSetterCount | (needSparseArray << 30)));
}
void InstructionSelection::callBuiltinSetupArgumentObject(IR::Expr *result)
{
- generateFunctionCall(result, Runtime::setupArgumentsObject, Assembler::ContextRegister);
+ generateFunctionCall(result, Runtime::setupArgumentsObject, Assembler::EngineRegister);
}
void InstructionSelection::callBuiltinConvertThisToObject()
{
- generateFunctionCall(Assembler::Void, Runtime::convertThisToObject, Assembler::ContextRegister);
+ generateFunctionCall(Assembler::Void, Runtime::convertThisToObject, Assembler::EngineRegister);
}
void InstructionSelection::callValue(IR::Expr *value, IR::ExprList *args, IR::Expr *result)
@@ -531,18 +553,19 @@ void InstructionSelection::callValue(IR::Expr *value, IR::ExprList *args, IR::Ex
prepareCallData(args, 0);
if (value->asConst())
- generateFunctionCall(result, Runtime::callValue, Assembler::ContextRegister,
+ generateFunctionCall(result, Runtime::callValue, Assembler::EngineRegister,
Assembler::PointerToValue(value),
baseAddressForCallData());
else
- generateFunctionCall(result, Runtime::callValue, Assembler::ContextRegister,
+ generateFunctionCall(result, Runtime::callValue, Assembler::EngineRegister,
Assembler::Reference(value),
baseAddressForCallData());
}
void InstructionSelection::loadThisObject(IR::Expr *temp)
{
- _as->loadPtr(Address(Assembler::ContextRegister, qOffsetOf(ExecutionContext::Data, callData)), Assembler::ScratchRegister);
+ _as->loadPtr(Address(Assembler::EngineRegister, qOffsetOf(QV4::ExecutionEngine, current)), Assembler::ScratchRegister);
+ _as->loadPtr(Address(Assembler::ScratchRegister, qOffsetOf(ExecutionContext::Data, callData)), Assembler::ScratchRegister);
#if defined(VALUE_FITS_IN_REGISTER)
_as->load64(Pointer(Assembler::ScratchRegister, qOffsetOf(CallData, thisObject)),
Assembler::ReturnValueRegister);
@@ -554,27 +577,27 @@ void InstructionSelection::loadThisObject(IR::Expr *temp)
void InstructionSelection::loadQmlIdArray(IR::Expr *temp)
{
- generateFunctionCall(temp, Runtime::getQmlIdArray, Assembler::ContextRegister);
+ generateFunctionCall(temp, Runtime::getQmlIdArray, Assembler::EngineRegister);
}
void InstructionSelection::loadQmlImportedScripts(IR::Expr *temp)
{
- generateFunctionCall(temp, Runtime::getQmlImportedScripts, Assembler::ContextRegister);
+ generateFunctionCall(temp, Runtime::getQmlImportedScripts, Assembler::EngineRegister);
}
void InstructionSelection::loadQmlContextObject(IR::Expr *temp)
{
- generateFunctionCall(temp, Runtime::getQmlContextObject, Assembler::ContextRegister);
+ generateFunctionCall(temp, Runtime::getQmlContextObject, Assembler::EngineRegister);
}
void InstructionSelection::loadQmlScopeObject(IR::Expr *temp)
{
- generateFunctionCall(temp, Runtime::getQmlScopeObject, Assembler::ContextRegister);
+ generateFunctionCall(temp, Runtime::getQmlScopeObject, Assembler::EngineRegister);
}
void InstructionSelection::loadQmlSingleton(const QString &name, IR::Expr *temp)
{
- generateFunctionCall(temp, Runtime::getQmlSingleton, Assembler::ContextRegister, Assembler::PointerToString(name));
+ generateFunctionCall(temp, Runtime::getQmlSingleton, Assembler::EngineRegister, Assembler::StringToIndex(name));
}
void InstructionSelection::loadConst(IR::Const *sourceConst, IR::Expr *target)
@@ -621,52 +644,52 @@ void InstructionSelection::loadString(const QString &str, IR::Expr *target)
void InstructionSelection::loadRegexp(IR::RegExp *sourceRegexp, IR::Expr *target)
{
int id = registerRegExp(sourceRegexp);
- generateFunctionCall(target, Runtime::regexpLiteral, Assembler::ContextRegister, Assembler::TrustedImm32(id));
+ generateFunctionCall(target, Runtime::regexpLiteral, Assembler::EngineRegister, Assembler::TrustedImm32(id));
}
void InstructionSelection::getActivationProperty(const IR::Name *name, IR::Expr *target)
{
if (useFastLookups && name->global) {
uint index = registerGlobalGetterLookup(*name->id);
- generateLookupCall(target, index, qOffsetOf(QV4::Lookup, globalGetter), Assembler::ContextRegister, Assembler::Void);
+ generateLookupCall(target, index, qOffsetOf(QV4::Lookup, globalGetter), Assembler::EngineRegister, Assembler::Void);
return;
}
- generateFunctionCall(target, Runtime::getActivationProperty, Assembler::ContextRegister, Assembler::PointerToString(*name->id));
+ generateFunctionCall(target, Runtime::getActivationProperty, Assembler::EngineRegister, Assembler::StringToIndex(*name->id));
}
void InstructionSelection::setActivationProperty(IR::Expr *source, const QString &targetName)
{
// ### should use a lookup call here
generateFunctionCall(Assembler::Void, Runtime::setActivationProperty,
- Assembler::ContextRegister, Assembler::PointerToString(targetName), Assembler::PointerToValue(source));
+ Assembler::EngineRegister, Assembler::StringToIndex(targetName), Assembler::PointerToValue(source));
}
void InstructionSelection::initClosure(IR::Closure *closure, IR::Expr *target)
{
int id = closure->value;
- generateFunctionCall(target, Runtime::closure, Assembler::ContextRegister, Assembler::TrustedImm32(id));
+ generateFunctionCall(target, Runtime::closure, Assembler::EngineRegister, Assembler::TrustedImm32(id));
}
void InstructionSelection::getProperty(IR::Expr *base, const QString &name, IR::Expr *target)
{
if (useFastLookups) {
uint index = registerGetterLookup(name);
- generateLookupCall(target, index, qOffsetOf(QV4::Lookup, getter), Assembler::PointerToValue(base), Assembler::Void);
+ generateLookupCall(target, index, qOffsetOf(QV4::Lookup, getter), Assembler::EngineRegister, Assembler::PointerToValue(base), Assembler::Void);
} else {
- generateFunctionCall(target, Runtime::getProperty, Assembler::ContextRegister,
- Assembler::PointerToValue(base), Assembler::PointerToString(name));
+ generateFunctionCall(target, Runtime::getProperty, Assembler::EngineRegister,
+ Assembler::PointerToValue(base), Assembler::StringToIndex(name));
}
}
void InstructionSelection::getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, bool isSingleton, int attachedPropertiesId, IR::Expr *target)
{
if (attachedPropertiesId != 0)
- generateFunctionCall(target, Runtime::getQmlAttachedProperty, Assembler::ContextRegister, Assembler::TrustedImm32(attachedPropertiesId), Assembler::TrustedImm32(propertyIndex));
+ generateFunctionCall(target, Runtime::getQmlAttachedProperty, Assembler::EngineRegister, Assembler::TrustedImm32(attachedPropertiesId), Assembler::TrustedImm32(propertyIndex));
else if (isSingleton)
- generateFunctionCall(target, Runtime::getQmlSingletonQObjectProperty, Assembler::ContextRegister, Assembler::PointerToValue(base), Assembler::TrustedImm32(propertyIndex),
+ generateFunctionCall(target, Runtime::getQmlSingletonQObjectProperty, Assembler::EngineRegister, Assembler::PointerToValue(base), Assembler::TrustedImm32(propertyIndex),
Assembler::TrustedImm32(captureRequired));
else
- generateFunctionCall(target, Runtime::getQmlQObjectProperty, Assembler::ContextRegister, Assembler::PointerToValue(base), Assembler::TrustedImm32(propertyIndex),
+ generateFunctionCall(target, Runtime::getQmlQObjectProperty, Assembler::EngineRegister, Assembler::PointerToValue(base), Assembler::TrustedImm32(propertyIndex),
Assembler::TrustedImm32(captureRequired));
}
@@ -676,18 +699,19 @@ void InstructionSelection::setProperty(IR::Expr *source, IR::Expr *targetBase,
if (useFastLookups) {
uint index = registerSetterLookup(targetName);
generateLookupCall(Assembler::Void, index, qOffsetOf(QV4::Lookup, setter),
+ Assembler::EngineRegister,
Assembler::PointerToValue(targetBase),
Assembler::PointerToValue(source));
} else {
- generateFunctionCall(Assembler::Void, Runtime::setProperty, Assembler::ContextRegister,
- Assembler::PointerToValue(targetBase), Assembler::PointerToString(targetName),
+ generateFunctionCall(Assembler::Void, Runtime::setProperty, Assembler::EngineRegister,
+ Assembler::PointerToValue(targetBase), Assembler::StringToIndex(targetName),
Assembler::PointerToValue(source));
}
}
void InstructionSelection::setQObjectProperty(IR::Expr *source, IR::Expr *targetBase, int propertyIndex)
{
- generateFunctionCall(Assembler::Void, Runtime::setQmlQObjectProperty, Assembler::ContextRegister, Assembler::PointerToValue(targetBase),
+ generateFunctionCall(Assembler::Void, Runtime::setQmlQObjectProperty, Assembler::EngineRegister, Assembler::PointerToValue(targetBase),
Assembler::TrustedImm32(propertyIndex), Assembler::PointerToValue(source));
}
@@ -701,7 +725,7 @@ void InstructionSelection::getElement(IR::Expr *base, IR::Expr *index, IR::Expr
return;
}
- generateFunctionCall(target, Runtime::getElement, Assembler::ContextRegister,
+ generateFunctionCall(target, Runtime::getElement, Assembler::EngineRegister,
Assembler::PointerToValue(base), Assembler::PointerToValue(index));
}
@@ -714,7 +738,7 @@ void InstructionSelection::setElement(IR::Expr *source, IR::Expr *targetBase, IR
Assembler::PointerToValue(source));
return;
}
- generateFunctionCall(Assembler::Void, Runtime::setElement, Assembler::ContextRegister,
+ generateFunctionCall(Assembler::Void, Runtime::setElement, Assembler::EngineRegister,
Assembler::PointerToValue(targetBase), Assembler::PointerToValue(targetIndex),
Assembler::PointerToValue(source));
}
@@ -888,12 +912,12 @@ void InstructionSelection::callProperty(IR::Expr *base, const QString &name, IR:
if (useFastLookups) {
uint index = registerGetterLookup(name);
generateFunctionCall(result, Runtime::callPropertyLookup,
- Assembler::ContextRegister,
+ Assembler::EngineRegister,
Assembler::TrustedImm32(index),
baseAddressForCallData());
} else {
- generateFunctionCall(result, Runtime::callProperty, Assembler::ContextRegister,
- Assembler::PointerToString(name),
+ generateFunctionCall(result, Runtime::callProperty, Assembler::EngineRegister,
+ Assembler::StringToIndex(name),
baseAddressForCallData());
}
}
@@ -904,7 +928,7 @@ void InstructionSelection::callSubscript(IR::Expr *base, IR::Expr *index, IR::Ex
Q_ASSERT(base != 0);
prepareCallData(args, base);
- generateFunctionCall(result, Runtime::callElement, Assembler::ContextRegister,
+ generateFunctionCall(result, Runtime::callElement, Assembler::EngineRegister,
Assembler::PointerToValue(index),
baseAddressForCallData());
}
@@ -1214,14 +1238,14 @@ void InstructionSelection::constructActivationProperty(IR::Name *func, IR::ExprL
if (useFastLookups && func->global) {
uint index = registerGlobalGetterLookup(*func->id);
generateFunctionCall(result, Runtime::constructGlobalLookup,
- Assembler::ContextRegister,
+ Assembler::EngineRegister,
Assembler::TrustedImm32(index), baseAddressForCallData());
return;
}
generateFunctionCall(result, Runtime::constructActivationProperty,
- Assembler::ContextRegister,
- Assembler::PointerToString(*func->id),
+ Assembler::EngineRegister,
+ Assembler::StringToIndex(*func->id),
baseAddressForCallData());
}
@@ -1232,14 +1256,14 @@ void InstructionSelection::constructProperty(IR::Expr *base, const QString &name
if (useFastLookups) {
uint index = registerGetterLookup(name);
generateFunctionCall(result, Runtime::constructPropertyLookup,
- Assembler::ContextRegister,
+ Assembler::EngineRegister,
Assembler::TrustedImm32(index),
baseAddressForCallData());
return;
}
- generateFunctionCall(result, Runtime::constructProperty, Assembler::ContextRegister,
- Assembler::PointerToString(name),
+ generateFunctionCall(result, Runtime::constructProperty, Assembler::EngineRegister,
+ Assembler::StringToIndex(name),
baseAddressForCallData());
}
@@ -1249,7 +1273,7 @@ void InstructionSelection::constructValue(IR::Expr *value, IR::ExprList *args, I
prepareCallData(args, 0);
generateFunctionCall(result, Runtime::constructValue,
- Assembler::ContextRegister,
+ Assembler::EngineRegister,
Assembler::Reference(value),
baseAddressForCallData());
}
@@ -1340,7 +1364,7 @@ void InstructionSelection::visitCJump(IR::CJump *s)
// elimination (which isn't there either) would remove the whole else block.
if (opContext)
_as->generateFunctionCallImp(Assembler::ReturnValueRegister, opName, opContext,
- Assembler::ContextRegister,
+ Assembler::EngineRegister,
Assembler::PointerToValue(b->left),
Assembler::PointerToValue(b->right));
else
@@ -1466,7 +1490,8 @@ void InstructionSelection::visitRet(IR::Ret *s)
const int locals = _as->stackLayout().calculateJSStackFrameSize();
_as->subPtr(Assembler::TrustedImm32(sizeof(QV4::Value)*locals), Assembler::LocalsRegister);
- _as->loadPtr(Address(Assembler::ContextRegister, qOffsetOf(ExecutionContext::Data, engine)), Assembler::ScratchRegister);
+ _as->loadPtr(Address(Assembler::EngineRegister, qOffsetOf(QV4::ExecutionEngine, current)), Assembler::ScratchRegister);
+ _as->loadPtr(Address(Assembler::ScratchRegister, qOffsetOf(ExecutionContext::Data, engine)), Assembler::ScratchRegister);
_as->storePtr(Assembler::LocalsRegister, Address(Assembler::ScratchRegister, qOffsetOf(ExecutionEngine, jsStackTop)));
_as->leaveStandardStackFrame(regularRegistersToSave, fpRegistersToSave);
diff --git a/src/qml/jit/qv4regalloc.cpp b/src/qml/jit/qv4regalloc.cpp
index e69522404d..64cbdf9f3b 100644
--- a/src/qml/jit/qv4regalloc.cpp
+++ b/src/qml/jit/qv4regalloc.cpp
@@ -31,10 +31,15 @@
**
****************************************************************************/
+#include <QtCore/QBuffer>
+#include <QtCore/QDebug>
#include "qv4regalloc_p.h"
#include <private/qv4value_inl_p.h>
#include <algorithm>
+#if defined(Q_CC_MINGW)
+# include <malloc.h>
+#endif
namespace {
enum { DebugRegAlloc = 0 };
@@ -223,7 +228,9 @@ public:
if (!DebugRegAlloc)
return;
- QTextStream qout(stdout, QIODevice::WriteOnly);
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream qout(&buf);
IRPrinterWithPositions printer(&qout, _lifeTimeIntervals);
qout << "RegAllocInfo:" << endl << "Defs/uses:" << endl;
@@ -264,6 +271,7 @@ public:
}
qout << endl;
}
+ qDebug("%s", buf.data().constData());
}
protected: // IRDecoder
@@ -823,8 +831,11 @@ public:
void run() {
renumber();
if (DebugRegAlloc) {
- QTextStream qout(stdout, QIODevice::WriteOnly);
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream qout(&buf);
IRPrinterWithPositions(&qout, _intervals).print(_function);
+ qDebug("%s", buf.data().constData());
}
resolve();
}
@@ -842,12 +853,14 @@ private:
void renumber()
{
+ QVector<Stmt *> newStatements;
+
foreach (BasicBlock *bb, _function->basicBlocks()) {
_currentStmt = 0;
QVector<Stmt *> statements = bb->statements();
- QVector<Stmt *> newStatements;
newStatements.reserve(bb->statements().size() + 7);
+ newStatements.erase(newStatements.begin(), newStatements.end());
cleanOldIntervals(_intervals->startPosition(bb));
addNewIntervals(_intervals->startPosition(bb));
@@ -876,7 +889,9 @@ private:
_liveAtEnd[bb] = _intervalForTemp.values();
if (DebugRegAlloc) {
- QTextStream os(stdout, QIODevice::WriteOnly);
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream os(&buf);
os << "Intervals live at the start of L" << bb->index() << ":" << endl;
if (_liveAtStart[bb].isEmpty())
os << "\t(none)" << endl;
@@ -893,6 +908,7 @@ private:
i->dump(os);
os << endl;
}
+ qDebug("%s", buf.data().constData());
}
bb->setStatements(newStatements);
@@ -967,11 +983,13 @@ private:
{
if (DebugRegAlloc) {
qDebug() << "Resolving edge" << predecessor->index() << "->" << successor->index();
- QTextStream qout(stdout, QIODevice::WriteOnly);
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream qout(&buf);
IRPrinterWithPositions printer(&qout, _intervals);
printer.print(predecessor);
printer.print(successor);
- qout.flush();
+ qDebug("%s", buf.data().constData());
}
MoveMapping mapping;
@@ -1088,11 +1106,13 @@ private:
if (DebugRegAlloc) {
qDebug() << ".. done, result:";
- QTextStream qout(stdout, QIODevice::WriteOnly);
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream qout(&buf);
IRPrinterWithPositions printer(&qout, _intervals);
printer.print(predecessor);
printer.print(successor);
- qout.flush();
+ qDebug("%s", buf.data().constData());
}
}
@@ -1260,7 +1280,9 @@ void RegisterAllocator::run(IR::Function *function, const Optimizer &opt)
_info->collect(function, _lifeTimeIntervals);
if (DebugRegAlloc) {
- QTextStream qout(stdout, QIODevice::WriteOnly);
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream qout(&buf);
qout << "Ranges:" << endl;
QVector<LifeTimeInterval *> intervals = _unhandled;
std::reverse(intervals.begin(), intervals.end());
@@ -1268,13 +1290,13 @@ void RegisterAllocator::run(IR::Function *function, const Optimizer &opt)
r->dump(qout);
qout << endl;
}
+ qDebug("%s", buf.data().constData());
_info->dump();
- }
- if (DebugRegAlloc) {
qDebug() << "*** Before register allocation:";
- QTextStream qout(stdout, QIODevice::WriteOnly);
+ buf.setData(QByteArray());
IRPrinterWithPositions(&qout, _lifeTimeIntervals).print(function);
+ qDebug("%s", buf.data().constData());
}
prepareRanges();
@@ -1293,8 +1315,11 @@ void RegisterAllocator::run(IR::Function *function, const Optimizer &opt)
static bool showCode = !qgetenv("QV4_SHOW_IR").isNull();
if (showCode) {
- QTextStream qout(stdout, QIODevice::WriteOnly);
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream qout(&buf);
IRPrinterWithRegisters(&qout, _lifeTimeIntervals, _registerInformation).print(function);
+ qDebug("%s", buf.data().constData());
}
}
@@ -1675,10 +1700,12 @@ void RegisterAllocator::allocateBlockedReg(LifeTimeInterval &current)
// spill interval that currently block reg
if (DebugRegAlloc) {
- QTextStream out(stderr, QIODevice::WriteOnly);
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream out(&buf);
out << "*** spilling intervals that block reg " <<reg<< " for interval ";
current.dump(out);
- out << endl;
+ qDebug("%s", buf.data().constData());
}
current.setReg(reg);
_lastAssignedRegister[current.temp().index] = reg;
@@ -1701,8 +1728,7 @@ void RegisterAllocator::allocateBlockedReg(LifeTimeInterval &current)
int ni = nextIntersection(current, *fixedRegRange);
if (ni != -1) {
if (DebugRegAlloc) {
- QTextStream out(stderr, QIODevice::WriteOnly);
- out << "***-- current range intersects with a fixed reg use at " << ni << ", so splitting it." << endl;
+ qDebug("***-- current range intersects with a fixed reg use at %d, so splitting it.", ni);
}
// current does overlap with a fixed interval, so split current before that intersection.
split(current, ni, true);
@@ -1767,8 +1793,14 @@ void RegisterAllocator::split(LifeTimeInterval &current, int beforePosition,
Q_ASSERT(!current.isFixedInterval());
if (DebugRegAlloc) {
- QTextStream out(stderr, QIODevice::WriteOnly);
- out << "***** split request for range ";current.dump(out);out<<" before position "<<beforePosition<<" and skipOptionalRegisterUses = "<<skipOptionalRegisterUses<<endl;
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream out(&buf);
+ out << "***** split request for range ";
+ current.dump(out);
+ out << " before position " << beforePosition
+ << " and skipOptionalRegisterUses = " << skipOptionalRegisterUses << endl;
+ qDebug("%s", buf.data().constData());
}
assignSpillSlot(current.temp(), current.start(), current.end());
@@ -1796,10 +1828,17 @@ void RegisterAllocator::split(LifeTimeInterval &current, int beforePosition,
LifeTimeInterval newInterval = current.split(lastUse, nextUse);
if (DebugRegAlloc) {
- QTextStream out(stderr, QIODevice::WriteOnly);
- out << "***** last use = "<<lastUse<<", nextUse = " << nextUse<<endl;
- out << "***** new interval: "; newInterval.dump(out); out << endl;
- out << "***** preceding interval: "; current.dump(out); out << endl;
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream out(&buf);
+ out << "***** last use = " << lastUse << ", nextUse = " << nextUse << endl;
+ out << "***** new interval: ";
+ newInterval.dump(out);
+ out << endl;
+ out << "***** preceding interval: ";
+ current.dump(out);
+ out << endl;
+ qDebug("%s", buf.data().constData());
}
if (newInterval.isValid()) {
if (current.reg() != LifeTimeInterval::InvalidRegister)
@@ -1848,7 +1887,9 @@ void RegisterAllocator::assignSpillSlot(const Temp &t, int startPos, int endPos)
void RegisterAllocator::dump(IR::Function *function) const
{
- QTextStream qout(stdout, QIODevice::WriteOnly);
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream qout(&buf);
IRPrinterWithPositions printer(&qout, _lifeTimeIntervals);
qout << "Ranges:" << endl;
@@ -1865,6 +1906,7 @@ void RegisterAllocator::dump(IR::Function *function) const
qout << "\t%" << i << " -> " << _assignedSpillSlots[i] << endl;
printer.print(function);
+ qDebug("%s", buf.data().constData());
}
// References:
diff --git a/src/qml/jit/qv4targetplatform_p.h b/src/qml/jit/qv4targetplatform_p.h
index 17098d6aad..de132cc709 100644
--- a/src/qml/jit/qv4targetplatform_p.h
+++ b/src/qml/jit/qv4targetplatform_p.h
@@ -71,7 +71,7 @@ public:
static const JSC::MacroAssembler::RegisterID StackFrameRegister = JSC::X86Registers::ebp;
static const JSC::MacroAssembler::RegisterID StackPointerRegister = JSC::X86Registers::esp;
static const JSC::MacroAssembler::RegisterID LocalsRegister = JSC::X86Registers::edi;
- static const JSC::MacroAssembler::RegisterID ContextRegister = JSC::X86Registers::esi;
+ static const JSC::MacroAssembler::RegisterID EngineRegister = JSC::X86Registers::esi;
static const JSC::MacroAssembler::RegisterID ReturnValueRegister = JSC::X86Registers::eax;
static const JSC::MacroAssembler::RegisterID ScratchRegister = JSC::X86Registers::ecx;
static const JSC::MacroAssembler::FPRegisterID FPGpr0 = JSC::X86Registers::xmm0;
@@ -140,7 +140,7 @@ public:
static const JSC::MacroAssembler::RegisterID StackFrameRegister = JSC::X86Registers::ebp;
static const JSC::MacroAssembler::RegisterID StackPointerRegister = JSC::X86Registers::esp;
static const JSC::MacroAssembler::RegisterID LocalsRegister = JSC::X86Registers::r12;
- static const JSC::MacroAssembler::RegisterID ContextRegister = JSC::X86Registers::r14;
+ static const JSC::MacroAssembler::RegisterID EngineRegister = JSC::X86Registers::r14;
static const JSC::MacroAssembler::RegisterID ReturnValueRegister = JSC::X86Registers::eax;
static const JSC::MacroAssembler::RegisterID ScratchRegister = JSC::X86Registers::r10;
static const JSC::MacroAssembler::FPRegisterID FPGpr0 = JSC::X86Registers::xmm0;
@@ -205,7 +205,7 @@ public:
static const JSC::MacroAssembler::RegisterID StackFrameRegister = JSC::X86Registers::ebp;
static const JSC::MacroAssembler::RegisterID StackPointerRegister = JSC::X86Registers::esp;
static const JSC::MacroAssembler::RegisterID LocalsRegister = JSC::X86Registers::r12;
- static const JSC::MacroAssembler::RegisterID ContextRegister = JSC::X86Registers::r14;
+ static const JSC::MacroAssembler::RegisterID EngineRegister = JSC::X86Registers::r14;
static const JSC::MacroAssembler::RegisterID ReturnValueRegister = JSC::X86Registers::eax;
static const JSC::MacroAssembler::RegisterID ScratchRegister = JSC::X86Registers::r10;
static const JSC::MacroAssembler::FPRegisterID FPGpr0 = JSC::X86Registers::xmm0;
@@ -276,8 +276,8 @@ public:
static const JSC::MacroAssembler::RegisterID LocalsRegister = JSC::ARMRegisters::r7;
#endif
static const JSC::MacroAssembler::RegisterID StackPointerRegister = JSC::ARMRegisters::r13;
- static const JSC::MacroAssembler::RegisterID ScratchRegister = JSC::ARMRegisters::r6;
- static const JSC::MacroAssembler::RegisterID ContextRegister = JSC::ARMRegisters::r5;
+ static const JSC::MacroAssembler::RegisterID ScratchRegister = JSC::ARMRegisters::r5;
+ static const JSC::MacroAssembler::RegisterID EngineRegister = JSC::ARMRegisters::r10;
static const JSC::MacroAssembler::RegisterID ReturnValueRegister = JSC::ARMRegisters::r0;
static const JSC::MacroAssembler::FPRegisterID FPGpr0 = JSC::ARMRegisters::d0;
static const JSC::MacroAssembler::FPRegisterID FPGpr1 = JSC::ARMRegisters::d1;
diff --git a/src/qml/jsapi/qjsengine.cpp b/src/qml/jsapi/qjsengine.cpp
index d7f45b56e0..831287d0b3 100644
--- a/src/qml/jsapi/qjsengine.cpp
+++ b/src/qml/jsapi/qjsengine.cpp
@@ -165,7 +165,8 @@ QT_BEGIN_NAMESPACE
\l{ECMA-262}, Section 15.1.
*/
QJSEngine::QJSEngine()
- : d(new QV8Engine(this))
+ : QObject(*new QJSEnginePrivate, 0)
+ , d(new QV8Engine(this))
{
}
@@ -177,7 +178,7 @@ QJSEngine::QJSEngine()
*/
QJSEngine::QJSEngine(QObject *parent)
- : QObject(parent)
+ : QObject(*new QJSEnginePrivate, parent)
, d(new QV8Engine(this))
{
}
@@ -254,7 +255,7 @@ void QJSEngine::installTranslatorFunctions(const QJSValue &object)
QJSValuePrivate *vp = QJSValuePrivate::get(object);
QV4::ScopedObject obj(scope, vp->getValue(v4));
if (!obj)
- obj = v4->globalObject;
+ obj = v4->globalObject();
#ifndef QT_NO_TRANSLATION
obj->defineDefaultProperty(QStringLiteral("qsTranslate"), QV4::GlobalExtensions::method_qsTranslate);
obj->defineDefaultProperty(QStringLiteral("QT_TRANSLATE_NOOP"), QV4::GlobalExtensions::method_qsTranslateNoOp);
@@ -264,8 +265,8 @@ void QJSEngine::installTranslatorFunctions(const QJSValue &object)
obj->defineDefaultProperty(QStringLiteral("QT_TRID_NOOP"), QV4::GlobalExtensions::method_qsTrIdNoOp);
// string prototype extension
- v4->stringObjectClass->prototype->defineDefaultProperty(QStringLiteral("arg"),
- QV4::GlobalExtensions::method_string_arg);
+ v4->stringPrototype.asObject()->defineDefaultProperty(QStringLiteral("arg"),
+ QV4::GlobalExtensions::method_string_arg);
#endif
}
@@ -301,8 +302,8 @@ QJSValue QJSEngine::evaluate(const QString& program, const QString& fileName, in
{
QV4::ExecutionEngine *v4 = d->m_v4Engine;
QV4::Scope scope(v4);
- QV4::ExecutionContext *ctx = v4->currentContext();
- if (ctx != v4->rootContext)
+ QV4::ScopedContext ctx(scope, v4->currentContext());
+ if (ctx->d() != v4->rootContext())
ctx = v4->pushGlobalContext();
QV4::ScopedValue result(scope);
@@ -313,8 +314,8 @@ QJSValue QJSEngine::evaluate(const QString& program, const QString& fileName, in
if (!scope.engine->hasException)
result = script.run();
if (scope.engine->hasException)
- result = ctx->catchException();
- if (ctx != v4->rootContext)
+ result = v4->catchException();
+ if (ctx->d() != v4->rootContext())
v4->popContext();
return new QJSValuePrivate(v4, result);
}
@@ -342,7 +343,7 @@ QJSValue QJSEngine::newObject()
QJSValue QJSEngine::newArray(uint length)
{
QV4::Scope scope(d->m_v4Engine);
- QV4::Scoped<QV4::ArrayObject> array(scope, d->m_v4Engine->newArrayObject());
+ QV4::ScopedArrayObject array(scope, d->m_v4Engine->newArrayObject());
if (length < 0x1000)
array->arrayReserve(length);
array->setArrayLengthUnchecked(length);
@@ -397,7 +398,7 @@ QJSValue QJSEngine::globalObject() const
{
Q_D(const QJSEngine);
QV4::Scope scope(d->m_v4Engine);
- QV4::ScopedValue v(scope, d->m_v4Engine->globalObject);
+ QV4::ScopedValue v(scope, d->m_v4Engine->globalObject());
return new QJSValuePrivate(d->m_v4Engine, v);
}
@@ -409,7 +410,7 @@ QJSValue QJSEngine::create(int type, const void *ptr)
{
Q_D(QJSEngine);
QV4::Scope scope(d->m_v4Engine);
- QV4::ScopedValue v(scope, d->metaTypeToJS(type, ptr));
+ QV4::ScopedValue v(scope, scope.engine->metaTypeToJS(type, ptr));
return new QJSValuePrivate(d->m_v4Engine, v);
}
@@ -420,11 +421,10 @@ QJSValue QJSEngine::create(int type, const void *ptr)
bool QJSEngine::convertV2(const QJSValue &value, int type, void *ptr)
{
QJSValuePrivate *vp = QJSValuePrivate::get(value);
- QV8Engine *engine = vp->engine ? vp->engine->v8Engine : 0;
- if (engine) {
- QV4::Scope scope(engine->m_v4Engine);
- QV4::ScopedValue v(scope, vp->getValue(engine->m_v4Engine));
- return engine->metaTypeFromJS(v, type, ptr);
+ if (vp->engine) {
+ QV4::Scope scope(vp->engine);
+ QV4::ScopedValue v(scope, vp->getValue(scope.engine));
+ return scope.engine->metaTypeFromJS(v, type, ptr);
} else if (vp->value.isEmpty()) {
if (vp->unboundData.userType() == QMetaType::QString) {
QString string = vp->unboundData.toString();
@@ -529,7 +529,7 @@ bool QJSEngine::convertV2(const QJSValue &value, int type, void *ptr)
Creates a QJSValue with the given \a value.
- \sa fromScriptValue()
+ \sa fromScriptValue(), newVariant()
*/
/*! \fn T QJSEngine::fromScriptValue(const QJSValue &value)
@@ -539,6 +539,50 @@ bool QJSEngine::convertV2(const QJSValue &value, int type, void *ptr)
\sa toScriptValue()
*/
+
+QJSEnginePrivate *QJSEnginePrivate::get(QV4::ExecutionEngine *e)
+{
+ return e->v8Engine->publicEngine()->d_func();
+}
+
+QJSEnginePrivate::~QJSEnginePrivate()
+{
+ for (QHash<const QMetaObject *, QQmlPropertyCache *>::Iterator iter = propertyCache.begin(); iter != propertyCache.end(); ++iter)
+ (*iter)->release();
+}
+
+QQmlPropertyCache *QJSEnginePrivate::createCache(const QMetaObject *mo)
+{
+ if (!mo->superClass()) {
+ QQmlPropertyCache *rv = new QQmlPropertyCache(q_func(), mo);
+ propertyCache.insert(mo, rv);
+ return rv;
+ } else {
+ QQmlPropertyCache *super = cache(mo->superClass());
+ QQmlPropertyCache *rv = super->copyAndAppend(mo);
+ propertyCache.insert(mo, rv);
+ return rv;
+ }
+}
+
+/*!
+ \since 5.5
+ \relates QJSEngine
+
+ Returns the QJSEngine associated with \a object, if any.
+
+ This function is useful if you have exposed a QObject to the JavaScript environment
+ and later in your program would like to regain access. It does not require you to
+ keep the wrapper around that was returned from QJSEngine::newQObject().
+ */
+QJSEngine *qjsEngine(const QObject *object)
+{
+ QQmlData *data = QQmlData::get(object, false);
+ if (!data || data->jsWrapper.isNullOrUndefined())
+ return 0;
+ return data->jsWrapper.engine()->jsEngine();
+}
+
QT_END_NAMESPACE
#include "moc_qjsengine.cpp"
diff --git a/src/qml/jsapi/qjsengine.h b/src/qml/jsapi/qjsengine.h
index bddc6f133c..f24808f503 100644
--- a/src/qml/jsapi/qjsengine.h
+++ b/src/qml/jsapi/qjsengine.h
@@ -127,6 +127,8 @@ inline QVariant qjsvalue_cast<QVariant>(const QJSValue &value)
return value.toVariant();
}
+Q_QML_EXPORT QJSEngine *qjsEngine(const QObject *);
+
QT_END_NAMESPACE
#endif // QJSENGINE_H
diff --git a/src/qml/jsapi/qjsengine_p.h b/src/qml/jsapi/qjsengine_p.h
index 654d0dee56..09fa24e1c3 100644
--- a/src/qml/jsapi/qjsengine_p.h
+++ b/src/qml/jsapi/qjsengine_p.h
@@ -46,22 +46,150 @@
//
#include <QtCore/private/qobject_p.h>
+#include <QtCore/qmutex.h>
#include "qjsengine.h"
-
+#include "private/qtqmlglobal_p.h"
QT_BEGIN_NAMESPACE
+class QQmlPropertyCache;
+
+namespace QV4 {
+struct ExecutionEngine;
+}
-class QJSEnginePrivate : public QObjectPrivate
+class Q_QML_PRIVATE_EXPORT QJSEnginePrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QJSEngine)
public:
static QJSEnginePrivate* get(QJSEngine*e) { return e->d_func(); }
+ static const QJSEnginePrivate* get(const QJSEngine*e) { return e->d_func(); }
+ static QJSEnginePrivate* get(QV4::ExecutionEngine *e);
+
+ QJSEnginePrivate() : mutex(QMutex::Recursive) {}
+ ~QJSEnginePrivate();
+
+ // Locker locks the QQmlEnginePrivate data structures for read and write, if necessary.
+ // Currently, locking is only necessary if the threaded loader is running concurrently. If it is
+ // either idle, or is running with the main thread blocked, no locking is necessary. This way
+ // we only pay for locking when we have to.
+ // Consequently, this class should only be used to protect simple accesses or modifications of the
+ // QQmlEnginePrivate structures or operations that can be guaranteed not to start activity
+ // on the loader thread.
+ // The Locker API is identical to QMutexLocker. Locker reuses the QQmlEnginePrivate::mutex
+ // QMutex instance and multiple Lockers are recursive in the same thread.
+ class Locker
+ {
+ public:
+ inline Locker(const QJSEngine *);
+ inline Locker(const QJSEnginePrivate *);
+ inline ~Locker();
+
+ inline void unlock();
+ inline void relock();
+
+ private:
+ const QJSEnginePrivate *m_ep;
+ quint32 m_locked:1;
+ };
+
+ // Shared by QQmlEngine
+ mutable QMutex mutex;
+
- QJSEnginePrivate() {}
+ // These methods may be called from the QML loader thread
+ inline QQmlPropertyCache *cache(QObject *obj);
+ inline QQmlPropertyCache *cache(const QMetaObject *);
+
+private:
+ // Must be called locked
+ QQmlPropertyCache *createCache(const QMetaObject *);
+
+ // These members must be protected by a QJSEnginePrivate::Locker as they are required by
+ // the threaded loader. Only access them through their respective accessor methods.
+ QHash<const QMetaObject *, QQmlPropertyCache *> propertyCache;
};
+QJSEnginePrivate::Locker::Locker(const QJSEngine *e)
+: m_ep(QJSEnginePrivate::get(e))
+{
+ relock();
+}
+
+QJSEnginePrivate::Locker::Locker(const QJSEnginePrivate *e)
+: m_ep(e), m_locked(false)
+{
+ relock();
+}
+
+QJSEnginePrivate::Locker::~Locker()
+{
+ unlock();
+}
+
+void QJSEnginePrivate::Locker::unlock()
+{
+ if (m_locked) {
+ m_ep->mutex.unlock();
+ m_locked = false;
+ }
+}
+
+void QJSEnginePrivate::Locker::relock()
+{
+ Q_ASSERT(!m_locked);
+ m_ep->mutex.lock();
+ m_locked = true;
+}
+
+/*!
+Returns a QQmlPropertyCache for \a obj if one is available.
+
+If \a obj is null, being deleted or contains a dynamic meta object 0
+is returned.
+
+The returned cache is not referenced, so if it is to be stored, call addref().
+
+XXX thread There is a potential future race condition in this and all the cache()
+functions. As the QQmlPropertyCache is returned unreferenced, when called
+from the loader thread, it is possible that the cache will have been dereferenced
+and deleted before the loader thread has a chance to use or reference it. This
+can't currently happen as the cache holds a reference to the
+QQmlPropertyCache until the QQmlEngine is destroyed.
+*/
+QQmlPropertyCache *QJSEnginePrivate::cache(QObject *obj)
+{
+ if (!obj || QObjectPrivate::get(obj)->metaObject || QObjectPrivate::get(obj)->wasDeleted)
+ return 0;
+
+ Locker locker(this);
+ const QMetaObject *mo = obj->metaObject();
+ QQmlPropertyCache *rv = propertyCache.value(mo);
+ if (!rv) rv = createCache(mo);
+ return rv;
+}
+
+/*!
+Returns a QQmlPropertyCache for \a metaObject.
+
+As the cache is persisted for the life of the engine, \a metaObject must be
+a static "compile time" meta-object, or a meta-object that is otherwise known to
+exist for the lifetime of the QQmlEngine.
+
+The returned cache is not referenced, so if it is to be stored, call addref().
+*/
+QQmlPropertyCache *QJSEnginePrivate::cache(const QMetaObject *metaObject)
+{
+ Q_ASSERT(metaObject);
+
+ Locker locker(this);
+ QQmlPropertyCache *rv = propertyCache.value(metaObject);
+ if (!rv) rv = createCache(metaObject);
+ return rv;
+}
+
+
QT_END_NAMESPACE
#endif // QJSENGINE_P_H
diff --git a/src/qml/jsapi/qjsvalue.cpp b/src/qml/jsapi/qjsvalue.cpp
index 47a764e641..d888ea3535 100644
--- a/src/qml/jsapi/qjsvalue.cpp
+++ b/src/qml/jsapi/qjsvalue.cpp
@@ -58,7 +58,7 @@ QV4::ReturnedValue QJSValuePrivate::getValue(QV4::ExecutionEngine *e)
}
if (value.isEmpty()) {
- value = QV4::Encode(engine->v8Engine->fromVariant(unboundData));
+ value = QV4::Encode(e->fromVariant(unboundData));
PersistentValuePrivate **listRoot = &engine->memoryManager->m_persistentValues;
prev = listRoot;
next = *listRoot;
@@ -394,10 +394,9 @@ double QJSValue::toNumber() const
return std::numeric_limits<double>::quiet_NaN();
}
- QV4::ExecutionContext *ctx = d->engine ? d->engine->currentContext() : 0;
double dbl = d->value.toNumber();
- if (ctx && ctx->d()->engine->hasException) {
- ctx->catchException();
+ if (d->engine && d->engine->hasException) {
+ d->engine->catchException();
return 0;
}
return dbl;
@@ -424,10 +423,9 @@ bool QJSValue::toBool() const
return d->unboundData.toBool();
}
- QV4::ExecutionContext *ctx = d->engine ? d->engine->currentContext() : 0;
bool b = d->value.toBoolean();
- if (ctx && ctx->d()->engine->hasException) {
- ctx->catchException();
+ if (d->engine && d->engine->hasException) {
+ d->engine->catchException();
return false;
}
return b;
@@ -454,10 +452,9 @@ qint32 QJSValue::toInt() const
return d->unboundData.toInt();
}
- QV4::ExecutionContext *ctx = d->engine ? d->engine->currentContext() : 0;
qint32 i = d->value.toInt32();
- if (ctx && ctx->d()->engine->hasException) {
- ctx->catchException();
+ if (d->engine && d->engine->hasException) {
+ d->engine->catchException();
return 0;
}
return i;
@@ -484,10 +481,9 @@ quint32 QJSValue::toUInt() const
return d->unboundData.toUInt();
}
- QV4::ExecutionContext *ctx = d->engine ? d->engine->currentContext() : 0;
quint32 u = d->value.toUInt32();
- if (ctx && ctx->d()->engine->hasException) {
- ctx->catchException();
+ if (d->engine && d->engine->hasException) {
+ d->engine->catchException();
return 0;
}
return u;
@@ -520,7 +516,22 @@ QVariant QJSValue::toVariant() const
if (d->value.isEmpty())
return d->unboundData;
- return QV4::VariantObject::toVariant(d->value);
+ if (Object *o = d->value.asObject())
+ return o->engine()->toVariant(d->value, /*typeHint*/ -1, /*createJSValueForObjects*/ false);
+
+ if (d->value.isString())
+ return QVariant(d->value.stringValue()->toQString());
+ if (d->value.isBoolean())
+ return QVariant(d->value.booleanValue());
+ if (d->value.isNumber()) {
+ if (d->value.isInt32())
+ return QVariant(d->value.integerValue());
+ return QVariant(d->value.asDouble());
+ }
+ if (d->value.isNull())
+ return QVariant(QMetaType::VoidStar, 0);
+ Q_ASSERT(d->value.isUndefined());
+ return QVariant();
}
/*!
@@ -549,7 +560,7 @@ QJSValue QJSValue::call(const QJSValueList &args)
Scope scope(engine);
ScopedCallData callData(scope, args.length());
- callData->thisObject = engine->globalObject->asReturnedValue();
+ callData->thisObject = engine->globalObject()->asReturnedValue();
for (int i = 0; i < args.size(); ++i) {
if (!args.at(i).d->checkEngine(engine)) {
qWarning("QJSValue::call() failed: cannot call function with argument created in a different engine");
@@ -558,11 +569,9 @@ QJSValue QJSValue::call(const QJSValueList &args)
callData->args[i] = args.at(i).d->getValue(engine);
}
- ScopedValue result(scope);
- QV4::ExecutionContext *ctx = engine->currentContext();
- result = f->call(callData);
- if (scope.hasException())
- result = ctx->catchException();
+ ScopedValue result(scope, f->call(callData));
+ if (d->engine->hasException)
+ result = d->engine->catchException();
return new QJSValuePrivate(engine, result);
}
@@ -612,11 +621,9 @@ QJSValue QJSValue::callWithInstance(const QJSValue &instance, const QJSValueList
callData->args[i] = args.at(i).d->getValue(engine);
}
- ScopedValue result(scope);
- QV4::ExecutionContext *ctx = engine->currentContext();
- result = f->call(callData);
- if (scope.hasException())
- result = ctx->catchException();
+ ScopedValue result(scope, f->call(callData));
+ if (d->engine->hasException)
+ result = d->engine->catchException();
return new QJSValuePrivate(engine, result);
}
@@ -658,11 +665,9 @@ QJSValue QJSValue::callAsConstructor(const QJSValueList &args)
callData->args[i] = args.at(i).d->getValue(engine);
}
- ScopedValue result(scope);
- QV4::ExecutionContext *ctx = engine->currentContext();
- result = f->construct(callData);
- if (scope.hasException())
- result = ctx->catchException();
+ ScopedValue result(scope, f->construct(callData));
+ if (d->engine->hasException)
+ result = d->engine->catchException();
return new QJSValuePrivate(engine, result);
}
@@ -680,7 +685,7 @@ QJSEngine* QJSValue::engine() const
{
QV4::ExecutionEngine *engine = d->engine;
if (engine)
- return engine->v8Engine->publicEngine();
+ return engine->jsEngine();
return 0;
}
@@ -699,10 +704,10 @@ QJSValue QJSValue::prototype() const
if (!engine)
return QJSValue();
QV4::Scope scope(engine);
- Scoped<Object> o(scope, d->value.asObject());
+ ScopedObject o(scope, d->value.asObject());
if (!o)
return QJSValue();
- Scoped<Object> p(scope, o->prototype());
+ ScopedObject p(scope, o->prototype());
if (!p)
return QJSValue(NullValue);
return new QJSValuePrivate(o->internalClass()->engine, p);
@@ -741,7 +746,7 @@ void QJSValue::setPrototype(const QJSValue& prototype)
qWarning("QJSValue::setPrototype() failed: cannot set a prototype created in a different engine");
return;
}
- if (!o->setPrototype(p.getPointer()))
+ if (!o->setPrototype(p))
qWarning("QJSValue::setPrototype() failed: cyclic prototype value");
}
@@ -886,11 +891,9 @@ QJSValue QJSValue::property(const QString& name) const
return property(idx);
s->makeIdentifier();
- QV4::ExecutionContext *ctx = engine->currentContext();
- QV4::ScopedValue result(scope);
- result = o->get(s.getPointer());
- if (scope.hasException())
- result = ctx->catchException();
+ QV4::ScopedValue result(scope, o->get(s));
+ if (d->engine->hasException)
+ result = d->engine->catchException();
return new QJSValuePrivate(engine, result);
}
@@ -918,11 +921,9 @@ QJSValue QJSValue::property(quint32 arrayIndex) const
if (!o)
return QJSValue();
- QV4::ExecutionContext *ctx = engine->currentContext();
- QV4::ScopedValue result(scope);
- result = arrayIndex == UINT_MAX ? o->get(engine->id_uintMax.getPointer()) : o->getIndexed(arrayIndex);
- if (scope.hasException())
- result = ctx->catchException();
+ QV4::ScopedValue result(scope, arrayIndex == UINT_MAX ? o->get(engine->id_uintMax) : o->getIndexed(arrayIndex));
+ if (d->engine->hasException)
+ d->engine->catchException();
return new QJSValuePrivate(engine, result);
}
@@ -944,7 +945,7 @@ void QJSValue::setProperty(const QString& name, const QJSValue& value)
return;
Scope scope(engine);
- Scoped<Object> o(scope, d->value);
+ ScopedObject o(scope, d->value);
if (!o)
return;
@@ -960,12 +961,11 @@ void QJSValue::setProperty(const QString& name, const QJSValue& value)
return;
}
- QV4::ExecutionContext *ctx = engine->currentContext();
s->makeIdentifier();
QV4::ScopedValue v(scope, value.d->getValue(engine));
- o->put(s.getPointer(), v);
- if (scope.hasException())
- ctx->catchException();
+ o->put(s, v);
+ if (d->engine->hasException)
+ d->engine->catchException();
}
/*!
@@ -987,18 +987,17 @@ void QJSValue::setProperty(quint32 arrayIndex, const QJSValue& value)
return;
Scope scope(engine);
- Scoped<Object> o(scope, d->value);
+ ScopedObject o(scope, d->value);
if (!o)
return;
- QV4::ExecutionContext *ctx = engine->currentContext();
QV4::ScopedValue v(scope, value.d->getValue(engine));
if (arrayIndex != UINT_MAX)
o->putIndexed(arrayIndex, v);
else
- o->put(engine->id_uintMax.getPointer(), v);
- if (scope.hasException())
- ctx->catchException();
+ o->put(engine->id_uintMax, v);
+ if (d->engine->hasException)
+ d->engine->catchException();
}
/*!
@@ -1024,16 +1023,15 @@ void QJSValue::setProperty(quint32 arrayIndex, const QJSValue& value)
bool QJSValue::deleteProperty(const QString &name)
{
ExecutionEngine *engine = d->engine;
- ExecutionContext *ctx = engine->currentContext();
Scope scope(engine);
ScopedObject o(scope, d->value.asObject());
if (!o)
return false;
ScopedString s(scope, engine->newString(name));
- bool b = o->deleteProperty(s.getPointer());
- if (scope.hasException())
- ctx->catchException();
+ bool b = o->deleteProperty(s);
+ if (d->engine->hasException)
+ d->engine->catchException();
return b;
}
@@ -1055,7 +1053,7 @@ bool QJSValue::hasProperty(const QString &name) const
return false;
ScopedString s(scope, engine->newIdentifier(name));
- return o->hasProperty(s.getPointer());
+ return o->hasProperty(s);
}
/*!
@@ -1076,7 +1074,7 @@ bool QJSValue::hasOwnProperty(const QString &name) const
return false;
ScopedString s(scope, engine->newIdentifier(name));
- return o->hasOwnProperty(s.getPointer());
+ return o->hasOwnProperty(s);
}
/*!
@@ -1091,11 +1089,14 @@ bool QJSValue::hasOwnProperty(const QString &name) const
*/
QObject *QJSValue::toQObject() const
{
- Returned<QV4::QObjectWrapper> *o = d->value.as<QV4::QObjectWrapper>();
- if (!o)
+ if (!d->engine)
+ return 0;
+ QV4::Scope scope(d->engine);
+ QV4::Scoped<QV4::QObjectWrapper> wrapper(scope, d->value);
+ if (!wrapper)
return 0;
- return o->getPointer()->object();
+ return wrapper->object();
}
/*!
diff --git a/src/qml/jsapi/qjsvalueiterator.cpp b/src/qml/jsapi/qjsvalueiterator.cpp
index f7976e7cfc..c74a5d2d76 100644
--- a/src/qml/jsapi/qjsvalueiterator.cpp
+++ b/src/qml/jsapi/qjsvalueiterator.cpp
@@ -36,6 +36,7 @@
#include "qjsvalue_p.h"
#include "private/qv4string_p.h"
#include "private/qv4object_p.h"
+#include "private/qv4context_p.h"
QT_BEGIN_NAMESPACE
@@ -51,7 +52,7 @@ QJSValueIteratorPrivate::QJSValueIteratorPrivate(const QJSValue &v)
QV4::Scope scope(e);
QV4::ScopedObject o(scope, jsp->value);
- iterator = e->newForEachIteratorObject(e->currentContext(), o)->asReturnedValue();
+ iterator.set(e, e->newForEachIteratorObject(o));
currentName = (QV4::String *)0;
nextName = (QV4::String *)0;
@@ -101,8 +102,8 @@ QJSValueIterator::QJSValueIterator(const QJSValue& object)
QV4::Scope scope(v4);
QV4::Scoped<QV4::ForEachIteratorObject> it(scope, d_ptr->iterator.value());
it->d()->it.flags = QV4::ObjectIterator::NoFlags;
- QV4::String *nm = 0;
- it->d()->it.next(nm, &d_ptr->nextIndex, &d_ptr->nextProperty, &d_ptr->nextAttributes);
+ QV4::ScopedString nm(scope);
+ it->d()->it.next(nm.getRef(), &d_ptr->nextIndex, &d_ptr->nextProperty, &d_ptr->nextAttributes);
d_ptr->nextName = nm;
}
@@ -141,7 +142,7 @@ bool QJSValueIterator::next()
return false;
d_ptr->currentName = d_ptr->nextName;
d_ptr->currentIndex = d_ptr->nextIndex;
- d_ptr->currentProperty.copy(d_ptr->nextProperty, d_ptr->nextAttributes);
+ d_ptr->currentProperty.copy(&d_ptr->nextProperty, d_ptr->nextAttributes);
d_ptr->currentAttributes = d_ptr->nextAttributes;
QV4::ExecutionEngine *v4 = d_ptr->iterator.engine();
@@ -149,8 +150,8 @@ bool QJSValueIterator::next()
return false;
QV4::Scope scope(v4);
QV4::Scoped<QV4::ForEachIteratorObject> it(scope, d_ptr->iterator.value());
- QV4::String *nm = 0;
- it->d()->it.next(nm, &d_ptr->nextIndex, &d_ptr->nextProperty, &d_ptr->nextAttributes);
+ QV4::ScopedString nm(scope);
+ it->d()->it.next(nm.getRef(), &d_ptr->nextIndex, &d_ptr->nextProperty, &d_ptr->nextAttributes);
d_ptr->nextName = nm;
return !!d_ptr->currentName || d_ptr->currentIndex != UINT_MAX;
}
@@ -189,13 +190,12 @@ QJSValue QJSValueIterator::value() const
if (!obj)
return QJSValue();
- QV4::ExecutionContext *ctx = engine->currentContext();
if (!d_ptr->currentName && d_ptr->currentIndex == UINT_MAX)
return QJSValue();
QV4::ScopedValue v(scope, obj->getValue(obj, &d_ptr->currentProperty, d_ptr->currentAttributes));
if (scope.hasException()) {
- ctx->catchException();
+ engine->catchException();
return QJSValue();
}
return new QJSValuePrivate(engine, v);
@@ -216,18 +216,18 @@ QJSValueIterator& QJSValueIterator::operator=(QJSValue& object)
d_ptr->nextName = (QV4::String *)0;
QV4::ExecutionEngine *v4 = d_ptr->iterator.engine();
if (!v4) {
- d_ptr->iterator = QV4::Encode::undefined();
+ d_ptr->iterator.set(v4, QV4::Encode::undefined());
return *this;
}
QJSValuePrivate *jsp = QJSValuePrivate::get(object);
QV4::Scope scope(v4);
QV4::ScopedObject o(scope, jsp->value);
- d_ptr->iterator = v4->newForEachIteratorObject(v4->currentContext(), o)->asReturnedValue();
+ d_ptr->iterator.set(v4, v4->newForEachIteratorObject(o));
QV4::Scoped<QV4::ForEachIteratorObject> it(scope, d_ptr->iterator.value());
it->d()->it.flags = QV4::ObjectIterator::NoFlags;
- QV4::String *nm = 0;
- it->d()->it.next(nm, &d_ptr->nextIndex, &d_ptr->nextProperty, &d_ptr->nextAttributes);
+ QV4::ScopedString nm(scope);
+ it->d()->it.next(nm.getRef(), &d_ptr->nextIndex, &d_ptr->nextProperty, &d_ptr->nextAttributes);
d_ptr->nextName = nm;
return *this;
}
diff --git a/src/qml/jsapi/qjsvalueiterator_p.h b/src/qml/jsapi/qjsvalueiterator_p.h
index fe1d3aa932..c8f149c75d 100644
--- a/src/qml/jsapi/qjsvalueiterator_p.h
+++ b/src/qml/jsapi/qjsvalueiterator_p.h
@@ -48,10 +48,12 @@ public:
QJSValue value;
QV4::PersistentValue iterator;
+ // ### GC
QV4::Property currentProperty;
QV4::PropertyAttributes currentAttributes;
QV4::StringValue currentName;
uint currentIndex;
+ // ### GC
QV4::Property nextProperty;
QV4::PropertyAttributes nextAttributes;
QV4::StringValue nextName;
diff --git a/src/qml/jsruntime/jsruntime.pri b/src/qml/jsruntime/jsruntime.pri
index c27aaa90d8..ef44ca6f4d 100644
--- a/src/qml/jsruntime/jsruntime.pri
+++ b/src/qml/jsruntime/jsruntime.pri
@@ -42,7 +42,10 @@ SOURCES += \
$$PWD/qv4qobjectwrapper.cpp \
$$PWD/qv4qmlextensions.cpp \
$$PWD/qv4vme_moth.cpp \
- $$PWD/qv4profiling.cpp
+ $$PWD/qv4profiling.cpp \
+ $$PWD/qv4arraybuffer.cpp \
+ $$PWD/qv4typedarray.cpp \
+ $$PWD/qv4dataview.cpp
HEADERS += \
$$PWD/qv4global_p.h \
@@ -89,7 +92,10 @@ HEADERS += \
$$PWD/qv4qobjectwrapper_p.h \
$$PWD/qv4qmlextensions_p.h \
$$PWD/qv4vme_moth_p.h \
- $$PWD/qv4profiling_p.h
+ $$PWD/qv4profiling_p.h \
+ $$PWD/qv4arraybuffer_p.h \
+ $$PWD/qv4typedarray_p.h \
+ $$PWD/qv4dataview_p.h
}
diff --git a/src/qml/jsruntime/qv4argumentsobject.cpp b/src/qml/jsruntime/qv4argumentsobject.cpp
index 4af8927a2e..33529dbfab 100644
--- a/src/qml/jsruntime/qv4argumentsobject.cpp
+++ b/src/qml/jsruntime/qv4argumentsobject.cpp
@@ -38,18 +38,19 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(ArgumentsObject);
-ArgumentsObject::Data::Data(CallContext *context)
- : Object::Data(context->d()->strictMode ? context->d()->engine->strictArgumentsObjectClass : context->d()->engine->argumentsObjectClass)
- , context(context)
+Heap::ArgumentsObject::ArgumentsObject(QV4::CallContext *context)
+ : Heap::Object(context->d()->strictMode ? context->d()->engine->strictArgumentsObjectClass : context->d()->engine->argumentsObjectClass,
+ context->d()->engine->objectPrototype.asObject())
+ , context(context->d())
, fullyCreated(false)
{
- Q_ASSERT(internalClass->vtable == staticVTable());
+ Q_ASSERT(internalClass->vtable == QV4::ArgumentsObject::staticVTable());
ExecutionEngine *v4 = context->d()->engine;
Scope scope(v4);
- Scoped<ArgumentsObject> args(scope, this);
+ Scoped<QV4::ArgumentsObject> args(scope, this);
- args->setArrayType(ArrayData::Complex);
+ args->setArrayType(Heap::ArrayData::Complex);
if (context->d()->strictMode) {
Q_ASSERT(CalleePropertyIndex == args->internalClass()->find(context->d()->engine->id_callee));
@@ -63,12 +64,11 @@ ArgumentsObject::Data::Data(CallContext *context)
args->arrayPut(0, context->d()->callData->args, context->d()->callData->argc);
args->d()->fullyCreated = true;
} else {
- args->setHasAccessorProperty();
Q_ASSERT(CalleePropertyIndex == args->internalClass()->find(context->d()->engine->id_callee));
- args->memberData()[CalleePropertyIndex] = context->d()->function->asReturnedValue();
+ args->memberData()->data[CalleePropertyIndex] = context->d()->function->asReturnedValue();
}
Q_ASSERT(LengthPropertyIndex == args->internalClass()->find(context->d()->engine->id_length));
- args->memberData()[LengthPropertyIndex] = Primitive::fromInt32(context->d()->realArgumentCount);
+ args->memberData()->data[LengthPropertyIndex] = Primitive::fromInt32(context->d()->realArgumentCount);
}
void ArgumentsObject::fullyCreate()
@@ -76,55 +76,61 @@ void ArgumentsObject::fullyCreate()
if (fullyCreated())
return;
- uint numAccessors = qMin((int)context()->d()->function->formalParameterCount(), context()->d()->realArgumentCount);
- uint argCount = qMin(context()->d()->realArgumentCount, context()->d()->callData->argc);
- ArrayData::realloc(this, ArrayData::Sparse, argCount, true);
- context()->d()->engine->requireArgumentsAccessors(numAccessors);
- mappedArguments().ensureIndex(engine(), numAccessors);
+ uint numAccessors = qMin((int)context()->function->formalParameterCount(), context()->realArgumentCount);
+ uint argCount = qMin(context()->realArgumentCount, context()->callData->argc);
+ ArrayData::realloc(this, Heap::ArrayData::Sparse, argCount, true);
+ context()->engine->requireArgumentsAccessors(numAccessors);
+
+ Scope scope(engine());
+ Scoped<MemberData> md(scope, d()->mappedArguments);
+ if (!md || md->size() < numAccessors)
+ d()->mappedArguments = md->reallocate(engine(), d()->mappedArguments, numAccessors);
for (uint i = 0; i < (uint)numAccessors; ++i) {
- mappedArguments()[i] = context()->d()->callData->args[i];
- arraySet(i, context()->d()->engine->argumentsAccessors[i], Attr_Accessor);
+ mappedArguments()->data[i] = context()->callData->args[i];
+ arraySet(i, context()->engine->argumentsAccessors + i, Attr_Accessor);
}
- arrayPut(numAccessors, context()->d()->callData->args + numAccessors, argCount - numAccessors);
+ arrayPut(numAccessors, context()->callData->args + numAccessors, argCount - numAccessors);
for (uint i = numAccessors; i < argCount; ++i)
setArrayAttributes(i, Attr_Data);
d()->fullyCreated = true;
}
-bool ArgumentsObject::defineOwnProperty(ExecutionContext *ctx, uint index, const Property &desc, PropertyAttributes attrs)
+bool ArgumentsObject::defineOwnProperty(ExecutionEngine *engine, uint index, const Property *desc, PropertyAttributes attrs)
{
fullyCreate();
- Scope scope(ctx);
+ Scope scope(engine);
Property *pd = arrayData() ? arrayData()->getProperty(index) : 0;
- Property map;
+ ScopedProperty map(scope);
PropertyAttributes mapAttrs;
bool isMapped = false;
- uint numAccessors = qMin((int)context()->d()->function->formalParameterCount(), context()->d()->realArgumentCount);
+ uint numAccessors = qMin((int)context()->function->formalParameterCount(), context()->realArgumentCount);
if (pd && index < (uint)numAccessors)
- isMapped = arrayData()->attributes(index).isAccessor() && pd->getter() == context()->d()->engine->argumentsAccessors[index].getter();
+ isMapped = arrayData()->attributes(index).isAccessor() &&
+ pd->getter() == context()->engine->argumentsAccessors[index].getter();
if (isMapped) {
Q_ASSERT(arrayData());
mapAttrs = arrayData()->attributes(index);
- map.copy(*pd, mapAttrs);
+ map->copy(pd, mapAttrs);
setArrayAttributes(index, Attr_Data);
pd = arrayData()->getProperty(index);
- pd->value = mappedArguments()[index];
+ pd->value = mappedArguments()->data[index];
}
- bool strict = ctx->d()->strictMode;
- ctx->d()->strictMode = false;
- bool result = Object::defineOwnProperty2(ctx, index, desc, attrs);
- ctx->d()->strictMode = strict;
+ bool strict = engine->currentContext()->strictMode;
+ engine->currentContext()->strictMode = false;
+ bool result = Object::defineOwnProperty2(scope.engine, index, desc, attrs);
+ engine->currentContext()->strictMode = strict;
if (isMapped && attrs.isData()) {
Q_ASSERT(arrayData());
+ ScopedFunctionObject setter(scope, map->setter());
ScopedCallData callData(scope, 1);
callData->thisObject = this->asReturnedValue();
- callData->args[0] = desc.value;
- map.setter()->call(callData);
+ callData->args[0] = desc->value;
+ setter->call(callData);
if (attrs.isWritable()) {
setArrayAttributes(index, mapAttrs);
@@ -133,8 +139,8 @@ bool ArgumentsObject::defineOwnProperty(ExecutionContext *ctx, uint index, const
}
}
- if (ctx->d()->strictMode && !result)
- return ctx->throwTypeError();
+ if (engine->currentContext()->strictMode && !result)
+ return engine->throwTypeError();
return result;
}
@@ -144,10 +150,10 @@ ReturnedValue ArgumentsObject::getIndexed(Managed *m, uint index, bool *hasPrope
if (args->fullyCreated())
return Object::getIndexed(m, index, hasProperty);
- if (index < static_cast<uint>(args->context()->d()->callData->argc)) {
+ if (index < static_cast<uint>(args->context()->callData->argc)) {
if (hasProperty)
*hasProperty = true;
- return args->context()->d()->callData->args[index].asReturnedValue();
+ return args->context()->callData->args[index].asReturnedValue();
}
if (hasProperty)
*hasProperty = false;
@@ -157,7 +163,7 @@ ReturnedValue ArgumentsObject::getIndexed(Managed *m, uint index, bool *hasPrope
void ArgumentsObject::putIndexed(Managed *m, uint index, const ValueRef value)
{
ArgumentsObject *args = static_cast<ArgumentsObject *>(m);
- if (!args->fullyCreated() && index >= static_cast<uint>(args->context()->d()->callData->argc))
+ if (!args->fullyCreated() && index >= static_cast<uint>(args->context()->callData->argc))
args->fullyCreate();
if (args->fullyCreated()) {
@@ -165,7 +171,7 @@ void ArgumentsObject::putIndexed(Managed *m, uint index, const ValueRef value)
return;
}
- args->context()->d()->callData->args[index] = value;
+ args->context()->callData->args[index] = value;
}
bool ArgumentsObject::deleteIndexedProperty(Managed *m, uint index)
@@ -182,8 +188,8 @@ PropertyAttributes ArgumentsObject::queryIndexed(const Managed *m, uint index)
if (args->fullyCreated())
return Object::queryIndexed(m, index);
- uint numAccessors = qMin((int)args->context()->d()->function->formalParameterCount(), args->context()->d()->realArgumentCount);
- uint argCount = qMin(args->context()->d()->realArgumentCount, args->context()->d()->callData->argc);
+ uint numAccessors = qMin((int)args->context()->function->formalParameterCount(), args->context()->realArgumentCount);
+ uint argCount = qMin(args->context()->realArgumentCount, args->context()->callData->argc);
if (index >= argCount)
return PropertyAttributes();
if (index >= numAccessors)
@@ -200,10 +206,10 @@ ReturnedValue ArgumentsGetterFunction::call(Managed *getter, CallData *callData)
Scoped<ArgumentsGetterFunction> g(scope, static_cast<ArgumentsGetterFunction *>(getter));
Scoped<ArgumentsObject> o(scope, callData->thisObject.as<ArgumentsObject>());
if (!o)
- return v4->currentContext()->throwTypeError();
+ return v4->throwTypeError();
- Q_ASSERT(g->index() < static_cast<unsigned>(o->context()->d()->callData->argc));
- return o->context()->argument(g->index());
+ Q_ASSERT(g->index() < static_cast<unsigned>(o->context()->callData->argc));
+ return o->context()->callData->args[g->index()].asReturnedValue();
}
DEFINE_OBJECT_VTABLE(ArgumentsSetterFunction);
@@ -215,19 +221,20 @@ ReturnedValue ArgumentsSetterFunction::call(Managed *setter, CallData *callData)
Scoped<ArgumentsSetterFunction> s(scope, static_cast<ArgumentsSetterFunction *>(setter));
Scoped<ArgumentsObject> o(scope, callData->thisObject.as<ArgumentsObject>());
if (!o)
- return v4->currentContext()->throwTypeError();
+ return v4->throwTypeError();
- Q_ASSERT(s->index() < static_cast<unsigned>(o->context()->d()->callData->argc));
- o->context()->d()->callData->args[s->index()] = callData->argc ? callData->args[0].asReturnedValue() : Encode::undefined();
+ Q_ASSERT(s->index() < static_cast<unsigned>(o->context()->callData->argc));
+ o->context()->callData->args[s->index()] = callData->argc ? callData->args[0].asReturnedValue() : Encode::undefined();
return Encode::undefined();
}
-void ArgumentsObject::markObjects(Managed *that, ExecutionEngine *e)
+void ArgumentsObject::markObjects(Heap::Base *that, ExecutionEngine *e)
{
- ArgumentsObject *o = static_cast<ArgumentsObject *>(that);
- if (o->context())
- o->context()->mark(e);
- o->mappedArguments().mark(e);
+ ArgumentsObject::Data *o = static_cast<ArgumentsObject::Data *>(that);
+ if (o->context)
+ o->context->mark(e);
+ if (o->mappedArguments)
+ o->mappedArguments->mark(e);
Object::markObjects(that, e);
}
diff --git a/src/qml/jsruntime/qv4argumentsobject_p.h b/src/qml/jsruntime/qv4argumentsobject_p.h
index 786cb36d0a..dfa7ec4219 100644
--- a/src/qml/jsruntime/qv4argumentsobject_p.h
+++ b/src/qml/jsruntime/qv4argumentsobject_p.h
@@ -40,73 +40,84 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
+namespace Heap {
+
+struct ArgumentsGetterFunction : FunctionObject {
+ inline ArgumentsGetterFunction(QV4::ExecutionContext *scope, uint index);
+ uint index;
+};
+
+struct ArgumentsSetterFunction : FunctionObject {
+ inline ArgumentsSetterFunction(QV4::ExecutionContext *scope, uint index);
+ uint index;
+};
+
+struct ArgumentsObject : Object {
+ enum {
+ LengthPropertyIndex = 0,
+ CalleePropertyIndex = 1,
+ CallerPropertyIndex = 3
+ };
+ ArgumentsObject(QV4::CallContext *context);
+ CallContext *context;
+ bool fullyCreated;
+ MemberData *mappedArguments;
+};
+
+}
+
struct ArgumentsGetterFunction: FunctionObject
{
- struct Data : FunctionObject::Data {
- Data(ExecutionContext *scope, uint index)
- : FunctionObject::Data(scope)
- , index(index)
- {
- setVTable(staticVTable());
- }
- uint index;
- };
- V4_OBJECT(FunctionObject)
+ V4_OBJECT2(ArgumentsGetterFunction, FunctionObject)
uint index() const { return d()->index; }
-
static ReturnedValue call(Managed *that, CallData *d);
};
+inline
+Heap::ArgumentsGetterFunction::ArgumentsGetterFunction(QV4::ExecutionContext *scope, uint index)
+ : Heap::FunctionObject(scope)
+ , index(index)
+{
+ setVTable(QV4::ArgumentsGetterFunction::staticVTable());
+}
+
struct ArgumentsSetterFunction: FunctionObject
{
- struct Data : FunctionObject::Data {
- Data(ExecutionContext *scope, uint index)
- : FunctionObject::Data(scope)
- , index(index)
- {
- setVTable(staticVTable());
- }
- uint index;
- };
- V4_OBJECT(FunctionObject)
+ V4_OBJECT2(ArgumentsSetterFunction, FunctionObject)
uint index() const { return d()->index; }
-
static ReturnedValue call(Managed *that, CallData *callData);
};
+inline
+Heap::ArgumentsSetterFunction::ArgumentsSetterFunction(QV4::ExecutionContext *scope, uint index)
+ : Heap::FunctionObject(scope)
+ , index(index)
+{
+ setVTable(QV4::ArgumentsSetterFunction::staticVTable());
+}
+
struct ArgumentsObject: Object {
- struct Data : Object::Data {
- Data(CallContext *context);
- CallContext *context;
- bool fullyCreated;
- Members mappedArguments;
- };
- V4_OBJECT(Object)
+ V4_OBJECT2(ArgumentsObject, Object)
Q_MANAGED_TYPE(ArgumentsObject)
- CallContext *context() const { return d()->context; }
+ Heap::CallContext *context() const { return d()->context; }
bool fullyCreated() const { return d()->fullyCreated; }
- Members &mappedArguments() { return d()->mappedArguments; }
+ Heap::MemberData *mappedArguments() { return d()->mappedArguments; }
static bool isNonStrictArgumentsObject(Managed *m) {
return m->internalClass()->vtable->type == Type_ArgumentsObject &&
- !static_cast<ArgumentsObject *>(m)->context()->d()->strictMode;
+ !static_cast<ArgumentsObject *>(m)->context()->strictMode;
}
- enum {
- LengthPropertyIndex = 0,
- CalleePropertyIndex = 1,
- CallerPropertyIndex = 3
- };
- bool defineOwnProperty(ExecutionContext *ctx, uint index, const Property &desc, PropertyAttributes attrs);
+ bool defineOwnProperty(ExecutionEngine *engine, uint index, const Property *desc, PropertyAttributes attrs);
static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty);
static void putIndexed(Managed *m, uint index, const ValueRef value);
static bool deleteIndexedProperty(Managed *m, uint index);
static PropertyAttributes queryIndexed(const Managed *m, uint index);
- static void markObjects(Managed *that, ExecutionEngine *e);
+ static void markObjects(Heap::Base *that, ExecutionEngine *e);
void fullyCreate();
};
diff --git a/src/qml/jsruntime/qv4arraybuffer.cpp b/src/qml/jsruntime/qv4arraybuffer.cpp
new file mode 100644
index 0000000000..f54161ea18
--- /dev/null
+++ b/src/qml/jsruntime/qv4arraybuffer.cpp
@@ -0,0 +1,164 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "qv4arraybuffer_p.h"
+#include "qv4typedarray_p.h"
+#include "qv4dataview_p.h"
+
+using namespace QV4;
+
+DEFINE_OBJECT_VTABLE(ArrayBufferCtor);
+DEFINE_OBJECT_VTABLE(ArrayBuffer);
+
+Heap::ArrayBufferCtor::ArrayBufferCtor(QV4::ExecutionContext *scope)
+ : Heap::FunctionObject(scope, QStringLiteral("ArrayBuffer"))
+{
+ setVTable(QV4::ArrayBufferCtor::staticVTable());
+}
+
+ReturnedValue ArrayBufferCtor::construct(Managed *m, CallData *callData)
+{
+ ExecutionEngine *v4 = m->engine();
+
+ Scope scope(v4);
+ ScopedValue l(scope, callData->argument(0));
+ double dl = l->toInteger();
+ if (v4->hasException)
+ return Encode::undefined();
+ uint len = (uint)qBound(0., dl, (double)UINT_MAX);
+ if (len != dl)
+ return v4->throwRangeError(QLatin1String("ArrayBuffer constructor: invalid length"));
+
+ Scoped<ArrayBuffer> a(scope, v4->memoryManager->alloc<ArrayBuffer>(v4, len));
+ if (scope.engine->hasException)
+ return Encode::undefined();
+ return a.asReturnedValue();
+}
+
+
+ReturnedValue ArrayBufferCtor::call(Managed *that, CallData *callData)
+{
+ return construct(that, callData);
+}
+
+ReturnedValue ArrayBufferCtor::method_isView(CallContext *ctx)
+{
+ QV4::Scope scope(ctx);
+ QV4::Scoped<TypedArray> a(scope, ctx->argument(0));
+ if (!!a)
+ return Encode(true);
+ QV4::Scoped<DataView> v(scope, ctx->argument(0));
+ if (!!v)
+ return Encode(true);
+ return Encode(true);
+}
+
+
+Heap::ArrayBuffer::ArrayBuffer(ExecutionEngine *e, int length)
+ : Heap::Object(e->arrayBufferClass, e->arrayBufferPrototype.asObject())
+{
+ data = QTypedArrayData<char>::allocate(length + 1);
+ if (!data) {
+ data = 0;
+ e->throwRangeError(QStringLiteral("ArrayBuffer: out of memory"));
+ return;
+ }
+ data->size = length;
+ memset(data->data(), 0, length + 1);
+}
+
+Heap::ArrayBuffer::~ArrayBuffer()
+{
+ if (!data->ref.deref())
+ QTypedArrayData<char>::deallocate(data);
+}
+
+QByteArray ArrayBuffer::asByteArray() const
+{
+ QByteArrayDataPtr ba = { d()->data };
+ ba.ptr->ref.ref();
+ return QByteArray(ba);
+}
+
+void ArrayBufferPrototype::init(ExecutionEngine *engine, Object *ctor)
+{
+ Scope scope(engine);
+ ScopedObject o(scope);
+ ctor->defineReadonlyProperty(engine->id_length, Primitive::fromInt32(1));
+ ctor->defineReadonlyProperty(engine->id_prototype, (o = this));
+ ctor->defineDefaultProperty(QStringLiteral("isView"), ArrayBufferCtor::method_isView, 1);
+ defineDefaultProperty(engine->id_constructor, (o = ctor));
+ defineAccessorProperty(QStringLiteral("byteLength"), method_get_byteLength, 0);
+ defineDefaultProperty(QStringLiteral("slice"), method_slice, 2);
+}
+
+ReturnedValue ArrayBufferPrototype::method_get_byteLength(CallContext *ctx)
+{
+ Scope scope(ctx);
+ Scoped<ArrayBuffer> v(scope, ctx->d()->callData->thisObject);
+ if (!v)
+ return scope.engine->throwTypeError();
+
+ return Encode(v->d()->data->size);
+}
+
+ReturnedValue ArrayBufferPrototype::method_slice(CallContext *ctx)
+{
+ Scope scope(ctx);
+ Scoped<ArrayBuffer> a(scope, ctx->d()->callData->thisObject);
+ if (!a)
+ return scope.engine->throwTypeError();
+
+ double start = ctx->d()->callData->argc > 0 ? ctx->d()->callData->args[0].toInteger() : 0;
+ double end = (ctx->d()->callData->argc < 2 || ctx->d()->callData->args[1].isUndefined()) ?
+ a->d()->data->size : ctx->d()->callData->args[1].toInteger();
+ if (scope.engine->hasException)
+ return Encode::undefined();
+
+ double first = (start < 0) ? qMax(a->d()->data->size + start, 0.) : qMin(start, (double)a->d()->data->size);
+ double final = (end < 0) ? qMax(a->d()->data->size + end, 0.) : qMin(end, (double)a->d()->data->size);
+
+ ScopedFunctionObject constructor(scope, a->get(scope.engine->id_constructor));
+ if (!constructor)
+ return scope.engine->throwTypeError();
+
+ ScopedCallData callData(scope, 1);
+ double newLen = qMax(final - first, 0.);
+ callData->args[0] = QV4::Encode(newLen);
+ QV4::Scoped<ArrayBuffer> newBuffer(scope, constructor->construct(callData));
+ if (!newBuffer || newBuffer->d()->data->size < (int)newLen)
+ return scope.engine->throwTypeError();
+
+ memcpy(newBuffer->d()->data->data(), a->d()->data->data() + (uint)first, newLen);
+
+ return newBuffer.asReturnedValue();
+}
diff --git a/src/quick/accessible/qqmlaccessible_p.h b/src/qml/jsruntime/qv4arraybuffer_p.h
index 5948f06cb5..b2d24f76bc 100644
--- a/src/quick/accessible/qqmlaccessible_p.h
+++ b/src/qml/jsruntime/qv4arraybuffer_p.h
@@ -30,53 +30,72 @@
** $QT_END_LICENSE$
**
****************************************************************************/
+#ifndef QV4ARRAYBUFFER_H
+#define QV4ARRAYBUFFER_H
-#ifndef QQMLACCESSIBLE_H
-#define QQMLACCESSIBLE_H
-
-#include <QtGui/qaccessibleobject.h>
-#include <QtQml/qqmlproperty.h>
+#include "qv4object_p.h"
+#include "qv4functionobject_p.h"
QT_BEGIN_NAMESPACE
-#ifndef QT_NO_ACCESSIBILITY
+namespace QV4 {
+
+namespace Heap {
+
+struct ArrayBufferCtor : FunctionObject {
+ ArrayBufferCtor(QV4::ExecutionContext *scope);
+};
+
+struct ArrayBuffer : Object {
+ ArrayBuffer(ExecutionEngine *e, int length);
+ ~ArrayBuffer();
+ QTypedArrayData<char> *data;
+
+ uint byteLength() const { return data->size; }
+};
-/*
- -- Declarative Accessibility Overview. --
+}
- * Item interface classes:
- QAccessibleDeclarativeItem for Qt Quick 1
- QAccessibleQuickItem for for Qt Quick 2
- Common base class: QQmlAccessible
+struct ArrayBufferCtor: FunctionObject
+{
+ V4_OBJECT2(ArrayBufferCtor, FunctionObject)
- * View interface classes.
+ static ReturnedValue construct(Managed *m, CallData *callData);
+ static ReturnedValue call(Managed *that, CallData *callData);
- These are the root of the QML accessible tree and connects it to the widget hierarchy.
+ static ReturnedValue method_isView(CallContext *ctx);
- QAccessbileDeclarativeView is the root for the QGraphicsView implementation
- QAccessbileQuickView is the root for the SceneGraph implementation
+};
-*/
-class QQmlAccessible: public QAccessibleObject, public QAccessibleActionInterface
+struct ArrayBuffer : Object
{
-public:
- ~QQmlAccessible();
- void *interface_cast(QAccessible::InterfaceType t);
+ V4_OBJECT2(ArrayBuffer, Object)
+ V4_NEEDS_DESTROY
+
+ QByteArray asByteArray() const;
+ uint byteLength() const { return d()->byteLength(); }
+ char *data() {
+ // ### detach if refcount > 1
+ return d()->data->data();
+ }
+ const char *constData() {
+ // ### detach if refcount > 1
+ return d()->data->data();
+ }
- virtual QRect viewRect() const = 0;
- QAccessible::State state() const;
+};
- QStringList actionNames() const;
- void doAction(const QString &actionName);
- QStringList keyBindingsForAction(const QString &actionName) const;
+struct ArrayBufferPrototype: Object
+{
+ void init(ExecutionEngine *engine, Object *ctor);
-protected:
- // For subclasses, use instantiateObject factory method outside the class.
- QQmlAccessible(QObject *object);
+ static ReturnedValue method_get_byteLength(CallContext *ctx);
+ static ReturnedValue method_slice(CallContext *ctx);
};
-#endif // QT_NO_ACCESSIBILITY
+
+} // namespace QV4
QT_END_NAMESPACE
-#endif // QQMLACCESSIBLE_H
+#endif
diff --git a/src/qml/jsruntime/qv4arraydata.cpp b/src/qml/jsruntime/qv4arraydata.cpp
index 0aaf50a43c..a4f67c7656 100644
--- a/src/qml/jsruntime/qv4arraydata.cpp
+++ b/src/qml/jsruntime/qv4arraydata.cpp
@@ -34,6 +34,8 @@
#include "qv4object_p.h"
#include "qv4functionobject_p.h"
#include "qv4mm_p.h"
+#include "qv4runtime_p.h"
+#include "qv4argumentsobject_p.h"
using namespace QV4;
@@ -56,14 +58,13 @@ const QV4::ManagedVTable QV4::ArrayData::static_vtbl = {
const ArrayVTable SimpleArrayData::static_vtbl =
{
DEFINE_MANAGED_VTABLE_INT(SimpleArrayData, 0),
- SimpleArrayData::Simple,
+ Heap::ArrayData::Simple,
SimpleArrayData::reallocate,
SimpleArrayData::get,
SimpleArrayData::put,
SimpleArrayData::putArray,
SimpleArrayData::del,
SimpleArrayData::setAttribute,
- SimpleArrayData::attribute,
SimpleArrayData::push_front,
SimpleArrayData::pop_front,
SimpleArrayData::truncate,
@@ -73,26 +74,26 @@ const ArrayVTable SimpleArrayData::static_vtbl =
const ArrayVTable SparseArrayData::static_vtbl =
{
DEFINE_MANAGED_VTABLE_INT(SparseArrayData, 0),
- ArrayData::Sparse,
+ Heap::ArrayData::Sparse,
SparseArrayData::reallocate,
SparseArrayData::get,
SparseArrayData::put,
SparseArrayData::putArray,
SparseArrayData::del,
SparseArrayData::setAttribute,
- SparseArrayData::attribute,
SparseArrayData::push_front,
SparseArrayData::pop_front,
SparseArrayData::truncate,
SparseArrayData::length
};
-Q_STATIC_ASSERT(sizeof(ArrayData::Data) == sizeof(SimpleArrayData::Data));
-Q_STATIC_ASSERT(sizeof(ArrayData::Data) == sizeof(SparseArrayData::Data));
+Q_STATIC_ASSERT(sizeof(Heap::ArrayData) == sizeof(Heap::SimpleArrayData));
+Q_STATIC_ASSERT(sizeof(Heap::ArrayData) == sizeof(Heap::SparseArrayData));
void ArrayData::realloc(Object *o, Type newType, uint requested, bool enforceAttributes)
{
- ArrayData *d = o->arrayData();
+ Scope scope(o->engine());
+ Scoped<ArrayData> d(scope, o->arrayData());
uint alloc = 8;
uint toCopy = 0;
@@ -107,34 +108,34 @@ void ArrayData::realloc(Object *o, Type newType, uint requested, bool enforceAtt
if (alloc < d->alloc())
alloc = d->alloc();
- if (d->type() < Sparse) {
- offset = static_cast<SimpleArrayData *>(d)->d()->offset;
- toCopy = static_cast<SimpleArrayData *>(d)->len();
+ if (d->type() < Heap::ArrayData::Sparse) {
+ offset = d->d()->offset;
+ toCopy = d->d()->len;
} else {
toCopy = d->alloc();
}
if (d->type() > newType)
newType = d->type();
}
- if (enforceAttributes && newType == Simple)
- newType = Complex;
+ if (enforceAttributes && newType == Heap::ArrayData::Simple)
+ newType = Heap::ArrayData::Complex;
while (alloc < requested)
alloc *= 2;
- size_t size = sizeof(ArrayData::Data) + (alloc - 1)*sizeof(Value);
+ size_t size = sizeof(Heap::ArrayData) + (alloc - 1)*sizeof(Value);
if (enforceAttributes)
size += alloc*sizeof(PropertyAttributes);
- ArrayData *newData;
- if (newType < Sparse) {
- SimpleArrayData *n = static_cast<SimpleArrayData *>(o->engine()->memoryManager->allocManaged(size));
- new (n->d()) SimpleArrayData::Data(o->engine());
- n->d()->offset = 0;
- n->len() = d ? static_cast<SimpleArrayData *>(d)->len() : 0;
+ Scoped<ArrayData> newData(scope);
+ if (newType < Heap::ArrayData::Sparse) {
+ Heap::SimpleArrayData *n = static_cast<Heap::SimpleArrayData *>(scope.engine->memoryManager->allocManaged(size));
+ new (n) Heap::SimpleArrayData(scope.engine);
+ n->offset = 0;
+ n->len = d ? d->d()->len : 0;
newData = n;
} else {
- SparseArrayData *n = static_cast<SparseArrayData *>(o->engine()->memoryManager->allocManaged(size));
- new (n->d()) SparseArrayData::Data(o->engine());
+ Heap::SparseArrayData *n = static_cast<Heap::SparseArrayData *>(scope.engine->memoryManager->allocManaged(size));
+ new (n) Heap::SparseArrayData(scope.engine);
newData = n;
}
newData->setAlloc(alloc);
@@ -145,113 +146,113 @@ void ArrayData::realloc(Object *o, Type newType, uint requested, bool enforceAtt
if (d) {
if (enforceAttributes) {
if (d->attrs())
- memcpy(o->arrayData()->attrs(), d->attrs(), sizeof(PropertyAttributes)*toCopy);
+ memcpy(newData->attrs(), d->attrs(), sizeof(PropertyAttributes)*toCopy);
else
for (uint i = 0; i < toCopy; ++i)
- o->arrayData()->attrs()[i] = Attr_Data;
+ newData->attrs()[i] = Attr_Data;
}
if (toCopy > d->d()->alloc - offset) {
uint copyFromStart = toCopy - (d->d()->alloc - offset);
- memcpy(o->arrayData()->d()->arrayData + toCopy - copyFromStart, d->d()->arrayData, sizeof(Value)*copyFromStart);
+ memcpy(newData->d()->arrayData + toCopy - copyFromStart, d->d()->arrayData, sizeof(Value)*copyFromStart);
toCopy -= copyFromStart;
}
- memcpy(o->arrayData()->d()->arrayData, d->d()->arrayData + offset, sizeof(Value)*toCopy);
+ memcpy(newData->d()->arrayData, d->d()->arrayData + offset, sizeof(Value)*toCopy);
}
- if (newType != Sparse)
+ if (newType != Heap::ArrayData::Sparse)
return;
- SparseArrayData *sparse = static_cast<SparseArrayData *>(o->arrayData());
+ Heap::SparseArrayData *sparse = static_cast<Heap::SparseArrayData *>(newData->d());
uint *lastFree;
- if (d && d->type() == Sparse) {
- SparseArrayData *old = static_cast<SparseArrayData *>(d);
- sparse->setSparse(old->sparse());
- old->setSparse(0);
- sparse->freeList() = old->freeList();
- lastFree = &sparse->freeList();
+ if (d && d->type() == Heap::ArrayData::Sparse) {
+ Heap::SparseArrayData *old = static_cast<Heap::SparseArrayData *>(d->d());
+ sparse->sparse = old->sparse;
+ old->sparse = 0;
+ sparse->freeList = old->freeList;
+ lastFree = &sparse->freeList;
} else {
- sparse->setSparse(new SparseArray);
- lastFree = &sparse->freeList();
+ sparse->sparse = new SparseArray;
+ lastFree = &sparse->freeList;
for (uint i = 0; i < toCopy; ++i) {
- if (!sparse->arrayData()[i].isEmpty()) {
- SparseArrayNode *n = sparse->sparse()->insert(i);
+ if (!sparse->arrayData[i].isEmpty()) {
+ SparseArrayNode *n = sparse->sparse->insert(i);
n->value = i;
} else {
*lastFree = i;
- sparse->arrayData()[i].tag = Value::Empty_Type;
- lastFree = &sparse->arrayData()[i].uint_32;
+ sparse->arrayData[i].tag = Value::Empty_Type;
+ lastFree = &sparse->arrayData[i].uint_32;
}
}
}
- if (toCopy < sparse->alloc()) {
- for (uint i = toCopy; i < sparse->alloc(); ++i) {
+ if (toCopy < sparse->alloc) {
+ for (uint i = toCopy; i < sparse->alloc; ++i) {
*lastFree = i;
- sparse->arrayData()[i].tag = Value::Empty_Type;
- lastFree = &sparse->arrayData()[i].uint_32;
+ sparse->arrayData[i].tag = Value::Empty_Type;
+ lastFree = &sparse->arrayData[i].uint_32;
}
*lastFree = UINT_MAX;
}
// ### Could explicitly free the old data
}
-ArrayData *SimpleArrayData::reallocate(Object *o, uint n, bool enforceAttributes)
+Heap::ArrayData *SimpleArrayData::reallocate(Object *o, uint n, bool enforceAttributes)
{
- realloc(o, Simple, n, enforceAttributes);
+ realloc(o, Heap::ArrayData::Simple, n, enforceAttributes);
return o->arrayData();
}
void ArrayData::ensureAttributes(Object *o)
{
- if (o->arrayData() && o->arrayData()->attrs())
+ if (o->arrayData() && o->arrayData()->attrs)
return;
- ArrayData::realloc(o, Simple, 0, true);
+ ArrayData::realloc(o, Heap::ArrayData::Simple, 0, true);
}
-void SimpleArrayData::markObjects(Managed *d, ExecutionEngine *e)
+void SimpleArrayData::markObjects(Heap::Base *d, ExecutionEngine *e)
{
- SimpleArrayData *dd = static_cast<SimpleArrayData *>(d);
- uint l = dd->len();
+ Heap::SimpleArrayData *dd = static_cast<Heap::SimpleArrayData *>(d);
+ uint l = dd->len;
for (uint i = 0; i < l; ++i)
- dd->data(i).mark(e);
+ dd->arrayData[i].mark(e);
}
-ReturnedValue SimpleArrayData::get(const ArrayData *d, uint index)
+ReturnedValue SimpleArrayData::get(const Heap::ArrayData *d, uint index)
{
- const SimpleArrayData *dd = static_cast<const SimpleArrayData *>(d);
- if (index >= dd->len())
+ const Heap::SimpleArrayData *dd = static_cast<const Heap::SimpleArrayData *>(d);
+ if (index >= dd->len)
return Primitive::emptyValue().asReturnedValue();
return dd->data(index).asReturnedValue();
}
bool SimpleArrayData::put(Object *o, uint index, ValueRef value)
{
- SimpleArrayData *dd = static_cast<SimpleArrayData *>(o->arrayData());
- Q_ASSERT(index >= dd->len() || !dd->attrs() || !dd->attrs()[index].isAccessor());
+ Heap::SimpleArrayData *dd = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ Q_ASSERT(index >= dd->len || !dd->attrs || !dd->attrs[index].isAccessor());
// ### honour attributes
dd->data(index) = value;
- if (index >= dd->len()) {
- if (dd->attrs())
- dd->attrs()[index] = Attr_Data;
- dd->len() = index + 1;
+ if (index >= dd->len) {
+ if (dd->attrs)
+ dd->attrs[index] = Attr_Data;
+ dd->len = index + 1;
}
return true;
}
bool SimpleArrayData::del(Object *o, uint index)
{
- SimpleArrayData *dd = static_cast<SimpleArrayData *>(o->arrayData());
- if (index >= dd->len())
+ Heap::SimpleArrayData *dd = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ if (index >= dd->len)
return true;
- if (!dd->attrs() || dd->attrs()[index].isConfigurable()) {
+ if (!dd->attrs || dd->attrs[index].isConfigurable()) {
dd->data(index) = Primitive::emptyValue();
- if (dd->attrs())
- dd->attrs()[index] = Attr_Data;
+ if (dd->attrs)
+ dd->attrs[index] = Attr_Data;
return true;
}
if (dd->data(index).isEmpty())
@@ -261,167 +262,156 @@ bool SimpleArrayData::del(Object *o, uint index)
void SimpleArrayData::setAttribute(Object *o, uint index, PropertyAttributes attrs)
{
- o->arrayData()->attrs()[index] = attrs;
-}
-
-PropertyAttributes SimpleArrayData::attribute(const ArrayData *d, uint index)
-{
- return d->attrs()[index];
+ o->arrayData()->attrs[index] = attrs;
}
void SimpleArrayData::push_front(Object *o, Value *values, uint n)
{
- SimpleArrayData *dd = static_cast<SimpleArrayData *>(o->arrayData());
- Q_ASSERT(!dd->attrs());
- if (dd->len() + n > dd->alloc()) {
- realloc(o, Simple, dd->len() + n, false);
- dd = static_cast<SimpleArrayData *>(o->arrayData());
+ Heap::SimpleArrayData *dd = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ Q_ASSERT(!dd->attrs);
+ if (dd->len + n > dd->alloc) {
+ realloc(o, Heap::ArrayData::Simple, dd->len + n, false);
+ Q_ASSERT(o->d()->arrayData->type == Heap::ArrayData::Simple);
+ dd = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
}
- dd->d()->offset = (dd->d()->offset - n) % dd->d()->alloc;
- dd->len() += n;
+ dd->offset = (dd->offset - n) % dd->alloc;
+ dd->len += n;
for (uint i = 0; i < n; ++i)
dd->data(i) = values[i].asReturnedValue();
}
ReturnedValue SimpleArrayData::pop_front(Object *o)
{
- SimpleArrayData *dd = static_cast<SimpleArrayData *>(o->arrayData());
- Q_ASSERT(!dd->attrs());
- if (!dd->len())
+ Heap::SimpleArrayData *dd = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ Q_ASSERT(!dd->attrs);
+ if (!dd->len)
return Encode::undefined();
ReturnedValue v = dd->data(0).isEmpty() ? Encode::undefined() : dd->data(0).asReturnedValue();
- dd->d()->offset = (dd->d()->offset + 1) % dd->d()->alloc;
- --dd->len();
+ dd->offset = (dd->offset + 1) % dd->alloc;
+ --dd->len;
return v;
}
uint SimpleArrayData::truncate(Object *o, uint newLen)
{
- SimpleArrayData *dd = static_cast<SimpleArrayData *>(o->arrayData());
- if (dd->len() < newLen)
+ Heap::SimpleArrayData *dd = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ if (dd->len < newLen)
return newLen;
- if (!dd->attrs()) {
- dd->len() = newLen;
+ if (!dd->attrs) {
+ dd->len = newLen;
return newLen;
}
- while (dd->len() > newLen) {
- if (!dd->data(dd->len() - 1).isEmpty() && !dd->attrs()[dd->len() - 1].isConfigurable())
- return dd->len();
- --dd->len();
+ while (dd->len > newLen) {
+ if (!dd->data(dd->len - 1).isEmpty() && !dd->attrs[dd->len - 1].isConfigurable())
+ return dd->len;
+ --dd->len;
}
- return dd->len();
+ return dd->len;
}
-uint SimpleArrayData::length(const ArrayData *d)
+uint SimpleArrayData::length(const Heap::ArrayData *d)
{
- return static_cast<const SimpleArrayData *>(d)->len();
+ return d->len;
}
bool SimpleArrayData::putArray(Object *o, uint index, Value *values, uint n)
{
- SimpleArrayData *dd = static_cast<SimpleArrayData *>(o->arrayData());
- if (index + n > dd->alloc()) {
+ Heap::SimpleArrayData *dd = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ if (index + n > dd->alloc) {
reallocate(o, index + n + 1, false);
- dd = static_cast<SimpleArrayData *>(o->arrayData());
+ dd = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
}
- for (uint i = dd->len(); i < index; ++i)
+ for (uint i = dd->len; i < index; ++i)
dd->data(i) = Primitive::emptyValue();
for (uint i = 0; i < n; ++i)
dd->data(index + i) = values[i];
- dd->len() = qMax(dd->len(), index + n);
+ dd->len = qMax(dd->len, index + n);
return true;
}
-void SparseArrayData::free(ArrayData *d, uint idx)
+void SparseArrayData::free(Heap::ArrayData *d, uint idx)
{
- Q_ASSERT(d && d->type() == ArrayData::Sparse);
- SparseArrayData *dd = static_cast<SparseArrayData *>(d);
- Value *v = dd->arrayData() + idx;
- if (dd->attrs() && dd->attrs()[idx].isAccessor()) {
+ Q_ASSERT(d && d->type == Heap::ArrayData::Sparse);
+ Value *v = d->arrayData + idx;
+ if (d->attrs && d->attrs[idx].isAccessor()) {
// double slot, free both. Order is important, so we have a double slot for allocation again afterwards.
v[1].tag = Value::Empty_Type;
- v[1].uint_32 = dd->freeList();
+ v[1].uint_32 = d->freeList;
v[0].tag = Value::Empty_Type;
v[0].uint_32 = idx + 1;
} else {
v->tag = Value::Empty_Type;
- v->uint_32 = dd->freeList();
+ v->uint_32 = d->freeList;
}
- dd->freeList() = idx;
- if (dd->attrs())
- dd->attrs()[idx].clear();
+ d->freeList = idx;
+ if (d->attrs)
+ d->attrs[idx].clear();
}
-void SparseArrayData::destroy(Managed *d)
+void SparseArrayData::markObjects(Heap::Base *d, ExecutionEngine *e)
{
- SparseArrayData *dd = static_cast<SparseArrayData *>(d);
- delete dd->sparse();
-}
-
-void SparseArrayData::markObjects(Managed *d, ExecutionEngine *e)
-{
- SparseArrayData *dd = static_cast<SparseArrayData *>(d);
- uint l = dd->alloc();
+ Heap::SparseArrayData *dd = static_cast<Heap::SparseArrayData *>(d);
+ uint l = dd->alloc;
for (uint i = 0; i < l; ++i)
- dd->arrayData()[i].mark(e);
+ dd->arrayData[i].mark(e);
}
-ArrayData *SparseArrayData::reallocate(Object *o, uint n, bool enforceAttributes)
+Heap::ArrayData *SparseArrayData::reallocate(Object *o, uint n, bool enforceAttributes)
{
- realloc(o, Sparse, n, enforceAttributes);
+ realloc(o, Heap::ArrayData::Sparse, n, enforceAttributes);
return o->arrayData();
}
// double slots are required for accessor properties
uint SparseArrayData::allocate(Object *o, bool doubleSlot)
{
- Q_ASSERT(o->arrayData()->type() == ArrayData::Sparse);
- SparseArrayData *dd = static_cast<SparseArrayData *>(o->arrayData());
+ Q_ASSERT(o->d()->arrayData->type == Heap::ArrayData::Sparse);
+ Heap::SparseArrayData *dd = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
if (doubleSlot) {
- uint *last = &dd->freeList();
+ uint *last = &dd->freeList;
while (1) {
if (*last == UINT_MAX) {
- reallocate(o, o->arrayData()->alloc() + 2, true);
- dd = static_cast<SparseArrayData *>(o->arrayData());
- last = &dd->freeList();
+ reallocate(o, dd->alloc + 2, true);
+ dd = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ last = &dd->freeList;
Q_ASSERT(*last != UINT_MAX);
}
- Q_ASSERT(dd->arrayData()[*last].uint_32 != *last);
- if (dd->arrayData()[*last].uint_32 == (*last + 1)) {
+ Q_ASSERT(dd->arrayData[*last].uint_32 != *last);
+ if (dd->arrayData[*last].uint_32 == (*last + 1)) {
// found two slots in a row
uint idx = *last;
- *last = dd->arrayData()[*last + 1].uint_32;
- o->arrayData()->attrs()[idx] = Attr_Accessor;
+ *last = dd->arrayData[*last + 1].uint_32;
+ dd->attrs[idx] = Attr_Accessor;
return idx;
}
- last = &dd->arrayData()[*last].uint_32;
+ last = &dd->arrayData[*last].uint_32;
}
} else {
- if (dd->freeList() == UINT_MAX) {
- reallocate(o, o->arrayData()->alloc() + 1, false);
- dd = static_cast<SparseArrayData *>(o->arrayData());
+ if (dd->freeList == UINT_MAX) {
+ reallocate(o, dd->alloc + 1, false);
+ dd = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
}
- uint idx = dd->freeList();
+ uint idx = dd->freeList;
Q_ASSERT(idx != UINT_MAX);
- dd->freeList() = dd->arrayData()[idx].uint_32;
- if (dd->attrs())
- dd->attrs()[idx] = Attr_Data;
+ dd->freeList = dd->arrayData[idx].uint_32;
+ if (dd->attrs)
+ dd->attrs[idx] = Attr_Data;
return idx;
}
}
-ReturnedValue SparseArrayData::get(const ArrayData *d, uint index)
+ReturnedValue SparseArrayData::get(const Heap::ArrayData *d, uint index)
{
- const SparseArrayData *s = static_cast<const SparseArrayData *>(d);
+ const Heap::SparseArrayData *s = static_cast<const Heap::SparseArrayData *>(d);
index = s->mappedIndex(index);
if (index == UINT_MAX)
return Primitive::emptyValue().asReturnedValue();
- return s->arrayData()[index].asReturnedValue();
+ return s->arrayData[index].asReturnedValue();
}
bool SparseArrayData::put(Object *o, uint index, ValueRef value)
@@ -429,96 +419,91 @@ bool SparseArrayData::put(Object *o, uint index, ValueRef value)
if (value->isEmpty())
return true;
- SparseArrayData *s = static_cast<SparseArrayData *>(o->arrayData());
- SparseArrayNode *n = s->sparse()->insert(index);
- Q_ASSERT(n->value == UINT_MAX || !o->arrayData()->attrs() || !o->arrayData()->attrs()[n->value].isAccessor());
+ Heap::SparseArrayData *s = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ SparseArrayNode *n = s->sparse->insert(index);
+ Q_ASSERT(n->value == UINT_MAX || !s->attrs || !s->attrs[n->value].isAccessor());
if (n->value == UINT_MAX)
n->value = allocate(o);
- s->arrayData()[n->value] = value;
- if (s->attrs())
- s->attrs()[n->value] = Attr_Data;
+ s = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ s->arrayData[n->value] = value;
+ if (s->attrs)
+ s->attrs[n->value] = Attr_Data;
return true;
}
bool SparseArrayData::del(Object *o, uint index)
{
- SparseArrayData *dd = static_cast<SparseArrayData *>(o->arrayData());
+ Heap::SparseArrayData *dd = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
- SparseArrayNode *n = dd->sparse()->findNode(index);
+ SparseArrayNode *n = dd->sparse->findNode(index);
if (!n)
return true;
uint pidx = n->value;
- Q_ASSERT(!dd->arrayData()[pidx].isEmpty());
+ Q_ASSERT(!dd->arrayData[pidx].isEmpty());
bool isAccessor = false;
- if (dd->attrs()) {
- if (!dd->attrs()[pidx].isConfigurable())
+ if (dd->attrs) {
+ if (!dd->attrs[pidx].isConfigurable())
return false;
- isAccessor = dd->attrs()[pidx].isAccessor();
- dd->attrs()[pidx] = Attr_Data;
+ isAccessor = dd->attrs[pidx].isAccessor();
+ dd->attrs[pidx] = Attr_Data;
}
if (isAccessor) {
// free up both indices
- dd->arrayData()[pidx + 1].tag = Value::Empty_Type;
- dd->arrayData()[pidx + 1].uint_32 = static_cast<SparseArrayData *>(dd)->freeList();
- dd->arrayData()[pidx].tag = Value::Undefined_Type;
- dd->arrayData()[pidx].uint_32 = pidx + 1;
+ dd->arrayData[pidx + 1].tag = Value::Empty_Type;
+ dd->arrayData[pidx + 1].uint_32 = dd->freeList;
+ dd->arrayData[pidx].tag = Value::Undefined_Type;
+ dd->arrayData[pidx].uint_32 = pidx + 1;
} else {
- dd->arrayData()[pidx].tag = Value::Empty_Type;
- dd->arrayData()[pidx].uint_32 = static_cast<SparseArrayData *>(dd)->freeList();
+ dd->arrayData[pidx].tag = Value::Empty_Type;
+ dd->arrayData[pidx].uint_32 = dd->freeList;
}
- dd->freeList() = pidx;
- dd->sparse()->erase(n);
+ dd->freeList = pidx;
+ dd->sparse->erase(n);
return true;
}
void SparseArrayData::setAttribute(Object *o, uint index, PropertyAttributes attrs)
{
- SparseArrayData *d = static_cast<SparseArrayData *>(o->arrayData());
- SparseArrayNode *n = d->sparse()->insert(index);
+ Heap::SparseArrayData *d = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ SparseArrayNode *n = d->sparse->insert(index);
if (n->value == UINT_MAX) {
n->value = allocate(o, attrs.isAccessor());
- d = static_cast<SparseArrayData *>(o->arrayData());
+ d = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
}
- else if (attrs.isAccessor() != d->attrs()[n->value].isAccessor()) {
+ else if (attrs.isAccessor() != d->attrs[n->value].isAccessor()) {
// need to convert the slot
- free(d, n->value);
+ free(o->arrayData(), n->value);
n->value = allocate(o, attrs.isAccessor());
+ d = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
}
- o->arrayData()->attrs()[n->value] = attrs;
-}
-
-PropertyAttributes SparseArrayData::attribute(const ArrayData *d, uint index)
-{
- SparseArrayNode *n = static_cast<const SparseArrayData *>(d)->sparse()->insert(index);
- if (!n)
- return PropertyAttributes();
- return d->attrs()[n->value];
+ d->attrs[n->value] = attrs;
}
void SparseArrayData::push_front(Object *o, Value *values, uint n)
{
- SparseArrayData *d = static_cast<SparseArrayData *>(o->arrayData());
- Q_ASSERT(!o->arrayData()->attrs());
+ Heap::SparseArrayData *d = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ Q_ASSERT(!d->attrs);
for (int i = n - 1; i >= 0; --i) {
uint idx = allocate(o);
- d->arrayData()[idx] = values[i];
- d->sparse()->push_front(idx);
+ d = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ d->arrayData[idx] = values[i];
+ d->sparse->push_front(idx);
}
}
ReturnedValue SparseArrayData::pop_front(Object *o)
{
- SparseArrayData *d = static_cast<SparseArrayData *>(o->arrayData());
- Q_ASSERT(!o->arrayData()->attrs());
- uint idx = d->sparse()->pop_front();
+ Heap::SparseArrayData *d = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ Q_ASSERT(!d->attrs);
+ uint idx = d->sparse->pop_front();
ReturnedValue v;
if (idx != UINT_MAX) {
- v = d->arrayData()[idx].asReturnedValue();
+ v = d->arrayData[idx].asReturnedValue();
free(o->arrayData(), idx);
} else {
v = Encode::undefined();
@@ -528,21 +513,21 @@ ReturnedValue SparseArrayData::pop_front(Object *o)
uint SparseArrayData::truncate(Object *o, uint newLen)
{
- SparseArrayData *d = static_cast<SparseArrayData *>(o->arrayData());
- SparseArrayNode *begin = d->sparse()->lowerBound(newLen);
- if (begin != d->sparse()->end()) {
- SparseArrayNode *it = d->sparse()->end()->previousNode();
+ Heap::SparseArrayData *d = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ SparseArrayNode *begin = d->sparse->lowerBound(newLen);
+ if (begin != d->sparse->end()) {
+ SparseArrayNode *it = d->sparse->end()->previousNode();
while (1) {
- if (d->attrs()) {
- if (!d->attrs()[it->value].isConfigurable()) {
+ if (d->attrs) {
+ if (!d->attrs[it->value].isConfigurable()) {
newLen = it->key() + 1;
break;
}
}
- free(d, it->value);
+ free(o->arrayData(), it->value);
bool brk = (it == begin);
SparseArrayNode *prev = it->previousNode();
- static_cast<SparseArrayData *>(d)->sparse()->erase(it);
+ d->sparse->erase(it);
if (brk)
break;
it = prev;
@@ -551,12 +536,12 @@ uint SparseArrayData::truncate(Object *o, uint newLen)
return newLen;
}
-uint SparseArrayData::length(const ArrayData *d)
+uint SparseArrayData::length(const Heap::ArrayData *d)
{
- const SparseArrayData *dd = static_cast<const SparseArrayData *>(d);
- if (!dd->sparse())
+ const Heap::SparseArrayData *dd = static_cast<const Heap::SparseArrayData *>(d);
+ if (!dd->sparse)
return 0;
- SparseArrayNode *n = dd->sparse()->end();
+ SparseArrayNode *n = dd->sparse->end();
n = n->previousNode();
return n ? n->key() + 1 : 0;
}
@@ -571,12 +556,13 @@ bool SparseArrayData::putArray(Object *o, uint index, Value *values, uint n)
uint ArrayData::append(Object *obj, ArrayObject *otherObj, uint n)
{
- Q_ASSERT(!obj->arrayData() || !obj->arrayData()->hasAttributes());
+ Q_ASSERT(!obj->d()->arrayData || !obj->d()->arrayData->attrs);
if (!n)
return obj->getLength();
- ArrayData *other = otherObj->arrayData();
+ Scope scope(obj->engine());
+ Scoped<ArrayData> other(scope, otherObj->arrayData());
if (other && other->isSparse())
obj->initSparseArray();
@@ -585,31 +571,34 @@ uint ArrayData::append(Object *obj, ArrayObject *otherObj, uint n)
uint oldSize = obj->getLength();
- if (other && other->isSparse()) {
- SparseArrayData *os = static_cast<SparseArrayData *>(other);
- if (otherObj->hasAccessorProperty() && other->hasAttributes()) {
- Scope scope(obj->engine());
+ if (!other || ArgumentsObject::isNonStrictArgumentsObject(otherObj)) {
+ ScopedValue v(scope);
+ for (uint i = 0; i < n; ++i)
+ obj->arraySet(oldSize + i, (v = otherObj->getIndexed(i)));
+ } else if (other && other->isSparse()) {
+ Heap::SparseArrayData *os = static_cast<Heap::SparseArrayData *>(other->d());
+ if (other->hasAttributes()) {
ScopedValue v(scope);
- for (const SparseArrayNode *it = os->sparse()->begin();
- it != os->sparse()->end(); it = it->nextNode()) {
- v = otherObj->getValue(reinterpret_cast<Property *>(os->arrayData() + it->value), other->attrs()[it->value]);
+ for (const SparseArrayNode *it = os->sparse->begin();
+ it != os->sparse->end(); it = it->nextNode()) {
+ v = otherObj->getValue(reinterpret_cast<Property *>(os->arrayData + it->value), other->d()->attrs[it->value]);
obj->arraySet(oldSize + it->key(), v);
}
} else {
- for (const SparseArrayNode *it = static_cast<const SparseArrayData *>(other)->sparse()->begin();
- it != os->sparse()->end(); it = it->nextNode())
- obj->arraySet(oldSize + it->key(), ValueRef(os->arrayData()[it->value]));
+ for (const SparseArrayNode *it = other->d()->sparse->begin();
+ it != os->sparse->end(); it = it->nextNode())
+ obj->arraySet(oldSize + it->key(), ValueRef(os->arrayData[it->value]));
}
} else {
- SimpleArrayData *os = static_cast<SimpleArrayData *>(other);
+ Heap::SimpleArrayData *os = static_cast<Heap::SimpleArrayData *>(other->d());
uint toCopy = n;
uint chunk = toCopy;
- if (chunk > os->alloc() - os->d()->offset)
- chunk -= os->alloc() - os->d()->offset;
- obj->arrayPut(oldSize, os->arrayData() + os->d()->offset, chunk);
+ if (chunk > os->alloc - os->offset)
+ chunk -= os->alloc - os->offset;
+ obj->arrayPut(oldSize, os->arrayData + os->offset, chunk);
toCopy -= chunk;
if (toCopy)
- obj->arrayPut(oldSize + chunk, os->arrayData(), toCopy);
+ obj->arrayPut(oldSize + chunk, os->arrayData, toCopy);
}
return oldSize + n;
@@ -617,44 +606,43 @@ uint ArrayData::append(Object *obj, ArrayObject *otherObj, uint n)
Property *ArrayData::insert(Object *o, uint index, bool isAccessor)
{
- if (!isAccessor && o->arrayData()->type() != ArrayData::Sparse) {
- SimpleArrayData *d = static_cast<SimpleArrayData *>(o->arrayData());
- if (index < 0x1000 || index < d->len() + (d->len() >> 2)) {
- if (index >= o->arrayData()->alloc()) {
+ if (!isAccessor && o->d()->arrayData->type != Heap::ArrayData::Sparse) {
+ Heap::SimpleArrayData *d = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ if (index < 0x1000 || index < d->len + (d->len >> 2)) {
+ if (index >= d->alloc) {
o->arrayReserve(index + 1);
- d = static_cast<SimpleArrayData *>(o->arrayData());
+ d = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
}
- if (index >= d->len()) {
+ if (index >= d->len) {
// mark possible hole in the array
- for (uint i = d->len(); i < index; ++i)
+ for (uint i = d->len; i < index; ++i)
d->data(i) = Primitive::emptyValue();
- d->len() = index + 1;
+ d->len = index + 1;
}
- return reinterpret_cast<Property *>(d->d()->arrayData + d->mappedIndex(index));
+ return reinterpret_cast<Property *>(d->arrayData + d->mappedIndex(index));
}
}
o->initSparseArray();
- SparseArrayData *s = static_cast<SparseArrayData *>(o->arrayData());
- SparseArrayNode *n = s->sparse()->insert(index);
- if (n->value == UINT_MAX) {
+ Heap::SparseArrayData *s = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ SparseArrayNode *n = s->sparse->insert(index);
+ if (n->value == UINT_MAX)
n->value = SparseArrayData::allocate(o, isAccessor);
- s = static_cast<SparseArrayData *>(o->arrayData());
- }
- return reinterpret_cast<Property *>(s->arrayData() + n->value);
+ s = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ return reinterpret_cast<Property *>(s->arrayData + n->value);
}
class ArrayElementLessThan
{
public:
- inline ArrayElementLessThan(ExecutionContext *context, Object *thisObject, const ValueRef comparefn)
- : m_context(context), thisObject(thisObject), m_comparefn(comparefn) {}
+ inline ArrayElementLessThan(ExecutionEngine *engine, Object *thisObject, const ValueRef comparefn)
+ : m_engine(engine), thisObject(thisObject), m_comparefn(comparefn) {}
bool operator()(Value v1, Value v2) const;
private:
- ExecutionContext *m_context;
+ ExecutionEngine *m_engine;
Object *thisObject;
const ValueRef m_comparefn;
};
@@ -662,7 +650,7 @@ private:
bool ArrayElementLessThan::operator()(Value v1, Value v2) const
{
- Scope scope(m_context);
+ Scope scope(m_engine);
if (v1.isUndefined() || v1.isEmpty())
return false;
@@ -676,12 +664,12 @@ bool ArrayElementLessThan::operator()(Value v1, Value v2) const
callData->thisObject = Primitive::undefinedValue();
callData->args[0] = v1;
callData->args[1] = v2;
- result = Runtime::callValue(m_context, m_comparefn, callData);
+ result = Runtime::callValue(scope.engine, m_comparefn, callData);
return result->toNumber() < 0;
}
- ScopedString p1s(scope, v1.toString(m_context));
- ScopedString p2s(scope, v2.toString(m_context));
+ ScopedString p1s(scope, v1.toString(scope.engine));
+ ScopedString p2s(scope, v2.toString(scope.engine));
return p1s->toQString() < p2s->toQString();
}
@@ -739,33 +727,36 @@ top:
}
-void ArrayData::sort(ExecutionContext *context, Object *thisObject, const ValueRef comparefn, uint len)
+void ArrayData::sort(ExecutionEngine *engine, Object *thisObject, const ValueRef comparefn, uint len)
{
if (!len)
return;
- if (!thisObject->arrayData() || !thisObject->arrayData()->length())
+ Scope scope(engine);
+ Scoped<ArrayData> arrayData(scope, thisObject->arrayData());
+
+ if (!arrayData || !arrayData->length())
return;
if (!(comparefn->isUndefined() || comparefn->asObject())) {
- context->throwTypeError();
+ engine->throwTypeError();
return;
}
// The spec says the sorting goes through a series of get,put and delete operations.
// this implies that the attributes don't get sorted around.
- if (thisObject->arrayData()->type() == ArrayData::Sparse) {
+ if (arrayData->type() == Heap::ArrayData::Sparse) {
// since we sort anyway, we can simply iterate over the entries in the sparse
// array and append them one by one to a regular one.
- SparseArrayData *sparse = static_cast<SparseArrayData *>(thisObject->arrayData());
+ Scoped<SparseArrayData> sparse(scope, static_cast<Heap::SparseArrayData *>(arrayData->d()));
if (!sparse->sparse()->nEntries())
return;
thisObject->setArrayData(0);
- ArrayData::realloc(thisObject, ArrayData::Simple, sparse->sparse()->nEntries(), sparse->attrs() ? true : false);
- SimpleArrayData *d = static_cast<SimpleArrayData *>(thisObject->arrayData());
+ ArrayData::realloc(thisObject, Heap::ArrayData::Simple, sparse->sparse()->nEntries(), sparse->attrs() ? true : false);
+ Heap::SimpleArrayData *d = static_cast<Heap::SimpleArrayData *>(thisObject->d()->arrayData);
SparseArrayNode *n = sparse->sparse()->begin();
uint i = 0;
@@ -776,7 +767,7 @@ void ArrayData::sort(ExecutionContext *context, Object *thisObject, const ValueR
PropertyAttributes a = sparse->attrs() ? sparse->attrs()[n->value] : Attr_Data;
d->data(i) = thisObject->getValue(reinterpret_cast<Property *>(sparse->arrayData() + n->value), a);
- d->attrs()[i] = a.isAccessor() ? Attr_Data : a;
+ d->attrs[i] = a.isAccessor() ? Attr_Data : a;
n = n->nextNode();
++i;
@@ -790,7 +781,7 @@ void ArrayData::sort(ExecutionContext *context, Object *thisObject, const ValueR
++i;
}
}
- d->len() = i;
+ d->len = i;
if (len > i)
len = i;
if (n != sparse->sparse()->end()) {
@@ -798,17 +789,16 @@ void ArrayData::sort(ExecutionContext *context, Object *thisObject, const ValueR
thisObject->initSparseArray();
while (n != sparse->sparse()->end()) {
PropertyAttributes a = sparse->attrs() ? sparse->attrs()[n->value] : Attr_Data;
- thisObject->arraySet(n->value, *reinterpret_cast<Property *>(sparse->arrayData() + n->value), a);
+ thisObject->arraySet(n->value, reinterpret_cast<Property *>(sparse->arrayData() + n->value), a);
n = n->nextNode();
}
}
- // ### explicitly delete sparse
} else {
- SimpleArrayData *d = static_cast<SimpleArrayData *>(thisObject->arrayData());
- if (len > d->len())
- len = d->len();
+ Heap::SimpleArrayData *d = static_cast<Heap::SimpleArrayData *>(thisObject->d()->arrayData);
+ if (len > d->len)
+ len = d->len;
// sort empty values to the end
for (uint i = 0; i < len; i++) {
@@ -816,7 +806,7 @@ void ArrayData::sort(ExecutionContext *context, Object *thisObject, const ValueR
while (--len > i)
if (!d->data(len).isEmpty())
break;
- Q_ASSERT(!d->attrs() || !d->attrs()[len].isAccessor());
+ Q_ASSERT(!d->attrs || !d->attrs[len].isAccessor());
d->data(i) = d->data(len);
d->data(len) = Primitive::emptyValue();
}
@@ -827,9 +817,9 @@ void ArrayData::sort(ExecutionContext *context, Object *thisObject, const ValueR
}
- ArrayElementLessThan lessThan(context, thisObject, comparefn);
+ ArrayElementLessThan lessThan(engine, thisObject, comparefn);
- Value *begin = thisObject->arrayData()->d()->arrayData;
+ Value *begin = thisObject->arrayData()->arrayData;
sortHelper(begin, begin + len, *begin, lessThan);
#ifdef CHECK_SPARSE_ARRAYS
diff --git a/src/qml/jsruntime/qv4arraydata_p.h b/src/qml/jsruntime/qv4arraydata_p.h
index b69d200665..533d51cd91 100644
--- a/src/qml/jsruntime/qv4arraydata_p.h
+++ b/src/qml/jsruntime/qv4arraydata_p.h
@@ -42,16 +42,14 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
-#define V4_ARRAYDATA \
+#define V4_ARRAYDATA(Data) \
public: \
Q_MANAGED_CHECK \
static const QV4::ArrayVTable static_vtbl; \
static inline const QV4::ManagedVTable *staticVTable() { return &static_vtbl.managedVTable; } \
- template <typename T> \
- QV4::Returned<T> *asReturned() { return QV4::Returned<T>::create(this); } \
V4_MANAGED_SIZE_TEST \
- const Data *d() const { return &static_cast<const Data &>(Managed::data); } \
- Data *d() { return &static_cast<Data &>(Managed::data); }
+ const QV4::Heap::Data *d() const { return static_cast<const QV4::Heap::Data *>(m); } \
+ QV4::Heap::Data *d() { return static_cast<QV4::Heap::Data *>(m); }
struct ArrayData;
@@ -60,22 +58,24 @@ struct ArrayVTable
{
ManagedVTable managedVTable;
uint type;
- ArrayData *(*reallocate)(Object *o, uint n, bool enforceAttributes);
- ReturnedValue (*get)(const ArrayData *d, uint index);
+ Heap::ArrayData *(*reallocate)(Object *o, uint n, bool enforceAttributes);
+ ReturnedValue (*get)(const Heap::ArrayData *d, uint index);
bool (*put)(Object *o, uint index, ValueRef value);
bool (*putArray)(Object *o, uint index, Value *values, uint n);
bool (*del)(Object *o, uint index);
void (*setAttribute)(Object *o, uint index, PropertyAttributes attrs);
- PropertyAttributes (*attribute)(const ArrayData *d, uint index);
void (*push_front)(Object *o, Value *values, uint n);
ReturnedValue (*pop_front)(Object *o);
uint (*truncate)(Object *o, uint newLen);
- uint (*length)(const ArrayData *d);
+ uint (*length)(const Heap::ArrayData *d);
};
+namespace Heap {
-struct Q_QML_EXPORT ArrayData : public Managed
-{
+struct ArrayData : public Base {
+ ArrayData(InternalClass *ic)
+ : Base(ic)
+ {}
enum Type {
Simple = 0,
Complex = 1,
@@ -83,24 +83,94 @@ struct Q_QML_EXPORT ArrayData : public Managed
Custom = 3
};
- struct Data : public Managed::Data {
- Data(InternalClass *ic)
- : Managed::Data(ic)
- {}
- uint alloc;
- Type type;
- PropertyAttributes *attrs;
- union {
- uint len;
- uint freeList;
- };
- union {
- uint offset;
- SparseArray *sparse;
- };
- Value arrayData[1];
+ uint alloc;
+ Type type;
+ PropertyAttributes *attrs;
+ union {
+ uint len;
+ uint freeList;
+ };
+ union {
+ uint offset;
+ SparseArray *sparse;
};
- V4_MANAGED(Managed)
+ Value arrayData[1];
+
+ bool isSparse() const { return type == Sparse; }
+
+ const ArrayVTable *vtable() const { return reinterpret_cast<const ArrayVTable *>(internalClass->vtable); }
+
+ inline ReturnedValue get(uint i) const {
+ return vtable()->get(this, i);
+ }
+ inline Property *getProperty(uint index);
+ inline PropertyAttributes attributes(uint i) const;
+
+ bool isEmpty(uint i) const {
+ return get(i) == Primitive::emptyValue().asReturnedValue();
+ }
+
+ inline ReturnedValue length() const {
+ return vtable()->length(this);
+ }
+
+};
+
+struct SimpleArrayData : public ArrayData {
+ SimpleArrayData(ExecutionEngine *engine)
+ : ArrayData(engine->simpleArrayDataClass)
+ {}
+
+ uint mappedIndex(uint index) const { return (index + offset) % alloc; }
+ Value data(uint index) const { return arrayData[mappedIndex(index)]; }
+ Value &data(uint index) { return arrayData[mappedIndex(index)]; }
+
+ Property *getProperty(uint index) {
+ if (index >= len)
+ return 0;
+ index = mappedIndex(index);
+ if (arrayData[index].isEmpty())
+ return 0;
+ return reinterpret_cast<Property *>(arrayData + index);
+ }
+
+ PropertyAttributes attributes(uint i) const {
+ return attrs ? attrs[i] : Attr_Data;
+ }
+};
+
+struct SparseArrayData : public ArrayData {
+ inline SparseArrayData(ExecutionEngine *engine);
+ inline ~SparseArrayData();
+
+ uint mappedIndex(uint index) const {
+ SparseArrayNode *n = sparse->findNode(index);
+ if (!n)
+ return UINT_MAX;
+ return n->value;
+ }
+
+ Property *getProperty(uint index) {
+ SparseArrayNode *n = sparse->findNode(index);
+ if (!n)
+ return 0;
+ return reinterpret_cast<Property *>(arrayData + n->value);
+ }
+
+ PropertyAttributes attributes(uint i) const {
+ if (!attrs)
+ return Attr_Data;
+ uint index = mappedIndex(i);
+ return index < UINT_MAX ? attrs[index] : Attr_Data;
+ }
+};
+
+}
+
+struct Q_QML_EXPORT ArrayData : public Managed
+{
+ typedef Heap::ArrayData::Type Type;
+ V4_MANAGED(ArrayData, Managed)
uint alloc() const { return d()->alloc; }
uint &alloc() { return d()->alloc; }
@@ -113,87 +183,68 @@ struct Q_QML_EXPORT ArrayData : public Managed
Value *arrayData() { return &d()->arrayData[0]; }
const ArrayVTable *vtable() const { return reinterpret_cast<const ArrayVTable *>(internalClass()->vtable); }
- bool isSparse() const { return type() == Sparse; }
+ bool isSparse() const { return type() == Heap::ArrayData::Sparse; }
uint length() const {
- return vtable()->length(this);
+ return d()->length();
}
bool hasAttributes() const {
return attrs();
}
- PropertyAttributes attributes(int i) const {
- Q_ASSERT(this);
- return attrs() ? vtable()->attribute(this, i) : Attr_Data;
+ PropertyAttributes attributes(uint i) const {
+ return d()->attributes(i);
}
bool isEmpty(uint i) const {
- return (vtable()->get(this, i) == Primitive::emptyValue().asReturnedValue());
+ return d()->isEmpty(i);
}
ReturnedValue get(uint i) const {
- return vtable()->get(this, i);
+ return d()->get(i);
+ }
+ inline Property *getProperty(uint index) {
+ return d()->getProperty(index);
}
- inline Property *getProperty(uint index);
static void ensureAttributes(Object *o);
static void realloc(Object *o, Type newType, uint alloc, bool enforceAttributes);
- static void sort(ExecutionContext *context, Object *thisObject, const ValueRef comparefn, uint dataLen);
+ static void sort(ExecutionEngine *engine, Object *thisObject, const ValueRef comparefn, uint dataLen);
static uint append(Object *obj, ArrayObject *otherObj, uint n);
static Property *insert(Object *o, uint index, bool isAccessor = false);
};
struct Q_QML_EXPORT SimpleArrayData : public ArrayData
{
+ V4_ARRAYDATA(SimpleArrayData)
- struct Data : public ArrayData::Data {
- Data(ExecutionEngine *engine)
- : ArrayData::Data(engine->simpleArrayDataClass)
- {}
- };
- V4_ARRAYDATA
-
- uint mappedIndex(uint index) const { return (index + d()->offset) % d()->alloc; }
- Value data(uint index) const { return d()->arrayData[mappedIndex(index)]; }
- Value &data(uint index) { return d()->arrayData[mappedIndex(index)]; }
-
- Property *getProperty(uint index) {
- if (index >= len())
- return 0;
- index = mappedIndex(index);
- if (d()->arrayData[index].isEmpty())
- return 0;
- return reinterpret_cast<Property *>(d()->arrayData + index);
- }
+ uint mappedIndex(uint index) const { return d()->mappedIndex(index); }
+ Value data(uint index) const { return d()->data(index); }
+ Value &data(uint index) { return d()->data(index); }
uint &len() { return d()->len; }
uint len() const { return d()->len; }
- static ArrayData *reallocate(Object *o, uint n, bool enforceAttributes);
+ static Heap::ArrayData *reallocate(Object *o, uint n, bool enforceAttributes);
- static void markObjects(Managed *d, ExecutionEngine *e);
+ static void markObjects(Heap::Base *d, ExecutionEngine *e);
- static ReturnedValue get(const ArrayData *d, uint index);
+ static ReturnedValue get(const Heap::ArrayData *d, uint index);
static bool put(Object *o, uint index, ValueRef value);
static bool putArray(Object *o, uint index, Value *values, uint n);
static bool del(Object *o, uint index);
static void setAttribute(Object *o, uint index, PropertyAttributes attrs);
- static PropertyAttributes attribute(const ArrayData *d, uint index);
static void push_front(Object *o, Value *values, uint n);
static ReturnedValue pop_front(Object *o);
static uint truncate(Object *o, uint newLen);
- static uint length(const ArrayData *d);
+ static uint length(const Heap::ArrayData *d);
};
struct Q_QML_EXPORT SparseArrayData : public ArrayData
{
- struct Data : public ArrayData::Data {
- Data(ExecutionEngine *engine)
- : ArrayData::Data(engine->emptyClass)
- { setVTable(staticVTable()); }
- };
- V4_ARRAYDATA
+ V4_ARRAYDATA(SparseArrayData)
+ V4_NEEDS_DESTROY
uint &freeList() { return d()->freeList; }
uint freeList() const { return d()->freeList; }
@@ -201,48 +252,51 @@ struct Q_QML_EXPORT SparseArrayData : public ArrayData
void setSparse(SparseArray *s) { d()->sparse = s; }
static uint allocate(Object *o, bool doubleSlot = false);
- static void free(ArrayData *d, uint idx);
+ static void free(Heap::ArrayData *d, uint idx);
- Property *getProperty(uint index) {
- SparseArrayNode *n = sparse()->findNode(index);
- if (!n)
- return 0;
- return reinterpret_cast<Property *>(arrayData() + n->value);
- }
-
- uint mappedIndex(uint index) const {
- SparseArrayNode *n = sparse()->findNode(index);
- if (!n)
- return UINT_MAX;
- return n->value;
- }
+ uint mappedIndex(uint index) const { return d()->mappedIndex(index); }
- static void destroy(Managed *d);
- static void markObjects(Managed *d, ExecutionEngine *e);
+ static void markObjects(Heap::Base *d, ExecutionEngine *e);
- static ArrayData *reallocate(Object *o, uint n, bool enforceAttributes);
- static ReturnedValue get(const ArrayData *d, uint index);
+ static Heap::ArrayData *reallocate(Object *o, uint n, bool enforceAttributes);
+ static ReturnedValue get(const Heap::ArrayData *d, uint index);
static bool put(Object *o, uint index, ValueRef value);
static bool putArray(Object *o, uint index, Value *values, uint n);
static bool del(Object *o, uint index);
static void setAttribute(Object *o, uint index, PropertyAttributes attrs);
- static PropertyAttributes attribute(const ArrayData *d, uint index);
static void push_front(Object *o, Value *values, uint n);
static ReturnedValue pop_front(Object *o);
static uint truncate(Object *o, uint newLen);
- static uint length(const ArrayData *d);
+ static uint length(const Heap::ArrayData *d);
};
+namespace Heap {
+inline SparseArrayData::SparseArrayData(ExecutionEngine *engine)
+ : ArrayData(engine->emptyClass)
+{
+ setVTable(QV4::SparseArrayData::staticVTable());
+}
+
+inline SparseArrayData::~SparseArrayData()
+{
+ delete sparse;
+}
inline Property *ArrayData::getProperty(uint index)
{
- if (type() != Sparse) {
- SimpleArrayData *that = static_cast<SimpleArrayData *>(this);
- return that->getProperty(index);
- } else {
- SparseArrayData *that = static_cast<SparseArrayData *>(this);
- return that->getProperty(index);
- }
+ if (isSparse())
+ return static_cast<SparseArrayData *>(this)->getProperty(index);
+ return static_cast<SimpleArrayData *>(this)->getProperty(index);
+}
+
+inline PropertyAttributes ArrayData::attributes(uint i) const
+{
+ if (isSparse())
+ return static_cast<const SparseArrayData *>(this)->attributes(i);
+ return static_cast<const SimpleArrayData *>(this)->attributes(i);
+}
+
+
}
}
diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp
index 011279ae07..1186afb77c 100644
--- a/src/qml/jsruntime/qv4arrayobject.cpp
+++ b/src/qml/jsruntime/qv4arrayobject.cpp
@@ -35,29 +35,31 @@
#include "qv4sparsearray_p.h"
#include "qv4objectproto_p.h"
#include "qv4scopedvalue_p.h"
+#include "qv4argumentsobject_p.h"
+#include "qv4runtime_p.h"
using namespace QV4;
DEFINE_OBJECT_VTABLE(ArrayCtor);
-ArrayCtor::Data::Data(ExecutionContext *scope)
- : FunctionObject::Data(scope, QStringLiteral("Array"))
+Heap::ArrayCtor::ArrayCtor(QV4::ExecutionContext *scope)
+ : Heap::FunctionObject(scope, QStringLiteral("Array"))
{
- setVTable(staticVTable());
+ setVTable(QV4::ArrayCtor::staticVTable());
}
ReturnedValue ArrayCtor::construct(Managed *m, CallData *callData)
{
ExecutionEngine *v4 = m->engine();
Scope scope(v4);
- Scoped<ArrayObject> a(scope, v4->newArrayObject());
+ ScopedArrayObject a(scope, v4->newArrayObject());
uint len;
if (callData->argc == 1 && callData->args[0].isNumber()) {
bool ok;
len = callData->args[0].asArrayLength(&ok);
if (!ok)
- return v4->currentContext()->throwRangeError(callData->args[0]);
+ return v4->throwRangeError(callData->args[0]);
if (len < 0x1000)
a->arrayReserve(len);
@@ -120,7 +122,7 @@ ReturnedValue ArrayPrototype::method_toString(CallContext *ctx)
if (ctx->d()->engine->hasException)
return Encode::undefined();
ScopedString s(scope, ctx->d()->engine->newString(QStringLiteral("join")));
- ScopedFunctionObject f(scope, o->get(s.getPointer()));
+ ScopedFunctionObject f(scope, o->get(s));
if (!!f) {
ScopedCallData d(scope, 0);
d->thisObject = ctx->d()->callData->thisObject;
@@ -139,12 +141,12 @@ ReturnedValue ArrayPrototype::method_concat(CallContext *ctx)
Scope scope(ctx);
ScopedObject result(scope, ctx->d()->engine->newArrayObject());
- ScopedObject thisObject(scope, ctx->d()->callData->thisObject.toObject(ctx));
+ ScopedObject thisObject(scope, ctx->d()->callData->thisObject.toObject(scope.engine));
if (!thisObject)
return Encode::undefined();
ScopedArrayObject instance(scope, thisObject);
if (instance) {
- result->copyArrayData(instance.getPointer());
+ result->copyArrayData(instance);
} else {
result->arraySet(0, thisObject);
}
@@ -157,7 +159,7 @@ ReturnedValue ArrayPrototype::method_concat(CallContext *ctx)
elt = ctx->d()->callData->args[i];
if (elt) {
uint n = elt->getLength();
- uint newLen = ArrayData::append(result.getPointer(), elt.getPointer(), n);
+ uint newLen = ArrayData::append(result, elt, n);
result->setArrayLengthUnchecked(newLen);
} else if (eltAsObj && eltAsObj->isListType()) {
const uint startIndex = result->getLength();
@@ -189,7 +191,7 @@ ReturnedValue ArrayPrototype::method_join(CallContext *ctx)
const quint32 r2 = length->isUndefined() ? 0 : length->toUInt32();
if (!r2)
- return ctx->d()->engine->newString(QString())->asReturnedValue();
+ return ctx->d()->engine->newString()->asReturnedValue();
QString R;
@@ -204,28 +206,28 @@ ReturnedValue ArrayPrototype::method_join(CallContext *ctx)
if (scope.hasException())
return Encode::undefined();
if (!e->isNullOrUndefined())
- R += e->toString(ctx)->toQString();
+ R += e->toQString();
}
} else {
//
// crazy!
//
ScopedString name(scope, ctx->d()->engine->newString(QStringLiteral("0")));
- ScopedValue r6(scope, self->get(name.getPointer()));
+ ScopedValue r6(scope, self->get(name));
if (!r6->isNullOrUndefined())
- R = r6->toString(ctx)->toQString();
+ R = r6->toQString();
ScopedValue r12(scope);
for (quint32 k = 1; k < r2; ++k) {
R += r4;
- name = Primitive::fromDouble(k).toString(ctx);
- r12 = self->get(name.getPointer());
+ name = Primitive::fromDouble(k).toString(scope.engine);
+ r12 = self->get(name);
if (scope.hasException())
return Encode::undefined();
if (!r12->isNullOrUndefined())
- R += r12->toString(ctx)->toQString();
+ R += r12->toQString();
}
}
@@ -235,7 +237,7 @@ ReturnedValue ArrayPrototype::method_join(CallContext *ctx)
ReturnedValue ArrayPrototype::method_pop(CallContext *ctx)
{
Scope scope(ctx);
- ScopedObject instance(scope, ctx->d()->callData->thisObject.toObject(ctx));
+ ScopedObject instance(scope, ctx->d()->callData->thisObject.toObject(scope.engine));
if (!instance)
return Encode::undefined();
uint len = instance->getLength();
@@ -263,7 +265,7 @@ ReturnedValue ArrayPrototype::method_pop(CallContext *ctx)
ReturnedValue ArrayPrototype::method_push(CallContext *ctx)
{
Scope scope(ctx);
- ScopedObject instance(scope, ctx->d()->callData->thisObject.toObject(ctx));
+ ScopedObject instance(scope, ctx->d()->callData->thisObject.toObject(scope.engine));
if (!instance)
return Encode::undefined();
@@ -277,23 +279,23 @@ ReturnedValue ArrayPrototype::method_push(CallContext *ctx)
double l = len;
ScopedString s(scope);
for (int i = 0; i < ctx->d()->callData->argc; ++i) {
- s = Primitive::fromDouble(l + i).toString(ctx);
- instance->put(s.getPointer(), ctx->d()->callData->args[i]);
+ s = Primitive::fromDouble(l + i).toString(scope.engine);
+ instance->put(s, ctx->d()->callData->args[i]);
}
double newLen = l + ctx->d()->callData->argc;
if (!instance->isArrayObject())
instance->put(ctx->d()->engine->id_length, ScopedValue(scope, Primitive::fromDouble(newLen)));
else {
ScopedString str(scope, ctx->d()->engine->newString(QStringLiteral("Array.prototype.push: Overflow")));
- return ctx->throwRangeError(str);
+ return ctx->engine()->throwRangeError(str);
}
return Encode(newLen);
}
- if (!ctx->d()->callData->argc) {
+ if (!ctx->d()->callData->argc)
;
- } else if (!instance->protoHasArray() && instance->arrayData()->length() <= len && instance->arrayType() == ArrayData::Simple) {
- instance->arrayData()->vtable()->putArray(instance.getPointer(), len, ctx->d()->callData->args, ctx->d()->callData->argc);
+ else if (!instance->protoHasArray() && instance->arrayData()->length() <= len && instance->arrayData()->type == Heap::ArrayData::Simple) {
+ instance->arrayData()->vtable()->putArray(instance, len, ctx->d()->callData->args, ctx->d()->callData->argc);
len = instance->arrayData()->length();
} else {
for (int i = 0; i < ctx->d()->callData->argc; ++i)
@@ -311,7 +313,7 @@ ReturnedValue ArrayPrototype::method_push(CallContext *ctx)
ReturnedValue ArrayPrototype::method_reverse(CallContext *ctx)
{
Scope scope(ctx);
- ScopedObject instance(scope, ctx->d()->callData->thisObject.toObject(ctx));
+ ScopedObject instance(scope, ctx->d()->callData->thisObject.toObject(scope.engine));
if (!instance)
return Encode::undefined();
uint length = instance->getLength();
@@ -343,7 +345,7 @@ ReturnedValue ArrayPrototype::method_reverse(CallContext *ctx)
ReturnedValue ArrayPrototype::method_shift(CallContext *ctx)
{
Scope scope(ctx);
- ScopedObject instance(scope, ctx->d()->callData->thisObject.toObject(ctx));
+ ScopedObject instance(scope, ctx->d()->callData->thisObject.toObject(scope.engine));
if (!instance)
return Encode::undefined();
@@ -360,8 +362,8 @@ ReturnedValue ArrayPrototype::method_shift(CallContext *ctx)
ScopedValue result(scope);
- if (!instance->protoHasArray() && !instance->arrayData()->hasAttributes() && instance->arrayData()->length() <= len && instance->arrayData()->type() != ArrayData::Custom) {
- result = instance->arrayData()->vtable()->pop_front(instance.getPointer());
+ if (!instance->protoHasArray() && !instance->arrayData()->attrs && instance->arrayData()->length() <= len && instance->arrayData()->type != Heap::ArrayData::Custom) {
+ result = instance->arrayData()->vtable()->pop_front(instance);
} else {
result = instance->getIndexed(0);
if (scope.hasException())
@@ -395,11 +397,11 @@ ReturnedValue ArrayPrototype::method_shift(CallContext *ctx)
ReturnedValue ArrayPrototype::method_slice(CallContext *ctx)
{
Scope scope(ctx);
- ScopedObject o(scope, ctx->d()->callData->thisObject.toObject(ctx));
+ ScopedObject o(scope, ctx->d()->callData->thisObject.toObject(scope.engine));
if (!o)
return Encode::undefined();
- Scoped<ArrayObject> result(scope, ctx->d()->engine->newArrayObject());
+ ScopedArrayObject result(scope, ctx->d()->engine->newArrayObject());
uint len = o->getLength();
double s = ScopedValue(scope, ctx->argument(0))->toInteger();
uint start;
@@ -437,26 +439,26 @@ ReturnedValue ArrayPrototype::method_slice(CallContext *ctx)
ReturnedValue ArrayPrototype::method_sort(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<Object> instance(scope, ctx->d()->callData->thisObject.toObject(ctx));
+ ScopedObject instance(scope, ctx->d()->callData->thisObject.toObject(scope.engine));
if (!instance)
return Encode::undefined();
uint len = instance->getLength();
ScopedValue comparefn(scope, ctx->argument(0));
- ArrayData::sort(ctx, instance, comparefn, len);
+ ArrayData::sort(scope.engine, instance, comparefn, len);
return ctx->d()->callData->thisObject.asReturnedValue();
}
ReturnedValue ArrayPrototype::method_splice(CallContext *ctx)
{
Scope scope(ctx);
- ScopedObject instance(scope, ctx->d()->callData->thisObject.toObject(ctx));
+ ScopedObject instance(scope, ctx->d()->callData->thisObject.toObject(scope.engine));
if (!instance)
return Encode::undefined();
uint len = instance->getLength();
- Scoped<ArrayObject> newArray(scope, ctx->d()->engine->newArrayObject());
+ ScopedArrayObject newArray(scope, ctx->d()->engine->newArrayObject());
double rs = ScopedValue(scope, ctx->argument(0))->toInteger();
uint start;
@@ -531,7 +533,7 @@ ReturnedValue ArrayPrototype::method_splice(CallContext *ctx)
ReturnedValue ArrayPrototype::method_unshift(CallContext *ctx)
{
Scope scope(ctx);
- ScopedObject instance(scope, ctx->d()->callData->thisObject.toObject(ctx));
+ ScopedObject instance(scope, ctx->d()->callData->thisObject.toObject(scope.engine));
if (!instance)
return Encode::undefined();
@@ -540,8 +542,9 @@ ReturnedValue ArrayPrototype::method_unshift(CallContext *ctx)
uint len = instance->getLength();
- if (!instance->protoHasArray() && !instance->arrayData()->hasAttributes() && instance->arrayData()->length() <= len && instance->arrayData()->type() != ArrayData::Custom) {
- instance->arrayData()->vtable()->push_front(instance.getPointer(), ctx->d()->callData->args, ctx->d()->callData->argc);
+ if (!instance->protoHasArray() && !instance->arrayData()->attrs && instance->arrayData()->length() <= len &&
+ instance->arrayData()->type != Heap::ArrayData::Custom) {
+ instance->arrayData()->vtable()->push_front(instance, ctx->d()->callData->args, ctx->d()->callData->argc);
} else {
ScopedValue v(scope);
for (uint k = len; k > 0; --k) {
@@ -569,7 +572,7 @@ ReturnedValue ArrayPrototype::method_indexOf(CallContext *ctx)
{
Scope scope(ctx);
- ScopedObject instance(scope, ctx->d()->callData->thisObject.toObject(ctx));
+ ScopedObject instance(scope, ctx->d()->callData->thisObject.toObject(scope.engine));
if (!instance)
return Encode::undefined();
uint len = instance->getLength();
@@ -603,7 +606,8 @@ ReturnedValue ArrayPrototype::method_indexOf(CallContext *ctx)
ScopedValue value(scope);
- if (instance->hasAccessorProperty() || (instance->arrayType() >= ArrayData::Sparse) || instance->protoHasArray()) {
+ if (ArgumentsObject::isNonStrictArgumentsObject(instance) ||
+ (instance->arrayType() >= Heap::ArrayData::Sparse) || instance->protoHasArray()) {
// lets be safe and slow
for (uint i = fromIndex; i < len; ++i) {
bool exists;
@@ -616,10 +620,10 @@ ReturnedValue ArrayPrototype::method_indexOf(CallContext *ctx)
} else if (!instance->arrayData()) {
return Encode(-1);
} else {
- Q_ASSERT(instance->arrayType() == ArrayData::Simple || instance->arrayType() == ArrayData::Complex);
- SimpleArrayData *sa = static_cast<SimpleArrayData *>(instance->arrayData());
- if (len > sa->len())
- len = sa->len();
+ Q_ASSERT(instance->arrayType() == Heap::ArrayData::Simple || instance->arrayType() == Heap::ArrayData::Complex);
+ Heap::SimpleArrayData *sa = static_cast<Heap::SimpleArrayData *>(instance->d()->arrayData);
+ if (len > sa->len)
+ len = sa->len;
uint idx = fromIndex;
while (idx < len) {
value = sa->data(idx);
@@ -637,7 +641,7 @@ ReturnedValue ArrayPrototype::method_lastIndexOf(CallContext *ctx)
{
Scope scope(ctx);
- ScopedObject instance(scope, ctx->d()->callData->thisObject.toObject(ctx));
+ ScopedObject instance(scope, ctx->d()->callData->thisObject.toObject(scope.engine));
if (!instance)
return Encode::undefined();
uint len = instance->getLength();
@@ -682,15 +686,15 @@ ReturnedValue ArrayPrototype::method_lastIndexOf(CallContext *ctx)
ReturnedValue ArrayPrototype::method_every(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<Object> instance(scope, ctx->d()->callData->thisObject.toObject(ctx));
+ ScopedObject instance(scope, ctx->d()->callData->thisObject.toObject(scope.engine));
if (!instance)
return Encode::undefined();
uint len = instance->getLength();
- Scoped<FunctionObject> callback(scope, ctx->argument(0));
+ ScopedFunctionObject callback(scope, ctx->argument(0));
if (!callback)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
ScopedCallData callData(scope, 3);
callData->args[2] = instance;
@@ -716,15 +720,15 @@ ReturnedValue ArrayPrototype::method_every(CallContext *ctx)
ReturnedValue ArrayPrototype::method_some(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<Object> instance(scope, ctx->d()->callData->thisObject.toObject(ctx));
+ ScopedObject instance(scope, ctx->d()->callData->thisObject.toObject(scope.engine));
if (!instance)
return Encode::undefined();
uint len = instance->getLength();
- Scoped<FunctionObject> callback(scope, ctx->argument(0));
+ ScopedFunctionObject callback(scope, ctx->argument(0));
if (!callback)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
ScopedCallData callData(scope, 3);
callData->thisObject = ctx->argument(1);
@@ -750,15 +754,15 @@ ReturnedValue ArrayPrototype::method_some(CallContext *ctx)
ReturnedValue ArrayPrototype::method_forEach(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<Object> instance(scope, ctx->d()->callData->thisObject.toObject(ctx));
+ ScopedObject instance(scope, ctx->d()->callData->thisObject.toObject(scope.engine));
if (!instance)
return Encode::undefined();
uint len = instance->getLength();
- Scoped<FunctionObject> callback(scope, ctx->argument(0));
+ ScopedFunctionObject callback(scope, ctx->argument(0));
if (!callback)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
ScopedCallData callData(scope, 3);
callData->thisObject = ctx->argument(1);
@@ -781,17 +785,17 @@ ReturnedValue ArrayPrototype::method_forEach(CallContext *ctx)
ReturnedValue ArrayPrototype::method_map(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<Object> instance(scope, ctx->d()->callData->thisObject.toObject(ctx));
+ ScopedObject instance(scope, ctx->d()->callData->thisObject.toObject(scope.engine));
if (!instance)
return Encode::undefined();
uint len = instance->getLength();
- Scoped<FunctionObject> callback(scope, ctx->argument(0));
+ ScopedFunctionObject callback(scope, ctx->argument(0));
if (!callback)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
- Scoped<ArrayObject> a(scope, ctx->d()->engine->newArrayObject());
+ ScopedArrayObject a(scope, ctx->d()->engine->newArrayObject());
a->arrayReserve(len);
a->setArrayLengthUnchecked(len);
@@ -818,17 +822,17 @@ ReturnedValue ArrayPrototype::method_map(CallContext *ctx)
ReturnedValue ArrayPrototype::method_filter(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<Object> instance(scope, ctx->d()->callData->thisObject.toObject(ctx));
+ ScopedObject instance(scope, ctx->d()->callData->thisObject.toObject(scope.engine));
if (!instance)
return Encode::undefined();
uint len = instance->getLength();
- Scoped<FunctionObject> callback(scope, ctx->argument(0));
+ ScopedFunctionObject callback(scope, ctx->argument(0));
if (!callback)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
- Scoped<ArrayObject> a(scope, ctx->d()->engine->newArrayObject());
+ ScopedArrayObject a(scope, ctx->d()->engine->newArrayObject());
a->arrayReserve(len);
ScopedValue selected(scope);
@@ -859,15 +863,15 @@ ReturnedValue ArrayPrototype::method_filter(CallContext *ctx)
ReturnedValue ArrayPrototype::method_reduce(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<Object> instance(scope, ctx->d()->callData->thisObject.toObject(ctx));
+ ScopedObject instance(scope, ctx->d()->callData->thisObject.toObject(scope.engine));
if (!instance)
return Encode::undefined();
uint len = instance->getLength();
- Scoped<FunctionObject> callback(scope, ctx->argument(0));
+ ScopedFunctionObject callback(scope, ctx->argument(0));
if (!callback)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
uint k = 0;
ScopedValue acc(scope);
@@ -884,7 +888,7 @@ ReturnedValue ArrayPrototype::method_reduce(CallContext *ctx)
++k;
}
if (!kPresent)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
}
ScopedCallData callData(scope, 4);
@@ -909,19 +913,19 @@ ReturnedValue ArrayPrototype::method_reduce(CallContext *ctx)
ReturnedValue ArrayPrototype::method_reduceRight(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<Object> instance(scope, ctx->d()->callData->thisObject.toObject(ctx));
+ ScopedObject instance(scope, ctx->d()->callData->thisObject.toObject(scope.engine));
if (!instance)
return Encode::undefined();
uint len = instance->getLength();
- Scoped<FunctionObject> callback(scope, ctx->argument(0));
+ ScopedFunctionObject callback(scope, ctx->argument(0));
if (!callback)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
if (len == 0) {
if (ctx->d()->callData->argc == 1)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
return ctx->argument(1);
}
@@ -939,7 +943,7 @@ ReturnedValue ArrayPrototype::method_reduceRight(CallContext *ctx)
--k;
}
if (!kPresent)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
}
ScopedCallData callData(scope, 4);
diff --git a/src/qml/jsruntime/qv4arrayobject_p.h b/src/qml/jsruntime/qv4arrayobject_p.h
index 9cd967ddd9..cbb3c24bc2 100644
--- a/src/qml/jsruntime/qv4arrayobject_p.h
+++ b/src/qml/jsruntime/qv4arrayobject_p.h
@@ -41,13 +41,17 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
+namespace Heap {
+
+struct ArrayCtor : FunctionObject {
+ ArrayCtor(QV4::ExecutionContext *scope);
+};
+
+}
+
struct ArrayCtor: FunctionObject
{
- struct Data : FunctionObject::Data {
- Data(ExecutionContext *scope);
- };
-
- V4_OBJECT(FunctionObject)
+ V4_OBJECT2(ArrayCtor, FunctionObject)
static ReturnedValue construct(Managed *m, CallData *callData);
static ReturnedValue call(Managed *that, CallData *callData);
diff --git a/src/qml/jsruntime/qv4booleanobject.cpp b/src/qml/jsruntime/qv4booleanobject.cpp
index b58fcbe709..6de7059034 100644
--- a/src/qml/jsruntime/qv4booleanobject.cpp
+++ b/src/qml/jsruntime/qv4booleanobject.cpp
@@ -38,10 +38,10 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(BooleanCtor);
DEFINE_OBJECT_VTABLE(BooleanObject);
-BooleanCtor::Data::Data(ExecutionContext *scope)
- : FunctionObject::Data(scope, QStringLiteral("Boolean"))
+Heap::BooleanCtor::BooleanCtor(QV4::ExecutionContext *scope)
+ : Heap::FunctionObject(scope, QStringLiteral("Boolean"))
{
- setVTable(staticVTable());
+ setVTable(QV4::BooleanCtor::staticVTable());
}
ReturnedValue BooleanCtor::construct(Managed *m, CallData *callData)
@@ -78,7 +78,7 @@ ReturnedValue BooleanPrototype::method_toString(CallContext *ctx)
Scope scope(ctx);
Scoped<BooleanObject> thisObject(scope, ctx->d()->callData->thisObject);
if (!thisObject)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
result = thisObject->value().booleanValue();
}
@@ -93,7 +93,7 @@ ReturnedValue BooleanPrototype::method_valueOf(CallContext *ctx)
Scope scope(ctx);
Scoped<BooleanObject> thisObject(scope, ctx->d()->callData->thisObject);
if (!thisObject)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
return thisObject->value().asReturnedValue();
}
diff --git a/src/qml/jsruntime/qv4booleanobject_p.h b/src/qml/jsruntime/qv4booleanobject_p.h
index 2e96b72b64..c956c01853 100644
--- a/src/qml/jsruntime/qv4booleanobject_p.h
+++ b/src/qml/jsruntime/qv4booleanobject_p.h
@@ -41,13 +41,17 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
+namespace Heap {
+
+struct BooleanCtor : FunctionObject {
+ BooleanCtor(QV4::ExecutionContext *scope);
+};
+
+}
+
struct BooleanCtor: FunctionObject
{
- struct Data : FunctionObject::Data {
- Data(ExecutionContext *scope);
- };
-
- V4_OBJECT(FunctionObject)
+ V4_OBJECT2(BooleanCtor, FunctionObject)
static ReturnedValue construct(Managed *, CallData *callData);
static ReturnedValue call(Managed *that, CallData *callData);
diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp
index 5ca47a80b1..40c02ef4ee 100644
--- a/src/qml/jsruntime/qv4context.cpp
+++ b/src/qml/jsruntime/qv4context.cpp
@@ -46,16 +46,17 @@ using namespace QV4;
DEFINE_MANAGED_VTABLE(ExecutionContext);
DEFINE_MANAGED_VTABLE(CallContext);
DEFINE_MANAGED_VTABLE(WithContext);
+DEFINE_MANAGED_VTABLE(CatchContext);
DEFINE_MANAGED_VTABLE(GlobalContext);
-HeapObject *ExecutionContext::newCallContext(FunctionObject *function, CallData *callData)
+Heap::CallContext *ExecutionContext::newCallContext(FunctionObject *function, CallData *callData)
{
Q_ASSERT(function->function());
- CallContext::Data *c = reinterpret_cast<CallContext::Data *>(d()->engine->memoryManager->allocManaged(requiredMemoryForExecutionContect(function, callData->argc)));
- new (c) CallContext::Data(d()->engine, Type_CallContext);
+ Heap::CallContext *c = static_cast<Heap::CallContext *>(d()->engine->memoryManager->allocManaged(requiredMemoryForExecutionContect(function, callData->argc)));
+ new (c) Heap::CallContext(d()->engine, Heap::ExecutionContext::Type_CallContext);
- c->function = function;
+ c->function = function->d();
c->realArgumentCount = callData->argc;
c->strictMode = function->strictMode();
@@ -81,21 +82,22 @@ HeapObject *ExecutionContext::newCallContext(FunctionObject *function, CallData
return c;
}
-WithContext *ExecutionContext::newWithContext(Object *with)
+Heap::WithContext *ExecutionContext::newWithContext(Object *with)
{
return d()->engine->memoryManager->alloc<WithContext>(d()->engine, with);
}
-CatchContext *ExecutionContext::newCatchContext(String *exceptionVarName, const ValueRef exceptionValue)
+Heap::CatchContext *ExecutionContext::newCatchContext(String *exceptionVarName, const ValueRef exceptionValue)
{
return d()->engine->memoryManager->alloc<CatchContext>(d()->engine, exceptionVarName, exceptionValue);
}
-CallContext *ExecutionContext::newQmlContext(FunctionObject *f, Object *qml)
+Heap::CallContext *ExecutionContext::newQmlContext(FunctionObject *f, Object *qml)
{
- CallContext *c = reinterpret_cast<CallContext*>(d()->engine->memoryManager->allocManaged(requiredMemoryForExecutionContect(f, 0)));
- new (c->d()) CallContext::Data(d()->engine, qml, f);
- return c;
+ Scope scope(this);
+ Scoped<CallContext> c(scope, static_cast<Heap::CallContext*>(d()->engine->memoryManager->allocManaged(requiredMemoryForExecutionContect(f, 0))));
+ new (c->d()) Heap::CallContext(d()->engine, qml, f);
+ return c->d();
}
@@ -105,14 +107,14 @@ void ExecutionContext::createMutableBinding(String *name, bool deletable)
Scope scope(this);
// find the right context to create the binding on
- ScopedObject activation(scope, d()->engine->globalObject);
- ExecutionContext *ctx = this;
+ ScopedObject activation(scope, d()->engine->globalObject());
+ ScopedContext ctx(scope, this);
while (ctx) {
- if (ctx->d()->type >= Type_CallContext) {
- CallContext *c = static_cast<CallContext *>(ctx);
- if (!c->d()->activation)
- c->d()->activation = d()->engine->newObject()->getPointer();
- activation = c->d()->activation;
+ if (ctx->d()->type >= Heap::ExecutionContext::Type_CallContext) {
+ Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx->d());
+ if (!c->activation)
+ c->activation = scope.engine->newObject();
+ activation = c->activation;
break;
}
ctx = ctx->d()->outer;
@@ -120,47 +122,47 @@ void ExecutionContext::createMutableBinding(String *name, bool deletable)
if (activation->hasProperty(name))
return;
- Property desc(Primitive::undefinedValue());
+ ScopedProperty desc(scope);
PropertyAttributes attrs(Attr_Data);
attrs.setConfigurable(deletable);
- activation->__defineOwnProperty__(this, name, desc, attrs);
+ activation->__defineOwnProperty__(scope.engine, name, desc, attrs);
}
-GlobalContext::Data::Data(ExecutionEngine *eng)
- : ExecutionContext::Data(eng, Type_GlobalContext)
+Heap::GlobalContext::GlobalContext(ExecutionEngine *eng)
+ : Heap::ExecutionContext(eng, Heap::ExecutionContext::Type_GlobalContext)
{
- global = eng->globalObject;
+ global = eng->globalObject()->d();
}
-WithContext::Data::Data(ExecutionEngine *engine, Object *with)
- : ExecutionContext::Data(engine, Type_WithContext)
+Heap::WithContext::WithContext(ExecutionEngine *engine, QV4::Object *with)
+ : Heap::ExecutionContext(engine, Heap::ExecutionContext::Type_WithContext)
{
- callData = parent->d()->callData;
+ callData = parent->callData;
outer = parent;
- lookups = parent->d()->lookups;
- compilationUnit = parent->d()->compilationUnit;
+ lookups = parent->lookups;
+ compilationUnit = parent->compilationUnit;
- withObject = with;
+ withObject = with ? with->d() : 0;
}
-CatchContext::Data::Data(ExecutionEngine *engine, String *exceptionVarName, const ValueRef exceptionValue)
- : ExecutionContext::Data(engine, Type_CatchContext)
+Heap::CatchContext::CatchContext(ExecutionEngine *engine, QV4::String *exceptionVarName, const ValueRef exceptionValue)
+ : Heap::ExecutionContext(engine, Heap::ExecutionContext::Type_CatchContext)
{
- strictMode = parent->d()->strictMode;
- callData = parent->d()->callData;
+ strictMode = parent->strictMode;
+ callData = parent->callData;
outer = parent;
- lookups = parent->d()->lookups;
- compilationUnit = parent->d()->compilationUnit;
+ lookups = parent->lookups;
+ compilationUnit = parent->compilationUnit;
this->exceptionVarName = exceptionVarName;
this->exceptionValue = exceptionValue;
}
-CallContext::Data::Data(ExecutionEngine *engine, Object *qml, FunctionObject *function)
- : ExecutionContext::Data(engine, Type_QmlContext)
+Heap::CallContext::CallContext(ExecutionEngine *engine, QV4::Object *qml, QV4::FunctionObject *function)
+ : Heap::ExecutionContext(engine, Heap::ExecutionContext::Type_QmlContext)
{
- this->function = function;
+ this->function = function->d();
callData = reinterpret_cast<CallData *>(this + 1);
callData->tag = QV4::Value::_Integer_Type;
callData->argc = 0;
@@ -169,7 +171,7 @@ CallContext::Data::Data(ExecutionEngine *engine, Object *qml, FunctionObject *fu
strictMode = true;
outer = function->scope();
- activation = qml;
+ activation = qml->d();
if (function->function()) {
compilationUnit = function->function()->compilationUnit;
@@ -181,9 +183,9 @@ CallContext::Data::Data(ExecutionEngine *engine, Object *qml, FunctionObject *fu
std::fill(locals, locals + function->varCount(), Primitive::undefinedValue());
}
-String * const *CallContext::formals() const
+Identifier * const *CallContext::formals() const
{
- return (d()->function && d()->function->function()) ? d()->function->function()->internalClass->nameMap.constData() : 0;
+ return (d()->function && d()->function->function) ? d()->function->function->internalClass->nameMap.constData() : 0;
}
unsigned int CallContext::formalCount() const
@@ -191,9 +193,9 @@ unsigned int CallContext::formalCount() const
return d()->function ? d()->function->formalParameterCount() : 0;
}
-String * const *CallContext::variables() const
+Identifier * const *CallContext::variables() const
{
- return (d()->function && d()->function->function()) ? d()->function->function()->internalClass->nameMap.constData() + d()->function->function()->compiledFunction->nFormals : 0;
+ return (d()->function && d()->function->function) ? d()->function->function->internalClass->nameMap.constData() + d()->function->formalParameterCount() : 0;
}
unsigned int CallContext::variableCount() const
@@ -207,36 +209,38 @@ bool ExecutionContext::deleteProperty(String *name)
{
Scope scope(this);
bool hasWith = false;
- for (ExecutionContext *ctx = this; ctx; ctx = ctx->d()->outer) {
- if (ctx->d()->type == Type_WithContext) {
+ ScopedContext ctx(scope, this);
+ for (; ctx; ctx = ctx->d()->outer) {
+ if (ctx->d()->type == Heap::ExecutionContext::Type_WithContext) {
hasWith = true;
- WithContext *w = static_cast<WithContext *>(ctx);
- if (w->d()->withObject->hasProperty(name))
- return w->d()->withObject->deleteProperty(name);
- } else if (ctx->d()->type == Type_CatchContext) {
- CatchContext *c = static_cast<CatchContext *>(ctx);
- if (c->d()->exceptionVarName->isEqualTo(name))
+ ScopedObject withObject(scope, static_cast<Heap::WithContext *>(ctx->d())->withObject);
+ if (withObject->hasProperty(name))
+ return withObject->deleteProperty(name);
+ } else if (ctx->d()->type == Heap::ExecutionContext::Type_CatchContext) {
+ Heap::CatchContext *c = static_cast<Heap::CatchContext *>(ctx->d());
+ if (c->exceptionVarName->isEqualTo(name))
return false;
- } else if (ctx->d()->type >= Type_CallContext) {
- CallContext *c = static_cast<CallContext *>(ctx);
- FunctionObject *f = c->d()->function;
+ } else if (ctx->d()->type >= Heap::ExecutionContext::Type_CallContext) {
+ Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx->d());
+ ScopedFunctionObject f(scope, c->function);
if (f->needsActivation() || hasWith) {
uint index = f->function()->internalClass->find(name);
if (index < UINT_MAX)
// ### throw in strict mode?
return false;
}
- if (c->d()->activation && c->d()->activation->hasProperty(name))
- return c->d()->activation->deleteProperty(name);
- } else if (ctx->d()->type == Type_GlobalContext) {
- GlobalContext *g = static_cast<GlobalContext *>(ctx);
- if (g->d()->global->hasProperty(name))
- return g->d()->global->deleteProperty(name);
+ ScopedObject activation(scope, c->activation);
+ if (activation && activation->hasProperty(name))
+ return activation->deleteProperty(name);
+ } else if (ctx->d()->type == Heap::ExecutionContext::Type_GlobalContext) {
+ ScopedObject global(scope, static_cast<Heap::GlobalContext *>(ctx->d())->global);
+ if (global->hasProperty(name))
+ return global->deleteProperty(name);
}
}
if (d()->strictMode)
- throwSyntaxError(QStringLiteral("Can't delete property %1").arg(name->toQString()));
+ engine()->throwSyntaxError(QStringLiteral("Can't delete property %1").arg(name->toQString()));
return true;
}
@@ -245,74 +249,76 @@ bool CallContext::needsOwnArguments() const
return d()->function->needsActivation() || d()->callData->argc < static_cast<int>(d()->function->formalParameterCount());
}
-void ExecutionContext::markObjects(Managed *m, ExecutionEngine *engine)
+void ExecutionContext::markObjects(Heap::Base *m, ExecutionEngine *engine)
{
- ExecutionContext *ctx = static_cast<ExecutionContext *>(m);
+ ExecutionContext::Data *ctx = static_cast<ExecutionContext::Data *>(m);
- if (ctx->d()->outer)
- ctx->d()->outer->mark(engine);
+ if (ctx->outer)
+ ctx->outer->mark(engine);
// ### shouldn't need these 3 lines
- ctx->d()->callData->thisObject.mark(engine);
- for (int arg = 0; arg < ctx->d()->callData->argc; ++arg)
- ctx->d()->callData->args[arg].mark(engine);
-
- if (ctx->d()->type >= Type_CallContext) {
- QV4::CallContext *c = static_cast<CallContext *>(ctx);
- for (unsigned local = 0, lastLocal = c->d()->function->varCount(); local < lastLocal; ++local)
- c->d()->locals[local].mark(engine);
- if (c->d()->activation)
- c->d()->activation->mark(engine);
- c->d()->function->mark(engine);
- } else if (ctx->d()->type == Type_WithContext) {
- WithContext *w = static_cast<WithContext *>(ctx);
- w->d()->withObject->mark(engine);
- } else if (ctx->d()->type == Type_CatchContext) {
- CatchContext *c = static_cast<CatchContext *>(ctx);
- c->d()->exceptionVarName->mark(engine);
- c->d()->exceptionValue.mark(engine);
- } else if (ctx->d()->type == Type_GlobalContext) {
- GlobalContext *g = static_cast<GlobalContext *>(ctx);
- g->d()->global->mark(engine);
+ ctx->callData->thisObject.mark(engine);
+ for (int arg = 0; arg < ctx->callData->argc; ++arg)
+ ctx->callData->args[arg].mark(engine);
+
+ if (ctx->type >= Heap::ExecutionContext::Type_CallContext) {
+ QV4::Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx);
+ for (unsigned local = 0, lastLocal = c->function->varCount(); local < lastLocal; ++local)
+ c->locals[local].mark(engine);
+ if (c->activation)
+ c->activation->mark(engine);
+ c->function->mark(engine);
+ } else if (ctx->type == Heap::ExecutionContext::Type_WithContext) {
+ WithContext::Data *w = static_cast<WithContext::Data *>(ctx);
+ if (w->withObject)
+ w->withObject->mark(engine);
+ } else if (ctx->type == Heap::ExecutionContext::Type_CatchContext) {
+ CatchContext::Data *c = static_cast<CatchContext::Data *>(ctx);
+ c->exceptionVarName->mark(engine);
+ c->exceptionValue.mark(engine);
+ } else if (ctx->type == Heap::ExecutionContext::Type_GlobalContext) {
+ GlobalContext::Data *g = static_cast<GlobalContext::Data *>(ctx);
+ g->global->mark(engine);
}
}
void ExecutionContext::setProperty(String *name, const ValueRef value)
{
Scope scope(this);
- for (ExecutionContext *ctx = this; ctx; ctx = ctx->d()->outer) {
- if (ctx->d()->type == Type_WithContext) {
- ScopedObject w(scope, static_cast<WithContext *>(ctx)->d()->withObject);
+ ScopedContext ctx(scope, this);
+ for (; ctx; ctx = ctx->d()->outer) {
+ if (ctx->d()->type == Heap::ExecutionContext::Type_WithContext) {
+ ScopedObject w(scope, static_cast<Heap::WithContext *>(ctx->d())->withObject);
if (w->hasProperty(name)) {
w->put(name, value);
return;
}
- } else if (ctx->d()->type == Type_CatchContext && static_cast<CatchContext *>(ctx)->d()->exceptionVarName->isEqualTo(name)) {
- static_cast<CatchContext *>(ctx)->d()->exceptionValue = *value;
+ } else if (ctx->d()->type == Heap::ExecutionContext::Type_CatchContext && static_cast<Heap::CatchContext *>(ctx->d())->exceptionVarName->isEqualTo(name)) {
+ static_cast<Heap::CatchContext *>(ctx->d())->exceptionValue = *value;
return;
} else {
ScopedObject activation(scope, (Object *)0);
- if (ctx->d()->type >= Type_CallContext) {
- CallContext *c = static_cast<CallContext *>(ctx);
- if (c->d()->function->function()) {
- uint index = c->d()->function->function()->internalClass->find(name);
+ if (ctx->d()->type >= Heap::ExecutionContext::Type_CallContext) {
+ Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx->d());
+ if (c->function->function) {
+ uint index = c->function->function->internalClass->find(name);
if (index < UINT_MAX) {
- if (index < c->d()->function->formalParameterCount()) {
- c->d()->callData->args[c->d()->function->formalParameterCount() - index - 1] = *value;
+ if (index < c->function->formalParameterCount()) {
+ c->callData->args[c->function->formalParameterCount() - index - 1] = *value;
} else {
- index -= c->d()->function->formalParameterCount();
- c->d()->locals[index] = *value;
+ index -= c->function->formalParameterCount();
+ c->locals[index] = *value;
}
return;
}
}
- activation = c->d()->activation;
- } else if (ctx->d()->type == Type_GlobalContext) {
- activation = static_cast<GlobalContext *>(ctx)->d()->global;
+ activation = c->activation;
+ } else if (ctx->d()->type == Heap::ExecutionContext::Type_GlobalContext) {
+ activation = static_cast<Heap::GlobalContext *>(ctx->d())->global;
}
if (activation) {
- if (ctx->d()->type == Type_QmlContext) {
+ if (ctx->d()->type == Heap::ExecutionContext::Type_QmlContext) {
activation->put(name, value);
return;
} else {
@@ -325,12 +331,12 @@ void ExecutionContext::setProperty(String *name, const ValueRef value)
}
}
}
- if (d()->strictMode || name->equals(d()->engine->id_this.getPointer())) {
+ if (d()->strictMode || name->equals(d()->engine->id_this)) {
ScopedValue n(scope, name->asReturnedValue());
- throwReferenceError(n);
+ engine()->throwReferenceError(n);
return;
}
- d()->engine->globalObject->put(name, value);
+ d()->engine->globalObject()->put(name, value);
}
ReturnedValue ExecutionContext::getProperty(String *name)
@@ -339,14 +345,15 @@ ReturnedValue ExecutionContext::getProperty(String *name)
ScopedValue v(scope);
name->makeIdentifier();
- if (name->equals(d()->engine->id_this.getPointer()))
+ if (name->equals(d()->engine->id_this))
return d()->callData->thisObject.asReturnedValue();
bool hasWith = false;
bool hasCatchScope = false;
- for (ExecutionContext *ctx = this; ctx; ctx = ctx->d()->outer) {
- if (ctx->d()->type == Type_WithContext) {
- ScopedObject w(scope, static_cast<WithContext *>(ctx)->d()->withObject);
+ ScopedContext ctx(scope, this);
+ for (; ctx; ctx = ctx->d()->outer) {
+ if (ctx->d()->type == Heap::ExecutionContext::Type_WithContext) {
+ ScopedObject w(scope, static_cast<Heap::WithContext *>(ctx->d())->withObject);
hasWith = true;
bool hasProperty = false;
v = w->get(name, &hasProperty);
@@ -356,207 +363,131 @@ ReturnedValue ExecutionContext::getProperty(String *name)
continue;
}
- else if (ctx->d()->type == Type_CatchContext) {
+ else if (ctx->d()->type == Heap::ExecutionContext::Type_CatchContext) {
hasCatchScope = true;
- CatchContext *c = static_cast<CatchContext *>(ctx);
- if (c->d()->exceptionVarName->isEqualTo(name))
- return c->d()->exceptionValue.asReturnedValue();
+ Heap::CatchContext *c = static_cast<Heap::CatchContext *>(ctx->d());
+ if (c->exceptionVarName->isEqualTo(name))
+ return c->exceptionValue.asReturnedValue();
}
- else if (ctx->d()->type >= Type_CallContext) {
- QV4::CallContext *c = static_cast<CallContext *>(ctx);
- ScopedFunctionObject f(scope, c->d()->function);
+ else if (ctx->d()->type >= Heap::ExecutionContext::Type_CallContext) {
+ Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx->d());
+ ScopedFunctionObject f(scope, c->function);
if (f->function() && (f->needsActivation() || hasWith || hasCatchScope)) {
uint index = f->function()->internalClass->find(name);
if (index < UINT_MAX) {
- if (index < c->d()->function->formalParameterCount())
- return c->d()->callData->args[c->d()->function->formalParameterCount() - index - 1].asReturnedValue();
- return c->d()->locals[index - c->d()->function->formalParameterCount()].asReturnedValue();
+ if (index < c->function->formalParameterCount())
+ return c->callData->args[c->function->formalParameterCount() - index - 1].asReturnedValue();
+ return c->locals[index - c->function->formalParameterCount()].asReturnedValue();
}
}
- if (c->d()->activation) {
+ ScopedObject activation(scope, c->activation);
+ if (activation) {
bool hasProperty = false;
- v = c->d()->activation->get(name, &hasProperty);
+ v = activation->get(name, &hasProperty);
if (hasProperty)
return v.asReturnedValue();
}
if (f->function() && f->function()->isNamedExpression()
- && name->equals(f->function()->name()))
+ && name->equals(ScopedString(scope, f->function()->name())))
return f.asReturnedValue();
}
- else if (ctx->d()->type == Type_GlobalContext) {
- GlobalContext *g = static_cast<GlobalContext *>(ctx);
+ else if (ctx->d()->type == Heap::ExecutionContext::Type_GlobalContext) {
+ ScopedObject global(scope, static_cast<Heap::GlobalContext *>(ctx->d())->global);
bool hasProperty = false;
- v = g->d()->global->get(name, &hasProperty);
+ v = global->get(name, &hasProperty);
if (hasProperty)
return v.asReturnedValue();
}
}
ScopedValue n(scope, name);
- return throwReferenceError(n);
+ return engine()->throwReferenceError(n);
}
-ReturnedValue ExecutionContext::getPropertyAndBase(String *name, Object *&base)
+ReturnedValue ExecutionContext::getPropertyAndBase(String *name, Heap::Object **base)
{
Scope scope(this);
ScopedValue v(scope);
- base = (Object *)0;
+ *base = (Heap::Object *)0;
name->makeIdentifier();
- if (name->equals(d()->engine->id_this.getPointer()))
+ if (name->equals(d()->engine->id_this))
return d()->callData->thisObject.asReturnedValue();
bool hasWith = false;
bool hasCatchScope = false;
- for (ExecutionContext *ctx = this; ctx; ctx = ctx->d()->outer) {
- if (ctx->d()->type == Type_WithContext) {
- Object *w = static_cast<WithContext *>(ctx)->d()->withObject;
+ ScopedContext ctx(scope, this);
+ for (; ctx; ctx = ctx->d()->outer) {
+ if (ctx->d()->type == Heap::ExecutionContext::Type_WithContext) {
+ ScopedObject w(scope, static_cast<Heap::WithContext *>(ctx->d())->withObject);
hasWith = true;
bool hasProperty = false;
v = w->get(name, &hasProperty);
if (hasProperty) {
- base = w;
+ *base = w->d();
return v.asReturnedValue();
}
continue;
}
- else if (ctx->d()->type == Type_CatchContext) {
+ else if (ctx->d()->type == Heap::ExecutionContext::Type_CatchContext) {
hasCatchScope = true;
- CatchContext *c = static_cast<CatchContext *>(ctx);
- if (c->d()->exceptionVarName->isEqualTo(name))
- return c->d()->exceptionValue.asReturnedValue();
+ Heap::CatchContext *c = static_cast<Heap::CatchContext *>(ctx->d());
+ if (c->exceptionVarName->isEqualTo(name))
+ return c->exceptionValue.asReturnedValue();
}
- else if (ctx->d()->type >= Type_CallContext) {
- QV4::CallContext *c = static_cast<CallContext *>(ctx);
- FunctionObject *f = c->d()->function;
+ else if (ctx->d()->type >= Heap::ExecutionContext::Type_CallContext) {
+ Heap::CallContext *c = static_cast<Heap::CallContext *>(ctx->d());
+ ScopedFunctionObject f(scope, c->function);
if (f->function() && (f->needsActivation() || hasWith || hasCatchScope)) {
uint index = f->function()->internalClass->find(name);
if (index < UINT_MAX) {
- if (index < c->d()->function->formalParameterCount())
- return c->d()->callData->args[c->d()->function->formalParameterCount() - index - 1].asReturnedValue();
- return c->d()->locals[index - c->d()->function->formalParameterCount()].asReturnedValue();
+ if (index < f->formalParameterCount())
+ return c->callData->args[f->formalParameterCount() - index - 1].asReturnedValue();
+ return c->locals[index - f->formalParameterCount()].asReturnedValue();
}
}
- if (c->d()->activation) {
+ ScopedObject activation(scope, c->activation);
+ if (activation) {
bool hasProperty = false;
- v = c->d()->activation->get(name, &hasProperty);
+ v = activation->get(name, &hasProperty);
if (hasProperty) {
- if (ctx->d()->type == Type_QmlContext)
- base = c->d()->activation;
+ if (ctx->d()->type == Heap::ExecutionContext::Type_QmlContext)
+ *base = activation->d();
return v.asReturnedValue();
}
}
if (f->function() && f->function()->isNamedExpression()
- && name->equals(f->function()->name()))
- return c->d()->function->asReturnedValue();
+ && name->equals(ScopedString(scope, f->function()->name())))
+ return c->function->asReturnedValue();
}
- else if (ctx->d()->type == Type_GlobalContext) {
- GlobalContext *g = static_cast<GlobalContext *>(ctx);
+ else if (ctx->d()->type == Heap::ExecutionContext::Type_GlobalContext) {
+ ScopedObject global(scope, static_cast<Heap::GlobalContext *>(ctx->d())->global);
bool hasProperty = false;
- v = g->d()->global->get(name, &hasProperty);
+ v = global->get(name, &hasProperty);
if (hasProperty)
return v.asReturnedValue();
}
}
ScopedValue n(scope, name);
- return throwReferenceError(n);
-}
-
-
-ReturnedValue ExecutionContext::throwError(const ValueRef value)
-{
- return d()->engine->throwException(value);
+ return engine()->throwReferenceError(n);
}
-ReturnedValue ExecutionContext::throwError(const QString &message)
+Heap::FunctionObject *ExecutionContext::getFunctionObject() const
{
- Scope scope(this);
- ScopedValue v(scope, d()->engine->newString(message));
- v = d()->engine->newErrorObject(v);
- return throwError(v);
-}
-
-ReturnedValue ExecutionContext::throwSyntaxError(const QString &message, const QString &fileName, int line, int column)
-{
- Scope scope(this);
- Scoped<Object> error(scope, d()->engine->newSyntaxErrorObject(message, fileName, line, column));
- return throwError(error);
-}
-
-ReturnedValue ExecutionContext::throwSyntaxError(const QString &message)
-{
- Scope scope(this);
- Scoped<Object> error(scope, d()->engine->newSyntaxErrorObject(message));
- return throwError(error);
-}
-
-ReturnedValue ExecutionContext::throwTypeError()
-{
- Scope scope(this);
- Scoped<Object> error(scope, d()->engine->newTypeErrorObject(QStringLiteral("Type error")));
- return throwError(error);
-}
-
-ReturnedValue ExecutionContext::throwTypeError(const QString &message)
-{
- Scope scope(this);
- Scoped<Object> error(scope, d()->engine->newTypeErrorObject(message));
- return throwError(error);
-}
-
-ReturnedValue ExecutionContext::throwUnimplemented(const QString &message)
-{
- Scope scope(this);
- ScopedValue v(scope, d()->engine->newString(QStringLiteral("Unimplemented ") + message));
- v = d()->engine->newErrorObject(v);
- return throwError(v);
-}
-
-ReturnedValue ExecutionContext::catchException(StackTrace *trace)
-{
- return d()->engine->catchException(this, trace);
-}
-
-ReturnedValue ExecutionContext::throwReferenceError(const ValueRef value)
-{
- Scope scope(this);
- Scoped<String> s(scope, value->toString(this));
- QString msg = s->toQString() + QStringLiteral(" is not defined");
- Scoped<Object> error(scope, d()->engine->newReferenceErrorObject(msg));
- return throwError(error);
-}
-
-ReturnedValue ExecutionContext::throwReferenceError(const QString &message, const QString &fileName, int line, int column)
-{
- Scope scope(this);
- QString msg = message;
- Scoped<Object> error(scope, d()->engine->newReferenceErrorObject(msg, fileName, line, column));
- return throwError(error);
-}
-
-ReturnedValue ExecutionContext::throwRangeError(const ValueRef value)
-{
- Scope scope(this);
- ScopedString s(scope, value->toString(this));
- QString msg = s->toQString() + QStringLiteral(" out of range");
- ScopedObject error(scope, d()->engine->newRangeErrorObject(msg));
- return throwError(error);
-}
-
-ReturnedValue ExecutionContext::throwRangeError(const QString &message)
-{
- Scope scope(this);
- ScopedObject error(scope, d()->engine->newRangeErrorObject(message));
- return throwError(error);
-}
+ Scope scope(d()->engine);
+ ScopedContext it(scope, this->d());
+ for (; it; it = it->d()->parent) {
+ if (const CallContext *callCtx = it->asCallContext())
+ return callCtx->d()->function;
+ else if (it->asCatchContext() || it->asWithContext())
+ continue; // look in the parent context for a FunctionObject
+ else
+ break;
+ }
-ReturnedValue ExecutionContext::throwURIError(const ValueRef msg)
-{
- Scope scope(this);
- ScopedObject error(scope, d()->engine->newURIErrorObject(msg));
- return throwError(error);
+ return 0;
}
diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h
index 99a982aa7f..48319c7444 100644
--- a/src/qml/jsruntime/qv4context_p.h
+++ b/src/qml/jsruntime/qv4context_p.h
@@ -34,21 +34,12 @@
#define QMLJS_ENVIRONMENT_H
#include "qv4global_p.h"
-#include "qv4scopedvalue_p.h"
#include "qv4managed_p.h"
-#include "qv4engine_p.h"
QT_BEGIN_NAMESPACE
namespace QV4 {
-struct Object;
-struct ExecutionEngine;
-struct DeclarativeEnvironment;
-struct Lookup;
-struct Function;
-struct ValueRef;
-
namespace CompiledData {
struct CompilationUnit;
struct Function;
@@ -58,12 +49,27 @@ struct CallContext;
struct CatchContext;
struct WithContext;
-struct Q_QML_EXPORT ExecutionContext : public Managed
+struct CallData
{
- enum {
- IsExecutionContext = true
- };
+ // below is to be compatible with Value. Initialize tag to 0
+#if Q_BYTE_ORDER != Q_LITTLE_ENDIAN
+ uint tag;
+#endif
+ int argc;
+#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
+ uint tag;
+#endif
+ inline ReturnedValue argument(int i) const {
+ return i < argc ? args[i].asReturnedValue() : Primitive::undefinedValue().asReturnedValue();
+ }
+ Value thisObject;
+ Value args[1];
+};
+
+namespace Heap {
+
+struct ExecutionContext : Base {
enum ContextType {
Type_GlobalContext = 0x1,
Type_CatchContext = 0x2,
@@ -73,112 +79,97 @@ struct Q_QML_EXPORT ExecutionContext : public Managed
Type_QmlContext = 0x6
};
- struct Data : Managed::Data {
- Data(ExecutionEngine *engine, ContextType t)
- : Managed::Data(engine->executionContextClass)
- , type(t)
- , strictMode(false)
- , engine(engine)
- , parent(engine->currentContext())
- , outer(0)
- , lookups(0)
- , compilationUnit(0)
- , lineNumber(-1)
- {
- engine->current = reinterpret_cast<ExecutionContext *>(this);
- }
- ContextType type;
- bool strictMode;
-
- CallData *callData;
-
- ExecutionEngine *engine;
- ExecutionContext *parent;
- ExecutionContext *outer;
- Lookup *lookups;
- CompiledData::CompilationUnit *compilationUnit;
-
- int lineNumber;
+ inline ExecutionContext(ExecutionEngine *engine, ContextType t);
- };
- V4_MANAGED(Managed)
- Q_MANAGED_TYPE(ExecutionContext)
+ ContextType type;
+ bool strictMode;
+
+ CallData *callData;
+
+ ExecutionEngine *engine;
+ ExecutionContext *parent;
+ ExecutionContext *outer;
+ Lookup *lookups;
+ CompiledData::CompilationUnit *compilationUnit;
+
+ int lineNumber;
- ExecutionContext(ExecutionEngine *engine, ContextType t)
- : Managed(engine->executionContextClass)
+};
+
+struct CallContext : ExecutionContext {
+ CallContext(ExecutionEngine *engine, ContextType t = Type_SimpleCallContext)
+ : ExecutionContext(engine, t)
{
- d()->type = t;
- d()->strictMode = false;
- d()->engine = engine;
- d()->parent = engine->currentContext();
- d()->outer = 0;
- d()->lookups = 0;
- d()->compilationUnit = 0;
- d()->lineNumber = -1;
- engine->current = this;
+ function = 0;
+ locals = 0;
+ activation = 0;
}
+ CallContext(ExecutionEngine *engine, QV4::Object *qml, QV4::FunctionObject *function);
- HeapObject *newCallContext(FunctionObject *f, CallData *callData);
- WithContext *newWithContext(Object *with);
- CatchContext *newCatchContext(String *exceptionVarName, const ValueRef exceptionValue);
- CallContext *newQmlContext(FunctionObject *f, Object *qml);
+ FunctionObject *function;
+ int realArgumentCount;
+ Value *locals;
+ Object *activation;
+};
- void createMutableBinding(String *name, bool deletable);
+struct GlobalContext : ExecutionContext {
+ GlobalContext(ExecutionEngine *engine);
+ Object *global;
+};
+
+struct CatchContext : ExecutionContext {
+ CatchContext(ExecutionEngine *engine, QV4::String *exceptionVarName, const ValueRef exceptionValue);
+ StringValue exceptionVarName;
+ Value exceptionValue;
+};
+
+struct WithContext : ExecutionContext {
+ WithContext(ExecutionEngine *engine, QV4::Object *with);
+ Object *withObject;
+};
- ReturnedValue throwError(const QV4::ValueRef value);
- ReturnedValue throwError(const QString &message);
- ReturnedValue throwSyntaxError(const QString &message);
- ReturnedValue throwSyntaxError(const QString &message, const QString &fileName, int lineNumber, int column);
- ReturnedValue throwTypeError();
- ReturnedValue throwTypeError(const QString &message);
- ReturnedValue throwReferenceError(const ValueRef value);
- ReturnedValue throwReferenceError(const QString &value, const QString &fileName, int lineNumber, int column);
- ReturnedValue throwRangeError(const ValueRef value);
- ReturnedValue throwRangeError(const QString &message);
- ReturnedValue throwURIError(const ValueRef msg);
- ReturnedValue throwUnimplemented(const QString &message);
+
+}
+
+struct Q_QML_EXPORT ExecutionContext : public Managed
+{
+ enum {
+ IsExecutionContext = true
+ };
+
+ V4_MANAGED(ExecutionContext, Managed)
+ Q_MANAGED_TYPE(ExecutionContext)
+
+ Heap::CallContext *newCallContext(FunctionObject *f, CallData *callData);
+ Heap::WithContext *newWithContext(Object *with);
+ Heap::CatchContext *newCatchContext(String *exceptionVarName, const ValueRef exceptionValue);
+ Heap::CallContext *newQmlContext(FunctionObject *f, Object *qml);
+
+ void createMutableBinding(String *name, bool deletable);
void setProperty(String *name, const ValueRef value);
ReturnedValue getProperty(String *name);
- ReturnedValue getPropertyAndBase(String *name, Object *&base);
+ ReturnedValue getPropertyAndBase(String *name, Heap::Object **base);
bool deleteProperty(String *name);
- // Can only be called from within catch(...), rethrows if no JS exception.
- ReturnedValue catchException(StackTrace *trace = 0);
-
inline CallContext *asCallContext();
inline const CallContext *asCallContext() const;
inline const CatchContext *asCatchContext() const;
inline const WithContext *asWithContext() const;
- inline FunctionObject *getFunctionObject() const;
+ Heap::FunctionObject *getFunctionObject() const;
- static void markObjects(Managed *m, ExecutionEngine *e);
+ static void markObjects(Heap::Base *m, ExecutionEngine *e);
};
struct CallContext : public ExecutionContext
{
- struct Data : ExecutionContext::Data {
- Data(ExecutionEngine *engine, ContextType t = Type_SimpleCallContext)
- : ExecutionContext::Data(engine, t)
- {
- function = 0;
- locals = 0;
- activation = 0;
- }
- Data(ExecutionEngine *engine, Object *qml, QV4::FunctionObject *function);
-
- FunctionObject *function;
- int realArgumentCount;
- Value *locals;
- Object *activation;
- };
- V4_MANAGED(ExecutionContext)
+ V4_MANAGED(CallContext, ExecutionContext)
// formals are in reverse order
- String * const *formals() const;
+ Identifier * const *formals() const;
unsigned int formalCount() const;
- String * const *variables() const;
+ Identifier * const *variables() const;
unsigned int variableCount() const;
inline ReturnedValue argument(int i);
@@ -191,103 +182,38 @@ inline ReturnedValue CallContext::argument(int i) {
struct GlobalContext : public ExecutionContext
{
- struct Data : ExecutionContext::Data {
- Data(ExecutionEngine *engine);
- Object *global;
- };
- V4_MANAGED(ExecutionContext)
+ V4_MANAGED(GlobalContext, ExecutionContext)
};
struct CatchContext : public ExecutionContext
{
- struct Data : ExecutionContext::Data {
- Data(ExecutionEngine *engine, String *exceptionVarName, const ValueRef exceptionValue);
- StringValue exceptionVarName;
- Value exceptionValue;
- };
- V4_MANAGED(ExecutionContext)
+ V4_MANAGED(CatchContext, ExecutionContext)
};
struct WithContext : public ExecutionContext
{
- struct Data : ExecutionContext::Data {
- Data(ExecutionEngine *engine, Object *with);
- Object *withObject;
- };
- V4_MANAGED(ExecutionContext)
+ V4_MANAGED(WithContext, ExecutionContext)
};
inline CallContext *ExecutionContext::asCallContext()
{
- return d()->type >= Type_SimpleCallContext ? static_cast<CallContext *>(this) : 0;
+ return d()->type >= Heap::ExecutionContext::Type_SimpleCallContext ? static_cast<CallContext *>(this) : 0;
}
inline const CallContext *ExecutionContext::asCallContext() const
{
- return d()->type >= Type_SimpleCallContext ? static_cast<const CallContext *>(this) : 0;
+ return d()->type >= Heap::ExecutionContext::Type_SimpleCallContext ? static_cast<const CallContext *>(this) : 0;
}
inline const CatchContext *ExecutionContext::asCatchContext() const
{
- return d()->type == Type_CatchContext ? static_cast<const CatchContext *>(this) : 0;
+ return d()->type == Heap::ExecutionContext::Type_CatchContext ? static_cast<const CatchContext *>(this) : 0;
}
inline const WithContext *ExecutionContext::asWithContext() const
{
- return d()->type == Type_WithContext ? static_cast<const WithContext *>(this) : 0;
-}
-
-inline FunctionObject *ExecutionContext::getFunctionObject() const
-{
- for (const ExecutionContext *it = this; it; it = it->d()->parent) {
- if (const CallContext *callCtx = it->asCallContext())
- return callCtx->d()->function;
- else if (it->asCatchContext() || it->asWithContext())
- continue; // look in the parent context for a FunctionObject
- else
- break;
- }
-
- return 0;
-}
-
-inline void ExecutionEngine::pushContext(CallContext *context)
-{
- context->d()->parent = current;
- current = context;
-}
-
-inline ExecutionContext *ExecutionEngine::popContext()
-{
- Q_ASSERT(current->d()->parent);
- current = current->d()->parent;
- return current;
-}
-
-struct ExecutionContextSaver
-{
- ExecutionEngine *engine;
- ExecutionContext *savedContext;
-
- ExecutionContextSaver(ExecutionContext *context)
- : engine(context->d()->engine)
- , savedContext(context)
- {
- }
- ~ExecutionContextSaver()
- {
- engine->current = savedContext;
- }
-};
-
-inline Scope::Scope(ExecutionContext *ctx)
- : engine(ctx->d()->engine)
-#ifndef QT_NO_DEBUG
- , size(0)
-#endif
-{
- mark = engine->jsStackTop;
+ return d()->type == Heap::ExecutionContext::Type_WithContext ? static_cast<const WithContext *>(this) : 0;
}
/* Function *f, int argc */
diff --git a/src/qml/jsruntime/qv4dataview.cpp b/src/qml/jsruntime/qv4dataview.cpp
new file mode 100644
index 0000000000..36d597fb6e
--- /dev/null
+++ b/src/qml/jsruntime/qv4dataview.cpp
@@ -0,0 +1,316 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qv4dataview_p.h"
+#include "qv4arraybuffer_p.h"
+
+#include "qendian.h"
+
+using namespace QV4;
+
+DEFINE_OBJECT_VTABLE(DataViewCtor);
+DEFINE_OBJECT_VTABLE(DataView);
+
+Heap::DataViewCtor::DataViewCtor(QV4::ExecutionContext *scope)
+ : Heap::FunctionObject(scope, QStringLiteral("DataView"))
+{
+ setVTable(QV4::DataViewCtor::staticVTable());
+}
+
+ReturnedValue DataViewCtor::construct(Managed *m, CallData *callData)
+{
+ Scope scope(m->engine());
+ Scoped<ArrayBuffer> buffer(scope, callData->argument(0));
+ if (!buffer)
+ return scope.engine->throwTypeError();
+
+ double bo = callData->argc > 1 ? callData->args[1].toNumber() : 0;
+ uint byteOffset = (uint)bo;
+ uint bufferLength = buffer->d()->data->size;
+ double bl = callData->argc < 3 || callData->args[2].isUndefined() ? (bufferLength - bo) : callData->args[2].toNumber();
+ uint byteLength = (uint)bl;
+ if (bo != byteOffset || bl != byteLength || byteOffset + byteLength > bufferLength)
+ return scope.engine->throwRangeError(QStringLiteral("DataView: constructor arguments out of range"));
+
+ Scoped<DataView> a(scope, scope.engine->memoryManager->alloc<DataView>(scope.engine));
+ a->d()->buffer = buffer->d();
+ a->d()->byteLength = byteLength;
+ a->d()->byteOffset = byteOffset;
+ return a.asReturnedValue();
+
+}
+
+ReturnedValue DataViewCtor::call(Managed *that, CallData *callData)
+{
+ return construct(that, callData);
+}
+
+
+Heap::DataView::DataView(ExecutionEngine *e)
+ : Heap::Object(e->dataViewClass, e->dataViewPrototype.asObject()),
+ buffer(0),
+ byteLength(0),
+ byteOffset(0)
+{
+}
+
+
+void DataView::markObjects(Heap::Base *that, ExecutionEngine *e)
+{
+ DataView::Data *v = static_cast<DataView::Data *>(that);
+ v->buffer->mark(e);
+}
+
+void DataViewPrototype::init(ExecutionEngine *engine, Object *ctor)
+{
+ Scope scope(engine);
+ ScopedObject o(scope);
+ ctor->defineReadonlyProperty(engine->id_length, Primitive::fromInt32(3));
+ ctor->defineReadonlyProperty(engine->id_prototype, (o = this));
+ defineDefaultProperty(engine->id_constructor, (o = ctor));
+ defineAccessorProperty(QStringLiteral("buffer"), method_get_buffer, 0);
+ defineAccessorProperty(QStringLiteral("byteLength"), method_get_byteLength, 0);
+ defineAccessorProperty(QStringLiteral("byteOffset"), method_get_byteOffset, 0);
+
+ defineDefaultProperty(QStringLiteral("getInt8"), method_getChar<signed char>, 0);
+ defineDefaultProperty(QStringLiteral("getUInt8"), method_getChar<unsigned char>, 0);
+ defineDefaultProperty(QStringLiteral("getInt16"), method_get<short>, 0);
+ defineDefaultProperty(QStringLiteral("getUInt16"), method_get<unsigned short>, 0);
+ defineDefaultProperty(QStringLiteral("getInt32"), method_get<int>, 0);
+ defineDefaultProperty(QStringLiteral("getUInt32"), method_get<unsigned int>, 0);
+ defineDefaultProperty(QStringLiteral("getFloat32"), method_getFloat<float>, 0);
+ defineDefaultProperty(QStringLiteral("getFloat64"), method_getFloat<double>, 0);
+
+ defineDefaultProperty(QStringLiteral("setInt8"), method_setChar<signed char>, 0);
+ defineDefaultProperty(QStringLiteral("setUInt8"), method_setChar<unsigned char>, 0);
+ defineDefaultProperty(QStringLiteral("setInt16"), method_set<short>, 0);
+ defineDefaultProperty(QStringLiteral("setUInt16"), method_set<unsigned short>, 0);
+ defineDefaultProperty(QStringLiteral("setInt32"), method_set<int>, 0);
+ defineDefaultProperty(QStringLiteral("setUInt32"), method_set<unsigned int>, 0);
+ defineDefaultProperty(QStringLiteral("setFloat32"), method_setFloat<float>, 0);
+ defineDefaultProperty(QStringLiteral("setFloat64"), method_setFloat<double>, 0);
+}
+
+ReturnedValue DataViewPrototype::method_get_buffer(CallContext *ctx)
+{
+ Scope scope(ctx);
+ Scoped<DataView> v(scope, ctx->d()->callData->thisObject);
+ if (!v)
+ return scope.engine->throwTypeError();
+
+ return Encode(v->d()->buffer->asReturnedValue());
+}
+
+ReturnedValue DataViewPrototype::method_get_byteLength(CallContext *ctx)
+{
+ Scope scope(ctx);
+ Scoped<DataView> v(scope, ctx->d()->callData->thisObject);
+ if (!v)
+ return scope.engine->throwTypeError();
+
+ return Encode(v->d()->byteLength);
+}
+
+ReturnedValue DataViewPrototype::method_get_byteOffset(CallContext *ctx)
+{
+ Scope scope(ctx);
+ Scoped<DataView> v(scope, ctx->d()->callData->thisObject);
+ if (!v)
+ return scope.engine->throwTypeError();
+
+ return Encode(v->d()->byteOffset);
+}
+
+template <typename T>
+ReturnedValue DataViewPrototype::method_getChar(CallContext *ctx)
+{
+ Scope scope(ctx);
+ Scoped<DataView> v(scope, ctx->d()->callData->thisObject);
+ if (!v || ctx->d()->callData->argc < 1)
+ return scope.engine->throwTypeError();
+ double l = ctx->d()->callData->args[0].toNumber();
+ uint idx = (uint)l;
+ if (l != idx || idx + sizeof(T) > v->d()->byteLength)
+ return scope.engine->throwTypeError();
+ idx += v->d()->byteOffset;
+
+ T t = T(v->d()->buffer->data->data()[idx]);
+
+ return Encode((int)t);
+}
+
+template <typename T>
+ReturnedValue DataViewPrototype::method_get(CallContext *ctx)
+{
+ Scope scope(ctx);
+ Scoped<DataView> v(scope, ctx->d()->callData->thisObject);
+ if (!v || ctx->d()->callData->argc < 1)
+ return scope.engine->throwTypeError();
+ double l = ctx->d()->callData->args[0].toNumber();
+ uint idx = (uint)l;
+ if (l != idx || idx + sizeof(T) > v->d()->byteLength)
+ return scope.engine->throwTypeError();
+ idx += v->d()->byteOffset;
+
+ bool littleEndian = ctx->d()->callData->argc < 2 ? false : ctx->d()->callData->args[1].toBoolean();
+
+ T t = littleEndian
+ ? qFromLittleEndian<T>((uchar *)v->d()->buffer->data->data() + idx)
+ : qFromBigEndian<T>((uchar *)v->d()->buffer->data->data() + idx);
+
+ return Encode(t);
+}
+
+template <typename T>
+ReturnedValue DataViewPrototype::method_getFloat(CallContext *ctx)
+{
+ Scope scope(ctx);
+ Scoped<DataView> v(scope, ctx->d()->callData->thisObject);
+ if (!v || ctx->d()->callData->argc < 1)
+ return scope.engine->throwTypeError();
+ double l = ctx->d()->callData->args[0].toNumber();
+ uint idx = (uint)l;
+ if (l != idx || idx + sizeof(T) > v->d()->byteLength)
+ return scope.engine->throwTypeError();
+ idx += v->d()->byteOffset;
+
+ bool littleEndian = ctx->d()->callData->argc < 2 ? false : ctx->d()->callData->args[1].toBoolean();
+
+ if (sizeof(T) == 4) {
+ // float
+ union {
+ uint i;
+ float f;
+ } u;
+ u.i = littleEndian
+ ? qFromLittleEndian<uint>((uchar *)v->d()->buffer->data->data() + idx)
+ : qFromBigEndian<uint>((uchar *)v->d()->buffer->data->data() + idx);
+ return Encode(u.f);
+ } else {
+ Q_ASSERT(sizeof(T) == 8);
+ union {
+ quint64 i;
+ double d;
+ } u;
+ u.i = littleEndian
+ ? qFromLittleEndian<quint64>((uchar *)v->d()->buffer->data->data() + idx)
+ : qFromBigEndian<quint64>((uchar *)v->d()->buffer->data->data() + idx);
+ return Encode(u.d);
+ }
+}
+
+template <typename T>
+ReturnedValue DataViewPrototype::method_setChar(CallContext *ctx)
+{
+ Scope scope(ctx);
+ Scoped<DataView> v(scope, ctx->d()->callData->thisObject);
+ if (!v || ctx->d()->callData->argc < 1)
+ return scope.engine->throwTypeError();
+ double l = ctx->d()->callData->args[0].toNumber();
+ uint idx = (uint)l;
+ if (l != idx || idx + sizeof(T) > v->d()->byteLength)
+ return scope.engine->throwTypeError();
+ idx += v->d()->byteOffset;
+
+ int val = ctx->d()->callData->argc >= 2 ? ctx->d()->callData->args[1].toInt32() : 0;
+ v->d()->buffer->data->data()[idx] = (char)val;
+
+ return Encode::undefined();
+}
+
+template <typename T>
+ReturnedValue DataViewPrototype::method_set(CallContext *ctx)
+{
+ Scope scope(ctx);
+ Scoped<DataView> v(scope, ctx->d()->callData->thisObject);
+ if (!v || ctx->d()->callData->argc < 1)
+ return scope.engine->throwTypeError();
+ double l = ctx->d()->callData->args[0].toNumber();
+ uint idx = (uint)l;
+ if (l != idx || idx + sizeof(T) > v->d()->byteLength)
+ return scope.engine->throwTypeError();
+ idx += v->d()->byteOffset;
+
+ int val = ctx->d()->callData->argc >= 2 ? ctx->d()->callData->args[1].toInt32() : 0;
+
+ bool littleEndian = ctx->d()->callData->argc < 3 ? false : ctx->d()->callData->args[2].toBoolean();
+
+ if (littleEndian)
+ qToLittleEndian<T>(val, (uchar *)v->d()->buffer->data->data() + idx);
+ else
+ qToBigEndian<T>(val, (uchar *)v->d()->buffer->data->data() + idx);
+
+ return Encode::undefined();
+}
+
+template <typename T>
+ReturnedValue DataViewPrototype::method_setFloat(CallContext *ctx)
+{
+ Scope scope(ctx);
+ Scoped<DataView> v(scope, ctx->d()->callData->thisObject);
+ if (!v || ctx->d()->callData->argc < 1)
+ return scope.engine->throwTypeError();
+ double l = ctx->d()->callData->args[0].toNumber();
+ uint idx = (uint)l;
+ if (l != idx || idx + sizeof(T) > v->d()->byteLength)
+ return scope.engine->throwTypeError();
+ idx += v->d()->byteOffset;
+
+ double val = ctx->d()->callData->argc >= 2 ? ctx->d()->callData->args[1].toNumber() : qSNaN();
+ bool littleEndian = ctx->d()->callData->argc < 3 ? false : ctx->d()->callData->args[2].toBoolean();
+
+ if (sizeof(T) == 4) {
+ // float
+ union {
+ uint i;
+ float f;
+ } u;
+ u.f = val;
+ if (littleEndian)
+ qToLittleEndian(u.i, (uchar *)v->d()->buffer->data->data() + idx);
+ else
+ qToBigEndian(u.i, (uchar *)v->d()->buffer->data->data() + idx);
+ } else {
+ Q_ASSERT(sizeof(T) == 8);
+ union {
+ quint64 i;
+ double d;
+ } u;
+ u.d = val;
+ if (littleEndian)
+ qToLittleEndian(u.i, (uchar *)v->d()->buffer->data->data() + idx);
+ else
+ qToBigEndian(u.i, (uchar *)v->d()->buffer->data->data() + idx);
+ }
+ return Encode::undefined();
+}
diff --git a/src/qml/qml/v8/qv8debug_p.h b/src/qml/jsruntime/qv4dataview_p.h
index 75342aa070..c9e4375137 100644
--- a/src/qml/qml/v8/qv8debug_p.h
+++ b/src/qml/jsruntime/qv4dataview_p.h
@@ -30,5 +30,70 @@
** $QT_END_LICENSE$
**
****************************************************************************/
+#ifndef QV4DATAVIEW_H
+#define QV4DATAVIEW_H
-//#include <private/v8-debug.h>
+#include "qv4object_p.h"
+#include "qv4functionobject_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace QV4 {
+
+namespace Heap {
+
+struct DataViewCtor : FunctionObject {
+ DataViewCtor(QV4::ExecutionContext *scope);
+};
+
+struct DataView : Object {
+ DataView(ExecutionEngine *e);
+ ArrayBuffer *buffer;
+ uint byteLength;
+ uint byteOffset;
+};
+
+}
+
+struct DataViewCtor: FunctionObject
+{
+ V4_OBJECT2(DataViewCtor, FunctionObject)
+
+ static ReturnedValue construct(Managed *m, CallData *callData);
+ static ReturnedValue call(Managed *that, CallData *callData);
+};
+
+struct DataView : Object
+{
+ V4_OBJECT2(DataView, Object)
+
+ static void markObjects(Heap::Base *that, ExecutionEngine *e);
+};
+
+struct DataViewPrototype: Object
+{
+ void init(ExecutionEngine *engine, Object *ctor);
+
+ static ReturnedValue method_get_buffer(CallContext *ctx);
+ static ReturnedValue method_get_byteLength(CallContext *ctx);
+ static ReturnedValue method_get_byteOffset(CallContext *ctx);
+ template <typename T>
+ static ReturnedValue method_getChar(CallContext *ctx);
+ template <typename T>
+ static ReturnedValue method_get(CallContext *ctx);
+ template <typename T>
+ static ReturnedValue method_getFloat(CallContext *ctx);
+ template <typename T>
+ static ReturnedValue method_setChar(CallContext *ctx);
+ template <typename T>
+ static ReturnedValue method_set(CallContext *ctx);
+ template <typename T>
+ static ReturnedValue method_setFloat(CallContext *ctx);
+};
+
+
+} // namespace QV4
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/qml/jsruntime/qv4dateobject.cpp b/src/qml/jsruntime/qv4dateobject.cpp
index b3c340ccb2..4379e3ff94 100644
--- a/src/qml/jsruntime/qv4dateobject.cpp
+++ b/src/qml/jsruntime/qv4dateobject.cpp
@@ -35,6 +35,8 @@
#include "qv4dateobject_p.h"
#include "qv4objectproto_p.h"
#include "qv4scopedvalue_p.h"
+#include "qv4runtime_p.h"
+
#include <QtCore/qnumeric.h>
#include <QtCore/qmath.h>
#include <QtCore/QDateTime>
@@ -559,13 +561,7 @@ static inline QString ToString(double t)
{
if (std::isnan(t))
return QStringLiteral("Invalid Date");
- QDateTime dateTime = ToDateTime(t, Qt::LocalTime);
-
- // JavaScript knows a year 0, while QDateTime doesn't. So, in order to show the right date we
- // have to add a year to negative ones here.
- if (dateTime.date().year() < 0)
- dateTime = dateTime.addYears(1);
- QString str = dateTime.toString() + QStringLiteral(" GMT");
+ QString str = ToDateTime(t, Qt::LocalTime).toString() + QStringLiteral(" GMT");
double tzoffset = LocalTZA + DaylightSavingTA(t);
if (tzoffset) {
int hours = static_cast<int>(::fabs(tzoffset) / 1000 / 60 / 60);
@@ -634,10 +630,10 @@ static double getLocalTZA()
DEFINE_OBJECT_VTABLE(DateObject);
-DateObject::Data::Data(ExecutionEngine *engine, const QDateTime &date)
- : Object::Data(engine->dateClass)
+Heap::DateObject::DateObject(QV4::ExecutionEngine *engine, const QDateTime &date)
+ : Heap::Object(engine->dateClass, engine->datePrototype.asObject())
{
- setVTable(staticVTable());
+ setVTable(QV4::DateObject::staticVTable());
value.setDouble(date.isValid() ? date.toMSecsSinceEpoch() : qSNaN());
}
@@ -648,10 +644,10 @@ QDateTime DateObject::toQDateTime() const
DEFINE_OBJECT_VTABLE(DateCtor);
-DateCtor::Data::Data(ExecutionContext *scope)
- : FunctionObject::Data(scope, QStringLiteral("Date"))
+Heap::DateCtor::DateCtor(QV4::ExecutionContext *scope)
+ : Heap::FunctionObject(scope, QStringLiteral("Date"))
{
- setVTable(staticVTable());
+ setVTable(QV4::DateCtor::staticVTable());
}
ReturnedValue DateCtor::construct(Managed *m, CallData *callData)
@@ -764,7 +760,7 @@ double DatePrototype::getThisDate(ExecutionContext *ctx)
if (DateObject *thisObject = ctx->d()->callData->thisObject.asDateObject())
return thisObject->date().asDouble();
else {
- ctx->throwTypeError();
+ ctx->engine()->throwTypeError();
return 0;
}
}
@@ -773,7 +769,7 @@ ReturnedValue DatePrototype::method_parse(CallContext *ctx)
{
if (!ctx->d()->callData->argc)
return Encode(qSNaN());
- return Encode(ParseString(ctx->d()->callData->args[0].toString(ctx)->toQString()));
+ return Encode(ParseString(ctx->d()->callData->args[0].toQString()));
}
ReturnedValue DatePrototype::method_UTC(CallContext *ctx)
@@ -1000,7 +996,7 @@ ReturnedValue DatePrototype::method_setTime(CallContext *ctx)
Scope scope(ctx);
Scoped<DateObject> self(scope, ctx->d()->callData->thisObject);
if (!self)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
double t = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toNumber() : qSNaN();
self->date().setDouble(TimeClip(t));
@@ -1012,7 +1008,7 @@ ReturnedValue DatePrototype::method_setMilliseconds(CallContext *ctx)
Scope scope(ctx);
Scoped<DateObject> self(scope, ctx->d()->callData->thisObject);
if (!self)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
double t = LocalTime(self->date().asDouble());
double ms = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toNumber() : qSNaN();
@@ -1024,7 +1020,7 @@ ReturnedValue DatePrototype::method_setUTCMilliseconds(CallContext *ctx)
{
DateObject *self = ctx->d()->callData->thisObject.asDateObject();
if (!self)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
double t = self->date().asDouble();
double ms = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toNumber() : qSNaN();
@@ -1036,7 +1032,7 @@ ReturnedValue DatePrototype::method_setSeconds(CallContext *ctx)
{
DateObject *self = ctx->d()->callData->thisObject.asDateObject();
if (!self)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
double t = LocalTime(self->date().asDouble());
double sec = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toNumber() : qSNaN();
@@ -1050,7 +1046,7 @@ ReturnedValue DatePrototype::method_setUTCSeconds(CallContext *ctx)
{
DateObject *self = ctx->d()->callData->thisObject.asDateObject();
if (!self)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
double t = self->date().asDouble();
double sec = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toNumber() : qSNaN();
@@ -1064,7 +1060,7 @@ ReturnedValue DatePrototype::method_setMinutes(CallContext *ctx)
{
DateObject *self = ctx->d()->callData->thisObject.asDateObject();
if (!self)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
double t = LocalTime(self->date().asDouble());
double min = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toNumber() : qSNaN();
@@ -1079,7 +1075,7 @@ ReturnedValue DatePrototype::method_setUTCMinutes(CallContext *ctx)
{
DateObject *self = ctx->d()->callData->thisObject.asDateObject();
if (!self)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
double t = self->date().asDouble();
double min = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toNumber() : qSNaN();
@@ -1094,7 +1090,7 @@ ReturnedValue DatePrototype::method_setHours(CallContext *ctx)
{
DateObject *self = ctx->d()->callData->thisObject.asDateObject();
if (!self)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
double t = LocalTime(self->date().asDouble());
double hour = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toNumber() : qSNaN();
@@ -1110,7 +1106,7 @@ ReturnedValue DatePrototype::method_setUTCHours(CallContext *ctx)
{
DateObject *self = ctx->d()->callData->thisObject.asDateObject();
if (!self)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
double t = self->date().asDouble();
double hour = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toNumber() : qSNaN();
@@ -1126,7 +1122,7 @@ ReturnedValue DatePrototype::method_setDate(CallContext *ctx)
{
DateObject *self = ctx->d()->callData->thisObject.asDateObject();
if (!self)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
double t = LocalTime(self->date().asDouble());
double date = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toNumber() : qSNaN();
@@ -1139,7 +1135,7 @@ ReturnedValue DatePrototype::method_setUTCDate(CallContext *ctx)
{
DateObject *self = ctx->d()->callData->thisObject.asDateObject();
if (!self)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
double t = self->date().asDouble();
double date = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toNumber() : qSNaN();
@@ -1152,7 +1148,7 @@ ReturnedValue DatePrototype::method_setMonth(CallContext *ctx)
{
DateObject *self = ctx->d()->callData->thisObject.asDateObject();
if (!self)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
double t = LocalTime(self->date().asDouble());
double month = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toNumber() : qSNaN();
@@ -1166,7 +1162,7 @@ ReturnedValue DatePrototype::method_setUTCMonth(CallContext *ctx)
{
DateObject *self = ctx->d()->callData->thisObject.asDateObject();
if (!self)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
double t = self->date().asDouble();
double month = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toNumber() : qSNaN();
@@ -1180,7 +1176,7 @@ ReturnedValue DatePrototype::method_setYear(CallContext *ctx)
{
DateObject *self = ctx->d()->callData->thisObject.asDateObject();
if (!self)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
double t = self->date().asDouble();
if (std::isnan(t))
@@ -1206,7 +1202,7 @@ ReturnedValue DatePrototype::method_setUTCFullYear(CallContext *ctx)
{
DateObject *self = ctx->d()->callData->thisObject.asDateObject();
if (!self)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
double t = self->date().asDouble();
double year = ctx->d()->callData->argc ? ctx->d()->callData->args[0].toNumber() : qSNaN();
@@ -1221,7 +1217,7 @@ ReturnedValue DatePrototype::method_setFullYear(CallContext *ctx)
{
DateObject *self = ctx->d()->callData->thisObject.asDateObject();
if (!self)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
double t = LocalTime(self->date().asDouble());
if (std::isnan(t))
@@ -1238,7 +1234,7 @@ ReturnedValue DatePrototype::method_toUTCString(CallContext *ctx)
{
DateObject *self = ctx->d()->callData->thisObject.asDateObject();
if (!self)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
double t = self->date().asDouble();
return ctx->d()->engine->newString(ToUTCString(t))->asReturnedValue();
@@ -1261,11 +1257,11 @@ ReturnedValue DatePrototype::method_toISOString(CallContext *ctx)
{
DateObject *self = ctx->d()->callData->thisObject.asDateObject();
if (!self)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
double t = self->date().asDouble();
if (!std::isfinite(t))
- return ctx->throwRangeError(ctx->d()->callData->thisObject);
+ return ctx->engine()->throwRangeError(ctx->d()->callData->thisObject);
QString result;
int year = (int)YearFromTime(t);
@@ -1298,20 +1294,20 @@ ReturnedValue DatePrototype::method_toISOString(CallContext *ctx)
ReturnedValue DatePrototype::method_toJSON(CallContext *ctx)
{
Scope scope(ctx);
- ScopedValue O(scope, RuntimeHelpers::toObject(ctx, ValueRef(&ctx->d()->callData->thisObject)));
+ ScopedValue O(scope, RuntimeHelpers::toObject(scope.engine, ValueRef(&ctx->d()->callData->thisObject)));
ScopedValue tv(scope, RuntimeHelpers::toPrimitive(O, NUMBER_HINT));
if (tv->isNumber() && !std::isfinite(tv->toNumber()))
return Encode::null();
ScopedString s(scope, ctx->d()->engine->newString(QStringLiteral("toISOString")));
- ScopedValue v(scope, O->objectValue()->get(s.getPointer()));
+ ScopedValue v(scope, O->objectValue()->get(s));
FunctionObject *toIso = v->asFunctionObject();
if (!toIso)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
- ScopedCallData callData(scope, 0);
+ ScopedCallData callData(scope);
callData->thisObject = ctx->d()->callData->thisObject;
return toIso->call(callData);
}
diff --git a/src/qml/jsruntime/qv4dateobject_p.h b/src/qml/jsruntime/qv4dateobject_p.h
index abab5390a6..b164de6baa 100644
--- a/src/qml/jsruntime/qv4dateobject_p.h
+++ b/src/qml/jsruntime/qv4dateobject_p.h
@@ -43,23 +43,32 @@ class QDateTime;
namespace QV4 {
+namespace Heap {
+
+struct DateObject : Object {
+ DateObject(InternalClass *ic, QV4::Object *prototype)
+ : Object(ic, prototype)
+ {
+ value = Encode(qSNaN());
+ }
+
+ DateObject(QV4::ExecutionEngine *engine, const ValueRef date)
+ : Object(engine->dateClass, engine->datePrototype.asObject())
+ {
+ value = date;
+ }
+ DateObject(QV4::ExecutionEngine *engine, const QDateTime &date);
+ Value value;
+};
+
+struct DateCtor : FunctionObject {
+ DateCtor(QV4::ExecutionContext *scope);
+};
+
+}
+
struct DateObject: Object {
- struct Data : Object::Data {
- Data(ExecutionEngine *engine, const ValueRef date)
- : Object::Data(engine->dateClass)
- {
- value = date;
- }
- Data(ExecutionEngine *engine, const QDateTime &date);
- Data(InternalClass *ic)
- : Object::Data(ic)
- {
- Q_ASSERT(internalClass->vtable == staticVTable());
- value = Primitive::fromDouble(qSNaN());
- }
- Value value;
- };
- V4_OBJECT(Object)
+ V4_OBJECT2(DateObject, Object)
Q_MANAGED_TYPE(DateObject)
@@ -72,10 +81,7 @@ struct DateObject: Object {
struct DateCtor: FunctionObject
{
- struct Data : FunctionObject::Data {
- Data(ExecutionContext *scope);
- };
- V4_OBJECT(FunctionObject)
+ V4_OBJECT2(DateCtor, FunctionObject)
static ReturnedValue construct(Managed *, CallData *callData);
static ReturnedValue call(Managed *that, CallData *);
diff --git a/src/qml/jsruntime/qv4debugging.cpp b/src/qml/jsruntime/qv4debugging.cpp
index 50142ab155..01ee9585c3 100644
--- a/src/qml/jsruntime/qv4debugging.cpp
+++ b/src/qml/jsruntime/qv4debugging.cpp
@@ -38,6 +38,8 @@
#include "qv4instr_moth_p.h"
#include "qv4runtime_p.h"
#include "qv4script_p.h"
+#include "qv4objectiterator_p.h"
+#include "qv4identifier_p.h"
#include <iostream>
#include <algorithm>
@@ -63,7 +65,7 @@ public:
{
Scope scope(engine);
- ExecutionContextSaver saver(engine->currentContext());
+ ExecutionContextSaver saver(scope, engine->currentContext());
if (frameNr > 0) {
Value *savedContexts = scope.alloc(frameNr);
@@ -73,7 +75,7 @@ public:
}
}
- ExecutionContext *ctx = engine->currentContext();
+ ScopedContext ctx(scope, engine->currentContext());
QV4::Script script(ctx, this->script);
script.strictMode = ctx->d()->strictMode;
// In order for property lookups in QML to work, we need to disable fast v4 lookups. That
@@ -84,7 +86,7 @@ public:
if (!scope.engine->hasException)
result = script.run();
if (scope.engine->hasException)
- result = ctx->catchException();
+ result = scope.engine->catchException();
handleResult(result);
}
@@ -164,14 +166,13 @@ public:
Debugger::Debugger(QV4::ExecutionEngine *engine)
: m_engine(engine)
- , m_currentContext(0)
, m_agent(0)
, m_state(Running)
, m_stepping(NotStepping)
, m_pauseRequested(false)
, m_haveBreakPoints(false)
, m_breakOnThrow(false)
- , m_returnedValue(Primitive::undefinedValue())
+ , m_returnedValue(engine, Primitive::undefinedValue())
, m_gatherSources(0)
, m_runningJob(0)
{
@@ -229,9 +230,9 @@ void Debugger::resume(Speed speed)
return;
if (!m_returnedValue.isUndefined())
- m_returnedValue = Encode::undefined();
+ m_returnedValue.set(m_engine, Encode::undefined());
- m_currentContext = m_engine->currentContext();
+ m_currentContext.set(m_engine, m_engine->currentContext());
m_stepping = speed;
m_runningCondition.wakeAll();
}
@@ -261,7 +262,7 @@ Debugger::ExecutionState Debugger::currentExecutionState() const
{
ExecutionState state;
state.fileName = getFunction()->sourceFile();
- state.lineNumber = engine()->currentContext()->d()->lineNumber;
+ state.lineNumber = engine()->currentContext()->lineNumber;
return state;
}
@@ -271,27 +272,37 @@ QVector<StackFrame> Debugger::stackTrace(int frameLimit) const
return m_engine->stackTrace(frameLimit);
}
-static inline CallContext *findContext(ExecutionContext *ctxt, int frame)
+static inline Heap::CallContext *findContext(Heap::ExecutionContext *ctxt, int frame)
{
- while (ctxt) {
- CallContext *cCtxt = ctxt->asCallContext();
+ if (!ctxt)
+ return 0;
+
+ Scope scope(ctxt->engine);
+ ScopedContext ctx(scope, ctxt);
+ while (ctx) {
+ CallContext *cCtxt = ctx->asCallContext();
if (cCtxt && cCtxt->d()->function) {
if (frame < 1)
- return cCtxt;
+ return cCtxt->d();
--frame;
}
- ctxt = ctxt->d()->parent;
+ ctx = ctx->d()->parent;
}
return 0;
}
-static inline CallContext *findScope(ExecutionContext *ctxt, int scope)
+static inline Heap::CallContext *findScope(Heap::ExecutionContext *ctxt, int scope)
{
- for (; scope > 0 && ctxt; --scope)
- ctxt = ctxt->d()->outer;
+ if (!ctxt)
+ return 0;
+
+ Scope s(ctxt->engine);
+ ScopedContext ctx(s, ctxt);
+ for (; scope > 0 && ctx; --scope)
+ ctx = ctx->d()->outer;
- return ctxt ? ctxt->asCallContext() : 0;
+ return (ctx && ctx->d()) ? ctx->asCallContext()->d() : 0;
}
void Debugger::collectArgumentsInContext(Collector *collector, int frameNr, int scopeNr)
@@ -321,17 +332,17 @@ void Debugger::collectArgumentsInContext(Collector *collector, int frameNr, int
if (frameNr < 0)
return;
- CallContext *ctxt = findScope(findContext(engine->currentContext(), frameNr), scopeNr);
+ Scope scope(engine);
+ Scoped<CallContext> ctxt(scope, findScope(findContext(engine->currentContext(), frameNr), scopeNr));
if (!ctxt)
return;
- Scope scope(engine);
ScopedValue v(scope);
int nFormals = ctxt->formalCount();
for (unsigned i = 0, ei = nFormals; i != ei; ++i) {
QString qName;
- if (String *name = ctxt->formals()[nFormals - i - 1])
- qName = name->toQString();
+ if (Identifier *name = ctxt->formals()[nFormals - i - 1])
+ qName = name->string;
v = ctxt->argument(i);
collector->collect(qName, v);
}
@@ -368,16 +379,16 @@ void Debugger::collectLocalsInContext(Collector *collector, int frameNr, int sco
if (frameNr < 0)
return;
- CallContext *ctxt = findScope(findContext(engine->currentContext(), frameNr), scopeNr);
+ Scope scope(engine);
+ Scoped<CallContext> ctxt(scope, findScope(findContext(engine->currentContext(), frameNr), scopeNr));
if (!ctxt)
return;
- Scope scope(engine);
ScopedValue v(scope);
for (unsigned i = 0, ei = ctxt->variableCount(); i != ei; ++i) {
QString qName;
- if (String *name = ctxt->variables()[i])
- qName = name->toQString();
+ if (Identifier *name = ctxt->variables()[i])
+ qName = name->string;
v = ctxt->d()->locals[i];
collector->collect(qName, v);
}
@@ -415,7 +426,8 @@ bool Debugger::collectThisInContext(Debugger::Collector *collector, int frame)
bool myRun()
{
- ExecutionContext *ctxt = findContext(engine->currentContext(), frameNr);
+ Scope scope(engine);
+ ScopedContext ctxt(scope, findContext(engine->currentContext(), frameNr));
while (ctxt) {
if (CallContext *cCtxt = ctxt->asCallContext())
if (cCtxt->d()->activation)
@@ -426,7 +438,6 @@ bool Debugger::collectThisInContext(Debugger::Collector *collector, int frame)
if (!ctxt)
return false;
- Scope scope(engine);
ScopedObject o(scope, ctxt->asCallContext()->d()->activation);
collector->collect(o);
return true;
@@ -477,19 +488,20 @@ void Debugger::collectReturnedValue(Collector *collector) const
collector->collect(o);
}
-QVector<ExecutionContext::ContextType> Debugger::getScopeTypes(int frame) const
+QVector<Heap::ExecutionContext::ContextType> Debugger::getScopeTypes(int frame) const
{
- QVector<ExecutionContext::ContextType> types;
+ QVector<Heap::ExecutionContext::ContextType> types;
if (state() != Paused)
return types;
- CallContext *sctxt = findContext(m_engine->currentContext(), frame);
- if (!sctxt || sctxt->d()->type < ExecutionContext::Type_SimpleCallContext)
+ Scope scope(m_engine);
+ Scoped<CallContext> sctxt(scope, findContext(m_engine->currentContext(), frame));
+ if (!sctxt || sctxt->d()->type < Heap::ExecutionContext::Type_SimpleCallContext)
return types;
- CallContext *ctxt = static_cast<CallContext *>(sctxt);
- for (ExecutionContext *it = ctxt; it; it = it->d()->outer)
+ ScopedContext it(scope, sctxt->d());
+ for (; it; it = it->d()->outer)
types.append(it->d()->type);
return types;
@@ -520,7 +532,7 @@ void Debugger::maybeBreakAtInstruction()
switch (m_stepping) {
case StepOver:
- if (m_currentContext != m_engine->currentContext())
+ if (m_currentContext.asManaged()->d() != m_engine->currentContext())
break;
// fall through
case StepIn:
@@ -536,7 +548,7 @@ void Debugger::maybeBreakAtInstruction()
pauseAndWait(PauseRequest);
} else if (m_haveBreakPoints) {
if (Function *f = getFunction()) {
- const int lineNumber = engine()->currentContext()->d()->lineNumber;
+ const int lineNumber = engine()->currentContext()->lineNumber;
if (reallyHitTheBreakPoint(f->sourceFile(), lineNumber))
pauseAndWait(BreakPoint);
}
@@ -550,7 +562,7 @@ void Debugger::enteringFunction()
QMutexLocker locker(&m_lock);
if (m_stepping == StepIn) {
- m_currentContext = m_engine->currentContext();
+ m_currentContext.set(m_engine, m_engine->currentContext());
}
}
@@ -562,10 +574,10 @@ void Debugger::leavingFunction(const ReturnedValue &retVal)
QMutexLocker locker(&m_lock);
- if (m_stepping != NotStepping && m_currentContext == m_engine->currentContext()) {
- m_currentContext = m_engine->currentContext()->d()->parent;
+ if (m_stepping != NotStepping && m_currentContext.asManaged()->d() == m_engine->currentContext()) {
+ m_currentContext.set(m_engine, m_engine->currentContext()->parent);
m_stepping = StepOver;
- m_returnedValue = retVal;
+ m_returnedValue.set(m_engine, retVal);
}
}
@@ -583,8 +595,10 @@ void Debugger::aboutToThrow()
Function *Debugger::getFunction() const
{
- ExecutionContext *context = m_engine->currentContext();
- if (const FunctionObject *function = context->getFunctionObject())
+ Scope scope(m_engine);
+ ScopedContext context(scope, m_engine->currentContext());
+ ScopedFunctionObject function(scope, context->getFunctionObject());
+ if (function)
return function->function();
else
return context->d()->engine->globalCode;
diff --git a/src/qml/jsruntime/qv4debugging_p.h b/src/qml/jsruntime/qv4debugging_p.h
index 0e115f0de6..5780dc7c0d 100644
--- a/src/qml/jsruntime/qv4debugging_p.h
+++ b/src/qml/jsruntime/qv4debugging_p.h
@@ -171,7 +171,7 @@ public:
bool collectThisInContext(Collector *collector, int frame = 0);
void collectThrownValue(Collector *collector);
void collectReturnedValue(Collector *collector) const;
- QVector<ExecutionContext::ContextType> getScopeTypes(int frame = 0) const;
+ QVector<Heap::ExecutionContext::ContextType> getScopeTypes(int frame = 0) const;
void evaluateExpression(int frameNr, const QString &expression, Collector *resultsCollector);
@@ -196,7 +196,7 @@ private:
private:
QV4::ExecutionEngine *m_engine;
- QV4::ExecutionContext *m_currentContext;
+ QV4::PersistentValue m_currentContext;
DebuggerAgent *m_agent;
QMutex m_lock;
QWaitCondition m_runningCondition;
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index 74b262e86d..a51ea36351 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -61,6 +61,18 @@
#include "qv4qobjectwrapper_p.h"
#include "qv4qmlextensions_p.h"
#include "qv4memberdata_p.h"
+#include "qv4arraybuffer_p.h"
+#include "qv4dataview_p.h"
+#include "qv4typedarray_p.h"
+#include <private/qv8engine_p.h>
+#include <private/qjsvalue_p.h>
+#include <private/qqmlcontextwrapper_p.h>
+#include <private/qqmltypewrapper_p.h>
+#include <private/qqmlvaluetypewrapper_p.h>
+#include <private/qqmlvaluetype_p.h>
+#include <private/qqmllistwrapper_p.h>
+#include <private/qqmllist_p.h>
+#include <private/qqmllocale_p.h>
#include <QtCore/QTextStream>
#include <QDateTime>
@@ -79,6 +91,10 @@
#endif
#endif
+#ifdef V4_USE_VALGRIND
+#include <valgrind/memcheck.h>
+#endif
+
QT_BEGIN_NAMESPACE
using namespace QV4;
@@ -87,7 +103,7 @@ static QBasicAtomicInt engineSerial = Q_BASIC_ATOMIC_INITIALIZER(1);
static ReturnedValue throwTypeError(CallContext *ctx)
{
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
}
const int MinimumStackSize = 256; // in kbytes
@@ -155,6 +171,16 @@ quintptr getStackLimit()
}
+QJSEngine *ExecutionEngine::jsEngine() const
+{
+ return v8Engine->publicEngine();
+}
+
+QQmlEngine *ExecutionEngine::qmlEngine() const
+{
+ return v8Engine->engine();
+}
+
ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
: current(0)
, memoryManager(new QV4::MemoryManager)
@@ -164,7 +190,6 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
, jsStack(new WTF::PageAllocation)
, debugger(0)
, profiler(0)
- , globalObject(0)
, globalCode(0)
, v8Engine(0)
, argumentsAccessors(0)
@@ -198,10 +223,16 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
// reserve space for the JS stack
// we allow it to grow to 2 times JSStackLimit, as we can overshoot due to garbage collection
// and ScopedValues allocated outside of JIT'ed methods.
- *jsStack = WTF::PageAllocation::allocate(2*JSStackLimit, WTF::OSAllocator::JSVMStackPages, true);
+ *jsStack = WTF::PageAllocation::allocate(2 * JSStackLimit, WTF::OSAllocator::JSVMStackPages,
+ /* writable */ true, /* executable */ false,
+ /* includesGuardPages */ true);
jsStackBase = (Value *)jsStack->base();
jsStackTop = jsStackBase;
+#ifdef V4_USE_VALGRIND
+ VALGRIND_MAKE_MEM_UNDEFINED(jsStackBase, 2*JSStackLimit);
+#endif
+
// set up stack limits
jsStackLimit = jsStackBase + JSStackLimit/sizeof(Value);
cStackLimit = getStackLimit();
@@ -215,10 +246,9 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
classPool = new InternalClassPool;
emptyClass = new (classPool) InternalClass(this);
- executionContextClass = InternalClass::create(this, ExecutionContext::staticVTable(), 0);
- constructClass = InternalClass::create(this, Object::staticVTable(), 0);
- stringClass = InternalClass::create(this, String::staticVTable(), 0);
- regExpValueClass = InternalClass::create(this, RegExp::staticVTable(), 0);
+ executionContextClass = InternalClass::create(this, ExecutionContext::staticVTable());
+ stringClass = InternalClass::create(this, String::staticVTable());
+ regExpValueClass = InternalClass::create(this, RegExp::staticVTable());
id_empty = newIdentifier(QString());
id_undefined = newIdentifier(QStringLiteral("undefined"));
@@ -252,21 +282,24 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
id_toString = newIdentifier(QStringLiteral("toString"));
id_destroy = newIdentifier(QStringLiteral("destroy"));
id_valueOf = newIdentifier(QStringLiteral("valueOf"));
+ id_byteLength = newIdentifier(QStringLiteral("byteLength"));
+ id_byteOffset = newIdentifier(QStringLiteral("byteOffset"));
+ id_buffer = newIdentifier(QStringLiteral("buffer"));
+ id_lastIndex = newIdentifier(QStringLiteral("lastIndex"));
- memberDataClass = InternalClass::create(this, MemberData::staticVTable(), 0);
+ memberDataClass = InternalClass::create(this, MemberData::staticVTable());
- ScopedObject objectPrototype(scope, memoryManager->alloc<ObjectPrototype>(InternalClass::create(this, ObjectPrototype::staticVTable(), 0)));
- objectClass = InternalClass::create(this, Object::staticVTable(), objectPrototype);
+ objectPrototype = memoryManager->alloc<ObjectPrototype>(InternalClass::create(this, ObjectPrototype::staticVTable()), (QV4::Object *)0);
+ objectClass = InternalClass::create(this, Object::staticVTable());
Q_ASSERT(objectClass->vtable == Object::staticVTable());
- arrayClass = InternalClass::create(this, ArrayObject::staticVTable(), objectPrototype);
+ arrayClass = InternalClass::create(this, ArrayObject::staticVTable());
arrayClass = arrayClass->addMember(id_length, Attr_NotConfigurable|Attr_NotEnumerable);
- ScopedObject arrayPrototype(scope, memoryManager->alloc<ArrayPrototype>(arrayClass));
- arrayClass = arrayClass->changePrototype(arrayPrototype);
+ arrayPrototype = memoryManager->alloc<ArrayPrototype>(arrayClass, objectPrototype.asObject());
- simpleArrayDataClass = InternalClass::create(this, SimpleArrayData::staticVTable(), 0);
+ simpleArrayDataClass = InternalClass::create(this, SimpleArrayData::staticVTable());
- InternalClass *argsClass = InternalClass::create(this, ArgumentsObject::staticVTable(), objectPrototype);
+ InternalClass *argsClass = InternalClass::create(this, ArgumentsObject::staticVTable());
argsClass = argsClass->addMember(id_length, Attr_NotEnumerable);
argumentsObjectClass = argsClass->addMember(id_callee, Attr_Data|Attr_NotEnumerable);
strictArgumentsObjectClass = argsClass->addMember(id_callee, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
@@ -274,143 +307,170 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory)
Q_ASSERT(argumentsObjectClass->vtable == ArgumentsObject::staticVTable());
Q_ASSERT(strictArgumentsObjectClass->vtable == ArgumentsObject::staticVTable());
+ m_globalObject = newObject();
+ Q_ASSERT(globalObject()->internalClass()->vtable);
initRootContext();
- ScopedObject stringPrototype(scope, memoryManager->alloc<StringPrototype>(InternalClass::create(this, StringPrototype::staticVTable(), objectPrototype)));
- stringObjectClass = InternalClass::create(this, String::staticVTable(), stringPrototype);
+ stringPrototype = memoryManager->alloc<StringPrototype>(InternalClass::create(this, StringPrototype::staticVTable()), objectPrototype.asObject());
+ stringObjectClass = InternalClass::create(this, String::staticVTable());
- ScopedObject numberPrototype(scope, memoryManager->alloc<NumberPrototype>(InternalClass::create(this, NumberPrototype::staticVTable(), objectPrototype)));
- numberClass = InternalClass::create(this, NumberObject::staticVTable(), numberPrototype);
+ numberPrototype = memoryManager->alloc<NumberPrototype>(InternalClass::create(this, NumberPrototype::staticVTable()), objectPrototype.asObject());
+ numberClass = InternalClass::create(this, NumberObject::staticVTable());
- ScopedObject booleanPrototype(scope, memoryManager->alloc<BooleanPrototype>(InternalClass::create(this, BooleanPrototype::staticVTable(), objectPrototype)));
- booleanClass = InternalClass::create(this, BooleanObject::staticVTable(), booleanPrototype);
+ booleanPrototype = memoryManager->alloc<BooleanPrototype>(InternalClass::create(this, BooleanPrototype::staticVTable()), objectPrototype.asObject());
+ booleanClass = InternalClass::create(this, BooleanObject::staticVTable());
- ScopedObject datePrototype(scope, memoryManager->alloc<DatePrototype>(InternalClass::create(this, DatePrototype::staticVTable(), objectPrototype)));
- dateClass = InternalClass::create(this, DateObject::staticVTable(), datePrototype);
+ datePrototype = memoryManager->alloc<DatePrototype>(InternalClass::create(this, DatePrototype::staticVTable()), objectPrototype.asObject());
+ dateClass = InternalClass::create(this, DateObject::staticVTable());
- InternalClass *functionProtoClass = InternalClass::create(this, FunctionObject::staticVTable(), objectPrototype);
+ InternalClass *functionProtoClass = InternalClass::create(this, FunctionObject::staticVTable());
uint index;
functionProtoClass = functionProtoClass->addMember(id_prototype, Attr_NotEnumerable, &index);
- Q_ASSERT(index == FunctionObject::Index_Prototype);
- ScopedObject functionPrototype(scope, memoryManager->alloc<FunctionPrototype>(functionProtoClass));
- functionClass = InternalClass::create(this, FunctionObject::staticVTable(), functionPrototype);
+ Q_ASSERT(index == Heap::FunctionObject::Index_Prototype);
+ functionPrototype = memoryManager->alloc<FunctionPrototype>(functionProtoClass, objectPrototype.asObject());
+ functionClass = InternalClass::create(this, FunctionObject::staticVTable());
functionClass = functionClass->addMember(id_prototype, Attr_NotEnumerable|Attr_NotConfigurable, &index);
- Q_ASSERT(index == FunctionObject::Index_Prototype);
+ Q_ASSERT(index == Heap::FunctionObject::Index_Prototype);
protoClass = objectClass->addMember(id_constructor, Attr_NotEnumerable, &index);
- Q_ASSERT(index == FunctionObject::Index_ProtoConstructor);
+ Q_ASSERT(index == Heap::FunctionObject::Index_ProtoConstructor);
- Scoped<RegExpPrototype> regExpPrototype(scope, memoryManager->alloc<RegExpPrototype>(InternalClass::create(this, RegExpPrototype::staticVTable(), objectPrototype)));
- regExpClass = InternalClass::create(this, RegExpObject::staticVTable(), regExpPrototype.getPointer());
+ regExpPrototype = memoryManager->alloc<RegExpPrototype>(this);
+ regExpClass = InternalClass::create(this, RegExpObject::staticVTable());
regExpExecArrayClass = arrayClass->addMember(id_index, Attr_Data, &index);
Q_ASSERT(index == RegExpObject::Index_ArrayIndex);
regExpExecArrayClass = regExpExecArrayClass->addMember(id_input, Attr_Data, &index);
Q_ASSERT(index == RegExpObject::Index_ArrayInput);
- ScopedObject errorPrototype(scope, memoryManager->alloc<ErrorPrototype>(InternalClass::create(this, ErrorObject::staticVTable(), objectPrototype)));
- errorClass = InternalClass::create(this, ErrorObject::staticVTable(), errorPrototype);
- ScopedObject evalErrorPrototype(scope, memoryManager->alloc<EvalErrorPrototype>(errorClass));
- evalErrorClass = InternalClass::create(this, EvalErrorObject::staticVTable(), evalErrorPrototype);
- ScopedObject rangeErrorPrototype(scope, memoryManager->alloc<RangeErrorPrototype>(errorClass));
- rangeErrorClass = InternalClass::create(this, RangeErrorObject::staticVTable(), rangeErrorPrototype);
- ScopedObject referenceErrorPrototype(scope, memoryManager->alloc<ReferenceErrorPrototype>(errorClass));
- referenceErrorClass = InternalClass::create(this, ReferenceErrorObject::staticVTable(), referenceErrorPrototype);
- ScopedObject syntaxErrorPrototype(scope, memoryManager->alloc<SyntaxErrorPrototype>(errorClass));
- syntaxErrorClass = InternalClass::create(this, SyntaxErrorObject::staticVTable(), syntaxErrorPrototype);
- ScopedObject typeErrorPrototype(scope, memoryManager->alloc<TypeErrorPrototype>(errorClass));
- typeErrorClass = InternalClass::create(this, TypeErrorObject::staticVTable(), typeErrorPrototype);
- ScopedObject uRIErrorPrototype(scope, memoryManager->alloc<URIErrorPrototype>(errorClass));
- uriErrorClass = InternalClass::create(this, URIErrorObject::staticVTable(), uRIErrorPrototype);
-
- ScopedObject variantPrototype(scope, memoryManager->alloc<VariantPrototype>(InternalClass::create(this, VariantPrototype::staticVTable(), objectPrototype)));
- variantClass = InternalClass::create(this, VariantObject::staticVTable(), variantPrototype);
- Q_ASSERT(variantClass->prototype == variantPrototype);
- Q_ASSERT(variantPrototype->internalClass()->prototype == objectPrototype);
-
- sequencePrototype = ScopedValue(scope, memoryManager->alloc<SequencePrototype>(arrayClass));
-
- objectCtor = memoryManager->alloc<ObjectCtor>(rootContext);
- stringCtor = memoryManager->alloc<StringCtor>(rootContext);
- numberCtor = memoryManager->alloc<NumberCtor>(rootContext);
- booleanCtor = memoryManager->alloc<BooleanCtor>(rootContext);
- arrayCtor = memoryManager->alloc<ArrayCtor>(rootContext);
- functionCtor = memoryManager->alloc<FunctionCtor>(rootContext);
- dateCtor = memoryManager->alloc<DateCtor>(rootContext);
- regExpCtor = memoryManager->alloc<RegExpCtor>(rootContext);
- errorCtor = memoryManager->alloc<ErrorCtor>(rootContext);
- evalErrorCtor = memoryManager->alloc<EvalErrorCtor>(rootContext);
- rangeErrorCtor = memoryManager->alloc<RangeErrorCtor>(rootContext);
- referenceErrorCtor = memoryManager->alloc<ReferenceErrorCtor>(rootContext);
- syntaxErrorCtor = memoryManager->alloc<SyntaxErrorCtor>(rootContext);
- typeErrorCtor = memoryManager->alloc<TypeErrorCtor>(rootContext);
- uRIErrorCtor = memoryManager->alloc<URIErrorCtor>(rootContext);
-
- static_cast<ObjectPrototype *>(objectPrototype.getPointer())->init(this, objectCtor.asObject());
- static_cast<StringPrototype *>(stringPrototype.getPointer())->init(this, stringCtor.asObject());
- static_cast<NumberPrototype *>(numberPrototype.getPointer())->init(this, numberCtor.asObject());
- static_cast<BooleanPrototype *>(booleanPrototype.getPointer())->init(this, booleanCtor.asObject());
- static_cast<ArrayPrototype *>(arrayPrototype.getPointer())->init(this, arrayCtor.asObject());
- static_cast<DatePrototype *>(datePrototype.getPointer())->init(this, dateCtor.asObject());
- static_cast<FunctionPrototype *>(functionPrototype.getPointer())->init(this, functionCtor.asObject());
- static_cast<RegExpPrototype *>(regExpPrototype.getPointer())->init(this, regExpCtor.asObject());
- static_cast<ErrorPrototype *>(errorPrototype.getPointer())->init(this, errorCtor.asObject());
- static_cast<EvalErrorPrototype *>(evalErrorPrototype.getPointer())->init(this, evalErrorCtor.asObject());
- static_cast<RangeErrorPrototype *>(rangeErrorPrototype.getPointer())->init(this, rangeErrorCtor.asObject());
- static_cast<ReferenceErrorPrototype *>(referenceErrorPrototype.getPointer())->init(this, referenceErrorCtor.asObject());
- static_cast<SyntaxErrorPrototype *>(syntaxErrorPrototype.getPointer())->init(this, syntaxErrorCtor.asObject());
- static_cast<TypeErrorPrototype *>(typeErrorPrototype.getPointer())->init(this, typeErrorCtor.asObject());
- static_cast<URIErrorPrototype *>(uRIErrorPrototype.getPointer())->init(this, uRIErrorCtor.asObject());
-
- static_cast<VariantPrototype *>(variantPrototype.getPointer())->init();
- static_cast<SequencePrototype *>(sequencePrototype.managed())->init();
+ errorPrototype = memoryManager->alloc<ErrorPrototype>(InternalClass::create(this, ErrorObject::staticVTable()), objectPrototype.asObject());
+ errorClass = InternalClass::create(this, ErrorObject::staticVTable());
+ evalErrorPrototype = memoryManager->alloc<EvalErrorPrototype>(errorClass, errorPrototype.asObject());
+ evalErrorClass = InternalClass::create(this, EvalErrorObject::staticVTable());
+ rangeErrorPrototype = memoryManager->alloc<RangeErrorPrototype>(errorClass, errorPrototype.asObject());
+ rangeErrorClass = InternalClass::create(this, RangeErrorObject::staticVTable());
+ referenceErrorPrototype = memoryManager->alloc<ReferenceErrorPrototype>(errorClass, errorPrototype.asObject());
+ referenceErrorClass = InternalClass::create(this, ReferenceErrorObject::staticVTable());
+ syntaxErrorPrototype = memoryManager->alloc<SyntaxErrorPrototype>(errorClass, errorPrototype.asObject());
+ syntaxErrorClass = InternalClass::create(this, SyntaxErrorObject::staticVTable());
+ typeErrorPrototype = memoryManager->alloc<TypeErrorPrototype>(errorClass, errorPrototype.asObject());
+ typeErrorClass = InternalClass::create(this, TypeErrorObject::staticVTable());
+ uRIErrorPrototype = memoryManager->alloc<URIErrorPrototype>(errorClass, errorPrototype.asObject());
+ uriErrorClass = InternalClass::create(this, URIErrorObject::staticVTable());
+
+ variantPrototype = memoryManager->alloc<VariantPrototype>(InternalClass::create(this, VariantPrototype::staticVTable()), objectPrototype.asObject());
+ variantClass = InternalClass::create(this, VariantObject::staticVTable());
+ Q_ASSERT(variantPrototype.asObject()->prototype() == objectPrototype.asObject()->d());
+
+ sequencePrototype = ScopedValue(scope, memoryManager->alloc<SequencePrototype>(arrayClass, arrayPrototype.asObject()));
+
+ ScopedContext global(scope, rootContext());
+ objectCtor = memoryManager->alloc<ObjectCtor>(global);
+ stringCtor = memoryManager->alloc<StringCtor>(global);
+ numberCtor = memoryManager->alloc<NumberCtor>(global);
+ booleanCtor = memoryManager->alloc<BooleanCtor>(global);
+ arrayCtor = memoryManager->alloc<ArrayCtor>(global);
+ functionCtor = memoryManager->alloc<FunctionCtor>(global);
+ dateCtor = memoryManager->alloc<DateCtor>(global);
+ regExpCtor = memoryManager->alloc<RegExpCtor>(global);
+ errorCtor = memoryManager->alloc<ErrorCtor>(global);
+ evalErrorCtor = memoryManager->alloc<EvalErrorCtor>(global);
+ rangeErrorCtor = memoryManager->alloc<RangeErrorCtor>(global);
+ referenceErrorCtor = memoryManager->alloc<ReferenceErrorCtor>(global);
+ syntaxErrorCtor = memoryManager->alloc<SyntaxErrorCtor>(global);
+ typeErrorCtor = memoryManager->alloc<TypeErrorCtor>(global);
+ uRIErrorCtor = memoryManager->alloc<URIErrorCtor>(global);
+
+ static_cast<ObjectPrototype *>(objectPrototype.asObject())->init(this, objectCtor.asObject());
+ static_cast<StringPrototype *>(stringPrototype.asObject())->init(this, stringCtor.asObject());
+ static_cast<NumberPrototype *>(numberPrototype.asObject())->init(this, numberCtor.asObject());
+ static_cast<BooleanPrototype *>(booleanPrototype.asObject())->init(this, booleanCtor.asObject());
+ static_cast<ArrayPrototype *>(arrayPrototype.asObject())->init(this, arrayCtor.asObject());
+ static_cast<DatePrototype *>(datePrototype.asObject())->init(this, dateCtor.asObject());
+ static_cast<FunctionPrototype *>(functionPrototype.asObject())->init(this, functionCtor.asObject());
+ static_cast<RegExpPrototype *>(regExpPrototype.asObject())->init(this, regExpCtor.asObject());
+ static_cast<ErrorPrototype *>(errorPrototype.asObject())->init(this, errorCtor.asObject());
+ static_cast<EvalErrorPrototype *>(evalErrorPrototype.asObject())->init(this, evalErrorCtor.asObject());
+ static_cast<RangeErrorPrototype *>(rangeErrorPrototype.asObject())->init(this, rangeErrorCtor.asObject());
+ static_cast<ReferenceErrorPrototype *>(referenceErrorPrototype.asObject())->init(this, referenceErrorCtor.asObject());
+ static_cast<SyntaxErrorPrototype *>(syntaxErrorPrototype.asObject())->init(this, syntaxErrorCtor.asObject());
+ static_cast<TypeErrorPrototype *>(typeErrorPrototype.asObject())->init(this, typeErrorCtor.asObject());
+ static_cast<URIErrorPrototype *>(uRIErrorPrototype.asObject())->init(this, uRIErrorCtor.asObject());
+
+ static_cast<VariantPrototype *>(variantPrototype.asObject())->init();
+ sequencePrototype.cast<SequencePrototype>()->init();
+
+
+ // typed arrays
+
+ arrayBufferCtor = memoryManager->alloc<ArrayBufferCtor>(global);
+ arrayBufferPrototype = memoryManager->alloc<ArrayBufferPrototype>(objectClass, objectPrototype.asObject());
+ static_cast<ArrayBufferPrototype *>(arrayBufferPrototype.asObject())->init(this, arrayBufferCtor.asObject());
+ arrayBufferClass = InternalClass::create(this, ArrayBuffer::staticVTable());
+
+ dataViewCtor = memoryManager->alloc<DataViewCtor>(global);
+ dataViewPrototype = memoryManager->alloc<DataViewPrototype>(objectClass, objectPrototype.asObject());
+ static_cast<DataViewPrototype *>(dataViewPrototype.asObject())->init(this, dataViewCtor.asObject());
+ dataViewClass = InternalClass::create(this, DataView::staticVTable());
+
+ for (int i = 0; i < Heap::TypedArray::NTypes; ++i) {
+ typedArrayCtors[i] = memoryManager->alloc<TypedArrayCtor>(global, Heap::TypedArray::Type(i));
+ typedArrayPrototype[i] = memoryManager->alloc<TypedArrayPrototype>(this, Heap::TypedArray::Type(i));
+ typedArrayPrototype[i].as<TypedArrayPrototype>()->init(this, static_cast<TypedArrayCtor *>(typedArrayCtors[i].asObject()));
+ typedArrayClasses[i] = InternalClass::create(this, TypedArray::staticVTable());
+ }
//
// set up the global object
//
- globalObject = newObject()->getPointer();
- rootContext->d()->global = globalObject;
- rootContext->d()->callData->thisObject = globalObject;
- Q_ASSERT(globalObject->internalClass()->vtable);
-
- globalObject->defineDefaultProperty(QStringLiteral("Object"), objectCtor);
- globalObject->defineDefaultProperty(QStringLiteral("String"), stringCtor);
- globalObject->defineDefaultProperty(QStringLiteral("Number"), numberCtor);
- globalObject->defineDefaultProperty(QStringLiteral("Boolean"), booleanCtor);
- globalObject->defineDefaultProperty(QStringLiteral("Array"), arrayCtor);
- globalObject->defineDefaultProperty(QStringLiteral("Function"), functionCtor);
- globalObject->defineDefaultProperty(QStringLiteral("Date"), dateCtor);
- globalObject->defineDefaultProperty(QStringLiteral("RegExp"), regExpCtor);
- globalObject->defineDefaultProperty(QStringLiteral("Error"), errorCtor);
- globalObject->defineDefaultProperty(QStringLiteral("EvalError"), evalErrorCtor);
- globalObject->defineDefaultProperty(QStringLiteral("RangeError"), rangeErrorCtor);
- globalObject->defineDefaultProperty(QStringLiteral("ReferenceError"), referenceErrorCtor);
- globalObject->defineDefaultProperty(QStringLiteral("SyntaxError"), syntaxErrorCtor);
- globalObject->defineDefaultProperty(QStringLiteral("TypeError"), typeErrorCtor);
- globalObject->defineDefaultProperty(QStringLiteral("URIError"), uRIErrorCtor);
+ rootContext()->global = globalObject()->d();
+ rootContext()->callData->thisObject = globalObject();
+ Q_ASSERT(globalObject()->internalClass()->vtable);
+
+ globalObject()->defineDefaultProperty(QStringLiteral("Object"), objectCtor);
+ globalObject()->defineDefaultProperty(QStringLiteral("String"), stringCtor);
+ globalObject()->defineDefaultProperty(QStringLiteral("Number"), numberCtor);
+ globalObject()->defineDefaultProperty(QStringLiteral("Boolean"), booleanCtor);
+ globalObject()->defineDefaultProperty(QStringLiteral("Array"), arrayCtor);
+ globalObject()->defineDefaultProperty(QStringLiteral("Function"), functionCtor);
+ globalObject()->defineDefaultProperty(QStringLiteral("Date"), dateCtor);
+ globalObject()->defineDefaultProperty(QStringLiteral("RegExp"), regExpCtor);
+ globalObject()->defineDefaultProperty(QStringLiteral("Error"), errorCtor);
+ globalObject()->defineDefaultProperty(QStringLiteral("EvalError"), evalErrorCtor);
+ globalObject()->defineDefaultProperty(QStringLiteral("RangeError"), rangeErrorCtor);
+ globalObject()->defineDefaultProperty(QStringLiteral("ReferenceError"), referenceErrorCtor);
+ globalObject()->defineDefaultProperty(QStringLiteral("SyntaxError"), syntaxErrorCtor);
+ globalObject()->defineDefaultProperty(QStringLiteral("TypeError"), typeErrorCtor);
+ globalObject()->defineDefaultProperty(QStringLiteral("URIError"), uRIErrorCtor);
+
+ globalObject()->defineDefaultProperty(QStringLiteral("ArrayBuffer"), arrayBufferCtor);
+ globalObject()->defineDefaultProperty(QStringLiteral("DataView"), dataViewCtor);
+ ScopedString str(scope);
+ for (int i = 0; i < Heap::TypedArray::NTypes; ++i)
+ globalObject()->defineDefaultProperty((str = typedArrayCtors[i].asFunctionObject()->name())->toQString(), typedArrayCtors[i]);
ScopedObject o(scope);
- globalObject->defineDefaultProperty(QStringLiteral("Math"), (o = memoryManager->alloc<MathObject>(QV4::InternalClass::create(this, MathObject::staticVTable(), objectPrototype))));
- globalObject->defineDefaultProperty(QStringLiteral("JSON"), (o = memoryManager->alloc<JsonObject>(QV4::InternalClass::create(this, JsonObject::staticVTable(), objectPrototype))));
-
- globalObject->defineReadonlyProperty(QStringLiteral("undefined"), Primitive::undefinedValue());
- globalObject->defineReadonlyProperty(QStringLiteral("NaN"), Primitive::fromDouble(std::numeric_limits<double>::quiet_NaN()));
- globalObject->defineReadonlyProperty(QStringLiteral("Infinity"), Primitive::fromDouble(Q_INFINITY));
-
-
- evalFunction = Scoped<EvalFunction>(scope, memoryManager->alloc<EvalFunction>(rootContext));
- globalObject->defineDefaultProperty(QStringLiteral("eval"), (o = evalFunction));
-
- globalObject->defineDefaultProperty(QStringLiteral("parseInt"), GlobalFunctions::method_parseInt, 2);
- globalObject->defineDefaultProperty(QStringLiteral("parseFloat"), GlobalFunctions::method_parseFloat, 1);
- globalObject->defineDefaultProperty(QStringLiteral("isNaN"), GlobalFunctions::method_isNaN, 1);
- globalObject->defineDefaultProperty(QStringLiteral("isFinite"), GlobalFunctions::method_isFinite, 1);
- globalObject->defineDefaultProperty(QStringLiteral("decodeURI"), GlobalFunctions::method_decodeURI, 1);
- globalObject->defineDefaultProperty(QStringLiteral("decodeURIComponent"), GlobalFunctions::method_decodeURIComponent, 1);
- globalObject->defineDefaultProperty(QStringLiteral("encodeURI"), GlobalFunctions::method_encodeURI, 1);
- globalObject->defineDefaultProperty(QStringLiteral("encodeURIComponent"), GlobalFunctions::method_encodeURIComponent, 1);
- globalObject->defineDefaultProperty(QStringLiteral("escape"), GlobalFunctions::method_escape, 1);
- globalObject->defineDefaultProperty(QStringLiteral("unescape"), GlobalFunctions::method_unescape, 1);
-
- Scoped<String> name(scope, newString(QStringLiteral("thrower")));
- thrower = ScopedFunctionObject(scope, BuiltinFunction::create(rootContext, name.getPointer(), throwTypeError)).getPointer();
+ globalObject()->defineDefaultProperty(QStringLiteral("Math"), (o = memoryManager->alloc<MathObject>(this)));
+ globalObject()->defineDefaultProperty(QStringLiteral("JSON"), (o = memoryManager->alloc<JsonObject>(this)));
+
+ globalObject()->defineReadonlyProperty(QStringLiteral("undefined"), Primitive::undefinedValue());
+ globalObject()->defineReadonlyProperty(QStringLiteral("NaN"), Primitive::fromDouble(std::numeric_limits<double>::quiet_NaN()));
+ globalObject()->defineReadonlyProperty(QStringLiteral("Infinity"), Primitive::fromDouble(Q_INFINITY));
+
+
+ evalFunction = memoryManager->alloc<EvalFunction>(global);
+ globalObject()->defineDefaultProperty(QStringLiteral("eval"), (o = evalFunction));
+
+ globalObject()->defineDefaultProperty(QStringLiteral("parseInt"), GlobalFunctions::method_parseInt, 2);
+ globalObject()->defineDefaultProperty(QStringLiteral("parseFloat"), GlobalFunctions::method_parseFloat, 1);
+ globalObject()->defineDefaultProperty(QStringLiteral("isNaN"), GlobalFunctions::method_isNaN, 1);
+ globalObject()->defineDefaultProperty(QStringLiteral("isFinite"), GlobalFunctions::method_isFinite, 1);
+ globalObject()->defineDefaultProperty(QStringLiteral("decodeURI"), GlobalFunctions::method_decodeURI, 1);
+ globalObject()->defineDefaultProperty(QStringLiteral("decodeURIComponent"), GlobalFunctions::method_decodeURIComponent, 1);
+ globalObject()->defineDefaultProperty(QStringLiteral("encodeURI"), GlobalFunctions::method_encodeURI, 1);
+ globalObject()->defineDefaultProperty(QStringLiteral("encodeURIComponent"), GlobalFunctions::method_encodeURIComponent, 1);
+ globalObject()->defineDefaultProperty(QStringLiteral("escape"), GlobalFunctions::method_escape, 1);
+ globalObject()->defineDefaultProperty(QStringLiteral("unescape"), GlobalFunctions::method_unescape, 1);
+
+ ScopedString name(scope, newString(QStringLiteral("thrower")));
+ thrower = BuiltinFunction::create(global, name, ::throwTypeError);
}
ExecutionEngine::~ExecutionEngine()
@@ -456,15 +516,16 @@ void ExecutionEngine::enableProfiler()
void ExecutionEngine::initRootContext()
{
- GlobalContext *r = static_cast<GlobalContext*>(memoryManager->allocManaged(sizeof(GlobalContext::Data) + sizeof(CallData)));
+ Scope scope(this);
+ Scoped<GlobalContext> r(scope, static_cast<Heap::GlobalContext*>(memoryManager->allocManaged(sizeof(GlobalContext::Data) + sizeof(CallData))));
new (r->d()) GlobalContext::Data(this);
r->d()->callData = reinterpret_cast<CallData *>(r->d() + 1);
r->d()->callData->tag = QV4::Value::_Integer_Type;
r->d()->callData->argc = 0;
- r->d()->callData->thisObject = globalObject;
+ r->d()->callData->thisObject = globalObject();
r->d()->callData->args[0] = Encode::undefined();
- rootContext = r;
+ m_rootContext = r->d();
}
InternalClass *ExecutionEngine::newClass(const InternalClass &other)
@@ -472,63 +533,64 @@ InternalClass *ExecutionEngine::newClass(const InternalClass &other)
return new (classPool) InternalClass(other);
}
-ExecutionContext *ExecutionEngine::pushGlobalContext()
+Heap::ExecutionContext *ExecutionEngine::pushGlobalContext()
{
- GlobalContext *g = memoryManager->alloc<GlobalContext>(this);
- g->d()->callData = rootContext->d()->callData;
+ Scope scope(this);
+ Scoped<GlobalContext> g(scope, memoryManager->alloc<GlobalContext>(this));
+ g->d()->callData = rootContext()->callData;
- Q_ASSERT(currentContext() == g);
- return g;
+ Q_ASSERT(currentContext() == g->d());
+ return g->d();
}
-Returned<Object> *ExecutionEngine::newObject()
+Heap::Object *ExecutionEngine::newObject()
{
Scope scope(this);
ScopedObject object(scope, memoryManager->alloc<Object>(this));
- return object->asReturned<Object>();
+ return object->d();
}
-Returned<Object> *ExecutionEngine::newObject(InternalClass *internalClass)
+Heap::Object *ExecutionEngine::newObject(InternalClass *internalClass, QV4::Object *prototype)
{
Scope scope(this);
- ScopedObject object(scope, memoryManager->alloc<Object>(internalClass));
- return object->asReturned<Object>();
+ ScopedObject object(scope, memoryManager->alloc<Object>(internalClass, prototype));
+ return object->d();
}
-Returned<String> *ExecutionEngine::newString(const QString &s)
+Heap::String *ExecutionEngine::newString(const QString &s)
{
Scope scope(this);
- return ScopedString(scope, memoryManager->alloc<String>(this, s))->asReturned<String>();
+ return ScopedString(scope, memoryManager->alloc<String>(this, s))->d();
}
-String *ExecutionEngine::newIdentifier(const QString &text)
+Heap::String *ExecutionEngine::newIdentifier(const QString &text)
{
return identifierTable->insertString(text);
}
-Returned<Object> *ExecutionEngine::newStringObject(const ValueRef value)
+Heap::Object *ExecutionEngine::newStringObject(const ValueRef value)
{
Scope scope(this);
Scoped<StringObject> object(scope, memoryManager->alloc<StringObject>(this, value));
- return object->asReturned<Object>();
+ return object->d();
}
-Returned<Object> *ExecutionEngine::newNumberObject(const ValueRef value)
+Heap::Object *ExecutionEngine::newNumberObject(const ValueRef value)
{
Scope scope(this);
Scoped<NumberObject> object(scope, memoryManager->alloc<NumberObject>(this, value));
- return object->asReturned<Object>();
+ return object->d();
}
-Returned<Object> *ExecutionEngine::newBooleanObject(const ValueRef value)
+Heap::Object *ExecutionEngine::newBooleanObject(const ValueRef value)
{
Scope scope(this);
ScopedObject object(scope, memoryManager->alloc<BooleanObject>(this, value));
- return object->asReturned<Object>();
+ return object->d();
}
-Returned<ArrayObject> *ExecutionEngine::newArrayObject(int count)
+Heap::ArrayObject *ExecutionEngine::newArrayObject(int count)
{
Scope scope(this);
ScopedArrayObject object(scope, memoryManager->alloc<ArrayObject>(this));
@@ -538,39 +600,39 @@ Returned<ArrayObject> *ExecutionEngine::newArrayObject(int count)
object->arrayReserve(count);
object->setArrayLengthUnchecked(count);
}
- return object->asReturned<ArrayObject>();
+ return object->d();
}
-Returned<ArrayObject> *ExecutionEngine::newArrayObject(const QStringList &list)
+Heap::ArrayObject *ExecutionEngine::newArrayObject(const QStringList &list)
{
Scope scope(this);
ScopedArrayObject object(scope, memoryManager->alloc<ArrayObject>(this, list));
- return object->asReturned<ArrayObject>();
+ return object->d();
}
-Returned<ArrayObject> *ExecutionEngine::newArrayObject(InternalClass *ic)
+Heap::ArrayObject *ExecutionEngine::newArrayObject(InternalClass *ic, Object *prototype)
{
Scope scope(this);
- ScopedArrayObject object(scope, memoryManager->alloc<ArrayObject>(ic));
- return object->asReturned<ArrayObject>();
+ ScopedArrayObject object(scope, memoryManager->alloc<ArrayObject>(ic, prototype));
+ return object->d();
}
-Returned<DateObject> *ExecutionEngine::newDateObject(const ValueRef value)
+Heap::DateObject *ExecutionEngine::newDateObject(const ValueRef value)
{
Scope scope(this);
Scoped<DateObject> object(scope, memoryManager->alloc<DateObject>(this, value));
- return object->asReturned<DateObject>();
+ return object->d();
}
-Returned<DateObject> *ExecutionEngine::newDateObject(const QDateTime &dt)
+Heap::DateObject *ExecutionEngine::newDateObject(const QDateTime &dt)
{
Scope scope(this);
Scoped<DateObject> object(scope, memoryManager->alloc<DateObject>(this, dt));
- return object->asReturned<DateObject>();
+ return object->d();
}
-Returned<RegExpObject> *ExecutionEngine::newRegExpObject(const QString &pattern, int flags)
+Heap::RegExpObject *ExecutionEngine::newRegExpObject(const QString &pattern, int flags)
{
bool global = (flags & IR::RegExp::RegExp_Global);
bool ignoreCase = false;
@@ -585,122 +647,125 @@ Returned<RegExpObject> *ExecutionEngine::newRegExpObject(const QString &pattern,
return newRegExpObject(re, global);
}
-Returned<RegExpObject> *ExecutionEngine::newRegExpObject(RegExp *re, bool global)
+Heap::RegExpObject *ExecutionEngine::newRegExpObject(RegExp *re, bool global)
{
Scope scope(this);
Scoped<RegExpObject> object(scope, memoryManager->alloc<RegExpObject>(this, re, global));
- return object->asReturned<RegExpObject>();
+ return object->d();
}
-Returned<RegExpObject> *ExecutionEngine::newRegExpObject(const QRegExp &re)
+Heap::RegExpObject *ExecutionEngine::newRegExpObject(const QRegExp &re)
{
Scope scope(this);
Scoped<RegExpObject> object(scope, memoryManager->alloc<RegExpObject>(this, re));
- return object->asReturned<RegExpObject>();
+ return object->d();
}
-Returned<Object> *ExecutionEngine::newErrorObject(const ValueRef value)
+Heap::Object *ExecutionEngine::newErrorObject(const ValueRef value)
{
Scope scope(this);
- ScopedObject object(scope, memoryManager->alloc<ErrorObject>(errorClass, value));
- return object->asReturned<Object>();
+ ScopedObject object(scope, memoryManager->alloc<ErrorObject>(errorClass, errorPrototype.asObject(), value));
+ return object->d();
}
-Returned<Object> *ExecutionEngine::newSyntaxErrorObject(const QString &message)
+Heap::Object *ExecutionEngine::newSyntaxErrorObject(const QString &message)
{
Scope scope(this);
ScopedString s(scope, newString(message));
ScopedObject error(scope, memoryManager->alloc<SyntaxErrorObject>(this, s));
- return error->asReturned<Object>();
+ return error->d();
}
-Returned<Object> *ExecutionEngine::newSyntaxErrorObject(const QString &message, const QString &fileName, int line, int column)
+Heap::Object *ExecutionEngine::newSyntaxErrorObject(const QString &message, const QString &fileName, int line, int column)
{
Scope scope(this);
ScopedObject error(scope, memoryManager->alloc<SyntaxErrorObject>(this, message, fileName, line, column));
- return error->asReturned<Object>();
+ return error->d();
}
-Returned<Object> *ExecutionEngine::newReferenceErrorObject(const QString &message)
+Heap::Object *ExecutionEngine::newReferenceErrorObject(const QString &message)
{
Scope scope(this);
ScopedObject o(scope, memoryManager->alloc<ReferenceErrorObject>(this, message));
- return o->asReturned<Object>();
+ return o->d();
}
-Returned<Object> *ExecutionEngine::newReferenceErrorObject(const QString &message, const QString &fileName, int lineNumber, int columnNumber)
+Heap::Object *ExecutionEngine::newReferenceErrorObject(const QString &message, const QString &fileName, int lineNumber, int columnNumber)
{
Scope scope(this);
ScopedObject o(scope, memoryManager->alloc<ReferenceErrorObject>(this, message, fileName, lineNumber, columnNumber));
- return o->asReturned<Object>();
+ return o->d();
}
-Returned<Object> *ExecutionEngine::newTypeErrorObject(const QString &message)
+Heap::Object *ExecutionEngine::newTypeErrorObject(const QString &message)
{
Scope scope(this);
ScopedObject o(scope, memoryManager->alloc<TypeErrorObject>(this, message));
- return o->asReturned<Object>();
+ return o->d();
}
-Returned<Object> *ExecutionEngine::newRangeErrorObject(const QString &message)
+Heap::Object *ExecutionEngine::newRangeErrorObject(const QString &message)
{
Scope scope(this);
ScopedObject o(scope, memoryManager->alloc<RangeErrorObject>(this, message));
- return o->asReturned<Object>();
+ return o->d();
}
-Returned<Object> *ExecutionEngine::newURIErrorObject(const ValueRef message)
+Heap::Object *ExecutionEngine::newURIErrorObject(const ValueRef message)
{
Scope scope(this);
ScopedObject o(scope, memoryManager->alloc<URIErrorObject>(this, message));
- return o->asReturned<Object>();
+ return o->d();
}
-Returned<Object> *ExecutionEngine::newVariantObject(const QVariant &v)
+Heap::Object *ExecutionEngine::newVariantObject(const QVariant &v)
{
Scope scope(this);
ScopedObject o(scope, memoryManager->alloc<VariantObject>(this, v));
- return o->asReturned<Object>();
+ return o->d();
}
-Returned<Object> *ExecutionEngine::newForEachIteratorObject(ExecutionContext *ctx, Object *o)
+Heap::Object *ExecutionEngine::newForEachIteratorObject(Object *o)
{
Scope scope(this);
- ScopedObject obj(scope, memoryManager->alloc<ForEachIteratorObject>(ctx, o));
- return obj->asReturned<Object>();
+ ScopedObject obj(scope, memoryManager->alloc<ForEachIteratorObject>(this, o));
+ return obj->d();
}
-Returned<Object> *ExecutionEngine::qmlContextObject() const
+Heap::Object *ExecutionEngine::qmlContextObject() const
{
- ExecutionContext *ctx = currentContext();
+ Heap::ExecutionContext *ctx = currentContext();
- if (ctx->d()->type == QV4::ExecutionContext::Type_SimpleCallContext && !ctx->d()->outer)
- ctx = ctx->d()->parent;
+ if (ctx->type == Heap::ExecutionContext::Type_SimpleCallContext && !ctx->outer)
+ ctx = ctx->parent;
- if (!ctx->d()->outer)
+ if (!ctx->outer)
return 0;
- while (ctx->d()->outer && ctx->d()->outer->d()->type != ExecutionContext::Type_GlobalContext)
- ctx = ctx->d()->outer;
+ while (ctx->outer && ctx->outer->type != Heap::ExecutionContext::Type_GlobalContext)
+ ctx = ctx->outer;
Q_ASSERT(ctx);
- if (ctx->d()->type != ExecutionContext::Type_QmlContext)
+ if (ctx->type != Heap::ExecutionContext::Type_QmlContext)
return 0;
- return static_cast<CallContext *>(ctx)->d()->activation->asReturned<Object>();
+ Q_ASSERT(static_cast<Heap::CallContext *>(ctx)->activation);
+ return static_cast<Heap::CallContext *>(ctx)->activation;
}
QVector<StackFrame> ExecutionEngine::stackTrace(int frameLimit) const
{
- Scope scope(this->currentContext());
+ Scope scope(const_cast<ExecutionEngine *>(this));
ScopedString name(scope);
QVector<StackFrame> stack;
- QV4::ExecutionContext *c = currentContext();
+ ScopedContext c(scope, currentContext());
+ ScopedFunctionObject function(scope);
while (c && frameLimit) {
- if (FunctionObject *function = c->getFunctionObject()) {
+ function = c->getFunctionObject();
+ if (function) {
StackFrame frame;
if (const Function *f = function->function())
frame.source = f->sourceFile();
@@ -723,7 +788,7 @@ QVector<StackFrame> ExecutionEngine::stackTrace(int frameLimit) const
StackFrame frame;
frame.source = globalCode->sourceFile();
frame.function = globalCode->name()->toQString();
- frame.line = rootContext->d()->lineNumber;
+ frame.line = rootContext()->lineNumber;
frame.column = -1;
stack.append(frame);
@@ -784,12 +849,13 @@ QUrl ExecutionEngine::resolvedUrl(const QString &file)
return src;
QUrl base;
- QV4::ExecutionContext *c = currentContext();
+ Scope scope(this);
+ ScopedContext c(scope, currentContext());
while (c) {
CallContext *callCtx = c->asCallContext();
if (callCtx && callCtx->d()->function) {
- if (callCtx->d()->function->function())
- base.setUrl(callCtx->d()->function->function()->sourceFile());
+ if (callCtx->d()->function->function)
+ base.setUrl(callCtx->d()->function->function->sourceFile());
break;
}
c = c->d()->parent;
@@ -822,9 +888,10 @@ void ExecutionEngine::requireArgumentsAccessors(int n)
memcpy(argumentsAccessors, oldAccessors, oldSize*sizeof(Property));
delete [] oldAccessors;
}
+ ScopedContext global(scope, scope.engine->rootContext());
for (int i = oldSize; i < nArgumentsAccessors; ++i) {
- argumentsAccessors[i].value = ScopedValue(scope, memoryManager->alloc<ArgumentsGetterFunction>(rootContext, i));
- argumentsAccessors[i].set = ScopedValue(scope, memoryManager->alloc<ArgumentsSetterFunction>(rootContext, i));
+ argumentsAccessors[i].value = ScopedValue(scope, memoryManager->alloc<ArgumentsGetterFunction>(global, i));
+ argumentsAccessors[i].set = ScopedValue(scope, memoryManager->alloc<ArgumentsSetterFunction>(global, i));
}
}
}
@@ -833,24 +900,24 @@ void ExecutionEngine::markObjects()
{
identifierTable->mark(this);
- globalObject->mark(this);
+ globalObject()->mark(this);
for (int i = 0; i < nArgumentsAccessors; ++i) {
const Property &pd = argumentsAccessors[i];
- if (FunctionObject *getter = pd.getter())
+ if (Heap::FunctionObject *getter = pd.getter())
getter->mark(this);
- if (FunctionObject *setter = pd.setter())
+ if (Heap::FunctionObject *setter = pd.setter())
setter->mark(this);
}
- ExecutionContext *c = currentContext();
+ Heap::ExecutionContext *c = currentContext();
while (c) {
Q_ASSERT(c->inUse());
- if (!c->markBit()) {
- c->d()->markBit = 1;
- c->markObjects(c, this);
+ if (!c->isMarked()) {
+ c->setMarkBit();
+ c->gcGetInternalClass()->vtable->markObjects(c, this);
}
- c = c->d()->parent;
+ c = c->parent;
}
id_empty->mark(this);
@@ -885,6 +952,10 @@ void ExecutionEngine::markObjects()
id_toString->mark(this);
id_destroy->mark(this);
id_valueOf->mark(this);
+ id_byteLength->mark(this);
+ id_byteOffset->mark(this);
+ id_buffer->mark(this);
+ id_lastIndex->mark(this);
objectCtor.mark(this);
stringCtor.mark(this);
@@ -901,8 +972,34 @@ void ExecutionEngine::markObjects()
syntaxErrorCtor.mark(this);
typeErrorCtor.mark(this);
uRIErrorCtor.mark(this);
+ arrayBufferCtor.mark(this);
+ dataViewCtor.mark(this);
+ for (int i = 0; i < Heap::TypedArray::NTypes; ++i)
+ typedArrayCtors[i].mark(this);
+
+ objectPrototype.mark(this);
+ arrayPrototype.mark(this);
+ stringPrototype.mark(this);
+ numberPrototype.mark(this);
+ booleanPrototype.mark(this);
+ datePrototype.mark(this);
+ functionPrototype.mark(this);
+ regExpPrototype.mark(this);
+ errorPrototype.mark(this);
+ evalErrorPrototype.mark(this);
+ rangeErrorPrototype.mark(this);
+ referenceErrorPrototype.mark(this);
+ syntaxErrorPrototype.mark(this);
+ typeErrorPrototype.mark(this);
+ uRIErrorPrototype.mark(this);
+ variantPrototype.mark(this);
sequencePrototype.mark(this);
+ arrayBufferPrototype.mark(this);
+ dataViewPrototype.mark(this);
+ for (int i = 0; i < Heap::TypedArray::NTypes; ++i)
+ typedArrayPrototype[i].mark(this);
+
exceptionValue.mark(this);
thrower->mark(this);
@@ -924,7 +1021,7 @@ QmlExtensions *ExecutionEngine::qmlExtensions()
return m_qmlExtensions;
}
-ReturnedValue ExecutionEngine::throwException(const ValueRef value)
+ReturnedValue ExecutionEngine::throwError(const ValueRef value)
{
// we can get in here with an exception already set, as the runtime
// doesn't check after every operation that can throw.
@@ -948,11 +1045,9 @@ ReturnedValue ExecutionEngine::throwException(const ValueRef value)
return Encode::undefined();
}
-ReturnedValue ExecutionEngine::catchException(ExecutionContext *catchingContext, StackTrace *trace)
+ReturnedValue ExecutionEngine::catchException(StackTrace *trace)
{
Q_ASSERT(hasException);
- Q_UNUSED(catchingContext);
- Q_ASSERT(currentContext() == catchingContext);
if (trace)
*trace = exceptionStackTrace;
exceptionStackTrace.clear();
@@ -962,11 +1057,97 @@ ReturnedValue ExecutionEngine::catchException(ExecutionContext *catchingContext,
return res;
}
-QQmlError ExecutionEngine::catchExceptionAsQmlError(ExecutionContext *context)
+ReturnedValue ExecutionEngine::throwError(const QString &message)
+{
+ Scope scope(this);
+ ScopedValue v(scope, newString(message));
+ v = newErrorObject(v);
+ return throwError(v);
+}
+
+ReturnedValue ExecutionEngine::throwSyntaxError(const QString &message, const QString &fileName, int line, int column)
+{
+ Scope scope(this);
+ ScopedObject error(scope, newSyntaxErrorObject(message, fileName, line, column));
+ return throwError(error);
+}
+
+ReturnedValue ExecutionEngine::throwSyntaxError(const QString &message)
+{
+ Scope scope(this);
+ ScopedObject error(scope, newSyntaxErrorObject(message));
+ return throwError(error);
+}
+
+
+ReturnedValue ExecutionEngine::throwTypeError()
+{
+ Scope scope(this);
+ ScopedObject error(scope, newTypeErrorObject(QStringLiteral("Type error")));
+ return throwError(error);
+}
+
+ReturnedValue ExecutionEngine::throwTypeError(const QString &message)
+{
+ Scope scope(this);
+ ScopedObject error(scope, newTypeErrorObject(message));
+ return throwError(error);
+}
+
+ReturnedValue ExecutionEngine::throwReferenceError(const ValueRef value)
+{
+ Scope scope(this);
+ ScopedString s(scope, value->toString(this));
+ QString msg = s->toQString() + QStringLiteral(" is not defined");
+ ScopedObject error(scope, newReferenceErrorObject(msg));
+ return throwError(error);
+}
+
+ReturnedValue ExecutionEngine::throwReferenceError(const QString &message, const QString &fileName, int line, int column)
+{
+ Scope scope(this);
+ QString msg = message;
+ ScopedObject error(scope, newReferenceErrorObject(msg, fileName, line, column));
+ return throwError(error);
+}
+
+ReturnedValue ExecutionEngine::throwRangeError(const QString &message)
+{
+ Scope scope(this);
+ ScopedObject error(scope, newRangeErrorObject(message));
+ return throwError(error);
+}
+
+ReturnedValue ExecutionEngine::throwRangeError(const ValueRef value)
+{
+ Scope scope(this);
+ ScopedString s(scope, value->toString(this));
+ QString msg = s->toQString() + QStringLiteral(" out of range");
+ ScopedObject error(scope, newRangeErrorObject(msg));
+ return throwError(error);
+}
+
+ReturnedValue ExecutionEngine::throwURIError(const ValueRef msg)
+{
+ Scope scope(this);
+ ScopedObject error(scope, newURIErrorObject(msg));
+ return throwError(error);
+}
+
+ReturnedValue ExecutionEngine::throwUnimplemented(const QString &message)
+{
+ Scope scope(this);
+ ScopedValue v(scope, newString(QStringLiteral("Unimplemented ") + message));
+ v = newErrorObject(v);
+ return throwError(v);
+}
+
+
+QQmlError ExecutionEngine::catchExceptionAsQmlError()
{
QV4::StackTrace trace;
- QV4::Scope scope(context);
- QV4::ScopedValue exception(scope, context->catchException(&trace));
+ QV4::Scope scope(this);
+ QV4::ScopedValue exception(scope, catchException(&trace));
QQmlError error;
if (!trace.isEmpty()) {
QV4::StackFrame frame = trace.first();
@@ -976,8 +1157,8 @@ QQmlError ExecutionEngine::catchExceptionAsQmlError(ExecutionContext *context)
}
QV4::Scoped<QV4::ErrorObject> errorObj(scope, exception);
if (!!errorObj && errorObj->asSyntaxError()) {
- QV4::ScopedString m(scope, errorObj->engine()->newString(QStringLiteral("message")));
- QV4::ScopedValue v(scope, errorObj->get(m.getPointer()));
+ QV4::ScopedString m(scope, newString(QStringLiteral("message")));
+ QV4::ScopedValue v(scope, errorObj->get(m));
error.setDescription(v->toQStringNoThrow());
} else
error.setDescription(exception->toQStringNoThrow());
@@ -999,4 +1180,702 @@ bool ExecutionEngine::recheckCStackLimits()
return (reinterpret_cast<quintptr>(&dummy) >= cStackLimit);
}
+
+// Variant conversion code
+
+typedef QSet<QV4::Heap::Object *> V4ObjectSet;
+static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::ValueRef value, int typeHint, bool createJSValueForObjects, V4ObjectSet *visitedObjects);
+static QObject *qtObjectFromJS(QV4::ExecutionEngine *engine, const QV4::ValueRef value);
+static QVariant objectToVariant(QV4::ExecutionEngine *e, QV4::Object *o, V4ObjectSet *visitedObjects = 0);
+static bool convertToNativeQObject(QV4::ExecutionEngine *e, const QV4::ValueRef value,
+ const QByteArray &targetType,
+ void **result);
+static QV4::ReturnedValue variantListToJS(QV4::ExecutionEngine *v4, const QVariantList &lst);
+static QV4::ReturnedValue variantMapToJS(QV4::ExecutionEngine *v4, const QVariantMap &vmap);
+static QV4::ReturnedValue variantToJS(QV4::ExecutionEngine *v4, const QVariant &value)
+{
+ return v4->metaTypeToJS(value.userType(), value.constData());
+}
+
+
+QVariant ExecutionEngine::toVariant(const ValueRef value, int typeHint, bool createJSValueForObjects)
+{
+ return ::toVariant(this, value, typeHint, createJSValueForObjects, 0);
+}
+
+
+static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::ValueRef value, int typeHint, bool createJSValueForObjects, V4ObjectSet *visitedObjects)
+{
+ Q_ASSERT (!value->isEmpty());
+ QV4::Scope scope(e);
+
+ if (QV4::VariantObject *v = value->as<QV4::VariantObject>())
+ return v->d()->data;
+
+ if (typeHint == QVariant::Bool)
+ return QVariant(value->toBoolean());
+
+ if (typeHint == QMetaType::QJsonValue)
+ return QVariant::fromValue(QV4::JsonObject::toJsonValue(value));
+
+ if (typeHint == qMetaTypeId<QJSValue>())
+ return QVariant::fromValue(QJSValue(new QJSValuePrivate(e, value)));
+
+ if (value->asObject()) {
+ QV4::ScopedObject object(scope, value);
+ if (typeHint == QMetaType::QJsonObject
+ && !value->asArrayObject() && !value->asFunctionObject()) {
+ return QVariant::fromValue(QV4::JsonObject::toJsonObject(object));
+ } else if (QV4::QObjectWrapper *wrapper = object->as<QV4::QObjectWrapper>()) {
+ return qVariantFromValue<QObject *>(wrapper->object());
+ } else if (object->as<QV4::QmlContextWrapper>()) {
+ return QVariant();
+ } else if (QV4::QmlTypeWrapper *w = object->as<QV4::QmlTypeWrapper>()) {
+ return w->toVariant();
+ } else if (QV4::QQmlValueTypeWrapper *v = object->as<QV4::QQmlValueTypeWrapper>()) {
+ return v->toVariant();
+ } else if (QV4::QmlListWrapper *l = object->as<QV4::QmlListWrapper>()) {
+ return l->toVariant();
+ } else if (object->isListType())
+ return QV4::SequencePrototype::toVariant(object);
+ }
+
+ if (value->asArrayObject()) {
+ QV4::ScopedArrayObject a(scope, value);
+ if (typeHint == qMetaTypeId<QList<QObject *> >()) {
+ QList<QObject *> list;
+ uint length = a->getLength();
+ QV4::Scoped<QV4::QObjectWrapper> qobjectWrapper(scope);
+ for (uint ii = 0; ii < length; ++ii) {
+ qobjectWrapper = a->getIndexed(ii);
+ if (!!qobjectWrapper) {
+ list << qobjectWrapper->object();
+ } else {
+ list << 0;
+ }
+ }
+
+ return qVariantFromValue<QList<QObject*> >(list);
+ } else if (typeHint == QMetaType::QJsonArray) {
+ return QVariant::fromValue(QV4::JsonObject::toJsonArray(a));
+ }
+
+ bool succeeded = false;
+ QVariant retn = QV4::SequencePrototype::toVariant(value, typeHint, &succeeded);
+ if (succeeded)
+ return retn;
+ }
+
+ if (value->isUndefined())
+ return QVariant();
+ if (value->isNull())
+ return QVariant(QMetaType::VoidStar, (void *)0);
+ if (value->isBoolean())
+ return value->booleanValue();
+ if (value->isInteger())
+ return value->integerValue();
+ if (value->isNumber())
+ return value->asDouble();
+ if (value->isString())
+ return value->stringValue()->toQString();
+ if (QV4::QQmlLocaleData *ld = value->as<QV4::QQmlLocaleData>())
+ return ld->d()->locale;
+ if (QV4::DateObject *d = value->asDateObject())
+ return d->toQDateTime();
+ // NOTE: since we convert QTime to JS Date, round trip will change the variant type (to QDateTime)!
+
+ QV4::ScopedObject o(scope, value);
+ Q_ASSERT(o);
+
+ if (QV4::RegExpObject *re = o->as<QV4::RegExpObject>())
+ return re->toQRegExp();
+
+ if (createJSValueForObjects)
+ return QVariant::fromValue(QJSValue(new QJSValuePrivate(o->asReturnedValue())));
+
+ return objectToVariant(e, o, visitedObjects);
+}
+
+static QVariant objectToVariant(QV4::ExecutionEngine *e, QV4::Object *o, V4ObjectSet *visitedObjects)
+{
+ Q_ASSERT(o);
+
+ V4ObjectSet recursionGuardSet;
+ if (!visitedObjects) {
+ visitedObjects = &recursionGuardSet;
+ } else if (visitedObjects->contains(o->d())) {
+ // Avoid recursion.
+ // For compatibility with QVariant{List,Map} conversion, we return an
+ // empty object (and no error is thrown).
+ if (o->asArrayObject())
+ return QVariantList();
+ return QVariantMap();
+ }
+ visitedObjects->insert(o->d());
+
+ QVariant result;
+
+ if (o->asArrayObject()) {
+ QV4::Scope scope(e);
+ QV4::ScopedArrayObject a(scope, o->asReturnedValue());
+ QV4::ScopedValue v(scope);
+ QVariantList list;
+
+ int length = a->getLength();
+ for (int ii = 0; ii < length; ++ii) {
+ v = a->getIndexed(ii);
+ list << ::toVariant(e, v, -1, /*createJSValueForObjects*/false, visitedObjects);
+ }
+
+ result = list;
+ } else if (!o->asFunctionObject()) {
+ QVariantMap map;
+ QV4::Scope scope(e);
+ QV4::ObjectIterator it(scope, o, QV4::ObjectIterator::EnumerableOnly);
+ QV4::ScopedValue name(scope);
+ QV4::ScopedValue val(scope);
+ while (1) {
+ name = it.nextPropertyNameAsString(val);
+ if (name->isNull())
+ break;
+
+ QString key = name->toQStringNoThrow();
+ map.insert(key, ::toVariant(e, val, /*type hint*/-1, /*createJSValueForObjects*/false, visitedObjects));
+ }
+
+ result = map;
+ }
+
+ visitedObjects->remove(o->d());
+ return result;
+}
+
+static QV4::ReturnedValue arrayFromVariantList(QV4::ExecutionEngine *e, const QVariantList &list)
+{
+ QV4::Scope scope(e);
+ QV4::ScopedArrayObject a(scope, e->newArrayObject());
+ int len = list.count();
+ a->arrayReserve(len);
+ QV4::ScopedValue v(scope);
+ for (int ii = 0; ii < len; ++ii)
+ a->arrayPut(ii, (v = scope.engine->fromVariant(list.at(ii))));
+
+ a->setArrayLengthUnchecked(len);
+ return a.asReturnedValue();
+}
+
+static QV4::ReturnedValue objectFromVariantMap(QV4::ExecutionEngine *e, const QVariantMap &map)
+{
+ QV4::Scope scope(e);
+ QV4::ScopedObject o(scope, e->newObject());
+ QV4::ScopedString s(scope);
+ QV4::ScopedValue v(scope);
+ for (QVariantMap::ConstIterator iter = map.begin(); iter != map.end(); ++iter) {
+ s = e->newString(iter.key());
+ uint idx = s->asArrayIndex();
+ if (idx > 16 && (!o->arrayData() || idx > o->arrayData()->length() * 2))
+ o->initSparseArray();
+ o->put(s, (v = e->fromVariant(iter.value())));
+ }
+ return o.asReturnedValue();
+}
+
+Q_CORE_EXPORT QString qt_regexp_toCanonical(const QString &, QRegExp::PatternSyntax);
+
+QV4::ReturnedValue QV4::ExecutionEngine::fromVariant(const QVariant &variant)
+{
+ int type = variant.userType();
+ const void *ptr = variant.constData();
+
+ if (type < QMetaType::User) {
+ switch (QMetaType::Type(type)) {
+ case QMetaType::UnknownType:
+ case QMetaType::Void:
+ return QV4::Encode::undefined();
+ case QMetaType::VoidStar:
+ return QV4::Encode::null();
+ case QMetaType::Bool:
+ return QV4::Encode(*reinterpret_cast<const bool*>(ptr));
+ case QMetaType::Int:
+ return QV4::Encode(*reinterpret_cast<const int*>(ptr));
+ case QMetaType::UInt:
+ return QV4::Encode(*reinterpret_cast<const uint*>(ptr));
+ case QMetaType::LongLong:
+ return QV4::Encode((double)*reinterpret_cast<const qlonglong*>(ptr));
+ case QMetaType::ULongLong:
+ return QV4::Encode((double)*reinterpret_cast<const qulonglong*>(ptr));
+ case QMetaType::Double:
+ return QV4::Encode(*reinterpret_cast<const double*>(ptr));
+ case QMetaType::QString:
+ return newString(*reinterpret_cast<const QString*>(ptr))->asReturnedValue();
+ case QMetaType::Float:
+ return QV4::Encode(*reinterpret_cast<const float*>(ptr));
+ case QMetaType::Short:
+ return QV4::Encode((int)*reinterpret_cast<const short*>(ptr));
+ case QMetaType::UShort:
+ return QV4::Encode((int)*reinterpret_cast<const unsigned short*>(ptr));
+ case QMetaType::Char:
+ return QV4::Encode((int)*reinterpret_cast<const char*>(ptr));
+ case QMetaType::UChar:
+ return QV4::Encode((int)*reinterpret_cast<const unsigned char*>(ptr));
+ case QMetaType::QChar:
+ return QV4::Encode((int)(*reinterpret_cast<const QChar*>(ptr)).unicode());
+ case QMetaType::QDateTime:
+ return QV4::Encode(newDateObject(*reinterpret_cast<const QDateTime *>(ptr)));
+ case QMetaType::QDate:
+ return QV4::Encode(newDateObject(QDateTime(*reinterpret_cast<const QDate *>(ptr))));
+ case QMetaType::QTime:
+ return QV4::Encode(newDateObject(QDateTime(QDate(1970,1,1), *reinterpret_cast<const QTime *>(ptr))));
+ case QMetaType::QRegExp:
+ return QV4::Encode(newRegExpObject(*reinterpret_cast<const QRegExp *>(ptr)));
+ case QMetaType::QObjectStar:
+ return QV4::QObjectWrapper::wrap(this, *reinterpret_cast<QObject* const *>(ptr));
+ case QMetaType::QStringList:
+ {
+ bool succeeded = false;
+ QV4::Scope scope(this);
+ QV4::ScopedValue retn(scope, QV4::SequencePrototype::fromVariant(this, variant, &succeeded));
+ if (succeeded)
+ return retn.asReturnedValue();
+ return QV4::Encode(newArrayObject(*reinterpret_cast<const QStringList *>(ptr)));
+ }
+ case QMetaType::QVariantList:
+ return arrayFromVariantList(this, *reinterpret_cast<const QVariantList *>(ptr));
+ case QMetaType::QVariantMap:
+ return objectFromVariantMap(this, *reinterpret_cast<const QVariantMap *>(ptr));
+ case QMetaType::QJsonValue:
+ return QV4::JsonObject::fromJsonValue(this, *reinterpret_cast<const QJsonValue *>(ptr));
+ case QMetaType::QJsonObject:
+ return QV4::JsonObject::fromJsonObject(this, *reinterpret_cast<const QJsonObject *>(ptr));
+ case QMetaType::QJsonArray:
+ return QV4::JsonObject::fromJsonArray(this, *reinterpret_cast<const QJsonArray *>(ptr));
+ case QMetaType::QLocale:
+ return QQmlLocale::wrap(this, *reinterpret_cast<const QLocale*>(ptr));
+ default:
+ break;
+ }
+
+ if (const QMetaObject *vtmo = QQmlValueTypeFactory::metaObjectForMetaType(type))
+ return QV4::QQmlValueTypeWrapper::create(this, variant, vtmo, type);
+ } else {
+ QV4::Scope scope(this);
+ if (type == qMetaTypeId<QQmlListReference>()) {
+ typedef QQmlListReferencePrivate QDLRP;
+ QDLRP *p = QDLRP::get((QQmlListReference*)ptr);
+ if (p->object) {
+ return QV4::QmlListWrapper::create(scope.engine, p->property, p->propertyType);
+ } else {
+ return QV4::Encode::null();
+ }
+ } else if (type == qMetaTypeId<QJSValue>()) {
+ const QJSValue *value = reinterpret_cast<const QJSValue *>(ptr);
+ QJSValuePrivate *valuep = QJSValuePrivate::get(*value);
+ return valuep->getValue(this);
+ } else if (type == qMetaTypeId<QList<QObject *> >()) {
+ // XXX Can this be made more by using Array as a prototype and implementing
+ // directly against QList<QObject*>?
+ const QList<QObject *> &list = *(QList<QObject *>*)ptr;
+ QV4::ScopedArrayObject a(scope, newArrayObject());
+ a->arrayReserve(list.count());
+ QV4::ScopedValue v(scope);
+ for (int ii = 0; ii < list.count(); ++ii)
+ a->arrayPut(ii, (v = QV4::QObjectWrapper::wrap(this, list.at(ii))));
+ a->setArrayLengthUnchecked(list.count());
+ return a.asReturnedValue();
+ } else if (QMetaType::typeFlags(type) & QMetaType::PointerToQObject) {
+ return QV4::QObjectWrapper::wrap(this, *reinterpret_cast<QObject* const *>(ptr));
+ }
+
+ bool objOk;
+ QObject *obj = QQmlMetaType::toQObject(variant, &objOk);
+ if (objOk)
+ return QV4::QObjectWrapper::wrap(this, obj);
+
+ bool succeeded = false;
+ QV4::ScopedValue retn(scope, QV4::SequencePrototype::fromVariant(this, variant, &succeeded));
+ if (succeeded)
+ return retn.asReturnedValue();
+
+ if (const QMetaObject *vtmo = QQmlValueTypeFactory::metaObjectForMetaType(type))
+ return QV4::QQmlValueTypeWrapper::create(this, variant, vtmo, type);
+ }
+
+ // XXX TODO: To be compatible, we still need to handle:
+ // + QObjectList
+ // + QList<int>
+
+ return QV4::Encode(newVariantObject(variant));
+}
+
+QVariantMap ExecutionEngine::variantMapFromJS(Object *o)
+{
+ return objectToVariant(this, o).toMap();
+}
+
+
+// Converts a QVariantList to JS.
+// The result is a new Array object with length equal to the length
+// of the QVariantList, and the elements being the QVariantList's
+// elements converted to JS, recursively.
+static QV4::ReturnedValue variantListToJS(QV4::ExecutionEngine *v4, const QVariantList &lst)
+{
+ QV4::Scope scope(v4);
+ QV4::ScopedArrayObject a(scope, v4->newArrayObject());
+ a->arrayReserve(lst.size());
+ QV4::ScopedValue v(scope);
+ for (int i = 0; i < lst.size(); i++)
+ a->arrayPut(i, (v = variantToJS(v4, lst.at(i))));
+ a->setArrayLengthUnchecked(lst.size());
+ return a.asReturnedValue();
+}
+
+// Converts a QVariantMap to JS.
+// The result is a new Object object with property names being
+// the keys of the QVariantMap, and values being the values of
+// the QVariantMap converted to JS, recursively.
+static QV4::ReturnedValue variantMapToJS(QV4::ExecutionEngine *v4, const QVariantMap &vmap)
+{
+ QV4::Scope scope(v4);
+ QV4::ScopedObject o(scope, v4->newObject());
+ QVariantMap::const_iterator it;
+ QV4::ScopedString s(scope);
+ QV4::ScopedValue v(scope);
+ for (it = vmap.constBegin(); it != vmap.constEnd(); ++it) {
+ s = v4->newIdentifier(it.key());
+ v = variantToJS(v4, it.value());
+ uint idx = s->asArrayIndex();
+ if (idx < UINT_MAX)
+ o->arraySet(idx, v);
+ else
+ o->insertMember(s, v);
+ }
+ return o.asReturnedValue();
+}
+
+// Converts the meta-type defined by the given type and data to JS.
+// Returns the value if conversion succeeded, an empty handle otherwise.
+QV4::ReturnedValue ExecutionEngine::metaTypeToJS(int type, const void *data)
+{
+ Q_ASSERT(data != 0);
+
+ // check if it's one of the types we know
+ switch (QMetaType::Type(type)) {
+ case QMetaType::UnknownType:
+ case QMetaType::Void:
+ return QV4::Encode::undefined();
+ case QMetaType::VoidStar:
+ return QV4::Encode::null();
+ case QMetaType::Bool:
+ return QV4::Encode(*reinterpret_cast<const bool*>(data));
+ case QMetaType::Int:
+ return QV4::Encode(*reinterpret_cast<const int*>(data));
+ case QMetaType::UInt:
+ return QV4::Encode(*reinterpret_cast<const uint*>(data));
+ case QMetaType::LongLong:
+ return QV4::Encode(double(*reinterpret_cast<const qlonglong*>(data)));
+ case QMetaType::ULongLong:
+#if defined(Q_OS_WIN) && defined(_MSC_FULL_VER) && _MSC_FULL_VER <= 12008804
+#pragma message("** NOTE: You need the Visual Studio Processor Pack to compile support for 64bit unsigned integers.")
+ return QV4::Encode(double((qlonglong)*reinterpret_cast<const qulonglong*>(data)));
+#elif defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET)
+ return QV4::Encode(double((qlonglong)*reinterpret_cast<const qulonglong*>(data)));
+#else
+ return QV4::Encode(double(*reinterpret_cast<const qulonglong*>(data)));
+#endif
+ case QMetaType::Double:
+ return QV4::Encode(*reinterpret_cast<const double*>(data));
+ case QMetaType::QString:
+ return newString(*reinterpret_cast<const QString*>(data))->asReturnedValue();
+ case QMetaType::Float:
+ return QV4::Encode(*reinterpret_cast<const float*>(data));
+ case QMetaType::Short:
+ return QV4::Encode((int)*reinterpret_cast<const short*>(data));
+ case QMetaType::UShort:
+ return QV4::Encode((int)*reinterpret_cast<const unsigned short*>(data));
+ case QMetaType::Char:
+ return QV4::Encode((int)*reinterpret_cast<const char*>(data));
+ case QMetaType::UChar:
+ return QV4::Encode((int)*reinterpret_cast<const unsigned char*>(data));
+ case QMetaType::QChar:
+ return QV4::Encode((int)(*reinterpret_cast<const QChar*>(data)).unicode());
+ case QMetaType::QStringList:
+ return QV4::Encode(newArrayObject(*reinterpret_cast<const QStringList *>(data)));
+ case QMetaType::QVariantList:
+ return variantListToJS(this, *reinterpret_cast<const QVariantList *>(data));
+ case QMetaType::QVariantMap:
+ return variantMapToJS(this, *reinterpret_cast<const QVariantMap *>(data));
+ case QMetaType::QDateTime:
+ return QV4::Encode(newDateObject(*reinterpret_cast<const QDateTime *>(data)));
+ case QMetaType::QDate:
+ return QV4::Encode(newDateObject(QDateTime(*reinterpret_cast<const QDate *>(data))));
+ case QMetaType::QRegExp:
+ return QV4::Encode(newRegExpObject(*reinterpret_cast<const QRegExp *>(data)));
+ case QMetaType::QObjectStar:
+ return QV4::QObjectWrapper::wrap(this, *reinterpret_cast<QObject* const *>(data));
+ case QMetaType::QVariant:
+ return variantToJS(this, *reinterpret_cast<const QVariant*>(data));
+ case QMetaType::QJsonValue:
+ return QV4::JsonObject::fromJsonValue(this, *reinterpret_cast<const QJsonValue *>(data));
+ case QMetaType::QJsonObject:
+ return QV4::JsonObject::fromJsonObject(this, *reinterpret_cast<const QJsonObject *>(data));
+ case QMetaType::QJsonArray:
+ return QV4::JsonObject::fromJsonArray(this, *reinterpret_cast<const QJsonArray *>(data));
+ default:
+ if (type == qMetaTypeId<QJSValue>()) {
+ return QJSValuePrivate::get(*reinterpret_cast<const QJSValue*>(data))->getValue(this);
+ } else {
+ QByteArray typeName = QMetaType::typeName(type);
+ if (typeName.endsWith('*') && !*reinterpret_cast<void* const *>(data)) {
+ return QV4::Encode::null();
+ }
+ QMetaType mt(type);
+ if (mt.flags() & QMetaType::IsGadget) {
+ Q_ASSERT(mt.metaObject());
+ return QV4::QQmlValueTypeWrapper::create(this, QVariant(type, data), mt.metaObject(), type);
+ }
+ // Fall back to wrapping in a QVariant.
+ return QV4::Encode(newVariantObject(QVariant(type, data)));
+ }
+ }
+ Q_UNREACHABLE();
+ return 0;
+}
+
+// Converts a JS value to a meta-type.
+// data must point to a place that can store a value of the given type.
+// Returns true if conversion succeeded, false otherwise.
+bool ExecutionEngine::metaTypeFromJS(const QV4::ValueRef value, int type, void *data)
+{
+ QV4::Scope scope(this);
+
+ // check if it's one of the types we know
+ switch (QMetaType::Type(type)) {
+ case QMetaType::Bool:
+ *reinterpret_cast<bool*>(data) = value->toBoolean();
+ return true;
+ case QMetaType::Int:
+ *reinterpret_cast<int*>(data) = value->toInt32();
+ return true;
+ case QMetaType::UInt:
+ *reinterpret_cast<uint*>(data) = value->toUInt32();
+ return true;
+ case QMetaType::LongLong:
+ *reinterpret_cast<qlonglong*>(data) = qlonglong(value->toInteger());
+ return true;
+ case QMetaType::ULongLong:
+ *reinterpret_cast<qulonglong*>(data) = qulonglong(value->toInteger());
+ return true;
+ case QMetaType::Double:
+ *reinterpret_cast<double*>(data) = value->toNumber();
+ return true;
+ case QMetaType::QString:
+ if (value->isUndefined() || value->isNull())
+ *reinterpret_cast<QString*>(data) = QString();
+ else
+ *reinterpret_cast<QString*>(data) = value->toQString();
+ return true;
+ case QMetaType::Float:
+ *reinterpret_cast<float*>(data) = value->toNumber();
+ return true;
+ case QMetaType::Short:
+ *reinterpret_cast<short*>(data) = short(value->toInt32());
+ return true;
+ case QMetaType::UShort:
+ *reinterpret_cast<unsigned short*>(data) = value->toUInt16();
+ return true;
+ case QMetaType::Char:
+ *reinterpret_cast<char*>(data) = char(value->toInt32());
+ return true;
+ case QMetaType::UChar:
+ *reinterpret_cast<unsigned char*>(data) = (unsigned char)(value->toInt32());
+ return true;
+ case QMetaType::QChar:
+ if (value->isString()) {
+ QString str = value->stringValue()->toQString();
+ *reinterpret_cast<QChar*>(data) = str.isEmpty() ? QChar() : str.at(0);
+ } else {
+ *reinterpret_cast<QChar*>(data) = QChar(ushort(value->toUInt16()));
+ }
+ return true;
+ case QMetaType::QDateTime:
+ if (QV4::DateObject *d = value->asDateObject()) {
+ *reinterpret_cast<QDateTime *>(data) = d->toQDateTime();
+ return true;
+ } break;
+ case QMetaType::QDate:
+ if (QV4::DateObject *d = value->asDateObject()) {
+ *reinterpret_cast<QDate *>(data) = d->toQDateTime().date();
+ return true;
+ } break;
+ case QMetaType::QRegExp:
+ if (QV4::RegExpObject *r = value->as<QV4::RegExpObject>()) {
+ *reinterpret_cast<QRegExp *>(data) = r->toQRegExp();
+ return true;
+ } break;
+ case QMetaType::QObjectStar: {
+ QV4::QObjectWrapper *qobjectWrapper = value->as<QV4::QObjectWrapper>();
+ if (qobjectWrapper || value->isNull()) {
+ *reinterpret_cast<QObject* *>(data) = qtObjectFromJS(scope.engine, value);
+ return true;
+ } break;
+ }
+ case QMetaType::QStringList: {
+ QV4::ScopedArrayObject a(scope, value);
+ if (a) {
+ *reinterpret_cast<QStringList *>(data) = a->toQStringList();
+ return true;
+ }
+ break;
+ }
+ case QMetaType::QVariantList: {
+ QV4::ScopedArrayObject a(scope, value);
+ if (a) {
+ *reinterpret_cast<QVariantList *>(data) = scope.engine->toVariant(a, /*typeHint*/-1, /*createJSValueForObjects*/false).toList();
+ return true;
+ }
+ break;
+ }
+ case QMetaType::QVariantMap: {
+ QV4::ScopedObject o(scope, value);
+ if (o) {
+ *reinterpret_cast<QVariantMap *>(data) = variantMapFromJS(o);
+ return true;
+ }
+ break;
+ }
+ case QMetaType::QVariant:
+ *reinterpret_cast<QVariant*>(data) = scope.engine->toVariant(value, /*typeHint*/-1, /*createJSValueForObjects*/false);
+ return true;
+ case QMetaType::QJsonValue:
+ *reinterpret_cast<QJsonValue *>(data) = QV4::JsonObject::toJsonValue(value);
+ return true;
+ case QMetaType::QJsonObject: {
+ QV4::ScopedObject o(scope, value);
+ *reinterpret_cast<QJsonObject *>(data) = QV4::JsonObject::toJsonObject(o);
+ return true;
+ }
+ case QMetaType::QJsonArray: {
+ QV4::ScopedArrayObject a(scope, value);
+ if (a) {
+ *reinterpret_cast<QJsonArray *>(data) = QV4::JsonObject::toJsonArray(a);
+ return true;
+ }
+ break;
+ }
+ default:
+ ;
+ }
+
+ {
+ QV4::Scoped<QV4::QQmlValueTypeWrapper> vtw(scope, value);
+ if (vtw && vtw->d()->metaType == type) {
+ vtw->toGadget(data);
+ return true;
+ }
+ }
+
+#if 0
+ if (isQtVariant(value)) {
+ const QVariant &var = variantValue(value);
+ // ### Enable once constructInPlace() is in qt master.
+ if (var.userType() == type) {
+ QMetaType::constructInPlace(type, data, var.constData());
+ return true;
+ }
+ if (var.canConvert(type)) {
+ QVariant vv = var;
+ vv.convert(type);
+ Q_ASSERT(vv.userType() == type);
+ QMetaType::constructInPlace(type, data, vv.constData());
+ return true;
+ }
+
+ }
+#endif
+
+ // Try to use magic; for compatibility with qscriptvalue_cast.
+
+ QByteArray name = QMetaType::typeName(type);
+ if (convertToNativeQObject(this, value, name, reinterpret_cast<void* *>(data)))
+ return true;
+ if (value->as<QV4::VariantObject>() && name.endsWith('*')) {
+ int valueType = QMetaType::type(name.left(name.size()-1));
+ QVariant &var = value->as<QV4::VariantObject>()->d()->data;
+ if (valueType == var.userType()) {
+ // We have T t, T* is requested, so return &t.
+ *reinterpret_cast<void* *>(data) = var.data();
+ return true;
+ } else if (value->isObject()) {
+ // Look in the prototype chain.
+ QV4::ScopedObject proto(scope, value->objectValue()->prototype());
+ while (proto) {
+ bool canCast = false;
+ if (QV4::VariantObject *vo = proto->as<QV4::VariantObject>()) {
+ const QVariant &v = vo->d()->data;
+ canCast = (type == v.userType()) || (valueType && (valueType == v.userType()));
+ }
+ else if (proto->as<QV4::QObjectWrapper>()) {
+ QByteArray className = name.left(name.size()-1);
+ QV4::ScopedObject p(scope, proto.getPointer());
+ if (QObject *qobject = qtObjectFromJS(scope.engine, p))
+ canCast = qobject->qt_metacast(className) != 0;
+ }
+ if (canCast) {
+ QByteArray varTypeName = QMetaType::typeName(var.userType());
+ if (varTypeName.endsWith('*'))
+ *reinterpret_cast<void* *>(data) = *reinterpret_cast<void* *>(var.data());
+ else
+ *reinterpret_cast<void* *>(data) = var.data();
+ return true;
+ }
+ proto = proto->prototype();
+ }
+ }
+ } else if (value->isNull() && name.endsWith('*')) {
+ *reinterpret_cast<void* *>(data) = 0;
+ return true;
+ } else if (type == qMetaTypeId<QJSValue>()) {
+ *reinterpret_cast<QJSValue*>(data) = QJSValuePrivate::get(new QJSValuePrivate(this, value));
+ return true;
+ }
+
+ return false;
+}
+
+static bool convertToNativeQObject(QV4::ExecutionEngine *e, const QV4::ValueRef value, const QByteArray &targetType, void **result)
+{
+ if (!targetType.endsWith('*'))
+ return false;
+ if (QObject *qobject = qtObjectFromJS(e, value)) {
+ int start = targetType.startsWith("const ") ? 6 : 0;
+ QByteArray className = targetType.mid(start, targetType.size()-start-1);
+ if (void *instance = qobject->qt_metacast(className)) {
+ *result = instance;
+ return true;
+ }
+ }
+ return false;
+}
+
+static QObject *qtObjectFromJS(QV4::ExecutionEngine *engine, const QV4::ValueRef value)
+{
+ if (!value->isObject())
+ return 0;
+
+ QV4::Scope scope(engine);
+ QV4::Scoped<QV4::VariantObject> v(scope, value);
+
+ if (v) {
+ QVariant variant = v->d()->data;
+ int type = variant.userType();
+ if (type == QMetaType::QObjectStar)
+ return *reinterpret_cast<QObject* const *>(variant.constData());
+ }
+ QV4::Scoped<QV4::QObjectWrapper> wrapper(scope, value);
+ if (!wrapper)
+ return 0;
+ return wrapper->object();
+}
+
+
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h
index a4a40c2f41..8b813ea598 100644
--- a/src/qml/jsruntime/qv4engine_p.h
+++ b/src/qml/jsruntime/qv4engine_p.h
@@ -35,8 +35,8 @@
#include "qv4global_p.h"
#include "private/qv4isel_p.h"
-#include "qv4util_p.h"
-#include "qv4property_p.h"
+#include "qv4managed_p.h"
+#include "qv4context_p.h"
#include <private/qintrusivelist_p.h>
namespace WTF {
@@ -48,6 +48,8 @@ QT_BEGIN_NAMESPACE
class QV8Engine;
class QQmlError;
+class QJSEngine;
+class QQmlEngine;
namespace QV4 {
namespace Debugging {
@@ -59,61 +61,11 @@ class Profiler;
namespace CompiledData {
struct CompilationUnit;
}
-}
-
-namespace QV4 {
-
-struct Function;
-struct Object;
-struct BooleanObject;
-struct NumberObject;
-struct StringObject;
-struct ArrayObject;
-struct DateObject;
-struct FunctionObject;
-struct BoundFunction;
-struct RegExpObject;
-struct ErrorObject;
-struct SyntaxErrorObject;
-struct ArgumentsObject;
-struct ExecutionContext;
-struct ExecutionEngine;
-struct Members;
-class MemoryManager;
-class ExecutableAllocator;
-
-struct ObjectPrototype;
-struct StringPrototype;
-struct NumberPrototype;
-struct BooleanPrototype;
-struct ArrayPrototype;
-struct FunctionPrototype;
-struct DatePrototype;
-struct RegExpPrototype;
-struct ErrorPrototype;
-struct EvalErrorPrototype;
-struct RangeErrorPrototype;
-struct ReferenceErrorPrototype;
-struct SyntaxErrorPrototype;
-struct TypeErrorPrototype;
-struct URIErrorPrototype;
-struct VariantPrototype;
-struct SequencePrototype;
-struct EvalFunction;
-struct IdentifierTable;
-struct InternalClass;
-struct InternalClassPool;
-class MultiplyWrappedQObjectMap;
-struct RegExp;
-class RegExpCache;
-struct QmlExtensions;
-struct Exception;
-struct ExecutionContextSaver;
#define CHECK_STACK_LIMITS(v4) \
if ((v4->jsStackTop <= v4->jsStackLimit) && (reinterpret_cast<quintptr>(&v4) >= v4->cStackLimit || v4->recheckCStackLimits())) {} \
else \
- return v4->currentContext()->throwRangeError(QStringLiteral("Maximum call stack size exceeded."))
+ return v4->throwRangeError(QStringLiteral("Maximum call stack size exceeded."))
struct Q_QML_EXPORT ExecutionEngine
@@ -121,13 +73,15 @@ struct Q_QML_EXPORT ExecutionEngine
private:
friend struct ExecutionContextSaver;
friend struct ExecutionContext;
- ExecutionContext *current;
+ friend struct Heap::ExecutionContext;
public:
- ExecutionContext *currentContext() const { return current; }
+ Heap::ExecutionContext *current;
+ Heap::ExecutionContext *currentContext() const { return current; }
Value *jsStackTop;
quint32 hasException;
- GlobalContext *rootContext;
+ Heap::GlobalContext *m_rootContext;
+ Heap::GlobalContext *rootContext() const { return m_rootContext; }
MemoryManager *memoryManager;
ExecutableAllocator *executableAllocator;
@@ -144,22 +98,13 @@ public:
WTF::PageAllocation *jsStack;
Value *jsStackBase;
- Value *stackPush(uint nValues) {
- Value *ptr = jsStackTop;
- jsStackTop = ptr + nValues;
- return ptr;
- }
- void stackPop(uint nValues) {
- jsStackTop -= nValues;
- }
-
- void pushForGC(Managed *m) {
- *jsStackTop = Value::fromManaged(m);
+ void pushForGC(Heap::Base *m) {
+ *jsStackTop = m;
++jsStackTop;
}
- Managed *popForGC() {
+ Heap::Base *popForGC() {
--jsStackTop;
- return jsStackTop->managed();
+ return jsStackTop->heapObject();
}
IdentifierTable *identifierTable;
@@ -167,10 +112,13 @@ public:
QV4::Debugging::Debugger *debugger;
QV4::Profiling::Profiler *profiler;
- Object *globalObject;
+ Value m_globalObject;
+ Object *globalObject() { return reinterpret_cast<Object *>(&m_globalObject); }
Function *globalCode;
+ QJSEngine *jsEngine() const;
+ QQmlEngine *qmlEngine() const;
QV8Engine *v8Engine;
Value objectCtor;
@@ -188,12 +136,36 @@ public:
Value syntaxErrorCtor;
Value typeErrorCtor;
Value uRIErrorCtor;
+ Value arrayBufferCtor;
+ Value dataViewCtor;
+ enum { NTypedArrayTypes = 9 }; // avoid header dependency
+ Value typedArrayCtors[NTypedArrayTypes];
+
+ Value objectPrototype;
+ Value arrayPrototype;
+ Value stringPrototype;
+ Value numberPrototype;
+ Value booleanPrototype;
+ Value datePrototype;
+ Value functionPrototype;
+ Value regExpPrototype;
+ Value errorPrototype;
+ Value evalErrorPrototype;
+ Value rangeErrorPrototype;
+ Value referenceErrorPrototype;
+ Value syntaxErrorPrototype;
+ Value typeErrorPrototype;
+ Value uRIErrorPrototype;
+ Value variantPrototype;
Value sequencePrototype;
+ Value arrayBufferPrototype;
+ Value dataViewPrototype;
+ Value typedArrayPrototype[NTypedArrayTypes]; // TypedArray::NValues, avoid including the header here
+
InternalClassPool *classPool;
InternalClass *emptyClass;
InternalClass *executionContextClass;
- InternalClass *constructClass;
InternalClass *stringClass;
InternalClass *objectClass;
@@ -224,8 +196,12 @@ public:
InternalClass *variantClass;
InternalClass *memberDataClass;
- EvalFunction *evalFunction;
- FunctionObject *thrower;
+ InternalClass *arrayBufferClass;
+ InternalClass *dataViewClass;
+ InternalClass *typedArrayClasses[NTypedArrayTypes]; // TypedArray::NValues, avoid including the header here
+
+ Heap::EvalFunction *evalFunction;
+ Heap::FunctionObject *thrower;
Property *argumentsAccessors;
int nArgumentsAccessors;
@@ -262,6 +238,10 @@ public:
StringValue id_toString;
StringValue id_destroy;
StringValue id_valueOf;
+ StringValue id_byteLength;
+ StringValue id_byteOffset;
+ StringValue id_buffer;
+ StringValue id_lastIndex;
QSet<CompiledData::CompilationUnit*> compilationUnits;
@@ -294,45 +274,45 @@ public:
void enableDebugger();
void enableProfiler();
- ExecutionContext *pushGlobalContext();
+ Heap::ExecutionContext *pushGlobalContext();
void pushContext(CallContext *context);
- ExecutionContext *popContext();
+ Heap::ExecutionContext *popContext();
- Returned<Object> *newObject();
- Returned<Object> *newObject(InternalClass *internalClass);
+ Heap::Object *newObject();
+ Heap::Object *newObject(InternalClass *internalClass, Object *prototype);
- Returned<String> *newString(const QString &s);
- String *newIdentifier(const QString &text);
+ Heap::String *newString(const QString &s = QString());
+ Heap::String *newIdentifier(const QString &text);
- Returned<Object> *newStringObject(const ValueRef value);
- Returned<Object> *newNumberObject(const ValueRef value);
- Returned<Object> *newBooleanObject(const ValueRef value);
+ Heap::Object *newStringObject(const ValueRef value);
+ Heap::Object *newNumberObject(const ValueRef value);
+ Heap::Object *newBooleanObject(const ValueRef value);
- Returned<ArrayObject> *newArrayObject(int count = 0);
- Returned<ArrayObject> *newArrayObject(const QStringList &list);
- Returned<ArrayObject> *newArrayObject(InternalClass *ic);
+ Heap::ArrayObject *newArrayObject(int count = 0);
+ Heap::ArrayObject *newArrayObject(const QStringList &list);
+ Heap::ArrayObject *newArrayObject(InternalClass *ic, Object *prototype);
- Returned<DateObject> *newDateObject(const ValueRef value);
- Returned<DateObject> *newDateObject(const QDateTime &dt);
+ Heap::DateObject *newDateObject(const ValueRef value);
+ Heap::DateObject *newDateObject(const QDateTime &dt);
- Returned<RegExpObject> *newRegExpObject(const QString &pattern, int flags);
- Returned<RegExpObject> *newRegExpObject(RegExp *re, bool global);
- Returned<RegExpObject> *newRegExpObject(const QRegExp &re);
+ Heap::RegExpObject *newRegExpObject(const QString &pattern, int flags);
+ Heap::RegExpObject *newRegExpObject(RegExp *re, bool global);
+ Heap::RegExpObject *newRegExpObject(const QRegExp &re);
- Returned<Object> *newErrorObject(const ValueRef value);
- Returned<Object> *newSyntaxErrorObject(const QString &message, const QString &fileName, int line, int column);
- Returned<Object> *newSyntaxErrorObject(const QString &message);
- Returned<Object> *newReferenceErrorObject(const QString &message);
- Returned<Object> *newReferenceErrorObject(const QString &message, const QString &fileName, int lineNumber, int columnNumber);
- Returned<Object> *newTypeErrorObject(const QString &message);
- Returned<Object> *newRangeErrorObject(const QString &message);
- Returned<Object> *newURIErrorObject(const ValueRef message);
+ Heap::Object *newErrorObject(const ValueRef value);
+ Heap::Object *newSyntaxErrorObject(const QString &message, const QString &fileName, int line, int column);
+ Heap::Object *newSyntaxErrorObject(const QString &message);
+ Heap::Object *newReferenceErrorObject(const QString &message);
+ Heap::Object *newReferenceErrorObject(const QString &message, const QString &fileName, int lineNumber, int columnNumber);
+ Heap::Object *newTypeErrorObject(const QString &message);
+ Heap::Object *newRangeErrorObject(const QString &message);
+ Heap::Object *newURIErrorObject(const ValueRef message);
- Returned<Object> *newVariantObject(const QVariant &v);
+ Heap::Object *newVariantObject(const QVariant &v);
- Returned<Object> *newForEachIteratorObject(ExecutionContext *ctx, Object *o);
+ Heap::Object *newForEachIteratorObject(Object *o);
- Returned<Object> *qmlContextObject() const;
+ Heap::Object *qmlContextObject() const;
StackTrace stackTrace(int frameLimit = -1) const;
StackFrame currentStackFrame() const;
@@ -354,23 +334,87 @@ public:
Value exceptionValue;
StackTrace exceptionStackTrace;
- ReturnedValue throwException(const ValueRef value);
- ReturnedValue catchException(ExecutionContext *catchingContext, StackTrace *trace);
+ ReturnedValue throwError(const ValueRef value);
+ ReturnedValue catchException(StackTrace *trace = 0);
+
+ ReturnedValue throwError(const QString &message);
+ ReturnedValue throwSyntaxError(const QString &message);
+ ReturnedValue throwSyntaxError(const QString &message, const QString &fileName, int lineNumber, int column);
+ ReturnedValue throwTypeError();
+ ReturnedValue throwTypeError(const QString &message);
+ ReturnedValue throwReferenceError(const ValueRef value);
+ ReturnedValue throwReferenceError(const QString &value, const QString &fileName, int lineNumber, int column);
+ ReturnedValue throwRangeError(const ValueRef value);
+ ReturnedValue throwRangeError(const QString &message);
+ ReturnedValue throwURIError(const ValueRef msg);
+ ReturnedValue throwUnimplemented(const QString &message);
// Use only inside catch(...) -- will re-throw if no JS exception
- static QQmlError catchExceptionAsQmlError(QV4::ExecutionContext *context);
+ QQmlError catchExceptionAsQmlError();
+
+ // variant conversions
+ QVariant toVariant(const QV4::ValueRef value, int typeHint, bool createJSValueForObjects = true);
+ QV4::ReturnedValue fromVariant(const QVariant &);
+
+ QVariantMap variantMapFromJS(QV4::Object *o);
+
+ bool metaTypeFromJS(const QV4::ValueRef value, int type, void *data);
+ QV4::ReturnedValue metaTypeToJS(int type, const void *data);
private:
QmlExtensions *m_qmlExtensions;
};
+inline void ExecutionEngine::pushContext(CallContext *context)
+{
+ Q_ASSERT(current && context && context->d());
+ context->d()->parent = current;
+ current = context->d();
+}
+
+inline Heap::ExecutionContext *ExecutionEngine::popContext()
+{
+ Q_ASSERT(current->parent);
+ current = current->parent;
+ Q_ASSERT(current);
+ return current;
+}
+
+inline
+Heap::ExecutionContext::ExecutionContext(ExecutionEngine *engine, ContextType t)
+ : Heap::Base(engine->executionContextClass)
+ , type(t)
+ , strictMode(false)
+ , engine(engine)
+ , parent(engine->currentContext())
+ , outer(0)
+ , lookups(0)
+ , compilationUnit(0)
+ , lineNumber(-1)
+{
+ engine->current = this;
+}
+
+
+// ### Remove me
inline
void Managed::mark(QV4::ExecutionEngine *engine)
{
Q_ASSERT(inUse());
if (markBit())
return;
- d()->markBit = 1;
+ d()->setMarkBit();
+ engine->pushForGC(d());
+}
+
+
+inline
+void Heap::Base::mark(QV4::ExecutionEngine *engine)
+{
+ Q_ASSERT(inUse());
+ if (isMarked())
+ return;
+ setMarkBit();
engine->pushForGC(this);
}
diff --git a/src/qml/jsruntime/qv4errorobject.cpp b/src/qml/jsruntime/qv4errorobject.cpp
index d87083275d..eda371433a 100644
--- a/src/qml/jsruntime/qv4errorobject.cpp
+++ b/src/qml/jsruntime/qv4errorobject.cpp
@@ -63,25 +63,25 @@
using namespace QV4;
-ErrorObject::Data::Data(InternalClass *ic)
- : Object::Data(ic)
+Heap::ErrorObject::ErrorObject(InternalClass *ic, QV4::Object *prototype)
+ : Heap::Object(ic, prototype)
{
Scope scope(ic->engine);
- Scoped<ErrorObject> e(scope, this);
+ Scoped<QV4::ErrorObject> e(scope, this);
ScopedString s(scope, scope.engine->newString(QStringLiteral("Error")));
e->defineDefaultProperty(QStringLiteral("name"), s);
}
-ErrorObject::Data::Data(InternalClass *ic, const ValueRef message, ErrorType t)
- : Object::Data(ic)
+Heap::ErrorObject::ErrorObject(InternalClass *ic, QV4::Object *prototype, const ValueRef message, ErrorType t)
+ : Heap::Object(ic, prototype)
{
- subtype = t;
+ errorType = t;
Scope scope(ic->engine);
- Scoped<ErrorObject> e(scope, this);
+ Scoped<QV4::ErrorObject> e(scope, this);
- e->defineAccessorProperty(QStringLiteral("stack"), ErrorObject::method_get_stack, 0);
+ e->defineAccessorProperty(QStringLiteral("stack"), QV4::ErrorObject::method_get_stack, 0);
if (!message->isUndefined())
e->defineDefaultProperty(QStringLiteral("message"), message);
@@ -95,16 +95,16 @@ ErrorObject::Data::Data(InternalClass *ic, const ValueRef message, ErrorType t)
}
}
-ErrorObject::Data::Data(InternalClass *ic, const QString &message, ErrorObject::ErrorType t)
- : Object::Data(ic)
+Heap::ErrorObject::ErrorObject(InternalClass *ic, QV4::Object *prototype, const QString &message, ErrorObject::ErrorType t)
+ : Heap::Object(ic, prototype)
{
- subtype = t;
+ errorType = t;
Scope scope(ic->engine);
- Scoped<ErrorObject> e(scope, this);
+ Scoped<QV4::ErrorObject> e(scope, this);
ScopedString s(scope);
- e->defineAccessorProperty(QStringLiteral("stack"), ErrorObject::method_get_stack, 0);
+ e->defineAccessorProperty(QStringLiteral("stack"), QV4::ErrorObject::method_get_stack, 0);
ScopedValue v(scope, scope.engine->newString(message));
e->defineDefaultProperty(QStringLiteral("message"), v);
@@ -117,16 +117,16 @@ ErrorObject::Data::Data(InternalClass *ic, const QString &message, ErrorObject::
}
}
-ErrorObject::Data::Data(InternalClass *ic, const QString &message, const QString &fileName, int line, int column, ErrorObject::ErrorType t)
- : Object::Data(ic)
+Heap::ErrorObject::ErrorObject(InternalClass *ic, QV4::Object *prototype, const QString &message, const QString &fileName, int line, int column, ErrorObject::ErrorType t)
+ : Heap::Object(ic, prototype)
{
- subtype = t;
+ errorType = t;
Scope scope(ic->engine);
- Scoped<ErrorObject> e(scope, this);
+ Scoped<QV4::ErrorObject> e(scope, this);
ScopedString s(scope);
- e->defineAccessorProperty(QStringLiteral("stack"), ErrorObject::method_get_stack, 0);
+ e->defineAccessorProperty(QStringLiteral("stack"), QV4::ErrorObject::method_get_stack, 0);
e->defineDefaultProperty(QStringLiteral("name"), (s = scope.engine->newString(e->className())));
e->d()->stackTrace = scope.engine->stackTrace();
@@ -150,7 +150,7 @@ ReturnedValue ErrorObject::method_get_stack(CallContext *ctx)
Scope scope(ctx);
Scoped<ErrorObject> This(scope, ctx->d()->callData->thisObject);
if (!This)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
if (!This->d()->stack) {
QString trace;
for (int i = 0; i < This->d()->stackTrace.count(); ++i) {
@@ -165,16 +165,16 @@ ReturnedValue ErrorObject::method_get_stack(CallContext *ctx)
trace += QString::number(frame.line);
}
}
- This->d()->stack = ctx->d()->engine->newString(trace)->getPointer();
+ This->d()->stack = ctx->d()->engine->newString(trace);
}
return This->d()->stack->asReturnedValue();
}
-void ErrorObject::markObjects(Managed *that, ExecutionEngine *e)
+void ErrorObject::markObjects(Heap::Base *that, ExecutionEngine *e)
{
- ErrorObject *This = that->asErrorObject();
- if (This->d()->stack)
- This->d()->stack->mark(e);
+ ErrorObject::Data *This = static_cast<ErrorObject::Data *>(that);
+ if (This->stack)
+ This->stack->mark(e);
Object::markObjects(that, e);
}
@@ -182,58 +182,58 @@ DEFINE_OBJECT_VTABLE(ErrorObject);
DEFINE_OBJECT_VTABLE(SyntaxErrorObject);
-SyntaxErrorObject::Data::Data(ExecutionEngine *engine, const ValueRef msg)
- : ErrorObject::Data(engine->syntaxErrorClass, msg, SyntaxError)
+Heap::SyntaxErrorObject::SyntaxErrorObject(ExecutionEngine *engine, const ValueRef msg)
+ : Heap::ErrorObject(engine->syntaxErrorClass, engine->syntaxErrorPrototype.asObject(), msg, SyntaxError)
{
}
-SyntaxErrorObject::Data::Data(ExecutionEngine *engine, const QString &msg, const QString &fileName, int lineNumber, int columnNumber)
- : ErrorObject::Data(engine->syntaxErrorClass, msg, fileName, lineNumber, columnNumber, SyntaxError)
+Heap::SyntaxErrorObject::SyntaxErrorObject(ExecutionEngine *engine, const QString &msg, const QString &fileName, int lineNumber, int columnNumber)
+ : Heap::ErrorObject(engine->syntaxErrorClass, engine->syntaxErrorPrototype.asObject(), msg, fileName, lineNumber, columnNumber, SyntaxError)
{
}
-EvalErrorObject::Data::Data(ExecutionEngine *engine, const ValueRef message)
- : ErrorObject::Data(engine->evalErrorClass, message, EvalError)
+Heap::EvalErrorObject::EvalErrorObject(ExecutionEngine *engine, const ValueRef message)
+ : Heap::ErrorObject(engine->evalErrorClass, engine->evalErrorPrototype.asObject(), message, EvalError)
{
}
-RangeErrorObject::Data::Data(ExecutionEngine *engine, const ValueRef message)
- : ErrorObject::Data(engine->rangeErrorClass, message, RangeError)
+Heap::RangeErrorObject::RangeErrorObject(ExecutionEngine *engine, const ValueRef message)
+ : Heap::ErrorObject(engine->rangeErrorClass, engine->rangeErrorPrototype.asObject(), message, RangeError)
{
}
-RangeErrorObject::Data::Data(ExecutionEngine *engine, const QString &message)
- : ErrorObject::Data(engine->rangeErrorClass, message, RangeError)
+Heap::RangeErrorObject::RangeErrorObject(ExecutionEngine *engine, const QString &message)
+ : Heap::ErrorObject(engine->rangeErrorClass, engine->rangeErrorPrototype.asObject(), message, RangeError)
{
}
-ReferenceErrorObject::Data::Data(ExecutionEngine *engine, const ValueRef message)
- : ErrorObject::Data(engine->referenceErrorClass, message, ReferenceError)
+Heap::ReferenceErrorObject::ReferenceErrorObject(ExecutionEngine *engine, const ValueRef message)
+ : Heap::ErrorObject(engine->referenceErrorClass, engine->referenceErrorPrototype.asObject(), message, ReferenceError)
{
}
-ReferenceErrorObject::Data::Data(ExecutionEngine *engine, const QString &message)
- : ErrorObject::Data(engine->referenceErrorClass, message, ReferenceError)
+Heap::ReferenceErrorObject::ReferenceErrorObject(ExecutionEngine *engine, const QString &message)
+ : Heap::ErrorObject(engine->referenceErrorClass, engine->referenceErrorPrototype.asObject(), message, ReferenceError)
{
}
-ReferenceErrorObject::Data::Data(ExecutionEngine *engine, const QString &msg, const QString &fileName, int lineNumber, int columnNumber)
- : ErrorObject::Data(engine->referenceErrorClass, msg, fileName, lineNumber, columnNumber, ReferenceError)
+Heap::ReferenceErrorObject::ReferenceErrorObject(ExecutionEngine *engine, const QString &msg, const QString &fileName, int lineNumber, int columnNumber)
+ : Heap::ErrorObject(engine->referenceErrorClass, engine->referenceErrorPrototype.asObject(), msg, fileName, lineNumber, columnNumber, ReferenceError)
{
}
-TypeErrorObject::Data::Data(ExecutionEngine *engine, const ValueRef message)
- : ErrorObject::Data(engine->typeErrorClass, message, TypeError)
+Heap::TypeErrorObject::TypeErrorObject(ExecutionEngine *engine, const ValueRef message)
+ : Heap::ErrorObject(engine->typeErrorClass, engine->typeErrorPrototype.asObject(), message, TypeError)
{
}
-TypeErrorObject::Data::Data(ExecutionEngine *engine, const QString &message)
- : ErrorObject::Data(engine->typeErrorClass, message, TypeError)
+Heap::TypeErrorObject::TypeErrorObject(ExecutionEngine *engine, const QString &message)
+ : Heap::ErrorObject(engine->typeErrorClass, engine->typeErrorPrototype.asObject(), message, TypeError)
{
}
-URIErrorObject::Data::Data(ExecutionEngine *engine, const ValueRef message)
- : ErrorObject::Data(engine->uriErrorClass, message, URIError)
+Heap::URIErrorObject::URIErrorObject(ExecutionEngine *engine, const ValueRef message)
+ : Heap::ErrorObject(engine->uriErrorClass, engine->uRIErrorPrototype.asObject(), message, URIError)
{
}
@@ -245,16 +245,16 @@ DEFINE_OBJECT_VTABLE(SyntaxErrorCtor);
DEFINE_OBJECT_VTABLE(TypeErrorCtor);
DEFINE_OBJECT_VTABLE(URIErrorCtor);
-ErrorCtor::Data::Data(ExecutionContext *scope)
- : FunctionObject::Data(scope, QStringLiteral("Error"))
+Heap::ErrorCtor::ErrorCtor(QV4::ExecutionContext *scope)
+ : Heap::FunctionObject(scope, QStringLiteral("Error"))
{
- setVTable(staticVTable());
+ setVTable(QV4::ErrorCtor::staticVTable());
}
-ErrorCtor::Data::Data(ExecutionContext *scope, const QString &name)
- : FunctionObject::Data(scope, name)
+Heap::ErrorCtor::ErrorCtor(QV4::ExecutionContext *scope, const QString &name)
+ : Heap::FunctionObject(scope, name)
{
- setVTable(staticVTable());
+ setVTable(QV4::ErrorCtor::staticVTable());
}
ReturnedValue ErrorCtor::construct(Managed *m, CallData *callData)
@@ -269,10 +269,10 @@ ReturnedValue ErrorCtor::call(Managed *that, CallData *callData)
return static_cast<Object *>(that)->construct(callData);
}
-EvalErrorCtor::Data::Data(ExecutionContext *scope)
- : ErrorCtor::Data(scope, QStringLiteral("EvalError"))
+Heap::EvalErrorCtor::EvalErrorCtor(QV4::ExecutionContext *scope)
+ : Heap::ErrorCtor(scope, QStringLiteral("EvalError"))
{
- setVTable(staticVTable());
+ setVTable(QV4::EvalErrorCtor::staticVTable());
}
ReturnedValue EvalErrorCtor::construct(Managed *m, CallData *callData)
@@ -282,10 +282,10 @@ ReturnedValue EvalErrorCtor::construct(Managed *m, CallData *callData)
return (m->engine()->memoryManager->alloc<EvalErrorObject>(m->engine(), v))->asReturnedValue();
}
-RangeErrorCtor::Data::Data(ExecutionContext *scope)
- : ErrorCtor::Data(scope, QStringLiteral("RangeError"))
+Heap::RangeErrorCtor::RangeErrorCtor(QV4::ExecutionContext *scope)
+ : Heap::ErrorCtor(scope, QStringLiteral("RangeError"))
{
- setVTable(staticVTable());
+ setVTable(QV4::RangeErrorCtor::staticVTable());
}
ReturnedValue RangeErrorCtor::construct(Managed *m, CallData *callData)
@@ -295,10 +295,10 @@ ReturnedValue RangeErrorCtor::construct(Managed *m, CallData *callData)
return (m->engine()->memoryManager->alloc<RangeErrorObject>(scope.engine, v))->asReturnedValue();
}
-ReferenceErrorCtor::Data::Data(ExecutionContext *scope)
- : ErrorCtor::Data(scope, QStringLiteral("ReferenceError"))
+Heap::ReferenceErrorCtor::ReferenceErrorCtor(QV4::ExecutionContext *scope)
+ : Heap::ErrorCtor(scope, QStringLiteral("ReferenceError"))
{
- setVTable(staticVTable());
+ setVTable(QV4::ReferenceErrorCtor::staticVTable());
}
ReturnedValue ReferenceErrorCtor::construct(Managed *m, CallData *callData)
@@ -308,10 +308,10 @@ ReturnedValue ReferenceErrorCtor::construct(Managed *m, CallData *callData)
return (m->engine()->memoryManager->alloc<ReferenceErrorObject>(scope.engine, v))->asReturnedValue();
}
-SyntaxErrorCtor::Data::Data(ExecutionContext *scope)
- : ErrorCtor::Data(scope, QStringLiteral("SyntaxError"))
+Heap::SyntaxErrorCtor::SyntaxErrorCtor(QV4::ExecutionContext *scope)
+ : Heap::ErrorCtor(scope, QStringLiteral("SyntaxError"))
{
- setVTable(staticVTable());
+ setVTable(QV4::SyntaxErrorCtor::staticVTable());
}
ReturnedValue SyntaxErrorCtor::construct(Managed *m, CallData *callData)
@@ -321,10 +321,10 @@ ReturnedValue SyntaxErrorCtor::construct(Managed *m, CallData *callData)
return (m->engine()->memoryManager->alloc<SyntaxErrorObject>(scope.engine, v))->asReturnedValue();
}
-TypeErrorCtor::Data::Data(ExecutionContext *scope)
- : ErrorCtor::Data(scope, QStringLiteral("TypeError"))
+Heap::TypeErrorCtor::TypeErrorCtor(QV4::ExecutionContext *scope)
+ : Heap::ErrorCtor(scope, QStringLiteral("TypeError"))
{
- setVTable(staticVTable());
+ setVTable(QV4::TypeErrorCtor::staticVTable());
}
ReturnedValue TypeErrorCtor::construct(Managed *m, CallData *callData)
@@ -334,10 +334,10 @@ ReturnedValue TypeErrorCtor::construct(Managed *m, CallData *callData)
return (m->engine()->memoryManager->alloc<TypeErrorObject>(scope.engine, v))->asReturnedValue();
}
-URIErrorCtor::Data::Data(ExecutionContext *scope)
- : ErrorCtor::Data(scope, QStringLiteral("URIError"))
+Heap::URIErrorCtor::URIErrorCtor(QV4::ExecutionContext *scope)
+ : Heap::ErrorCtor(scope, QStringLiteral("URIError"))
{
- setVTable(staticVTable());
+ setVTable(QV4::URIErrorCtor::staticVTable());
}
ReturnedValue URIErrorCtor::construct(Managed *m, CallData *callData)
@@ -356,7 +356,7 @@ void ErrorPrototype::init(ExecutionEngine *engine, Object *ctor, Object *obj)
ctor->defineReadonlyProperty(engine->id_length, Primitive::fromInt32(1));
obj->defineDefaultProperty(QStringLiteral("constructor"), (o = ctor));
obj->defineDefaultProperty(engine->id_toString, method_toString, 0);
- obj->defineDefaultProperty(QStringLiteral("message"), (s = engine->newString(QString())));
+ obj->defineDefaultProperty(QStringLiteral("message"), (s = engine->newString()));
}
ReturnedValue ErrorPrototype::method_toString(CallContext *ctx)
@@ -365,7 +365,7 @@ ReturnedValue ErrorPrototype::method_toString(CallContext *ctx)
Object *o = ctx->d()->callData->thisObject.asObject();
if (!o)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
ScopedValue name(scope, o->get(ctx->d()->engine->id_name));
QString qname;
@@ -375,7 +375,7 @@ ReturnedValue ErrorPrototype::method_toString(CallContext *ctx)
qname = name->toQString();
ScopedString s(scope, ctx->d()->engine->newString(QString::fromLatin1("message")));
- ScopedValue message(scope, o->get(s.getPointer()));
+ ScopedValue message(scope, o->get(s));
QString qmessage;
if (!message->isUndefined())
qmessage = message->toQString();
diff --git a/src/qml/jsruntime/qv4errorobject_p.h b/src/qml/jsruntime/qv4errorobject_p.h
index 47442ad985..54762d8172 100644
--- a/src/qml/jsruntime/qv4errorobject_p.h
+++ b/src/qml/jsruntime/qv4errorobject_p.h
@@ -42,11 +42,9 @@ namespace QV4 {
struct SyntaxErrorObject;
-struct ErrorObject: Object {
- enum {
- IsErrorObject = true
- };
+namespace Heap {
+struct ErrorObject : Object {
enum ErrorType {
Error,
EvalError,
@@ -56,22 +54,90 @@ struct ErrorObject: Object {
TypeError,
URIError
};
- struct Data : Object::Data {
- Data(InternalClass *ic);
- Data(InternalClass *ic, const ValueRef message, ErrorType t = Error);
- Data(InternalClass *ic, const QString &message, ErrorType t = Error);
- Data(InternalClass *ic, const QString &message, const QString &fileName, int line, int column, ErrorType t = Error);
- StackTrace stackTrace;
- String *stack;
+
+ ErrorObject(InternalClass *ic, QV4::Object *prototype);
+ ErrorObject(InternalClass *ic, QV4::Object *prototype, const ValueRef message, ErrorType t = Error);
+ ErrorObject(InternalClass *ic, QV4::Object *prototype, const QString &message, ErrorType t = Error);
+ ErrorObject(InternalClass *ic, QV4::Object *prototype, const QString &message, const QString &fileName, int line, int column, ErrorType t = Error);
+
+ ErrorType errorType;
+ StackTrace stackTrace;
+ String *stack;
+};
+
+struct EvalErrorObject : ErrorObject {
+ EvalErrorObject(ExecutionEngine *engine, const ValueRef message);
+};
+
+struct RangeErrorObject : ErrorObject {
+ RangeErrorObject(ExecutionEngine *engine, const ValueRef message);
+ RangeErrorObject(ExecutionEngine *engine, const QString &msg);
+};
+
+struct ReferenceErrorObject : ErrorObject {
+ ReferenceErrorObject(ExecutionEngine *engine, const ValueRef message);
+ ReferenceErrorObject(ExecutionEngine *engine, const QString &msg);
+ ReferenceErrorObject(ExecutionEngine *engine, const QString &msg, const QString &fileName, int lineNumber, int columnNumber);
+};
+
+struct SyntaxErrorObject : ErrorObject {
+ SyntaxErrorObject(ExecutionEngine *engine, const ValueRef message);
+ SyntaxErrorObject(ExecutionEngine *engine, const QString &msg, const QString &fileName, int lineNumber, int columnNumber);
+};
+
+struct TypeErrorObject : ErrorObject {
+ TypeErrorObject(ExecutionEngine *engine, const ValueRef message);
+ TypeErrorObject(ExecutionEngine *engine, const QString &msg);
+};
+
+struct URIErrorObject : ErrorObject {
+ URIErrorObject(ExecutionEngine *engine, const ValueRef message);
+};
+
+struct ErrorCtor : Heap::FunctionObject {
+ ErrorCtor(QV4::ExecutionContext *scope);
+ ErrorCtor(QV4::ExecutionContext *scope, const QString &name);
+};
+
+struct EvalErrorCtor : ErrorCtor {
+ EvalErrorCtor(QV4::ExecutionContext *scope);
+};
+
+struct RangeErrorCtor : ErrorCtor {
+ RangeErrorCtor(QV4::ExecutionContext *scope);
+};
+
+struct ReferenceErrorCtor : ErrorCtor {
+ ReferenceErrorCtor(QV4::ExecutionContext *scope);
+};
+
+struct SyntaxErrorCtor : ErrorCtor {
+ SyntaxErrorCtor(QV4::ExecutionContext *scope);
+};
+
+struct TypeErrorCtor : ErrorCtor {
+ TypeErrorCtor(QV4::ExecutionContext *scope);
+};
+
+struct URIErrorCtor : ErrorCtor {
+ URIErrorCtor(QV4::ExecutionContext *scope);
+};
+
+}
+
+struct ErrorObject: Object {
+ enum {
+ IsErrorObject = true
};
- V4_OBJECT(Object)
+
+ V4_OBJECT2(ErrorObject, Object)
Q_MANAGED_TYPE(ErrorObject)
+ V4_NEEDS_DESTROY
SyntaxErrorObject *asSyntaxError();
static ReturnedValue method_get_stack(CallContext *ctx);
- static void markObjects(Managed *that, ExecutionEngine *e);
- static void destroy(Managed *that) { static_cast<ErrorObject *>(that)->d()->~Data(); }
+ static void markObjects(Heap::Base *that, ExecutionEngine *e);
};
template<>
@@ -80,55 +146,42 @@ inline ErrorObject *value_cast(const Value &v) {
}
struct EvalErrorObject: ErrorObject {
- struct Data : ErrorObject::Data {
- Data(ExecutionEngine *engine, const ValueRef message);
- };
+ typedef Heap::EvalErrorObject Data;
+ const Data *d() const { return static_cast<const Data *>(ErrorObject::d()); }
+ Data *d() { return static_cast<Data *>(ErrorObject::d()); }
};
struct RangeErrorObject: ErrorObject {
- struct Data : ErrorObject::Data {
- Data(ExecutionEngine *engine, const ValueRef message);
- Data(ExecutionEngine *engine, const QString &msg);
- };
+ typedef Heap::RangeErrorObject Data;
+ const Data *d() const { return static_cast<const Data *>(ErrorObject::d()); }
+ Data *d() { return static_cast<Data *>(ErrorObject::d()); }
};
struct ReferenceErrorObject: ErrorObject {
- struct Data : ErrorObject::Data {
- Data(ExecutionEngine *engine, const ValueRef message);
- Data(ExecutionEngine *engine, const QString &msg);
- Data(ExecutionEngine *engine, const QString &msg, const QString &fileName, int lineNumber, int columnNumber);
- };
+ typedef Heap::ReferenceErrorObject Data;
+ const Data *d() const { return static_cast<const Data *>(ErrorObject::d()); }
+ Data *d() { return static_cast<Data *>(ErrorObject::d()); }
};
struct SyntaxErrorObject: ErrorObject {
- struct Data : ErrorObject::Data {
- Data(ExecutionEngine *engine, const ValueRef message);
- Data(ExecutionEngine *engine, const QString &msg, const QString &fileName, int lineNumber, int columnNumber);
- };
- V4_OBJECT(ErrorObject)
+ V4_OBJECT2(SyntaxErrorObject, ErrorObject)
};
struct TypeErrorObject: ErrorObject {
- struct Data : ErrorObject::Data {
- Data(ExecutionEngine *engine, const ValueRef message);
- Data(ExecutionEngine *engine, const QString &msg);
- };
+ typedef Heap::TypeErrorObject Data;
+ const Data *d() const { return static_cast<const Data *>(ErrorObject::d()); }
+ Data *d() { return static_cast<Data *>(ErrorObject::d()); }
};
struct URIErrorObject: ErrorObject {
- struct Data : ErrorObject::Data {
- Data(ExecutionEngine *engine, const ValueRef message);
- };
+ typedef Heap::URIErrorObject Data;
+ const Data *d() const { return static_cast<const Data *>(ErrorObject::d()); }
+ Data *d() { return static_cast<Data *>(ErrorObject::d()); }
};
struct ErrorCtor: FunctionObject
{
- struct Data : FunctionObject::Data {
- Data(ExecutionContext *scope);
- Data(ExecutionContext *scope, const QString &name);
- };
-
- V4_OBJECT(FunctionObject)
+ V4_OBJECT2(ErrorCtor, FunctionObject)
static ReturnedValue construct(Managed *, CallData *callData);
static ReturnedValue call(Managed *that, CallData *callData);
@@ -136,60 +189,42 @@ struct ErrorCtor: FunctionObject
struct EvalErrorCtor: ErrorCtor
{
- struct Data : ErrorCtor::Data {
- Data(ExecutionContext *scope);
- };
- V4_OBJECT(ErrorCtor)
+ V4_OBJECT2(EvalErrorCtor, ErrorCtor)
static ReturnedValue construct(Managed *m, CallData *callData);
};
struct RangeErrorCtor: ErrorCtor
{
- struct Data : ErrorCtor::Data {
- Data(ExecutionContext *scope);
- };
- V4_OBJECT(ErrorCtor)
+ V4_OBJECT2(RangeErrorCtor, ErrorCtor)
static ReturnedValue construct(Managed *m, CallData *callData);
};
struct ReferenceErrorCtor: ErrorCtor
{
- struct Data : ErrorCtor::Data {
- Data(ExecutionContext *scope);
- };
- V4_OBJECT(ErrorCtor)
+ V4_OBJECT2(ReferenceErrorCtor, ErrorCtor)
static ReturnedValue construct(Managed *m, CallData *callData);
};
struct SyntaxErrorCtor: ErrorCtor
{
- struct Data : ErrorCtor::Data {
- Data(ExecutionContext *scope);
- };
- V4_OBJECT(ErrorCtor)
+ V4_OBJECT2(SyntaxErrorCtor, ErrorCtor)
static ReturnedValue construct(Managed *m, CallData *callData);
};
struct TypeErrorCtor: ErrorCtor
{
- struct Data : ErrorCtor::Data {
- Data(ExecutionContext *scope);
- };
- V4_OBJECT(ErrorCtor)
+ V4_OBJECT2(TypeErrorCtor, ErrorCtor)
static ReturnedValue construct(Managed *m, CallData *callData);
};
struct URIErrorCtor: ErrorCtor
{
- struct Data : ErrorCtor::Data {
- Data(ExecutionContext *scope);
- };
- V4_OBJECT(ErrorCtor)
+ V4_OBJECT2(URIErrorCtor, ErrorCtor)
static ReturnedValue construct(Managed *m, CallData *callData);
};
@@ -236,7 +271,7 @@ struct URIErrorPrototype : ErrorObject
inline SyntaxErrorObject *ErrorObject::asSyntaxError()
{
- return subtype() == SyntaxError ? static_cast<SyntaxErrorObject *>(this) : 0;
+ return d()->errorType == QV4::Heap::ErrorObject::SyntaxError ? static_cast<SyntaxErrorObject *>(this) : 0;
}
}
diff --git a/src/qml/jsruntime/qv4function.cpp b/src/qml/jsruntime/qv4function.cpp
index c7fe2128ce..ef8b1eafd9 100644
--- a/src/qml/jsruntime/qv4function.cpp
+++ b/src/qml/jsruntime/qv4function.cpp
@@ -44,7 +44,7 @@ QT_BEGIN_NAMESPACE
using namespace QV4;
Function::Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit, const CompiledData::Function *function,
- ReturnedValue (*codePtr)(ExecutionContext *, const uchar *))
+ ReturnedValue (*codePtr)(ExecutionEngine *, const uchar *))
: compiledFunction(function)
, compilationUnit(unit)
, code(codePtr)
@@ -56,9 +56,9 @@ Function::Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit,
const quint32 *formalsIndices = compiledFunction->formalsTable();
// iterate backwards, so we get the right ordering for duplicate names
Scope scope(engine);
- ScopedString s(scope);
+ ScopedString arg(scope);
for (int i = static_cast<int>(compiledFunction->nFormals - 1); i >= 0; --i) {
- String *arg = compilationUnit->runtimeStrings[formalsIndices[i]].asString();
+ arg = compilationUnit->runtimeStrings[formalsIndices[i]];
while (1) {
InternalClass *newClass = internalClass->addMember(arg, Attr_NotConfigurable);
if (newClass != internalClass) {
@@ -66,15 +66,13 @@ Function::Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit,
break;
}
// duplicate arguments, need some trick to store them
- arg = (s = engine->memoryManager->alloc<String>(engine, arg, engine->newString(QString(0xfffe))->getPointer())).getPointer();
+ arg = engine->memoryManager->alloc<String>(engine, arg->d(), engine->newString(QString(0xfffe)));
}
}
const quint32 *localsIndices = compiledFunction->localsTable();
- for (quint32 i = 0; i < compiledFunction->nLocals; ++i) {
- String *local = compilationUnit->runtimeStrings[localsIndices[i]].asString();
- internalClass = internalClass->addMember(local, Attr_NotConfigurable);
- }
+ for (quint32 i = 0; i < compiledFunction->nLocals; ++i)
+ internalClass = internalClass->addMember(compilationUnit->runtimeStrings[localsIndices[i]]->identifier, Attr_NotConfigurable);
}
Function::~Function()
diff --git a/src/qml/jsruntime/qv4function_p.h b/src/qml/jsruntime/qv4function_p.h
index 465489b83f..47dfe9012e 100644
--- a/src/qml/jsruntime/qv4function_p.h
+++ b/src/qml/jsruntime/qv4function_p.h
@@ -34,60 +34,28 @@
#define QV4FUNCTION_H
#include "qv4global_p.h"
-
-#include <QtCore/QVector>
-#include <QtCore/QByteArray>
-#include <QtCore/qurl.h>
-
-#include "qv4value_p.h"
#include <private/qv4compileddata_p.h>
-#include <private/qv4engine_p.h>
QT_BEGIN_NAMESPACE
namespace QV4 {
-struct String;
-struct Function;
-struct Object;
-struct FunctionObject;
-struct ExecutionContext;
-struct ExecutionEngine;
-class MemoryManager;
-
-struct ObjectPrototype;
-struct StringPrototype;
-struct NumberPrototype;
-struct BooleanPrototype;
-struct ArrayPrototype;
-struct FunctionPrototype;
-struct DatePrototype;
-struct ErrorPrototype;
-struct EvalErrorPrototype;
-struct RangeErrorPrototype;
-struct ReferenceErrorPrototype;
-struct SyntaxErrorPrototype;
-struct TypeErrorPrototype;
-struct URIErrorPrototype;
-struct InternalClass;
-struct Lookup;
-
struct Q_QML_EXPORT Function {
const CompiledData::Function *compiledFunction;
CompiledData::CompilationUnit *compilationUnit;
- ReturnedValue (*code)(ExecutionContext *, const uchar *);
+ ReturnedValue (*code)(ExecutionEngine *, const uchar *);
const uchar *codeData;
// first nArguments names in internalClass are the actual arguments
InternalClass *internalClass;
Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit, const CompiledData::Function *function,
- ReturnedValue (*codePtr)(ExecutionContext *, const uchar *));
+ ReturnedValue (*codePtr)(ExecutionEngine *, const uchar *));
~Function();
- inline String *name() {
- return compilationUnit->runtimeStrings[compiledFunction->nameIndex].getPointer();
+ inline Heap::String *name() {
+ return compilationUnit->runtimeStrings[compiledFunction->nameIndex];
}
inline QString sourceFile() const { return compilationUnit->fileName(); }
diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp
index f3ad8ef892..e74acf78d4 100644
--- a/src/qml/jsruntime/qv4functionobject.cpp
+++ b/src/qml/jsruntime/qv4functionobject.cpp
@@ -48,15 +48,12 @@
#include <private/qqmljsast_p.h>
#include <private/qqmlcontextwrapper_p.h>
#include <private/qqmlengine_p.h>
-#include <qv4jsir_p.h>
#include <qv4codegen_p.h>
#include "private/qlocale_tools_p.h"
+#include "private/qqmlbuiltinfunctions_p.h"
#include <QtCore/qmath.h>
#include <QtCore/QDebug>
-#include <cassert>
-#include <typeinfo>
-#include <iostream>
#include <algorithm>
#include "qv4alloca_p.h"
#include "qv4profiling_p.h"
@@ -66,46 +63,77 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(FunctionObject);
-FunctionObject::Data::Data(ExecutionContext *scope, String *name, bool createProto)
- : Object::Data(scope->d()->engine->functionClass)
- , scope(scope)
+Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, QV4::String *name, bool createProto)
+ : Heap::Object(scope->d()->engine->functionClass, scope->d()->engine->functionPrototype.asObject())
+ , scope(scope->d())
{
- Scope s(scope);
+ Scope s(scope->engine());
ScopedFunctionObject f(s, this);
f->init(name, createProto);
}
+Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, Function *function, bool createProto)
+ : Heap::Object(scope->d()->engine->functionClass, scope->d()->engine->functionPrototype.asObject())
+ , scope(scope->d())
+{
+ Scope s(scope->engine());
+ ScopedString name(s, function->name());
+ ScopedFunctionObject f(s, this);
+ f->init(name, createProto);
+}
-FunctionObject::Data::Data(ExecutionContext *scope, const QString &name, bool createProto)
- : Object::Data(scope->d()->engine->functionClass)
- , scope(scope)
+Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, const QString &name, bool createProto)
+ : Heap::Object(scope->d()->engine->functionClass, scope->d()->engine->functionPrototype.asObject())
+ , scope(scope->d())
{
- Scope s(scope);
+ Scope s(scope->engine());
ScopedFunctionObject f(s, this);
ScopedString n(s, s.engine->newString(name));
- f->init(n.getPointer(), createProto);
+ f->init(n, createProto);
}
-FunctionObject::Data::Data(ExecutionContext *scope, const ReturnedValue name)
- : Object::Data(scope->d()->engine->functionClass)
+Heap::FunctionObject::FunctionObject(ExecutionContext *scope, const QString &name, bool createProto)
+ : Heap::Object(scope->engine->functionClass, scope->engine->functionPrototype.asObject())
, scope(scope)
{
+ Scope s(scope->engine);
+ ScopedFunctionObject f(s, this);
+ ScopedString n(s, s.engine->newString(name));
+ f->init(n, createProto);
+}
+
+Heap::FunctionObject::FunctionObject(QV4::ExecutionContext *scope, const ReturnedValue name)
+ : Heap::Object(scope->d()->engine->functionClass, scope->d()->engine->functionPrototype.asObject())
+ , scope(scope->d())
+{
Scope s(scope);
ScopedFunctionObject f(s, this);
ScopedString n(s, name);
- f->init(n.getPointer(), false);
+ f->init(n, false);
+}
+
+Heap::FunctionObject::FunctionObject(ExecutionContext *scope, const ReturnedValue name)
+ : Heap::Object(scope->engine->functionClass, scope->engine->functionPrototype.asObject())
+ , scope(scope)
+{
+ Scope s(scope->engine);
+ ScopedFunctionObject f(s, this);
+ ScopedString n(s, name);
+ f->init(n, false);
}
-FunctionObject::Data::Data(InternalClass *ic)
- : Object::Data(ic)
- , scope(ic->engine->rootContext)
+Heap::FunctionObject::FunctionObject(InternalClass *ic, QV4::Object *prototype)
+ : Heap::Object(ic, prototype)
+ , scope(ic->engine->rootContext())
{
- memberData.ensureIndex(ic->engine, Index_Prototype);
- memberData[Index_Prototype] = Encode::undefined();
+ Scope scope(ic->engine);
+ ScopedObject o(scope, this);
+ o->ensureMemberIndex(ic->engine, Index_Prototype);
+ memberData->data[Index_Prototype] = Encode::undefined();
}
-FunctionObject::Data::~Data()
+Heap::FunctionObject::~FunctionObject()
{
if (function)
function->compilationUnit->release();
@@ -116,16 +144,14 @@ void FunctionObject::init(String *n, bool createProto)
Scope s(internalClass()->engine);
ScopedValue protectThis(s, this);
- d()->needsActivation = true;
- d()->strictMode = false;
-
- memberData().ensureIndex(s.engine, Index_Prototype);
+ ensureMemberIndex(s.engine, Heap::FunctionObject::Index_Prototype);
if (createProto) {
- Scoped<Object> proto(s, scope()->d()->engine->newObject(scope()->d()->engine->protoClass));
- proto->memberData()[Index_ProtoConstructor] = this->asReturnedValue();
- memberData()[Index_Prototype] = proto.asReturnedValue();
+ ScopedObject proto(s, scope()->engine->newObject(s.engine->protoClass, s.engine->objectPrototype.asObject()));
+ proto->ensureMemberIndex(s.engine, Heap::FunctionObject::Index_ProtoConstructor);
+ proto->memberData()->data[Heap::FunctionObject::Index_ProtoConstructor] = this->asReturnedValue();
+ memberData()->data[Heap::FunctionObject::Index_Prototype] = proto.asReturnedValue();
} else {
- memberData()[Index_Prototype] = Encode::undefined();
+ memberData()->data[Heap::FunctionObject::Index_Prototype] = Encode::undefined();
}
ScopedValue v(s, n);
@@ -134,20 +160,20 @@ void FunctionObject::init(String *n, bool createProto)
ReturnedValue FunctionObject::name()
{
- return get(scope()->d()->engine->id_name);
+ return get(scope()->engine->id_name);
}
ReturnedValue FunctionObject::newInstance()
{
Scope scope(internalClass()->engine);
- ScopedCallData callData(scope, 0);
+ ScopedCallData callData(scope);
return construct(callData);
}
ReturnedValue FunctionObject::construct(Managed *that, CallData *)
{
- that->internalClass()->engine->currentContext()->throwTypeError();
+ that->internalClass()->engine->throwTypeError();
return Encode::undefined();
}
@@ -156,16 +182,16 @@ ReturnedValue FunctionObject::call(Managed *, CallData *)
return Encode::undefined();
}
-void FunctionObject::markObjects(Managed *that, ExecutionEngine *e)
+void FunctionObject::markObjects(Heap::Base *that, ExecutionEngine *e)
{
- FunctionObject *o = static_cast<FunctionObject *>(that);
- if (o->scope())
- o->scope()->mark(e);
+ Heap::FunctionObject *o = static_cast<Heap::FunctionObject *>(that);
+ if (o->scope)
+ o->scope->mark(e);
Object::markObjects(that, e);
}
-FunctionObject *FunctionObject::createScriptFunction(ExecutionContext *scope, Function *function, bool createProto)
+Heap::FunctionObject *FunctionObject::createScriptFunction(ExecutionContext *scope, Function *function, bool createProto)
{
if (function->needsActivation() ||
function->compiledFunction->flags & CompiledData::Function::HasCatchOrWith ||
@@ -175,29 +201,39 @@ FunctionObject *FunctionObject::createScriptFunction(ExecutionContext *scope, Fu
return scope->d()->engine->memoryManager->alloc<SimpleScriptFunction>(scope, function, createProto);
}
+bool FunctionObject::isBinding() const
+{
+ return d()->internalClass->vtable == QQmlBindingFunction::staticVTable();
+}
+
+bool FunctionObject::isBoundFunction() const
+{
+ return d()->internalClass->vtable == BoundFunction::staticVTable();
+}
+
DEFINE_OBJECT_VTABLE(FunctionCtor);
-FunctionCtor::Data::Data(ExecutionContext *scope)
- : FunctionObject::Data(scope, QStringLiteral("Function"))
+Heap::FunctionCtor::FunctionCtor(QV4::ExecutionContext *scope)
+ : Heap::FunctionObject(scope, QStringLiteral("Function"))
{
- setVTable(staticVTable());
+ setVTable(QV4::FunctionCtor::staticVTable());
}
// 15.3.2
ReturnedValue FunctionCtor::construct(Managed *that, CallData *callData)
{
- FunctionCtor *f = static_cast<FunctionCtor *>(that);
- ExecutionEngine *v4 = f->internalClass()->engine;
- ExecutionContext *ctx = v4->currentContext();
+ Scope scope(that->engine());
+ Scoped<FunctionCtor> f(scope, static_cast<FunctionCtor *>(that));
+ ScopedContext ctx(scope, scope.engine->currentContext());
QString arguments;
QString body;
if (callData->argc > 0) {
for (int i = 0; i < callData->argc - 1; ++i) {
if (i)
arguments += QLatin1String(", ");
- arguments += callData->args[i].toString(ctx)->toQString();
+ arguments += callData->args[i].toQString();
}
- body = callData->args[callData->argc - 1].toString(ctx)->toQString();
+ body = callData->args[callData->argc - 1].toQString();
}
if (ctx->d()->engine->hasException)
return Encode::undefined();
@@ -212,24 +248,25 @@ ReturnedValue FunctionCtor::construct(Managed *that, CallData *callData)
const bool parsed = parser.parseExpression();
if (!parsed)
- return v4->currentContext()->throwSyntaxError(QLatin1String("Parse error"));
+ return scope.engine->throwSyntaxError(QLatin1String("Parse error"));
using namespace QQmlJS::AST;
FunctionExpression *fe = QQmlJS::AST::cast<FunctionExpression *>(parser.rootNode());
if (!fe)
- return v4->currentContext()->throwSyntaxError(QLatin1String("Parse error"));
+ return scope.engine->throwSyntaxError(QLatin1String("Parse error"));
- IR::Module module(v4->debugger != 0);
+ IR::Module module(scope.engine->debugger != 0);
- QQmlJS::RuntimeCodegen cg(v4->currentContext(), f->strictMode());
+ QQmlJS::RuntimeCodegen cg(scope.engine, f->strictMode());
cg.generateFromFunctionExpression(QString(), function, fe, &module);
- QV4::Compiler::JSUnitGenerator jsGenerator(&module);
- QScopedPointer<EvalInstructionSelection> isel(v4->iselFactory->create(QQmlEnginePrivate::get(v4), v4->executableAllocator, &module, &jsGenerator));
- QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit = isel->compile();
- QV4::Function *vmf = compilationUnit->linkToEngine(v4);
+ Compiler::JSUnitGenerator jsGenerator(&module);
+ QScopedPointer<EvalInstructionSelection> isel(scope.engine->iselFactory->create(QQmlEnginePrivate::get(scope.engine), scope.engine->executableAllocator, &module, &jsGenerator));
+ QQmlRefPointer<CompiledData::CompilationUnit> compilationUnit = isel->compile();
+ Function *vmf = compilationUnit->linkToEngine(scope.engine);
- return FunctionObject::createScriptFunction(v4->rootContext, vmf)->asReturnedValue();
+ ScopedContext global(scope, scope.engine->rootContext());
+ return FunctionObject::createScriptFunction(global, vmf)->asReturnedValue();
}
// 15.3.1: This is equivalent to new Function(...)
@@ -240,8 +277,8 @@ ReturnedValue FunctionCtor::call(Managed *that, CallData *callData)
DEFINE_OBJECT_VTABLE(FunctionPrototype);
-FunctionPrototype::Data::Data(InternalClass *ic)
- : FunctionObject::Data(ic)
+Heap::FunctionPrototype::FunctionPrototype(InternalClass *ic, QV4::Object *prototype)
+ : Heap::FunctionObject(ic, prototype)
{
}
@@ -266,7 +303,7 @@ ReturnedValue FunctionPrototype::method_toString(CallContext *ctx)
{
FunctionObject *fun = ctx->d()->callData->thisObject.asFunctionObject();
if (!fun)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
return ctx->d()->engine->newString(QStringLiteral("function() { [code] }"))->asReturnedValue();
}
@@ -274,9 +311,9 @@ ReturnedValue FunctionPrototype::method_toString(CallContext *ctx)
ReturnedValue FunctionPrototype::method_apply(CallContext *ctx)
{
Scope scope(ctx);
- FunctionObject *o = ctx->d()->callData->thisObject.asFunctionObject();
+ ScopedFunctionObject o(scope, ctx->d()->callData->thisObject.asFunctionObject());
if (!o)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
ScopedValue arg(scope, ctx->argument(1));
@@ -286,7 +323,7 @@ ReturnedValue FunctionPrototype::method_apply(CallContext *ctx)
if (!arr) {
len = 0;
if (!arg->isNullOrUndefined())
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
} else {
len = arr->getLength();
}
@@ -294,15 +331,15 @@ ReturnedValue FunctionPrototype::method_apply(CallContext *ctx)
ScopedCallData callData(scope, len);
if (len) {
- if (arr->arrayType() != ArrayData::Simple || arr->protoHasArray() || arr->hasAccessorProperty()) {
+ if (arr->arrayType() != Heap::ArrayData::Simple || arr->protoHasArray()) {
for (quint32 i = 0; i < len; ++i)
callData->args[i] = arr->getIndexed(i);
} else {
- uint alen = arr->arrayData() ? arr->arrayData()->length() : 0;
+ uint alen = arr->arrayData() ? arr->arrayData()->len : 0;
if (alen > len)
alen = len;
for (uint i = 0; i < alen; ++i)
- callData->args[i] = static_cast<SimpleArrayData *>(arr->arrayData())->data(i);
+ callData->args[i] = static_cast<Heap::SimpleArrayData *>(arr->arrayData())->data(i);
for (quint32 i = alen; i < len; ++i)
callData->args[i] = Primitive::undefinedValue();
}
@@ -316,9 +353,9 @@ ReturnedValue FunctionPrototype::method_call(CallContext *ctx)
{
Scope scope(ctx);
- FunctionObject *o = ctx->d()->callData->thisObject.asFunctionObject();
+ ScopedFunctionObject o(scope, ctx->d()->callData->thisObject.asFunctionObject());
if (!o)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
ScopedCallData callData(scope, ctx->d()->callData->argc ? ctx->d()->callData->argc - 1 : 0);
if (ctx->d()->callData->argc) {
@@ -332,29 +369,28 @@ ReturnedValue FunctionPrototype::method_call(CallContext *ctx)
ReturnedValue FunctionPrototype::method_bind(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<FunctionObject> target(scope, ctx->d()->callData->thisObject);
+ ScopedFunctionObject target(scope, ctx->d()->callData->thisObject);
if (!target)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
ScopedValue boundThis(scope, ctx->argument(0));
- Members boundArgs;
- boundArgs.reset();
+ Scoped<MemberData> boundArgs(scope, (Heap::MemberData *)0);
if (ctx->d()->callData->argc > 1) {
- boundArgs.ensureIndex(scope.engine, ctx->d()->callData->argc - 1);
- boundArgs.d()->d()->size = ctx->d()->callData->argc - 1;
- memcpy(boundArgs.data(), ctx->d()->callData->args + 1, (ctx->d()->callData->argc - 1)*sizeof(Value));
+ boundArgs = MemberData::reallocate(scope.engine, 0, ctx->d()->callData->argc - 1);
+ boundArgs->d()->size = ctx->d()->callData->argc - 1;
+ memcpy(boundArgs->data(), ctx->d()->callData->args + 1, (ctx->d()->callData->argc - 1)*sizeof(Value));
}
- ScopedValue protectBoundArgs(scope, boundArgs.d());
- return BoundFunction::create(ctx->d()->engine->rootContext, target, boundThis, boundArgs)->asReturnedValue();
+ ScopedContext global(scope, scope.engine->rootContext());
+ return BoundFunction::create(global, target, boundThis, boundArgs)->asReturnedValue();
}
DEFINE_OBJECT_VTABLE(ScriptFunction);
-ScriptFunction::Data::Data(ExecutionContext *scope, Function *function)
- : SimpleScriptFunction::Data(scope, function, true)
+Heap::ScriptFunction::ScriptFunction(QV4::ExecutionContext *scope, Function *function)
+ : Heap::SimpleScriptFunction(scope, function, true)
{
- setVTable(staticVTable());
+ setVTable(QV4::ScriptFunction::staticVTable());
}
ReturnedValue ScriptFunction::construct(Managed *that, CallData *callData)
@@ -367,15 +403,16 @@ ReturnedValue ScriptFunction::construct(Managed *that, CallData *callData)
Scope scope(v4);
Scoped<ScriptFunction> f(scope, static_cast<ScriptFunction *>(that));
- InternalClass *ic = f->internalClassForConstructor();
- ScopedObject obj(scope, v4->newObject(ic));
+ InternalClass *ic = scope.engine->objectClass;
+ ScopedObject proto(scope, f->protoForConstructor());
+ ScopedObject obj(scope, v4->newObject(ic, proto));
- ExecutionContext *context = v4->currentContext();
+ ScopedContext context(scope, v4->currentContext());
callData->thisObject = obj.asReturnedValue();
- ExecutionContext *ctx = reinterpret_cast<ExecutionContext *>(context->newCallContext(f.getPointer(), callData));
+ Scoped<CallContext> ctx(scope, context->newCallContext(f, callData));
- ExecutionContextSaver ctxSaver(context);
- ScopedValue result(scope, Q_V4_PROFILE(v4, ctx, f->function()));
+ ExecutionContextSaver ctxSaver(scope, context);
+ ScopedValue result(scope, Q_V4_PROFILE(v4, f->function()));
if (f->function()->compiledFunction->hasQmlDependencies())
QmlContextWrapper::registerQmlDependencies(v4, f->function()->compiledFunction);
@@ -390,19 +427,19 @@ ReturnedValue ScriptFunction::construct(Managed *that, CallData *callData)
ReturnedValue ScriptFunction::call(Managed *that, CallData *callData)
{
- ScriptFunction *f = static_cast<ScriptFunction *>(that);
- ExecutionEngine *v4 = f->engine();
+ ExecutionEngine *v4 = that->engine();
if (v4->hasException)
return Encode::undefined();
CHECK_STACK_LIMITS(v4);
- ExecutionContext *context = v4->currentContext();
- Scope scope(context);
+ Scope scope(v4);
+ Scoped<ScriptFunction> f(scope, static_cast<ScriptFunction *>(that));
+ ScopedContext context(scope, v4->currentContext());
- CallContext *ctx = reinterpret_cast<CallContext *>(context->newCallContext(f, callData));
+ Scoped<CallContext> ctx(scope, context->newCallContext(f, callData));
- ExecutionContextSaver ctxSaver(context);
- ScopedValue result(scope, Q_V4_PROFILE(v4, ctx, f->function()));
+ ExecutionContextSaver ctxSaver(scope, context);
+ ScopedValue result(scope, Q_V4_PROFILE(v4, f->function()));
if (f->function()->compiledFunction->hasQmlDependencies())
QmlContextWrapper::registerQmlDependencies(ctx->d()->engine, f->function()->compiledFunction);
@@ -412,19 +449,16 @@ ReturnedValue ScriptFunction::call(Managed *that, CallData *callData)
DEFINE_OBJECT_VTABLE(SimpleScriptFunction);
-SimpleScriptFunction::Data::Data(ExecutionContext *scope, Function *function, bool createProto)
- : FunctionObject::Data(scope, function->name(), createProto)
+Heap::SimpleScriptFunction::SimpleScriptFunction(QV4::ExecutionContext *scope, Function *function, bool createProto)
+ : Heap::FunctionObject(scope, function, createProto)
{
- setVTable(staticVTable());
+ setVTable(QV4::SimpleScriptFunction::staticVTable());
this->function = function;
function->compilationUnit->addref();
Q_ASSERT(function);
Q_ASSERT(function->code);
- needsActivation = function->needsActivation();
- strictMode = function->isStrict();
-
// global function
if (!scope)
return;
@@ -435,7 +469,9 @@ SimpleScriptFunction::Data::Data(ExecutionContext *scope, Function *function, bo
f->defineReadonlyProperty(scope->d()->engine->id_length, Primitive::fromInt32(f->formalParameterCount()));
if (scope->d()->strictMode) {
- Property pd(s.engine->thrower, s.engine->thrower);
+ ScopedProperty pd(s);
+ pd->value = s.engine->thrower;
+ pd->set = s.engine->thrower;
f->insertMember(scope->d()->engine->id_caller, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
f->insertMember(scope->d()->engine->id_arguments, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
}
@@ -451,27 +487,27 @@ ReturnedValue SimpleScriptFunction::construct(Managed *that, CallData *callData)
Scope scope(v4);
Scoped<SimpleScriptFunction> f(scope, static_cast<SimpleScriptFunction *>(that));
- InternalClass *ic = f->internalClassForConstructor();
- callData->thisObject = v4->newObject(ic);
+ InternalClass *ic = scope.engine->objectClass;
+ ScopedObject proto(scope, f->protoForConstructor());
+ callData->thisObject = v4->newObject(ic, proto);
- ExecutionContext *context = v4->currentContext();
- ExecutionContextSaver ctxSaver(context);
+ ExecutionContextSaver ctxSaver(scope, v4->currentContext());
CallContext::Data ctx(v4);
ctx.strictMode = f->strictMode();
ctx.callData = callData;
- ctx.function = f.getPointer();
+ ctx.function = f->d();
ctx.compilationUnit = f->function()->compilationUnit;
ctx.lookups = ctx.compilationUnit->runtimeLookups;
ctx.outer = f->scope();
- ctx.locals = v4->stackPush(f->varCount());
+ ctx.locals = scope.alloc(f->varCount());
while (callData->argc < (int)f->formalParameterCount()) {
callData->args[callData->argc] = Encode::undefined();
++callData->argc;
}
- Q_ASSERT(v4->currentContext()->d() == &ctx);
+ Q_ASSERT(v4->currentContext() == &ctx);
- Scoped<Object> result(scope, Q_V4_PROFILE(v4, reinterpret_cast<CallContext *>(&ctx), f->function()));
+ ScopedObject result(scope, Q_V4_PROFILE(v4, f->function()));
if (f->function()->compiledFunction->hasQmlDependencies())
QmlContextWrapper::registerQmlDependencies(v4, f->function()->compiledFunction);
@@ -488,27 +524,26 @@ ReturnedValue SimpleScriptFunction::call(Managed *that, CallData *callData)
return Encode::undefined();
CHECK_STACK_LIMITS(v4);
- SimpleScriptFunction *f = static_cast<SimpleScriptFunction *>(that);
-
Scope scope(v4);
- ExecutionContext *context = v4->currentContext();
- ExecutionContextSaver ctxSaver(context);
+ Scoped<SimpleScriptFunction> f(scope, static_cast<SimpleScriptFunction *>(that));
+
+ ExecutionContextSaver ctxSaver(scope, v4->currentContext());
CallContext::Data ctx(v4);
ctx.strictMode = f->strictMode();
ctx.callData = callData;
- ctx.function = f;
+ ctx.function = f->d();
ctx.compilationUnit = f->function()->compilationUnit;
ctx.lookups = ctx.compilationUnit->runtimeLookups;
ctx.outer = f->scope();
- ctx.locals = v4->stackPush(f->varCount());
+ ctx.locals = scope.alloc(f->varCount());
while (callData->argc < (int)f->formalParameterCount()) {
callData->args[callData->argc] = Encode::undefined();
++callData->argc;
}
- Q_ASSERT(v4->currentContext()->d() == &ctx);
+ Q_ASSERT(v4->currentContext() == &ctx);
- ScopedValue result(scope, Q_V4_PROFILE(v4, reinterpret_cast<CallContext *>(&ctx), f->function()));
+ ScopedValue result(scope, Q_V4_PROFILE(v4, f->function()));
if (f->function()->compiledFunction->hasQmlDependencies())
QmlContextWrapper::registerQmlDependencies(v4, f->function()->compiledFunction);
@@ -516,34 +551,29 @@ ReturnedValue SimpleScriptFunction::call(Managed *that, CallData *callData)
return result.asReturnedValue();
}
-InternalClass *SimpleScriptFunction::internalClassForConstructor()
+Heap::Object *SimpleScriptFunction::protoForConstructor()
{
- ReturnedValue proto = protoProperty();
- InternalClass *classForConstructor;
- Scope scope(internalClass()->engine);
- ScopedObject p(scope, proto);
+ Scope scope(engine());
+ ScopedObject p(scope, protoProperty());
if (p)
- classForConstructor = internalClass()->engine->constructClass->changePrototype(p.getPointer());
- else
- classForConstructor = scope.engine->objectClass;
-
- return classForConstructor;
+ return p->d();
+ return scope.engine->objectPrototype.asObject()->d();
}
DEFINE_OBJECT_VTABLE(BuiltinFunction);
-BuiltinFunction::Data::Data(ExecutionContext *scope, String *name, ReturnedValue (*code)(CallContext *))
- : FunctionObject::Data(scope, name)
+Heap::BuiltinFunction::BuiltinFunction(QV4::ExecutionContext *scope, QV4::String *name, ReturnedValue (*code)(QV4::CallContext *))
+ : Heap::FunctionObject(scope, name)
, code(code)
{
- setVTable(staticVTable());
+ setVTable(QV4::BuiltinFunction::staticVTable());
}
ReturnedValue BuiltinFunction::construct(Managed *f, CallData *)
{
- return f->internalClass()->engine->currentContext()->throwTypeError();
+ return f->internalClass()->engine->throwTypeError();
}
ReturnedValue BuiltinFunction::call(Managed *that, CallData *callData)
@@ -554,15 +584,16 @@ ReturnedValue BuiltinFunction::call(Managed *that, CallData *callData)
return Encode::undefined();
CHECK_STACK_LIMITS(v4);
- ExecutionContext *context = v4->currentContext();
- ExecutionContextSaver ctxSaver(context);
+ Scope scope(v4);
+ ExecutionContextSaver ctxSaver(scope, v4->currentContext());
CallContext::Data ctx(v4);
- ctx.strictMode = f->scope()->d()->strictMode; // ### needed? scope or parent context?
+ ctx.strictMode = f->scope()->strictMode; // ### needed? scope or parent context?
ctx.callData = callData;
- Q_ASSERT(v4->currentContext()->d() == &ctx);
+ Q_ASSERT(v4->currentContext() == &ctx);
+ Scoped<CallContext> sctx(scope, &ctx);
- return f->d()->code(reinterpret_cast<CallContext *>(&ctx));
+ return f->d()->code(sctx);
}
ReturnedValue IndexedBuiltinFunction::call(Managed *that, CallData *callData)
@@ -573,43 +604,45 @@ ReturnedValue IndexedBuiltinFunction::call(Managed *that, CallData *callData)
return Encode::undefined();
CHECK_STACK_LIMITS(v4);
- ExecutionContext *context = v4->currentContext();
- ExecutionContextSaver ctxSaver(context);
+ Scope scope(v4);
+ ExecutionContextSaver ctxSaver(scope, v4->currentContext());
CallContext::Data ctx(v4);
- ctx.strictMode = f->scope()->d()->strictMode; // ### needed? scope or parent context?
+ ctx.strictMode = f->scope()->strictMode; // ### needed? scope or parent context?
ctx.callData = callData;
- Q_ASSERT(v4->currentContext()->d() == &ctx);
+ Q_ASSERT(v4->currentContext() == &ctx);
+ Scoped<CallContext> sctx(scope, &ctx);
- return f->d()->code(reinterpret_cast<CallContext *>(&ctx), f->d()->index);
+ return f->d()->code(sctx, f->d()->index);
}
DEFINE_OBJECT_VTABLE(IndexedBuiltinFunction);
DEFINE_OBJECT_VTABLE(BoundFunction);
-BoundFunction::Data::Data(ExecutionContext *scope, FunctionObject *target, const ValueRef boundThis, const Members &boundArgs)
- : FunctionObject::Data(scope, QStringLiteral("__bound function__"))
- , target(target)
- , boundArgs(boundArgs)
+Heap::BoundFunction::BoundFunction(QV4::ExecutionContext *scope, QV4::FunctionObject *target,
+ const ValueRef boundThis, QV4::MemberData *boundArgs)
+ : Heap::FunctionObject(scope, QStringLiteral("__bound function__"))
+ , target(target->d())
+ , boundArgs(boundArgs ? boundArgs->d() : 0)
{
this->boundThis = boundThis;
- setVTable(staticVTable());
- subtype = FunctionObject::BoundFunction;
+ setVTable(QV4::BoundFunction::staticVTable());
Scope s(scope);
ScopedObject f(s, this);
ScopedValue l(s, target->get(s.engine->id_length));
int len = l->toUInt32();
- len -= boundArgs.size();
+ if (boundArgs)
+ len -= boundArgs->size();
if (len < 0)
len = 0;
f->defineReadonlyProperty(s.engine->id_length, Primitive::fromInt32(len));
- ExecutionEngine *v4 = s.engine;
-
- Property pd(v4->thrower, v4->thrower);
+ ScopedProperty pd(s);
+ pd->value = s.engine->thrower;
+ pd->set = s.engine->thrower;
f->insertMember(s.engine->id_arguments, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
f->insertMember(s.engine->id_caller, pd, Attr_Accessor|Attr_NotConfigurable|Attr_NotEnumerable);
}
@@ -617,35 +650,48 @@ BoundFunction::Data::Data(ExecutionContext *scope, FunctionObject *target, const
ReturnedValue BoundFunction::call(Managed *that, CallData *dd)
{
BoundFunction *f = static_cast<BoundFunction *>(that);
- Scope scope(f->scope()->d()->engine);
+ Scope scope(f->engine());
if (scope.hasException())
return Encode::undefined();
- ScopedCallData callData(scope, f->boundArgs().size() + dd->argc);
+ Scoped<MemberData> boundArgs(scope, f->boundArgs());
+ ScopedCallData callData(scope, (boundArgs ? boundArgs->size() : 0) + dd->argc);
callData->thisObject = f->boundThis();
- memcpy(callData->args, f->boundArgs().data(), f->boundArgs().size()*sizeof(Value));
- memcpy(callData->args + f->boundArgs().size(), dd->args, dd->argc*sizeof(Value));
- return f->target()->call(callData);
+ Value *argp = callData->args;
+ if (boundArgs) {
+ memcpy(argp, boundArgs->data(), boundArgs->size()*sizeof(Value));
+ argp += boundArgs->size();
+ }
+ memcpy(argp, dd->args, dd->argc*sizeof(Value));
+ ScopedFunctionObject t(scope, f->target());
+ return t->call(callData);
}
ReturnedValue BoundFunction::construct(Managed *that, CallData *dd)
{
BoundFunction *f = static_cast<BoundFunction *>(that);
- Scope scope(f->scope()->d()->engine);
+ Scope scope(f->engine());
if (scope.hasException())
return Encode::undefined();
- ScopedCallData callData(scope, f->boundArgs().size() + dd->argc);
- memcpy(callData->args, f->boundArgs().data(), f->boundArgs().size()*sizeof(Value));
- memcpy(callData->args + f->boundArgs().size(), dd->args, dd->argc*sizeof(Value));
- return f->target()->construct(callData);
+ Scoped<MemberData> boundArgs(scope, f->boundArgs());
+ ScopedCallData callData(scope, (boundArgs ? boundArgs->size() : 0) + dd->argc);
+ Value *argp = callData->args;
+ if (boundArgs) {
+ memcpy(argp, boundArgs->data(), boundArgs->size()*sizeof(Value));
+ argp += boundArgs->size();
+ }
+ memcpy(argp, dd->args, dd->argc*sizeof(Value));
+ ScopedFunctionObject t(scope, f->target());
+ return t->construct(callData);
}
-void BoundFunction::markObjects(Managed *that, ExecutionEngine *e)
+void BoundFunction::markObjects(Heap::Base *that, ExecutionEngine *e)
{
- BoundFunction *o = static_cast<BoundFunction *>(that);
- o->target()->mark(e);
- o->boundThis().mark(e);
- o->boundArgs().mark(e);
+ BoundFunction::Data *o = static_cast<BoundFunction::Data *>(that);
+ o->target->mark(e);
+ o->boundThis.mark(e);
+ if (o->boundArgs)
+ o->boundArgs->mark(e);
FunctionObject::markObjects(that, e);
}
diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h
index adedb9fb7d..e806888243 100644
--- a/src/qml/jsruntime/qv4functionobject_p.h
+++ b/src/qml/jsruntime/qv4functionobject_p.h
@@ -33,94 +33,90 @@
#ifndef QV4FUNCTIONOBJECT_H
#define QV4FUNCTIONOBJECT_H
-#include "qv4global_p.h"
-#include "qv4runtime_p.h"
-#include "qv4engine_p.h"
-#include "qv4context_p.h"
#include "qv4object_p.h"
-#include "qv4string_p.h"
-#include "qv4managed_p.h"
-#include "qv4property_p.h"
#include "qv4function_p.h"
-#include "qv4objectiterator_p.h"
+#include "qv4context_p.h"
#include "qv4mm_p.h"
-#include <QtCore/QString>
-#include <QtCore/QHash>
-#include <QtCore/QScopedPointer>
-#include <cstdio>
-#include <cassert>
-
QT_BEGIN_NAMESPACE
namespace QV4 {
-struct Function;
-struct Object;
-struct BooleanObject;
-struct NumberObject;
-struct StringObject;
-struct ArrayObject;
-struct DateObject;
-struct FunctionObject;
-struct ErrorObject;
-struct ArgumentsObject;
-struct ExecutionContext;
-struct ExecutionEngine;
-class MemoryManager;
-
-struct ObjectPrototype;
-struct StringPrototype;
-struct NumberPrototype;
-struct BooleanPrototype;
-struct ArrayPrototype;
-struct FunctionPrototype;
-struct DatePrototype;
-struct ErrorPrototype;
-struct EvalErrorPrototype;
-struct RangeErrorPrototype;
-struct ReferenceErrorPrototype;
-struct SyntaxErrorPrototype;
-struct TypeErrorPrototype;
-struct URIErrorPrototype;
-struct InternalClass;
-struct Lookup;
-
-struct Q_QML_EXPORT FunctionObject: Object {
- struct Q_QML_PRIVATE_EXPORT Data : Object::Data {
- Data(ExecutionContext *scope, String *name, bool createProto = false);
- Data(ExecutionContext *scope, const QString &name = QString(), bool createProto = false);
- Data(ExecutionContext *scope, const ReturnedValue name);
- Data(InternalClass *ic);
- ~Data();
-
- ExecutionContext *scope;
- Function *function;
- };
- V4_OBJECT(Object)
- Q_MANAGED_TYPE(FunctionObject)
- enum {
- IsFunctionObject = true
- };
- // Used with Managed::subType
- enum FunctionType {
- RegularFunction = 0,
- WrappedQtMethod = 1,
- BoundFunction
- };
+namespace Heap {
+struct Q_QML_PRIVATE_EXPORT FunctionObject : Object {
enum {
Index_Prototype = 0,
Index_ProtoConstructor = 0
};
+ FunctionObject(QV4::ExecutionContext *scope, QV4::String *name, bool createProto = false);
+ FunctionObject(QV4::ExecutionContext *scope, QV4::Function *function, bool createProto = false);
+ FunctionObject(QV4::ExecutionContext *scope, const QString &name = QString(), bool createProto = false);
+ FunctionObject(ExecutionContext *scope, const QString &name = QString(), bool createProto = false);
+ FunctionObject(QV4::ExecutionContext *scope, const ReturnedValue name);
+ FunctionObject(ExecutionContext *scope, const ReturnedValue name);
+ FunctionObject(InternalClass *ic, QV4::Object *prototype);
+ ~FunctionObject();
+
+ unsigned int formalParameterCount() { return function ? function->compiledFunction->nFormals : 0; }
+ unsigned int varCount() { return function ? function->compiledFunction->nLocals : 0; }
+ bool needsActivation() const { return function ? function->needsActivation() : false; }
+
+ ExecutionContext *scope;
+ Function *function;
+};
+
+struct FunctionCtor : FunctionObject {
+ FunctionCtor(QV4::ExecutionContext *scope);
+};
+
+struct FunctionPrototype : FunctionObject {
+ FunctionPrototype(InternalClass *ic, QV4::Object *prototype);
+};
+
+struct Q_QML_EXPORT BuiltinFunction : FunctionObject {
+ BuiltinFunction(QV4::ExecutionContext *scope, QV4::String *name, ReturnedValue (*code)(QV4::CallContext *));
+ ReturnedValue (*code)(QV4::CallContext *);
+};
+
+struct IndexedBuiltinFunction : FunctionObject {
+ inline IndexedBuiltinFunction(QV4::ExecutionContext *scope, uint index, ReturnedValue (*code)(QV4::CallContext *ctx, uint index));
+ ReturnedValue (*code)(QV4::CallContext *, uint index);
+ uint index;
+};
+
+struct SimpleScriptFunction : FunctionObject {
+ SimpleScriptFunction(QV4::ExecutionContext *scope, Function *function, bool createProto);
+};
+
+struct ScriptFunction : SimpleScriptFunction {
+ ScriptFunction(QV4::ExecutionContext *scope, Function *function);
+};
+
+struct BoundFunction : FunctionObject {
+ BoundFunction(QV4::ExecutionContext *scope, QV4::FunctionObject *target, const ValueRef boundThis, QV4::MemberData *boundArgs);
+ FunctionObject *target;
+ Value boundThis;
+ MemberData *boundArgs;
+};
+
+}
+
+struct Q_QML_EXPORT FunctionObject: Object {
+ enum {
+ IsFunctionObject = true
+ };
+ V4_OBJECT2(FunctionObject, Object)
+ Q_MANAGED_TYPE(FunctionObject)
+ V4_NEEDS_DESTROY
- ExecutionContext *scope() { return d()->scope; }
- Function *function() const { return d()->function; }
+ Heap::ExecutionContext *scope() { return d()->scope; }
+ Function *function() { return d()->function; }
ReturnedValue name();
- unsigned int formalParameterCount() { return function() ? function()->compiledFunction->nFormals : 0; }
- unsigned int varCount() { return function() ? function()->compiledFunction->nLocals : 0; }
+ unsigned int formalParameterCount() { return d()->formalParameterCount(); }
+ unsigned int varCount() { return d()->varCount(); }
void init(String *name, bool createProto);
@@ -130,23 +126,21 @@ struct Q_QML_EXPORT FunctionObject: Object {
using Object::call;
static ReturnedValue construct(Managed *that, CallData *);
static ReturnedValue call(Managed *that, CallData *d);
- static void destroy(Managed *m) {
- static_cast<FunctionObject *>(m)->d()->~Data();
- }
static FunctionObject *cast(const Value &v) {
return v.asFunctionObject();
}
- static FunctionObject *createScriptFunction(ExecutionContext *scope, Function *function, bool createProto = true);
+ static Heap::FunctionObject *createScriptFunction(ExecutionContext *scope, Function *function, bool createProto = true);
- ReturnedValue protoProperty() { return memberData()[Index_Prototype].asReturnedValue(); }
+ ReturnedValue protoProperty() { return memberData()->data[Heap::FunctionObject::Index_Prototype].asReturnedValue(); }
- bool needsActivation() const { return d()->needsActivation; }
- bool strictMode() const { return d()->strictMode; }
- bool bindingKeyFlag() const { return d()->bindingKeyFlag; }
+ bool needsActivation() const { return d()->needsActivation(); }
+ bool strictMode() const { return d()->function ? d()->function->isStrict() : false; }
+ bool isBinding() const;
+ bool isBoundFunction() const;
- static void markObjects(Managed *that, ExecutionEngine *e);
+ static void markObjects(Heap::Base *that, ExecutionEngine *e);
};
template<>
@@ -156,11 +150,7 @@ inline FunctionObject *value_cast(const Value &v) {
struct FunctionCtor: FunctionObject
{
- struct Data : FunctionObject::Data {
- Data(ExecutionContext *scope);
- };
-
- V4_OBJECT(FunctionObject)
+ V4_OBJECT2(FunctionCtor, FunctionObject)
static ReturnedValue construct(Managed *that, CallData *callData);
static ReturnedValue call(Managed *that, CallData *callData);
@@ -168,10 +158,7 @@ struct FunctionCtor: FunctionObject
struct FunctionPrototype: FunctionObject
{
- struct Data : FunctionObject::Data {
- Data(InternalClass *ic);
- };
- V4_OBJECT(FunctionObject)
+ V4_OBJECT2(FunctionPrototype, FunctionObject)
void init(ExecutionEngine *engine, Object *ctor);
@@ -182,13 +169,9 @@ struct FunctionPrototype: FunctionObject
};
struct Q_QML_EXPORT BuiltinFunction: FunctionObject {
- struct Q_QML_EXPORT Data : FunctionObject::Data {
- Data(ExecutionContext *scope, String *name, ReturnedValue (*code)(CallContext *));
- ReturnedValue (*code)(CallContext *);
- };
- V4_OBJECT(FunctionObject)
+ V4_OBJECT2(BuiltinFunction, FunctionObject)
- static BuiltinFunction *create(ExecutionContext *scope, String *name, ReturnedValue (*code)(CallContext *))
+ static Heap::BuiltinFunction *create(ExecutionContext *scope, String *name, ReturnedValue (*code)(CallContext *))
{
return scope->engine()->memoryManager->alloc<BuiltinFunction>(scope, name, code);
}
@@ -199,45 +182,37 @@ struct Q_QML_EXPORT BuiltinFunction: FunctionObject {
struct IndexedBuiltinFunction: FunctionObject
{
- struct Data : FunctionObject::Data {
- Data(ExecutionContext *scope, uint index, ReturnedValue (*code)(CallContext *ctx, uint index))
- : FunctionObject::Data(scope),
- code(code)
- , index(index)
- {
- setVTable(staticVTable());
- }
- ReturnedValue (*code)(CallContext *, uint index);
- uint index;
- };
- V4_OBJECT(FunctionObject)
+ V4_OBJECT2(IndexedBuiltinFunction, FunctionObject)
static ReturnedValue construct(Managed *m, CallData *)
{
- return m->engine()->currentContext()->throwTypeError();
+ return m->engine()->throwTypeError();
}
static ReturnedValue call(Managed *that, CallData *callData);
};
+Heap::IndexedBuiltinFunction::IndexedBuiltinFunction(QV4::ExecutionContext *scope, uint index,
+ ReturnedValue (*code)(QV4::CallContext *ctx, uint index))
+ : Heap::FunctionObject(scope),
+ code(code)
+ , index(index)
+{
+ setVTable(QV4::IndexedBuiltinFunction::staticVTable());
+}
+
struct SimpleScriptFunction: FunctionObject {
- struct Data : FunctionObject::Data {
- Data(ExecutionContext *scope, Function *function, bool createProto);
- };
- V4_OBJECT(FunctionObject)
+ V4_OBJECT2(SimpleScriptFunction, FunctionObject)
static ReturnedValue construct(Managed *, CallData *callData);
static ReturnedValue call(Managed *that, CallData *callData);
- InternalClass *internalClassForConstructor();
+ Heap::Object *protoForConstructor();
};
struct ScriptFunction: SimpleScriptFunction {
- struct Data : SimpleScriptFunction::Data {
- Data(ExecutionContext *scope, Function *function);
- };
- V4_OBJECT(FunctionObject)
+ V4_OBJECT2(ScriptFunction, FunctionObject)
static ReturnedValue construct(Managed *, CallData *callData);
static ReturnedValue call(Managed *that, CallData *callData);
@@ -245,27 +220,21 @@ struct ScriptFunction: SimpleScriptFunction {
struct BoundFunction: FunctionObject {
- struct Data : FunctionObject::Data {
- Data(ExecutionContext *scope, FunctionObject *target, const ValueRef boundThis, const Members &boundArgs);
- FunctionObject *target;
- Value boundThis;
- Members boundArgs;
- };
- V4_OBJECT(FunctionObject)
+ V4_OBJECT2(BoundFunction, FunctionObject)
- static BoundFunction *create(ExecutionContext *scope, FunctionObject *target, const ValueRef boundThis, const QV4::Members &boundArgs)
+ static Heap::BoundFunction *create(ExecutionContext *scope, FunctionObject *target, const ValueRef boundThis, QV4::MemberData *boundArgs)
{
return scope->engine()->memoryManager->alloc<BoundFunction>(scope, target, boundThis, boundArgs);
}
- FunctionObject *target() { return d()->target; }
+ Heap::FunctionObject *target() { return d()->target; }
Value boundThis() const { return d()->boundThis; }
- Members boundArgs() const { return d()->boundArgs; }
+ Heap::MemberData *boundArgs() const { return d()->boundArgs; }
static ReturnedValue construct(Managed *, CallData *d);
static ReturnedValue call(Managed *that, CallData *dd);
- static void markObjects(Managed *that, ExecutionEngine *e);
+ static void markObjects(Heap::Base *that, ExecutionEngine *e);
};
}
diff --git a/src/qml/jsruntime/qv4global_p.h b/src/qml/jsruntime/qv4global_p.h
index a58beb3aaa..687ff19be4 100644
--- a/src/qml/jsruntime/qv4global_p.h
+++ b/src/qml/jsruntime/qv4global_p.h
@@ -114,6 +114,39 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
+namespace Heap {
+ struct Base;
+ struct MemberData;
+ struct ArrayData;
+
+ struct String;
+ struct Object;
+ struct ObjectPrototype;
+
+ struct ExecutionContext;
+ struct GlobalContext;
+ struct CallContext;
+ struct ScriptFunction;
+
+ struct BooleanObject;
+ struct NumberObject;
+ struct StringObject;
+ struct ArrayObject;
+ struct DateObject;
+ struct FunctionObject;
+ struct ErrorObject;
+ struct ArgumentsObject;
+ struct QObjectWrapper;
+ struct RegExpObject;
+ struct RegExp;
+ struct EvalFunction;
+
+ struct ArrayBuffer;
+ struct DataView;
+ struct TypedArray;
+
+}
+
class MemoryManager;
struct String;
struct Object;
@@ -126,6 +159,9 @@ struct ScriptFunction;
struct InternalClass;
struct Property;
struct Value;
+struct Lookup;
+struct ArrayData;
+struct ManagedVTable;
struct BooleanObject;
struct NumberObject;
@@ -136,9 +172,15 @@ struct FunctionObject;
struct ErrorObject;
struct ArgumentsObject;
struct Managed;
-struct Lookup;
struct ExecutionEngine;
struct QObjectWrapper;
+struct RegExpObject;
+struct RegExp;
+struct EvalFunction;
+
+struct ArrayBuffer;
+struct DataView;
+struct TypedArray;
// ReturnedValue is used to return values from runtime methods
// the type has to be a primitive type (no struct or union), so that the compiler
@@ -146,6 +188,7 @@ struct QObjectWrapper;
// It will be returned in rax on x64, [eax,edx] on x86 and [r0,r1] on arm
typedef quint64 ReturnedValue;
struct CallData;
+struct Scope;
struct ScopedValue;
struct ValueRef;
template<typename T> struct Scoped;
@@ -153,15 +196,16 @@ typedef Scoped<String> ScopedString;
typedef Scoped<Object> ScopedObject;
typedef Scoped<ArrayObject> ScopedArrayObject;
typedef Scoped<FunctionObject> ScopedFunctionObject;
-template<typename T> struct Returned;
-typedef Returned<String> ReturnedString;
-typedef Returned<Object> ReturnedObject;
-typedef Returned<FunctionObject> ReturnedFunctionObject;
+typedef Scoped<ExecutionContext> ScopedContext;
struct PersistentValuePrivate;
class PersistentValue;
class WeakValue;
+struct IdentifierTable;
+class RegExpCache;
+class MultiplyWrappedQObjectMap;
+struct QmlExtensions;
namespace Global {
enum {
diff --git a/src/qml/jsruntime/qv4globalobject.cpp b/src/qml/jsruntime/qv4globalobject.cpp
index 9a9de8bb41..c521337ce6 100644
--- a/src/qml/jsruntime/qv4globalobject.cpp
+++ b/src/qml/jsruntime/qv4globalobject.cpp
@@ -338,10 +338,10 @@ static QString decode(const QString &input, DecodeMode decodeMode, bool *ok)
DEFINE_OBJECT_VTABLE(EvalFunction);
-EvalFunction::Data::Data(ExecutionContext *scope)
- : FunctionObject::Data(scope, scope->d()->engine->id_eval)
+Heap::EvalFunction::EvalFunction(QV4::ExecutionContext *scope)
+ : Heap::FunctionObject(scope, scope->d()->engine->id_eval)
{
- setVTable(staticVTable());
+ setVTable(QV4::EvalFunction::staticVTable());
Scope s(scope);
ScopedFunctionObject f(s, this);
f->defineReadonlyProperty(s.engine->id_length, Primitive::fromInt32(1));
@@ -353,11 +353,12 @@ ReturnedValue EvalFunction::evalCall(CallData *callData, bool directCall)
return Encode::undefined();
ExecutionEngine *v4 = engine();
- ExecutionContext *parentContext = v4->currentContext();
- ExecutionContextSaver ctxSaver(parentContext);
+ Scope scope(v4);
- ExecutionContext *ctx = parentContext;
- Scope scope(ctx);
+ ScopedContext parentContext(scope, v4->currentContext());
+ ExecutionContextSaver ctxSaver(scope, parentContext);
+
+ ScopedContext ctx(scope, parentContext.getPointer());
if (!directCall) {
// the context for eval should be the global scope, so we fake a root
@@ -382,24 +383,20 @@ ReturnedValue EvalFunction::evalCall(CallData *callData, bool directCall)
if (!function)
return Encode::undefined();
- d()->strictMode = function->isStrict() || (ctx->d()->strictMode);
-
- d()->needsActivation = function->needsActivation();
-
- if (strictMode()) {
+ if (function->isStrict() || (ctx->d()->strictMode)) {
ScopedFunctionObject e(scope, FunctionObject::createScriptFunction(ctx, function));
ScopedCallData callData(scope, 0);
callData->thisObject = ctx->d()->callData->thisObject;
return e->call(callData);
}
- ContextStateSaver stateSaver(ctx);
+ ContextStateSaver stateSaver(scope, ctx);
// set the correct strict mode flag on the context
- ctx->d()->strictMode = strictMode();
+ ctx->d()->strictMode = false;
ctx->d()->compilationUnit = function->compilationUnit;
- return function->code(ctx, function->codeData);
+ return function->code(ctx->engine(), function->codeData);
}
@@ -430,13 +427,12 @@ static inline int toInt(const QChar &qc, int R)
ReturnedValue GlobalFunctions::method_parseInt(CallContext *ctx)
{
Scope scope(ctx);
- ScopedValue string(scope, ctx->argument(0));
+ ScopedValue inputString(scope, ctx->argument(0));
ScopedValue radix(scope, ctx->argument(1));
int R = radix->isUndefined() ? 0 : radix->toInt32();
// [15.1.2.2] step by step:
- String *inputString = string->toString(ctx); // 1
- QString trimmed = inputString->toQString().trimmed(); // 2
+ QString trimmed = inputString->toQString().trimmed(); // 1 + 2
if (ctx->d()->engine->hasException)
return Encode::undefined();
@@ -516,7 +512,7 @@ ReturnedValue GlobalFunctions::method_parseFloat(CallContext *ctx)
Scope scope(ctx);
// [15.1.2.3] step by step:
- Scoped<String> inputString(scope, ctx->argument(0), Scoped<String>::Convert);
+ ScopedString inputString(scope, ctx->argument(0), ScopedString::Convert);
if (scope.engine->hasException)
return Encode::undefined();
@@ -573,13 +569,13 @@ ReturnedValue GlobalFunctions::method_decodeURI(CallContext *context)
if (context->d()->callData->argc == 0)
return Encode::undefined();
- QString uriString = context->d()->callData->args[0].toString(context)->toQString();
+ QString uriString = context->d()->callData->args[0].toQString();
bool ok;
QString out = decode(uriString, DecodeNonReserved, &ok);
if (!ok) {
Scope scope(context);
ScopedString s(scope, context->d()->engine->newString(QStringLiteral("malformed URI sequence")));
- return context->throwURIError(s);
+ return context->engine()->throwURIError(s);
}
return context->d()->engine->newString(out)->asReturnedValue();
@@ -591,13 +587,13 @@ ReturnedValue GlobalFunctions::method_decodeURIComponent(CallContext *context)
if (context->d()->callData->argc == 0)
return Encode::undefined();
- QString uriString = context->d()->callData->args[0].toString(context)->toQString();
+ QString uriString = context->d()->callData->args[0].toQString();
bool ok;
QString out = decode(uriString, DecodeAll, &ok);
if (!ok) {
Scope scope(context);
ScopedString s(scope, context->d()->engine->newString(QStringLiteral("malformed URI sequence")));
- return context->throwURIError(s);
+ return context->engine()->throwURIError(s);
}
return context->d()->engine->newString(out)->asReturnedValue();
@@ -609,13 +605,13 @@ ReturnedValue GlobalFunctions::method_encodeURI(CallContext *context)
if (context->d()->callData->argc == 0)
return Encode::undefined();
- QString uriString = context->d()->callData->args[0].toString(context)->toQString();
+ QString uriString = context->d()->callData->args[0].toQString();
bool ok;
QString out = encode(uriString, uriUnescapedReserved, &ok);
if (!ok) {
Scope scope(context);
ScopedString s(scope, context->d()->engine->newString(QStringLiteral("malformed URI sequence")));
- return context->throwURIError(s);
+ return context->engine()->throwURIError(s);
}
return context->d()->engine->newString(out)->asReturnedValue();
@@ -627,13 +623,13 @@ ReturnedValue GlobalFunctions::method_encodeURIComponent(CallContext *context)
if (context->d()->callData->argc == 0)
return Encode::undefined();
- QString uriString = context->d()->callData->args[0].toString(context)->toQString();
+ QString uriString = context->d()->callData->args[0].toQString();
bool ok;
QString out = encode(uriString, uriUnescaped, &ok);
if (!ok) {
Scope scope(context);
ScopedString s(scope, context->d()->engine->newString(QStringLiteral("malformed URI sequence")));
- return context->throwURIError(s);
+ return context->engine()->throwURIError(s);
}
return context->d()->engine->newString(out)->asReturnedValue();
@@ -644,7 +640,7 @@ ReturnedValue GlobalFunctions::method_escape(CallContext *context)
if (!context->d()->callData->argc)
return context->d()->engine->newString(QStringLiteral("undefined"))->asReturnedValue();
- QString str = context->d()->callData->args[0].toString(context)->toQString();
+ QString str = context->d()->callData->args[0].toQString();
return context->d()->engine->newString(escape(str))->asReturnedValue();
}
@@ -653,6 +649,6 @@ ReturnedValue GlobalFunctions::method_unescape(CallContext *context)
if (!context->d()->callData->argc)
return context->d()->engine->newString(QStringLiteral("undefined"))->asReturnedValue();
- QString str = context->d()->callData->args[0].toString(context)->toQString();
+ QString str = context->d()->callData->args[0].toQString();
return context->d()->engine->newString(unescape(str))->asReturnedValue();
}
diff --git a/src/qml/jsruntime/qv4globalobject_p.h b/src/qml/jsruntime/qv4globalobject_p.h
index 352519ceaf..176ae37300 100644
--- a/src/qml/jsruntime/qv4globalobject_p.h
+++ b/src/qml/jsruntime/qv4globalobject_p.h
@@ -40,13 +40,17 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
+namespace Heap {
+
+struct EvalFunction : FunctionObject {
+ EvalFunction(QV4::ExecutionContext *scope);
+};
+
+}
+
struct Q_QML_EXPORT EvalFunction : FunctionObject
{
- struct Data : FunctionObject::Data {
- Data(ExecutionContext *scope);
- };
-
- V4_OBJECT(FunctionObject)
+ V4_OBJECT2(EvalFunction, FunctionObject)
ReturnedValue evalCall(CallData *callData, bool directCall);
diff --git a/src/qml/jsruntime/qv4identifier.cpp b/src/qml/jsruntime/qv4identifier.cpp
index d7e0e25ddf..3432f8702d 100644
--- a/src/qml/jsruntime/qv4identifier.cpp
+++ b/src/qml/jsruntime/qv4identifier.cpp
@@ -152,7 +152,7 @@ const Identifier *IdentifierHashBase::toIdentifier(const QString &str) const
return d->identifierTable->identifier(str);
}
-const Identifier *IdentifierHashBase::toIdentifier(String *str) const
+const Identifier *IdentifierHashBase::toIdentifier(Heap::String *str) const
{
Q_ASSERT(d);
return d->identifierTable->identifier(str);
diff --git a/src/qml/jsruntime/qv4identifier_p.h b/src/qml/jsruntime/qv4identifier_p.h
index afed5c646f..a89ac29d2f 100644
--- a/src/qml/jsruntime/qv4identifier_p.h
+++ b/src/qml/jsruntime/qv4identifier_p.h
@@ -39,6 +39,10 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
+namespace Heap {
+ struct String;
+}
+
struct String;
struct IdentifierTable;
struct ExecutionEngine;
@@ -102,7 +106,7 @@ protected:
const IdentifierHashEntry *lookup(const QString &str) const;
const IdentifierHashEntry *lookup(String *str) const;
const Identifier *toIdentifier(const QString &str) const;
- const Identifier *toIdentifier(String *str) const;
+ const Identifier *toIdentifier(Heap::String *str) const;
};
diff --git a/src/qml/jsruntime/qv4identifiertable.cpp b/src/qml/jsruntime/qv4identifiertable.cpp
index d7ed7a8db0..46e309c7f3 100644
--- a/src/qml/jsruntime/qv4identifiertable.cpp
+++ b/src/qml/jsruntime/qv4identifiertable.cpp
@@ -53,41 +53,41 @@ IdentifierTable::IdentifierTable(ExecutionEngine *engine)
, numBits(8)
{
alloc = primeForNumBits(numBits);
- entries = (String **)malloc(alloc*sizeof(String *));
- memset(entries, 0, alloc*sizeof(String *));
+ entries = (Heap::String **)malloc(alloc*sizeof(Heap::String *));
+ memset(entries, 0, alloc*sizeof(Heap::String *));
}
IdentifierTable::~IdentifierTable()
{
for (int i = 0; i < alloc; ++i)
if (entries[i])
- delete entries[i]->d()->identifier;
+ delete entries[i]->identifier;
free(entries);
}
-void IdentifierTable::addEntry(String *str)
+void IdentifierTable::addEntry(Heap::String *str)
{
uint hash = str->hashValue();
- if (str->subtype() == String::StringType_ArrayIndex)
+ if (str->subtype == Heap::String::StringType_ArrayIndex)
return;
- str->d()->identifier = new Identifier;
- str->d()->identifier->string = str->toQString();
- str->d()->identifier->hashValue = hash;
+ str->identifier = new Identifier;
+ str->identifier->string = str->toQString();
+ str->identifier->hashValue = hash;
bool grow = (alloc <= size*2);
if (grow) {
++numBits;
int newAlloc = primeForNumBits(numBits);
- String **newEntries = (String **)malloc(newAlloc*sizeof(String *));
- memset(newEntries, 0, newAlloc*sizeof(String *));
+ Heap::String **newEntries = (Heap::String **)malloc(newAlloc*sizeof(Heap::String *));
+ memset(newEntries, 0, newAlloc*sizeof(Heap::String *));
for (int i = 0; i < alloc; ++i) {
- String *e = entries[i];
+ Heap::String *e = entries[i];
if (!e)
continue;
- uint idx = e->d()->stringHash % newAlloc;
+ uint idx = e->stringHash % newAlloc;
while (newEntries[idx]) {
++idx;
idx %= newAlloc;
@@ -110,48 +110,48 @@ void IdentifierTable::addEntry(String *str)
-String *IdentifierTable::insertString(const QString &s)
+Heap::String *IdentifierTable::insertString(const QString &s)
{
uint hash = String::createHashValue(s.constData(), s.length());
uint idx = hash % alloc;
- while (String *e = entries[idx]) {
- if (e->d()->stringHash == hash && e->toQString() == s)
+ while (Heap::String *e = entries[idx]) {
+ if (e->stringHash == hash && e->toQString() == s)
return e;
++idx;
idx %= alloc;
}
- String *str = engine->newString(s)->getPointer();
+ Heap::String *str = engine->newString(s);
addEntry(str);
return str;
}
-Identifier *IdentifierTable::identifierImpl(const String *str)
+Identifier *IdentifierTable::identifierImpl(const Heap::String *str)
{
- if (str->d()->identifier)
- return str->d()->identifier;
+ if (str->identifier)
+ return str->identifier;
uint hash = str->hashValue();
- if (str->subtype() == String::StringType_ArrayIndex)
+ if (str->subtype == Heap::String::StringType_ArrayIndex)
return 0;
uint idx = hash % alloc;
- while (String *e = entries[idx]) {
- if (e->d()->stringHash == hash && e->isEqualTo(str)) {
- str->d()->identifier = e->d()->identifier;
- return e->d()->identifier;
+ while (Heap::String *e = entries[idx]) {
+ if (e->stringHash == hash && e->isEqualTo(str)) {
+ str->identifier = e->identifier;
+ return e->identifier;
}
++idx;
idx %= alloc;
}
- addEntry(const_cast<QV4::String *>(str));
- return str->d()->identifier;
+ addEntry(const_cast<QV4::Heap::String *>(str));
+ return str->identifier;
}
Identifier *IdentifierTable::identifier(const QString &s)
{
- return insertString(s)->d()->identifier;
+ return insertString(s)->identifier;
}
Identifier *IdentifierTable::identifier(const char *s, int len)
@@ -162,16 +162,16 @@ Identifier *IdentifierTable::identifier(const char *s, int len)
QLatin1String latin(s, len);
uint idx = hash % alloc;
- while (String *e = entries[idx]) {
- if (e->d()->stringHash == hash && e->toQString() == latin)
- return e->d()->identifier;
+ while (Heap::String *e = entries[idx]) {
+ if (e->stringHash == hash && e->toQString() == latin)
+ return e->identifier;
++idx;
idx %= alloc;
}
- String *str = engine->newString(QString::fromLatin1(s, len))->getPointer();
+ Heap::String *str = engine->newString(QString::fromLatin1(s, len));
addEntry(str);
- return str->d()->identifier;
+ return str->identifier;
}
}
diff --git a/src/qml/jsruntime/qv4identifiertable_p.h b/src/qml/jsruntime/qv4identifiertable_p.h
index 6ae2ec06d6..5d29d44dc0 100644
--- a/src/qml/jsruntime/qv4identifiertable_p.h
+++ b/src/qml/jsruntime/qv4identifiertable_p.h
@@ -49,36 +49,39 @@ struct IdentifierTable
int alloc;
int size;
int numBits;
- String **entries;
+ Heap::String **entries;
- void addEntry(String *str);
+ void addEntry(Heap::String *str);
public:
IdentifierTable(ExecutionEngine *engine);
~IdentifierTable();
- String *insertString(const QString &s);
+ Heap::String *insertString(const QString &s);
- Identifier *identifier(const String *str) {
- if (str->d()->identifier)
- return str->d()->identifier;
+ Identifier *identifier(const Heap::String *str) {
+ if (str->identifier)
+ return str->identifier;
return identifierImpl(str);
}
+ Identifier *identifier(const QV4::String *str) {
+ return identifier(str->d());
+ }
Identifier *identifier(const QString &s);
Identifier *identifier(const char *s, int len);
- Identifier *identifierImpl(const String *str);
+ Identifier *identifierImpl(const Heap::String *str);
void mark(ExecutionEngine *e) {
for (int i = 0; i < alloc; ++i) {
- String *entry = entries[i];
- if (!entry || entry->markBit())
+ Heap::String *entry = entries[i];
+ if (!entry || entry->isMarked())
continue;
- entry->d()->markBit = 1;
- Q_ASSERT(entry->internalClass()->vtable->markObjects);
- entry->internalClass()->vtable->markObjects(entry, e);
+ entry->setMarkBit();
+ Q_ASSERT(entry->gcGetInternalClass()->vtable->markObjects);
+ entry->gcGetInternalClass()->vtable->markObjects(entry, e);
}
}
};
diff --git a/src/qml/jsruntime/qv4include.cpp b/src/qml/jsruntime/qv4include.cpp
index 9d6a4ab10a..56e7717c26 100644
--- a/src/qml/jsruntime/qv4include.cpp
+++ b/src/qml/jsruntime/qv4include.cpp
@@ -49,17 +49,17 @@
QT_BEGIN_NAMESPACE
-QV4Include::QV4Include(const QUrl &url, QV8Engine *engine, QQmlContextData *context,
+QV4Include::QV4Include(const QUrl &url, QV4::ExecutionEngine *engine, QQmlContextData *context,
const QV4::ValueRef qmlglobal, const QV4::ValueRef callback)
- : v4(QV8Engine::getV4(engine)), m_network(0), m_reply(0), m_url(url), m_redirectCount(0), m_context(context)
+ : v4(engine), m_network(0), m_reply(0), m_url(url), m_redirectCount(0), m_context(context)
{
- m_qmlglobal = qmlglobal;
+ m_qmlglobal.set(engine, qmlglobal);
if (callback->asFunctionObject())
- m_callbackFunction = callback;
+ m_callbackFunction.set(engine, callback);
- m_resultObject = resultValue(v4);
+ m_resultObject.set(v4, resultValue(v4));
- m_network = engine->networkAccessManager();
+ m_network = engine->v8Engine->networkAccessManager();
QNetworkRequest request;
request.setUrl(url);
@@ -81,32 +81,31 @@ QV4::ReturnedValue QV4Include::resultValue(QV4::ExecutionEngine *v4, Status stat
QV4::ScopedObject o(scope, v4->newObject());
QV4::ScopedString s(scope);
QV4::ScopedValue v(scope);
- o->put((s = v4->newString(QStringLiteral("OK"))).getPointer(), (v = QV4::Primitive::fromInt32(Ok)));
- o->put((s = v4->newString(QStringLiteral("LOADING"))).getPointer(), (v = QV4::Primitive::fromInt32(Loading)));
- o->put((s = v4->newString(QStringLiteral("NETWORK_ERROR"))).getPointer(), (v = QV4::Primitive::fromInt32(NetworkError)));
- o->put((s = v4->newString(QStringLiteral("EXCEPTION"))).getPointer(), (v = QV4::Primitive::fromInt32(Exception)));
- o->put((s = v4->newString(QStringLiteral("status"))).getPointer(), (v = QV4::Primitive::fromInt32(status)));
+ o->put((s = v4->newString(QStringLiteral("OK"))), (v = QV4::Primitive::fromInt32(Ok)));
+ o->put((s = v4->newString(QStringLiteral("LOADING"))), (v = QV4::Primitive::fromInt32(Loading)));
+ o->put((s = v4->newString(QStringLiteral("NETWORK_ERROR"))), (v = QV4::Primitive::fromInt32(NetworkError)));
+ o->put((s = v4->newString(QStringLiteral("EXCEPTION"))), (v = QV4::Primitive::fromInt32(Exception)));
+ o->put((s = v4->newString(QStringLiteral("status"))), (v = QV4::Primitive::fromInt32(status)));
return o.asReturnedValue();
}
void QV4Include::callback(const QV4::ValueRef callback, const QV4::ValueRef status)
{
- QV4::ExecutionEngine *v4 = callback->engine();
- if (!v4)
+ if (!callback->isObject())
return;
+ QV4::ExecutionEngine *v4 = callback->asObject()->engine();
QV4::Scope scope(v4);
QV4::ScopedFunctionObject f(scope, callback);
if (!f)
return;
- QV4::ExecutionContext *ctx = v4->currentContext();
QV4::ScopedCallData callData(scope, 1);
- callData->thisObject = v4->globalObject->asReturnedValue();
+ callData->thisObject = v4->globalObject()->asReturnedValue();
callData->args[0] = status;
f->call(callData);
if (scope.hasException())
- ctx->catchException();
+ scope.engine->catchException();
}
QV4::ReturnedValue QV4Include::result()
@@ -136,6 +135,7 @@ void QV4Include::finished()
QV4::Scope scope(v4);
QV4::ScopedObject resultObj(scope, m_resultObject.value());
+ QV4::ScopedString status(scope, v4->newString(QStringLiteral("status")));
if (m_reply->error() == QNetworkReply::NoError) {
QByteArray data = m_reply->readAll();
@@ -145,20 +145,19 @@ void QV4Include::finished()
QV4::ScopedObject qmlglobal(scope, m_qmlglobal.value());
QV4::Script script(v4, qmlglobal, code, m_url.toString());
- QV4::ExecutionContext *ctx = v4->currentContext();
- QV4::ScopedString status(scope, v4->newString(QStringLiteral("status")));
script.parse();
if (!scope.engine->hasException)
script.run();
if (scope.engine->hasException) {
- QV4::ScopedValue ex(scope, ctx->catchException());
- resultObj->put(status.getPointer(), QV4::ScopedValue(scope, QV4::Primitive::fromInt32(Exception)));
- resultObj->put(v4->newString(QStringLiteral("exception"))->getPointer(), ex);
+ QV4::ScopedValue ex(scope, scope.engine->catchException());
+ resultObj->put(status, QV4::ScopedValue(scope, QV4::Primitive::fromInt32(Exception)));
+ QV4::ScopedString exception(scope, v4->newString(QStringLiteral("exception")));
+ resultObj->put(exception, ex);
} else {
- resultObj->put(status.getPointer(), QV4::ScopedValue(scope, QV4::Primitive::fromInt32(Ok)));
+ resultObj->put(status, QV4::ScopedValue(scope, QV4::Primitive::fromInt32(Ok)));
}
} else {
- resultObj->put(v4->newString(QStringLiteral("status"))->getPointer(), QV4::ScopedValue(scope, QV4::Primitive::fromInt32(NetworkError)));
+ resultObj->put(status, QV4::ScopedValue(scope, QV4::Primitive::fromInt32(NetworkError)));
}
QV4::ScopedValue cb(scope, m_callbackFunction.value());
@@ -177,7 +176,6 @@ QV4::ReturnedValue QV4Include::method_include(QV4::CallContext *ctx)
return QV4::Encode::undefined();
QV4::Scope scope(ctx->engine());
- QV8Engine *engine = scope.engine->v8Engine;
QQmlContextData *context = QV4::QmlContextWrapper::callingContext(scope.engine);
if (!context || !context->isJSContext)
@@ -195,7 +193,7 @@ QV4::ReturnedValue QV4Include::method_include(QV4::CallContext *ctx)
QV4::ScopedObject qmlcontextobject(scope, scope.engine->qmlContextObject());
if (localFile.isEmpty()) {
- QV4Include *i = new QV4Include(url, engine, context,
+ QV4Include *i = new QV4Include(url, scope.engine, context,
qmlcontextobject,
callbackFunction);
result = i->result();
@@ -219,14 +217,14 @@ QV4::ReturnedValue QV4Include::method_include(QV4::CallContext *ctx)
}
if (!script.isNull()) {
- QV4::ExecutionContext *ctx = scope.engine->currentContext();
script->parse();
if (!scope.engine->hasException)
script->run();
if (scope.engine->hasException) {
- QV4::ScopedValue ex(scope, ctx->catchException());
+ QV4::ScopedValue ex(scope, scope.engine->catchException());
result = resultValue(scope.engine, Exception);
- result->asObject()->put(scope.engine->newString(QStringLiteral("exception"))->getPointer(), ex);
+ QV4::ScopedString exception(scope, scope.engine->newString(QStringLiteral("exception")));
+ result->asObject()->put(exception, ex);
} else {
result = resultValue(scope.engine, Ok);
}
diff --git a/src/qml/jsruntime/qv4include_p.h b/src/qml/jsruntime/qv4include_p.h
index 71c09bc314..c6b153502f 100644
--- a/src/qml/jsruntime/qv4include_p.h
+++ b/src/qml/jsruntime/qv4include_p.h
@@ -76,7 +76,7 @@ private Q_SLOTS:
void finished();
private:
- QV4Include(const QUrl &url, QV8Engine *engine, QQmlContextData *context,
+ QV4Include(const QUrl &url, QV4::ExecutionEngine *engine, QQmlContextData *context,
const QV4::ValueRef qmlglobal, const QV4::ValueRef callback);
~QV4Include();
diff --git a/src/qml/jsruntime/qv4internalclass.cpp b/src/qml/jsruntime/qv4internalclass.cpp
index bb22e30ac1..2115ee09a0 100644
--- a/src/qml/jsruntime/qv4internalclass.cpp
+++ b/src/qml/jsruntime/qv4internalclass.cpp
@@ -40,14 +40,6 @@
QT_BEGIN_NAMESPACE
-uint QV4::qHash(const QV4::InternalClassTransition &t, uint)
-{
- if (t.flags == QV4::InternalClassTransition::ProtoChange)
- // INT_MAX is prime, so this should give a decent distribution of keys
- return (uint)((quintptr)t.prototype * INT_MAX);
- return t.id->hashValue ^ t.flags;
-}
-
using namespace QV4;
static const uchar prime_deltas[] = {
@@ -120,11 +112,11 @@ uint PropertyHash::lookup(const Identifier *identifier) const
InternalClass::InternalClass(ExecutionEngine *engine)
: engine(engine)
- , prototype(0)
, vtable(&QV4::Managed::static_vtbl)
, m_sealed(0)
, m_frozen(0)
, size(0)
+ , extensible(true)
{
}
@@ -132,39 +124,50 @@ InternalClass::InternalClass(ExecutionEngine *engine)
InternalClass::InternalClass(const QV4::InternalClass &other)
: QQmlJS::Managed()
, engine(other.engine)
- , prototype(other.prototype)
, vtable(other.vtable)
, propertyTable(other.propertyTable)
, nameMap(other.nameMap)
, propertyData(other.propertyData)
- , transitions()
, m_sealed(0)
, m_frozen(0)
, size(other.size)
+ , extensible(other.extensible)
{
+ Q_ASSERT(extensible);
}
void InternalClass::changeMember(Object *object, String *string, PropertyAttributes data, uint *index)
{
uint idx;
- InternalClass *newClass = object->internalClass()->changeMember(string, data, &idx);
+ InternalClass *newClass = object->internalClass()->changeMember(string->identifier(), data, &idx);
if (index)
*index = idx;
if (newClass->size > object->internalClass()->size) {
Q_ASSERT(newClass->size == object->internalClass()->size + 1);
- memmove(object->memberData().data() + idx + 2, object->memberData().data() + idx + 1, (object->internalClass()->size - idx - 1)*sizeof(Value));
+ memmove(object->memberData()->data + idx + 2, object->memberData()->data + idx + 1, (object->internalClass()->size - idx - 1)*sizeof(Value));
} else if (newClass->size < object->internalClass()->size) {
Q_ASSERT(newClass->size == object->internalClass()->size - 1);
- memmove(object->memberData().data() + idx + 1, object->memberData().data() + idx + 2, (object->internalClass()->size - idx - 2)*sizeof(Value));
+ memmove(object->memberData()->data + idx + 1, object->memberData()->data + idx + 2, (object->internalClass()->size - idx - 2)*sizeof(Value));
}
object->setInternalClass(newClass);
}
-InternalClass *InternalClass::changeMember(String *string, PropertyAttributes data, uint *index)
+InternalClassTransition &InternalClass::lookupOrInsertTransition(const InternalClassTransition &t)
+{
+ std::vector<Transition>::iterator it = std::lower_bound(transitions.begin(), transitions.end(), t);
+ if (it != transitions.end() && *it == t) {
+ return *it;
+ } else {
+ it = transitions.insert(it, t);
+ return *it;
+ }
+}
+
+InternalClass *InternalClass::changeMember(Identifier *identifier, PropertyAttributes data, uint *index)
{
data.resolve();
- uint idx = find(string);
+ uint idx = find(identifier);
Q_ASSERT(idx != UINT_MAX);
if (index)
@@ -173,14 +176,13 @@ InternalClass *InternalClass::changeMember(String *string, PropertyAttributes da
if (data == propertyData.at(idx))
return this;
- Transition t = { { string->d()->identifier }, (int)data.flags() };
- QHash<Transition, InternalClass *>::const_iterator tit = transitions.constFind(t);
- if (tit != transitions.constEnd())
- return tit.value();
+ Transition temp = { { identifier }, 0, (int)data.flags() };
+ Transition &t = lookupOrInsertTransition(temp);
+ if (t.lookup)
+ return t.lookup;
// create a new class and add it to the tree
InternalClass *newClass = engine->emptyClass->changeVTable(vtable);
- newClass = newClass->changePrototype(prototype);
for (uint i = 0; i < size; ++i) {
if (i == idx) {
newClass = newClass->addMember(nameMap.at(i), data);
@@ -189,77 +191,64 @@ InternalClass *InternalClass::changeMember(String *string, PropertyAttributes da
}
}
- transitions.insert(t, newClass);
+ t.lookup = newClass;
return newClass;
}
-InternalClass *InternalClass::create(ExecutionEngine *engine, const ManagedVTable *vtable, Object *proto)
+InternalClass *InternalClass::create(ExecutionEngine *engine, const ManagedVTable *vtable)
{
- InternalClass *c = engine->emptyClass->changeVTable(vtable);
- if (!proto)
- return c;
- return c->changePrototype(proto);
+ return engine->emptyClass->changeVTable(vtable);
}
-InternalClass *InternalClass::changePrototype(Object *proto)
+InternalClass *InternalClass::changeVTable(const ManagedVTable *vt)
{
- if (prototype == proto)
+ if (vtable == vt)
return this;
- Transition t;
- t.prototype = proto;
- t.flags = Transition::ProtoChange;
+ Transition temp;
+ temp.vtable = vt;
+ temp.lookup = 0;
+ temp.flags = Transition::VTableChange;
- QHash<Transition, InternalClass *>::const_iterator tit = transitions.constFind(t);
- if (tit != transitions.constEnd())
- return tit.value();
+ Transition &t = lookupOrInsertTransition(temp);
+ if (t.lookup)
+ return t.lookup;
// create a new class and add it to the tree
InternalClass *newClass;
- if (!size) {
+ if (this == engine->emptyClass) {
newClass = engine->newClass(*this);
- newClass->prototype = proto;
+ newClass->vtable = vt;
} else {
- newClass = engine->emptyClass->changeVTable(vtable);
- newClass = newClass->changePrototype(proto);
+ newClass = engine->emptyClass->changeVTable(vt);
for (uint i = 0; i < size; ++i) {
if (!propertyData.at(i).isEmpty())
newClass = newClass->addMember(nameMap.at(i), propertyData.at(i));
}
}
- transitions.insert(t, newClass);
+ t.lookup = newClass;
return newClass;
}
-InternalClass *InternalClass::changeVTable(const ManagedVTable *vt)
+InternalClass *InternalClass::nonExtensible()
{
- if (vtable == vt)
+ if (!extensible)
return this;
- Transition t;
- t.vtable = vt;
- t.flags = Transition::VTableChange;
+ Transition temp;
+ temp.vtable = 0;
+ temp.lookup = 0;
+ temp.flags = Transition::NotExtensible;
- QHash<Transition, InternalClass *>::const_iterator tit = transitions.constFind(t);
- if (tit != transitions.constEnd())
- return tit.value();
+ Transition &t = lookupOrInsertTransition(temp);
+ if (t.lookup)
+ return t.lookup;
- // create a new class and add it to the tree
- InternalClass *newClass;
- if (this == engine->emptyClass) {
- newClass = engine->newClass(*this);
- newClass->vtable = vt;
- } else {
- newClass = engine->emptyClass->changeVTable(vt);
- newClass = newClass->changePrototype(prototype);
- for (uint i = 0; i < size; ++i) {
- if (!propertyData.at(i).isEmpty())
- newClass = newClass->addMember(nameMap.at(i), propertyData.at(i));
- }
- }
+ InternalClass *newClass = engine->newClass(*this);
+ newClass->extensible = false;
- transitions.insert(t, newClass);
+ t.lookup = newClass;
return newClass;
}
@@ -273,45 +262,46 @@ void InternalClass::addMember(Object *object, String *string, PropertyAttributes
}
uint idx;
- InternalClass *newClass = object->internalClass()->addMemberImpl(string, data, &idx);
+ InternalClass *newClass = object->internalClass()->addMemberImpl(string->identifier(), data, &idx);
if (index)
*index = idx;
object->setInternalClass(newClass);
}
-
InternalClass *InternalClass::addMember(String *string, PropertyAttributes data, uint *index)
{
- data.resolve();
engine->identifierTable->identifier(string);
+ return addMember(string->identifier(), data, index);
+}
- if (propertyTable.lookup(string->d()->identifier) < size)
- return changeMember(string, data, index);
+InternalClass *InternalClass::addMember(Identifier *identifier, PropertyAttributes data, uint *index)
+{
+ data.resolve();
+
+ if (propertyTable.lookup(identifier) < size)
+ return changeMember(identifier, data, index);
- return addMemberImpl(string, data, index);
+ return addMemberImpl(identifier, data, index);
}
-InternalClass *InternalClass::addMemberImpl(String *string, PropertyAttributes data, uint *index)
+InternalClass *InternalClass::addMemberImpl(Identifier *identifier, PropertyAttributes data, uint *index)
{
- Transition t = { { string->d()->identifier }, (int)data.flags() };
- QHash<Transition, InternalClass *>::const_iterator tit = transitions.constFind(t);
+ Transition temp = { { identifier }, 0, (int)data.flags() };
+ Transition &t = lookupOrInsertTransition(temp);
if (index)
*index = size;
- if (tit != transitions.constEnd())
- return tit.value();
+
+ if (t.lookup)
+ return t.lookup;
// create a new class and add it to the tree
InternalClass *newClass = engine->newClass(*this);
- PropertyHash::Entry e = { string->d()->identifier, newClass->size };
+ PropertyHash::Entry e = { identifier, newClass->size };
newClass->propertyTable.addEntry(e, newClass->size);
- // The incoming string can come from anywhere, so make sure to
- // store a string in the nameMap that's guaranteed to get
- // marked properly during GC.
- String *name = engine->newIdentifier(string->toQString());
- newClass->nameMap.add(newClass->size, name);
+ newClass->nameMap.add(newClass->size, identifier);
newClass->propertyData.add(newClass->size, data);
++newClass->size;
if (data.isAccessor()) {
@@ -322,7 +312,7 @@ InternalClass *InternalClass::addMemberImpl(String *string, PropertyAttributes d
++newClass->size;
}
- transitions.insert(t, newClass);
+ t.lookup = newClass;
return newClass;
}
@@ -332,15 +322,14 @@ void InternalClass::removeMember(Object *object, Identifier *id)
uint propIdx = oldClass->propertyTable.lookup(id);
Q_ASSERT(propIdx < oldClass->size);
- Transition t = { { id } , -1 };
- QHash<Transition, InternalClass *>::const_iterator tit = object->internalClass()->transitions.constFind(t);
+ Transition t = { { id }, 0, -1 };
+ t = object->internalClass()->lookupOrInsertTransition(t); // take a copy
- if (tit != object->internalClass()->transitions.constEnd()) {
- object->setInternalClass(tit.value());
+ if (t.lookup) {
+ object->setInternalClass(t.lookup);
} else {
// create a new class and add it to the tree
InternalClass *newClass = oldClass->engine->emptyClass->changeVTable(oldClass->vtable);
- newClass = newClass->changePrototype(oldClass->prototype);
for (uint i = 0; i < oldClass->size; ++i) {
if (i == propIdx)
continue;
@@ -351,9 +340,10 @@ void InternalClass::removeMember(Object *object, Identifier *id)
}
// remove the entry in memberdata
- memmove(object->memberData().data() + propIdx, object->memberData().data() + propIdx + 1, (object->internalClass()->size - propIdx)*sizeof(Value));
+ memmove(object->memberData()->data + propIdx, object->memberData()->data + propIdx + 1, (object->internalClass()->size - propIdx)*sizeof(Value));
- oldClass->transitions.insert(t, object->internalClass());
+ t.lookup = object->internalClass();
+ oldClass->lookupOrInsertTransition(t);
}
uint InternalClass::find(const String *string)
@@ -368,6 +358,15 @@ uint InternalClass::find(const String *string)
return UINT_MAX;
}
+uint InternalClass::find(const Identifier *id)
+{
+ uint index = propertyTable.lookup(id);
+ if (index < size)
+ return index;
+
+ return UINT_MAX;
+}
+
InternalClass *InternalClass::sealed()
{
if (m_sealed)
@@ -375,7 +374,6 @@ InternalClass *InternalClass::sealed()
m_sealed = engine->emptyClass;
m_sealed = m_sealed->changeVTable(vtable);
- m_sealed = m_sealed->changePrototype(prototype);
for (uint i = 0; i < size; ++i) {
PropertyAttributes attrs = propertyData.at(i);
if (attrs.isEmpty())
@@ -383,6 +381,7 @@ InternalClass *InternalClass::sealed()
attrs.setConfigurable(false);
m_sealed = m_sealed->addMember(nameMap.at(i), attrs);
}
+ m_sealed = m_sealed->nonExtensible();
m_sealed->m_sealed = m_sealed;
return m_sealed;
@@ -395,7 +394,6 @@ InternalClass *InternalClass::frozen()
m_frozen = engine->emptyClass;
m_frozen = m_frozen->changeVTable(vtable);
- m_frozen = m_frozen->changePrototype(prototype);
for (uint i = 0; i < size; ++i) {
PropertyAttributes attrs = propertyData.at(i);
if (attrs.isEmpty())
@@ -404,6 +402,7 @@ InternalClass *InternalClass::frozen()
attrs.setConfigurable(false);
m_frozen = m_frozen->addMember(nameMap.at(i), attrs);
}
+ m_frozen = m_frozen->nonExtensible();
m_frozen->m_frozen = m_frozen;
m_frozen->m_sealed = m_frozen;
@@ -421,35 +420,24 @@ void InternalClass::destroy()
continue;
next->engine = 0;
next->propertyTable.~PropertyHash();
- next->nameMap.~SharedInternalClassData<String *>();
+ next->nameMap.~SharedInternalClassData<Identifier *>();
next->propertyData.~SharedInternalClassData<PropertyAttributes>();
if (next->m_sealed)
destroyStack.append(next->m_sealed);
if (next->m_frozen)
destroyStack.append(next->m_frozen);
- destroyStack.append(next->transitions.values());
+
+ for (size_t i = 0; i < transitions.size(); ++i) {
+ destroyStack.append(next->transitions.at(i).lookup);
+ }
+
next->transitions.clear();
}
}
-struct InternalClassPoolVisitor
-{
- ExecutionEngine *engine;
- void operator()(InternalClass *klass)
- {
- // all prototype changes are done on the empty class
- Q_ASSERT(!klass->prototype || klass != engine->emptyClass);
-
- if (klass->prototype)
- klass->prototype->mark(engine);
- }
-};
-
void InternalClassPool::markObjects(ExecutionEngine *engine)
{
- InternalClassPoolVisitor v;
- v.engine = engine;
- visitManagedPool<InternalClass, InternalClassPoolVisitor>(v);
+ Q_UNUSED(engine);
}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4internalclass_p.h b/src/qml/jsruntime/qv4internalclass_p.h
index 06feea1d5a..b92bee3fac 100644
--- a/src/qml/jsruntime/qv4internalclass_p.h
+++ b/src/qml/jsruntime/qv4internalclass_p.h
@@ -33,9 +33,9 @@
#ifndef QV4INTERNALCLASS_H
#define QV4INTERNALCLASS_H
-#include <QHash>
-#include <QVector>
#include "qv4global_p.h"
+
+#include <QHash>
#include <private/qqmljsmemorypool_p.h>
QT_BEGIN_NAMESPACE
@@ -191,47 +191,52 @@ struct InternalClassTransition
{
union {
Identifier *id;
- Object *prototype;
const ManagedVTable *vtable;
};
+ InternalClass *lookup;
int flags;
enum {
// range 0-0xff is reserved for attribute changes
- ProtoChange = 0x100,
- VTableChange = 0x200
+ VTableChange = 0x100,
+ NotExtensible = 0x200
};
bool operator==(const InternalClassTransition &other) const
{ return id == other.id && flags == other.flags; }
+
+ bool operator<(const InternalClassTransition &other) const
+ { return id < other.id; }
};
-uint qHash(const QV4::InternalClassTransition &t, uint = 0);
struct InternalClass : public QQmlJS::Managed {
ExecutionEngine *engine;
- Object *prototype;
const ManagedVTable *vtable;
PropertyHash propertyTable; // id to valueIndex
- SharedInternalClassData<String *> nameMap;
+ SharedInternalClassData<Identifier *> nameMap;
SharedInternalClassData<PropertyAttributes> propertyData;
typedef InternalClassTransition Transition;
- QHash<Transition, InternalClass *> transitions; // id to next class, positive means add, negative delete
+ std::vector<Transition> transitions;
+ InternalClassTransition &lookupOrInsertTransition(const InternalClassTransition &t);
InternalClass *m_sealed;
InternalClass *m_frozen;
uint size;
+ bool extensible;
- static InternalClass *create(ExecutionEngine *engine, const ManagedVTable *vtable, Object *proto);
- InternalClass *changePrototype(Object *proto);
+ static InternalClass *create(ExecutionEngine *engine, const ManagedVTable *vtable);
InternalClass *changeVTable(const ManagedVTable *vt);
+ InternalClass *nonExtensible();
static void addMember(Object *object, String *string, PropertyAttributes data, uint *index);
InternalClass *addMember(String *string, PropertyAttributes data, uint *index = 0);
- InternalClass *changeMember(String *string, PropertyAttributes data, uint *index = 0);
+ InternalClass *addMember(Identifier *identifier, PropertyAttributes data, uint *index = 0);
+ InternalClass *changeMember(Identifier *identifier, PropertyAttributes data, uint *index = 0);
static void changeMember(Object *object, String *string, PropertyAttributes data, uint *index = 0);
static void removeMember(Object *object, Identifier *id);
uint find(const String *s);
+ uint find(const Identifier *id);
InternalClass *sealed();
InternalClass *frozen();
@@ -239,7 +244,7 @@ struct InternalClass : public QQmlJS::Managed {
void destroy();
private:
- InternalClass *addMemberImpl(String *string, PropertyAttributes data, uint *index);
+ InternalClass *addMemberImpl(Identifier *identifier, PropertyAttributes data, uint *index);
friend struct ExecutionEngine;
InternalClass(ExecutionEngine *engine);
InternalClass(const InternalClass &other);
diff --git a/src/qml/jsruntime/qv4jsonobject.cpp b/src/qml/jsruntime/qv4jsonobject.cpp
index 268559dec8..0de2aa7e3b 100644
--- a/src/qml/jsruntime/qv4jsonobject.cpp
+++ b/src/qml/jsruntime/qv4jsonobject.cpp
@@ -37,6 +37,8 @@
#include <qv4booleanobject_p.h>
#include <qv4objectiterator_p.h>
#include <qv4scopedvalue_p.h>
+#include <qv4runtime_p.h>
+
#include <qjsondocument.h>
#include <qstack.h>
#include <qstringlist.h>
@@ -63,7 +65,7 @@ DEFINE_OBJECT_VTABLE(JsonObject);
class JsonParser
{
public:
- JsonParser(ExecutionContext *context, const QChar *json, int length);
+ JsonParser(ExecutionEngine *engine, const QChar *json, int length);
ReturnedValue parse(QJsonParseError *error);
@@ -78,7 +80,7 @@ private:
bool parseValue(ValueRef val);
bool parseNumber(ValueRef val);
- ExecutionContext *context;
+ ExecutionEngine *engine;
const QChar *head;
const QChar *json;
const QChar *end;
@@ -90,8 +92,8 @@ private:
static const int nestingLimit = 1024;
-JsonParser::JsonParser(ExecutionContext *context, const QChar *json, int length)
- : context(context), head(json), json(json), nestingLevel(0), lastError(QJsonParseError::NoError)
+JsonParser::JsonParser(ExecutionEngine *engine, const QChar *json, int length)
+ : engine(engine), head(json), json(json), nestingLevel(0), lastError(QJsonParseError::NoError)
{
end = json + length;
}
@@ -187,7 +189,7 @@ ReturnedValue JsonParser::parse(QJsonParseError *error)
eatSpace();
- Scope scope(context);
+ Scope scope(engine);
ScopedValue v(scope);
if (!parseValue(v)) {
#ifdef PARSER_DEBUG
@@ -227,9 +229,9 @@ ReturnedValue JsonParser::parseObject()
}
BEGIN << "parseObject pos=" << json;
- Scope scope(context);
+ Scope scope(engine);
- ScopedObject o(scope, context->d()->engine->newObject());
+ ScopedObject o(scope, engine->newObject());
QChar token = nextToken();
while (token == Quote) {
@@ -263,7 +265,7 @@ ReturnedValue JsonParser::parseObject()
bool JsonParser::parseMember(Object *o)
{
BEGIN << "parseMember";
- Scope scope(context);
+ Scope scope(engine);
QString key;
if (!parseString(&key))
@@ -277,12 +279,12 @@ bool JsonParser::parseMember(Object *o)
if (!parseValue(val))
return false;
- ScopedString s(scope, context->d()->engine->newIdentifier(key));
+ ScopedString s(scope, engine->newIdentifier(key));
uint idx = s->asArrayIndex();
if (idx < UINT_MAX) {
o->putIndexed(idx, val);
} else {
- o->insertMember(s.getPointer(), val);
+ o->insertMember(s, val);
}
END;
@@ -294,9 +296,9 @@ bool JsonParser::parseMember(Object *o)
*/
ReturnedValue JsonParser::parseArray()
{
- Scope scope(context);
+ Scope scope(engine);
BEGIN << "parseArray";
- Scoped<ArrayObject> array(scope, context->d()->engine->newArrayObject());
+ ScopedArrayObject array(scope, engine->newArrayObject());
if (++nestingLevel > nestingLimit) {
lastError = QJsonParseError::DeepNesting;
@@ -399,7 +401,7 @@ bool JsonParser::parseValue(ValueRef val)
return false;
DEBUG << "value: string";
END;
- val = context->d()->engine->newString(value);
+ val = Value::fromHeapObject(engine->newString(value));
return true;
}
case BeginArray: {
@@ -639,11 +641,13 @@ struct Stringify
{
ExecutionContext *ctx;
FunctionObject *replacerFunction;
- QVector<String *> propertyList;
+ // ### GC
+ QVector<Heap::String *> propertyList;
QString gap;
QString indent;
- QStack<Object *> stack;
+ // ### GC
+ QStack<Heap::Object *> stack;
Stringify(ExecutionContext *ctx) : ctx(ctx), replacerFunction(0) {}
@@ -703,7 +707,7 @@ QString Stringify::Str(const QString &key, ValueRef v)
ScopedObject o(scope, value);
if (o) {
ScopedString s(scope, ctx->d()->engine->newString(QStringLiteral("toJSON")));
- Scoped<FunctionObject> toJSON(scope, o->get(s.getPointer()));
+ ScopedFunctionObject toJSON(scope, o->get(s));
if (!!toJSON) {
ScopedCallData callData(scope, 1);
callData->thisObject = value;
@@ -714,7 +718,7 @@ QString Stringify::Str(const QString &key, ValueRef v)
if (replacerFunction) {
ScopedObject holder(scope, ctx->d()->engine->newObject());
- holder->put(ctx, QString(), value);
+ holder->put(scope.engine, QString(), value);
ScopedCallData callData(scope, 2);
callData->args[0] = ctx->d()->engine->newString(key);
callData->args[1] = value;
@@ -741,7 +745,7 @@ QString Stringify::Str(const QString &key, ValueRef v)
if (value->isNumber()) {
double d = value->toNumber();
- return std::isfinite(d) ? value->toString(ctx)->toQString() : QStringLiteral("null");
+ return std::isfinite(d) ? value->toQString() : QStringLiteral("null");
}
o = value.asReturnedValue();
@@ -774,15 +778,15 @@ QString Stringify::makeMember(const QString &key, ValueRef v)
QString Stringify::JO(Object *o)
{
- if (stack.contains(o)) {
- ctx->throwTypeError();
+ if (stack.contains(o->d())) {
+ ctx->engine()->throwTypeError();
return QString();
}
Scope scope(ctx);
QString result;
- stack.push(o);
+ stack.push(o->d());
QString stepback = indent;
indent += gap;
@@ -806,7 +810,7 @@ QString Stringify::JO(Object *o)
for (int i = 0; i < propertyList.size(); ++i) {
bool exists;
s = propertyList.at(i);
- ScopedValue v(scope, o->get(s.getPointer(), &exists));
+ ScopedValue v(scope, o->get(s, &exists));
if (!exists)
continue;
QString member = makeMember(s->toQString(), v);
@@ -831,15 +835,15 @@ QString Stringify::JO(Object *o)
QString Stringify::JA(ArrayObject *a)
{
- if (stack.contains(a)) {
- ctx->throwTypeError();
+ if (stack.contains(a->d())) {
+ ctx->engine()->throwTypeError();
return QString();
}
Scope scope(a->engine());
QString result;
- stack.push(a);
+ stack.push(a->d());
QString stepback = indent;
indent += gap;
@@ -875,14 +879,14 @@ QString Stringify::JA(ArrayObject *a)
}
-JsonObject::Data::Data(InternalClass *ic)
- : Object::Data(ic)
+Heap::JsonObject::JsonObject(ExecutionEngine *e)
+ : Heap::Object(QV4::InternalClass::create(e, QV4::JsonObject::staticVTable()), e->objectPrototype.asObject())
{
- Scope scope(ic->engine);
+ Scope scope(e);
ScopedObject o(scope, this);
- o->defineDefaultProperty(QStringLiteral("parse"), method_parse, 2);
- o->defineDefaultProperty(QStringLiteral("stringify"), method_stringify, 3);
+ o->defineDefaultProperty(QStringLiteral("parse"), QV4::JsonObject::method_parse, 2);
+ o->defineDefaultProperty(QStringLiteral("stringify"), QV4::JsonObject::method_stringify, 3);
}
@@ -890,15 +894,15 @@ ReturnedValue JsonObject::method_parse(CallContext *ctx)
{
Scope scope(ctx);
ScopedValue v(scope, ctx->argument(0));
- QString jtext = v->toString(ctx)->toQString();
+ QString jtext = v->toQString();
DEBUG << "parsing source = " << jtext;
- JsonParser parser(ctx, jtext.constData(), jtext.length());
+ JsonParser parser(scope.engine, jtext.constData(), jtext.length());
QJsonParseError error;
ScopedValue result(scope, parser.parse(&error));
if (error.error != QJsonParseError::NoError) {
DEBUG << "parse error" << error.errorString();
- return ctx->throwSyntaxError(QStringLiteral("JSON.parse: Parse error"));
+ return ctx->engine()->throwSyntaxError(QStringLiteral("JSON.parse: Parse error"));
}
return result.asReturnedValue();
@@ -910,7 +914,7 @@ ReturnedValue JsonObject::method_stringify(CallContext *ctx)
Stringify stringify(ctx);
- Scoped<Object> o(scope, ctx->argument(1));
+ ScopedObject o(scope, ctx->argument(1));
if (o) {
stringify.replacerFunction = o->asFunctionObject();
if (o->isArrayObject()) {
@@ -919,11 +923,11 @@ ReturnedValue JsonObject::method_stringify(CallContext *ctx)
for (uint i = 0; i < arrayLen; ++i) {
v = o->getIndexed(i);
if (v->asNumberObject() || v->asStringObject() || v->isNumber())
- v = RuntimeHelpers::toString(ctx, v);
+ v = RuntimeHelpers::toString(scope.engine, v);
if (v->isString()) {
String *s = v->stringValue();
- if (!stringify.propertyList.contains(s))
- stringify.propertyList.append(s);
+ if (!stringify.propertyList.contains(s->d()))
+ stringify.propertyList.append(s->d());
}
}
}
@@ -954,7 +958,7 @@ ReturnedValue JsonObject::method_stringify(CallContext *ctx)
ReturnedValue JsonObject::fromJsonValue(ExecutionEngine *engine, const QJsonValue &value)
{
if (value.isString())
- return engine->currentContext()->d()->engine->newString(value.toString())->asReturnedValue();
+ return engine->currentContext()->engine->newString(value.toString())->asReturnedValue();
else if (value.isDouble())
return Encode(value.toDouble());
else if (value.isBool())
@@ -980,9 +984,11 @@ QJsonValue JsonObject::toJsonValue(const ValueRef value,
return QJsonValue(QJsonValue::Null);
else if (value->isUndefined())
return QJsonValue(QJsonValue::Undefined);
+ else if (value->isString())
+ return QJsonValue(value->toQString());
- Q_ASSERT(value->engine());
- Scope scope(value->engine());
+ Q_ASSERT(value->isObject());
+ Scope scope(value->asObject()->engine());
ScopedArrayObject a(scope, value);
if (a)
return toJsonArray(a, visitedObjects);
@@ -995,12 +1001,12 @@ QJsonValue JsonObject::toJsonValue(const ValueRef value,
QV4::ReturnedValue JsonObject::fromJsonObject(ExecutionEngine *engine, const QJsonObject &object)
{
Scope scope(engine);
- Scoped<Object> o(scope, engine->newObject());
+ ScopedObject o(scope, engine->newObject());
ScopedString s(scope);
ScopedValue v(scope);
for (QJsonObject::const_iterator it = object.begin(); it != object.end(); ++it) {
v = fromJsonValue(engine, it.value());
- o->put((s = engine->newString(it.key())).getPointer(), v);
+ o->put((s = engine->newString(it.key())), v);
}
return o.asReturnedValue();
}
@@ -1013,14 +1019,14 @@ QJsonObject JsonObject::toJsonObject(Object *o, V4ObjectSet &visitedObjects)
Scope scope(o->engine());
- if (visitedObjects.contains(o)) {
+ if (visitedObjects.contains(o->d())) {
// Avoid recursion.
// For compatibility with QVariant{List,Map} conversion, we return an
// empty object (and no error is thrown).
return result;
}
- visitedObjects.insert(o);
+ visitedObjects.insert(o->d());
ObjectIterator it(scope, o, ObjectIterator::EnumerableOnly);
ScopedValue name(scope);
@@ -1035,7 +1041,7 @@ QJsonObject JsonObject::toJsonObject(Object *o, V4ObjectSet &visitedObjects)
result.insert(key, toJsonValue(val, visitedObjects));
}
- visitedObjects.remove(o);
+ visitedObjects.remove(o->d());
return result;
}
@@ -1044,7 +1050,7 @@ QV4::ReturnedValue JsonObject::fromJsonArray(ExecutionEngine *engine, const QJso
{
Scope scope(engine);
int size = array.size();
- Scoped<ArrayObject> a(scope, engine->newArrayObject());
+ ScopedArrayObject a(scope, engine->newArrayObject());
a->arrayReserve(size);
ScopedValue v(scope);
for (int i = 0; i < size; i++)
@@ -1061,14 +1067,14 @@ QJsonArray JsonObject::toJsonArray(ArrayObject *a, V4ObjectSet &visitedObjects)
Scope scope(a->engine());
- if (visitedObjects.contains(a)) {
+ if (visitedObjects.contains(a->d())) {
// Avoid recursion.
// For compatibility with QVariant{List,Map} conversion, we return an
// empty array (and no error is thrown).
return result;
}
- visitedObjects.insert(a);
+ visitedObjects.insert(a->d());
ScopedValue v(scope);
quint32 length = a->getLength();
@@ -1079,7 +1085,7 @@ QJsonArray JsonObject::toJsonArray(ArrayObject *a, V4ObjectSet &visitedObjects)
result.append(toJsonValue(v, visitedObjects));
}
- visitedObjects.remove(a);
+ visitedObjects.remove(a->d());
return result;
}
diff --git a/src/qml/jsruntime/qv4jsonobject_p.h b/src/qml/jsruntime/qv4jsonobject_p.h
index 6b9840156d..32d890c488 100644
--- a/src/qml/jsruntime/qv4jsonobject_p.h
+++ b/src/qml/jsruntime/qv4jsonobject_p.h
@@ -42,14 +42,20 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
+namespace Heap {
+
+struct JsonObject : Object {
+ JsonObject(ExecutionEngine *e);
+};
+
+}
+
struct JsonObject : Object {
- struct Data : Object::Data {
- Data(InternalClass *ic);
- };
Q_MANAGED_TYPE(JsonObject)
- V4_OBJECT(Object)
+ V4_OBJECT2(JsonObject, Object)
private:
- typedef QSet<QV4::Object *> V4ObjectSet;
+ // ### GC
+ typedef QSet<QV4::Heap::Base *> V4ObjectSet;
public:
static ReturnedValue method_parse(CallContext *ctx);
diff --git a/src/qml/jsruntime/qv4lookup.cpp b/src/qml/jsruntime/qv4lookup.cpp
index 254666eca2..c0297696db 100644
--- a/src/qml/jsruntime/qv4lookup.cpp
+++ b/src/qml/jsruntime/qv4lookup.cpp
@@ -39,63 +39,68 @@ QT_BEGIN_NAMESPACE
using namespace QV4;
-ReturnedValue Lookup::lookup(ValueRef thisObject, Object *obj, PropertyAttributes *attrs)
+ReturnedValue Lookup::lookup(ValueRef thisObject, Object *o, PropertyAttributes *attrs)
{
+ ExecutionEngine *engine = o->engine();
+ Identifier *name = engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]->identifier;
int i = 0;
+ Heap::Object *obj = o->d();
while (i < Size && obj) {
- classList[i] = obj->internalClass();
+ classList[i] = obj->internalClass;
- index = obj->internalClass()->find(name);
+ index = obj->internalClass->find(name);
if (index != UINT_MAX) {
level = i;
- *attrs = obj->internalClass()->propertyData.at(index);
- return !attrs->isAccessor() ? obj->memberData()[index].asReturnedValue() : obj->getValue(thisObject, obj->propertyAt(index), *attrs);
+ *attrs = obj->internalClass->propertyData.at(index);
+ return !attrs->isAccessor() ? obj->memberData->data[index].asReturnedValue() : Object::getValue(thisObject, obj->propertyAt(index), *attrs);
}
- obj = obj->prototype();
+ obj = obj->prototype;
++i;
}
level = Size;
while (obj) {
- index = obj->internalClass()->find(name);
+ index = obj->internalClass->find(name);
if (index != UINT_MAX) {
- *attrs = obj->internalClass()->propertyData.at(index);
- return !attrs->isAccessor() ? obj->memberData()[index].asReturnedValue() : obj->getValue(thisObject, obj->propertyAt(index), *attrs);
+ *attrs = obj->internalClass->propertyData.at(index);
+ return !attrs->isAccessor() ? obj->memberData->data[index].asReturnedValue() : Object::getValue(thisObject, obj->propertyAt(index), *attrs);
}
- obj = obj->prototype();
+ obj = obj->prototype;
}
return Primitive::emptyValue().asReturnedValue();
}
-ReturnedValue Lookup::lookup(Object *obj, PropertyAttributes *attrs)
+ReturnedValue Lookup::lookup(Object *thisObject, PropertyAttributes *attrs)
{
- Object *thisObject = obj;
+ Heap::Object *obj = thisObject->d();
+ ExecutionEngine *engine = thisObject->engine();
+ Identifier *name = engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]->identifier;
int i = 0;
while (i < Size && obj) {
- classList[i] = obj->internalClass();
+ classList[i] = obj->internalClass;
- index = obj->internalClass()->find(name);
+ index = obj->internalClass->find(name);
if (index != UINT_MAX) {
level = i;
- *attrs = obj->internalClass()->propertyData.at(index);
- return !attrs->isAccessor() ? obj->memberData()[index].asReturnedValue() : thisObject->getValue(obj->propertyAt(index), *attrs);
+ *attrs = obj->internalClass->propertyData.at(index);
+ return !attrs->isAccessor() ? obj->memberData->data[index].asReturnedValue() : thisObject->getValue(obj->propertyAt(index), *attrs);
}
- obj = obj->prototype();
+ obj = obj->prototype;
++i;
}
level = Size;
while (obj) {
- index = obj->internalClass()->find(name);
+ index = obj->internalClass->find(name);
if (index != UINT_MAX) {
- *attrs = obj->internalClass()->propertyData.at(index);
- return !attrs->isAccessor() ? obj->memberData()[index].asReturnedValue() : thisObject->getValue(obj->propertyAt(index), *attrs);
+ *attrs = obj->internalClass->propertyData.at(index);
+ return !attrs->isAccessor() ? obj->memberData->data[index].asReturnedValue() : thisObject->getValue(obj->propertyAt(index), *attrs);
}
- obj = obj->prototype();
+ obj = obj->prototype;
}
return Primitive::emptyValue().asReturnedValue();
}
@@ -112,11 +117,10 @@ ReturnedValue Lookup::indexedGetterGeneric(Lookup *l, const ValueRef object, con
ReturnedValue Lookup::indexedGetterFallback(Lookup *l, const ValueRef object, const ValueRef index)
{
Q_UNUSED(l);
- ExecutionContext *ctx = l->engine->currentContext();
- Scope scope(ctx);
+ Scope scope(l->engine);
uint idx = index->asArrayIndex();
- Scoped<Object> o(scope, object);
+ ScopedObject o(scope, object);
if (!o) {
if (idx < UINT_MAX) {
if (String *str = object->asString()) {
@@ -130,17 +134,17 @@ ReturnedValue Lookup::indexedGetterFallback(Lookup *l, const ValueRef object, co
if (object->isNullOrUndefined()) {
QString message = QStringLiteral("Cannot read property '%1' of %2").arg(index->toQStringNoThrow()).arg(object->toQStringNoThrow());
- return ctx->throwTypeError(message);
+ return l->engine->throwTypeError(message);
}
- o = RuntimeHelpers::convertToObject(ctx, object);
+ o = RuntimeHelpers::convertToObject(scope.engine, object);
if (!o) // type error
return Encode::undefined();
}
if (idx < UINT_MAX) {
- if (o->arrayData() && !o->arrayData()->hasAttributes()) {
- ScopedValue v(scope, o->arrayData()->get(idx));
+ if (o->d()->arrayData && !o->d()->arrayData->attrs) {
+ ScopedValue v(scope, Scoped<ArrayData>(scope, o->arrayData())->get(idx));
if (!v->isEmpty())
return v->asReturnedValue();
}
@@ -148,10 +152,10 @@ ReturnedValue Lookup::indexedGetterFallback(Lookup *l, const ValueRef object, co
return o->getIndexed(idx);
}
- ScopedString name(scope, index->toString(ctx));
+ ScopedString name(scope, index->toString(scope.engine));
if (scope.hasException())
return Encode::undefined();
- return o->get(name.getPointer());
+ return o->get(name);
}
@@ -163,9 +167,9 @@ ReturnedValue Lookup::indexedGetterObjectInt(Lookup *l, const ValueRef object, c
return indexedGetterGeneric(l, object, index);
Object *o = object->objectValue();
- if (o->arrayData() && o->arrayData()->type() == ArrayData::Simple) {
- SimpleArrayData *s = static_cast<SimpleArrayData *>(o->arrayData());
- if (idx < s->len())
+ if (o->d()->arrayData && o->d()->arrayData->type == Heap::ArrayData::Simple) {
+ Heap::SimpleArrayData *s = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ if (idx < s->len)
if (!s->data(idx).isEmpty())
return s->data(idx).asReturnedValue();
}
@@ -177,7 +181,7 @@ void Lookup::indexedSetterGeneric(Lookup *l, const ValueRef object, const ValueR
{
if (object->isObject()) {
Object *o = object->objectValue();
- if (o->arrayData() && o->arrayData()->type() == ArrayData::Simple && index->asArrayIndex() < UINT_MAX) {
+ if (o->d()->arrayData && o->d()->arrayData->type == Heap::ArrayData::Simple && index->asArrayIndex() < UINT_MAX) {
l->indexedSetter = indexedSetterObjectInt;
indexedSetterObjectInt(l, object, index, v);
return;
@@ -188,17 +192,16 @@ void Lookup::indexedSetterGeneric(Lookup *l, const ValueRef object, const ValueR
void Lookup::indexedSetterFallback(Lookup *l, const ValueRef object, const ValueRef index, const ValueRef value)
{
- ExecutionContext *ctx = l->engine->currentContext();
- Scope scope(ctx);
- ScopedObject o(scope, object->toObject(ctx));
+ Scope scope(l->engine);
+ ScopedObject o(scope, object->toObject(scope.engine));
if (scope.engine->hasException)
return;
uint idx = index->asArrayIndex();
if (idx < UINT_MAX) {
- if (o->arrayData() && o->arrayData()->type() == ArrayData::Simple) {
- SimpleArrayData *s = static_cast<SimpleArrayData *>(o->arrayData());
- if (idx < s->len() && !s->data(idx).isEmpty()) {
+ if (o->d()->arrayData && o->d()->arrayData->type == Heap::ArrayData::Simple) {
+ Heap::SimpleArrayData *s = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ if (idx < s->len) {
s->data(idx) = value;
return;
}
@@ -207,8 +210,8 @@ void Lookup::indexedSetterFallback(Lookup *l, const ValueRef object, const Value
return;
}
- ScopedString name(scope, index->toString(ctx));
- o->put(name.getPointer(), value);
+ ScopedString name(scope, index->toString(scope.engine));
+ o->put(name, value);
}
void Lookup::indexedSetterObjectInt(Lookup *l, const ValueRef object, const ValueRef index, const ValueRef v)
@@ -220,9 +223,9 @@ void Lookup::indexedSetterObjectInt(Lookup *l, const ValueRef object, const Valu
}
Object *o = object->objectValue();
- if (o->arrayData() && o->arrayData()->type() == ArrayData::Simple) {
- SimpleArrayData *s = static_cast<SimpleArrayData *>(o->arrayData());
- if (idx < s->len() && !s->data(idx).isEmpty()) {
+ if (o->d()->arrayData && o->d()->arrayData->type == Heap::ArrayData::Simple) {
+ Heap::SimpleArrayData *s = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
+ if (idx < s->len) {
s->data(idx) = v;
return;
}
@@ -230,32 +233,34 @@ void Lookup::indexedSetterObjectInt(Lookup *l, const ValueRef object, const Valu
indexedSetterFallback(l, object, index, v);
}
-ReturnedValue Lookup::getterGeneric(QV4::Lookup *l, const ValueRef object)
+ReturnedValue Lookup::getterGeneric(Lookup *l, ExecutionEngine *engine, const ValueRef object)
{
if (Object *o = object->asObject())
return o->getLookup(l);
- ExecutionEngine *engine = l->name->engine();
Object *proto;
switch (object->type()) {
case Value::Undefined_Type:
case Value::Null_Type:
- return engine->currentContext()->throwTypeError();
+ return engine->throwTypeError();
case Value::Boolean_Type:
- proto = engine->booleanClass->prototype;
+ proto = engine->booleanPrototype.asObject();
break;
- case Value::Managed_Type:
+ case Value::Managed_Type: {
Q_ASSERT(object->isString());
- proto = engine->stringObjectClass->prototype;
- if (l->name->equals(engine->id_length.getPointer())) {
+ proto = engine->stringPrototype.asObject();
+ Scope scope(engine);
+ ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[l->nameIndex]);
+ if (name->equals(engine->id_length)) {
// special case, as the property is on the object itself
l->getter = stringLengthGetter;
- return stringLengthGetter(l, object);
+ return stringLengthGetter(l, engine, object);
}
break;
+ }
case Value::Integer_Type:
default: // Number
- proto = engine->numberClass->prototype;
+ proto = engine->numberPrototype.asObject();
}
PropertyAttributes attrs;
@@ -281,7 +286,7 @@ ReturnedValue Lookup::getterGeneric(QV4::Lookup *l, const ValueRef object)
return Encode::undefined();
}
-ReturnedValue Lookup::getterTwoClasses(Lookup *l, const ValueRef object)
+ReturnedValue Lookup::getterTwoClasses(Lookup *l, ExecutionEngine *engine, const ValueRef object)
{
Lookup l1 = *l;
@@ -314,114 +319,114 @@ ReturnedValue Lookup::getterTwoClasses(Lookup *l, const ValueRef object)
}
l->getter = getterFallback;
- return getterFallback(l, object);
+ return getterFallback(l, engine, object);
}
-ReturnedValue Lookup::getterFallback(Lookup *l, const ValueRef object)
+ReturnedValue Lookup::getterFallback(Lookup *l, ExecutionEngine *engine, const ValueRef object)
{
- QV4::Scope scope(l->name->engine());
- QV4::ScopedObject o(scope, object->toObject(scope.engine->currentContext()));
+ QV4::Scope scope(engine);
+ QV4::ScopedObject o(scope, object->toObject(scope.engine));
if (!o)
return Encode::undefined();
- QV4::ScopedString s(scope, l->name);
- return o->get(s.getPointer());
+ ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[l->nameIndex]);
+ return o->get(name);
}
-ReturnedValue Lookup::getter0(Lookup *l, const ValueRef object)
+ReturnedValue Lookup::getter0(Lookup *l, ExecutionEngine *engine, const ValueRef object)
{
if (object->isManaged()) {
// we can safely cast to a QV4::Object here. If object is actually a string,
// the internal class won't match
Object *o = object->objectValue();
if (l->classList[0] == o->internalClass())
- return o->memberData()[l->index].asReturnedValue();
+ return o->memberData()->data[l->index].asReturnedValue();
}
- return getterTwoClasses(l, object);
+ return getterTwoClasses(l, engine, object);
}
-ReturnedValue Lookup::getter1(Lookup *l, const ValueRef object)
+ReturnedValue Lookup::getter1(Lookup *l, ExecutionEngine *engine, const ValueRef object)
{
if (object->isManaged()) {
// we can safely cast to a QV4::Object here. If object is actually a string,
// the internal class won't match
Object *o = object->objectValue();
if (l->classList[0] == o->internalClass() &&
- l->classList[1] == o->prototype()->internalClass())
- return o->prototype()->memberData()[l->index].asReturnedValue();
+ l->classList[1] == o->prototype()->internalClass)
+ return o->prototype()->memberData->data[l->index].asReturnedValue();
}
- return getterTwoClasses(l, object);
+ return getterTwoClasses(l, engine, object);
}
-ReturnedValue Lookup::getter2(Lookup *l, const ValueRef object)
+ReturnedValue Lookup::getter2(Lookup *l, ExecutionEngine *engine, const ValueRef object)
{
if (object->isManaged()) {
// we can safely cast to a QV4::Object here. If object is actually a string,
// the internal class won't match
Object *o = object->objectValue();
if (l->classList[0] == o->internalClass()) {
- o = o->prototype();
- if (l->classList[1] == o->internalClass()) {
- o = o->prototype();
- if (l->classList[2] == o->internalClass())
- return o->memberData()[l->index].asReturnedValue();
+ Heap::Object *p = o->prototype();
+ if (l->classList[1] == p->internalClass) {
+ p = p->prototype;
+ if (l->classList[2] == p->internalClass)
+ return p->memberData->data[l->index].asReturnedValue();
}
}
}
l->getter = getterFallback;
- return getterFallback(l, object);
+ return getterFallback(l, engine, object);
}
-ReturnedValue Lookup::getter0getter0(Lookup *l, const ValueRef object)
+ReturnedValue Lookup::getter0getter0(Lookup *l, ExecutionEngine *engine, const ValueRef object)
{
if (object->isManaged()) {
// we can safely cast to a QV4::Object here. If object is actually a string,
// the internal class won't match
Object *o = object->objectValue();
if (l->classList[0] == o->internalClass())
- return o->memberData()[l->index].asReturnedValue();
+ return o->memberData()->data[l->index].asReturnedValue();
if (l->classList[2] == o->internalClass())
- return o->memberData()[l->index2].asReturnedValue();
+ return o->memberData()->data[l->index2].asReturnedValue();
}
l->getter = getterFallback;
- return getterFallback(l, object);
+ return getterFallback(l, engine, object);
}
-ReturnedValue Lookup::getter0getter1(Lookup *l, const ValueRef object)
+ReturnedValue Lookup::getter0getter1(Lookup *l, ExecutionEngine *engine, const ValueRef object)
{
if (object->isManaged()) {
// we can safely cast to a QV4::Object here. If object is actually a string,
// the internal class won't match
Object *o = object->objectValue();
if (l->classList[0] == o->internalClass())
- return o->memberData()[l->index].asReturnedValue();
+ return o->memberData()->data[l->index].asReturnedValue();
if (l->classList[2] == o->internalClass() &&
- l->classList[3] == o->prototype()->internalClass())
- return o->prototype()->memberData()[l->index2].asReturnedValue();
+ l->classList[3] == o->prototype()->internalClass)
+ return o->prototype()->memberData->data[l->index2].asReturnedValue();
}
l->getter = getterFallback;
- return getterFallback(l, object);
+ return getterFallback(l, engine, object);
}
-ReturnedValue Lookup::getter1getter1(Lookup *l, const ValueRef object)
+ReturnedValue Lookup::getter1getter1(Lookup *l, ExecutionEngine *engine, const ValueRef object)
{
if (object->isManaged()) {
// we can safely cast to a QV4::Object here. If object is actually a string,
// the internal class won't match
Object *o = object->objectValue();
if (l->classList[0] == o->internalClass() &&
- l->classList[1] == o->prototype()->internalClass())
- return o->prototype()->memberData()[l->index].asReturnedValue();
+ l->classList[1] == o->prototype()->internalClass)
+ return o->prototype()->memberData->data[l->index].asReturnedValue();
if (l->classList[2] == o->internalClass() &&
- l->classList[3] == o->prototype()->internalClass())
- return o->prototype()->memberData()[l->index2].asReturnedValue();
- return getterFallback(l, object);
+ l->classList[3] == o->prototype()->internalClass)
+ return o->prototype()->memberData->data[l->index2].asReturnedValue();
+ return getterFallback(l, engine, object);
}
l->getter = getterFallback;
- return getterFallback(l, object);
+ return getterFallback(l, engine, object);
}
-ReturnedValue Lookup::getterAccessor0(Lookup *l, const ValueRef object)
+ReturnedValue Lookup::getterAccessor0(Lookup *l, ExecutionEngine *engine, const ValueRef object)
{
if (object->isManaged()) {
// we can safely cast to a QV4::Object here. If object is actually a string,
@@ -429,7 +434,7 @@ ReturnedValue Lookup::getterAccessor0(Lookup *l, const ValueRef object)
Object *o = object->objectValue();
if (l->classList[0] == o->internalClass()) {
Scope scope(o->engine());
- FunctionObject *getter = o->propertyAt(l->index)->getter();
+ ScopedFunctionObject getter(scope, o->propertyAt(l->index)->getter());
if (!getter)
return Encode::undefined();
@@ -439,19 +444,19 @@ ReturnedValue Lookup::getterAccessor0(Lookup *l, const ValueRef object)
}
}
l->getter = getterFallback;
- return getterFallback(l, object);
+ return getterFallback(l, engine, object);
}
-ReturnedValue Lookup::getterAccessor1(Lookup *l, const ValueRef object)
+ReturnedValue Lookup::getterAccessor1(Lookup *l, ExecutionEngine *engine, const ValueRef object)
{
if (object->isManaged()) {
// we can safely cast to a QV4::Object here. If object is actually a string,
// the internal class won't match
- Object *o = object->objectValue();
- if (l->classList[0] == o->internalClass() &&
- l->classList[1] == o->prototype()->internalClass()) {
- Scope scope(o->engine());
- FunctionObject *getter = o->prototype()->propertyAt(l->index)->getter();
+ Heap::Object *o = object->objectValue()->d();
+ if (l->classList[0] == o->internalClass &&
+ l->classList[1] == o->prototype->internalClass) {
+ Scope scope(o->internalClass->engine);
+ ScopedFunctionObject getter(scope, o->prototype->propertyAt(l->index)->getter());
if (!getter)
return Encode::undefined();
@@ -461,22 +466,22 @@ ReturnedValue Lookup::getterAccessor1(Lookup *l, const ValueRef object)
}
}
l->getter = getterFallback;
- return getterFallback(l, object);
+ return getterFallback(l, engine, object);
}
-ReturnedValue Lookup::getterAccessor2(Lookup *l, const ValueRef object)
+ReturnedValue Lookup::getterAccessor2(Lookup *l, ExecutionEngine *engine, const ValueRef object)
{
if (object->isManaged()) {
// we can safely cast to a QV4::Object here. If object is actually a string,
// the internal class won't match
- Object *o = object->objectValue();
- if (l->classList[0] == o->internalClass()) {
- o = o->prototype();
- if (l->classList[1] == o->internalClass()) {
- o = o->prototype();
- if (l->classList[2] == o->internalClass()) {
- Scope scope(o->engine());
- FunctionObject *getter = o->propertyAt(l->index)->getter();
+ Heap::Object *o = object->objectValue()->d();
+ if (l->classList[0] == o->internalClass) {
+ o = o->prototype;
+ if (l->classList[1] == o->internalClass) {
+ o = o->prototype;
+ if (l->classList[2] == o->internalClass) {
+ Scope scope(o->internalClass->engine);
+ ScopedFunctionObject getter(scope, o->propertyAt(l->index)->getter());
if (!getter)
return Encode::undefined();
@@ -488,39 +493,39 @@ ReturnedValue Lookup::getterAccessor2(Lookup *l, const ValueRef object)
}
}
l->getter = getterFallback;
- return getterFallback(l, object);
+ return getterFallback(l, engine, object);
}
-ReturnedValue Lookup::primitiveGetter0(Lookup *l, const ValueRef object)
+ReturnedValue Lookup::primitiveGetter0(Lookup *l, ExecutionEngine *engine, const ValueRef object)
{
if (object->type() == l->type) {
Object *o = l->proto;
if (l->classList[0] == o->internalClass())
- return o->memberData()[l->index].asReturnedValue();
+ return o->memberData()->data[l->index].asReturnedValue();
}
l->getter = getterGeneric;
- return getterGeneric(l, object);
+ return getterGeneric(l, engine, object);
}
-ReturnedValue Lookup::primitiveGetter1(Lookup *l, const ValueRef object)
+ReturnedValue Lookup::primitiveGetter1(Lookup *l, ExecutionEngine *engine, const ValueRef object)
{
if (object->type() == l->type) {
Object *o = l->proto;
if (l->classList[0] == o->internalClass() &&
- l->classList[1] == o->prototype()->internalClass())
- return o->prototype()->memberData()[l->index].asReturnedValue();
+ l->classList[1] == o->prototype()->internalClass)
+ return o->prototype()->memberData->data[l->index].asReturnedValue();
}
l->getter = getterGeneric;
- return getterGeneric(l, object);
+ return getterGeneric(l, engine, object);
}
-ReturnedValue Lookup::primitiveGetterAccessor0(Lookup *l, const ValueRef object)
+ReturnedValue Lookup::primitiveGetterAccessor0(Lookup *l, ExecutionEngine *engine, const ValueRef object)
{
if (object->type() == l->type) {
Object *o = l->proto;
if (l->classList[0] == o->internalClass()) {
Scope scope(o->engine());
- FunctionObject *getter = o->propertyAt(l->index)->getter();
+ ScopedFunctionObject getter(scope, o->propertyAt(l->index)->getter());
if (!getter)
return Encode::undefined();
@@ -530,17 +535,17 @@ ReturnedValue Lookup::primitiveGetterAccessor0(Lookup *l, const ValueRef object)
}
}
l->getter = getterGeneric;
- return getterGeneric(l, object);
+ return getterGeneric(l, engine, object);
}
-ReturnedValue Lookup::primitiveGetterAccessor1(Lookup *l, const ValueRef object)
+ReturnedValue Lookup::primitiveGetterAccessor1(Lookup *l, ExecutionEngine *engine, const ValueRef object)
{
if (object->type() == l->type) {
Object *o = l->proto;
if (l->classList[0] == o->internalClass() &&
- l->classList[1] == o->prototype()->internalClass()) {
+ l->classList[1] == o->prototype()->internalClass) {
Scope scope(o->engine());
- FunctionObject *getter = o->prototype()->propertyAt(l->index)->getter();
+ ScopedFunctionObject getter(scope, o->prototype()->propertyAt(l->index)->getter());
if (!getter)
return Encode::undefined();
@@ -550,31 +555,31 @@ ReturnedValue Lookup::primitiveGetterAccessor1(Lookup *l, const ValueRef object)
}
}
l->getter = getterGeneric;
- return getterGeneric(l, object);
+ return getterGeneric(l, engine, object);
}
-ReturnedValue Lookup::stringLengthGetter(Lookup *l, const ValueRef object)
+ReturnedValue Lookup::stringLengthGetter(Lookup *l, ExecutionEngine *engine, const ValueRef object)
{
if (String *s = object->asString())
return Encode(s->d()->length());
l->getter = getterGeneric;
- return getterGeneric(l, object);
+ return getterGeneric(l, engine, object);
}
-ReturnedValue Lookup::arrayLengthGetter(Lookup *l, const ValueRef object)
+ReturnedValue Lookup::arrayLengthGetter(Lookup *l, ExecutionEngine *engine, const ValueRef object)
{
if (ArrayObject *a = object->asArrayObject())
- return a->memberData()[ArrayObject::LengthPropertyIndex].asReturnedValue();
+ return a->memberData()->data[Heap::ArrayObject::LengthPropertyIndex].asReturnedValue();
l->getter = getterGeneric;
- return getterGeneric(l, object);
+ return getterGeneric(l, engine, object);
}
-ReturnedValue Lookup::globalGetterGeneric(Lookup *l, ExecutionContext *ctx)
+ReturnedValue Lookup::globalGetterGeneric(Lookup *l, ExecutionEngine *engine)
{
- Object *o = ctx->d()->engine->globalObject;
+ Object *o = engine->globalObject();
PropertyAttributes attrs;
ReturnedValue v = l->lookup(o, &attrs);
if (v != Primitive::emptyValue().asReturnedValue()) {
@@ -596,54 +601,54 @@ ReturnedValue Lookup::globalGetterGeneric(Lookup *l, ExecutionContext *ctx)
return v;
}
}
- Scope scope(ctx);
- Scoped<String> n(scope, l->name);
- return ctx->throwReferenceError(n);
+ Scope scope(engine);
+ ScopedString n(scope, engine->currentContext()->compilationUnit->runtimeStrings[l->nameIndex]);
+ return engine->throwReferenceError(n);
}
-ReturnedValue Lookup::globalGetter0(Lookup *l, ExecutionContext *ctx)
+ReturnedValue Lookup::globalGetter0(Lookup *l, ExecutionEngine *engine)
{
- Object *o = ctx->d()->engine->globalObject;
+ Object *o = engine->globalObject();
if (l->classList[0] == o->internalClass())
- return o->memberData()[l->index].asReturnedValue();
+ return o->memberData()->data[l->index].asReturnedValue();
l->globalGetter = globalGetterGeneric;
- return globalGetterGeneric(l, ctx);
+ return globalGetterGeneric(l, engine);
}
-ReturnedValue Lookup::globalGetter1(Lookup *l, ExecutionContext *ctx)
+ReturnedValue Lookup::globalGetter1(Lookup *l, ExecutionEngine *engine)
{
- Object *o = ctx->d()->engine->globalObject;
+ Object *o = engine->globalObject();
if (l->classList[0] == o->internalClass() &&
- l->classList[1] == o->prototype()->internalClass())
- return o->prototype()->memberData()[l->index].asReturnedValue();
+ l->classList[1] == o->prototype()->internalClass)
+ return o->prototype()->memberData->data[l->index].asReturnedValue();
l->globalGetter = globalGetterGeneric;
- return globalGetterGeneric(l, ctx);
+ return globalGetterGeneric(l, engine);
}
-ReturnedValue Lookup::globalGetter2(Lookup *l, ExecutionContext *ctx)
+ReturnedValue Lookup::globalGetter2(Lookup *l, ExecutionEngine *engine)
{
- Object *o = ctx->d()->engine->globalObject;
- if (l->classList[0] == o->internalClass()) {
- o = o->prototype();
- if (l->classList[1] == o->internalClass()) {
- o = o->prototype();
- if (l->classList[2] == o->internalClass()) {
- return o->prototype()->memberData()[l->index].asReturnedValue();
+ Heap::Object *o = engine->globalObject()->d();
+ if (l->classList[0] == o->internalClass) {
+ o = o->prototype;
+ if (l->classList[1] == o->internalClass) {
+ o = o->prototype;
+ if (l->classList[2] == o->internalClass) {
+ return o->prototype->memberData->data[l->index].asReturnedValue();
}
}
}
l->globalGetter = globalGetterGeneric;
- return globalGetterGeneric(l, ctx);
+ return globalGetterGeneric(l, engine);
}
-ReturnedValue Lookup::globalGetterAccessor0(Lookup *l, ExecutionContext *ctx)
+ReturnedValue Lookup::globalGetterAccessor0(Lookup *l, ExecutionEngine *engine)
{
- Object *o = ctx->d()->engine->globalObject;
+ Object *o = engine->globalObject();
if (l->classList[0] == o->internalClass()) {
Scope scope(o->engine());
- FunctionObject *getter = o->propertyAt(l->index)->getter();
+ ScopedFunctionObject getter(scope, o->propertyAt(l->index)->getter());
if (!getter)
return Encode::undefined();
@@ -652,16 +657,16 @@ ReturnedValue Lookup::globalGetterAccessor0(Lookup *l, ExecutionContext *ctx)
return getter->call(callData);
}
l->globalGetter = globalGetterGeneric;
- return globalGetterGeneric(l, ctx);
+ return globalGetterGeneric(l, engine);
}
-ReturnedValue Lookup::globalGetterAccessor1(Lookup *l, ExecutionContext *ctx)
+ReturnedValue Lookup::globalGetterAccessor1(Lookup *l, ExecutionEngine *engine)
{
- Object *o = ctx->d()->engine->globalObject;
+ Object *o = engine->globalObject();
if (l->classList[0] == o->internalClass() &&
- l->classList[1] == o->prototype()->internalClass()) {
+ l->classList[1] == o->prototype()->internalClass) {
Scope scope(o->engine());
- FunctionObject *getter = o->prototype()->propertyAt(l->index)->getter();
+ ScopedFunctionObject getter(scope, o->prototype()->propertyAt(l->index)->getter());
if (!getter)
return Encode::undefined();
@@ -670,19 +675,19 @@ ReturnedValue Lookup::globalGetterAccessor1(Lookup *l, ExecutionContext *ctx)
return getter->call(callData);
}
l->globalGetter = globalGetterGeneric;
- return globalGetterGeneric(l, ctx);
+ return globalGetterGeneric(l, engine);
}
-ReturnedValue Lookup::globalGetterAccessor2(Lookup *l, ExecutionContext *ctx)
+ReturnedValue Lookup::globalGetterAccessor2(Lookup *l, ExecutionEngine *engine)
{
- Object *o = ctx->d()->engine->globalObject;
- if (l->classList[0] == o->internalClass()) {
- o = o->prototype();
- if (l->classList[1] == o->internalClass()) {
- o = o->prototype();
- if (l->classList[2] == o->internalClass()) {
- Scope scope(o->engine());
- FunctionObject *getter = o->propertyAt(l->index)->getter();
+ Heap::Object *o = engine->globalObject()->d();
+ if (l->classList[0] == o->internalClass) {
+ o = o->prototype;
+ if (l->classList[1] == o->internalClass) {
+ o = o->prototype;
+ if (l->classList[2] == o->internalClass) {
+ Scope scope(o->internalClass->engine);
+ ScopedFunctionObject getter(scope, o->propertyAt(l->index)->getter());
if (!getter)
return Encode::undefined();
@@ -693,25 +698,25 @@ ReturnedValue Lookup::globalGetterAccessor2(Lookup *l, ExecutionContext *ctx)
}
}
l->globalGetter = globalGetterGeneric;
- return globalGetterGeneric(l, ctx);
+ return globalGetterGeneric(l, engine);
}
-void Lookup::setterGeneric(Lookup *l, const ValueRef object, const ValueRef value)
+void Lookup::setterGeneric(Lookup *l, ExecutionEngine *engine, const ValueRef object, const ValueRef value)
{
- Scope scope(l->name->engine());
+ Scope scope(engine);
ScopedObject o(scope, object);
if (!o) {
- o = RuntimeHelpers::convertToObject(scope.engine->currentContext(), object);
+ o = RuntimeHelpers::convertToObject(scope.engine, object);
if (!o) // type error
return;
- ScopedString s(scope, l->name);
- o->put(s.getPointer(), value);
+ ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[l->nameIndex]);
+ o->put(name, value);
return;
}
o->setLookup(l, value);
}
-void Lookup::setterTwoClasses(Lookup *l, const ValueRef object, const ValueRef value)
+void Lookup::setterTwoClasses(Lookup *l, ExecutionEngine *engine, const ValueRef object, const ValueRef value)
{
Lookup l1 = *l;
@@ -727,76 +732,76 @@ void Lookup::setterTwoClasses(Lookup *l, const ValueRef object, const ValueRef v
}
l->setter = setterFallback;
- setterFallback(l, object, value);
+ setterFallback(l, engine, object, value);
}
-void Lookup::setterFallback(Lookup *l, const ValueRef object, const ValueRef value)
+void Lookup::setterFallback(Lookup *l, ExecutionEngine *engine, const ValueRef object, const ValueRef value)
{
- QV4::Scope scope(l->name->engine());
- QV4::ScopedObject o(scope, object->toObject(scope.engine->currentContext()));
+ QV4::Scope scope(engine);
+ QV4::ScopedObject o(scope, object->toObject(scope.engine));
if (o) {
- QV4::ScopedString s(scope, l->name);
- o->put(s.getPointer(), value);
+ ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[l->nameIndex]);
+ o->put(name, value);
}
}
-void Lookup::setter0(Lookup *l, const ValueRef object, const ValueRef value)
+void Lookup::setter0(Lookup *l, ExecutionEngine *engine, const ValueRef object, const ValueRef value)
{
Object *o = static_cast<Object *>(object->asManaged());
if (o && o->internalClass() == l->classList[0]) {
- o->memberData()[l->index] = *value;
+ o->memberData()->data[l->index] = *value;
return;
}
- setterTwoClasses(l, object, value);
+ setterTwoClasses(l, engine, object, value);
}
-void Lookup::setterInsert0(Lookup *l, const ValueRef object, const ValueRef value)
+void Lookup::setterInsert0(Lookup *l, ExecutionEngine *engine, const ValueRef object, const ValueRef value)
{
Object *o = static_cast<Object *>(object->asManaged());
if (o && o->internalClass() == l->classList[0]) {
if (!o->prototype()) {
- if (l->index >= o->memberData().size())
+ if (!o->memberData() || l->index >= o->memberData()->size)
o->ensureMemberIndex(l->index);
- o->memberData()[l->index] = *value;
+ o->memberData()->data[l->index] = *value;
o->setInternalClass(l->classList[3]);
return;
}
}
l->setter = setterFallback;
- setterFallback(l, object, value);
+ setterFallback(l, engine, object, value);
}
-void Lookup::setterInsert1(Lookup *l, const ValueRef object, const ValueRef value)
+void Lookup::setterInsert1(Lookup *l, ExecutionEngine *engine, const ValueRef object, const ValueRef value)
{
Object *o = static_cast<Object *>(object->asManaged());
if (o && o->internalClass() == l->classList[0]) {
- Object *p = o->prototype();
- if (p && p->internalClass() == l->classList[1]) {
- if (l->index >= o->memberData().size())
+ Heap::Object *p = o->prototype();
+ if (p && p->internalClass == l->classList[1]) {
+ if (!o->memberData() || l->index >= o->memberData()->size)
o->ensureMemberIndex(l->index);
- o->memberData()[l->index] = *value;
+ o->memberData()->data[l->index] = *value;
o->setInternalClass(l->classList[3]);
return;
}
}
l->setter = setterFallback;
- setterFallback(l, object, value);
+ setterFallback(l, engine, object, value);
}
-void Lookup::setterInsert2(Lookup *l, const ValueRef object, const ValueRef value)
+void Lookup::setterInsert2(Lookup *l, ExecutionEngine *engine, const ValueRef object, const ValueRef value)
{
Object *o = static_cast<Object *>(object->asManaged());
if (o && o->internalClass() == l->classList[0]) {
- Object *p = o->prototype();
- if (p && p->internalClass() == l->classList[1]) {
- p = p->prototype();
- if (p && p->internalClass() == l->classList[2]) {
- if (l->index >= o->memberData().size())
+ Heap::Object *p = o->prototype();
+ if (p && p->internalClass == l->classList[1]) {
+ p = p->prototype;
+ if (p && p->internalClass == l->classList[2]) {
+ if (!o->memberData() || l->index >= o->memberData()->size)
o->ensureMemberIndex(l->index);
- o->memberData()[l->index] = *value;
+ o->memberData()->data[l->index] = *value;
o->setInternalClass(l->classList[3]);
return;
}
@@ -804,25 +809,25 @@ void Lookup::setterInsert2(Lookup *l, const ValueRef object, const ValueRef valu
}
l->setter = setterFallback;
- setterFallback(l, object, value);
+ setterFallback(l, engine, object, value);
}
-void Lookup::setter0setter0(Lookup *l, const ValueRef object, const ValueRef value)
+void Lookup::setter0setter0(Lookup *l, ExecutionEngine *engine, const ValueRef object, const ValueRef value)
{
Object *o = static_cast<Object *>(object->asManaged());
if (o) {
if (o->internalClass() == l->classList[0]) {
- o->memberData()[l->index] = *value;
+ o->memberData()->data[l->index] = *value;
return;
}
if (o->internalClass() == l->classList[1]) {
- o->memberData()[l->index2] = *value;
+ o->memberData()->data[l->index2] = *value;
return;
}
}
l->setter = setterFallback;
- setterFallback(l, object, value);
+ setterFallback(l, engine, object, value);
}
diff --git a/src/qml/jsruntime/qv4lookup_p.h b/src/qml/jsruntime/qv4lookup_p.h
index 8ff7e98d0f..d491a62ddc 100644
--- a/src/qml/jsruntime/qv4lookup_p.h
+++ b/src/qml/jsruntime/qv4lookup_p.h
@@ -49,9 +49,9 @@ struct Lookup {
union {
ReturnedValue (*indexedGetter)(Lookup *l, const ValueRef object, const ValueRef index);
void (*indexedSetter)(Lookup *l, const ValueRef object, const ValueRef index, const ValueRef v);
- ReturnedValue (*getter)(Lookup *l, const ValueRef object);
- ReturnedValue (*globalGetter)(Lookup *l, ExecutionContext *ctx);
- void (*setter)(Lookup *l, const ValueRef object, const ValueRef v);
+ ReturnedValue (*getter)(Lookup *l, ExecutionEngine *engine, const ValueRef object);
+ ReturnedValue (*globalGetter)(Lookup *l, ExecutionEngine *engine);
+ void (*setter)(Lookup *l, ExecutionEngine *engine, const ValueRef object, const ValueRef v);
};
union {
ExecutionEngine *engine;
@@ -68,7 +68,7 @@ struct Lookup {
uint index2;
};
uint index;
- String *name;
+ uint nameIndex;
static ReturnedValue indexedGetterGeneric(Lookup *l, const ValueRef object, const ValueRef index);
static ReturnedValue indexedGetterFallback(Lookup *l, const ValueRef object, const ValueRef index);
@@ -78,43 +78,43 @@ struct Lookup {
static void indexedSetterFallback(Lookup *l, const ValueRef object, const ValueRef index, const ValueRef value);
static void indexedSetterObjectInt(Lookup *l, const ValueRef object, const ValueRef index, const ValueRef v);
- static ReturnedValue getterGeneric(Lookup *l, const ValueRef object);
- static ReturnedValue getterTwoClasses(Lookup *l, const ValueRef object);
- static ReturnedValue getterFallback(Lookup *l, const ValueRef object);
-
- static ReturnedValue getter0(Lookup *l, const ValueRef object);
- static ReturnedValue getter1(Lookup *l, const ValueRef object);
- static ReturnedValue getter2(Lookup *l, const ValueRef object);
- static ReturnedValue getter0getter0(Lookup *l, const ValueRef object);
- static ReturnedValue getter0getter1(Lookup *l, const ValueRef object);
- static ReturnedValue getter1getter1(Lookup *l, const ValueRef object);
- static ReturnedValue getterAccessor0(Lookup *l, const ValueRef object);
- static ReturnedValue getterAccessor1(Lookup *l, const ValueRef object);
- static ReturnedValue getterAccessor2(Lookup *l, const ValueRef object);
-
- static ReturnedValue primitiveGetter0(Lookup *l, const ValueRef object);
- static ReturnedValue primitiveGetter1(Lookup *l, const ValueRef object);
- static ReturnedValue primitiveGetterAccessor0(Lookup *l, const ValueRef object);
- static ReturnedValue primitiveGetterAccessor1(Lookup *l, const ValueRef object);
- static ReturnedValue stringLengthGetter(Lookup *l, const ValueRef object);
- static ReturnedValue arrayLengthGetter(Lookup *l, const ValueRef object);
-
- static ReturnedValue globalGetterGeneric(Lookup *l, ExecutionContext *ctx);
- static ReturnedValue globalGetter0(Lookup *l, ExecutionContext *ctx);
- static ReturnedValue globalGetter1(Lookup *l, ExecutionContext *ctx);
- static ReturnedValue globalGetter2(Lookup *l, ExecutionContext *ctx);
- static ReturnedValue globalGetterAccessor0(Lookup *l, ExecutionContext *ctx);
- static ReturnedValue globalGetterAccessor1(Lookup *l, ExecutionContext *ctx);
- static ReturnedValue globalGetterAccessor2(Lookup *l, ExecutionContext *ctx);
-
- static void setterGeneric(Lookup *l, const ValueRef object, const ValueRef value);
- static void setterTwoClasses(Lookup *l, const ValueRef object, const ValueRef value);
- static void setterFallback(Lookup *l, const ValueRef object, const ValueRef value);
- static void setter0(Lookup *l, const ValueRef object, const ValueRef value);
- static void setterInsert0(Lookup *l, const ValueRef object, const ValueRef value);
- static void setterInsert1(Lookup *l, const ValueRef object, const ValueRef value);
- static void setterInsert2(Lookup *l, const ValueRef object, const ValueRef value);
- static void setter0setter0(Lookup *l, const ValueRef object, const ValueRef value);
+ static ReturnedValue getterGeneric(Lookup *l, ExecutionEngine *engine, const ValueRef object);
+ static ReturnedValue getterTwoClasses(Lookup *l, ExecutionEngine *engine, const ValueRef object);
+ static ReturnedValue getterFallback(Lookup *l, ExecutionEngine *engine, const ValueRef object);
+
+ static ReturnedValue getter0(Lookup *l, ExecutionEngine *engine, const ValueRef object);
+ static ReturnedValue getter1(Lookup *l, ExecutionEngine *engine, const ValueRef object);
+ static ReturnedValue getter2(Lookup *l, ExecutionEngine *engine, const ValueRef object);
+ static ReturnedValue getter0getter0(Lookup *l, ExecutionEngine *engine, const ValueRef object);
+ static ReturnedValue getter0getter1(Lookup *l, ExecutionEngine *engine, const ValueRef object);
+ static ReturnedValue getter1getter1(Lookup *l, ExecutionEngine *engine, const ValueRef object);
+ static ReturnedValue getterAccessor0(Lookup *l, ExecutionEngine *engine, const ValueRef object);
+ static ReturnedValue getterAccessor1(Lookup *l, ExecutionEngine *engine, const ValueRef object);
+ static ReturnedValue getterAccessor2(Lookup *l, ExecutionEngine *engine, const ValueRef object);
+
+ static ReturnedValue primitiveGetter0(Lookup *l, ExecutionEngine *engine, const ValueRef object);
+ static ReturnedValue primitiveGetter1(Lookup *l, ExecutionEngine *engine, const ValueRef object);
+ static ReturnedValue primitiveGetterAccessor0(Lookup *l, ExecutionEngine *engine, const ValueRef object);
+ static ReturnedValue primitiveGetterAccessor1(Lookup *l, ExecutionEngine *engine, const ValueRef object);
+ static ReturnedValue stringLengthGetter(Lookup *l, ExecutionEngine *engine, const ValueRef object);
+ static ReturnedValue arrayLengthGetter(Lookup *l, ExecutionEngine *engine, const ValueRef object);
+
+ static ReturnedValue globalGetterGeneric(Lookup *l, ExecutionEngine *engine);
+ static ReturnedValue globalGetter0(Lookup *l, ExecutionEngine *engine);
+ static ReturnedValue globalGetter1(Lookup *l, ExecutionEngine *engine);
+ static ReturnedValue globalGetter2(Lookup *l, ExecutionEngine *engine);
+ static ReturnedValue globalGetterAccessor0(Lookup *l, ExecutionEngine *engine);
+ static ReturnedValue globalGetterAccessor1(Lookup *l, ExecutionEngine *engine);
+ static ReturnedValue globalGetterAccessor2(Lookup *l, ExecutionEngine *engine);
+
+ static void setterGeneric(Lookup *l, ExecutionEngine *engine, const ValueRef object, const ValueRef value);
+ static void setterTwoClasses(Lookup *l, ExecutionEngine *engine, const ValueRef object, const ValueRef value);
+ static void setterFallback(Lookup *l, ExecutionEngine *engine, const ValueRef object, const ValueRef value);
+ static void setter0(Lookup *l, ExecutionEngine *engine, const ValueRef object, const ValueRef value);
+ static void setterInsert0(Lookup *l, ExecutionEngine *engine, const ValueRef object, const ValueRef value);
+ static void setterInsert1(Lookup *l, ExecutionEngine *engine, const ValueRef object, const ValueRef value);
+ static void setterInsert2(Lookup *l, ExecutionEngine *engine, const ValueRef object, const ValueRef value);
+ static void setter0setter0(Lookup *l, ExecutionEngine *engine, const ValueRef object, const ValueRef value);
ReturnedValue lookup(ValueRef thisObject, Object *obj, PropertyAttributes *attrs);
ReturnedValue lookup(Object *obj, PropertyAttributes *attrs);
diff --git a/src/qml/jsruntime/qv4managed.cpp b/src/qml/jsruntime/qv4managed.cpp
index c7327addfd..668e7d296d 100644
--- a/src/qml/jsruntime/qv4managed.cpp
+++ b/src/qml/jsruntime/qv4managed.cpp
@@ -100,26 +100,26 @@ QString Managed::className() const
s = "RegExp";
break;
case Type_ErrorObject:
- switch (ErrorObject::ErrorType(subtype())) {
- case ErrorObject::Error:
+ switch (static_cast<Heap::ErrorObject *>(d())->errorType) {
+ case Heap::ErrorObject::Error:
s = "Error";
break;
- case ErrorObject::EvalError:
+ case Heap::ErrorObject::EvalError:
s = "EvalError";
break;
- case ErrorObject::RangeError:
+ case Heap::ErrorObject::RangeError:
s = "RangeError";
break;
- case ErrorObject::ReferenceError:
+ case Heap::ErrorObject::ReferenceError:
s = "ReferenceError";
break;
- case ErrorObject::SyntaxError:
+ case Heap::ErrorObject::SyntaxError:
s = "SyntaxError";
break;
- case ErrorObject::TypeError:
+ case Heap::ErrorObject::TypeError:
s = "TypeError";
break;
- case ErrorObject::URIError:
+ case Heap::ErrorObject::URIError:
s = "URIError";
break;
}
@@ -157,7 +157,7 @@ void Managed::setVTable(const ManagedVTable *vt)
d()->internalClass = internalClass()->changeVTable(vt);
}
-void Managed::Data::setVTable(const ManagedVTable *vt)
+void Heap::Base::setVTable(const ManagedVTable *vt)
{
Q_ASSERT(internalClass);
internalClass = internalClass->changeVTable(vt);
diff --git a/src/qml/jsruntime/qv4managed_p.h b/src/qml/jsruntime/qv4managed_p.h
index e679017b7e..fad3b85b2e 100644
--- a/src/qml/jsruntime/qv4managed_p.h
+++ b/src/qml/jsruntime/qv4managed_p.h
@@ -33,9 +33,6 @@
#ifndef QMLJS_MANAGED_H
#define QMLJS_MANAGED_H
-#include <QtCore/QString>
-#include <QtCore/QVector>
-#include <QtCore/QDebug>
#include "qv4global_p.h"
#include "qv4value_p.h"
#include "qv4internalclass_p.h"
@@ -45,7 +42,7 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
#define Q_MANAGED_CHECK \
- template <typename T> inline void qt_check_for_QMANAGED_macro(const T *_q_argument) const \
+ template <typename _T> inline void qt_check_for_QMANAGED_macro(const _T *_q_argument) const \
{ int i = qYouForgotTheQ_MANAGED_Macro(this, _q_argument); i = i + 1; }
template <typename T>
@@ -60,17 +57,18 @@ inline void qYouForgotTheQ_MANAGED_Macro(T1, T2) {}
#define V4_MANAGED_SIZE_TEST
#endif
-#define V4_MANAGED(superClass) \
+#define V4_NEEDS_DESTROY static void destroy(QV4::Heap::Base *b) { static_cast<Data *>(b)->~Data(); }
+
+
+#define V4_MANAGED(DataClass, superClass) \
public: \
Q_MANAGED_CHECK \
+ typedef QV4::Heap::DataClass Data; \
typedef superClass SuperClass; \
static const QV4::ManagedVTable static_vtbl; \
static inline const QV4::ManagedVTable *staticVTable() { return &static_vtbl; } \
- template <typename T> \
- QV4::Returned<T> *asReturned() { return QV4::Returned<T>::create(this); } \
V4_MANAGED_SIZE_TEST \
- const Data *d() const { return &static_cast<const Data &>(Managed::data); } \
- Data *d() { return &static_cast<Data &>(Managed::data); }
+ QV4::Heap::DataClass *d() const { return static_cast<QV4::Heap::DataClass *>(m); }
#define V4_OBJECT(superClass) \
public: \
@@ -78,11 +76,18 @@ inline void qYouForgotTheQ_MANAGED_Macro(T1, T2) {}
typedef superClass SuperClass; \
static const QV4::ObjectVTable static_vtbl; \
static inline const QV4::ManagedVTable *staticVTable() { return &static_vtbl.managedVTable; } \
- template <typename T> \
- QV4::Returned<T> *asReturned() { return QV4::Returned<T>::create(this); } \
V4_MANAGED_SIZE_TEST \
- const Data *d() const { return &static_cast<const Data &>(Managed::data); } \
- Data *d() { return &static_cast<Data &>(Managed::data); }
+ Data *d() const { return static_cast<Data *>(m); }
+
+#define V4_OBJECT2(DataClass, superClass) \
+ public: \
+ Q_MANAGED_CHECK \
+ typedef QV4::Heap::DataClass Data; \
+ typedef superClass SuperClass; \
+ static const QV4::ObjectVTable static_vtbl; \
+ static inline const QV4::ManagedVTable *staticVTable() { return &static_vtbl.managedVTable; } \
+ V4_MANAGED_SIZE_TEST \
+ QV4::Heap::DataClass *d() const { return static_cast<QV4::Heap::DataClass *>(m); }
#define Q_MANAGED_TYPE(type) \
public: \
@@ -112,8 +117,8 @@ struct ManagedVTable
uint unused : 18;
uint type : 8;
const char *className;
- void (*destroy)(Managed *);
- void (*markObjects)(Managed *, ExecutionEngine *e);
+ void (*destroy)(Heap::Base *);
+ void (*markObjects)(Heap::Base *, ExecutionEngine *e);
bool (*isEqualTo)(Managed *m, Managed *other);
};
@@ -133,7 +138,7 @@ struct ObjectVTable
ReturnedValue (*getLookup)(Managed *m, Lookup *l);
void (*setLookup)(Managed *m, Lookup *l, const ValueRef v);
uint (*getLength)(const Managed *m);
- void (*advanceIterator)(Managed *m, ObjectIterator *it, String *&name, uint *index, Property *p, PropertyAttributes *attributes);
+ void (*advanceIterator)(Managed *m, ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attributes);
};
#define DEFINE_MANAGED_VTABLE_INT(classname, parentVTable) \
@@ -177,45 +182,9 @@ const QV4::ObjectVTable classname::static_vtbl = \
advanceIterator \
}
-struct Q_QML_PRIVATE_EXPORT Managed
+struct Q_QML_PRIVATE_EXPORT Managed : Value
{
- struct Q_QML_PRIVATE_EXPORT Data : HeapObject {
- Data() {}
- Data(InternalClass *internal)
- : internalClass(internal)
- , markBit(0)
- , inUse(1)
- , extensible(1)
- {
- // ####
-// Q_ASSERT(internal && internal->vtable);
- }
- InternalClass *internalClass;
- struct {
- uchar markBit : 1;
- uchar inUse : 1;
- uchar extensible : 1; // used by Object
- uchar _unused : 1;
- uchar needsActivation : 1; // used by FunctionObject
- uchar strictMode : 1; // used by FunctionObject
- uchar bindingKeyFlag : 1;
- uchar hasAccessorProperty : 1;
- uchar _type;
- mutable uchar subtype;
- uchar _flags;
- };
-
- void setVTable(const ManagedVTable *vt);
- ReturnedValue asReturnedValue() const {
- return reinterpret_cast<Managed *>(const_cast<Data *>(this))->asReturnedValue();
- }
-
- void *operator new(size_t, Managed *m) { return m; }
- void *operator new(size_t, Managed::Data *m) { return m; }
- void operator delete(void *, Managed::Data *) {}
- };
- Data data;
- V4_MANAGED(Managed)
+ V4_MANAGED(Base, Managed)
enum {
IsExecutionContext = false,
IsString = false,
@@ -226,19 +195,14 @@ struct Q_QML_PRIVATE_EXPORT Managed
};
private:
void *operator new(size_t);
+ Managed();
Managed(const Managed &other);
void operator = (const Managed &other);
-
-protected:
- Managed(InternalClass *internal)
- : data(internal)
- {
- }
-
-public:
void *operator new(size_t size, MemoryManager *mm);
void *operator new(size_t, Managed *m) { return m; }
+public:
+
inline void mark(QV4::ExecutionEngine *engine);
enum Type {
@@ -314,20 +278,10 @@ public:
QString className() const;
- Managed **nextFreeRef() {
- return reinterpret_cast<Managed **>(this);
- }
- Managed *nextFree() {
- return *reinterpret_cast<Managed **>(this);
- }
- void setNextFree(Managed *m) {
- *reinterpret_cast<Managed **>(this) = m;
- }
-
void setVTable(const ManagedVTable *vt);
- bool isEqualTo(Managed *other)
- { return internalClass()->vtable->isEqualTo(this, other); }
+ bool isEqualTo(const Managed *other) const
+ { return internalClass()->vtable->isEqualTo(const_cast<Managed *>(this), const_cast<Managed *>(other)); }
static bool isEqualTo(Managed *m, Managed *other);
@@ -336,13 +290,10 @@ public:
InternalClass *internalClass() const { return d()->internalClass; }
void setInternalClass(InternalClass *ic) { d()->internalClass = ic; }
- uchar subtype() const { return d()->subtype; }
- void setSubtype(uchar subtype) const { d()->subtype = subtype; }
-
- bool inUse() const { return d()->inUse; }
- bool markBit() const { return d()->markBit; }
+ bool inUse() const { return d()->inUse(); }
+ bool markBit() const { return d()->isMarked(); }
- static void destroy(Managed *) {}
+ static void destroy(Heap::Base *) {}
private:
friend class MemoryManager;
friend struct Identifiers;
@@ -377,6 +328,13 @@ inline FunctionObject *managed_cast(Managed *m)
return m ? m->asFunctionObject() : 0;
}
+inline Value Value::fromManaged(Managed *m)
+{
+ if (!m)
+ return QV4::Primitive::undefinedValue();
+ return *m;
+}
+
}
diff --git a/src/qml/jsruntime/qv4mathobject.cpp b/src/qml/jsruntime/qv4mathobject.cpp
index 1148b0f97d..222a6fd97c 100644
--- a/src/qml/jsruntime/qv4mathobject.cpp
+++ b/src/qml/jsruntime/qv4mathobject.cpp
@@ -47,10 +47,10 @@ DEFINE_OBJECT_VTABLE(MathObject);
static const double qt_PI = 2.0 * ::asin(1.0);
-MathObject::Data::Data(InternalClass *ic)
- : Object::Data(ic)
+Heap::MathObject::MathObject(ExecutionEngine *e)
+ : Heap::Object(QV4::InternalClass::create(e, QV4::MathObject::staticVTable()), e->objectPrototype.asObject())
{
- Scope scope(ic->engine);
+ Scope scope(e);
ScopedObject m(scope, this);
m->defineReadonlyProperty(QStringLiteral("E"), Primitive::fromDouble(::exp(1.0)));
@@ -62,24 +62,24 @@ MathObject::Data::Data(InternalClass *ic)
m->defineReadonlyProperty(QStringLiteral("SQRT1_2"), Primitive::fromDouble(::sqrt(0.5)));
m->defineReadonlyProperty(QStringLiteral("SQRT2"), Primitive::fromDouble(::sqrt(2.0)));
- m->defineDefaultProperty(QStringLiteral("abs"), method_abs, 1);
- m->defineDefaultProperty(QStringLiteral("acos"), method_acos, 1);
- m->defineDefaultProperty(QStringLiteral("asin"), method_asin, 0);
- m->defineDefaultProperty(QStringLiteral("atan"), method_atan, 1);
- m->defineDefaultProperty(QStringLiteral("atan2"), method_atan2, 2);
- m->defineDefaultProperty(QStringLiteral("ceil"), method_ceil, 1);
- m->defineDefaultProperty(QStringLiteral("cos"), method_cos, 1);
- m->defineDefaultProperty(QStringLiteral("exp"), method_exp, 1);
- m->defineDefaultProperty(QStringLiteral("floor"), method_floor, 1);
- m->defineDefaultProperty(QStringLiteral("log"), method_log, 1);
- m->defineDefaultProperty(QStringLiteral("max"), method_max, 2);
- m->defineDefaultProperty(QStringLiteral("min"), method_min, 2);
- m->defineDefaultProperty(QStringLiteral("pow"), method_pow, 2);
- m->defineDefaultProperty(QStringLiteral("random"), method_random, 0);
- m->defineDefaultProperty(QStringLiteral("round"), method_round, 1);
- m->defineDefaultProperty(QStringLiteral("sin"), method_sin, 1);
- m->defineDefaultProperty(QStringLiteral("sqrt"), method_sqrt, 1);
- m->defineDefaultProperty(QStringLiteral("tan"), method_tan, 1);
+ m->defineDefaultProperty(QStringLiteral("abs"), QV4::MathObject::method_abs, 1);
+ m->defineDefaultProperty(QStringLiteral("acos"), QV4::MathObject::method_acos, 1);
+ m->defineDefaultProperty(QStringLiteral("asin"), QV4::MathObject::method_asin, 0);
+ m->defineDefaultProperty(QStringLiteral("atan"), QV4::MathObject::method_atan, 1);
+ m->defineDefaultProperty(QStringLiteral("atan2"), QV4::MathObject::method_atan2, 2);
+ m->defineDefaultProperty(QStringLiteral("ceil"), QV4::MathObject::method_ceil, 1);
+ m->defineDefaultProperty(QStringLiteral("cos"), QV4::MathObject::method_cos, 1);
+ m->defineDefaultProperty(QStringLiteral("exp"), QV4::MathObject::method_exp, 1);
+ m->defineDefaultProperty(QStringLiteral("floor"), QV4::MathObject::method_floor, 1);
+ m->defineDefaultProperty(QStringLiteral("log"), QV4::MathObject::method_log, 1);
+ m->defineDefaultProperty(QStringLiteral("max"), QV4::MathObject::method_max, 2);
+ m->defineDefaultProperty(QStringLiteral("min"), QV4::MathObject::method_min, 2);
+ m->defineDefaultProperty(QStringLiteral("pow"), QV4::MathObject::method_pow, 2);
+ m->defineDefaultProperty(QStringLiteral("random"), QV4::MathObject::method_random, 0);
+ m->defineDefaultProperty(QStringLiteral("round"), QV4::MathObject::method_round, 1);
+ m->defineDefaultProperty(QStringLiteral("sin"), QV4::MathObject::method_sin, 1);
+ m->defineDefaultProperty(QStringLiteral("sqrt"), QV4::MathObject::method_sqrt, 1);
+ m->defineDefaultProperty(QStringLiteral("tan"), QV4::MathObject::method_tan, 1);
}
/* copies the sign from y to x and returns the result */
diff --git a/src/qml/jsruntime/qv4mathobject_p.h b/src/qml/jsruntime/qv4mathobject_p.h
index ab50b0105a..feff968a17 100644
--- a/src/qml/jsruntime/qv4mathobject_p.h
+++ b/src/qml/jsruntime/qv4mathobject_p.h
@@ -39,13 +39,17 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
+namespace Heap {
+
+struct MathObject : Object {
+ MathObject(ExecutionEngine *e);
+};
+
+}
+
struct MathObject: Object
{
- struct Data : Object::Data {
- Data(InternalClass *ic);
- };
-
- V4_OBJECT(Object)
+ V4_OBJECT2(MathObject, Object)
Q_MANAGED_TYPE(MathObject)
static ReturnedValue method_abs(CallContext *context);
diff --git a/src/qml/jsruntime/qv4memberdata.cpp b/src/qml/jsruntime/qv4memberdata.cpp
index 405594ca9b..d4e196f091 100644
--- a/src/qml/jsruntime/qv4memberdata.cpp
+++ b/src/qml/jsruntime/qv4memberdata.cpp
@@ -38,25 +38,27 @@ using namespace QV4;
DEFINE_MANAGED_VTABLE(MemberData);
-void MemberData::markObjects(Managed *that, ExecutionEngine *e)
+void MemberData::markObjects(Heap::Base *that, ExecutionEngine *e)
{
- MemberData *m = static_cast<MemberData *>(that);
- for (uint i = 0; i < m->d()->size; ++i)
- m->d()->data[i].mark(e);
+ Heap::MemberData *m = static_cast<Heap::MemberData *>(that);
+ for (uint i = 0; i < m->size; ++i)
+ m->data[i].mark(e);
}
-void Members::ensureIndex(QV4::ExecutionEngine *e, uint idx)
+Heap::MemberData *MemberData::reallocate(ExecutionEngine *e, Heap::MemberData *old, uint idx)
{
- uint s = size();
- if (idx >= s) {
- int newAlloc = qMax((uint)4, 2*idx);
- uint alloc = sizeof(MemberData::Data) + (newAlloc)*sizeof(Value);
- MemberData *newMemberData = static_cast<MemberData *>(e->memoryManager->allocManaged(alloc));
- if (d())
- memcpy(newMemberData, d(), sizeof(MemberData::Data) + s*sizeof(Value));
- else
- new (newMemberData) MemberData(e->memberDataClass);
- newMemberData->d()->size = newAlloc;
- m = newMemberData;
- }
+ uint s = old ? old->size : 0;
+ if (idx < s)
+ return old;
+
+ int newAlloc = qMax((uint)4, 2*idx);
+ uint alloc = sizeof(Heap::MemberData) + (newAlloc)*sizeof(Value);
+ Scope scope(e);
+ Scoped<MemberData> newMemberData(scope, static_cast<Heap::MemberData *>(e->memoryManager->allocManaged(alloc)));
+ if (old)
+ memcpy(newMemberData->d(), old, sizeof(Heap::MemberData) + s*sizeof(Value));
+ else
+ new (newMemberData->d()) Heap::MemberData(e->memberDataClass);
+ newMemberData->d()->size = newAlloc;
+ return newMemberData->d();
}
diff --git a/src/qml/jsruntime/qv4memberdata_p.h b/src/qml/jsruntime/qv4memberdata_p.h
index 83732113a9..c881cf961a 100644
--- a/src/qml/jsruntime/qv4memberdata_p.h
+++ b/src/qml/jsruntime/qv4memberdata_p.h
@@ -40,37 +40,32 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
+namespace Heap {
+
+struct MemberData : Base {
+ MemberData(InternalClass *c)
+ : Base(c), size(0) {}
+ union {
+ uint size;
+ double _dummy;
+ };
+ Value data[1];
+};
+
+}
+
struct MemberData : Managed
{
- struct Data : Managed::Data {
- union {
- uint size;
- double _dummy;
- };
- Value data[1];
- };
- V4_MANAGED(Managed)
+ V4_MANAGED(MemberData, Managed)
- MemberData(QV4::InternalClass *ic) : Managed(ic) {}
Value &operator[] (uint idx) { return d()->data[idx]; }
+ const Value *data() const { return d()->data; }
+ Value *data() { return d()->data; }
+ inline uint size() const { return d()->size; }
- static void markObjects(Managed *that, ExecutionEngine *e);
-};
-
-struct Members : Value
-{
- void reset() { m = 0; }
- void ensureIndex(QV4::ExecutionEngine *e, uint idx);
- Value &operator[] (uint idx) const { return static_cast<MemberData *>(managed())->d()->data[idx]; }
- inline uint size() const { return d() ? d()->d()->size : 0; }
- inline MemberData *d() const { return static_cast<MemberData *>(managed()); }
- Value *data() const { return static_cast<MemberData *>(managed())->d()->data; }
+ static Heap::MemberData *reallocate(QV4::ExecutionEngine *e, Heap::MemberData *old, uint idx);
- void mark(ExecutionEngine *e) const {
- MemberData *m = d();
- if (m)
- m->mark(e);
- }
+ static void markObjects(Heap::Base *that, ExecutionEngine *e);
};
}
diff --git a/src/qml/jsruntime/qv4mm.cpp b/src/qml/jsruntime/qv4mm.cpp
index 975a5d5833..c5538a8c7f 100644
--- a/src/qml/jsruntime/qv4mm.cpp
+++ b/src/qml/jsruntime/qv4mm.cpp
@@ -64,20 +64,29 @@
#include <pthread_np.h>
#endif
+using namespace WTF;
+
QT_BEGIN_NAMESPACE
using namespace QV4;
-using namespace WTF;
struct MemoryManager::Data
{
+ struct ChunkHeader {
+ Heap::Base freeItems;
+ ChunkHeader *nextNonFull;
+ char *itemStart;
+ char *itemEnd;
+ int itemSize;
+ };
+
bool gcBlocked;
bool aggressiveGC;
bool gcStats;
ExecutionEngine *engine;
enum { MaxItemSize = 512 };
- Managed *smallItems[MaxItemSize/16];
+ ChunkHeader *nonFullChunks[MaxItemSize/16];
uint nChunks[MaxItemSize/16];
uint availableItems[MaxItemSize/16];
uint allocCount[MaxItemSize/16];
@@ -85,21 +94,15 @@ struct MemoryManager::Data
int totalAlloc;
uint maxShift;
std::size_t maxChunkSize;
- struct Chunk {
- PageAllocation memory;
- int chunkSize;
- };
-
- QVector<Chunk> heapChunks;
-
+ QVector<PageAllocation> heapChunks;
struct LargeItem {
LargeItem *next;
size_t size;
void *data;
- Managed *managed() {
- return reinterpret_cast<Managed *>(&data);
+ Heap::Base *heapObject() {
+ return reinterpret_cast<Heap::Base *>(&data);
}
};
@@ -124,7 +127,7 @@ struct MemoryManager::Data
, totalLargeItemsAllocated(0)
, deletable(0)
{
- memset(smallItems, 0, sizeof(smallItems));
+ memset(nonFullChunks, 0, sizeof(nonFullChunks));
memset(nChunks, 0, sizeof(nChunks));
memset(availableItems, 0, sizeof(availableItems));
memset(allocCount, 0, sizeof(allocCount));
@@ -145,22 +148,65 @@ struct MemoryManager::Data
~Data()
{
- for (QVector<Chunk>::iterator i = heapChunks.begin(), ei = heapChunks.end(); i != ei; ++i) {
- Q_V4_PROFILE_DEALLOC(engine, 0, i->memory.size(), Profiling::HeapPage);
- i->memory.deallocate();
+ for (QVector<PageAllocation>::iterator i = heapChunks.begin(), ei = heapChunks.end(); i != ei; ++i) {
+ Q_V4_PROFILE_DEALLOC(engine, 0, i->size(), Profiling::HeapPage);
+ i->deallocate();
}
}
};
+namespace {
-namespace QV4 {
-
-bool operator<(const MemoryManager::Data::Chunk &a, const MemoryManager::Data::Chunk &b)
+bool sweepChunk(MemoryManager::Data::ChunkHeader *header, uint *itemsInUse, ExecutionEngine *engine)
{
- return a.memory.base() < b.memory.base();
+ bool isEmpty = true;
+ Heap::Base *tail = &header->freeItems;
+// qDebug("chunkStart @ %p, size=%x, pos=%x", header->itemStart, header->itemSize, header->itemSize>>4);
+#ifdef V4_USE_VALGRIND
+ VALGRIND_DISABLE_ERROR_REPORTING;
+#endif
+ for (char *item = header->itemStart; item <= header->itemEnd; item += header->itemSize) {
+ Heap::Base *m = reinterpret_cast<Heap::Base *>(item);
+// qDebug("chunk @ %p, size = %lu, in use: %s, mark bit: %s",
+// item, m->size, (m->inUse ? "yes" : "no"), (m->markBit ? "true" : "false"));
+
+ Q_ASSERT((qintptr) item % 16 == 0);
+
+ if (m->isMarked()) {
+ Q_ASSERT(m->inUse());
+ m->clearMarkBit();
+ isEmpty = false;
+ ++(*itemsInUse);
+ } else {
+ if (m->inUse()) {
+// qDebug() << "-- collecting it." << m << tail << m->nextFree();
+#ifdef V4_USE_VALGRIND
+ VALGRIND_ENABLE_ERROR_REPORTING;
+#endif
+ if (m->gcGetInternalClass()->vtable->destroy)
+ m->gcGetInternalClass()->vtable->destroy(m);
+
+ memset(m, 0, header->itemSize);
+#ifdef V4_USE_VALGRIND
+ VALGRIND_DISABLE_ERROR_REPORTING;
+ VALGRIND_MEMPOOL_FREE(engine->memoryManager, m);
+#endif
+ Q_V4_PROFILE_DEALLOC(engine, m, header->itemSize, Profiling::SmallItem);
+ ++(*itemsInUse);
+ }
+ // Relink all free blocks to rewrite references to any released chunk.
+ tail->setNextFree(m);
+ tail = m;
+ }
+ }
+ tail->setNextFree(0);
+#ifdef V4_USE_VALGRIND
+ VALGRIND_ENABLE_ERROR_REPORTING;
+#endif
+ return isEmpty;
}
-} // namespace QV4
+} // namespace
MemoryManager::MemoryManager()
: m_d(new Data)
@@ -172,7 +218,7 @@ MemoryManager::MemoryManager()
#endif
}
-Managed *MemoryManager::allocData(std::size_t size)
+Heap::Base *MemoryManager::allocData(std::size_t size)
{
if (m_d->aggressiveGC)
runGC();
@@ -199,19 +245,24 @@ Managed *MemoryManager::allocData(std::size_t size)
item->size = size;
m_d->largeItems = item;
m_d->totalLargeItemsAllocated += size;
- return item->managed();
+ return item->heapObject();
}
- Managed *m = m_d->smallItems[pos];
- if (m)
+ Heap::Base *m = 0;
+ Data::ChunkHeader *header = m_d->nonFullChunks[pos];
+ if (header) {
+ m = header->freeItems.nextFree();
goto found;
+ }
// try to free up space, otherwise allocate
if (m_d->allocCount[pos] > (m_d->availableItems[pos] >> 1) && m_d->totalAlloc > (m_d->totalItems >> 1) && !m_d->aggressiveGC) {
runGC();
- m = m_d->smallItems[pos];
- if (m)
+ header = m_d->nonFullChunks[pos];
+ if (header) {
+ m = header->freeItems.nextFree();
goto found;
+ }
}
// no free item available, allocate a new chunk
@@ -222,30 +273,35 @@ Managed *MemoryManager::allocData(std::size_t size)
shift = m_d->maxShift;
std::size_t allocSize = m_d->maxChunkSize*(size_t(1) << shift);
allocSize = roundUpToMultipleOf(WTF::pageSize(), allocSize);
- Data::Chunk allocation;
- allocation.memory = PageAllocation::allocate(
+ PageAllocation allocation = PageAllocation::allocate(
Q_V4_PROFILE_ALLOC(m_d->engine, allocSize, Profiling::HeapPage),
OSAllocator::JSGCHeapPages);
- allocation.chunkSize = int(size);
m_d->heapChunks.append(allocation);
std::sort(m_d->heapChunks.begin(), m_d->heapChunks.end());
- char *chunk = (char *)allocation.memory.base();
- char *end = chunk + allocation.memory.size() - size;
-
- Managed **last = &m_d->smallItems[pos];
- while (chunk <= end) {
- Managed *o = reinterpret_cast<Managed *>(chunk);
- *last = o;
- last = o->nextFreeRef();
- chunk += size;
+
+ header = reinterpret_cast<Data::ChunkHeader *>(allocation.base());
+ header->itemSize = int(size);
+ header->itemStart = reinterpret_cast<char *>(allocation.base()) + roundUpToMultipleOf(16, sizeof(Data::ChunkHeader));
+ header->itemEnd = reinterpret_cast<char *>(allocation.base()) + allocation.size() - header->itemSize;
+
+ header->nextNonFull = m_d->nonFullChunks[pos];
+ m_d->nonFullChunks[pos] = header;
+
+ Heap::Base *last = &header->freeItems;
+ for (char *item = header->itemStart; item <= header->itemEnd; item += header->itemSize) {
+ Heap::Base *o = reinterpret_cast<Heap::Base *>(item);
+ last->setNextFree(o);
+ last = o;
+
}
- *last = 0;
- m = m_d->smallItems[pos];
- const size_t increase = allocation.memory.size()/size - 1;
+ last->setNextFree(0);
+ m = header->freeItems.nextFree();
+ const size_t increase = (header->itemEnd - header->itemStart) / header->itemSize;
m_d->availableItems[pos] += uint(increase);
m_d->totalItems += int(increase);
#ifdef V4_USE_VALGRIND
- VALGRIND_MAKE_MEM_NOACCESS(allocation.memory.base(), allocSize);
+ VALGRIND_MAKE_MEM_NOACCESS(allocation.base(), allocSize);
+ VALGRIND_MEMPOOL_ALLOC(this, header, sizeof(Data::ChunkHeader));
#endif
}
@@ -257,16 +313,18 @@ Managed *MemoryManager::allocData(std::size_t size)
++m_d->allocCount[pos];
++m_d->totalAlloc;
- m_d->smallItems[pos] = m->nextFree();
+ header->freeItems.setNextFree(m->nextFree());
+ if (!header->freeItems.nextFree())
+ m_d->nonFullChunks[pos] = header->nextNonFull;
return m;
}
static void drainMarkStack(QV4::ExecutionEngine *engine, Value *markBase)
{
while (engine->jsStackTop > markBase) {
- Managed *m = engine->popForGC();
- Q_ASSERT (m->internalClass()->vtable->markObjects);
- m->internalClass()->vtable->markObjects(m, engine);
+ Heap::Base *h = engine->popForGC();
+ Q_ASSERT (h->gcGetInternalClass()->vtable->markObjects);
+ h->gcGetInternalClass()->vtable->markObjects(h, engine);
}
}
@@ -301,12 +359,14 @@ void MemoryManager::mark()
// managed objects in the loop down there doesn't make then end up as leftovers
// on the stack and thus always get collected.
for (PersistentValuePrivate *weak = m_weakValues; weak; weak = weak->next) {
- if (!weak->refcount)
+ if (!weak->refcount || !weak->value.isManaged())
+ continue;
+ if (weak->value.asManaged()->d()->gcGetInternalClass()->vtable != QObjectWrapper::staticVTable())
continue;
- Returned<QObjectWrapper> *qobjectWrapper = weak->value.as<QObjectWrapper>();
+ QObjectWrapper *qobjectWrapper = static_cast<QObjectWrapper*>(weak->value.managed());
if (!qobjectWrapper)
continue;
- QObject *qobject = qobjectWrapper->getPointer()->object();
+ QObject *qobject = qobjectWrapper->object();
if (!qobject)
continue;
bool keepAlive = QQmlData::keepAliveDuringGarbageCollection(qobject);
@@ -321,7 +381,7 @@ void MemoryManager::mark()
}
if (keepAlive)
- qobjectWrapper->getPointer()->mark(m_d->engine);
+ qobjectWrapper->mark(m_d->engine);
if (m_d->engine->jsStackTop >= m_d->engine->jsStackLimit)
drainMarkStack(m_d->engine, markBase);
@@ -362,22 +422,55 @@ void MemoryManager::sweep(bool lastSweep)
}
}
- for (QVector<Data::Chunk>::iterator i = m_d->heapChunks.begin(), ei = m_d->heapChunks.end(); i != ei; ++i)
- sweep(reinterpret_cast<char*>(i->memory.base()), i->memory.size(), i->chunkSize);
+ bool *chunkIsEmpty = (bool *)alloca(m_d->heapChunks.size() * sizeof(bool));
+ uint itemsInUse[MemoryManager::Data::MaxItemSize/16];
+ memset(itemsInUse, 0, sizeof(itemsInUse));
+ memset(m_d->nonFullChunks, 0, sizeof(m_d->nonFullChunks));
+
+ for (int i = 0; i < m_d->heapChunks.size(); ++i) {
+ Data::ChunkHeader *header = reinterpret_cast<Data::ChunkHeader *>(m_d->heapChunks[i].base());
+ chunkIsEmpty[i] = sweepChunk(header, &itemsInUse[header->itemSize >> 4], m_d->engine);
+ }
+
+ QVector<PageAllocation>::iterator chunkIter = m_d->heapChunks.begin();
+ for (int i = 0; i < m_d->heapChunks.size(); ++i) {
+ Q_ASSERT(chunkIter != m_d->heapChunks.end());
+ Data::ChunkHeader *header = reinterpret_cast<Data::ChunkHeader *>(chunkIter->base());
+ const size_t pos = header->itemSize >> 4;
+ const size_t decrease = (header->itemEnd - header->itemStart) / header->itemSize;
+
+ // Release that chunk if it could have been spared since the last GC run without any difference.
+ if (chunkIsEmpty[i] && m_d->availableItems[pos] - decrease >= itemsInUse[pos]) {
+ Q_V4_PROFILE_DEALLOC(m_d->engine, 0, chunkIter->size(), Profiling::HeapPage);
+#ifdef V4_USE_VALGRIND
+ VALGRIND_MEMPOOL_FREE(this, header);
+#endif
+ --m_d->nChunks[pos];
+ m_d->availableItems[pos] -= uint(decrease);
+ m_d->totalItems -= int(decrease);
+ chunkIter->deallocate();
+ chunkIter = m_d->heapChunks.erase(chunkIter);
+ continue;
+ } else if (header->freeItems.nextFree()) {
+ header->nextNonFull = m_d->nonFullChunks[pos];
+ m_d->nonFullChunks[pos] = header;
+ }
+ ++chunkIter;
+ }
Data::LargeItem *i = m_d->largeItems;
Data::LargeItem **last = &m_d->largeItems;
while (i) {
- Managed *m = i->managed();
+ Heap::Base *m = i->heapObject();
Q_ASSERT(m->inUse());
- if (m->markBit()) {
- m->d()->markBit = 0;
+ if (m->isMarked()) {
+ m->clearMarkBit();
last = &i->next;
i = i->next;
continue;
}
- if (m->internalClass()->vtable->destroy)
- m->internalClass()->vtable->destroy(m);
+ if (m->gcGetInternalClass()->vtable->destroy)
+ m->gcGetInternalClass()->vtable->destroy(m);
*last = i->next;
free(Q_V4_PROFILE_DEALLOC(m_d->engine, i, i->size + sizeof(Data::LargeItem),
@@ -393,48 +486,15 @@ void MemoryManager::sweep(bool lastSweep)
delete deletable;
deletable = next;
}
-}
-
-void MemoryManager::sweep(char *chunkStart, std::size_t chunkSize, size_t size)
-{
-// qDebug("chunkStart @ %p, size=%x, pos=%x (%x)", chunkStart, size, size>>4, m_d->smallItems[size >> 4]);
- Managed **f = &m_d->smallItems[size >> 4];
-
-#ifdef V4_USE_VALGRIND
- VALGRIND_DISABLE_ERROR_REPORTING;
-#endif
- for (char *chunk = chunkStart, *chunkEnd = chunk + chunkSize - size; chunk <= chunkEnd; chunk += size) {
- Managed *m = reinterpret_cast<Managed *>(chunk);
-// qDebug("chunk @ %p, size = %lu, in use: %s, mark bit: %s",
-// chunk, m->size, (m->inUse ? "yes" : "no"), (m->markBit ? "true" : "false"));
-
- Q_ASSERT((qintptr) chunk % 16 == 0);
-
- if (m->inUse()) {
- if (m->markBit()) {
- m->d()->markBit = 0;
- } else {
-// qDebug() << "-- collecting it." << m << *f << m->nextFree();
-#ifdef V4_USE_VALGRIND
- VALGRIND_ENABLE_ERROR_REPORTING;
-#endif
- if (m->internalClass()->vtable->destroy)
- m->internalClass()->vtable->destroy(m);
- memset(m, 0, size);
- m->setNextFree(*f);
-#ifdef V4_USE_VALGRIND
- VALGRIND_DISABLE_ERROR_REPORTING;
- VALGRIND_MEMPOOL_FREE(this, m);
-#endif
- Q_V4_PROFILE_DEALLOC(m_d->engine, m, size, Profiling::SmallItem);
- *f = m;
- }
+ // some execution contexts are allocated on the stack, make sure we clear their markBit as well
+ if (!lastSweep) {
+ Heap::ExecutionContext *ctx = engine()->current;
+ while (ctx) {
+ ctx->clearMarkBit();
+ ctx = ctx->parent;
}
}
-#ifdef V4_USE_VALGRIND
- VALGRIND_ENABLE_ERROR_REPORTING;
-#endif
}
bool MemoryManager::isGCBlocked() const
@@ -466,6 +526,7 @@ void MemoryManager::runGC()
int markTime = t.elapsed();
t.restart();
int usedBefore = getUsedMem();
+ int chunksBefore = m_d->heapChunks.size();
sweep();
int usedAfter = getUsedMem();
int sweepTime = t.elapsed();
@@ -477,6 +538,7 @@ void MemoryManager::runGC()
qDebug() << "Used memory before GC:" << usedBefore;
qDebug() << "Used memory after GC:" << usedAfter;
qDebug() << "Freed up bytes:" << (usedBefore - usedAfter);
+ qDebug() << "Released chunks:" << (chunksBefore - m_d->heapChunks.size());
qDebug() << "======== End GC ========";
}
@@ -488,14 +550,13 @@ void MemoryManager::runGC()
size_t MemoryManager::getUsedMem() const
{
size_t usedMem = 0;
- for (QVector<Data::Chunk>::const_iterator i = m_d->heapChunks.begin(), ei = m_d->heapChunks.end(); i != ei; ++i) {
- char *chunkStart = reinterpret_cast<char *>(i->memory.base());
- char *chunkEnd = chunkStart + i->memory.size() - i->chunkSize;
- for (char *chunk = chunkStart; chunk <= chunkEnd; chunk += i->chunkSize) {
- Managed *m = reinterpret_cast<Managed *>(chunk);
- Q_ASSERT((qintptr) chunk % 16 == 0);
+ for (QVector<PageAllocation>::const_iterator i = m_d->heapChunks.begin(), ei = m_d->heapChunks.end(); i != ei; ++i) {
+ Data::ChunkHeader *header = reinterpret_cast<Data::ChunkHeader *>(i->base());
+ for (char *item = header->itemStart; item <= header->itemEnd; item += header->itemSize) {
+ Heap::Base *m = reinterpret_cast<Heap::Base *>(item);
+ Q_ASSERT((qintptr) item % 16 == 0);
if (m->inUse())
- usedMem += i->chunkSize;
+ usedMem += header->itemSize;
}
}
return usedMem;
@@ -505,7 +566,7 @@ size_t MemoryManager::getAllocatedMem() const
{
size_t total = 0;
for (int i = 0; i < m_d->heapChunks.size(); ++i)
- total += m_d->heapChunks.at(i).memory.size();
+ total += m_d->heapChunks.at(i).size();
return total;
}
@@ -535,6 +596,11 @@ MemoryManager::~MemoryManager()
#endif
}
+ExecutionEngine *MemoryManager::engine() const
+{
+ return m_d->engine;
+}
+
void MemoryManager::setExecutionEngine(ExecutionEngine *engine)
{
m_d->engine = engine;
diff --git a/src/qml/jsruntime/qv4mm_p.h b/src/qml/jsruntime/qv4mm_p.h
index d5e28f7f84..5c21294ad0 100644
--- a/src/qml/jsruntime/qv4mm_p.h
+++ b/src/qml/jsruntime/qv4mm_p.h
@@ -35,10 +35,8 @@
#define QV4GC_H
#include "qv4global_p.h"
-#include "qv4context_p.h"
#include "qv4value_inl_p.h"
-
-#include <QScopedPointer>
+#include "qv4scopedvalue_p.h"
//#define DETAILED_MM_STATS
@@ -46,9 +44,6 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
-struct ExecutionEngine;
-struct ExecutionContext;
-struct Managed;
struct GCDeletable;
class Q_QML_EXPORT MemoryManager
@@ -88,65 +83,72 @@ public:
static inline std::size_t align(std::size_t size)
{ return (size + 15) & ~0xf; }
- inline Managed *allocManaged(std::size_t size)
+ inline Heap::Base *allocManaged(std::size_t size)
{
size = align(size);
- Managed *o = allocData(size);
+ Heap::Base *o = allocData(size);
return o;
}
template <typename ManagedType>
- ManagedType *alloc()
+ typename ManagedType::Data *alloc()
{
- ManagedType *t = static_cast<ManagedType*>(allocManaged(sizeof(typename ManagedType::Data)));
+ Scope scope(engine());
+ Scoped<ManagedType> t(scope, static_cast<typename ManagedType::Data *>(allocManaged(sizeof(typename ManagedType::Data))));
(void)new (t->d()) typename ManagedType::Data();
- return t;
+ return t->d();
}
template <typename ManagedType, typename Arg1>
- ManagedType *alloc(Arg1 arg1)
+ typename ManagedType::Data *alloc(Arg1 arg1)
{
- ManagedType *t = static_cast<ManagedType*>(allocManaged(sizeof(typename ManagedType::Data)));
+ Scope scope(engine());
+ Scoped<ManagedType> t(scope, static_cast<typename ManagedType::Data *>(allocManaged(sizeof(typename ManagedType::Data))));
(void)new (t->d()) typename ManagedType::Data(arg1);
- return t;
+ return t->d();
}
template <typename ManagedType, typename Arg1, typename Arg2>
- ManagedType *alloc(Arg1 arg1, Arg2 arg2)
+ typename ManagedType::Data *alloc(Arg1 arg1, Arg2 arg2)
{
- ManagedType *t = static_cast<ManagedType*>(allocManaged(sizeof(typename ManagedType::Data)));
+ Scope scope(engine());
+ Scoped<ManagedType> t(scope, static_cast<typename ManagedType::Data *>(allocManaged(sizeof(typename ManagedType::Data))));
(void)new (t->d()) typename ManagedType::Data(arg1, arg2);
- return t;
+ return t->d();
}
template <typename ManagedType, typename Arg1, typename Arg2, typename Arg3>
- ManagedType *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3)
+ typename ManagedType::Data *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3)
{
- ManagedType *t = static_cast<ManagedType*>(allocManaged(sizeof(typename ManagedType::Data)));
+ Scope scope(engine());
+ Scoped<ManagedType> t(scope, static_cast<typename ManagedType::Data *>(allocManaged(sizeof(typename ManagedType::Data))));
(void)new (t->d()) typename ManagedType::Data(arg1, arg2, arg3);
- return t;
+ return t->d();
}
template <typename ManagedType, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
- ManagedType *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4)
+ typename ManagedType::Data *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4)
{
- ManagedType *t = static_cast<ManagedType*>(allocManaged(sizeof(typename ManagedType::Data)));
+ Scope scope(engine());
+ Scoped<ManagedType> t(scope, static_cast<typename ManagedType::Data *>(allocManaged(sizeof(typename ManagedType::Data))));
(void)new (t->d()) typename ManagedType::Data(arg1, arg2, arg3, arg4);
- return t;
+ return t->d();
}
template <typename ManagedType, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5>
- ManagedType *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5)
+ typename ManagedType::Data *alloc(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5)
{
- ManagedType *t = static_cast<ManagedType*>(allocManaged(sizeof(typename ManagedType::Data)));
+ Scope scope(engine());
+ Scoped<ManagedType> t(scope, static_cast<typename ManagedType::Data *>(allocManaged(sizeof(typename ManagedType::Data))));
(void)new (t->d()) typename ManagedType::Data(arg1, arg2, arg3, arg4, arg5);
- return t;
+ return t->d();
}
bool isGCBlocked() const;
void setGCBlocked(bool blockGC);
void runGC();
+ ExecutionEngine *engine() const;
void setExecutionEngine(ExecutionEngine *engine);
void dumpStats() const;
@@ -160,7 +162,7 @@ public:
protected:
/// expects size to be aligned
// TODO: try to inline
- Managed *allocData(std::size_t size);
+ Heap::Base *allocData(std::size_t size);
#ifdef DETAILED_MM_STATS
void willAllocate(std::size_t size);
@@ -170,7 +172,6 @@ private:
void collectFromJSStack() const;
void mark();
void sweep(bool lastSweep = false);
- void sweep(char *chunkStart, std::size_t chunkSize, size_t size);
protected:
QScopedPointer<Data> m_d;
diff --git a/src/qml/jsruntime/qv4numberobject.cpp b/src/qml/jsruntime/qv4numberobject.cpp
index 227ff14104..404ad8f61e 100644
--- a/src/qml/jsruntime/qv4numberobject.cpp
+++ b/src/qml/jsruntime/qv4numberobject.cpp
@@ -32,6 +32,8 @@
****************************************************************************/
#include "qv4numberobject_p.h"
+#include "qv4runtime_p.h"
+
#include <QtCore/qnumeric.h>
#include <QtCore/qmath.h>
#include <QtCore/QDebug>
@@ -43,10 +45,10 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(NumberCtor);
DEFINE_OBJECT_VTABLE(NumberObject);
-NumberCtor::Data::Data(ExecutionContext *scope)
- : FunctionObject::Data(scope, QStringLiteral("Number"))
+Heap::NumberCtor::NumberCtor(QV4::ExecutionContext *scope)
+ : Heap::FunctionObject(scope, QStringLiteral("Number"))
{
- setVTable(staticVTable());
+ setVTable(QV4::NumberCtor::staticVTable());
}
ReturnedValue NumberCtor::construct(Managed *m, CallData *callData)
@@ -99,7 +101,7 @@ inline ReturnedValue thisNumberValue(ExecutionContext *ctx)
return ctx->d()->callData->thisObject.asReturnedValue();
NumberObject *n = ctx->d()->callData->thisObject.asNumberObject();
if (!n)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
return n->value().asReturnedValue();
}
@@ -109,26 +111,27 @@ inline double thisNumber(ExecutionContext *ctx)
return ctx->d()->callData->thisObject.asDouble();
NumberObject *n = ctx->d()->callData->thisObject.asNumberObject();
if (!n)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
return n->value().asDouble();
}
ReturnedValue NumberPrototype::method_toString(CallContext *ctx)
{
+ Scope scope(ctx);
double num = thisNumber(ctx);
- if (ctx->d()->engine->hasException)
+ if (scope.engine->hasException)
return Encode::undefined();
if (ctx->d()->callData->argc && !ctx->d()->callData->args[0].isUndefined()) {
int radix = ctx->d()->callData->args[0].toInt32();
if (radix < 2 || radix > 36)
- return ctx->throwError(QString::fromLatin1("Number.prototype.toString: %0 is not a valid radix")
+ return ctx->engine()->throwError(QString::fromLatin1("Number.prototype.toString: %0 is not a valid radix")
.arg(radix));
if (std::isnan(num)) {
- return ctx->d()->engine->newString(QStringLiteral("NaN"))->asReturnedValue();
+ return scope.engine->newString(QStringLiteral("NaN"))->asReturnedValue();
} else if (qIsInf(num)) {
- return ctx->d()->engine->newString(QLatin1String(num < 0 ? "-Infinity" : "Infinity"))->asReturnedValue();
+ return scope.engine->newString(QLatin1String(num < 0 ? "-Infinity" : "Infinity"))->asReturnedValue();
}
if (radix != 10) {
@@ -158,19 +161,19 @@ ReturnedValue NumberPrototype::method_toString(CallContext *ctx)
}
if (negative)
str.prepend(QLatin1Char('-'));
- return ctx->d()->engine->newString(str)->asReturnedValue();
+ return scope.engine->newString(str)->asReturnedValue();
}
}
- return Primitive::fromDouble(num).toString(ctx)->asReturnedValue();
+ return Primitive::fromDouble(num).toString(scope.engine)->asReturnedValue();
}
ReturnedValue NumberPrototype::method_toLocaleString(CallContext *ctx)
{
Scope scope(ctx);
ScopedValue v(scope, thisNumberValue(ctx));
- ScopedString str(scope, v->toString(ctx));
- if (ctx->d()->engine->hasException)
+ ScopedString str(scope, v->toString(scope.engine));
+ if (scope.engine->hasException)
return Encode::undefined();
return str.asReturnedValue();
}
@@ -182,8 +185,9 @@ ReturnedValue NumberPrototype::method_valueOf(CallContext *ctx)
ReturnedValue NumberPrototype::method_toFixed(CallContext *ctx)
{
+ Scope scope(ctx);
double v = thisNumber(ctx);
- if (ctx->d()->engine->hasException)
+ if (scope.engine->hasException)
return Encode::undefined();
double fdigits = 0;
@@ -195,7 +199,7 @@ ReturnedValue NumberPrototype::method_toFixed(CallContext *ctx)
fdigits = 0;
if (fdigits < 0 || fdigits > 20)
- return ctx->throwRangeError(ctx->d()->callData->thisObject);
+ return ctx->engine()->throwRangeError(ctx->d()->callData->thisObject);
QString str;
if (std::isnan(v))
@@ -205,15 +209,15 @@ ReturnedValue NumberPrototype::method_toFixed(CallContext *ctx)
else if (v < 1.e21)
str = QString::number(v, 'f', int (fdigits));
else
- return RuntimeHelpers::stringFromNumber(ctx, v)->asReturnedValue();
- return ctx->d()->engine->newString(str)->asReturnedValue();
+ return RuntimeHelpers::stringFromNumber(ctx->engine(), v)->asReturnedValue();
+ return scope.engine->newString(str)->asReturnedValue();
}
ReturnedValue NumberPrototype::method_toExponential(CallContext *ctx)
{
Scope scope(ctx);
double d = thisNumber(ctx);
- if (ctx->d()->engine->hasException)
+ if (scope.engine->hasException)
return Encode::undefined();
int fdigits = -1;
@@ -221,8 +225,8 @@ ReturnedValue NumberPrototype::method_toExponential(CallContext *ctx)
if (ctx->d()->callData->argc && !ctx->d()->callData->args[0].isUndefined()) {
fdigits = ctx->d()->callData->args[0].toInt32();
if (fdigits < 0 || fdigits > 20) {
- ScopedString error(scope, ctx->d()->engine->newString(QStringLiteral("Number.prototype.toExponential: fractionDigits out of range")));
- return ctx->throwRangeError(error);
+ ScopedString error(scope, scope.engine->newString(QStringLiteral("Number.prototype.toExponential: fractionDigits out of range")));
+ return ctx->engine()->throwRangeError(error);
}
}
@@ -231,23 +235,23 @@ ReturnedValue NumberPrototype::method_toExponential(CallContext *ctx)
double_conversion::DoubleToStringConverter::EcmaScriptConverter().ToExponential(d, fdigits, &builder);
QString result = QString::fromLatin1(builder.Finalize());
- return ctx->d()->engine->newString(result)->asReturnedValue();
+ return scope.engine->newString(result)->asReturnedValue();
}
ReturnedValue NumberPrototype::method_toPrecision(CallContext *ctx)
{
Scope scope(ctx);
ScopedValue v(scope, thisNumberValue(ctx));
- if (ctx->d()->engine->hasException)
+ if (scope.engine->hasException)
return Encode::undefined();
if (!ctx->d()->callData->argc || ctx->d()->callData->args[0].isUndefined())
- return RuntimeHelpers::toString(ctx, v);
+ return RuntimeHelpers::toString(scope.engine, v);
double precision = ctx->d()->callData->args[0].toInt32();
if (precision < 1 || precision > 21) {
- ScopedString error(scope, ctx->d()->engine->newString(QStringLiteral("Number.prototype.toPrecision: precision out of range")));
- return ctx->throwRangeError(error);
+ ScopedString error(scope, scope.engine->newString(QStringLiteral("Number.prototype.toPrecision: precision out of range")));
+ return ctx->engine()->throwRangeError(error);
}
char str[100];
@@ -255,5 +259,5 @@ ReturnedValue NumberPrototype::method_toPrecision(CallContext *ctx)
double_conversion::DoubleToStringConverter::EcmaScriptConverter().ToPrecision(v->asDouble(), precision, &builder);
QString result = QString::fromLatin1(builder.Finalize());
- return ctx->d()->engine->newString(result)->asReturnedValue();
+ return scope.engine->newString(result)->asReturnedValue();
}
diff --git a/src/qml/jsruntime/qv4numberobject_p.h b/src/qml/jsruntime/qv4numberobject_p.h
index 9edaf09749..01a8773b73 100644
--- a/src/qml/jsruntime/qv4numberobject_p.h
+++ b/src/qml/jsruntime/qv4numberobject_p.h
@@ -41,12 +41,17 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
+namespace Heap {
+
+struct NumberCtor : FunctionObject {
+ NumberCtor(QV4::ExecutionContext *scope);
+};
+
+}
+
struct NumberCtor: FunctionObject
{
- struct Data : FunctionObject::Data {
- Data(ExecutionContext *scope);
- };
- V4_OBJECT(FunctionObject)
+ V4_OBJECT2(NumberCtor, FunctionObject)
static ReturnedValue construct(Managed *that, CallData *callData);
static ReturnedValue call(Managed *, CallData *callData);
diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp
index 0c61d666ab..d30c113c32 100644
--- a/src/qml/jsruntime/qv4object.cpp
+++ b/src/qml/jsruntime/qv4object.cpp
@@ -41,66 +41,55 @@
#include "qv4lookup_p.h"
#include "qv4scopedvalue_p.h"
#include "qv4memberdata_p.h"
+#include "qv4objectiterator_p.h"
+#include "qv4identifier_p.h"
-#include <private/qqmljsengine_p.h>
-#include <private/qqmljslexer_p.h>
-#include <private/qqmljsparser_p.h>
-#include <private/qqmljsast_p.h>
-#include <qv4jsir_p.h>
-#include <qv4codegen_p.h>
-#include "private/qlocale_tools_p.h"
-
-#include <QtCore/qmath.h>
-#include <QtCore/QDebug>
-#include <cassert>
-#include <typeinfo>
-#include <iostream>
#include <stdint.h>
-#include "qv4alloca_p.h"
using namespace QV4;
DEFINE_OBJECT_VTABLE(Object);
-Object::Data::Data(InternalClass *internalClass)
- : Managed::Data(internalClass)
+Heap::Object::Object(InternalClass *internalClass, QV4::Object *prototype)
+ : Heap::Base(internalClass),
+ prototype(prototype ? prototype->d() : 0)
{
if (internalClass->size) {
Scope scope(internalClass->engine);
ScopedObject o(scope, this);
- o->memberData().ensureIndex(internalClass->engine, internalClass->size);
+ o->ensureMemberIndex(internalClass->engine, internalClass->size);
}
}
bool Object::setPrototype(Object *proto)
{
- Object *pp = proto;
+ Heap::Object *pp = proto ? proto->d() : 0;
while (pp) {
- if (pp == this)
+ if (pp == d())
return false;
- pp = pp->prototype();
+ pp = pp->prototype;
}
- setInternalClass(internalClass()->changePrototype(proto));
+ d()->prototype = proto ? proto->d() : 0;
return true;
}
-void Object::put(ExecutionContext *ctx, const QString &name, const ValueRef value)
+void Object::put(ExecutionEngine *engine, const QString &name, const ValueRef value)
{
- Scope scope(ctx);
- ScopedString n(scope, ctx->d()->engine->newString(name));
- put(n.getPointer(), value);
+ Scope scope(engine);
+ ScopedString n(scope, engine->newString(name));
+ put(n, value);
}
ReturnedValue Object::getValue(const ValueRef thisObject, const Property *p, PropertyAttributes attrs)
{
if (!attrs.isAccessor())
return p->value.asReturnedValue();
- FunctionObject *getter = p->getter();
- if (!getter)
+ if (!p->getter())
return Encode::undefined();
- Scope scope(getter->engine());
- ScopedCallData callData(scope, 0);
+ Scope scope(p->getter()->internalClass->engine);
+ ScopedFunctionObject getter(scope, p->getter());
+ ScopedCallData callData(scope);
callData->thisObject = *thisObject;
return getter->call(callData);
}
@@ -111,12 +100,13 @@ void Object::putValue(Property *pd, PropertyAttributes attrs, const ValueRef val
return;
if (attrs.isAccessor()) {
- if (FunctionObject *set = pd->setter()) {
- Scope scope(set->engine());
+ if (Heap::FunctionObject *set = pd->setter()) {
+ Scope scope(set->internalClass->engine);
+ ScopedFunctionObject setter(scope, set);
ScopedCallData callData(scope, 1);
callData->args[0] = *value;
callData->thisObject = this;
- set->call(callData);
+ setter->call(callData);
return;
}
goto reject;
@@ -129,8 +119,8 @@ void Object::putValue(Property *pd, PropertyAttributes attrs, const ValueRef val
return;
reject:
- if (engine()->currentContext()->d()->strictMode)
- engine()->currentContext()->throwTypeError();
+ if (engine()->currentContext()->strictMode)
+ engine()->throwTypeError();
}
void Object::defineDefaultProperty(const QString &name, ValueRef value)
@@ -138,7 +128,7 @@ void Object::defineDefaultProperty(const QString &name, ValueRef value)
ExecutionEngine *e = engine();
Scope scope(e);
ScopedString s(scope, e->newIdentifier(name));
- defineDefaultProperty(s.getPointer(), value);
+ defineDefaultProperty(s, value);
}
void Object::defineDefaultProperty(const QString &name, ReturnedValue (*code)(CallContext *), int argumentCount)
@@ -146,16 +136,18 @@ void Object::defineDefaultProperty(const QString &name, ReturnedValue (*code)(Ca
ExecutionEngine *e = engine();
Scope scope(e);
ScopedString s(scope, e->newIdentifier(name));
- Scoped<FunctionObject> function(scope, BuiltinFunction::create(e->rootContext, s.getPointer(), code));
+ ScopedContext global(scope, e->rootContext());
+ ScopedFunctionObject function(scope, BuiltinFunction::create(global, s, code));
function->defineReadonlyProperty(e->id_length, Primitive::fromInt32(argumentCount));
- defineDefaultProperty(s.getPointer(), function);
+ defineDefaultProperty(s, function);
}
void Object::defineDefaultProperty(String *name, ReturnedValue (*code)(CallContext *), int argumentCount)
{
ExecutionEngine *e = engine();
Scope scope(e);
- Scoped<FunctionObject> function(scope, BuiltinFunction::create(e->rootContext, name, code));
+ ScopedContext global(scope, e->rootContext());
+ ScopedFunctionObject function(scope, BuiltinFunction::create(global, name, code));
function->defineReadonlyProperty(e->id_length, Primitive::fromInt32(argumentCount));
defineDefaultProperty(name, function);
}
@@ -164,8 +156,8 @@ void Object::defineAccessorProperty(const QString &name, ReturnedValue (*getter)
{
ExecutionEngine *e = engine();
Scope scope(e);
- Scoped<String> s(scope, e->newIdentifier(name));
- defineAccessorProperty(s.getPointer(), getter, setter);
+ ScopedString s(scope, e->newIdentifier(name));
+ defineAccessorProperty(s, getter, setter);
}
void Object::defineAccessorProperty(String *name, ReturnedValue (*getter)(CallContext *), ReturnedValue (*setter)(CallContext *))
@@ -173,8 +165,9 @@ void Object::defineAccessorProperty(String *name, ReturnedValue (*getter)(CallCo
ExecutionEngine *v4 = engine();
QV4::Scope scope(v4);
ScopedProperty p(scope);
- p->setGetter(getter ? ScopedFunctionObject(scope, BuiltinFunction::create(v4->rootContext, name, getter)).getPointer() : 0);
- p->setSetter(setter ? ScopedFunctionObject(scope, BuiltinFunction::create(v4->rootContext, name, setter)).getPointer() : 0);
+ ScopedContext global(scope, scope.engine->rootContext());
+ p->setGetter(ScopedFunctionObject(scope, (getter ? BuiltinFunction::create(global, name, getter) : 0)));
+ p->setSetter(ScopedFunctionObject(scope, (setter ? BuiltinFunction::create(global, name, setter) : 0)));
insertMember(name, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
}
@@ -183,7 +176,7 @@ void Object::defineReadonlyProperty(const QString &name, ValueRef value)
QV4::ExecutionEngine *e = engine();
Scope scope(e);
ScopedString s(scope, e->newIdentifier(name));
- defineReadonlyProperty(s.getPointer(), value);
+ defineReadonlyProperty(s, value);
}
void Object::defineReadonlyProperty(String *name, ValueRef value)
@@ -191,21 +184,24 @@ void Object::defineReadonlyProperty(String *name, ValueRef value)
insertMember(name, value, Attr_ReadOnly);
}
-void Object::markObjects(Managed *that, ExecutionEngine *e)
+void Object::markObjects(Heap::Base *that, ExecutionEngine *e)
{
- Object *o = static_cast<Object *>(that);
-
- o->memberData().mark(e);
- if (o->arrayData())
- o->arrayData()->mark(e);
+ Heap::Object *o = static_cast<Heap::Object *>(that);
+
+ if (o->memberData)
+ o->memberData->mark(e);
+ if (o->arrayData)
+ o->arrayData->mark(e);
+ if (o->prototype)
+ o->prototype->mark(e);
}
void Object::ensureMemberIndex(uint idx)
{
- memberData().ensureIndex(engine(), idx);
+ d()->memberData = MemberData::reallocate(engine(), d()->memberData, idx);
}
-void Object::insertMember(String *s, const Property &p, PropertyAttributes attributes)
+void Object::insertMember(String *s, const Property *p, PropertyAttributes attributes)
{
uint idx;
InternalClass::addMember(this, s, attributes, &idx);
@@ -214,12 +210,11 @@ void Object::insertMember(String *s, const Property &p, PropertyAttributes attri
ensureMemberIndex(internalClass()->size);
if (attributes.isAccessor()) {
- setHasAccessorProperty();
Property *pp = propertyAt(idx);
- pp->value = p.value;
- pp->set = p.set;
+ pp->value = p->value;
+ pp->set = p->set;
} else {
- memberData()[idx] = p.value;
+ d()->memberData->data[idx] = p->value;
}
}
@@ -269,16 +264,16 @@ Property *Object::__getPropertyDescriptor__(String *name, PropertyAttributes *at
return __getPropertyDescriptor__(idx, attrs);
- const Object *o = this;
+ const Heap::Object *o = d();
while (o) {
- uint idx = o->internalClass()->find(name);
+ uint idx = o->internalClass->find(name);
if (idx < UINT_MAX) {
if (attrs)
- *attrs = o->internalClass()->propertyData[idx];
- return o->propertyAt(idx);
+ *attrs = o->internalClass->propertyData[idx];
+ return const_cast<Property *>(o->propertyAt(idx));
}
- o = o->prototype();
+ o = o->prototype;
}
if (attrs)
*attrs = Attr_Invalid;
@@ -287,23 +282,23 @@ Property *Object::__getPropertyDescriptor__(String *name, PropertyAttributes *at
Property *Object::__getPropertyDescriptor__(uint index, PropertyAttributes *attrs) const
{
- const Object *o = this;
+ const Heap::Object *o = d();
while (o) {
- Property *p = o->arrayData() ? o->arrayData()->getProperty(index) : 0;
+ Property *p = o->arrayData ? o->arrayData->getProperty(index) : 0;
if (p) {
if (attrs)
- *attrs = o->arrayData()->attributes(index);
+ *attrs = o->arrayData->attributes(index);
return p;
}
- if (o->isStringObject()) {
- Property *p = static_cast<const StringObject *>(o)->getIndex(index);
+ if (o->internalClass->vtable->type == Type_StringObject) {
+ Property *p = static_cast<const Heap::StringObject *>(o)->getIndex(index);
if (p) {
if (attrs)
*attrs = (Attr_NotWritable|Attr_NotConfigurable);
return p;
}
}
- o = o->prototype();
+ o = o->prototype;
}
if (attrs)
*attrs = Attr_Invalid;
@@ -316,7 +311,8 @@ bool Object::hasProperty(String *name) const
if (idx != UINT_MAX)
return hasProperty(idx);
- const Object *o = this;
+ Scope scope(engine());
+ ScopedObject o(scope, d());
while (o) {
if (o->hasOwnProperty(name))
return true;
@@ -329,7 +325,8 @@ bool Object::hasProperty(String *name) const
bool Object::hasProperty(uint index) const
{
- const Object *o = this;
+ Scope scope(engine());
+ ScopedObject o(scope, d());
while (o) {
if (o->hasOwnProperty(index))
return true;
@@ -357,6 +354,7 @@ bool Object::hasOwnProperty(uint index) const
{
if (arrayData() && !arrayData()->isEmpty(index))
return true;
+
if (isStringObject()) {
String *s = static_cast<const StringObject *>(this)->d()->value.asString();
if (index < (uint)s->d()->length())
@@ -369,12 +367,12 @@ bool Object::hasOwnProperty(uint index) const
ReturnedValue Object::construct(Managed *m, CallData *)
{
- return m->engine()->currentContext()->throwTypeError();
+ return m->engine()->throwTypeError();
}
ReturnedValue Object::call(Managed *m, CallData *)
{
- return m->engine()->currentContext()->throwTypeError();
+ return m->engine()->throwTypeError();
}
ReturnedValue Object::get(Managed *m, String *name, bool *hasProperty)
@@ -414,7 +412,7 @@ PropertyAttributes Object::query(const Managed *m, String *name)
PropertyAttributes Object::queryIndexed(const Managed *m, uint index)
{
const Object *o = static_cast<const Object *>(m);
- if (o->arrayData() && o->arrayData()->get(index) != Primitive::emptyValue().asReturnedValue())
+ if (o->arrayData() && !o->arrayData()->isEmpty(index))
return o->arrayData()->attributes(index);
if (o->isStringObject()) {
@@ -470,15 +468,16 @@ void Object::setLookup(Managed *m, Lookup *l, const ValueRef value)
{
Scope scope(m->engine());
ScopedObject o(scope, static_cast<Object *>(m));
+ ScopedString name(scope, scope.engine->currentContext()->compilationUnit->runtimeStrings[l->nameIndex]);
InternalClass *c = o->internalClass();
- uint idx = c->find(l->name);
- if (!o->isArrayObject() || idx != ArrayObject::LengthPropertyIndex) {
+ uint idx = c->find(name);
+ if (!o->isArrayObject() || idx != Heap::ArrayObject::LengthPropertyIndex) {
if (idx != UINT_MAX && o->internalClass()->propertyData[idx].isData() && o->internalClass()->propertyData[idx].isWritable()) {
l->classList[0] = o->internalClass();
l->index = idx;
l->setter = Lookup::setter0;
- o->memberData()[idx] = *value;
+ o->memberData()->data[idx] = *value;
return;
}
@@ -488,12 +487,11 @@ void Object::setLookup(Managed *m, Lookup *l, const ValueRef value)
}
}
- ScopedString s(scope, l->name);
- o->put(s.getPointer(), value);
+ o->put(name, value);
if (o->internalClass() == c)
return;
- idx = o->internalClass()->find(l->name);
+ idx = o->internalClass()->find(name);
if (idx == UINT_MAX)
return;
l->classList[0] = c;
@@ -518,10 +516,10 @@ void Object::setLookup(Managed *m, Lookup *l, const ValueRef value)
l->setter = Lookup::setterGeneric;
}
-void Object::advanceIterator(Managed *m, ObjectIterator *it, String *&name, uint *index, Property *pd, PropertyAttributes *attrs)
+void Object::advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name, uint *index, Property *pd, PropertyAttributes *attrs)
{
Object *o = static_cast<Object *>(m);
- name = (String *)0;
+ *name = 0;
*index = UINT_MAX;
if (o->arrayData()) {
@@ -533,15 +531,15 @@ void Object::advanceIterator(Managed *m, ObjectIterator *it, String *&name, uint
while (it->arrayNode != o->sparseEnd()) {
int k = it->arrayNode->key();
uint pidx = it->arrayNode->value;
- SparseArrayData *sa = static_cast<SparseArrayData *>(o->arrayData());
- Property *p = reinterpret_cast<Property *>(sa->arrayData() + pidx);
+ Heap::SparseArrayData *sa = static_cast<Heap::SparseArrayData *>(o->d()->arrayData);
+ Property *p = reinterpret_cast<Property *>(sa->arrayData + pidx);
it->arrayNode = it->arrayNode->nextNode();
- PropertyAttributes a = o->arrayData()->attributes(k);
+ PropertyAttributes a = sa->attrs ? sa->attrs[pidx] : Attr_Data;
if (!(it->flags & ObjectIterator::EnumerableOnly) || a.isEnumerable()) {
it->arrayIndex = k + 1;
*index = k;
*attrs = a;
- pd->copy(*p, a);
+ pd->copy(p, a);
return;
}
}
@@ -549,8 +547,8 @@ void Object::advanceIterator(Managed *m, ObjectIterator *it, String *&name, uint
it->arrayIndex = UINT_MAX;
}
// dense arrays
- while (it->arrayIndex < o->arrayData()->length()) {
- SimpleArrayData *sa = static_cast<SimpleArrayData *>(o->arrayData());
+ while (it->arrayIndex < o->d()->arrayData->len) {
+ Heap::SimpleArrayData *sa = static_cast<Heap::SimpleArrayData *>(o->d()->arrayData);
Value &val = sa->data(it->arrayIndex);
PropertyAttributes a = o->arrayData()->attributes(it->arrayIndex);
++it->arrayIndex;
@@ -565,7 +563,7 @@ void Object::advanceIterator(Managed *m, ObjectIterator *it, String *&name, uint
}
while (it->memberIndex < o->internalClass()->size) {
- String *n = o->internalClass()->nameMap.at(it->memberIndex);
+ Identifier *n = o->internalClass()->nameMap.at(it->memberIndex);
if (!n) {
// accessor properties have a dummy entry with n == 0
++it->memberIndex;
@@ -576,9 +574,9 @@ void Object::advanceIterator(Managed *m, ObjectIterator *it, String *&name, uint
PropertyAttributes a = o->internalClass()->propertyData[it->memberIndex];
++it->memberIndex;
if (!(it->flags & ObjectIterator::EnumerableOnly) || a.isEnumerable()) {
- name = n;
+ *name = m->engine()->newString(n->string);
*attrs = a;
- pd->copy(*p, a);
+ pd->copy(p, a);
return;
}
}
@@ -595,7 +593,8 @@ ReturnedValue Object::internalGet(String *name, bool *hasProperty)
name->makeIdentifier();
- Object *o = this;
+ Scope scope(engine());
+ ScopedObject o(scope, this);
while (o) {
uint idx = o->internalClass()->find(name);
if (idx < UINT_MAX) {
@@ -616,7 +615,8 @@ ReturnedValue Object::internalGetIndexed(uint index, bool *hasProperty)
{
Property *pd = 0;
PropertyAttributes attrs;
- Object *o = this;
+ Scope scope(engine());
+ ScopedObject o(scope, this);
while (o) {
Property *p = o->arrayData() ? o->arrayData()->getProperty(index) : 0;
if (p) {
@@ -625,7 +625,7 @@ ReturnedValue Object::internalGetIndexed(uint index, bool *hasProperty)
break;
}
if (o->isStringObject()) {
- pd = static_cast<StringObject *>(o)->getIndex(index);
+ pd = static_cast<StringObject *>(o.getPointer())->getIndex(index);
if (pd) {
attrs = (Attr_NotWritable|Attr_NotConfigurable);
break;
@@ -678,7 +678,7 @@ void Object::internalPut(String *name, const ValueRef value)
bool ok;
uint l = value->asArrayLength(&ok);
if (!ok) {
- engine()->currentContext()->throwRangeError(value);
+ engine()->throwRangeError(value);
return;
}
ok = setArrayLength(l);
@@ -693,7 +693,8 @@ void Object::internalPut(String *name, const ValueRef value)
goto reject;
} else {
// clause 4
- if ((pd = prototype()->__getPropertyDescriptor__(name, &attrs))) {
+ Scope scope(engine());
+ if ((pd = ScopedObject(scope, prototype())->__getPropertyDescriptor__(name, &attrs))) {
if (attrs.isAccessor()) {
if (!pd->setter())
goto reject;
@@ -712,10 +713,11 @@ void Object::internalPut(String *name, const ValueRef value)
assert(pd->setter() != 0);
Scope scope(engine());
+ ScopedFunctionObject setter(scope, pd->setter());
ScopedCallData callData(scope, 1);
callData->args[0] = *value;
callData->thisObject = this;
- pd->setter()->call(callData);
+ setter->call(callData);
return;
}
@@ -723,11 +725,11 @@ void Object::internalPut(String *name, const ValueRef value)
return;
reject:
- if (engine()->currentContext()->d()->strictMode) {
+ if (engine()->currentContext()->strictMode) {
QString message = QStringLiteral("Cannot assign to read-only property \"");
message += name->toQString();
message += QLatin1Char('\"');
- engine()->currentContext()->throwTypeError(message);
+ engine()->throwTypeError(message);
}
}
@@ -765,7 +767,8 @@ void Object::internalPutIndexed(uint index, const ValueRef value)
goto reject;
} else {
// clause 4
- if ((pd = prototype()->__getPropertyDescriptor__(index, &attrs))) {
+ Scope scope(engine());
+ if ((pd = ScopedObject(scope, prototype())->__getPropertyDescriptor__(index, &attrs))) {
if (attrs.isAccessor()) {
if (!pd->setter())
goto reject;
@@ -784,10 +787,11 @@ void Object::internalPutIndexed(uint index, const ValueRef value)
assert(pd->setter() != 0);
Scope scope(engine());
+ ScopedFunctionObject setter(scope, pd->setter());
ScopedCallData callData(scope, 1);
callData->args[0] = *value;
callData->thisObject = this;
- pd->setter()->call(callData);
+ setter->call(callData);
return;
}
@@ -795,8 +799,8 @@ void Object::internalPutIndexed(uint index, const ValueRef value)
return;
reject:
- if (engine()->currentContext()->d()->strictMode)
- engine()->currentContext()->throwTypeError();
+ if (engine()->currentContext()->strictMode)
+ engine()->throwTypeError();
}
// Section 8.12.7
@@ -817,8 +821,8 @@ bool Object::internalDeleteProperty(String *name)
InternalClass::removeMember(this, name->identifier());
return true;
}
- if (engine()->currentContext()->d()->strictMode)
- engine()->currentContext()->throwTypeError();
+ if (engine()->currentContext()->strictMode)
+ engine()->throwTypeError();
return false;
}
@@ -827,46 +831,48 @@ bool Object::internalDeleteProperty(String *name)
bool Object::internalDeleteIndexedProperty(uint index)
{
- if (internalClass()->engine->hasException)
+ Scope scope(engine());
+ if (scope.engine->hasException)
return false;
- if (!arrayData() || arrayData()->vtable()->del(this, index))
+ Scoped<ArrayData> ad(scope, arrayData());
+ if (!ad || ad->vtable()->del(this, index))
return true;
- if (engine()->currentContext()->d()->strictMode)
- engine()->currentContext()->throwTypeError();
+ if (engine()->currentContext()->strictMode)
+ engine()->throwTypeError();
return false;
}
// Section 8.12.9
-bool Object::__defineOwnProperty__(ExecutionContext *ctx, String *name, const Property &p, PropertyAttributes attrs)
+bool Object::__defineOwnProperty__(ExecutionEngine *engine, String *name, const Property *p, PropertyAttributes attrs)
{
uint idx = name->asArrayIndex();
if (idx != UINT_MAX)
- return __defineOwnProperty__(ctx, idx, p, attrs);
+ return __defineOwnProperty__(engine, idx, p, attrs);
name->makeIdentifier();
- Scope scope(ctx);
+ Scope scope(engine);
Property *current;
PropertyAttributes *cattrs;
uint memberIndex;
- if (isArrayObject() && name->equals(ctx->d()->engine->id_length)) {
- assert(ArrayObject::LengthPropertyIndex == internalClass()->find(ctx->d()->engine->id_length));
- Property *lp = propertyAt(ArrayObject::LengthPropertyIndex);
- cattrs = internalClass()->propertyData.constData() + ArrayObject::LengthPropertyIndex;
- if (attrs.isEmpty() || p.isSubset(attrs, *lp, *cattrs))
+ if (isArrayObject() && name->equals(engine->id_length)) {
+ Q_ASSERT(Heap::ArrayObject::LengthPropertyIndex == internalClass()->find(engine->id_length));
+ Property *lp = propertyAt(Heap::ArrayObject::LengthPropertyIndex);
+ cattrs = internalClass()->propertyData.constData() + Heap::ArrayObject::LengthPropertyIndex;
+ if (attrs.isEmpty() || p->isSubset(attrs, lp, *cattrs))
return true;
if (!cattrs->isWritable() || attrs.type() == PropertyAttributes::Accessor || attrs.isConfigurable() || attrs.isEnumerable())
goto reject;
bool succeeded = true;
if (attrs.type() == PropertyAttributes::Data) {
bool ok;
- uint l = p.value.asArrayLength(&ok);
+ uint l = p->value.asArrayLength(&ok);
if (!ok) {
- ScopedValue v(scope, p.value);
- ctx->throwRangeError(v);
+ ScopedValue v(scope, p->value);
+ engine->throwRangeError(v);
return false;
}
succeeded = setArrayLength(l);
@@ -875,8 +881,6 @@ bool Object::__defineOwnProperty__(ExecutionContext *ctx, String *name, const Pr
cattrs->setWritable(false);
if (!succeeded)
goto reject;
- if (attrs.isAccessor())
- setHasAccessorProperty();
return true;
}
@@ -890,37 +894,37 @@ bool Object::__defineOwnProperty__(ExecutionContext *ctx, String *name, const Pr
if (!isExtensible())
goto reject;
// clause 4
- Property pd;
- pd.copy(p, attrs);
- pd.fullyPopulated(&attrs);
+ ScopedProperty pd(scope);
+ pd->copy(p, attrs);
+ pd->fullyPopulated(&attrs);
insertMember(name, pd, attrs);
return true;
}
- return __defineOwnProperty__(ctx, memberIndex, name, p, attrs);
+ return __defineOwnProperty__(engine, memberIndex, name, p, attrs);
reject:
- if (ctx->d()->strictMode)
- ctx->throwTypeError();
+ if (engine->currentContext()->strictMode)
+ engine->throwTypeError();
return false;
}
-bool Object::__defineOwnProperty__(ExecutionContext *ctx, uint index, const Property &p, PropertyAttributes attrs)
+bool Object::__defineOwnProperty__(ExecutionEngine *engine, uint index, const Property *p, PropertyAttributes attrs)
{
// 15.4.5.1, 4b
- if (isArrayObject() && index >= getLength() && !internalClass()->propertyData[ArrayObject::LengthPropertyIndex].isWritable())
+ if (isArrayObject() && index >= getLength() && !internalClass()->propertyData[Heap::ArrayObject::LengthPropertyIndex].isWritable())
goto reject;
if (ArgumentsObject::isNonStrictArgumentsObject(this))
- return static_cast<ArgumentsObject *>(this)->defineOwnProperty(ctx, index, p, attrs);
+ return static_cast<ArgumentsObject *>(this)->defineOwnProperty(engine, index, p, attrs);
- return defineOwnProperty2(ctx, index, p, attrs);
+ return defineOwnProperty2(engine, index, p, attrs);
reject:
- if (ctx->d()->strictMode)
- ctx->throwTypeError();
+ if (engine->currentContext()->strictMode)
+ engine->throwTypeError();
return false;
}
-bool Object::defineOwnProperty2(ExecutionContext *ctx, uint index, const Property &p, PropertyAttributes attrs)
+bool Object::defineOwnProperty2(ExecutionEngine *engine, uint index, const Property *p, PropertyAttributes attrs)
{
Property *current = 0;
@@ -936,12 +940,12 @@ bool Object::defineOwnProperty2(ExecutionContext *ctx, uint index, const Propert
if (!isExtensible())
goto reject;
// clause 4
- Property pp;
- pp.copy(p, attrs);
- pp.fullyPopulated(&attrs);
+ Scope scope(engine);
+ ScopedProperty pp(scope);
+ pp->copy(p, attrs);
+ pp->fullyPopulated(&attrs);
if (attrs == Attr_Data) {
- Scope scope(ctx);
- ScopedValue v(scope, pp.value);
+ ScopedValue v(scope, pp->value);
arraySet(index, v);
} else {
arraySet(index, pp, attrs);
@@ -949,14 +953,14 @@ bool Object::defineOwnProperty2(ExecutionContext *ctx, uint index, const Propert
return true;
}
- return __defineOwnProperty__(ctx, index, 0, p, attrs);
+ return __defineOwnProperty__(engine, index, 0, p, attrs);
reject:
- if (ctx->d()->strictMode)
- ctx->throwTypeError();
+ if (engine->currentContext()->strictMode)
+ engine->throwTypeError();
return false;
}
-bool Object::__defineOwnProperty__(ExecutionContext *ctx, uint index, String *member, const Property &p, PropertyAttributes attrs)
+bool Object::__defineOwnProperty__(ExecutionEngine *engine, uint index, String *member, const Property *p, PropertyAttributes attrs)
{
// clause 5
if (attrs.isEmpty())
@@ -973,7 +977,7 @@ bool Object::__defineOwnProperty__(ExecutionContext *ctx, uint index, String *me
}
// clause 6
- if (p.isSubset(attrs, *current, cattrs))
+ if (p->isSubset(attrs, current, cattrs))
return true;
// clause 7
@@ -1019,15 +1023,15 @@ bool Object::__defineOwnProperty__(ExecutionContext *ctx, uint index, String *me
}
} else if (cattrs.isData() && attrs.isData()) { // clause 10
if (!cattrs.isConfigurable() && !cattrs.isWritable()) {
- if (attrs.isWritable() || !current->value.sameValue(p.value))
+ if (attrs.isWritable() || !current->value.sameValue(p->value))
goto reject;
}
} else { // clause 10
Q_ASSERT(cattrs.isAccessor() && attrs.isAccessor());
if (!cattrs.isConfigurable()) {
- if (!p.value.isEmpty() && current->value.val != p.value.val)
+ if (!p->value.isEmpty() && current->value.val != p->value.val)
goto reject;
- if (!p.set.isEmpty() && current->set.val != p.set.val)
+ if (!p->set.isEmpty() && current->set.val != p->set.val)
goto reject;
}
}
@@ -1040,21 +1044,19 @@ bool Object::__defineOwnProperty__(ExecutionContext *ctx, uint index, String *me
} else {
setArrayAttributes(index, cattrs);
}
- if (cattrs.isAccessor())
- setHasAccessorProperty();
return true;
reject:
- if (ctx->d()->strictMode)
- ctx->throwTypeError();
+ if (engine->currentContext()->strictMode)
+ engine->throwTypeError();
return false;
}
-bool Object::__defineOwnProperty__(ExecutionContext *ctx, const QString &name, const Property &p, PropertyAttributes attrs)
+bool Object::__defineOwnProperty__(ExecutionEngine *engine, const QString &name, const Property *p, PropertyAttributes attrs)
{
- Scope scope(ctx);
- ScopedString s(scope, ctx->d()->engine->newString(name));
- return __defineOwnProperty__(ctx, s.getPointer(), p, attrs);
+ Scope scope(engine);
+ ScopedString s(scope, engine->newString(name));
+ return __defineOwnProperty__(engine, s, p, attrs);
}
@@ -1063,7 +1065,8 @@ void Object::copyArrayData(Object *other)
Q_ASSERT(isArrayObject());
Scope scope(engine());
- if (other->protoHasArray() || other->hasAccessorProperty()) {
+ if (other->protoHasArray() || ArgumentsObject::isNonStrictArgumentsObject(other) ||
+ (other->arrayType() == Heap::ArrayData::Sparse && other->arrayData()->attrs)) {
uint len = other->getLength();
Q_ASSERT(len);
@@ -1073,28 +1076,20 @@ void Object::copyArrayData(Object *other)
}
} else if (!other->arrayData()) {
;
- } else if (other->hasAccessorProperty() && other->arrayData()->attrs() && other->arrayData()->isSparse()){
- // do it the slow way
- ScopedValue v(scope);
- SparseArrayData *osa = static_cast<SparseArrayData *>(other->arrayData());
- for (const SparseArrayNode *it = osa->sparse()->begin(); it != osa->sparse()->end(); it = it->nextNode()) {
- v = other->getValue(reinterpret_cast<Property *>(osa->arrayData() + it->value), other->arrayData()->attrs()[it->value]);
- arraySet(it->key(), v);
- }
} else {
Q_ASSERT(!arrayData() && other->arrayData());
- ArrayData::realloc(this, other->arrayData()->type(), other->arrayData()->alloc(), false);
- if (other->arrayType() == ArrayData::Sparse) {
- SparseArrayData *od = static_cast<SparseArrayData *>(other->arrayData());
- SparseArrayData *dd = static_cast<SparseArrayData *>(arrayData());
- dd->setSparse(new SparseArray(*od->sparse()));
- dd->freeList() = od->freeList();
+ ArrayData::realloc(this, other->d()->arrayData->type, other->d()->arrayData->alloc, false);
+ if (other->arrayType() == Heap::ArrayData::Sparse) {
+ Heap::ArrayData *od = other->d()->arrayData;
+ Heap::ArrayData *dd = d()->arrayData;
+ dd->sparse = new SparseArray(*od->sparse);
+ dd->freeList = od->freeList;
} else {
- SimpleArrayData *d = static_cast<SimpleArrayData *>(arrayData());
- d->len() = static_cast<SimpleArrayData *>(other->arrayData())->len();
- d->d()->offset = static_cast<SimpleArrayData *>(other->arrayData())->d()->offset;
+ Heap::ArrayData *dd = d()->arrayData;
+ dd->len = other->d()->arrayData->len;
+ dd->offset = other->d()->arrayData->offset;
}
- memcpy(arrayData()->d()->arrayData, other->arrayData()->d()->arrayData, arrayData()->alloc()*sizeof(Value));
+ memcpy(d()->arrayData->arrayData, other->d()->arrayData->arrayData, d()->arrayData->alloc*sizeof(Value));
}
setArrayLengthUnchecked(other->getLength());
}
@@ -1109,7 +1104,7 @@ uint Object::getLength(const Managed *m)
bool Object::setArrayLength(uint newLen)
{
Q_ASSERT(isArrayObject());
- if (!internalClass()->propertyData[ArrayObject::LengthPropertyIndex].isWritable())
+ if (!internalClass()->propertyData[Heap::ArrayObject::LengthPropertyIndex].isWritable())
return false;
uint oldLen = getLength();
bool ok = true;
@@ -1132,17 +1127,17 @@ bool Object::setArrayLength(uint newLen)
void Object::initSparseArray()
{
- if (arrayType() == ArrayData::Sparse)
+ if (arrayType() == Heap::ArrayData::Sparse)
return;
- ArrayData::realloc(this, ArrayData::Sparse, 0, false);
+ ArrayData::realloc(this, Heap::ArrayData::Sparse, 0, false);
}
DEFINE_OBJECT_VTABLE(ArrayObject);
-ArrayObject::Data::Data(ExecutionEngine *engine, const QStringList &list)
- : Object::Data(engine->arrayClass)
+Heap::ArrayObject::ArrayObject(ExecutionEngine *engine, const QStringList &list)
+ : Heap::Object(engine->arrayClass, engine->arrayPrototype.asObject())
{
init();
Scope scope(engine);
@@ -1162,11 +1157,13 @@ ArrayObject::Data::Data(ExecutionEngine *engine, const QStringList &list)
ReturnedValue ArrayObject::getLookup(Managed *m, Lookup *l)
{
- if (l->name->equals(m->engine()->id_length)) {
+ Scope scope(m->engine());
+ ScopedString name(scope, m->engine()->currentContext()->compilationUnit->runtimeStrings[l->nameIndex]);
+ if (name->equals(m->engine()->id_length)) {
// special case, as the property is on the object itself
l->getter = Lookup::arrayLengthGetter;
ArrayObject *a = static_cast<ArrayObject *>(m);
- return a->memberData()[ArrayObject::LengthPropertyIndex].asReturnedValue();
+ return a->memberData()->data[Heap::ArrayObject::LengthPropertyIndex].asReturnedValue();
}
return Object::getLookup(m, l);
}
@@ -1174,9 +1171,9 @@ ReturnedValue ArrayObject::getLookup(Managed *m, Lookup *l)
uint ArrayObject::getLength(const Managed *m)
{
const ArrayObject *a = static_cast<const ArrayObject *>(m);
- if (a->memberData()[ArrayObject::LengthPropertyIndex].isInteger())
- return a->memberData()[ArrayObject::LengthPropertyIndex].integerValue();
- return Primitive::toUInt32(a->memberData()[ArrayObject::LengthPropertyIndex].doubleValue());
+ if (a->memberData()->data[Heap::ArrayObject::LengthPropertyIndex].isInteger())
+ return a->memberData()->data[Heap::ArrayObject::LengthPropertyIndex].integerValue();
+ return Primitive::toUInt32(a->memberData()->data[Heap::ArrayObject::LengthPropertyIndex].doubleValue());
}
QStringList ArrayObject::toQStringList() const
@@ -1187,8 +1184,8 @@ QStringList ArrayObject::toQStringList() const
Scope scope(engine);
ScopedValue v(scope);
- uint32_t length = getLength();
- for (uint32_t i = 0; i < length; ++i) {
+ uint length = getLength();
+ for (uint i = 0; i < length; ++i) {
v = const_cast<ArrayObject *>(this)->getIndexed(i);
result.append(v->toQStringNoThrow());
}
diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h
index 4e9d1527c2..298779906b 100644
--- a/src/qml/jsruntime/qv4object_p.h
+++ b/src/qml/jsruntime/qv4object_p.h
@@ -30,97 +30,55 @@
** $QT_END_LICENSE$
**
****************************************************************************/
-#ifndef QMLJS_OBJECTS_H
-#define QMLJS_OBJECTS_H
-
-#include "qv4global_p.h"
-#include "qv4runtime_p.h"
-#include "qv4engine_p.h"
-#include "qv4context_p.h"
-#include "qv4string_p.h"
+#ifndef QV4_OBJECT_H
+#define QV4_OBJECT_H
+
#include "qv4managed_p.h"
-#include "qv4property_p.h"
-#include "qv4internalclass_p.h"
-#include "qv4arraydata_p.h"
#include "qv4memberdata_p.h"
-
-#include <QtCore/QString>
-#include <QtCore/QHash>
-#include <QtCore/QScopedPointer>
-#include <cstdio>
-#include <cassert>
-
-#ifdef _WIN32_WCE
-#undef assert
-#define assert(x)
-#endif // _WIN32_WCE
+#include "qv4arraydata_p.h"
QT_BEGIN_NAMESPACE
namespace QV4 {
-struct Function;
-struct Lookup;
-struct Object;
-struct ObjectIterator;
-struct BooleanObject;
-struct NumberObject;
-struct StringObject;
-struct ArrayObject;
-struct DateObject;
-struct FunctionObject;
-struct RegExpObject;
-struct ErrorObject;
-struct ArgumentsObject;
-struct ExecutionContext;
-struct CallContext;
-struct ExecutionEngine;
-class MemoryManager;
-
-struct ObjectPrototype;
-struct StringPrototype;
-struct NumberPrototype;
-struct BooleanPrototype;
-struct ArrayPrototype;
-struct FunctionPrototype;
-struct DatePrototype;
-struct RegExpPrototype;
-struct ErrorPrototype;
-struct EvalErrorPrototype;
-struct RangeErrorPrototype;
-struct ReferenceErrorPrototype;
-struct SyntaxErrorPrototype;
-struct TypeErrorPrototype;
-struct URIErrorPrototype;
+namespace Heap {
+struct Object : Base {
+ Object(ExecutionEngine *engine)
+ : Base(engine->objectClass),
+ prototype(static_cast<Object *>(engine->objectPrototype.m))
+ {
+ }
+ Object(InternalClass *internal, QV4::Object *prototype);
-struct Q_QML_EXPORT Object: Managed {
- struct Data : Managed::Data {
- Data(ExecutionEngine *engine)
- : Managed::Data(engine->objectClass)
- {
- }
- Data(InternalClass *internal = 0);
+ const Property *propertyAt(uint index) const { return reinterpret_cast<const Property *>(memberData->data + index); }
+ Property *propertyAt(uint index) { return reinterpret_cast<Property *>(memberData->data + index); }
- Members memberData;
- ArrayData *arrayData;
- };
- V4_OBJECT(Object)
+ Heap::Object *prototype;
+ MemberData *memberData;
+ ArrayData *arrayData;
+};
+
+}
+
+struct Q_QML_EXPORT Object: Managed {
+ V4_OBJECT2(Object, Object)
Q_MANAGED_TYPE(Object)
enum {
IsObject = true
};
- Members &memberData() { return d()->memberData; }
- const Members &memberData() const { return d()->memberData; }
- ArrayData *arrayData() const { return d()->arrayData; }
- void setArrayData(ArrayData *a) { d()->arrayData = a; }
+ Heap::MemberData *memberData() { return d()->memberData; }
+ const Heap::MemberData *memberData() const { return d()->memberData; }
+ Heap::ArrayData *arrayData() const { return d()->arrayData; }
+ void setArrayData(ArrayData *a) { d()->arrayData = a->d(); }
- Property *propertyAt(uint index) const { return reinterpret_cast<Property *>(memberData().data() + index); }
+ const Property *propertyAt(uint index) const { return d()->propertyAt(index); }
+ Property *propertyAt(uint index) { return d()->propertyAt(index); }
const ObjectVTable *vtable() const { return reinterpret_cast<const ObjectVTable *>(internalClass()->vtable); }
- Object *prototype() const { return internalClass()->prototype; }
+ Heap::Object *prototype() const { return d()->prototype; }
bool setPrototype(Object *proto);
Property *__getOwnProperty__(String *name, PropertyAttributes *attrs = 0);
@@ -135,16 +93,16 @@ struct Q_QML_EXPORT Object: Managed {
bool hasOwnProperty(String *name) const;
bool hasOwnProperty(uint index) const;
- bool __defineOwnProperty__(ExecutionContext *ctx, uint index, String *member, const Property &p, PropertyAttributes attrs);
- bool __defineOwnProperty__(ExecutionContext *ctx, String *name, const Property &p, PropertyAttributes attrs);
- bool __defineOwnProperty__(ExecutionContext *ctx, uint index, const Property &p, PropertyAttributes attrs);
- bool __defineOwnProperty__(ExecutionContext *ctx, const QString &name, const Property &p, PropertyAttributes attrs);
- bool defineOwnProperty2(ExecutionContext *ctx, uint index, const Property &p, PropertyAttributes attrs);
+ bool __defineOwnProperty__(ExecutionEngine *engine, uint index, String *member, const Property *p, PropertyAttributes attrs);
+ bool __defineOwnProperty__(ExecutionEngine *engine, String *name, const Property *p, PropertyAttributes attrs);
+ bool __defineOwnProperty__(ExecutionEngine *engine, uint index, const Property *p, PropertyAttributes attrs);
+ bool __defineOwnProperty__(ExecutionEngine *engine, const QString &name, const Property *p, PropertyAttributes attrs);
+ bool defineOwnProperty2(ExecutionEngine *engine, uint index, const Property *p, PropertyAttributes attrs);
//
// helpers
//
- void put(ExecutionContext *ctx, const QString &name, const ValueRef value);
+ void put(ExecutionEngine *engine, const QString &name, const ValueRef value);
static ReturnedValue getValue(const ValueRef thisObject, const Property *p, PropertyAttributes attrs);
ReturnedValue getValue(const Property *p, PropertyAttributes attrs) const {
@@ -168,19 +126,21 @@ struct Q_QML_EXPORT Object: Managed {
void defineReadonlyProperty(const QString &name, ValueRef value);
void defineReadonlyProperty(String *name, ValueRef value);
+ void ensureMemberIndex(QV4::ExecutionEngine *e, uint idx) {
+ d()->memberData = MemberData::reallocate(e, d()->memberData, idx);
+ }
+
void insertMember(String *s, const ValueRef v, PropertyAttributes attributes = Attr_Data) {
- Property p(*v);
+ Scope scope(engine());
+ ScopedProperty p(scope);
+ p->value = *v;
insertMember(s, p, attributes);
}
- void insertMember(String *s, const Property &p, PropertyAttributes attributes);
+ void insertMember(String *s, const Property *p, PropertyAttributes attributes);
inline ExecutionEngine *engine() const { return internalClass()->engine; }
- inline bool hasAccessorProperty() const { return d()->hasAccessorProperty; }
- inline void setHasAccessorProperty() { d()->hasAccessorProperty = true; }
-
- bool isExtensible() const { return d()->extensible; }
- void setExtensible(bool b) { d()->extensible = b; }
+ bool isExtensible() const { return d()->internalClass->extensible; }
// Array handling
@@ -190,7 +150,7 @@ public:
bool setArrayLength(uint newLen);
void setArrayLengthUnchecked(uint l);
- void arraySet(uint index, const Property &p, PropertyAttributes attributes = Attr_Data);
+ void arraySet(uint index, const Property *p, PropertyAttributes attributes = Attr_Data);
void arraySet(uint index, ValueRef value);
bool arrayPut(uint index, ValueRef value) {
@@ -201,7 +161,7 @@ public:
}
void setArrayAttributes(uint i, PropertyAttributes a) {
Q_ASSERT(arrayData());
- if (arrayData()->attrs() || a != Attr_Data) {
+ if (d()->arrayData->attrs || a != Attr_Data) {
ArrayData::ensureAttributes(this);
a.resolve();
arrayData()->vtable()->setAttribute(this, i, a);
@@ -211,34 +171,34 @@ public:
void push_back(const ValueRef v);
ArrayData::Type arrayType() const {
- return arrayData() ? arrayData()->type() : ArrayData::Simple;
+ return arrayData() ? d()->arrayData->type : Heap::ArrayData::Simple;
}
// ### remove me
void setArrayType(ArrayData::Type t) {
- Q_ASSERT(t != ArrayData::Simple && t != ArrayData::Sparse);
+ Q_ASSERT(t != Heap::ArrayData::Simple && t != Heap::ArrayData::Sparse);
arrayCreate();
- arrayData()->setType(t);
+ d()->arrayData->type = t;
}
inline void arrayReserve(uint n) {
- ArrayData::realloc(this, ArrayData::Simple, n, false);
+ ArrayData::realloc(this, Heap::ArrayData::Simple, n, false);
}
void arrayCreate() {
if (!arrayData())
- ArrayData::realloc(this, ArrayData::Simple, 0, false);
+ ArrayData::realloc(this, Heap::ArrayData::Simple, 0, false);
#ifdef CHECK_SPARSE_ARRAYS
initSparseArray();
#endif
}
void initSparseArray();
- SparseArrayNode *sparseBegin() { return arrayType() == ArrayData::Sparse ? static_cast<SparseArrayData *>(arrayData())->sparse()->begin() : 0; }
- SparseArrayNode *sparseEnd() { return arrayType() == ArrayData::Sparse ? static_cast<SparseArrayData *>(arrayData())->sparse()->end() : 0; }
+ SparseArrayNode *sparseBegin() { return arrayType() == Heap::ArrayData::Sparse ? d()->arrayData->sparse->begin() : 0; }
+ SparseArrayNode *sparseEnd() { return arrayType() == Heap::ArrayData::Sparse ? d()->arrayData->sparse->end() : 0; }
inline bool protoHasArray() {
Scope scope(engine());
- Scoped<Object> p(scope, this);
+ ScopedObject p(scope, this);
while ((p = p->prototype()))
if (p->arrayData())
@@ -268,7 +228,7 @@ public:
{ return vtable()->getLookup(this, l); }
void setLookup(Lookup *l, const ValueRef v)
{ vtable()->setLookup(this, l, v); }
- void advanceIterator(ObjectIterator *it, String *&name, uint *index, Property *p, PropertyAttributes *attributes)
+ void advanceIterator(ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attributes)
{ vtable()->advanceIterator(this, it, name, index, p, attributes); }
uint getLength() const { return vtable()->getLength(this); }
@@ -277,7 +237,7 @@ public:
inline ReturnedValue call(CallData *d)
{ return vtable()->call(this, d); }
protected:
- static void markObjects(Managed *that, ExecutionEngine *e);
+ static void markObjects(Heap::Base *that, ExecutionEngine *e);
static ReturnedValue construct(Managed *m, CallData *);
static ReturnedValue call(Managed *m, CallData *);
static ReturnedValue get(Managed *m, String *name, bool *hasProperty);
@@ -290,7 +250,7 @@ protected:
static bool deleteIndexedProperty(Managed *m, uint index);
static ReturnedValue getLookup(Managed *m, Lookup *l);
static void setLookup(Managed *m, Lookup *l, const ValueRef v);
- static void advanceIterator(Managed *m, ObjectIterator *it, String *&name, uint *index, Property *p, PropertyAttributes *attributes);
+ static void advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attributes);
static uint getLength(const Managed *m);
private:
@@ -305,22 +265,58 @@ private:
friend struct ObjectPrototype;
};
-struct BooleanObject: Object {
- struct Data : Object::Data {
- Data(ExecutionEngine *engine, const ValueRef val)
- : Object::Data(engine->booleanClass)
- {
- value = val;
- }
- Data(InternalClass *ic)
- : Object::Data(ic)
- {
- Q_ASSERT(internalClass->vtable == staticVTable());
- value = Encode(false);
- }
- Value value;
+namespace Heap {
+
+struct BooleanObject : Object {
+ BooleanObject(InternalClass *ic, QV4::Object *prototype)
+ : Object(ic, prototype)
+ {
+ value = Encode((bool)false);
+ }
+
+ BooleanObject(ExecutionEngine *engine, const ValueRef val)
+ : Object(engine->booleanClass, engine->booleanPrototype.asObject())
+ {
+ value = val;
+ }
+ Value value;
+};
+
+struct NumberObject : Object {
+ NumberObject(InternalClass *ic, QV4::Object *prototype)
+ : Object(ic, prototype)
+ {
+ value = Encode((int)0);
+ }
+
+ NumberObject(ExecutionEngine *engine, const ValueRef val)
+ : Object(engine->numberClass, engine->numberPrototype.asObject())
+ {
+ value = val;
+ }
+ Value value;
+};
+
+struct ArrayObject : Object {
+ enum {
+ LengthPropertyIndex = 0
};
- V4_OBJECT(Object)
+
+ ArrayObject(ExecutionEngine *engine)
+ : Heap::Object(engine->arrayClass, engine->arrayPrototype.asObject())
+ { init(); }
+ ArrayObject(ExecutionEngine *engine, const QStringList &list);
+ ArrayObject(InternalClass *ic, QV4::Object *prototype)
+ : Heap::Object(ic, prototype)
+ { init(); }
+ void init()
+ { memberData->data[LengthPropertyIndex] = Primitive::fromInt32(0); }
+};
+
+}
+
+struct BooleanObject: Object {
+ V4_OBJECT2(BooleanObject, Object)
Q_MANAGED_TYPE(BooleanObject)
Value value() const { return d()->value; }
@@ -328,39 +324,15 @@ struct BooleanObject: Object {
};
struct NumberObject: Object {
- struct Data : Object::Data {
- Data(ExecutionEngine *engine, const ValueRef val)
- : Object::Data(engine->numberClass) {
- value = val;
- }
- Data(InternalClass *ic)
- : Object::Data(ic) {
- Q_ASSERT(internalClass->vtable == staticVTable());
- value = Encode((int)0);
- }
- Value value;
- };
- V4_OBJECT(Object)
+ V4_OBJECT2(NumberObject, Object)
Q_MANAGED_TYPE(NumberObject)
Value value() const { return d()->value; }
-
};
struct ArrayObject: Object {
- struct Data : Object::Data {
- Data(ExecutionEngine *engine) : Object::Data(engine->arrayClass) { init(); }
- Data(ExecutionEngine *engine, const QStringList &list);
- Data(InternalClass *ic) : Object::Data(ic) { init(); }
- void init()
- { memberData[LengthPropertyIndex] = Primitive::fromInt32(0); }
- };
-
- V4_OBJECT(Object)
+ V4_OBJECT2(ArrayObject, Object)
Q_MANAGED_TYPE(ArrayObject)
- enum {
- LengthPropertyIndex = 0
- };
void init(ExecutionEngine *engine);
@@ -374,7 +346,7 @@ struct ArrayObject: Object {
inline void Object::setArrayLengthUnchecked(uint l)
{
if (isArrayObject())
- memberData()[ArrayObject::LengthPropertyIndex] = Primitive::fromUInt32(l);
+ memberData()->data[Heap::ArrayObject::LengthPropertyIndex] = Primitive::fromUInt32(l);
}
inline void Object::push_back(const ValueRef v)
@@ -387,23 +359,20 @@ inline void Object::push_back(const ValueRef v)
setArrayLengthUnchecked(idx + 1);
}
-inline void Object::arraySet(uint index, const Property &p, PropertyAttributes attributes)
+inline void Object::arraySet(uint index, const Property *p, PropertyAttributes attributes)
{
// ### Clean up
arrayCreate();
- if (attributes.isAccessor()) {
- setHasAccessorProperty();
- initSparseArray();
- } else if (index > 0x1000 && index > 2*arrayData()->alloc()) {
+ if (attributes.isAccessor() || (index > 0x1000 && index > 2*d()->arrayData->alloc)) {
initSparseArray();
} else {
arrayData()->vtable()->reallocate(this, index + 1, false);
}
setArrayAttributes(index, attributes);
Property *pd = ArrayData::insert(this, index, attributes.isAccessor());
- pd->value = p.value;
+ pd->value = p->value;
if (attributes.isAccessor())
- pd->set = p.set;
+ pd->set = p->set;
if (isArrayObject() && index >= getLength())
setArrayLengthUnchecked(index + 1);
}
@@ -412,7 +381,7 @@ inline void Object::arraySet(uint index, const Property &p, PropertyAttributes a
inline void Object::arraySet(uint index, ValueRef value)
{
arrayCreate();
- if (index > 0x1000 && index > 2*arrayData()->alloc()) {
+ if (index > 0x1000 && index > 2*d()->arrayData->alloc) {
initSparseArray();
}
Property *pd = ArrayData::insert(this, index);
@@ -435,7 +404,7 @@ inline ArrayObject *value_cast(const Value &v) {
template<>
inline ReturnedValue value_convert<Object>(ExecutionEngine *e, const Value &v)
{
- return v.toObject(e->currentContext())->asReturnedValue();
+ return v.toObject(e)->asReturnedValue();
}
#endif
diff --git a/src/qml/jsruntime/qv4objectiterator.cpp b/src/qml/jsruntime/qv4objectiterator.cpp
index f9038472df..2ce5c98316 100644
--- a/src/qml/jsruntime/qv4objectiterator.cpp
+++ b/src/qml/jsruntime/qv4objectiterator.cpp
@@ -38,8 +38,9 @@
using namespace QV4;
-ObjectIterator::ObjectIterator(Value *scratch1, Value *scratch2, Object *o, uint flags)
- : object(scratch1)
+ObjectIterator::ObjectIterator(ExecutionEngine *e, Value *scratch1, Value *scratch2, Object *o, uint flags)
+ : engine(e)
+ , object(scratch1)
, current(scratch2)
, arrayNode(0)
, arrayIndex(0)
@@ -50,7 +51,8 @@ ObjectIterator::ObjectIterator(Value *scratch1, Value *scratch2, Object *o, uint
}
ObjectIterator::ObjectIterator(Scope &scope, Object *o, uint flags)
- : object(scope.alloc(1))
+ : engine(scope.engine)
+ , object(scope.alloc(1))
, current(scope.alloc(1))
, arrayNode(0)
, arrayIndex(0)
@@ -60,23 +62,10 @@ ObjectIterator::ObjectIterator(Scope &scope, Object *o, uint flags)
init(o);
}
-ObjectIterator::ObjectIterator(Value *scratch1, Value *scratch2, uint flags)
- : object(scratch1)
- , current(scratch2)
- , arrayNode(0)
- , arrayIndex(0)
- , memberIndex(0)
- , flags(flags)
-{
- object->o = (Object*)0;
- current->o = (Object*)0;
- // Caller needs to call init!
-}
-
void ObjectIterator::init(Object *o)
{
- object->o = o;
- current->o = o;
+ object->m = o ? o->m : 0;
+ current->m = o ? o->m : 0;
#if QT_POINTER_SIZE == 4
object->tag = QV4::Value::Managed_Type;
@@ -84,20 +73,23 @@ void ObjectIterator::init(Object *o)
#endif
if (object->as<ArgumentsObject>()) {
- Scope scope(object->engine());
+ Scope scope(engine);
Scoped<ArgumentsObject> (scope, object->asReturnedValue())->fullyCreate();
}
}
-void ObjectIterator::next(String *&name, uint *index, Property *pd, PropertyAttributes *attrs)
+void ObjectIterator::next(Heap::String **name, uint *index, Property *pd, PropertyAttributes *attrs)
{
- name = (String *)0;
+ *name = 0;
*index = UINT_MAX;
if (!object->asObject()) {
*attrs = PropertyAttributes();
return;
}
+ Scope scope(engine);
+ ScopedObject o(scope);
+ ScopedString n(scope);
while (1) {
if (!current->asObject())
@@ -108,11 +100,12 @@ void ObjectIterator::next(String *&name, uint *index, Property *pd, PropertyAttr
if (attrs->isEmpty())
break;
// check the property is not already defined earlier in the proto chain
- if (current->asObject() != object->asObject()) {
- Object *o = object->asObject();
+ if (current->heapObject() != object->heapObject()) {
+ o = object->asObject();
+ n = *name;
bool shadowed = false;
- while (o != current->asObject()) {
- if ((!!name && o->hasOwnProperty(name)) ||
+ while (o->asObject()->d() != current->heapObject()) {
+ if ((!!n && o->hasOwnProperty(n)) ||
(*index != UINT_MAX && o->hasOwnProperty(*index))) {
shadowed = true;
break;
@@ -126,9 +119,9 @@ void ObjectIterator::next(String *&name, uint *index, Property *pd, PropertyAttr
}
if (flags & WithProtoChain)
- current->o = current->objectValue()->prototype();
+ current->m = current->objectValue()->prototype();
else
- current->o = (Object *)0;
+ current->m = (Heap::Base *)0;
arrayIndex = 0;
memberIndex = 0;
@@ -142,17 +135,15 @@ ReturnedValue ObjectIterator::nextPropertyName(ValueRef value)
return Encode::null();
PropertyAttributes attrs;
- Property p;
uint index;
- Scope scope(object->engine());
+ Scope scope(engine);
+ ScopedProperty p(scope);
ScopedString name(scope);
- String *n;
- next(n, &index, &p, &attrs);
- name = n;
+ next(name.getRef(), &index, p, &attrs);
if (attrs.isEmpty())
return Encode::null();
- value = object->objectValue()->getValue(&p, attrs);
+ value = object->objectValue()->getValue(p, attrs);
if (!!name)
return name->asReturnedValue();
@@ -166,22 +157,20 @@ ReturnedValue ObjectIterator::nextPropertyNameAsString(ValueRef value)
return Encode::null();
PropertyAttributes attrs;
- Property p;
uint index;
- Scope scope(object->engine());
+ Scope scope(engine);
+ ScopedProperty p(scope);
ScopedString name(scope);
- String *n;
- next(n, &index, &p, &attrs);
- name = n;
+ next(name.getRef(), &index, p, &attrs);
if (attrs.isEmpty())
return Encode::null();
- value = object->objectValue()->getValue(&p, attrs);
+ value = object->objectValue()->getValue(p, attrs);
if (!!name)
return name->asReturnedValue();
assert(index < UINT_MAX);
- return Encode(object->engine()->newString(QString::number(index)));
+ return Encode(engine->newString(QString::number(index)));
}
ReturnedValue ObjectIterator::nextPropertyNameAsString()
@@ -190,29 +179,27 @@ ReturnedValue ObjectIterator::nextPropertyNameAsString()
return Encode::null();
PropertyAttributes attrs;
- Property p;
uint index;
- Scope scope(object->engine());
+ Scope scope(engine);
+ ScopedProperty p(scope);
ScopedString name(scope);
- String *n;
- next(n, &index, &p, &attrs);
- name = n;
+ next(name.getRef(), &index, p, &attrs);
if (attrs.isEmpty())
return Encode::null();
if (!!name)
return name->asReturnedValue();
- assert(index < UINT_MAX);
- return Encode(object->engine()->newString(QString::number(index)));
+ Q_ASSERT(index < UINT_MAX);
+ return Encode(engine->newString(QString::number(index)));
}
DEFINE_OBJECT_VTABLE(ForEachIteratorObject);
-void ForEachIteratorObject::markObjects(Managed *that, ExecutionEngine *e)
+void ForEachIteratorObject::markObjects(Heap::Base *that, ExecutionEngine *e)
{
- ForEachIteratorObject *o = static_cast<ForEachIteratorObject *>(that);
- o->d()->workArea[0].mark(e);
- o->d()->workArea[1].mark(e);
+ ForEachIteratorObject::Data *o = static_cast<ForEachIteratorObject::Data *>(that);
+ o->workArea[0].mark(e);
+ o->workArea[1].mark(e);
Object::markObjects(that, e);
}
diff --git a/src/qml/jsruntime/qv4objectiterator_p.h b/src/qml/jsruntime/qv4objectiterator_p.h
index 3ed73b5c08..f1f70d07a2 100644
--- a/src/qml/jsruntime/qv4objectiterator_p.h
+++ b/src/qml/jsruntime/qv4objectiterator_p.h
@@ -34,24 +34,12 @@
#define QV4OBJECTITERATOR_H
#include "qv4global_p.h"
-#include "qv4property_p.h"
-#include "qv4scopedvalue_p.h"
#include "qv4object_p.h"
QT_BEGIN_NAMESPACE
namespace QV4 {
-struct SparseArrayNode;
-struct Object;
-struct ArrayObject;
-struct PropertyAttributes;
-struct ExecutionContext;
-struct Property;
-struct String;
-struct InternalClass;
-struct ForEachIteratorObject;
-
struct Q_QML_EXPORT ObjectIterator
{
enum Flags {
@@ -60,6 +48,7 @@ struct Q_QML_EXPORT ObjectIterator
WithProtoChain = 0x2,
};
+ ExecutionEngine *engine;
Value *object;
Value *current;
SparseArrayNode *arrayNode;
@@ -67,37 +56,42 @@ struct Q_QML_EXPORT ObjectIterator
uint memberIndex;
uint flags;
- ObjectIterator(Value *scratch1, Value *scratch2, Object *o, uint flags);
+ ObjectIterator(ExecutionEngine *e, Value *scratch1, Value *scratch2, Object *o, uint flags);
ObjectIterator(Scope &scope, Object *o, uint flags);
void init(Object *o);
- void next(String *&name, uint *index, Property *pd, PropertyAttributes *attributes = 0);
+ void next(Heap::String **name, uint *index, Property *pd, PropertyAttributes *attributes = 0);
ReturnedValue nextPropertyName(ValueRef value);
ReturnedValue nextPropertyNameAsString(ValueRef value);
ReturnedValue nextPropertyNameAsString();
-private:
- friend struct ForEachIteratorObject;
- ObjectIterator(Value *scratch1, Value *scratch2, uint flags); // Constructor that requires calling init()
};
+namespace Heap {
+struct ForEachIteratorObject : Object {
+ ForEachIteratorObject(QV4::ExecutionEngine *engine, QV4::Object *o);
+ ObjectIterator it;
+ Value workArea[2];
+};
+
+}
+
struct ForEachIteratorObject: Object {
- struct Data : Object::Data {
- Data(ExecutionContext *ctx, Object *o)
- : Object::Data(ctx->engine())
- , it(workArea, workArea + 1, o, ObjectIterator::EnumerableOnly|ObjectIterator::WithProtoChain) {
- setVTable(staticVTable());
- }
- ObjectIterator it;
- Value workArea[2];
- };
- V4_OBJECT(Object)
+ V4_OBJECT2(ForEachIteratorObject, Object)
Q_MANAGED_TYPE(ForeachIteratorObject)
ReturnedValue nextPropertyName() { return d()->it.nextPropertyNameAsString(); }
protected:
- static void markObjects(Managed *that, ExecutionEngine *e);
+ static void markObjects(Heap::Base *that, ExecutionEngine *e);
};
+inline
+Heap::ForEachIteratorObject::ForEachIteratorObject(QV4::ExecutionEngine *engine, QV4::Object *o)
+ : Heap::Object(engine)
+ , it(engine, workArea, workArea + 1, o, ObjectIterator::EnumerableOnly|ObjectIterator::WithProtoChain)
+{
+ setVTable(QV4::ForEachIteratorObject::staticVTable());
+}
+
}
diff --git a/src/qml/jsruntime/qv4objectproto.cpp b/src/qml/jsruntime/qv4objectproto.cpp
index 9cbf4b204e..445d4f7a68 100644
--- a/src/qml/jsruntime/qv4objectproto.cpp
+++ b/src/qml/jsruntime/qv4objectproto.cpp
@@ -36,40 +36,23 @@
#include "qv4argumentsobject_p.h"
#include "qv4mm_p.h"
#include "qv4scopedvalue_p.h"
+#include "qv4runtime_p.h"
+#include "qv4objectiterator_p.h"
+
#include <QtCore/qnumeric.h>
#include <QtCore/qmath.h>
#include <QtCore/QDateTime>
#include <QtCore/QStringList>
-#include <QtCore/QDebug>
-#include <cassert>
-
-#include <private/qqmljsengine_p.h>
-#include <private/qqmljslexer_p.h>
-#include <private/qqmljsparser_p.h>
-#include <private/qqmljsast_p.h>
-#include <qv4jsir_p.h>
-#include <qv4codegen_p.h>
-
-#ifndef Q_OS_WIN
-# include <time.h>
-# ifndef Q_OS_VXWORKS
-# include <sys/time.h>
-# else
-# include "qplatformdefs.h"
-# endif
-#else
-# include <windows.h>
-#endif
using namespace QV4;
DEFINE_OBJECT_VTABLE(ObjectCtor);
-ObjectCtor::Data::Data(ExecutionContext *scope)
- : FunctionObject::Data(scope, QStringLiteral("Object"))
+Heap::ObjectCtor::ObjectCtor(QV4::ExecutionContext *scope)
+ : Heap::FunctionObject(scope, QStringLiteral("Object"))
{
- setVTable(staticVTable());
+ setVTable(QV4::ObjectCtor::staticVTable());
}
ReturnedValue ObjectCtor::construct(Managed *that, CallData *callData)
@@ -78,20 +61,20 @@ ReturnedValue ObjectCtor::construct(Managed *that, CallData *callData)
Scope scope(v4);
ObjectCtor *ctor = static_cast<ObjectCtor *>(that);
if (!callData->argc || callData->args[0].isUndefined() || callData->args[0].isNull()) {
- Scoped<Object> obj(scope, v4->newObject());
- Scoped<Object> proto(scope, ctor->get(v4->id_prototype));
+ ScopedObject obj(scope, v4->newObject());
+ ScopedObject proto(scope, ctor->get(v4->id_prototype));
if (!!proto)
- obj->setPrototype(proto.getPointer());
+ obj->setPrototype(proto);
return obj.asReturnedValue();
}
- return RuntimeHelpers::toObject(v4->currentContext(), ValueRef(&callData->args[0]));
+ return RuntimeHelpers::toObject(scope.engine, ValueRef(&callData->args[0]));
}
ReturnedValue ObjectCtor::call(Managed *m, CallData *callData)
{
if (!callData->argc || callData->args[0].isUndefined() || callData->args[0].isNull())
return m->engine()->newObject()->asReturnedValue();
- return RuntimeHelpers::toObject(m->engine()->currentContext(), ValueRef(&callData->args[0]));
+ return RuntimeHelpers::toObject(m->engine(), ValueRef(&callData->args[0]));
}
void ObjectPrototype::init(ExecutionEngine *v4, Object *ctor)
@@ -125,39 +108,41 @@ void ObjectPrototype::init(ExecutionEngine *v4, Object *ctor)
defineDefaultProperty(QStringLiteral("__defineGetter__"), method_defineGetter, 2);
defineDefaultProperty(QStringLiteral("__defineSetter__"), method_defineSetter, 2);
- Property p(ScopedFunctionObject(scope, BuiltinFunction::create(v4->rootContext, v4->id___proto__, method_get_proto)).getPointer(),
- ScopedFunctionObject(scope, BuiltinFunction::create(v4->rootContext, v4->id___proto__, method_set_proto)).getPointer());
+ ScopedContext global(scope, scope.engine->rootContext());
+ ScopedProperty p(scope);
+ p->value = BuiltinFunction::create(global, v4->id___proto__, method_get_proto);
+ p->set = BuiltinFunction::create(global, v4->id___proto__, method_set_proto);
insertMember(v4->id___proto__, p, Attr_Accessor|Attr_NotEnumerable);
}
ReturnedValue ObjectPrototype::method_getPrototypeOf(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<Object> o(scope, ctx->argument(0));
+ ScopedObject o(scope, ctx->argument(0));
if (!o)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
- Scoped<Object> p(scope, o->prototype());
+ ScopedObject p(scope, o->prototype());
return !!p ? p->asReturnedValue() : Encode::null();
}
ReturnedValue ObjectPrototype::method_getOwnPropertyDescriptor(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<Object> O(scope, ctx->argument(0));
+ ScopedObject O(scope, ctx->argument(0));
if (!O)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
- if (ArgumentsObject::isNonStrictArgumentsObject(O.getPointer()))
+ if (ArgumentsObject::isNonStrictArgumentsObject(O))
Scoped<ArgumentsObject>(scope, O)->fullyCreate();
ScopedValue v(scope, ctx->argument(1));
- Scoped<String> name(scope, v->toString(ctx));
+ ScopedString name(scope, v->toString(scope.engine));
if (scope.hasException())
return Encode::undefined();
PropertyAttributes attrs;
- Property *desc = O->__getOwnProperty__(name.getPointer(), &attrs);
- return fromPropertyDescriptor(ctx, desc, attrs);
+ Property *desc = O->__getOwnProperty__(name, &attrs);
+ return fromPropertyDescriptor(scope.engine, desc, attrs);
}
ReturnedValue ObjectPrototype::method_getOwnPropertyNames(CallContext *context)
@@ -165,7 +150,7 @@ ReturnedValue ObjectPrototype::method_getOwnPropertyNames(CallContext *context)
Scope scope(context);
ScopedObject O(scope, context->argument(0));
if (!O)
- return context->throwTypeError();
+ return context->engine()->throwTypeError();
ScopedArrayObject array(scope, getOwnPropertyNames(context->d()->engine, context->d()->callData->args[0]));
return array.asReturnedValue();
@@ -176,9 +161,9 @@ ReturnedValue ObjectPrototype::method_create(CallContext *ctx)
Scope scope(ctx);
ScopedValue O(scope, ctx->argument(0));
if (!O->isObject() && !O->isNull())
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
- Scoped<Object> newObject(scope, ctx->d()->engine->newObject());
+ ScopedObject newObject(scope, ctx->d()->engine->newObject());
newObject->setPrototype(O->asObject());
if (ctx->d()->callData->argc > 1 && !ctx->d()->callData->args[1].isUndefined()) {
@@ -192,23 +177,23 @@ ReturnedValue ObjectPrototype::method_create(CallContext *ctx)
ReturnedValue ObjectPrototype::method_defineProperty(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<Object> O(scope, ctx->argument(0));
+ ScopedObject O(scope, ctx->argument(0));
if (!O)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
- Scoped<String> name(scope, ctx->argument(1), Scoped<String>::Convert);
+ ScopedString name(scope, ctx->argument(1), ScopedString::Convert);
if (scope.engine->hasException)
return Encode::undefined();
ScopedValue attributes(scope, ctx->argument(2));
- Property pd;
+ ScopedProperty pd(scope);
PropertyAttributes attrs;
- toPropertyDescriptor(ctx, attributes, &pd, &attrs);
+ toPropertyDescriptor(scope.engine, attributes, pd, &attrs);
if (scope.engine->hasException)
return Encode::undefined();
- if (!O->__defineOwnProperty__(ctx, name.getPointer(), pd, attrs))
- return ctx->throwTypeError();
+ if (!O->__defineOwnProperty__(scope.engine, name, pd, attrs))
+ return ctx->engine()->throwTypeError();
return O.asReturnedValue();
}
@@ -216,39 +201,37 @@ ReturnedValue ObjectPrototype::method_defineProperty(CallContext *ctx)
ReturnedValue ObjectPrototype::method_defineProperties(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<Object> O(scope, ctx->argument(0));
+ ScopedObject O(scope, ctx->argument(0));
if (!O)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
- Scoped<Object> o(scope, ctx->argument(1), Scoped<Object>::Convert);
+ ScopedObject o(scope, ctx->argument(1), ScopedObject::Convert);
if (scope.engine->hasException)
return Encode::undefined();
ScopedValue val(scope);
ObjectIterator it(scope, o, ObjectIterator::EnumerableOnly);
ScopedString name(scope);
+ ScopedProperty pd(scope);
+ ScopedProperty n(scope);
while (1) {
uint index;
PropertyAttributes attrs;
- Property pd;
- String *nm;
- it.next(nm, &index, &pd, &attrs);
- name = nm;
+ it.next(name.getRef(), &index, pd, &attrs);
if (attrs.isEmpty())
break;
- Property n;
PropertyAttributes nattrs;
- val = o->getValue(&pd, attrs);
- toPropertyDescriptor(ctx, val, &n, &nattrs);
+ val = o->getValue(pd, attrs);
+ toPropertyDescriptor(scope.engine, val, n, &nattrs);
if (scope.engine->hasException)
return Encode::undefined();
bool ok;
if (name)
- ok = O->__defineOwnProperty__(ctx, name.getPointer(), n, nattrs);
+ ok = O->__defineOwnProperty__(scope.engine, name, n, nattrs);
else
- ok = O->__defineOwnProperty__(ctx, index, n, nattrs);
+ ok = O->__defineOwnProperty__(scope.engine, index, n, nattrs);
if (!ok)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
}
return O.asReturnedValue();
@@ -257,19 +240,17 @@ ReturnedValue ObjectPrototype::method_defineProperties(CallContext *ctx)
ReturnedValue ObjectPrototype::method_seal(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<Object> o(scope, ctx->argument(0));
+ ScopedObject o(scope, ctx->argument(0));
if (!o)
- return ctx->throwTypeError();
-
- o->setExtensible(false);
+ return ctx->engine()->throwTypeError();
o->setInternalClass(o->internalClass()->sealed());
if (o->arrayData()) {
- ArrayData::ensureAttributes(o.getPointer());
- for (uint i = 0; i < o->arrayData()->alloc(); ++i) {
+ ArrayData::ensureAttributes(o);
+ for (uint i = 0; i < o->d()->arrayData->alloc; ++i) {
if (!o->arrayData()->isEmpty(i))
- o->arrayData()->attrs()[i].setConfigurable(false);
+ o->d()->arrayData->attrs[i].setConfigurable(false);
}
}
@@ -279,24 +260,22 @@ ReturnedValue ObjectPrototype::method_seal(CallContext *ctx)
ReturnedValue ObjectPrototype::method_freeze(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<Object> o(scope, ctx->argument(0));
+ ScopedObject o(scope, ctx->argument(0));
if (!o)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
- if (ArgumentsObject::isNonStrictArgumentsObject(o.getPointer()))
+ if (ArgumentsObject::isNonStrictArgumentsObject(o))
Scoped<ArgumentsObject>(scope, o)->fullyCreate();
- o->setExtensible(false);
-
o->setInternalClass(o->internalClass()->frozen());
if (o->arrayData()) {
- ArrayData::ensureAttributes(o.getPointer());
- for (uint i = 0; i < o->arrayData()->alloc(); ++i) {
+ ArrayData::ensureAttributes(o);
+ for (uint i = 0; i < o->arrayData()->alloc; ++i) {
if (!o->arrayData()->isEmpty(i))
- o->arrayData()->attrs()[i].setConfigurable(false);
- if (o->arrayData()->attrs()[i].isData())
- o->arrayData()->attrs()[i].setWritable(false);
+ o->arrayData()->attrs[i].setConfigurable(false);
+ if (o->arrayData()->attrs[i].isData())
+ o->arrayData()->attrs[i].setWritable(false);
}
}
return o.asReturnedValue();
@@ -305,20 +284,20 @@ ReturnedValue ObjectPrototype::method_freeze(CallContext *ctx)
ReturnedValue ObjectPrototype::method_preventExtensions(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<Object> o(scope, ctx->argument(0));
+ ScopedObject o(scope, ctx->argument(0));
if (!o)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
- o->setExtensible(false);
+ o->setInternalClass(o->internalClass()->nonExtensible());
return o.asReturnedValue();
}
ReturnedValue ObjectPrototype::method_isSealed(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<Object> o(scope, ctx->argument(0));
+ ScopedObject o(scope, ctx->argument(0));
if (!o)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
if (o->isExtensible())
return Encode(false);
@@ -330,10 +309,10 @@ ReturnedValue ObjectPrototype::method_isSealed(CallContext *ctx)
return Encode(true);
Q_ASSERT(o->arrayData() && o->arrayData()->length());
- if (!o->arrayData()->attrs())
+ if (!o->arrayData()->attrs)
return Encode(false);
- for (uint i = 0; i < o->arrayData()->alloc(); ++i) {
+ for (uint i = 0; i < o->arrayData()->alloc; ++i) {
if (!o->arrayData()->isEmpty(i))
if (o->arrayData()->attributes(i).isConfigurable())
return Encode(false);
@@ -345,9 +324,9 @@ ReturnedValue ObjectPrototype::method_isSealed(CallContext *ctx)
ReturnedValue ObjectPrototype::method_isFrozen(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<Object> o(scope, ctx->argument(0));
+ ScopedObject o(scope, ctx->argument(0));
if (!o)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
if (o->isExtensible())
return Encode(false);
@@ -359,10 +338,10 @@ ReturnedValue ObjectPrototype::method_isFrozen(CallContext *ctx)
return Encode(true);
Q_ASSERT(o->arrayData() && o->arrayData()->length());
- if (!o->arrayData()->attrs())
+ if (!o->arrayData()->attrs)
return Encode(false);
- for (uint i = 0; i < o->arrayData()->alloc(); ++i) {
+ for (uint i = 0; i < o->arrayData()->alloc; ++i) {
if (!o->arrayData()->isEmpty(i))
if (o->arrayData()->attributes(i).isConfigurable() || o->arrayData()->attributes(i).isWritable())
return Encode(false);
@@ -374,9 +353,9 @@ ReturnedValue ObjectPrototype::method_isFrozen(CallContext *ctx)
ReturnedValue ObjectPrototype::method_isExtensible(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<Object> o(scope, ctx->argument(0));
+ ScopedObject o(scope, ctx->argument(0));
if (!o)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
return Encode((bool)o->isExtensible());
}
@@ -384,11 +363,11 @@ ReturnedValue ObjectPrototype::method_isExtensible(CallContext *ctx)
ReturnedValue ObjectPrototype::method_keys(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<Object> o(scope, ctx->argument(0));
+ ScopedObject o(scope, ctx->argument(0));
if (!o)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
- Scoped<ArrayObject> a(scope, ctx->d()->engine->newArrayObject());
+ ScopedArrayObject a(scope, ctx->d()->engine->newArrayObject());
ObjectIterator it(scope, o, ObjectIterator::EnumerableOnly);
ScopedValue name(scope);
@@ -410,7 +389,7 @@ ReturnedValue ObjectPrototype::method_toString(CallContext *ctx)
} else if (ctx->d()->callData->thisObject.isNull()) {
return ctx->d()->engine->newString(QStringLiteral("[object Null]"))->asReturnedValue();
} else {
- ScopedObject obj(scope, RuntimeHelpers::toObject(ctx, ValueRef(&ctx->d()->callData->thisObject)));
+ ScopedObject obj(scope, RuntimeHelpers::toObject(scope.engine, ValueRef(&ctx->d()->callData->thisObject)));
QString className = obj->className();
return ctx->d()->engine->newString(QString::fromLatin1("[object %1]").arg(className))->asReturnedValue();
}
@@ -419,13 +398,13 @@ ReturnedValue ObjectPrototype::method_toString(CallContext *ctx)
ReturnedValue ObjectPrototype::method_toLocaleString(CallContext *ctx)
{
Scope scope(ctx);
- ScopedObject o(scope, ctx->d()->callData->thisObject.toObject(ctx));
+ ScopedObject o(scope, ctx->d()->callData->thisObject.toObject(scope.engine));
if (!o)
return Encode::undefined();
- Scoped<FunctionObject> f(scope, o->get(ctx->d()->engine->id_toString));
+ ScopedFunctionObject f(scope, o->get(ctx->d()->engine->id_toString));
if (!f)
- return ctx->throwTypeError();
- ScopedCallData callData(scope, 0);
+ return ctx->engine()->throwTypeError();
+ ScopedCallData callData(scope);
callData->thisObject = o;
return f->call(callData);
}
@@ -433,7 +412,7 @@ ReturnedValue ObjectPrototype::method_toLocaleString(CallContext *ctx)
ReturnedValue ObjectPrototype::method_valueOf(CallContext *ctx)
{
Scope scope(ctx);
- ScopedValue v(scope, ctx->d()->callData->thisObject.toObject(ctx));
+ ScopedValue v(scope, ctx->d()->callData->thisObject.toObject(scope.engine));
if (ctx->d()->engine->hasException)
return Encode::undefined();
return v.asReturnedValue();
@@ -442,31 +421,31 @@ ReturnedValue ObjectPrototype::method_valueOf(CallContext *ctx)
ReturnedValue ObjectPrototype::method_hasOwnProperty(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<String> P(scope, ctx->argument(0), Scoped<String>::Convert);
+ ScopedString P(scope, ctx->argument(0), ScopedString::Convert);
if (scope.engine->hasException)
return Encode::undefined();
- Scoped<Object> O(scope, ctx->d()->callData->thisObject, Scoped<Object>::Convert);
+ ScopedObject O(scope, ctx->d()->callData->thisObject, ScopedObject::Convert);
if (scope.engine->hasException)
return Encode::undefined();
- bool r = O->hasOwnProperty(P.getPointer());
+ bool r = O->hasOwnProperty(P);
if (!r)
- r = !O->query(P.getPointer()).isEmpty();
+ r = !O->query(P).isEmpty();
return Encode(r);
}
ReturnedValue ObjectPrototype::method_isPrototypeOf(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<Object> V(scope, ctx->argument(0));
+ ScopedObject V(scope, ctx->argument(0));
if (!V)
return Encode(false);
- Scoped<Object> O(scope, ctx->d()->callData->thisObject, Scoped<Object>::Convert);
+ ScopedObject O(scope, ctx->d()->callData->thisObject, ScopedObject::Convert);
if (scope.engine->hasException)
return Encode::undefined();
- Scoped<Object> proto(scope, V->prototype());
+ ScopedObject proto(scope, V->prototype());
while (proto) {
- if (O.getPointer() == proto.getPointer())
+ if (O->d() == proto->d())
return Encode(true);
proto = proto->prototype();
}
@@ -476,71 +455,71 @@ ReturnedValue ObjectPrototype::method_isPrototypeOf(CallContext *ctx)
ReturnedValue ObjectPrototype::method_propertyIsEnumerable(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<String> p(scope, ctx->argument(0), Scoped<String>::Convert);
+ ScopedString p(scope, ctx->argument(0), ScopedString::Convert);
if (scope.engine->hasException)
return Encode::undefined();
- Scoped<Object> o(scope, ctx->d()->callData->thisObject, Scoped<Object>::Convert);
+ ScopedObject o(scope, ctx->d()->callData->thisObject, ScopedObject::Convert);
if (scope.engine->hasException)
return Encode::undefined();
PropertyAttributes attrs;
- o->__getOwnProperty__(p.getPointer(), &attrs);
+ o->__getOwnProperty__(p, &attrs);
return Encode(attrs.isEnumerable());
}
ReturnedValue ObjectPrototype::method_defineGetter(CallContext *ctx)
{
if (ctx->d()->callData->argc < 2)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
Scope scope(ctx);
- Scoped<FunctionObject> f(scope, ctx->argument(1));
+ ScopedFunctionObject f(scope, ctx->argument(1));
if (!f)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
- Scoped<String> prop(scope, ctx->argument(0), Scoped<String>::Convert);
+ ScopedString prop(scope, ctx->argument(0), ScopedString::Convert);
if (scope.engine->hasException)
return Encode::undefined();
- Scoped<Object> o(scope, ctx->d()->callData->thisObject);
+ ScopedObject o(scope, ctx->d()->callData->thisObject);
if (!o) {
if (!ctx->d()->callData->thisObject.isUndefined())
return Encode::undefined();
- o = ctx->d()->engine->globalObject;
+ o = ctx->d()->engine->globalObject();
}
- Property pd;
- pd.value = f;
- pd.set = Primitive::emptyValue();
- o->__defineOwnProperty__(ctx, prop.getPointer(), pd, Attr_Accessor);
+ ScopedProperty pd(scope);
+ pd->value = f;
+ pd->set = Primitive::emptyValue();
+ o->__defineOwnProperty__(scope.engine, prop, pd, Attr_Accessor);
return Encode::undefined();
}
ReturnedValue ObjectPrototype::method_defineSetter(CallContext *ctx)
{
if (ctx->d()->callData->argc < 2)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
Scope scope(ctx);
- Scoped<FunctionObject> f(scope, ctx->argument(1));
+ ScopedFunctionObject f(scope, ctx->argument(1));
if (!f)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
- Scoped<String> prop(scope, ctx->argument(0), Scoped<String>::Convert);
+ ScopedString prop(scope, ctx->argument(0), ScopedString::Convert);
if (scope.engine->hasException)
return Encode::undefined();
- Scoped<Object> o(scope, ctx->d()->callData->thisObject);
+ ScopedObject o(scope, ctx->d()->callData->thisObject);
if (!o) {
if (!ctx->d()->callData->thisObject.isUndefined())
return Encode::undefined();
- o = ctx->d()->engine->globalObject;
+ o = ctx->d()->engine->globalObject();
}
- Property pd;
- pd.value = Primitive::emptyValue();
- pd.set = f;
- o->__defineOwnProperty__(ctx, prop.getPointer(), pd, Attr_Accessor);
+ ScopedProperty pd(scope);
+ pd->value = Primitive::emptyValue();
+ pd->set = f;
+ o->__defineOwnProperty__(scope.engine, prop, pd, Attr_Accessor);
return Encode::undefined();
}
@@ -549,7 +528,7 @@ ReturnedValue ObjectPrototype::method_get_proto(CallContext *ctx)
Scope scope(ctx);
ScopedObject o(scope, ctx->d()->callData->thisObject.asObject());
if (!o)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
return o->prototype()->asReturnedValue();
}
@@ -557,35 +536,35 @@ ReturnedValue ObjectPrototype::method_get_proto(CallContext *ctx)
ReturnedValue ObjectPrototype::method_set_proto(CallContext *ctx)
{
Scope scope(ctx);
- Scoped<Object> o(scope, ctx->d()->callData->thisObject);
+ ScopedObject o(scope, ctx->d()->callData->thisObject);
if (!o || !ctx->d()->callData->argc)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
if (ctx->d()->callData->args[0].isNull()) {
o->setPrototype(0);
return Encode::undefined();
}
- Scoped<Object> p(scope, ctx->d()->callData->args[0]);
+ ScopedObject p(scope, ctx->d()->callData->args[0]);
bool ok = false;
if (!!p) {
- if (o->prototype() == p.getPointer()) {
+ if (o->prototype() == p->d()) {
ok = true;
} else if (o->isExtensible()) {
- ok = o->setPrototype(p.getPointer());
+ ok = o->setPrototype(p);
}
}
if (!ok)
- return ctx->throwTypeError(QStringLiteral("Cyclic __proto__ value"));
+ return ctx->engine()->throwTypeError(QStringLiteral("Cyclic __proto__ value"));
return Encode::undefined();
}
-void ObjectPrototype::toPropertyDescriptor(ExecutionContext *ctx, const ValueRef v, Property *desc, PropertyAttributes *attrs)
+void ObjectPrototype::toPropertyDescriptor(ExecutionEngine *engine, const ValueRef v, Property *desc, PropertyAttributes *attrs)
{
- Scope scope(ctx);
+ Scope scope(engine);
ScopedObject o(scope, v);
if (!o) {
- ctx->throwTypeError();
+ engine->throwTypeError();
return;
}
@@ -594,52 +573,52 @@ void ObjectPrototype::toPropertyDescriptor(ExecutionContext *ctx, const ValueRef
desc->set = Primitive::emptyValue();
ScopedValue tmp(scope);
- if (o->hasProperty(ctx->d()->engine->id_enumerable))
- attrs->setEnumerable((tmp = o->get(ctx->d()->engine->id_enumerable))->toBoolean());
+ if (o->hasProperty(engine->id_enumerable))
+ attrs->setEnumerable((tmp = o->get(engine->id_enumerable))->toBoolean());
- if (o->hasProperty(ctx->d()->engine->id_configurable))
- attrs->setConfigurable((tmp = o->get(ctx->d()->engine->id_configurable))->toBoolean());
+ if (o->hasProperty(engine->id_configurable))
+ attrs->setConfigurable((tmp = o->get(engine->id_configurable))->toBoolean());
- if (o->hasProperty(ctx->d()->engine->id_get)) {
- ScopedValue get(scope, o->get(ctx->d()->engine->id_get));
+ if (o->hasProperty(engine->id_get)) {
+ ScopedValue get(scope, o->get(engine->id_get));
FunctionObject *f = get->asFunctionObject();
if (f || get->isUndefined()) {
desc->value = get;
} else {
- ctx->throwTypeError();
+ engine->throwTypeError();
return;
}
attrs->setType(PropertyAttributes::Accessor);
}
- if (o->hasProperty(ctx->d()->engine->id_set)) {
- ScopedValue set(scope, o->get(ctx->d()->engine->id_set));
+ if (o->hasProperty(engine->id_set)) {
+ ScopedValue set(scope, o->get(engine->id_set));
FunctionObject *f = set->asFunctionObject();
if (f || set->isUndefined()) {
desc->set = set;
} else {
- ctx->throwTypeError();
+ engine->throwTypeError();
return;
}
attrs->setType(PropertyAttributes::Accessor);
}
- if (o->hasProperty(ctx->d()->engine->id_writable)) {
+ if (o->hasProperty(engine->id_writable)) {
if (attrs->isAccessor()) {
- ctx->throwTypeError();
+ engine->throwTypeError();
return;
}
- attrs->setWritable((tmp = o->get(ctx->d()->engine->id_writable))->toBoolean());
+ attrs->setWritable((tmp = o->get(engine->id_writable))->toBoolean());
// writable forces it to be a data descriptor
desc->value = Primitive::undefinedValue();
}
- if (o->hasProperty(ctx->d()->engine->id_value)) {
+ if (o->hasProperty(engine->id_value)) {
if (attrs->isAccessor()) {
- ctx->throwTypeError();
+ engine->throwTypeError();
return;
}
- desc->value = o->get(ctx->d()->engine->id_value);
+ desc->value = o->get(engine->id_value);
attrs->setType(PropertyAttributes::Data);
}
@@ -648,49 +627,48 @@ void ObjectPrototype::toPropertyDescriptor(ExecutionContext *ctx, const ValueRef
}
-ReturnedValue ObjectPrototype::fromPropertyDescriptor(ExecutionContext *ctx, const Property *desc, PropertyAttributes attrs)
+ReturnedValue ObjectPrototype::fromPropertyDescriptor(ExecutionEngine *engine, const Property *desc, PropertyAttributes attrs)
{
if (!desc)
return Encode::undefined();
- ExecutionEngine *engine = ctx->d()->engine;
Scope scope(engine);
// Let obj be the result of creating a new object as if by the expression new Object() where Object
// is the standard built-in constructor with that name.
ScopedObject o(scope, engine->newObject());
ScopedString s(scope);
- Property pd;
+ ScopedProperty pd(scope);
if (attrs.isData()) {
- pd.value = desc->value;
+ pd->value = desc->value;
s = engine->newString(QStringLiteral("value"));
- o->__defineOwnProperty__(ctx, s.getPointer(), pd, Attr_Data);
- pd.value = Primitive::fromBoolean(attrs.isWritable());
+ o->__defineOwnProperty__(scope.engine, s, pd, Attr_Data);
+ pd->value = Primitive::fromBoolean(attrs.isWritable());
s = engine->newString(QStringLiteral("writable"));
- o->__defineOwnProperty__(ctx, s.getPointer(), pd, Attr_Data);
+ o->__defineOwnProperty__(scope.engine, s, pd, Attr_Data);
} else {
- pd.value = desc->getter() ? desc->getter()->asReturnedValue() : Encode::undefined();
+ pd->value = desc->getter() ? desc->getter()->asReturnedValue() : Encode::undefined();
s = engine->newString(QStringLiteral("get"));
- o->__defineOwnProperty__(ctx, s.getPointer(), pd, Attr_Data);
- pd.value = desc->setter() ? desc->setter()->asReturnedValue() : Encode::undefined();
+ o->__defineOwnProperty__(scope.engine, s, pd, Attr_Data);
+ pd->value = desc->setter() ? desc->setter()->asReturnedValue() : Encode::undefined();
s = engine->newString(QStringLiteral("set"));
- o->__defineOwnProperty__(ctx, s.getPointer(), pd, Attr_Data);
+ o->__defineOwnProperty__(scope.engine, s, pd, Attr_Data);
}
- pd.value = Primitive::fromBoolean(attrs.isEnumerable());
+ pd->value = Primitive::fromBoolean(attrs.isEnumerable());
s = engine->newString(QStringLiteral("enumerable"));
- o->__defineOwnProperty__(ctx, s.getPointer(), pd, Attr_Data);
- pd.value = Primitive::fromBoolean(attrs.isConfigurable());
+ o->__defineOwnProperty__(scope.engine, s, pd, Attr_Data);
+ pd->value = Primitive::fromBoolean(attrs.isConfigurable());
s = engine->newString(QStringLiteral("configurable"));
- o->__defineOwnProperty__(ctx, s.getPointer(), pd, Attr_Data);
+ o->__defineOwnProperty__(scope.engine, s, pd, Attr_Data);
return o.asReturnedValue();
}
-Returned<ArrayObject> *ObjectPrototype::getOwnPropertyNames(ExecutionEngine *v4, const ValueRef o)
+Heap::ArrayObject *ObjectPrototype::getOwnPropertyNames(ExecutionEngine *v4, const ValueRef o)
{
Scope scope(v4);
- Scoped<ArrayObject> array(scope, v4->newArrayObject());
+ ScopedArrayObject array(scope, v4->newArrayObject());
ScopedObject O(scope, o);
if (O) {
ObjectIterator it(scope, O, ObjectIterator::NoFlags);
@@ -702,5 +680,5 @@ Returned<ArrayObject> *ObjectPrototype::getOwnPropertyNames(ExecutionEngine *v4,
array->push_back(name);
}
}
- return array->asReturned<ArrayObject>();
+ return array->d();
}
diff --git a/src/qml/jsruntime/qv4objectproto_p.h b/src/qml/jsruntime/qv4objectproto_p.h
index 0a5bacbadb..4bbcb297be 100644
--- a/src/qml/jsruntime/qv4objectproto_p.h
+++ b/src/qml/jsruntime/qv4objectproto_p.h
@@ -41,12 +41,17 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
+namespace Heap {
+
+struct ObjectCtor : FunctionObject {
+ ObjectCtor(QV4::ExecutionContext *scope);
+};
+
+}
+
struct ObjectCtor: FunctionObject
{
- struct Data : FunctionObject::Data {
- Data(ExecutionContext *scope);
- };
- V4_OBJECT(FunctionObject)
+ V4_OBJECT2(ObjectCtor, FunctionObject)
static ReturnedValue construct(Managed *that, CallData *callData);
static ReturnedValue call(Managed *that, CallData *callData);
@@ -83,10 +88,10 @@ struct ObjectPrototype: Object
static ReturnedValue method_get_proto(CallContext *ctx);
static ReturnedValue method_set_proto(CallContext *ctx);
- static void toPropertyDescriptor(ExecutionContext *ctx, const ValueRef v, Property *desc, PropertyAttributes *attrs);
- static ReturnedValue fromPropertyDescriptor(ExecutionContext *ctx, const Property *desc, PropertyAttributes attrs);
+ static void toPropertyDescriptor(ExecutionEngine *engine, const ValueRef v, Property *desc, PropertyAttributes *attrs);
+ static ReturnedValue fromPropertyDescriptor(ExecutionEngine *engine, const Property *desc, PropertyAttributes attrs);
- static Returned<ArrayObject> *getOwnPropertyNames(ExecutionEngine *v4, const ValueRef o);
+ static Heap::ArrayObject *getOwnPropertyNames(ExecutionEngine *v4, const ValueRef o);
};
diff --git a/src/qml/jsruntime/qv4persistent.cpp b/src/qml/jsruntime/qv4persistent.cpp
index ff10d71aae..1236d2a469 100644
--- a/src/qml/jsruntime/qv4persistent.cpp
+++ b/src/qml/jsruntime/qv4persistent.cpp
@@ -33,16 +33,17 @@
#include "qv4persistent_p.h"
#include "qv4mm_p.h"
+#include "qv4object_p.h"
using namespace QV4;
-PersistentValue::PersistentValue(const ValueRef val)
- : d(new PersistentValuePrivate(val.asReturnedValue()))
+PersistentValue::PersistentValue(ExecutionEngine *engine, const ValueRef val)
+ : d(new PersistentValuePrivate(val.asReturnedValue(), engine))
{
}
-PersistentValue::PersistentValue(ReturnedValue val)
- : d(new PersistentValuePrivate(val))
+PersistentValue::PersistentValue(ExecutionEngine *engine, ReturnedValue val)
+ : d(new PersistentValuePrivate(val, engine))
{
}
@@ -53,6 +54,12 @@ PersistentValue::PersistentValue(const PersistentValue &other)
d->ref();
}
+PersistentValue::~PersistentValue()
+{
+ if (d)
+ d->deref();
+}
+
PersistentValue &PersistentValue::operator=(const PersistentValue &other)
{
if (d == other.d)
@@ -69,35 +76,48 @@ PersistentValue &PersistentValue::operator=(const PersistentValue &other)
return *this;
}
-PersistentValue &PersistentValue::operator =(const ValueRef other)
+PersistentValue &PersistentValue::operator=(const WeakValue &other)
{
- if (!d) {
- d = new PersistentValuePrivate(other.asReturnedValue());
- return *this;
- }
- d = d->detach(other.asReturnedValue());
+ QV4::ExecutionEngine *engine = other.engine();
+ if (!d)
+ d = new PersistentValuePrivate(other.value(), engine);
+ else
+ d = d->detach(other.value());
return *this;
}
-PersistentValue &PersistentValue::operator =(ReturnedValue other)
+PersistentValue &PersistentValue::operator=(Object *object)
{
- if (!d) {
- d = new PersistentValuePrivate(other);
- return *this;
- }
- d = d->detach(other);
+ QV4::ExecutionEngine *engine = object->engine();
+ if (!d)
+ d = new PersistentValuePrivate(object->asReturnedValue(), engine);
+ else
+ d = d->detach(object->asReturnedValue());
return *this;
}
-PersistentValue::~PersistentValue()
+void PersistentValue::set(ExecutionEngine *engine, const ValueRef val)
{
- if (d)
- d->deref();
+ if (!d)
+ d = new PersistentValuePrivate(val.asReturnedValue(), engine);
+ else
+ d = d->detach(val.asReturnedValue());
}
-WeakValue::WeakValue(const ValueRef val)
- : d(new PersistentValuePrivate(val.asReturnedValue(), /*engine*/0, /*weak*/true))
+void PersistentValue::set(ExecutionEngine *engine, ReturnedValue val)
{
+ if (!d)
+ d = new PersistentValuePrivate(val, engine);
+ else
+ d = d->detach(val);
+}
+
+void PersistentValue::set(ExecutionEngine *engine, Heap::Base *obj)
+{
+ if (!d)
+ d = new PersistentValuePrivate(obj->asReturnedValue(), engine);
+ else
+ d = d->detach(obj->asReturnedValue());
}
WeakValue::WeakValue(const WeakValue &other)
@@ -107,11 +127,6 @@ WeakValue::WeakValue(const WeakValue &other)
d->ref();
}
-WeakValue::WeakValue(ReturnedValue val)
- : d(new PersistentValuePrivate(val, /*engine*/0, /*weak*/true))
-{
-}
-
WeakValue &WeakValue::operator=(const WeakValue &other)
{
if (d == other.d)
@@ -128,31 +143,34 @@ WeakValue &WeakValue::operator=(const WeakValue &other)
return *this;
}
-WeakValue &WeakValue::operator =(const ValueRef other)
+WeakValue::~WeakValue()
{
- if (!d) {
- d = new PersistentValuePrivate(other.asReturnedValue(), /*engine*/0, /*weak*/true);
- return *this;
- }
- d = d->detach(other.asReturnedValue(), /*weak*/true);
- return *this;
+ if (d)
+ d->deref();
}
-WeakValue &WeakValue::operator =(const ReturnedValue &other)
+void WeakValue::set(ExecutionEngine *e, const ValueRef val)
{
- if (!d) {
- d = new PersistentValuePrivate(other, /*engine*/0, /*weak*/true);
- return *this;
- }
- d = d->detach(other, /*weak*/true);
- return *this;
+ if (!d)
+ d = new PersistentValuePrivate(val.asReturnedValue(), e, /*weak*/true);
+ else
+ d = d->detach(val.asReturnedValue(), /*weak*/true);
}
+void WeakValue::set(ExecutionEngine *e, ReturnedValue val)
+{
+ if (!d)
+ d = new PersistentValuePrivate(val, e, /*weak*/true);
+ else
+ d = d->detach(val, /*weak*/true);
+}
-WeakValue::~WeakValue()
+void WeakValue::set(ExecutionEngine *e, Heap::Base *obj)
{
- if (d)
- d->deref();
+ if (!d)
+ d = new PersistentValuePrivate(obj->asReturnedValue(), e, /*weak*/true);
+ else
+ d = d->detach(obj->asReturnedValue(), /*weak*/true);
}
void WeakValue::markOnce(ExecutionEngine *e)
diff --git a/src/qml/jsruntime/qv4persistent_p.h b/src/qml/jsruntime/qv4persistent_p.h
index 57b30f74ec..41c482fbb7 100644
--- a/src/qml/jsruntime/qv4persistent_p.h
+++ b/src/qml/jsruntime/qv4persistent_p.h
@@ -71,23 +71,27 @@ public:
PersistentValue() : d(0) {}
PersistentValue(const PersistentValue &other);
PersistentValue &operator=(const PersistentValue &other);
-
- PersistentValue(const ValueRef val);
- PersistentValue(ReturnedValue val);
- template<typename T>
- PersistentValue(Returned<T> *obj);
- PersistentValue &operator=(const ValueRef other);
- PersistentValue &operator=(const ScopedValue &other);
- PersistentValue &operator =(ReturnedValue other);
- template<typename T>
- PersistentValue &operator=(Returned<T> *obj);
+ PersistentValue &operator=(const WeakValue &other);
+ PersistentValue &operator=(Object *object);
~PersistentValue();
+ PersistentValue(ExecutionEngine *engine, const ValueRef val);
+ PersistentValue(ExecutionEngine *engine, ReturnedValue val);
+
+ void set(ExecutionEngine *engine, const ValueRef val);
+ void set(ExecutionEngine *engine, ReturnedValue val);
+ void set(ExecutionEngine *engine, Heap::Base *obj);
+
ReturnedValue value() const {
return (d ? d->value.asReturnedValue() : Primitive::undefinedValue().asReturnedValue());
}
+ Managed *asManaged() const {
+ if (!d)
+ return 0;
+ return d->value.asManaged();
+ }
- ExecutionEngine *engine() {
+ ExecutionEngine *engine() const {
if (!d)
return 0;
if (d->engine)
@@ -111,24 +115,19 @@ class Q_QML_EXPORT WeakValue
{
public:
WeakValue() : d(0) {}
- WeakValue(const ValueRef val);
WeakValue(const WeakValue &other);
- WeakValue(ReturnedValue val);
- template<typename T>
- WeakValue(Returned<T> *obj);
WeakValue &operator=(const WeakValue &other);
- WeakValue &operator=(const ValueRef other);
- WeakValue &operator =(const ReturnedValue &other);
- template<typename T>
- WeakValue &operator=(Returned<T> *obj);
-
~WeakValue();
+ void set(ExecutionEngine *e, const ValueRef val);
+ void set(ExecutionEngine *e, ReturnedValue val);
+ void set(ExecutionEngine *e, Heap::Base *obj);
+
ReturnedValue value() const {
return (d ? d->value.asReturnedValue() : Primitive::undefinedValue().asReturnedValue());
}
- ExecutionEngine *engine() {
+ ExecutionEngine *engine() const {
if (!d)
return 0;
if (d->engine)
diff --git a/src/qml/jsruntime/qv4profiling_p.h b/src/qml/jsruntime/qv4profiling_p.h
index 7c66ee0049..e6b6f7b1f3 100644
--- a/src/qml/jsruntime/qv4profiling_p.h
+++ b/src/qml/jsruntime/qv4profiling_p.h
@@ -120,11 +120,11 @@ private:
(engine->profiler->featuresEnabled & (1 << Profiling::FeatureMemoryAllocation)) ?\
engine->profiler->trackDealloc(pointer, size, type) : pointer)
-#define Q_V4_PROFILE(engine, ctx, function)\
+#define Q_V4_PROFILE(engine, function)\
(engine->profiler &&\
(engine->profiler->featuresEnabled & (1 << Profiling::FeatureFunctionCall)) ?\
- Profiling::FunctionCallProfiler::profileCall(engine->profiler, ctx, function) :\
- function->code(ctx, function->codeData))
+ Profiling::FunctionCallProfiler::profileCall(engine->profiler, engine, function) :\
+ function->code(engine, function->codeData))
class Q_QML_EXPORT Profiler : public QObject {
Q_OBJECT
@@ -182,10 +182,10 @@ public:
profiler->m_data.append(FunctionCall(function, startTime, profiler->m_timer.nsecsElapsed()));
}
- static ReturnedValue profileCall(Profiler *profiler, ExecutionContext *ctx, Function *function)
+ static ReturnedValue profileCall(Profiler *profiler, ExecutionEngine *engine, Function *function)
{
FunctionCallProfiler callProfiler(profiler, function);
- return function->code(ctx, function->codeData);
+ return function->code(engine, function->codeData);
}
Profiler *profiler;
diff --git a/src/qml/jsruntime/qv4property_p.h b/src/qml/jsruntime/qv4property_p.h
index f9b3159033..ddee264b0e 100644
--- a/src/qml/jsruntime/qv4property_p.h
+++ b/src/qml/jsruntime/qv4property_p.h
@@ -34,7 +34,7 @@
#define QV4PROPERTYDESCRIPTOR_H
#include "qv4global_p.h"
-#include "qv4value_inl_p.h"
+#include "qv4value_p.h"
#include "qv4internalclass_p.h"
QT_BEGIN_NAMESPACE
@@ -68,33 +68,37 @@ struct Property {
return pd;
}
- inline bool isSubset(const PropertyAttributes &attrs, const Property &other, PropertyAttributes otherAttrs) const;
- inline void merge(PropertyAttributes &attrs, const Property &other, PropertyAttributes otherAttrs);
+ inline bool isSubset(const PropertyAttributes &attrs, const Property *other, PropertyAttributes otherAttrs) const;
+ inline void merge(PropertyAttributes &attrs, const Property *other, PropertyAttributes otherAttrs);
- inline FunctionObject *getter() const { return reinterpret_cast<FunctionObject *>(value.asManaged()); }
- inline FunctionObject *setter() const { return reinterpret_cast<FunctionObject *>(set.asManaged()); }
+ inline Heap::FunctionObject *getter() const { return value.isManaged() ? reinterpret_cast<Heap::FunctionObject *>(value.heapObject()) : 0; }
+ inline Heap::FunctionObject *setter() const { return set.isManaged() ? reinterpret_cast<Heap::FunctionObject *>(set.heapObject()) : 0; }
inline void setGetter(FunctionObject *g) { value = Primitive::fromManaged(reinterpret_cast<Managed *>(g)); }
- inline void setSetter(FunctionObject *s) { set = Primitive::fromManaged(reinterpret_cast<Managed *>(s)); }
+ inline void setSetter(FunctionObject *s) { set = s ? Primitive::fromManaged(reinterpret_cast<Managed *>(s)) : Value::fromHeapObject(0); }
- void copy(const Property &other, PropertyAttributes attrs) {
- value = other.value;
+ void copy(const Property *other, PropertyAttributes attrs) {
+ value = other->value;
if (attrs.isAccessor())
- set = other.set;
+ set = other->set;
}
- explicit Property() { value = Encode::undefined(); set = Encode::undefined(); }
- explicit Property(Value v) : value(v) { set = Encode::undefined(); }
+ explicit Property() { value = Encode::undefined(); set = Value::fromHeapObject(0); }
+ explicit Property(Value v) : value(v) { set = Value::fromHeapObject(0); }
Property(FunctionObject *getter, FunctionObject *setter) {
value = Primitive::fromManaged(reinterpret_cast<Managed *>(getter));
set = Primitive::fromManaged(reinterpret_cast<Managed *>(setter));
}
+ Property(Heap::FunctionObject *getter, Heap::FunctionObject *setter) {
+ value.m = reinterpret_cast<Heap::Base *>(getter);
+ set.m = reinterpret_cast<Heap::Base *>(setter);
+ }
Property &operator=(Value v) { value = v; return *this; }
private:
Property(const Property &);
Property &operator=(const Property &);
};
-inline bool Property::isSubset(const PropertyAttributes &attrs, const Property &other, PropertyAttributes otherAttrs) const
+inline bool Property::isSubset(const PropertyAttributes &attrs, const Property *other, PropertyAttributes otherAttrs) const
{
if (attrs.type() != PropertyAttributes::Generic && attrs.type() != otherAttrs.type())
return false;
@@ -104,18 +108,18 @@ inline bool Property::isSubset(const PropertyAttributes &attrs, const Property &
return false;
if (attrs.hasWritable() && attrs.isWritable() != otherAttrs.isWritable())
return false;
- if (attrs.type() == PropertyAttributes::Data && !value.sameValue(other.value))
+ if (attrs.type() == PropertyAttributes::Data && !value.sameValue(other->value))
return false;
if (attrs.type() == PropertyAttributes::Accessor) {
- if (value.asManaged() != other.value.asManaged())
+ if (value.heapObject() != other->value.heapObject())
return false;
- if (set.asManaged() != other.set.asManaged())
+ if (set.heapObject() != other->set.heapObject())
return false;
}
return true;
}
-inline void Property::merge(PropertyAttributes &attrs, const Property &other, PropertyAttributes otherAttrs)
+inline void Property::merge(PropertyAttributes &attrs, const Property *other, PropertyAttributes otherAttrs)
{
if (otherAttrs.hasEnumerable())
attrs.setEnumerable(otherAttrs.isEnumerable());
@@ -125,13 +129,13 @@ inline void Property::merge(PropertyAttributes &attrs, const Property &other, Pr
attrs.setWritable(otherAttrs.isWritable());
if (otherAttrs.type() == PropertyAttributes::Accessor) {
attrs.setType(PropertyAttributes::Accessor);
- if (!other.value.isEmpty())
- value = other.value;
- if (!other.set.isEmpty())
- set = other.set;
+ if (!other->value.isEmpty())
+ value = other->value;
+ if (!other->set.isEmpty())
+ set = other->set;
} else if (otherAttrs.type() == PropertyAttributes::Data){
attrs.setType(PropertyAttributes::Data);
- value = other.value;
+ value = other->value;
}
}
diff --git a/src/qml/jsruntime/qv4qmlextensions_p.h b/src/qml/jsruntime/qv4qmlextensions_p.h
index ffa3071227..8f05ec5191 100644
--- a/src/qml/jsruntime/qv4qmlextensions_p.h
+++ b/src/qml/jsruntime/qv4qmlextensions_p.h
@@ -34,12 +34,11 @@
#define QV4QMLEXTENSIONS_P_H
#include <qtqmlglobal.h>
+#include <qv4global_p.h>
QT_BEGIN_NAMESPACE
namespace QV4 {
-struct Object;
-struct ExecutionEngine;
struct Q_QML_EXPORT QmlExtensions
{
@@ -47,7 +46,7 @@ struct Q_QML_EXPORT QmlExtensions
: valueTypeWrapperPrototype(0)
{}
- Object *valueTypeWrapperPrototype;
+ Heap::Object *valueTypeWrapperPrototype;
void markObjects(ExecutionEngine *e);
};
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index db1315dc87..1248991789 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -96,8 +96,8 @@ static QPair<QObject *, int> extractQtMethod(QV4::FunctionObject *function)
static QPair<QObject *, int> extractQtSignal(const ValueRef value)
{
- QV4::ExecutionEngine *v4 = value->engine();
- if (v4) {
+ if (value->isObject()) {
+ QV4::ExecutionEngine *v4 = value->asObject()->engine();
QV4::Scope scope(v4);
QV4::ScopedFunctionObject function(scope, value);
if (function)
@@ -146,12 +146,11 @@ struct ReadAccessor {
// Load value properties
template<void (*ReadFunction)(QObject *, const QQmlPropertyData &,
void *, QQmlNotifier **)>
-static QV4::ReturnedValue LoadProperty(QV8Engine *engine, QObject *object,
+static QV4::ReturnedValue LoadProperty(QV4::ExecutionEngine *v4, QObject *object,
const QQmlPropertyData &property,
QQmlNotifier **notifier)
{
Q_ASSERT(!property.isFunction());
- QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
QV4::Scope scope(v4);
if (property.isQObject()) {
@@ -159,7 +158,7 @@ static QV4::ReturnedValue LoadProperty(QV8Engine *engine, QObject *object,
ReadFunction(object, property, &rv, notifier);
return QV4::QObjectWrapper::wrap(v4, rv);
} else if (property.isQList()) {
- return QmlListWrapper::create(engine, object, property.coreIndex, property.propType);
+ return QmlListWrapper::create(v4, object, property.coreIndex, property.propType);
} else if (property.propType == QMetaType::QReal) {
qreal v = 0;
ReadFunction(object, property, &v, notifier);
@@ -201,16 +200,16 @@ static QV4::ReturnedValue LoadProperty(QV8Engine *engine, QObject *object,
ReadFunction(object, property, &v, notifier);
if (QQmlValueTypeFactory::isValueType(v.userType())) {
- if (QQmlValueType *valueType = QQmlValueTypeFactory::valueType(v.userType()))
- return QV4::QmlValueTypeWrapper::create(engine, object, property.coreIndex, valueType); // VariantReference value-type.
+ if (const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(v.userType()))
+ return QV4::QQmlValueTypeWrapper::create(v4, object, property.coreIndex, valueTypeMetaObject, v.userType()); // VariantReference value-type.
}
- return engine->fromVariant(v);
+ return scope.engine->fromVariant(v);
} else if (QQmlValueTypeFactory::isValueType(property.propType)) {
Q_ASSERT(notifier == 0);
- if (QQmlValueType *valueType = QQmlValueTypeFactory::valueType(property.propType))
- return QV4::QmlValueTypeWrapper::create(engine, object, property.coreIndex, valueType);
+ if (const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(property.propType))
+ return QV4::QQmlValueTypeWrapper::create(v4, object, property.coreIndex, valueTypeMetaObject, property.propType);
} else {
Q_ASSERT(notifier == 0);
@@ -229,21 +228,21 @@ static QV4::ReturnedValue LoadProperty(QV8Engine *engine, QObject *object,
} else {
QVariant v(property.propType, (void *)0);
ReadFunction(object, property, v.data(), notifier);
- return engine->fromVariant(v);
+ return scope.engine->fromVariant(v);
}
}
-QObjectWrapper::Data::Data(ExecutionEngine *engine, QObject *object)
- : Object::Data(engine)
+Heap::QObjectWrapper::QObjectWrapper(ExecutionEngine *engine, QObject *object)
+ : Heap::Object(engine)
, object(object)
{
- setVTable(staticVTable());
+ setVTable(QV4::QObjectWrapper::staticVTable());
}
void QObjectWrapper::initializeBindings(ExecutionEngine *engine)
{
- engine->functionClass->prototype->defineDefaultProperty(QStringLiteral("connect"), method_connect);
- engine->functionClass->prototype->defineDefaultProperty(QStringLiteral("disconnect"), method_disconnect);
+ engine->functionPrototype.asObject()->defineDefaultProperty(QStringLiteral("connect"), method_connect);
+ engine->functionPrototype.asObject()->defineDefaultProperty(QStringLiteral("disconnect"), method_disconnect);
}
QQmlPropertyData *QObjectWrapper::findProperty(ExecutionEngine *engine, QQmlContextData *qmlContext, String *name, RevisionMode revisionMode, QQmlPropertyData *local) const
@@ -257,11 +256,11 @@ QQmlPropertyData *QObjectWrapper::findProperty(ExecutionEngine *engine, QQmlCont
if (ddata && ddata->propertyCache)
result = ddata->propertyCache->property(name, d()->object, qmlContext);
else
- result = QQmlPropertyCache::property(engine->v8Engine->engine(), d()->object, name, qmlContext, *local);
+ result = QQmlPropertyCache::property(engine->jsEngine(), d()->object, name, qmlContext, *local);
return result;
}
-ReturnedValue QObjectWrapper::getQmlProperty(ExecutionContext *ctx, QQmlContextData *qmlContext, String *n, QObjectWrapper::RevisionMode revisionMode,
+ReturnedValue QObjectWrapper::getQmlProperty(QQmlContextData *qmlContext, String *n, QObjectWrapper::RevisionMode revisionMode,
bool *hasProperty, bool includeImports)
{
if (QQmlData::wasDeleted(d()->object)) {
@@ -270,25 +269,26 @@ ReturnedValue QObjectWrapper::getQmlProperty(ExecutionContext *ctx, QQmlContextD
return QV4::Encode::undefined();
}
- QV4::Scope scope(ctx);
+ QV4::Scope scope(engine());
QV4::ScopedString name(scope, n);
if (name->equals(scope.engine->id_destroy) || name->equals(scope.engine->id_toString)) {
int index = name->equals(scope.engine->id_destroy) ? QV4::QObjectMethod::DestroyMethod : QV4::QObjectMethod::ToStringMethod;
- QV4::ScopedValue method(scope, QV4::QObjectMethod::create(ctx->d()->engine->rootContext, d()->object, index));
+ ScopedContext global(scope, scope.engine->rootContext());
+ QV4::ScopedValue method(scope, QV4::QObjectMethod::create(global, d()->object, index));
if (hasProperty)
*hasProperty = true;
return method.asReturnedValue();
}
QQmlPropertyData local;
- QQmlPropertyData *result = findProperty(ctx->d()->engine, qmlContext, name.getPointer(), revisionMode, &local);
+ QQmlPropertyData *result = findProperty(scope.engine, qmlContext, name, revisionMode, &local);
if (!result) {
if (includeImports && name->startsWithUpper()) {
// Check for attached properties
if (qmlContext && qmlContext->imports) {
- QQmlTypeNameCache::Result r = qmlContext->imports->query(name.getPointer());
+ QQmlTypeNameCache::Result r = qmlContext->imports->query(name);
if (hasProperty)
*hasProperty = true;
@@ -297,15 +297,17 @@ ReturnedValue QObjectWrapper::getQmlProperty(ExecutionContext *ctx, QQmlContextD
if (r.scriptIndex != -1) {
return QV4::Encode::undefined();
} else if (r.type) {
- return QmlTypeWrapper::create(ctx->d()->engine->v8Engine, d()->object, r.type, QmlTypeWrapper::ExcludeEnums);
+ return QmlTypeWrapper::create(scope.engine, d()->object,
+ r.type, Heap::QmlTypeWrapper::ExcludeEnums);
} else if (r.importNamespace) {
- return QmlTypeWrapper::create(ctx->d()->engine->v8Engine, d()->object, qmlContext->imports, r.importNamespace, QmlTypeWrapper::ExcludeEnums);
+ return QmlTypeWrapper::create(scope.engine, d()->object,
+ qmlContext->imports, r.importNamespace, Heap::QmlTypeWrapper::ExcludeEnums);
}
Q_ASSERT(!"Unreachable");
}
}
}
- return QV4::Object::get(this, name.getPointer(), hasProperty);
+ return QV4::Object::get(this, name, hasProperty);
}
QQmlData *ddata = QQmlData::get(d()->object, false);
@@ -321,6 +323,7 @@ ReturnedValue QObjectWrapper::getQmlProperty(ExecutionContext *ctx, QQmlContextD
if (hasProperty)
*hasProperty = true;
+ ScopedContext ctx(scope, scope.engine->currentContext());
return getProperty(d()->object, ctx, result);
}
@@ -336,23 +339,25 @@ ReturnedValue QObjectWrapper::getProperty(QObject *object, ExecutionContext *ctx
Q_ASSERT(vmemo);
return vmemo->vmeMethod(property->coreIndex);
} else if (property->isV4Function()) {
- QV4::Scoped<QV4::Object> qmlcontextobject(scope, ctx->d()->engine->qmlContextObject());
- return QV4::QObjectMethod::create(ctx->d()->engine->rootContext, object, property->coreIndex, qmlcontextobject);
+ QV4::ScopedObject qmlcontextobject(scope, ctx->d()->engine->qmlContextObject());
+ ScopedContext global(scope, scope.engine->rootContext());
+ return QV4::QObjectMethod::create(global, object, property->coreIndex, qmlcontextobject);
} else if (property->isSignalHandler()) {
QV4::Scoped<QV4::QmlSignalHandler> handler(scope, scope.engine->memoryManager->alloc<QV4::QmlSignalHandler>(ctx->d()->engine, object, property->coreIndex));
QV4::ScopedString connect(scope, ctx->d()->engine->newIdentifier(QStringLiteral("connect")));
QV4::ScopedString disconnect(scope, ctx->d()->engine->newIdentifier(QStringLiteral("disconnect")));
- handler->put(connect.getPointer(), QV4::ScopedValue(scope, ctx->d()->engine->functionClass->prototype->get(connect.getPointer())));
- handler->put(disconnect.getPointer(), QV4::ScopedValue(scope, ctx->d()->engine->functionClass->prototype->get(disconnect.getPointer())));
+ handler->put(connect, QV4::ScopedValue(scope, ctx->d()->engine->functionPrototype.asObject()->get(connect)));
+ handler->put(disconnect, QV4::ScopedValue(scope, ctx->d()->engine->functionPrototype.asObject()->get(disconnect)));
return handler.asReturnedValue();
} else {
- return QV4::QObjectMethod::create(ctx->d()->engine->rootContext, object, property->coreIndex);
+ ScopedContext global(scope, scope.engine->rootContext());
+ return QV4::QObjectMethod::create(global, object, property->coreIndex);
}
}
- QQmlEnginePrivate *ep = ctx->d()->engine->v8Engine->engine() ? QQmlEnginePrivate::get(ctx->d()->engine->v8Engine->engine()) : 0;
+ QQmlEnginePrivate *ep = scope.engine->qmlEngine() ? QQmlEnginePrivate::get(scope.engine->qmlEngine()) : 0;
if (property->hasAccessors()) {
QQmlNotifier *n = 0;
@@ -361,7 +366,7 @@ ReturnedValue QObjectWrapper::getProperty(QObject *object, ExecutionContext *ctx
if (ep && ep->propertyCapture && property->accessors->notifier)
nptr = &n;
- QV4::ScopedValue rv(scope, LoadProperty<ReadAccessor::Accessor>(ctx->d()->engine->v8Engine, object, *property, nptr));
+ QV4::ScopedValue rv(scope, LoadProperty<ReadAccessor::Accessor>(ctx->d()->engine, object, *property, nptr));
if (captureRequired) {
if (property->accessors->notifier) {
@@ -383,15 +388,15 @@ ReturnedValue QObjectWrapper::getProperty(QObject *object, ExecutionContext *ctx
Q_ASSERT(vmemo);
return vmemo->vmeProperty(property->coreIndex);
} else if (property->isDirect()) {
- return LoadProperty<ReadAccessor::Direct>(ctx->d()->engine->v8Engine, object, *property, 0);
+ return LoadProperty<ReadAccessor::Direct>(ctx->d()->engine, object, *property, 0);
} else {
- return LoadProperty<ReadAccessor::Indirect>(ctx->d()->engine->v8Engine, object, *property, 0);
+ return LoadProperty<ReadAccessor::Indirect>(ctx->d()->engine, object, *property, 0);
}
}
-ReturnedValue QObjectWrapper::getQmlProperty(ExecutionContext *ctx, QQmlContextData *qmlContext, QObject *object, String *name, QObjectWrapper::RevisionMode revisionMode, bool *hasProperty)
+ReturnedValue QObjectWrapper::getQmlProperty(QV4::ExecutionEngine *engine, QQmlContextData *qmlContext, QObject *object, String *name, QObjectWrapper::RevisionMode revisionMode, bool *hasProperty)
{
- QV4::Scope scope(ctx);
+ QV4::Scope scope(engine);
if (QQmlData::wasDeleted(object)) {
if (hasProperty)
*hasProperty = false;
@@ -404,16 +409,16 @@ ReturnedValue QObjectWrapper::getQmlProperty(ExecutionContext *ctx, QQmlContextD
return QV4::Encode::null();
}
- QV4::Scoped<QObjectWrapper> wrapper(scope, wrap(ctx->d()->engine, object));
+ QV4::Scoped<QObjectWrapper> wrapper(scope, wrap(engine, object));
if (!wrapper) {
if (hasProperty)
*hasProperty = false;
return QV4::Encode::null();
}
- return wrapper->getQmlProperty(ctx, qmlContext, name, revisionMode, hasProperty);
+ return wrapper->getQmlProperty(qmlContext, name, revisionMode, hasProperty);
}
-bool QObjectWrapper::setQmlProperty(ExecutionContext *ctx, QQmlContextData *qmlContext, QObject *object, String *name,
+bool QObjectWrapper::setQmlProperty(ExecutionEngine *engine, QQmlContextData *qmlContext, QObject *object, String *name,
QObjectWrapper::RevisionMode revisionMode, const ValueRef value)
{
if (QQmlData::wasDeleted(object))
@@ -422,7 +427,7 @@ bool QObjectWrapper::setQmlProperty(ExecutionContext *ctx, QQmlContextData *qmlC
QQmlPropertyData local;
QQmlPropertyData *result = 0;
{
- result = QQmlPropertyCache::property(ctx->d()->engine->v8Engine->engine(), object, name, qmlContext, local);
+ result = QQmlPropertyCache::property(engine->jsEngine(), object, name, qmlContext, local);
}
if (!result)
@@ -434,6 +439,8 @@ bool QObjectWrapper::setQmlProperty(ExecutionContext *ctx, QQmlContextData *qmlC
return false;
}
+ Scope scope(engine);
+ ScopedContext ctx(scope, engine->currentContext());
setProperty(object, ctx, result, value);
return true;
}
@@ -443,7 +450,7 @@ void QObjectWrapper::setProperty(QObject *object, ExecutionContext *ctx, QQmlPro
if (!property->isWritable() && !property->isQList()) {
QString error = QLatin1String("Cannot assign to read-only property \"") +
property->name(object) + QLatin1Char('\"');
- ctx->throwTypeError(error);
+ ctx->engine()->throwTypeError(error);
return;
}
@@ -451,7 +458,7 @@ void QObjectWrapper::setProperty(QObject *object, ExecutionContext *ctx, QQmlPro
QV4::Scope scope(ctx);
QV4::ScopedFunctionObject f(scope, value);
if (f) {
- if (!f->bindingKeyFlag()) {
+ if (!f->isBinding()) {
if (!property->isVarProperty() && property->propType != qMetaTypeId<QJSValue>()) {
// assigning a JS function to a non var or QJSValue property or is not allowed.
QString error = QLatin1String("Cannot assign JavaScript function to ");
@@ -459,7 +466,7 @@ void QObjectWrapper::setProperty(QObject *object, ExecutionContext *ctx, QQmlPro
error += QLatin1String("[unknown property type]");
else
error += QLatin1String(QMetaType::typeName(property->propType));
- ctx->throwError(error);
+ ctx->engine()->throwError(error);
return;
}
} else {
@@ -511,7 +518,7 @@ void QObjectWrapper::setProperty(QObject *object, ExecutionContext *ctx, QQmlPro
error += QLatin1String("[unknown property type]");
else
error += QLatin1String(QMetaType::typeName(property->propType));
- ctx->throwError(error);
+ ctx->engine()->throwError(error);
return;
} else if (value->asFunctionObject()) {
// this is handled by the binding creation above
@@ -542,9 +549,9 @@ void QObjectWrapper::setProperty(QObject *object, ExecutionContext *ctx, QQmlPro
} else {
QVariant v;
if (property->isQList())
- v = ctx->d()->engine->v8Engine->toVariant(value, qMetaTypeId<QList<QObject *> >());
+ v = ctx->d()->engine->toVariant(value, qMetaTypeId<QList<QObject *> >());
else
- v = ctx->d()->engine->v8Engine->toVariant(value, property->propType);
+ v = ctx->d()->engine->toVariant(value, property->propType);
QQmlContextData *callingQmlContext = QV4::QmlContextWrapper::callingContext(ctx->d()->engine);
if (!QQmlPropertyPrivate::write(object, *property, v, callingQmlContext)) {
@@ -560,7 +567,7 @@ void QObjectWrapper::setProperty(QObject *object, ExecutionContext *ctx, QQmlPro
QLatin1String(valueType) +
QLatin1String(" to ") +
QLatin1String(targetTypeName);
- ctx->throwError(error);
+ ctx->engine()->throwError(error);
return;
}
}
@@ -586,14 +593,14 @@ ReturnedValue QObjectWrapper::wrap(ExecutionEngine *engine, QObject *object)
!ddata->hasTaintedV8Object)) { // Someone else has used the QObject, but it isn't tainted
QV4::ScopedValue rv(scope, create(engine, object));
- ddata->jsWrapper = rv;
+ ddata->jsWrapper.set(scope.engine, rv);
ddata->jsEngineId = engine->m_engineId;
return rv.asReturnedValue();
} else {
// If this object is tainted, we have to check to see if it is in our
// tainted object list
- Scoped<Object> alternateWrapper(scope, (Object *)0);
+ ScopedObject alternateWrapper(scope, (Object *)0);
if (engine->m_multiplyWrappedQObjects && ddata->hasTaintedV8Object)
alternateWrapper = engine->m_multiplyWrappedQObjects->value(object);
@@ -601,7 +608,7 @@ ReturnedValue QObjectWrapper::wrap(ExecutionEngine *engine, QObject *object)
// a handle in the ddata, we can assume ownership of the ddata->v8object
if (ddata->jsWrapper.isUndefined() && !alternateWrapper) {
QV4::ScopedValue result(scope, create(engine, object));
- ddata->jsWrapper = result;
+ ddata->jsWrapper.set(scope.engine, result);
ddata->jsEngineId = engine->m_engineId;
return result.asReturnedValue();
}
@@ -610,7 +617,7 @@ ReturnedValue QObjectWrapper::wrap(ExecutionEngine *engine, QObject *object)
alternateWrapper = create(engine, object);
if (!engine->m_multiplyWrappedQObjects)
engine->m_multiplyWrappedQObjects = new MultiplyWrappedQObjectMap;
- engine->m_multiplyWrappedQObjects->insert(object, alternateWrapper.getPointer());
+ engine->m_multiplyWrappedQObjects->insert(object, alternateWrapper);
ddata->hasTaintedV8Object = true;
}
@@ -663,18 +670,16 @@ bool QObjectWrapper::isEqualTo(Managed *a, Managed *b)
ReturnedValue QObjectWrapper::create(ExecutionEngine *engine, QObject *object)
{
- QQmlEngine *qmlEngine = engine->v8Engine->engine();
- if (qmlEngine)
- QQmlData::ensurePropertyCache(qmlEngine, object);
+ if (engine->jsEngine())
+ QQmlData::ensurePropertyCache(engine->jsEngine(), object);
return (engine->memoryManager->alloc<QV4::QObjectWrapper>(engine, object))->asReturnedValue();
}
QV4::ReturnedValue QObjectWrapper::get(Managed *m, String *name, bool *hasProperty)
{
QObjectWrapper *that = static_cast<QObjectWrapper*>(m);
- ExecutionEngine *v4 = m->engine();
- QQmlContextData *qmlContext = QV4::QmlContextWrapper::callingContext(v4);
- return that->getQmlProperty(v4->currentContext(), qmlContext, name, IgnoreRevision, hasProperty, /*includeImports*/ true);
+ QQmlContextData *qmlContext = QV4::QmlContextWrapper::callingContext(m->engine());
+ return that->getQmlProperty(qmlContext, name, IgnoreRevision, hasProperty, /*includeImports*/ true);
}
void QObjectWrapper::put(Managed *m, String *name, const ValueRef value)
@@ -686,14 +691,14 @@ void QObjectWrapper::put(Managed *m, String *name, const ValueRef value)
return;
QQmlContextData *qmlContext = QV4::QmlContextWrapper::callingContext(v4);
- if (!setQmlProperty(v4->currentContext(), qmlContext, that->d()->object, name, QV4::QObjectWrapper::IgnoreRevision, value)) {
+ if (!setQmlProperty(v4, qmlContext, that->d()->object, name, QV4::QObjectWrapper::IgnoreRevision, value)) {
QQmlData *ddata = QQmlData::get(that->d()->object);
// Types created by QML are not extensible at run-time, but for other QObjects we can store them
// as regular JavaScript properties, like on JavaScript objects.
if (ddata && ddata->context) {
QString error = QLatin1String("Cannot assign to non-existent property \"") +
name->toQString() + QLatin1Char('\"');
- v4->currentContext()->throwError(error);
+ v4->throwError(error);
} else {
QV4::Object::put(m, name, value);
}
@@ -713,26 +718,31 @@ PropertyAttributes QObjectWrapper::query(const Managed *m, String *name)
return QV4::Object::query(m, name);
}
-void QObjectWrapper::advanceIterator(Managed *m, ObjectIterator *it, String *&name, uint *index, Property *p, PropertyAttributes *attributes)
+void QObjectWrapper::advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attributes)
{
// Used to block access to QObject::destroyed() and QObject::deleteLater() from QML
static const int destroyedIdx1 = QObject::staticMetaObject.indexOfSignal("destroyed(QObject*)");
static const int destroyedIdx2 = QObject::staticMetaObject.indexOfSignal("destroyed()");
static const int deleteLaterIdx = QObject::staticMetaObject.indexOfSlot("deleteLater()");
- name = (String *)0;
+ *name = (Heap::String *)0;
*index = UINT_MAX;
QObjectWrapper *that = static_cast<QObjectWrapper*>(m);
if (that->d()->object) {
const QMetaObject *mo = that->d()->object->metaObject();
+ // These indices don't apply to gadgets, so don't block them.
+ const bool preventDestruction = mo->superClass() || mo == &QObject::staticMetaObject;
const int propertyCount = mo->propertyCount();
if (it->arrayIndex < static_cast<uint>(propertyCount)) {
- name = that->engine()->newString(QString::fromUtf8(mo->property(it->arrayIndex).name()))->getPointer();
+ // #### GC
+ Scope scope(that->engine());
+ ScopedString propName(scope, that->engine()->newString(QString::fromUtf8(mo->property(it->arrayIndex).name())));
+ *name = propName->d();
++it->arrayIndex;
*attributes = QV4::Attr_Data;
- p->value = that->get(name);
+ p->value = that->get(propName);
return;
}
const int methodCount = mo->methodCount();
@@ -740,11 +750,14 @@ void QObjectWrapper::advanceIterator(Managed *m, ObjectIterator *it, String *&na
const int index = it->arrayIndex - propertyCount;
const QMetaMethod method = mo->method(index);
++it->arrayIndex;
- if (method.access() == QMetaMethod::Private || index == deleteLaterIdx || index == destroyedIdx1 || index == destroyedIdx2)
+ if (method.access() == QMetaMethod::Private || (preventDestruction && (index == deleteLaterIdx || index == destroyedIdx1 || index == destroyedIdx2)))
continue;
- name = that->engine()->newString(QString::fromUtf8(method.name()))->getPointer();
+ // #### GC
+ Scope scope(that->engine());
+ ScopedString methodName(scope, that->engine()->newString(QString::fromUtf8(method.name())));
+ *name = methodName->d();
*attributes = QV4::Attr_Data;
- p->value = that->get(name);
+ p->value = that->get(methodName);
return;
}
}
@@ -781,33 +794,32 @@ struct QObjectSlotDispatcher : public QtPrivate::QSlotObjectBase
break;
QVarLengthArray<int, 9> dummy;
- int *argsTypes = QQmlPropertyCache::methodParameterTypes(r, This->signalIndex, dummy, 0);
+ int *argsTypes = QQmlMetaObject(r).methodParameterTypes(This->signalIndex, dummy, 0);
int argCount = argsTypes ? argsTypes[0]:0;
QV4::Scope scope(v4);
QV4::ScopedFunctionObject f(scope, This->function.value());
- QV4::ExecutionContext *ctx = v4->currentContext();
QV4::ScopedCallData callData(scope, argCount);
- callData->thisObject = This->thisObject.isUndefined() ? v4->globalObject->asReturnedValue() : This->thisObject.value();
+ callData->thisObject = This->thisObject.isUndefined() ? v4->globalObject()->asReturnedValue() : This->thisObject.value();
for (int ii = 0; ii < argCount; ++ii) {
int type = argsTypes[ii + 1];
if (type == qMetaTypeId<QVariant>()) {
- callData->args[ii] = v4->v8Engine->fromVariant(*((QVariant *)metaArgs[ii + 1]));
+ callData->args[ii] = v4->fromVariant(*((QVariant *)metaArgs[ii + 1]));
} else {
- callData->args[ii] = v4->v8Engine->fromVariant(QVariant(type, metaArgs[ii + 1]));
+ callData->args[ii] = v4->fromVariant(QVariant(type, metaArgs[ii + 1]));
}
}
f->call(callData);
- if (scope.hasException() && v4->v8Engine) {
- QQmlError error = QV4::ExecutionEngine::catchExceptionAsQmlError(ctx);
+ if (scope.hasException()) {
+ QQmlError error = v4->catchExceptionAsQmlError();
if (error.description().isEmpty()) {
QV4::ScopedString name(scope, f->name());
error.setDescription(QString::fromLatin1("Unknown exception occurred during evaluation of connected function: %1").arg(name->toQString()));
}
- if (QQmlEngine *qmlEngine = v4->v8Engine->engine()) {
+ if (QQmlEngine *qmlEngine = v4->qmlEngine()) {
QQmlEnginePrivate::get(qmlEngine)->warning(error);
} else {
QMessageLogger(error.url().toString().toLatin1().constData(),
@@ -911,8 +923,8 @@ ReturnedValue QObjectWrapper::method_connect(CallContext *ctx)
QV4::QObjectSlotDispatcher *slot = new QV4::QObjectSlotDispatcher;
slot->signalIndex = signalIndex;
- slot->thisObject = thisObject;
- slot->function = f;
+ slot->thisObject.set(scope.engine, thisObject);
+ slot->function.set(scope.engine, f);
if (QQmlData *ddata = QQmlData::get(signalObject)) {
if (QQmlPropertyCache *propertyCache = ddata->propertyCache) {
@@ -989,11 +1001,11 @@ static void markChildQObjectsRecursively(QObject *parent, QV4::ExecutionEngine *
}
}
-void QObjectWrapper::markObjects(Managed *that, QV4::ExecutionEngine *e)
+void QObjectWrapper::markObjects(Heap::Base *that, QV4::ExecutionEngine *e)
{
- QObjectWrapper *This = static_cast<QObjectWrapper*>(that);
+ QObjectWrapper::Data *This = static_cast<QObjectWrapper::Data *>(that);
- if (QObject *o = This->d()->object.data()) {
+ if (QObject *o = This->object.data()) {
QQmlVMEMetaObject *vme = QQmlVMEMetaObject::get(o);
if (vme)
vme->mark(e);
@@ -1032,12 +1044,12 @@ namespace {
};
}
-void QObjectWrapper::destroy(Managed *that)
+void QObjectWrapper::destroy(Heap::Base *that)
{
- QObjectWrapper *This = static_cast<QObjectWrapper*>(that);
- QPointer<QObject> object = This->d()->object;
- ExecutionEngine *engine = This->engine();
- This->d()->~Data();
+ Heap::QObjectWrapper *This = static_cast<Heap::QObjectWrapper*>(that);
+ QPointer<QObject> object = This->object;
+ ExecutionEngine *engine = This->internalClass->engine;
+ This->~Data();
This = 0;
if (!object)
return;
@@ -1078,8 +1090,8 @@ struct CallArgument {
inline void *dataPtr();
inline void initAsType(int type);
- inline void fromValue(int type, QV8Engine *, const ValueRef);
- inline ReturnedValue toValue(QV8Engine *);
+ inline void fromValue(int type, ExecutionEngine *, const ValueRef);
+ inline ReturnedValue toValue(ExecutionEngine *);
private:
CallArgument(const CallArgument &);
@@ -1120,21 +1132,10 @@ private:
};
}
-static QV4::ReturnedValue CallMethod(QObject *object, int index, int returnType, int argCount,
- int *argTypes, QV8Engine *engine, QV4::CallData *callArgs)
+static QV4::ReturnedValue CallMethod(const QQmlObjectOrGadget &object, int index, int returnType, int argCount,
+ int *argTypes, QV4::ExecutionEngine *engine, QV4::CallData *callArgs)
{
if (argCount > 0) {
-
- // Special handling is required for value types.
- // We need to save the current value in a temporary,
- // and reapply it after converting all arguments.
- // This avoids the "overwriting copy-value-type-value"
- // problem during Q_INVOKABLE function invocation.
- QQmlValueType *valueTypeObject = qobject_cast<QQmlValueType*>(object);
- QVariant valueTypeValue;
- if (valueTypeObject)
- valueTypeValue = valueTypeObject->value();
-
// Convert all arguments.
QVarLengthArray<CallArgument, 9> args(argCount + 1);
args[0].initAsType(returnType);
@@ -1144,11 +1145,7 @@ static QV4::ReturnedValue CallMethod(QObject *object, int index, int returnType,
for (int ii = 0; ii < args.count(); ++ii)
argData[ii] = args[ii].dataPtr();
- // Reinstate saved value type object value if required.
- if (valueTypeObject)
- valueTypeObject->setValue(valueTypeValue);
-
- QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, index, argData.data());
+ object.metacall(QMetaObject::InvokeMetaMethod, index, argData.data());
return args[0].toValue(engine);
@@ -1159,14 +1156,14 @@ static QV4::ReturnedValue CallMethod(QObject *object, int index, int returnType,
void *args[] = { arg.dataPtr() };
- QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, index, args);
+ object.metacall(QMetaObject::InvokeMetaMethod, index, args);
return arg.toValue(engine);
} else {
void *args[] = { 0 };
- QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, index, args);
+ object.metacall(QMetaObject::InvokeMetaMethod, index, args);
return Encode::undefined();
}
@@ -1273,12 +1270,10 @@ static int MatchScore(const QV4::ValueRef actual, int conversionType)
}
}
} else if (QV4::Object *obj = actual->asObject()) {
- QV8Engine *engine = obj->engine()->v8Engine;
-
if (obj->as<QV4::VariantObject>()) {
if (conversionType == qMetaTypeId<QVariant>())
return 0;
- if (engine->toVariant(actual, -1).userType() == conversionType)
+ if (obj->engine()->toVariant(actual, -1).userType() == conversionType)
return 0;
else
return 10;
@@ -1293,8 +1288,8 @@ static int MatchScore(const QV4::ValueRef actual, int conversionType)
}
}
- if (obj->as<QV4::QmlValueTypeWrapper>()) {
- if (engine->toVariant(actual, -1).userType() == conversionType)
+ if (obj->as<QV4::QQmlValueTypeWrapper>()) {
+ if (obj->engine()->toVariant(actual, -1).userType() == conversionType)
return 0;
return 10;
} else if (conversionType == QMetaType::QJsonObject) {
@@ -1324,20 +1319,20 @@ static inline int QMetaObject_methods(const QMetaObject *metaObject)
/*!
Returns the next related method, if one, or 0.
*/
-static const QQmlPropertyData * RelatedMethod(QObject *object,
- const QQmlPropertyData *current,
- QQmlPropertyData &dummy)
+static const QQmlPropertyData * RelatedMethod(const QQmlObjectOrGadget &object,
+ const QQmlPropertyData *current,
+ QQmlPropertyData &dummy,
+ const QQmlPropertyCache *propertyCache)
{
- QQmlPropertyCache *cache = QQmlData::get(object)->propertyCache;
if (!current->isOverload())
return 0;
Q_ASSERT(!current->overrideIndexIsProperty);
- if (cache) {
- return cache->method(current->overrideIndex);
+ if (propertyCache) {
+ return propertyCache->method(current->overrideIndex);
} else {
- const QMetaObject *mo = object->metaObject();
+ const QMetaObject *mo = object.metaObject();
int methodOffset = mo->methodCount() - QMetaObject_methods(mo);
while (methodOffset > current->overrideIndex) {
@@ -1368,17 +1363,17 @@ static const QQmlPropertyData * RelatedMethod(QObject *object,
}
}
-static QV4::ReturnedValue CallPrecise(QObject *object, const QQmlPropertyData &data,
- QV8Engine *engine, QV4::CallData *callArgs)
+static QV4::ReturnedValue CallPrecise(const QQmlObjectOrGadget &object, const QQmlPropertyData &data,
+ QV4::ExecutionEngine *engine, QV4::CallData *callArgs)
{
QByteArray unknownTypeError;
- int returnType = QQmlPropertyCache::methodReturnType(object, data, &unknownTypeError);
+ int returnType = object.methodReturnType(data, &unknownTypeError);
if (returnType == QMetaType::UnknownType) {
QString typeName = QString::fromLatin1(unknownTypeError);
QString error = QString::fromLatin1("Unknown method return type: %1").arg(typeName);
- return QV8Engine::getV4(engine)->currentContext()->throwError(error);
+ return engine->throwError(error);
}
if (data.hasArguments()) {
@@ -1386,18 +1381,17 @@ static QV4::ReturnedValue CallPrecise(QObject *object, const QQmlPropertyData &d
int *args = 0;
QVarLengthArray<int, 9> dummy;
- args = QQmlPropertyCache::methodParameterTypes(object, data.coreIndex, dummy,
- &unknownTypeError);
+ args = object.methodParameterTypes(data.coreIndex, dummy, &unknownTypeError);
if (!args) {
QString typeName = QString::fromLatin1(unknownTypeError);
QString error = QString::fromLatin1("Unknown method parameter type: %1").arg(typeName);
- return QV8Engine::getV4(engine)->currentContext()->throwError(error);
+ return engine->throwError(error);
}
if (args[0] > callArgs->argc) {
QString error = QLatin1String("Insufficient arguments");
- return QV8Engine::getV4(engine)->currentContext()->throwError(error);
+ return engine->throwError(error);
}
return CallMethod(object, data.coreIndex, returnType, args[0], args + 1, engine, callArgs);
@@ -1422,8 +1416,8 @@ Resolve the overloaded method to call. The algorithm works conceptually like th
If two or more overloads have the same match score, call the last one. The match
score is constructed by adding the matchScore() result for each of the parameters.
*/
-static QV4::ReturnedValue CallOverloaded(QObject *object, const QQmlPropertyData &data,
- QV8Engine *engine, QV4::CallData *callArgs)
+static QV4::ReturnedValue CallOverloaded(const QQmlObjectOrGadget &object, const QQmlPropertyData &data,
+ QV4::ExecutionEngine *engine, QV4::CallData *callArgs, const QQmlPropertyCache *propertyCache)
{
int argumentCount = callArgs->argc;
@@ -1431,20 +1425,10 @@ static QV4::ReturnedValue CallOverloaded(QObject *object, const QQmlPropertyData
int bestParameterScore = INT_MAX;
int bestMatchScore = INT_MAX;
- // Special handling is required for value types.
- // We need to save the current value in a temporary,
- // and reapply it after converting all arguments.
- // This avoids the "overwriting copy-value-type-value"
- // problem during Q_INVOKABLE function invocation.
- QQmlValueType *valueTypeObject = qobject_cast<QQmlValueType*>(object);
- QVariant valueTypeValue;
- if (valueTypeObject)
- valueTypeValue = valueTypeObject->value();
-
QQmlPropertyData dummy;
const QQmlPropertyData *attempt = &data;
- QV4::Scope scope(QV8Engine::getV4(engine));
+ QV4::Scope scope(engine);
QV4::ScopedValue v(scope);
do {
@@ -1452,8 +1436,7 @@ static QV4::ReturnedValue CallOverloaded(QObject *object, const QQmlPropertyData
int methodArgumentCount = 0;
int *methodArgTypes = 0;
if (attempt->hasArguments()) {
- typedef QQmlPropertyCache PC;
- int *args = PC::methodParameterTypes(object, attempt->coreIndex, dummy, 0);
+ int *args = object.methodParameterTypes(attempt->coreIndex, dummy, 0);
if (!args) // Must be an unknown argument
continue;
@@ -1481,22 +1464,20 @@ static QV4::ReturnedValue CallOverloaded(QObject *object, const QQmlPropertyData
if (bestParameterScore == 0 && bestMatchScore == 0)
break; // We can't get better than that
- } while((attempt = RelatedMethod(object, attempt, dummy)) != 0);
+ } while ((attempt = RelatedMethod(object, attempt, dummy, propertyCache)) != 0);
if (best.isValid()) {
- if (valueTypeObject)
- valueTypeObject->setValue(valueTypeValue);
return CallPrecise(object, best, engine, callArgs);
} else {
QString error = QLatin1String("Unable to determine callable overload. Candidates are:");
const QQmlPropertyData *candidate = &data;
while (candidate) {
error += QLatin1String("\n ") +
- QString::fromUtf8(object->metaObject()->method(candidate->coreIndex).methodSignature().constData());
- candidate = RelatedMethod(object, candidate, dummy);
+ QString::fromUtf8(object.metaObject()->method(candidate->coreIndex).methodSignature().constData());
+ candidate = RelatedMethod(object, candidate, dummy, propertyCache);
}
- return QV8Engine::getV4(engine)->currentContext()->throwError(error);
+ return engine->throwError(error);
}
}
@@ -1582,19 +1563,18 @@ void CallArgument::initAsType(int callType)
}
}
-void CallArgument::fromValue(int callType, QV8Engine *engine, const QV4::ValueRef value)
+void CallArgument::fromValue(int callType, QV4::ExecutionEngine *engine, const QV4::ValueRef value)
{
if (type != 0) {
cleanup();
type = 0;
}
- QV4::Scope scope(QV8Engine::getV4(engine));
+ QV4::Scope scope(engine);
bool queryEngine = false;
if (callType == qMetaTypeId<QJSValue>()) {
- QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
- qjsValuePtr = new (&allocData) QJSValue(new QJSValuePrivate(v4, value));
+ qjsValuePtr = new (&allocData) QJSValue(new QJSValuePrivate(scope.engine, value));
type = qMetaTypeId<QJSValue>();
} else if (callType == QMetaType::Int) {
intValue = quint32(value->toInt32());
@@ -1625,7 +1605,7 @@ void CallArgument::fromValue(int callType, QV8Engine *engine, const QV4::ValueRe
queryEngine = qmlTypeWrapper->isSingleton();
type = callType;
} else if (callType == qMetaTypeId<QVariant>()) {
- qvariantPtr = new (&allocData) QVariant(engine->toVariant(value, -1));
+ qvariantPtr = new (&allocData) QVariant(scope.engine->toVariant(value, -1));
type = callType;
} else if (callType == qMetaTypeId<QList<QObject*> >()) {
qlistPtr = new (&allocData) QList<QObject *>();
@@ -1633,8 +1613,8 @@ void CallArgument::fromValue(int callType, QV8Engine *engine, const QV4::ValueRe
if (array) {
Scoped<QV4::QObjectWrapper> qobjectWrapper(scope);
- uint32_t length = array->getLength();
- for (uint32_t ii = 0; ii < length; ++ii) {
+ uint length = array->getLength();
+ for (uint ii = 0; ii < length; ++ii) {
QObject *o = 0;
qobjectWrapper = array->getIndexed(ii);
if (!!qobjectWrapper)
@@ -1672,8 +1652,8 @@ void CallArgument::fromValue(int callType, QV8Engine *engine, const QV4::ValueRe
qvariantPtr = new (&allocData) QVariant();
type = -1;
- QQmlEnginePrivate *ep = engine->engine() ? QQmlEnginePrivate::get(engine->engine()) : 0;
- QVariant v = engine->toVariant(value, callType);
+ QQmlEnginePrivate *ep = engine->qmlEngine() ? QQmlEnginePrivate::get(engine->qmlEngine()) : 0;
+ QVariant v = scope.engine->toVariant(value, callType);
if (v.userType() == callType) {
*qvariantPtr = v;
@@ -1696,13 +1676,12 @@ void CallArgument::fromValue(int callType, QV8Engine *engine, const QV4::ValueRe
}
}
-QV4::ReturnedValue CallArgument::toValue(QV8Engine *engine)
+QV4::ReturnedValue CallArgument::toValue(QV4::ExecutionEngine *engine)
{
- QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
- QV4::Scope scope(v4);
+ QV4::Scope scope(engine);
if (type == qMetaTypeId<QJSValue>()) {
- return QJSValuePrivate::get(*qjsValuePtr)->getValue(v4);
+ return QJSValuePrivate::get(*qjsValuePtr)->getValue(scope.engine);
} else if (type == QMetaType::Int) {
return QV4::Encode(int(intValue));
} else if (type == QMetaType::UInt) {
@@ -1714,34 +1693,34 @@ QV4::ReturnedValue CallArgument::toValue(QV8Engine *engine)
} else if (type == QMetaType::Float) {
return QV4::Encode(floatValue);
} else if (type == QMetaType::QString) {
- return engine->toString(*qstringPtr);
+ return QV4::Encode(engine->newString(*qstringPtr));
} else if (type == QMetaType::QObjectStar) {
QObject *object = qobjectPtr;
if (object)
QQmlData::get(object, true)->setImplicitDestructible();
- return QV4::QObjectWrapper::wrap(v4, object);
+ return QV4::QObjectWrapper::wrap(scope.engine, object);
} else if (type == qMetaTypeId<QList<QObject *> >()) {
// XXX Can this be made more by using Array as a prototype and implementing
// directly against QList<QObject*>?
QList<QObject *> &list = *qlistPtr;
- QV4::Scoped<ArrayObject> array(scope, v4->newArrayObject());
+ QV4::ScopedArrayObject array(scope, scope.engine->newArrayObject());
array->arrayReserve(list.count());
QV4::ScopedValue v(scope);
for (int ii = 0; ii < list.count(); ++ii)
- array->arrayPut(ii, (v = QV4::QObjectWrapper::wrap(v4, list.at(ii))));
+ array->arrayPut(ii, (v = QV4::QObjectWrapper::wrap(scope.engine, list.at(ii))));
array->setArrayLengthUnchecked(list.count());
return array.asReturnedValue();
} else if (type == qMetaTypeId<QQmlV4Handle>()) {
return *handlePtr;
} else if (type == QMetaType::QJsonArray) {
- return QV4::JsonObject::fromJsonArray(v4, *jsonArrayPtr);
+ return QV4::JsonObject::fromJsonArray(scope.engine, *jsonArrayPtr);
} else if (type == QMetaType::QJsonObject) {
- return QV4::JsonObject::fromJsonObject(v4, *jsonObjectPtr);
+ return QV4::JsonObject::fromJsonObject(scope.engine, *jsonObjectPtr);
} else if (type == QMetaType::QJsonValue) {
- return QV4::JsonObject::fromJsonValue(v4, *jsonValuePtr);
+ return QV4::JsonObject::fromJsonValue(scope.engine, *jsonValuePtr);
} else if (type == -1 || type == qMetaTypeId<QVariant>()) {
QVariant value = *qvariantPtr;
- QV4::ScopedValue rv(scope, engine->fromVariant(value));
+ QV4::ScopedValue rv(scope, scope.engine->fromVariant(value));
QV4::Scoped<QV4::QObjectWrapper> qobjectWrapper(scope, rv);
if (!!qobjectWrapper) {
if (QObject *object = qobjectWrapper->object())
@@ -1755,33 +1734,59 @@ QV4::ReturnedValue CallArgument::toValue(QV8Engine *engine)
ReturnedValue QObjectMethod::create(ExecutionContext *scope, QObject *object, int index, const ValueRef qmlGlobal)
{
- return (scope->d()->engine->memoryManager->alloc<QObjectMethod>(scope, object, index, qmlGlobal))->asReturnedValue();
+ Scope valueScope(scope);
+ Scoped<QObjectMethod> method(valueScope, scope->d()->engine->memoryManager->alloc<QObjectMethod>(scope));
+ method->d()->object = object;
+
+ if (QQmlData *ddata = QQmlData::get(object))
+ method->d()->propertyCache = ddata->propertyCache;
+
+ method->d()->index = index;
+ method->d()->qmlGlobal = qmlGlobal;
+ method->d()->valueTypeWrapper = Primitive::undefinedValue();
+ return method.asReturnedValue();
}
-QObjectMethod::Data::Data(ExecutionContext *scope, QObject *object, int index, const ValueRef qmlGlobal)
- : FunctionObject::Data(scope)
- , object(object)
- , index(index)
- , qmlGlobal(qmlGlobal)
+ReturnedValue QObjectMethod::create(ExecutionContext *scope, QQmlValueTypeWrapper *valueType, int index, const ValueRef qmlGlobal)
{
- setVTable(staticVTable());
- subtype = WrappedQtMethod;
+ Scope valueScope(scope);
+ Scoped<QObjectMethod> method(valueScope, scope->d()->engine->memoryManager->alloc<QObjectMethod>(scope));
+ method->d()->propertyCache = valueType->d()->propertyCache;
+ method->d()->index = index;
+ method->d()->qmlGlobal = qmlGlobal;
+ method->d()->valueTypeWrapper = valueType;
+ return method.asReturnedValue();
+}
+
+Heap::QObjectMethod::QObjectMethod(QV4::ExecutionContext *scope)
+ : Heap::FunctionObject(scope)
+{
+ setVTable(QV4::QObjectMethod::staticVTable());
+}
+
+const QMetaObject *Heap::QObjectMethod::metaObject()
+{
+ if (propertyCache)
+ return propertyCache->createMetaObject();
+ return object->metaObject();
}
QV4::ReturnedValue QObjectMethod::method_toString(QV4::ExecutionContext *ctx)
{
QString result;
- if (d()->object) {
- QString objectName = d()->object->objectName();
+ if (const QMetaObject *metaObject = d()->metaObject()) {
- result += QString::fromUtf8(d()->object->metaObject()->className());
+ result += QString::fromUtf8(metaObject->className());
result += QLatin1String("(0x");
result += QString::number((quintptr)d()->object.data(),16);
- if (!objectName.isEmpty()) {
- result += QLatin1String(", \"");
- result += objectName;
- result += QLatin1Char('\"');
+ if (d()->object) {
+ QString objectName = d()->object->objectName();
+ if (!objectName.isEmpty()) {
+ result += QLatin1String(", \"");
+ result += objectName;
+ result += QLatin1Char('\"');
+ }
}
result += QLatin1Char(')');
@@ -1797,7 +1802,7 @@ QV4::ReturnedValue QObjectMethod::method_destroy(QV4::ExecutionContext *ctx, con
if (!d()->object)
return Encode::undefined();
if (QQmlData::keepAliveDuringGarbageCollection(d()->object))
- return ctx->throwError(QStringLiteral("Invalid attempt to destroy() an indestructible object"));
+ return ctx->engine()->throwError(QStringLiteral("Invalid attempt to destroy() an indestructible object"));
int delay = 0;
if (argc > 0)
@@ -1819,37 +1824,31 @@ ReturnedValue QObjectMethod::call(Managed *m, CallData *callData)
ReturnedValue QObjectMethod::callInternal(CallData *callData)
{
- ExecutionContext *context = engine()->currentContext();
+ Scope scope(engine());
+ ScopedContext context(scope, scope.engine->currentContext());
if (d()->index == DestroyMethod)
return method_destroy(context, callData->args, callData->argc);
else if (d()->index == ToStringMethod)
return method_toString(context);
- QObject *object = d()->object.data();
- if (!object)
- return Encode::undefined();
+ QQmlObjectOrGadget object(d()->object.data());
+ if (!d()->object) {
+ Scoped<QQmlValueTypeWrapper> wrapper(scope, d()->valueTypeWrapper);
+ if (!wrapper)
+ return Encode::undefined();
- QQmlData *ddata = QQmlData::get(object);
- if (!ddata)
- return Encode::undefined();
-
- QV8Engine *v8Engine = context->d()->engine->v8Engine;
- QV4::ExecutionEngine *v4 = QV8Engine::getV4(v8Engine);
- QV4::Scope scope(v4);
+ object = QQmlObjectOrGadget(d()->propertyCache.data(), wrapper->d()->gadget());
+ }
QQmlPropertyData method;
- if (QQmlData *ddata = static_cast<QQmlData *>(QObjectPrivate::get(object)->declarativeData)) {
- if (ddata->propertyCache) {
- QQmlPropertyData *data = ddata->propertyCache->method(d()->index);
- if (!data)
- return QV4::Encode::undefined();
- method = *data;
- }
- }
-
- if (method.coreIndex == -1) {
- const QMetaObject *mo = object->metaObject();
+ if (d()->propertyCache) {
+ QQmlPropertyData *data = d()->propertyCache->method(d()->index);
+ if (!data)
+ return QV4::Encode::undefined();
+ method = *data;
+ } else {
+ const QMetaObject *mo = d()->object->metaObject();
const QMetaMethod moMethod = mo->method(d()->index);
method.load(moMethod);
@@ -1872,33 +1871,40 @@ ReturnedValue QObjectMethod::callInternal(CallData *callData)
if (method.isV4Function()) {
QV4::ScopedValue rv(scope, QV4::Primitive::undefinedValue());
- QV4::ScopedValue qmlGlobal(scope, d()->qmlGlobal.value());
+ QV4::ScopedValue qmlGlobal(scope, d()->qmlGlobal);
QQmlV4Function func(callData, rv, qmlGlobal,
QmlContextWrapper::getContext(qmlGlobal),
- v8Engine);
+ scope.engine);
QQmlV4Function *funcptr = &func;
void *args[] = { 0, &funcptr };
- QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, method.coreIndex, args);
+ object.metacall(QMetaObject::InvokeMetaMethod, method.coreIndex, args);
return rv.asReturnedValue();
}
if (!method.isOverload()) {
- return CallPrecise(object, method, v8Engine, callData);
+ return CallPrecise(object, method, scope.engine, callData);
} else {
- return CallOverloaded(object, method, v8Engine, callData);
+ return CallOverloaded(object, method, scope.engine, callData, d()->propertyCache);
}
}
+void QObjectMethod::markObjects(Heap::Base *that, ExecutionEngine *e)
+{
+ QObjectMethod::Data *This = static_cast<QObjectMethod::Data*>(that);
+ This->qmlGlobal.mark(e);
+ This->valueTypeWrapper.mark(e);
+}
+
DEFINE_OBJECT_VTABLE(QObjectMethod);
-QmlSignalHandler::Data::Data(ExecutionEngine *engine, QObject *object, int signalIndex)
- : Object::Data(engine)
+Heap::QmlSignalHandler::QmlSignalHandler(QV4::ExecutionEngine *engine, QObject *object, int signalIndex)
+ : Heap::Object(engine)
, object(object)
, signalIndex(signalIndex)
{
- setVTable(staticVTable());
+ setVTable(QV4::QmlSignalHandler::staticVTable());
}
DEFINE_OBJECT_VTABLE(QmlSignalHandler);
diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h
index 1a31b5af4b..f0dd440ce3 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper_p.h
+++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h
@@ -67,13 +67,36 @@ class QQmlPropertyData;
namespace QV4 {
struct QObjectSlotDispatcher;
-struct Q_QML_EXPORT QObjectWrapper : public QV4::Object
+namespace Heap {
+
+struct QObjectWrapper : Object {
+ QObjectWrapper(QV4::ExecutionEngine *engine, QObject *object);
+ QPointer<QObject> object;
+};
+
+struct QObjectMethod : FunctionObject {
+ QObjectMethod(QV4::ExecutionContext *scope);
+ QPointer<QObject> object;
+ QQmlRefPointer<QQmlPropertyCache> propertyCache;
+ int index;
+ Value qmlGlobal;
+
+ Value valueTypeWrapper;
+
+ const QMetaObject *metaObject();
+};
+
+struct QmlSignalHandler : Object {
+ QmlSignalHandler(QV4::ExecutionEngine *engine, QObject *object, int signalIndex);
+ QPointer<QObject> object;
+ int signalIndex;
+};
+
+}
+
+struct Q_QML_EXPORT QObjectWrapper : public Object
{
- struct Data : QV4::Object::Data {
- Data(ExecutionEngine *engine, QObject *object);
- QPointer<QObject> object;
- };
- V4_OBJECT(QV4::Object)
+ V4_OBJECT2(QObjectWrapper, Object)
enum RevisionMode { IgnoreRevision, CheckRevision };
@@ -81,10 +104,10 @@ struct Q_QML_EXPORT QObjectWrapper : public QV4::Object
QObject *object() const { return d()->object.data(); }
- ReturnedValue getQmlProperty(ExecutionContext *ctx, QQmlContextData *qmlContext, String *name, RevisionMode revisionMode, bool *hasProperty = 0, bool includeImports = false);
- static ReturnedValue getQmlProperty(ExecutionContext *ctx, QQmlContextData *qmlContext, QObject *object, String *name, RevisionMode revisionMode, bool *hasProperty = 0);
+ ReturnedValue getQmlProperty(QQmlContextData *qmlContext, String *name, RevisionMode revisionMode, bool *hasProperty = 0, bool includeImports = false);
+ static ReturnedValue getQmlProperty(ExecutionEngine *engine, QQmlContextData *qmlContext, QObject *object, String *name, RevisionMode revisionMode, bool *hasProperty = 0);
- static bool setQmlProperty(ExecutionContext *ctx, QQmlContextData *qmlContext, QObject *object, String *name, RevisionMode revisionMode, const ValueRef value);
+ static bool setQmlProperty(ExecutionEngine *engine, QQmlContextData *qmlContext, QObject *object, String *name, RevisionMode revisionMode, const ValueRef value);
static ReturnedValue wrap(ExecutionEngine *engine, QObject *object);
@@ -107,27 +130,25 @@ private:
static ReturnedValue get(Managed *m, String *name, bool *hasProperty);
static void put(Managed *m, String *name, const ValueRef value);
static PropertyAttributes query(const Managed *, String *name);
- static void advanceIterator(Managed *m, ObjectIterator *it, String *&name, uint *index, Property *p, PropertyAttributes *attributes);
- static void markObjects(Managed *that, QV4::ExecutionEngine *e);
- static void destroy(Managed *that);
+ static void advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attributes);
+ static void markObjects(Heap::Base *that, QV4::ExecutionEngine *e);
+ static void destroy(Heap::Base *that);
static ReturnedValue method_connect(CallContext *ctx);
static ReturnedValue method_disconnect(CallContext *ctx);
};
+struct QQmlValueTypeWrapper;
+
struct Q_QML_EXPORT QObjectMethod : public QV4::FunctionObject
{
- struct Data : QV4::FunctionObject::Data {
- Data(QV4::ExecutionContext *scope, QObject *object, int index, const ValueRef qmlGlobal);
- QPointer<QObject> object;
- int index;
- QV4::PersistentValue qmlGlobal;
- };
- V4_OBJECT(QV4::FunctionObject)
+ V4_OBJECT2(QObjectMethod, QV4::FunctionObject)
+ V4_NEEDS_DESTROY
enum { DestroyMethod = -1, ToStringMethod = -2 };
static ReturnedValue create(QV4::ExecutionContext *scope, QObject *object, int index, const ValueRef qmlGlobal = Primitive::undefinedValue());
+ static ReturnedValue create(QV4::ExecutionContext *scope, QQmlValueTypeWrapper *valueType, int index, const ValueRef qmlGlobal = Primitive::undefinedValue());
int methodIndex() const { return d()->index; }
QObject *object() const { return d()->object.data(); }
@@ -139,31 +160,16 @@ struct Q_QML_EXPORT QObjectMethod : public QV4::FunctionObject
ReturnedValue callInternal(CallData *callData);
- static void destroy(Managed *that)
- {
- static_cast<QObjectMethod *>(that)->d()->~Data();
- }
+ static void markObjects(Heap::Base *that, QV4::ExecutionEngine *e);
};
struct QmlSignalHandler : public QV4::Object
{
- struct Data : QV4::Object::Data {
- Data(ExecutionEngine *engine, QObject *object, int signalIndex);
- QPointer<QObject> object;
- int signalIndex;
- };
- V4_OBJECT(QV4::Object)
-
+ V4_OBJECT2(QmlSignalHandler, QV4::Object)
+ V4_NEEDS_DESTROY
int signalIndex() const { return d()->signalIndex; }
QObject *object() const { return d()->object.data(); }
-
-private:
-
- static void destroy(Managed *that)
- {
- static_cast<QmlSignalHandler *>(that)->d()->~Data();
- }
};
class MultiplyWrappedQObjectMap : public QObject,
diff --git a/src/qml/jsruntime/qv4regexp.cpp b/src/qml/jsruntime/qv4regexp.cpp
index e84c96f417..2f1ede1b28 100644
--- a/src/qml/jsruntime/qv4regexp.cpp
+++ b/src/qml/jsruntime/qv4regexp.cpp
@@ -42,7 +42,7 @@ RegExpCache::~RegExpCache()
{
for (RegExpCache::Iterator it = begin(), e = end();
it != e; ++it)
- it.value()->d()->cache = 0;
+ it.value()->cache = 0;
clear();
}
@@ -63,34 +63,35 @@ uint RegExp::match(const QString &string, int start, uint *matchOffsets)
return JSC::Yarr::interpret(byteCode().get(), s.characters16(), string.length(), start, matchOffsets);
}
-RegExp* RegExp::create(ExecutionEngine* engine, const QString& pattern, bool ignoreCase, bool multiline)
+Heap::RegExp *RegExp::create(ExecutionEngine* engine, const QString& pattern, bool ignoreCase, bool multiline)
{
RegExpCacheKey key(pattern, ignoreCase, multiline);
RegExpCache *cache = engine->regExpCache;
if (cache) {
- if (RegExp *result = cache->value(key))
+ if (Heap::RegExp *result = cache->value(key))
return result;
}
- RegExp *result = engine->memoryManager->alloc<RegExp>(engine, pattern, ignoreCase, multiline);
+ Scope scope(engine);
+ Scoped<RegExp> result(scope, engine->memoryManager->alloc<RegExp>(engine, pattern, ignoreCase, multiline));
if (!cache)
cache = engine->regExpCache = new RegExpCache;
result->d()->cache = cache;
- cache->insert(key, result);
+ cache->insert(key, result->d());
- return result;
+ return result->d();
}
-RegExp::Data::Data(ExecutionEngine* engine, const QString &pattern, bool ignoreCase, bool multiline)
- : Managed::Data(engine->regExpValueClass)
+Heap::RegExp::RegExp(ExecutionEngine* engine, const QString &pattern, bool ignoreCase, bool multiline)
+ : Base(engine->regExpValueClass)
, pattern(pattern)
, ignoreCase(ignoreCase)
, multiLine(multiline)
{
- setVTable(staticVTable());
+ setVTable(QV4::RegExp::staticVTable());
const char* error = 0;
JSC::Yarr::YarrPattern yarrPattern(WTF::String(pattern), ignoreCase, multiline, &error);
if (error)
@@ -105,7 +106,7 @@ RegExp::Data::Data(ExecutionEngine* engine, const QString &pattern, bool ignoreC
#endif
}
-RegExp::Data::~Data()
+Heap::RegExp::~RegExp()
{
if (cache) {
RegExpCacheKey key(this);
@@ -113,12 +114,7 @@ RegExp::Data::~Data()
}
}
-void RegExp::destroy(Managed *that)
-{
- static_cast<RegExp*>(that)->d()->~Data();
-}
-
-void RegExp::markObjects(Managed *that, ExecutionEngine *e)
+void RegExp::markObjects(Heap::Base *that, ExecutionEngine *e)
{
Q_UNUSED(that);
Q_UNUSED(e);
diff --git a/src/qml/jsruntime/qv4regexp_p.h b/src/qml/jsruntime/qv4regexp_p.h
index e2f43bf7d7..b76c1ac0a0 100644
--- a/src/qml/jsruntime/qv4regexp_p.h
+++ b/src/qml/jsruntime/qv4regexp_p.h
@@ -56,24 +56,31 @@ namespace QV4 {
struct ExecutionEngine;
struct RegExpCacheKey;
-struct RegExp : public Managed
-{
- struct Data : Managed::Data {
- Data(ExecutionEngine* engine, const QString& pattern, bool ignoreCase, bool multiline);
- ~Data();
- QString pattern;
- OwnPtr<JSC::Yarr::BytecodePattern> byteCode;
+namespace Heap {
+
+struct RegExp : Base {
+ RegExp(ExecutionEngine* engine, const QString& pattern, bool ignoreCase, bool multiline);
+ ~RegExp();
+ QString pattern;
+ OwnPtr<JSC::Yarr::BytecodePattern> byteCode;
#if ENABLE(YARR_JIT)
- JSC::Yarr::YarrCodeBlock jitCode;
+ JSC::Yarr::YarrCodeBlock jitCode;
#endif
- RegExpCache *cache;
- int subPatternCount;
- bool ignoreCase;
- bool multiLine;
- };
- V4_MANAGED(Managed)
- Q_MANAGED_TYPE(RegExp)
+ RegExpCache *cache;
+ int subPatternCount;
+ bool ignoreCase;
+ bool multiLine;
+
+ int captureCount() const { return subPatternCount + 1; }
+};
+
+}
+struct RegExp : public Managed
+{
+ V4_MANAGED(RegExp, Managed)
+ Q_MANAGED_TYPE(RegExp)
+ V4_NEEDS_DESTROY
QString pattern() const { return d()->pattern; }
OwnPtr<JSC::Yarr::BytecodePattern> &byteCode() { return d()->byteCode; }
@@ -85,7 +92,7 @@ struct RegExp : public Managed
bool ignoreCase() const { return d()->ignoreCase; }
bool multiLine() const { return d()->multiLine; }
- static RegExp* create(ExecutionEngine* engine, const QString& pattern, bool ignoreCase = false, bool multiline = false);
+ static Heap::RegExp *create(ExecutionEngine* engine, const QString& pattern, bool ignoreCase = false, bool multiline = false);
bool isValid() const { return d()->byteCode.get(); }
@@ -93,8 +100,7 @@ struct RegExp : public Managed
int captureCount() const { return subPatternCount() + 1; }
- static void destroy(Managed *that);
- static void markObjects(Managed *that, QV4::ExecutionEngine *e);
+ static void markObjects(Heap::Base *that, QV4::ExecutionEngine *e);
friend class RegExpCache;
};
@@ -127,7 +133,8 @@ inline RegExpCacheKey::RegExpCacheKey(const RegExp::Data *re)
inline uint qHash(const RegExpCacheKey& key, uint seed = 0) Q_DECL_NOTHROW
{ return qHash(key.pattern, seed); }
-class RegExpCache : public QHash<RegExpCacheKey, RegExp*>
+// ### GC
+class RegExpCache : public QHash<RegExpCacheKey, Heap::RegExp*>
{
public:
~RegExpCache();
diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp
index c48175247e..4a843d8bdd 100644
--- a/src/qml/jsruntime/qv4regexpobject.cpp
+++ b/src/qml/jsruntime/qv4regexpobject.cpp
@@ -35,6 +35,7 @@
#include "qv4jsir_p.h"
#include "qv4isel_p.h"
#include "qv4objectproto_p.h"
+#include "qv4regexp_p.h"
#include "qv4stringobject_p.h"
#include "qv4mm_p.h"
#include "qv4scopedvalue_p.h"
@@ -64,37 +65,37 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(RegExpObject);
DEFINE_OBJECT_VTABLE(RegExpPrototype);
-RegExpObject::Data::Data(InternalClass *ic)
- : Object::Data(ic)
+Heap::RegExpObject::RegExpObject(InternalClass *ic, QV4::Object *prototype)
+ : Heap::Object(ic, prototype)
{
- setVTable(staticVTable());
+ setVTable(QV4::RegExpObject::staticVTable());
Scope scope(ic->engine);
- Scoped<RegExpObject> o(scope, this);
- o->d()->value = reinterpret_cast<RegExp *>(RegExp::create(ic->engine, QString(), false, false));
+ Scoped<QV4::RegExpObject> o(scope, this);
+ o->d()->value = QV4::RegExp::create(ic->engine, QString(), false, false);
o->d()->global = false;
o->init(ic->engine);
}
-RegExpObject::Data::Data(ExecutionEngine *engine, RegExp *value, bool global)
- : Object::Data(engine->regExpClass)
- , value(value)
+Heap::RegExpObject::RegExpObject(QV4::ExecutionEngine *engine, QV4::RegExp *value, bool global)
+ : Heap::Object(engine->regExpClass, engine->regExpPrototype.asObject())
+ , value(value->d())
, global(global)
{
- setVTable(staticVTable());
+ setVTable(QV4::RegExpObject::staticVTable());
Scope scope(engine);
- Scoped<RegExpObject> o(scope, this);
+ Scoped<QV4::RegExpObject> o(scope, this);
o->init(engine);
}
// Converts a QRegExp to a JS RegExp.
// The conversion is not 100% exact since ECMA regexp and QRegExp
// have different semantics/flags, but we try to do our best.
-RegExpObject::Data::Data(ExecutionEngine *engine, const QRegExp &re)
- : Object::Data(engine->regExpClass)
+Heap::RegExpObject::RegExpObject(QV4::ExecutionEngine *engine, const QRegExp &re)
+ : Heap::Object(engine->regExpClass, engine->regExpPrototype.asObject())
{
- setVTable(staticVTable());
+ setVTable(QV4::RegExpObject::staticVTable());
value = 0;
global = false;
@@ -137,9 +138,9 @@ RegExpObject::Data::Data(ExecutionEngine *engine, const QRegExp &re)
}
Scope scope(engine);
- Scoped<RegExpObject> o(scope, this);
+ Scoped<QV4::RegExpObject> o(scope, this);
- o->d()->value = reinterpret_cast<RegExp *>(RegExp::create(engine, pattern, re.caseSensitivity() == Qt::CaseInsensitive, false));
+ o->d()->value = QV4::RegExp::create(engine, pattern, re.caseSensitivity() == Qt::CaseInsensitive, false);
o->init(engine);
}
@@ -151,11 +152,11 @@ void RegExpObject::init(ExecutionEngine *engine)
ScopedString lastIndex(scope, engine->newIdentifier(QStringLiteral("lastIndex")));
ScopedValue v(scope, Primitive::fromInt32(0));
- insertMember(lastIndex.getPointer(), v, Attr_NotEnumerable|Attr_NotConfigurable);
+ insertMember(lastIndex, v, Attr_NotEnumerable|Attr_NotConfigurable);
if (!this->value())
return;
- QString p = this->value()->pattern();
+ QString p = this->value()->pattern;
if (p.isEmpty()) {
p = QStringLiteral("(?:)");
} else {
@@ -165,23 +166,22 @@ void RegExpObject::init(ExecutionEngine *engine)
defineReadonlyProperty(QStringLiteral("source"), (v = engine->newString(p)));
defineReadonlyProperty(QStringLiteral("global"), Primitive::fromBoolean(global()));
- defineReadonlyProperty(QStringLiteral("ignoreCase"), Primitive::fromBoolean(this->value()->ignoreCase()));
- defineReadonlyProperty(QStringLiteral("multiline"), Primitive::fromBoolean(this->value()->multiLine()));
+ defineReadonlyProperty(QStringLiteral("ignoreCase"), Primitive::fromBoolean(this->value()->ignoreCase));
+ defineReadonlyProperty(QStringLiteral("multiline"), Primitive::fromBoolean(this->value()->multiLine));
}
-void RegExpObject::markObjects(Managed *that, ExecutionEngine *e)
+void RegExpObject::markObjects(Heap::Base *that, ExecutionEngine *e)
{
- RegExpObject *re = static_cast<RegExpObject*>(that);
- if (re->value())
- re->value()->mark(e);
+ RegExpObject::Data *re = static_cast<RegExpObject::Data *>(that);
+ if (re->value)
+ re->value->mark(e);
Object::markObjects(that, e);
}
-Property *RegExpObject::lastIndexProperty(ExecutionContext *ctx)
+Property *RegExpObject::lastIndexProperty()
{
- Q_UNUSED(ctx);
- Q_ASSERT(0 == internalClass()->find(ctx->d()->engine->newIdentifier(QStringLiteral("lastIndex"))));
+ Q_ASSERT(0 == internalClass()->find(engine()->id_lastIndex));
return propertyAt(0);
}
@@ -190,8 +190,8 @@ Property *RegExpObject::lastIndexProperty(ExecutionContext *ctx)
// have different semantics/flags, but we try to do our best.
QRegExp RegExpObject::toQRegExp() const
{
- Qt::CaseSensitivity caseSensitivity = value()->ignoreCase() ? Qt::CaseInsensitive : Qt::CaseSensitive;
- return QRegExp(value()->pattern(), caseSensitivity, QRegExp::RegExp2);
+ Qt::CaseSensitivity caseSensitivity = value()->ignoreCase ? Qt::CaseInsensitive : Qt::CaseSensitive;
+ return QRegExp(value()->pattern, caseSensitivity, QRegExp::RegExp2);
}
QString RegExpObject::toString() const
@@ -200,9 +200,9 @@ QString RegExpObject::toString() const
result += QLatin1Char('/');
if (global())
result += QLatin1Char('g');
- if (value()->ignoreCase())
+ if (value()->ignoreCase)
result += QLatin1Char('i');
- if (value()->multiLine())
+ if (value()->multiLine)
result += QLatin1Char('m');
return result;
}
@@ -211,7 +211,7 @@ QString RegExpObject::source() const
{
Scope scope(engine());
ScopedString source(scope, scope.engine->newIdentifier(QStringLiteral("source")));
- ScopedValue s(scope, const_cast<RegExpObject *>(this)->get(source.getPointer()));
+ ScopedValue s(scope, const_cast<RegExpObject *>(this)->get(source));
return s->toQString();
}
@@ -220,23 +220,23 @@ uint RegExpObject::flags() const
uint f = 0;
if (global())
f |= QV4::RegExpObject::RegExp_Global;
- if (value()->ignoreCase())
+ if (value()->ignoreCase)
f |= QV4::RegExpObject::RegExp_IgnoreCase;
- if (value()->multiLine())
+ if (value()->multiLine)
f |= QV4::RegExpObject::RegExp_Multiline;
return f;
}
DEFINE_OBJECT_VTABLE(RegExpCtor);
-RegExpCtor::Data::Data(ExecutionContext *scope)
- : FunctionObject::Data(scope, QStringLiteral("RegExp"))
+Heap::RegExpCtor::RegExpCtor(QV4::ExecutionContext *scope)
+ : Heap::FunctionObject(scope, QStringLiteral("RegExp"))
{
- setVTable(staticVTable());
+ setVTable(QV4::RegExpCtor::staticVTable());
clearLastMatch();
}
-void RegExpCtor::Data::clearLastMatch()
+void Heap::RegExpCtor::clearLastMatch()
{
lastMatch = Primitive::nullValue();
lastInput = internalClass->engine->id_empty;
@@ -246,22 +246,23 @@ void RegExpCtor::Data::clearLastMatch()
ReturnedValue RegExpCtor::construct(Managed *m, CallData *callData)
{
- ExecutionContext *ctx = m->engine()->currentContext();
- Scope scope(ctx);
+ Scope scope(m->engine());
+ ScopedContext ctx(scope, scope.engine->currentContext());
ScopedValue r(scope, callData->argument(0));
ScopedValue f(scope, callData->argument(1));
Scoped<RegExpObject> re(scope, r);
if (re) {
if (!f->isUndefined())
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
- return Encode(ctx->d()->engine->newRegExpObject(re->value(), re->global()));
+ Scoped<RegExp> regexp(scope, re->value());
+ return Encode(ctx->d()->engine->newRegExpObject(regexp, re->global()));
}
QString pattern;
if (!r->isUndefined())
- pattern = r->toString(ctx)->toQString();
+ pattern = r->toQString();
if (scope.hasException())
return Encode::undefined();
@@ -269,7 +270,7 @@ ReturnedValue RegExpCtor::construct(Managed *m, CallData *callData)
bool ignoreCase = false;
bool multiLine = false;
if (!f->isUndefined()) {
- f = RuntimeHelpers::toString(ctx, f);
+ f = RuntimeHelpers::toString(scope.engine, f);
if (scope.hasException())
return Encode::undefined();
QString str = f->stringValue()->toQString();
@@ -281,14 +282,14 @@ ReturnedValue RegExpCtor::construct(Managed *m, CallData *callData)
} else if (str.at(i) == QLatin1Char('m') && !multiLine) {
multiLine = true;
} else {
- return ctx->throwSyntaxError(QStringLiteral("Invalid flags supplied to RegExp constructor"));
+ return ctx->engine()->throwSyntaxError(QStringLiteral("Invalid flags supplied to RegExp constructor"));
}
}
}
- RegExp *regexp = reinterpret_cast<RegExp *>(RegExp::create(ctx->d()->engine, pattern, ignoreCase, multiLine));
+ Scoped<RegExp> regexp(scope, RegExp::create(ctx->d()->engine, pattern, ignoreCase, multiLine));
if (!regexp->isValid())
- return ctx->throwSyntaxError(QStringLiteral("Invalid regular expression"));
+ return ctx->engine()->throwSyntaxError(QStringLiteral("Invalid regular expression"));
return Encode(ctx->d()->engine->newRegExpObject(regexp, global));
}
@@ -303,11 +304,11 @@ ReturnedValue RegExpCtor::call(Managed *that, CallData *callData)
return construct(that, callData);
}
-void RegExpCtor::markObjects(Managed *that, ExecutionEngine *e)
+void RegExpCtor::markObjects(Heap::Base *that, ExecutionEngine *e)
{
- RegExpCtor *This = static_cast<RegExpCtor*>(that);
- This->lastMatch().mark(e);
- This->lastInput().mark(e);
+ RegExpCtor::Data *This = static_cast<RegExpCtor::Data *>(that);
+ This->lastMatch.mark(e);
+ This->lastInput.mark(e);
FunctionObject::markObjects(that, e);
}
@@ -353,45 +354,45 @@ ReturnedValue RegExpPrototype::method_exec(CallContext *ctx)
Scope scope(ctx);
Scoped<RegExpObject> r(scope, ctx->d()->callData->thisObject.as<RegExpObject>());
if (!r)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
ScopedValue arg(scope, ctx->argument(0));
- arg = RuntimeHelpers::toString(ctx, arg);
+ arg = RuntimeHelpers::toString(scope.engine, arg);
if (scope.hasException())
return Encode::undefined();
QString s = arg->stringValue()->toQString();
- int offset = r->global() ? r->lastIndexProperty(ctx)->value.toInt32() : 0;
+ int offset = r->global() ? r->lastIndexProperty()->value.toInt32() : 0;
if (offset < 0 || offset > s.length()) {
- r->lastIndexProperty(ctx)->value = Primitive::fromInt32(0);
+ r->lastIndexProperty()->value = Primitive::fromInt32(0);
return Encode::null();
}
uint* matchOffsets = (uint*)alloca(r->value()->captureCount() * 2 * sizeof(uint));
- const int result = r->value()->match(s, offset, matchOffsets);
+ const int result = Scoped<RegExp>(scope, r->value())->match(s, offset, matchOffsets);
Scoped<RegExpCtor> regExpCtor(scope, ctx->d()->engine->regExpCtor);
regExpCtor->d()->clearLastMatch();
if (result == -1) {
- r->lastIndexProperty(ctx)->value = Primitive::fromInt32(0);
+ r->lastIndexProperty()->value = Primitive::fromInt32(0);
return Encode::null();
}
// fill in result data
- Scoped<ArrayObject> array(scope, ctx->d()->engine->newArrayObject(ctx->d()->engine->regExpExecArrayClass));
+ ScopedArrayObject array(scope, scope.engine->newArrayObject(scope.engine->regExpExecArrayClass, scope.engine->arrayPrototype.asObject()));
int len = r->value()->captureCount();
array->arrayReserve(len);
ScopedValue v(scope);
for (int i = 0; i < len; ++i) {
int start = matchOffsets[i * 2];
int end = matchOffsets[i * 2 + 1];
- v = (start != -1 && end != -1) ? ctx->d()->engine->newString(s.mid(start, end - start))->asReturnedValue() : Encode::undefined();
+ v = (start != -1) ? ctx->d()->engine->newString(s.mid(start, end - start))->asReturnedValue() : Encode::undefined();
array->arrayPut(i, v);
}
array->setArrayLengthUnchecked(len);
- array->memberData()[Index_ArrayIndex] = Primitive::fromInt32(result);
- array->memberData()[Index_ArrayInput] = arg.asReturnedValue();
+ array->memberData()->data[Index_ArrayIndex] = Primitive::fromInt32(result);
+ array->memberData()->data[Index_ArrayInput] = arg.asReturnedValue();
RegExpCtor::Data *dd = regExpCtor->d();
dd->lastMatch = array;
@@ -400,7 +401,7 @@ ReturnedValue RegExpPrototype::method_exec(CallContext *ctx)
dd->lastMatchEnd = matchOffsets[1];
if (r->global())
- r->lastIndexProperty(ctx)->value = Primitive::fromInt32(matchOffsets[1]);
+ r->lastIndexProperty()->value = Primitive::fromInt32(matchOffsets[1]);
return array.asReturnedValue();
}
@@ -417,7 +418,7 @@ ReturnedValue RegExpPrototype::method_toString(CallContext *ctx)
Scope scope(ctx);
Scoped<RegExpObject> r(scope, ctx->d()->callData->thisObject.as<RegExpObject>());
if (!r)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
return ctx->d()->engine->newString(r->toString())->asReturnedValue();
}
@@ -427,7 +428,7 @@ ReturnedValue RegExpPrototype::method_compile(CallContext *ctx)
Scope scope(ctx);
Scoped<RegExpObject> r(scope, ctx->d()->callData->thisObject.as<RegExpObject>());
if (!r)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
ScopedCallData callData(scope, ctx->d()->callData->argc);
memcpy(callData->args, ctx->d()->callData->args, ctx->d()->callData->argc*sizeof(Value));
@@ -446,7 +447,7 @@ ReturnedValue RegExpPrototype::method_get_lastMatch_n(CallContext *ctx)
ScopedArrayObject lastMatch(scope, static_cast<RegExpCtor*>(ctx->d()->engine->regExpCtor.objectValue())->lastMatch());
ScopedValue result(scope, lastMatch ? lastMatch->getIndexed(index) : Encode::undefined());
if (result->isUndefined())
- return ctx->d()->engine->newString(QString())->asReturnedValue();
+ return ctx->d()->engine->newString()->asReturnedValue();
return result.asReturnedValue();
}
@@ -456,7 +457,7 @@ ReturnedValue RegExpPrototype::method_get_lastParen(CallContext *ctx)
ScopedArrayObject lastMatch(scope, static_cast<RegExpCtor*>(ctx->d()->engine->regExpCtor.objectValue())->lastMatch());
ScopedValue result(scope, lastMatch ? lastMatch->getIndexed(lastMatch->getLength() - 1) : Encode::undefined());
if (result->isUndefined())
- return ctx->d()->engine->newString(QString())->asReturnedValue();
+ return ctx->d()->engine->newString()->asReturnedValue();
return result.asReturnedValue();
}
diff --git a/src/qml/jsruntime/qv4regexpobject_p.h b/src/qml/jsruntime/qv4regexpobject_p.h
index e2f8049157..1320527fe1 100644
--- a/src/qml/jsruntime/qv4regexpobject_p.h
+++ b/src/qml/jsruntime/qv4regexpobject_p.h
@@ -43,7 +43,6 @@
#include "qv4managed_p.h"
#include "qv4property_p.h"
#include "qv4objectiterator_p.h"
-#include "qv4regexp_p.h"
#include <QtCore/QString>
#include <QtCore/QHash>
@@ -55,16 +54,35 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
-struct RegExpObject: Object {
- struct Data : Object::Data {
- Data(ExecutionEngine *engine, RegExp *value, bool global);
- Data(ExecutionEngine *engine, const QRegExp &re);
- Data(InternalClass *ic);
+namespace Heap {
- RegExp *value;
- bool global;
- };
- V4_OBJECT(Object)
+struct RegExpObject : Object {
+ RegExpObject(InternalClass *ic, QV4::Object *prototype);
+ RegExpObject(QV4::ExecutionEngine *engine, QV4::RegExp *value, bool global);
+ RegExpObject(QV4::ExecutionEngine *engine, const QRegExp &re);
+
+ RegExp *value;
+ bool global;
+};
+
+struct RegExpCtor : FunctionObject {
+ RegExpCtor(QV4::ExecutionContext *scope);
+ Value lastMatch;
+ StringValue lastInput;
+ int lastMatchStart;
+ int lastMatchEnd;
+ void clearLastMatch();
+};
+
+struct RegExpPrototype : RegExpObject
+{
+ inline RegExpPrototype(ExecutionEngine *e);
+};
+
+}
+
+struct RegExpObject: Object {
+ V4_OBJECT2(RegExpObject, Object)
Q_MANAGED_TYPE(RegExpObject)
// needs to be compatible with the flags in qv4jsir_p.h
@@ -75,36 +93,28 @@ struct RegExpObject: Object {
};
enum {
- Index_ArrayIndex = ArrayObject::LengthPropertyIndex + 1,
+ Index_ArrayIndex = Heap::ArrayObject::LengthPropertyIndex + 1,
Index_ArrayInput = Index_ArrayIndex + 1
};
- RegExp *value() const { return d()->value; }
+ Heap::RegExp *value() const { return d()->value; }
bool global() const { return d()->global; }
void init(ExecutionEngine *engine);
- Property *lastIndexProperty(ExecutionContext *ctx);
+ Property *lastIndexProperty();
QRegExp toQRegExp() const;
QString toString() const;
QString source() const;
uint flags() const;
protected:
- static void markObjects(Managed *that, ExecutionEngine *e);
+ static void markObjects(Heap::Base *that, ExecutionEngine *e);
};
struct RegExpCtor: FunctionObject
{
- struct Data : FunctionObject::Data {
- Data(ExecutionContext *scope);
- Value lastMatch;
- StringValue lastInput;
- int lastMatchStart;
- int lastMatchEnd;
- void clearLastMatch();
- };
- V4_OBJECT(FunctionObject)
+ V4_OBJECT2(RegExpCtor, FunctionObject)
Value lastMatch() { return d()->lastMatch; }
StringValue lastInput() { return d()->lastInput; }
@@ -113,19 +123,12 @@ struct RegExpCtor: FunctionObject
static ReturnedValue construct(Managed *m, CallData *callData);
static ReturnedValue call(Managed *that, CallData *callData);
- static void markObjects(Managed *that, ExecutionEngine *e);
+ static void markObjects(Heap::Base *that, ExecutionEngine *e);
};
struct RegExpPrototype: RegExpObject
{
- struct Data : RegExpObject::Data
- {
- Data(InternalClass *ic): RegExpObject::Data(ic)
- {
- setVTable(staticVTable());
- }
- };
- V4_OBJECT(RegExpObject)
+ V4_OBJECT2(RegExpPrototype, RegExpObject)
void init(ExecutionEngine *engine, Object *ctor);
@@ -142,6 +145,11 @@ struct RegExpPrototype: RegExpObject
static ReturnedValue method_get_rightContext(CallContext *ctx);
};
+inline Heap::RegExpPrototype::RegExpPrototype(ExecutionEngine *e)
+ : RegExpObject(InternalClass::create(e, QV4::RegExpPrototype::staticVTable()), e->objectPrototype.asObject())
+{
+}
+
}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index f72f25bd58..61a2fc5fd3 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -35,11 +35,11 @@
#include "qv4runtime_p.h"
#ifndef V4_BOOTSTRAP
#include "qv4object_p.h"
-#include "qv4jsir_p.h"
#include "qv4objectproto_p.h"
#include "qv4globalobject_p.h"
#include "qv4stringobject_p.h"
#include "qv4argumentsobject_p.h"
+#include "qv4objectiterator_p.h"
#include "qv4lookup_p.h"
#include "qv4function_p.h"
#include "private/qlocale_tools_p.h"
@@ -60,6 +60,11 @@
#include "../../3rdparty/double-conversion/double-conversion.h"
+#ifdef QV4_COUNT_RUNTIME_FUNCTIONS
+# include <QtCore/QBuffer>
+# include <QtCore/QDebug>
+#endif // QV4_COUNT_RUNTIME_FUNCTIONS
+
QT_BEGIN_NAMESPACE
namespace QV4 {
@@ -144,7 +149,9 @@ struct RuntimeCounters::Data {
};
void dump() const {
- QTextStream outs(stderr, QIODevice::WriteOnly);
+ QBuffer buf;
+ buf.open(QIODevice::WriteOnly);
+ QTextStream outs(&buf);
QList<Line> lines;
foreach (const char *func, counters.keys()) {
const Counters &fCount = counters[func];
@@ -159,7 +166,7 @@ struct RuntimeCounters::Data {
lines.append(line);
}
}
- qSort(lines.begin(), lines.end(), Line::less);
+ std::sort(lines.begin(), lines.end(), Line::less);
outs << lines.size() << " counters:" << endl;
foreach (const Line &line, lines)
outs << qSetFieldWidth(10) << line.count << qSetFieldWidth(0)
@@ -167,6 +174,7 @@ struct RuntimeCounters::Data {
<< " | " << pretty(line.tag1)
<< " | " << pretty(line.tag2)
<< endl;
+ qDebug("%s", buf.data().constData());
}
};
@@ -256,16 +264,17 @@ void RuntimeHelpers::numberToString(QString *result, double num, int radix)
result->prepend(QLatin1Char('-'));
}
-ReturnedValue Runtime::closure(ExecutionContext *ctx, int functionId)
+ReturnedValue Runtime::closure(ExecutionEngine *engine, int functionId)
{
- QV4::Function *clos = ctx->d()->compilationUnit->runtimeFunctions[functionId];
+ QV4::Function *clos = engine->currentContext()->compilationUnit->runtimeFunctions[functionId];
Q_ASSERT(clos);
- return FunctionObject::createScriptFunction(ctx, clos)->asReturnedValue();
+ Scope scope(engine);
+ return FunctionObject::createScriptFunction(ScopedContext(scope, engine->currentContext()), clos)->asReturnedValue();
}
-ReturnedValue Runtime::deleteElement(ExecutionContext *ctx, const ValueRef base, const ValueRef index)
+ReturnedValue Runtime::deleteElement(ExecutionEngine *engine, const ValueRef base, const ValueRef index)
{
- Scope scope(ctx);
+ Scope scope(engine);
ScopedObject o(scope, base);
if (o) {
uint n = index->asArrayIndex();
@@ -274,66 +283,73 @@ ReturnedValue Runtime::deleteElement(ExecutionContext *ctx, const ValueRef base,
}
}
- ScopedString name(scope, index->toString(ctx));
- return Runtime::deleteMember(ctx, base, name.getPointer());
+ ScopedString name(scope, index->toString(engine));
+ return Runtime::deleteMemberString(engine, base, name);
+}
+
+ReturnedValue Runtime::deleteMember(ExecutionEngine *engine, const ValueRef base, int nameIndex)
+{
+ Scope scope(engine);
+ ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
+ return deleteMemberString(engine, base, name);
}
-ReturnedValue Runtime::deleteMember(ExecutionContext *ctx, const ValueRef base, String *name)
+ReturnedValue Runtime::deleteMemberString(ExecutionEngine *engine, const ValueRef base, String *name)
{
- Scope scope(ctx);
- ScopedObject obj(scope, base->toObject(ctx));
+ Scope scope(engine);
+ ScopedObject obj(scope, base->toObject(engine));
if (scope.engine->hasException)
return Encode::undefined();
return Encode(obj->deleteProperty(name));
}
-ReturnedValue Runtime::deleteName(ExecutionContext *ctx, String *name)
+ReturnedValue Runtime::deleteName(ExecutionEngine *engine, int nameIndex)
{
- Scope scope(ctx);
+ Scope scope(engine);
+ ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
+ ScopedContext ctx(scope, engine->currentContext());
return Encode(ctx->deleteProperty(name));
}
-QV4::ReturnedValue Runtime::instanceof(ExecutionContext *ctx, const ValueRef left, const ValueRef right)
+QV4::ReturnedValue Runtime::instanceof(ExecutionEngine *engine, const ValueRef left, const ValueRef right)
{
- // As nothing in this method can call into the memory manager, avoid using a Scope
- // for performance reasons
-
- FunctionObject *f = right->asFunctionObject();
+ Scope scope(engine);
+ ScopedFunctionObject f(scope, right->asFunctionObject());
if (!f)
- return ctx->throwTypeError();
+ return engine->throwTypeError();
- if (f->subtype() == FunctionObject::BoundFunction)
- f = static_cast<BoundFunction *>(f)->target();
+ if (f->isBoundFunction())
+ f = static_cast<BoundFunction *>(f.getPointer())->target();
- Object *v = left->asObject();
+ ScopedObject v(scope, left->asObject());
if (!v)
return Encode(false);
- Object *o = QV4::Value::fromReturnedValue(f->protoProperty()).asObject();
+ ScopedObject o(scope, QV4::Value::fromReturnedValue(f->protoProperty()).asObject());
if (!o)
- return ctx->throwTypeError();
+ return engine->throwTypeError();
while (v) {
v = v->prototype();
if (!v)
break;
- else if (o == v)
+ else if (o->d() == v->d())
return Encode(true);
}
return Encode(false);
}
-QV4::ReturnedValue Runtime::in(ExecutionContext *ctx, const ValueRef left, const ValueRef right)
+QV4::ReturnedValue Runtime::in(ExecutionEngine *engine, const ValueRef left, const ValueRef right)
{
if (!right->isObject())
- return ctx->throwTypeError();
- Scope scope(ctx);
- ScopedString s(scope, left->toString(ctx));
+ return engine->throwTypeError();
+ Scope scope(engine);
+ ScopedString s(scope, left->toString(engine));
if (scope.hasException())
return Encode::undefined();
- bool r = right->objectValue()->hasProperty(s.getPointer());
+ bool r = right->objectValue()->hasProperty(s);
return Encode(r);
}
@@ -358,11 +374,11 @@ double RuntimeHelpers::stringToNumber(const QString &string)
return d;
}
-Returned<String> *RuntimeHelpers::stringFromNumber(ExecutionContext *ctx, double number)
+Heap::String *RuntimeHelpers::stringFromNumber(ExecutionEngine *engine, double number)
{
QString qstr;
RuntimeHelpers::numberToString(&qstr, number, 10);
- return ctx->engine()->newString(qstr);
+ return engine->newString(qstr);
}
ReturnedValue RuntimeHelpers::objectDefaultValue(Object *object, int typeHint)
@@ -384,8 +400,7 @@ ReturnedValue RuntimeHelpers::objectDefaultValue(Object *object, int typeHint)
if (typeHint == NUMBER_HINT)
qSwap(meth1, meth2);
- ExecutionContext *ctx = engine->currentContext();
- Scope scope(ctx);
+ Scope scope(engine);
ScopedCallData callData(scope, 0);
callData->thisObject = object;
@@ -406,115 +421,115 @@ ReturnedValue RuntimeHelpers::objectDefaultValue(Object *object, int typeHint)
return r->asReturnedValue();
}
- return ctx->throwTypeError();
+ return engine->throwTypeError();
}
-Returned<Object> *RuntimeHelpers::convertToObject(ExecutionContext *ctx, const ValueRef value)
+Heap::Object *RuntimeHelpers::convertToObject(ExecutionEngine *engine, const ValueRef value)
{
- assert(!value->isObject());
+ Q_ASSERT(!value->isObject());
switch (value->type()) {
case Value::Undefined_Type:
case Value::Null_Type:
- ctx->throwTypeError();
+ engine->throwTypeError();
return 0;
case Value::Boolean_Type:
- return ctx->engine()->newBooleanObject(value);
+ return engine->newBooleanObject(value);
case Value::Managed_Type:
Q_ASSERT(value->isString());
- return ctx->engine()->newStringObject(value);
+ return engine->newStringObject(value);
case Value::Integer_Type:
default: // double
- return ctx->engine()->newNumberObject(value);
+ return engine->newNumberObject(value);
}
}
-Returned<String> *RuntimeHelpers::convertToString(ExecutionContext *ctx, const ValueRef value)
+Heap::String *RuntimeHelpers::convertToString(ExecutionEngine *engine, const ValueRef value)
{
switch (value->type()) {
case Value::Empty_Type:
Q_ASSERT(!"empty Value encountered");
case Value::Undefined_Type:
- return ctx->engine()->id_undefined.ret();
+ return engine->id_undefined->d();
case Value::Null_Type:
- return ctx->engine()->id_null.ret();
+ return engine->id_null->d();
case Value::Boolean_Type:
if (value->booleanValue())
- return ctx->engine()->id_true.ret();
+ return engine->id_true->d();
else
- return ctx->engine()->id_false.ret();
+ return engine->id_false->d();
case Value::Managed_Type:
if (value->isString())
- return value->stringValue()->asReturned<String>();
+ return value->stringValue()->d();
{
- Scope scope(ctx);
+ Scope scope(engine);
ScopedValue prim(scope, RuntimeHelpers::toPrimitive(value, STRING_HINT));
- return RuntimeHelpers::convertToString(ctx, prim);
+ return RuntimeHelpers::convertToString(engine, prim);
}
case Value::Integer_Type:
- return RuntimeHelpers::stringFromNumber(ctx, value->int_32);
+ return RuntimeHelpers::stringFromNumber(engine, value->int_32);
default: // double
- return RuntimeHelpers::stringFromNumber(ctx, value->doubleValue());
+ return RuntimeHelpers::stringFromNumber(engine, value->doubleValue());
} // switch
}
// This is slightly different from the method above, as
// the + operator requires a slightly different conversion
-static Returned<String> *convert_to_string_add(ExecutionContext *ctx, const ValueRef value)
+static Heap::String *convert_to_string_add(ExecutionEngine *engine, const ValueRef value)
{
switch (value->type()) {
case Value::Empty_Type:
Q_ASSERT(!"empty Value encountered");
case Value::Undefined_Type:
- return ctx->engine()->id_undefined.ret();
+ return engine->id_undefined->d();
case Value::Null_Type:
- return ctx->engine()->id_null.ret();
+ return engine->id_null->d();
case Value::Boolean_Type:
if (value->booleanValue())
- return ctx->engine()->id_true.ret();
+ return engine->id_true->d();
else
- return ctx->engine()->id_false.ret();
+ return engine->id_false->d();
case Value::Managed_Type:
if (value->isString())
- return value->stringValue()->asReturned<String>();
+ return value->stringValue()->d();
{
- Scope scope(ctx);
+ Scope scope(engine);
ScopedValue prim(scope, RuntimeHelpers::toPrimitive(value, PREFERREDTYPE_HINT));
- return RuntimeHelpers::convertToString(ctx, prim);
+ return RuntimeHelpers::convertToString(engine, prim);
}
case Value::Integer_Type:
- return RuntimeHelpers::stringFromNumber(ctx, value->int_32);
+ return RuntimeHelpers::stringFromNumber(engine, value->int_32);
default: // double
- return RuntimeHelpers::stringFromNumber(ctx, value->doubleValue());
+ return RuntimeHelpers::stringFromNumber(engine, value->doubleValue());
} // switch
}
-QV4::ReturnedValue RuntimeHelpers::addHelper(ExecutionContext *ctx, const ValueRef left, const ValueRef right)
+QV4::ReturnedValue RuntimeHelpers::addHelper(ExecutionEngine *engine, const ValueRef left, const ValueRef right)
{
- Scope scope(ctx);
+ Scope scope(engine);
ScopedValue pleft(scope, RuntimeHelpers::toPrimitive(left, PREFERREDTYPE_HINT));
ScopedValue pright(scope, RuntimeHelpers::toPrimitive(right, PREFERREDTYPE_HINT));
if (pleft->isString() || pright->isString()) {
if (!pleft->isString())
- pleft = convert_to_string_add(ctx, pleft);
+ pleft = convert_to_string_add(engine, pleft);
if (!pright->isString())
- pright = convert_to_string_add(ctx, pright);
+ pright = convert_to_string_add(engine, pright);
if (scope.engine->hasException)
return Encode::undefined();
if (!pleft->stringValue()->d()->length())
return pright->asReturnedValue();
if (!pright->stringValue()->d()->length())
return pleft->asReturnedValue();
- return (ctx->engine()->memoryManager->alloc<String>(ctx->d()->engine, pleft->stringValue(), pright->stringValue()))->asReturnedValue();
+ return (engine->memoryManager->alloc<String>(engine, pleft->stringValue()->d(), pright->stringValue()->d()))->asReturnedValue();
}
double x = RuntimeHelpers::toNumber(pleft);
double y = RuntimeHelpers::toNumber(pright);
return Encode(x + y);
}
-QV4::ReturnedValue Runtime::addString(QV4::ExecutionContext *ctx, const QV4::ValueRef left, const QV4::ValueRef right)
+QV4::ReturnedValue Runtime::addString(ExecutionEngine *engine, const QV4::ValueRef left, const QV4::ValueRef right)
{
Q_ASSERT(left->isString() || right->isString());
@@ -523,41 +538,42 @@ QV4::ReturnedValue Runtime::addString(QV4::ExecutionContext *ctx, const QV4::Val
return right->asReturnedValue();
if (!right->stringValue()->d()->length())
return left->asReturnedValue();
- return (ctx->engine()->memoryManager->alloc<String>(ctx->d()->engine, left->stringValue(), right->stringValue()))->asReturnedValue();
+ return (engine->memoryManager->alloc<String>(engine, left->stringValue()->d(), right->stringValue()->d()))->asReturnedValue();
}
- Scope scope(ctx);
+ Scope scope(engine);
ScopedValue pleft(scope, *left);
ScopedValue pright(scope, *right);
if (!pleft->isString())
- pleft = convert_to_string_add(ctx, left);
+ pleft = convert_to_string_add(engine, left);
if (!pright->isString())
- pright = convert_to_string_add(ctx, right);
+ pright = convert_to_string_add(engine, right);
if (scope.engine->hasException)
return Encode::undefined();
if (!pleft->stringValue()->d()->length())
return pright->asReturnedValue();
if (!pright->stringValue()->d()->length())
return pleft->asReturnedValue();
- return (ctx->engine()->memoryManager->alloc<String>(ctx->d()->engine, pleft->stringValue(), pright->stringValue()))->asReturnedValue();
+ return (engine->memoryManager->alloc<String>(engine, pleft->stringValue()->d(), pright->stringValue()->d()))->asReturnedValue();
}
-void Runtime::setProperty(ExecutionContext *ctx, const ValueRef object, String *name, const ValueRef value)
+void Runtime::setProperty(ExecutionEngine *engine, const ValueRef object, int nameIndex, const ValueRef value)
{
- Scope scope(ctx);
- ScopedObject o(scope, object->toObject(ctx));
+ Scope scope(engine);
+ ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
+ ScopedObject o(scope, object->toObject(engine));
if (!o)
return;
o->put(name, value);
}
-ReturnedValue Runtime::getElement(ExecutionContext *ctx, const ValueRef object, const ValueRef index)
+ReturnedValue Runtime::getElement(ExecutionEngine *engine, const ValueRef object, const ValueRef index)
{
- Scope scope(ctx);
+ Scope scope(engine);
uint idx = index->asArrayIndex();
- Scoped<Object> o(scope, object);
+ ScopedObject o(scope, object);
if (!o) {
if (idx < UINT_MAX) {
if (String *str = object->asString()) {
@@ -571,16 +587,16 @@ ReturnedValue Runtime::getElement(ExecutionContext *ctx, const ValueRef object,
if (object->isNullOrUndefined()) {
QString message = QStringLiteral("Cannot read property '%1' of %2").arg(index->toQStringNoThrow()).arg(object->toQStringNoThrow());
- return ctx->throwTypeError(message);
+ return engine->throwTypeError(message);
}
- o = RuntimeHelpers::convertToObject(ctx, object);
+ o = RuntimeHelpers::convertToObject(scope.engine, object);
if (!o) // type error
return Encode::undefined();
}
if (idx < UINT_MAX) {
- if (o->arrayData() && !o->arrayData()->hasAttributes()) {
+ if (o->arrayData() && !o->arrayData()->attrs) {
ScopedValue v(scope, o->arrayData()->get(idx));
if (!v->isEmpty())
return v->asReturnedValue();
@@ -589,24 +605,24 @@ ReturnedValue Runtime::getElement(ExecutionContext *ctx, const ValueRef object,
return o->getIndexed(idx);
}
- ScopedString name(scope, index->toString(ctx));
+ ScopedString name(scope, index->toString(engine));
if (scope.hasException())
return Encode::undefined();
- return o->get(name.getPointer());
+ return o->get(name);
}
-void Runtime::setElement(ExecutionContext *ctx, const ValueRef object, const ValueRef index, const ValueRef value)
+void Runtime::setElement(ExecutionEngine *engine, const ValueRef object, const ValueRef index, const ValueRef value)
{
- Scope scope(ctx);
- ScopedObject o(scope, object->toObject(ctx));
+ Scope scope(engine);
+ ScopedObject o(scope, object->toObject(engine));
if (scope.engine->hasException)
return;
uint idx = index->asArrayIndex();
if (idx < UINT_MAX) {
- if (o->arrayType() == ArrayData::Simple) {
- SimpleArrayData *s = static_cast<SimpleArrayData *>(o->arrayData());
- if (s && idx < s->len() && !s->data(idx).isEmpty()) {
+ if (o->arrayType() == Heap::ArrayData::Simple) {
+ Heap::SimpleArrayData *s = static_cast<Heap::SimpleArrayData *>(o->arrayData());
+ if (s && idx < s->len && !s->data(idx).isEmpty()) {
s->data(idx) = value;
return;
}
@@ -615,18 +631,17 @@ void Runtime::setElement(ExecutionContext *ctx, const ValueRef object, const Val
return;
}
- ScopedString name(scope, index->toString(ctx));
- o->put(name.getPointer(), value);
+ ScopedString name(scope, index->toString(engine));
+ o->put(name, value);
}
-ReturnedValue Runtime::foreachIterator(ExecutionContext *ctx, const ValueRef in)
+ReturnedValue Runtime::foreachIterator(ExecutionEngine *engine, const ValueRef in)
{
- Scope scope(ctx);
- Scoped<Object> o(scope, (Object *)0);
+ Scope scope(engine);
+ ScopedObject o(scope, (Object *)0);
if (!in->isNullOrUndefined())
- o = in->toObject(ctx);
- Scoped<Object> it(scope, ctx->engine()->newForEachIteratorObject(ctx, o));
- return it.asReturnedValue();
+ o = in->toObject(engine);
+ return engine->newForEachIteratorObject(o)->asReturnedValue();
}
ReturnedValue Runtime::foreachNextPropertyName(const ValueRef foreach_iterator)
@@ -640,32 +655,39 @@ ReturnedValue Runtime::foreachNextPropertyName(const ValueRef foreach_iterator)
}
-void Runtime::setActivationProperty(ExecutionContext *ctx, String *name, const ValueRef value)
+void Runtime::setActivationProperty(ExecutionEngine *engine, int nameIndex, const ValueRef value)
{
+ Scope scope(engine);
+ ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
+ ScopedContext ctx(scope, engine->currentContext());
ctx->setProperty(name, value);
}
-ReturnedValue Runtime::getProperty(ExecutionContext *ctx, const ValueRef object, String *name)
+ReturnedValue Runtime::getProperty(ExecutionEngine *engine, const ValueRef object, int nameIndex)
{
- Scope scope(ctx);
+ Scope scope(engine);
+ ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
- Scoped<Object> o(scope, object);
+ ScopedObject o(scope, object);
if (o)
return o->get(name);
if (object->isNullOrUndefined()) {
QString message = QStringLiteral("Cannot read property '%1' of %2").arg(name->toQString()).arg(object->toQStringNoThrow());
- return ctx->throwTypeError(message);
+ return engine->throwTypeError(message);
}
- o = RuntimeHelpers::convertToObject(ctx, object);
+ o = RuntimeHelpers::convertToObject(scope.engine, object);
if (!o) // type error
return Encode::undefined();
return o->get(name);
}
-ReturnedValue Runtime::getActivationProperty(ExecutionContext *ctx, String *name)
+ReturnedValue Runtime::getActivationProperty(ExecutionEngine *engine, int nameIndex)
{
+ Scope scope(engine);
+ ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
+ ScopedContext ctx(scope, engine->currentContext());
return ctx->getProperty(name);
}
@@ -721,7 +743,7 @@ Bool RuntimeHelpers::strictEqual(const ValueRef x, const ValueRef y)
if (x->isNumber())
return y->isNumber() && x->asDouble() == y->asDouble();
if (x->isManaged())
- return y->isManaged() && x->managed()->isEqualTo(y->managed());
+ return y->isManaged() && x->cast<Managed>()->isEqualTo(y->cast<Managed>());
return false;
}
@@ -858,30 +880,52 @@ QV4::Bool Runtime::compareLessEqual(const QV4::ValueRef l, const QV4::ValueRef r
}
#ifndef V4_BOOTSTRAP
-ReturnedValue Runtime::callGlobalLookup(ExecutionContext *context, uint index, CallData *callData)
+Bool Runtime::compareInstanceof(ExecutionEngine *engine, const ValueRef left, const ValueRef right)
{
- Scope scope(context);
+ TRACE2(left, right);
+
+ Scope scope(engine);
+ ScopedValue v(scope, Runtime::instanceof(engine, left, right));
+ return v->booleanValue();
+}
+
+uint Runtime::compareIn(ExecutionEngine *engine, const ValueRef left, const ValueRef right)
+{
+ TRACE2(left, right);
+
+ Scope scope(engine);
+ ScopedValue v(scope, Runtime::in(engine, left, right));
+ return v->booleanValue();
+}
+
+
+ReturnedValue Runtime::callGlobalLookup(ExecutionEngine *engine, uint index, CallData *callData)
+{
+ Scope scope(engine);
Q_ASSERT(callData->thisObject.isUndefined());
- Lookup *l = context->d()->lookups + index;
- Scoped<FunctionObject> o(scope, l->globalGetter(l, context));
+ Lookup *l = engine->currentContext()->lookups + index;
+ ScopedFunctionObject o(scope, l->globalGetter(l, engine));
if (!o)
- return context->throwTypeError();
+ return engine->throwTypeError();
- if (o.getPointer() == scope.engine->evalFunction && l->name->equals(scope.engine->id_eval))
+ ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[l->nameIndex]);
+ if (o->d() == scope.engine->evalFunction && name->equals(scope.engine->id_eval))
return static_cast<EvalFunction *>(o.getPointer())->evalCall(callData, true);
return o->call(callData);
}
-ReturnedValue Runtime::callActivationProperty(ExecutionContext *context, String *name, CallData *callData)
+ReturnedValue Runtime::callActivationProperty(ExecutionEngine *engine, int nameIndex, CallData *callData)
{
Q_ASSERT(callData->thisObject.isUndefined());
- Scope scope(context);
+ Scope scope(engine);
+ ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
ScopedObject base(scope);
- ScopedValue func(scope, context->getPropertyAndBase(name, base.ptr->o));
+ ScopedContext ctx(scope, engine->currentContext());
+ ScopedValue func(scope, ctx->getPropertyAndBase(name, base.getRef()));
if (scope.engine->hasException)
return Encode::undefined();
@@ -894,242 +938,255 @@ ReturnedValue Runtime::callActivationProperty(ExecutionContext *context, String
if (base)
objectAsString = ScopedValue(scope, base.asReturnedValue())->toQStringNoThrow();
QString msg = QStringLiteral("Property '%1' of object %2 is not a function").arg(name->toQString()).arg(objectAsString);
- return context->throwTypeError(msg);
+ return engine->throwTypeError(msg);
}
- if (o == scope.engine->evalFunction && name->equals(scope.engine->id_eval)) {
+ if (o->d() == scope.engine->evalFunction && name->equals(scope.engine->id_eval)) {
return static_cast<EvalFunction *>(o)->evalCall(callData, true);
}
return o->call(callData);
}
-ReturnedValue Runtime::callProperty(ExecutionContext *context, String *name, CallData *callData)
+ReturnedValue Runtime::callProperty(ExecutionEngine *engine, int nameIndex, CallData *callData)
{
- Scope scope(context);
- Scoped<Object> baseObject(scope, callData->thisObject);
+ Scope scope(engine);
+ ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
+ ScopedObject baseObject(scope, callData->thisObject);
if (!baseObject) {
Q_ASSERT(!callData->thisObject.isEmpty());
if (callData->thisObject.isNullOrUndefined()) {
QString message = QStringLiteral("Cannot call method '%1' of %2").arg(name->toQString()).arg(callData->thisObject.toQStringNoThrow());
- return context->throwTypeError(message);
+ return engine->throwTypeError(message);
}
- baseObject = RuntimeHelpers::convertToObject(context, ValueRef(&callData->thisObject));
+ baseObject = RuntimeHelpers::convertToObject(scope.engine, ValueRef(&callData->thisObject));
if (!baseObject) // type error
return Encode::undefined();
callData->thisObject = baseObject.asReturnedValue();
}
- Scoped<FunctionObject> o(scope, baseObject->get(name));
+ ScopedFunctionObject o(scope, baseObject->get(name));
if (!o) {
QString error = QStringLiteral("Property '%1' of object %2 is not a function").arg(name->toQString(), callData->thisObject.toQStringNoThrow());
- return context->throwTypeError(error);
+ return engine->throwTypeError(error);
}
return o->call(callData);
}
-ReturnedValue Runtime::callPropertyLookup(ExecutionContext *context, uint index, CallData *callData)
+ReturnedValue Runtime::callPropertyLookup(ExecutionEngine *engine, uint index, CallData *callData)
{
- Lookup *l = context->d()->lookups + index;
+ Lookup *l = engine->currentContext()->lookups + index;
Value v;
- v = l->getter(l, callData->thisObject);
+ v = l->getter(l, engine, callData->thisObject);
if (!v.isObject())
- return context->throwTypeError();
+ return engine->throwTypeError();
return v.objectValue()->call(callData);
}
-ReturnedValue Runtime::callElement(ExecutionContext *context, const ValueRef index, CallData *callData)
+ReturnedValue Runtime::callElement(ExecutionEngine *engine, const ValueRef index, CallData *callData)
{
- Scope scope(context);
- ScopedObject baseObject(scope, callData->thisObject.toObject(context));
- ScopedString s(scope, index->toString(context));
+ Scope scope(engine);
+ ScopedObject baseObject(scope, callData->thisObject.toObject(engine));
+ ScopedString s(scope, index->toString(engine));
if (scope.engine->hasException)
return Encode::undefined();
callData->thisObject = baseObject;
- ScopedObject o(scope, baseObject->get(s.getPointer()));
+ ScopedObject o(scope, baseObject->get(s));
if (!o)
- return context->throwTypeError();
+ return engine->throwTypeError();
return o->call(callData);
}
-ReturnedValue Runtime::callValue(ExecutionContext *context, const ValueRef func, CallData *callData)
+ReturnedValue Runtime::callValue(ExecutionEngine *engine, const ValueRef func, CallData *callData)
{
if (!func->isObject())
- return context->throwTypeError();
+ return engine->throwTypeError();
return func->objectValue()->call(callData);
}
-ReturnedValue Runtime::constructGlobalLookup(ExecutionContext *context, uint index, CallData *callData)
+ReturnedValue Runtime::constructGlobalLookup(ExecutionEngine *engine, uint index, CallData *callData)
{
- Scope scope(context);
+ Scope scope(engine);
Q_ASSERT(callData->thisObject.isUndefined());
- Lookup *l = context->d()->lookups + index;
- Scoped<Object> f(scope, l->globalGetter(l, context));
+ Lookup *l = engine->currentContext()->lookups + index;
+ ScopedObject f(scope, l->globalGetter(l, engine));
if (!f)
- return context->throwTypeError();
+ return engine->throwTypeError();
return f->construct(callData);
}
-ReturnedValue Runtime::constructActivationProperty(ExecutionContext *context, String *name, CallData *callData)
+ReturnedValue Runtime::constructActivationProperty(ExecutionEngine *engine, int nameIndex, CallData *callData)
{
- Scope scope(context);
- ScopedValue func(scope, context->getProperty(name));
+ Scope scope(engine);
+ ScopedContext ctx(scope, engine->currentContext());
+ ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
+ ScopedValue func(scope, ctx->getProperty(name));
if (scope.engine->hasException)
return Encode::undefined();
Object *f = func->asObject();
if (!f)
- return context->throwTypeError();
+ return engine->throwTypeError();
return f->construct(callData);
}
-ReturnedValue Runtime::constructValue(ExecutionContext *context, const ValueRef func, CallData *callData)
+ReturnedValue Runtime::constructValue(ExecutionEngine *engine, const ValueRef func, CallData *callData)
{
Object *f = func->asObject();
if (!f)
- return context->throwTypeError();
+ return engine->throwTypeError();
return f->construct(callData);
}
-ReturnedValue Runtime::constructProperty(ExecutionContext *context, String *name, CallData *callData)
+ReturnedValue Runtime::constructProperty(ExecutionEngine *engine, int nameIndex, CallData *callData)
{
- Scope scope(context);
- ScopedObject thisObject(scope, callData->thisObject.toObject(context));
+ Scope scope(engine);
+ ScopedObject thisObject(scope, callData->thisObject.toObject(engine));
+ ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
if (scope.engine->hasException)
return Encode::undefined();
- Scoped<Object> f(scope, thisObject->get(name));
+ ScopedObject f(scope, thisObject->get(name));
if (!f)
- return context->throwTypeError();
+ return engine->throwTypeError();
return f->construct(callData);
}
-ReturnedValue Runtime::constructPropertyLookup(ExecutionContext *context, uint index, CallData *callData)
+ReturnedValue Runtime::constructPropertyLookup(ExecutionEngine *engine, uint index, CallData *callData)
{
- Lookup *l = context->d()->lookups + index;
+ Lookup *l = engine->currentContext()->lookups + index;
Value v;
- v = l->getter(l, callData->thisObject);
+ v = l->getter(l, engine, callData->thisObject);
if (!v.isObject())
- return context->throwTypeError();
+ return engine->throwTypeError();
return v.objectValue()->construct(callData);
}
-void Runtime::throwException(ExecutionContext *context, const ValueRef value)
+void Runtime::throwException(ExecutionEngine *engine, const ValueRef value)
{
if (!value->isEmpty())
- context->throwError(value);
+ engine->throwError(value);
}
-ReturnedValue Runtime::typeofValue(ExecutionContext *ctx, const ValueRef value)
+ReturnedValue Runtime::typeofValue(ExecutionEngine *engine, const ValueRef value)
{
- Scope scope(ctx);
+ Scope scope(engine);
ScopedString res(scope);
switch (value->type()) {
case Value::Undefined_Type:
- res = ctx->engine()->id_undefined;
+ res = engine->id_undefined;
break;
case Value::Null_Type:
- res = ctx->engine()->id_object;
+ res = engine->id_object;
break;
case Value::Boolean_Type:
- res = ctx->engine()->id_boolean;
+ res = engine->id_boolean;
break;
case Value::Managed_Type:
if (value->isString())
- res = ctx->engine()->id_string;
+ res = engine->id_string;
else if (value->objectValue()->asFunctionObject())
- res = ctx->engine()->id_function;
+ res = engine->id_function;
else
- res = ctx->engine()->id_object; // ### implementation-defined
+ res = engine->id_object; // ### implementation-defined
break;
default:
- res = ctx->engine()->id_number;
+ res = engine->id_number;
break;
}
return res.asReturnedValue();
}
-QV4::ReturnedValue Runtime::typeofName(ExecutionContext *context, String *name)
+QV4::ReturnedValue Runtime::typeofName(ExecutionEngine *engine, int nameIndex)
{
- Scope scope(context);
- ScopedValue prop(scope, context->getProperty(name));
+ Scope scope(engine);
+ ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
+ ScopedContext ctx(scope, engine->currentContext());
+ ScopedValue prop(scope, ctx->getProperty(name));
// typeof doesn't throw. clear any possible exception
scope.engine->hasException = false;
- return Runtime::typeofValue(context, prop);
+ return Runtime::typeofValue(engine, prop);
}
-QV4::ReturnedValue Runtime::typeofMember(ExecutionContext *context, const ValueRef base, String *name)
+QV4::ReturnedValue Runtime::typeofMember(ExecutionEngine *engine, const ValueRef base, int nameIndex)
{
- Scope scope(context);
- ScopedObject obj(scope, base->toObject(context));
+ Scope scope(engine);
+ ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
+ ScopedObject obj(scope, base->toObject(engine));
if (scope.engine->hasException)
return Encode::undefined();
ScopedValue prop(scope, obj->get(name));
- return Runtime::typeofValue(context, prop);
+ return Runtime::typeofValue(engine, prop);
}
-QV4::ReturnedValue Runtime::typeofElement(ExecutionContext *context, const ValueRef base, const ValueRef index)
+QV4::ReturnedValue Runtime::typeofElement(ExecutionEngine *engine, const ValueRef base, const ValueRef index)
{
- Scope scope(context);
- ScopedString name(scope, index->toString(context));
- ScopedObject obj(scope, base->toObject(context));
+ Scope scope(engine);
+ ScopedString name(scope, index->toString(engine));
+ ScopedObject obj(scope, base->toObject(engine));
if (scope.engine->hasException)
return Encode::undefined();
- ScopedValue prop(scope, obj->get(name.getPointer()));
- return Runtime::typeofValue(context, prop);
+ ScopedValue prop(scope, obj->get(name));
+ return Runtime::typeofValue(engine, prop);
}
-ExecutionContext *Runtime::pushWithScope(const ValueRef o, ExecutionContext *ctx)
+void Runtime::pushWithScope(const ValueRef o, ExecutionEngine *engine)
{
- Scope scope(ctx);
- ScopedObject obj(scope, o->toObject(ctx));
- return reinterpret_cast<ExecutionContext *>(ctx->newWithContext(obj));
+ Scope scope(engine);
+ ScopedObject obj(scope, o->toObject(engine));
+ ScopedContext ctx(scope, engine->currentContext());
+ ctx->newWithContext(obj);
}
-ReturnedValue Runtime::unwindException(ExecutionContext *ctx)
+ReturnedValue Runtime::unwindException(ExecutionEngine *engine)
{
- if (!ctx->engine()->hasException)
+ if (!engine->hasException)
return Primitive::emptyValue().asReturnedValue();
- return ctx->engine()->catchException(ctx, 0);
+ return engine->catchException(0);
}
-ExecutionContext *Runtime::pushCatchScope(ExecutionContext *ctx, String *exceptionVarName)
+void Runtime::pushCatchScope(NoThrowEngine *engine, int exceptionVarNameIndex)
{
- Scope scope(ctx);
- ScopedValue v(scope, ctx->engine()->catchException(ctx, 0));
- return reinterpret_cast<ExecutionContext *>(ctx->newCatchContext(exceptionVarName, v));
+ Scope scope(engine);
+ ScopedValue v(scope, engine->catchException(0));
+ ScopedString exceptionVarName(scope, engine->currentContext()->compilationUnit->runtimeStrings[exceptionVarNameIndex]);
+ ScopedContext ctx(scope, engine->currentContext());
+ ctx->newCatchContext(exceptionVarName, v);
}
-ExecutionContext *Runtime::popScope(ExecutionContext *ctx)
+void Runtime::popScope(ExecutionEngine *engine)
{
- return ctx->engine()->popContext();
+ engine->popContext();
}
-void Runtime::declareVar(ExecutionContext *ctx, bool deletable, String *name)
+void Runtime::declareVar(ExecutionEngine *engine, bool deletable, int nameIndex)
{
+ Scope scope(engine);
+ ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
+ ScopedContext ctx(scope, engine->currentContext());
ctx->createMutableBinding(name, deletable);
}
-ReturnedValue Runtime::arrayLiteral(ExecutionContext *ctx, Value *values, uint length)
+ReturnedValue Runtime::arrayLiteral(ExecutionEngine *engine, Value *values, uint length)
{
- Scope scope(ctx);
- Scoped<ArrayObject> a(scope, ctx->engine()->newArrayObject());
+ Scope scope(engine);
+ ScopedArrayObject a(scope, engine->newArrayObject());
if (length) {
a->arrayReserve(length);
@@ -1139,11 +1196,11 @@ ReturnedValue Runtime::arrayLiteral(ExecutionContext *ctx, Value *values, uint l
return a.asReturnedValue();
}
-ReturnedValue Runtime::objectLiteral(QV4::ExecutionContext *ctx, const QV4::Value *args, int classId, int arrayValueCount, int arrayGetterSetterCountAndFlags)
+ReturnedValue Runtime::objectLiteral(ExecutionEngine *engine, const QV4::Value *args, int classId, int arrayValueCount, int arrayGetterSetterCountAndFlags)
{
- Scope scope(ctx);
- QV4::InternalClass *klass = ctx->d()->compilationUnit->runtimeClasses[classId];
- Scoped<Object> o(scope, ctx->engine()->newObject(klass));
+ Scope scope(engine);
+ QV4::InternalClass *klass = engine->currentContext()->compilationUnit->runtimeClasses[classId];
+ ScopedObject o(scope, engine->newObject(klass, engine->objectPrototype.asObject()));
{
bool needSparseArray = arrayGetterSetterCountAndFlags >> 30;
@@ -1152,7 +1209,7 @@ ReturnedValue Runtime::objectLiteral(QV4::ExecutionContext *ctx, const QV4::Valu
}
for (uint i = 0; i < klass->size; ++i)
- o->memberData()[i] = *args++;
+ o->memberData()->data[i] = *args++;
if (arrayValueCount > 0) {
ScopedValue entry(scope);
@@ -1181,11 +1238,12 @@ ReturnedValue Runtime::objectLiteral(QV4::ExecutionContext *ctx, const QV4::Valu
return o.asReturnedValue();
}
-QV4::ReturnedValue Runtime::setupArgumentsObject(ExecutionContext *ctx)
+QV4::ReturnedValue Runtime::setupArgumentsObject(ExecutionEngine *engine)
{
- Q_ASSERT(ctx->d()->type >= ExecutionContext::Type_CallContext);
- CallContext *c = static_cast<CallContext *>(ctx);
- return (c->engine()->memoryManager->alloc<ArgumentsObject>(c))->asReturnedValue();
+ Q_ASSERT(engine->currentContext()->type >= Heap::ExecutionContext::Type_CallContext);
+ Scope scope(engine);
+ Scoped<CallContext> c(scope, static_cast<Heap::CallContext *>(engine->currentContext()));
+ return (engine->memoryManager->alloc<ArgumentsObject>(c))->asReturnedValue();
}
#endif // V4_BOOTSTRAP
@@ -1216,19 +1274,19 @@ QV4::ReturnedValue Runtime::decrement(const QV4::ValueRef value)
#ifndef V4_BOOTSTRAP
-QV4::ReturnedValue RuntimeHelpers::toString(QV4::ExecutionContext *ctx, const QV4::ValueRef value)
+QV4::ReturnedValue RuntimeHelpers::toString(ExecutionEngine *engine, const QV4::ValueRef value)
{
if (value->isString())
return value.asReturnedValue();
- return RuntimeHelpers::convertToString(ctx, value)->asReturnedValue();
+ return RuntimeHelpers::convertToString(engine, value)->asReturnedValue();
}
-QV4::ReturnedValue RuntimeHelpers::toObject(QV4::ExecutionContext *ctx, const QV4::ValueRef value)
+QV4::ReturnedValue RuntimeHelpers::toObject(ExecutionEngine *engine, const QV4::ValueRef value)
{
if (value->isObject())
return value.asReturnedValue();
- Returned<Object> *o = RuntimeHelpers::convertToObject(ctx, value);
+ Heap::Object *o = RuntimeHelpers::convertToObject(engine, value);
if (!o) // type error
return Encode::undefined();
@@ -1269,99 +1327,108 @@ unsigned Runtime::doubleToUInt(const double &d)
#ifndef V4_BOOTSTRAP
-ReturnedValue Runtime::regexpLiteral(ExecutionContext *ctx, int id)
+ReturnedValue Runtime::regexpLiteral(ExecutionEngine *engine, int id)
{
- return ctx->d()->compilationUnit->runtimeRegularExpressions[id].asReturnedValue();
+ return engine->currentContext()->compilationUnit->runtimeRegularExpressions[id].asReturnedValue();
}
-ReturnedValue Runtime::getQmlIdArray(NoThrowContext *ctx)
+ReturnedValue Runtime::getQmlIdArray(NoThrowEngine *engine)
{
- Q_ASSERT(ctx->engine()->qmlContextObject()->getPointer()->as<QmlContextWrapper>());
- return static_cast<QmlContextWrapper *>(ctx->engine()->qmlContextObject()->getPointer())->idObjectsArray();
+ Q_ASSERT(engine->qmlContextObject());
+ Scope scope(engine);
+ Scoped<QmlContextWrapper> wrapper(scope, engine->qmlContextObject());
+ return wrapper->idObjectsArray();
}
-ReturnedValue Runtime::getQmlContextObject(NoThrowContext *ctx)
+ReturnedValue Runtime::getQmlContextObject(NoThrowEngine *engine)
{
- QQmlContextData *context = QmlContextWrapper::callingContext(ctx->engine());
+ QQmlContextData *context = QmlContextWrapper::callingContext(engine);
if (!context)
return Encode::undefined();
- return QObjectWrapper::wrap(ctx->d()->engine, context->contextObject);
+ return QObjectWrapper::wrap(engine, context->contextObject);
}
-ReturnedValue Runtime::getQmlScopeObject(NoThrowContext *ctx)
+ReturnedValue Runtime::getQmlScopeObject(NoThrowEngine *engine)
{
- Scope scope(ctx);
- QV4::Scoped<QmlContextWrapper> c(scope, ctx->engine()->qmlContextObject(), Scoped<QmlContextWrapper>::Cast);
- return QObjectWrapper::wrap(ctx->d()->engine, c->getScopeObject());
+ Scope scope(engine);
+ QV4::Scoped<QmlContextWrapper> c(scope, engine->qmlContextObject());
+ return QObjectWrapper::wrap(engine, c->getScopeObject());
}
-ReturnedValue Runtime::getQmlQObjectProperty(ExecutionContext *ctx, const ValueRef object, int propertyIndex, bool captureRequired)
+ReturnedValue Runtime::getQmlQObjectProperty(ExecutionEngine *engine, const ValueRef object, int propertyIndex, bool captureRequired)
{
- Scope scope(ctx);
+ Scope scope(engine);
QV4::Scoped<QObjectWrapper> wrapper(scope, object);
if (!wrapper) {
- ctx->throwTypeError(QStringLiteral("Cannot read property of null"));
+ engine->throwTypeError(QStringLiteral("Cannot read property of null"));
return Encode::undefined();
}
+ ScopedContext ctx(scope, engine->currentContext());
return QV4::QObjectWrapper::getProperty(wrapper->object(), ctx, propertyIndex, captureRequired);
}
-QV4::ReturnedValue Runtime::getQmlAttachedProperty(ExecutionContext *ctx, int attachedPropertiesId, int propertyIndex)
+QV4::ReturnedValue Runtime::getQmlAttachedProperty(ExecutionEngine *engine, int attachedPropertiesId, int propertyIndex)
{
- Scope scope(ctx);
- QV4::Scoped<QmlContextWrapper> c(scope, ctx->engine()->qmlContextObject(), Scoped<QmlContextWrapper>::Cast);
+ Scope scope(engine);
+ QV4::Scoped<QmlContextWrapper> c(scope, engine->qmlContextObject());
QObject *scopeObject = c->getScopeObject();
QObject *attachedObject = qmlAttachedPropertiesObjectById(attachedPropertiesId, scopeObject);
- QQmlEngine *qmlEngine = ctx->engine()->v8Engine->engine();
- QQmlData::ensurePropertyCache(qmlEngine, attachedObject);
+ QJSEngine *jsEngine = engine->jsEngine();
+ QQmlData::ensurePropertyCache(jsEngine, attachedObject);
+ ScopedContext ctx(scope, engine->currentContext());
return QV4::QObjectWrapper::getProperty(attachedObject, ctx, propertyIndex, /*captureRequired*/true);
}
-ReturnedValue Runtime::getQmlSingletonQObjectProperty(ExecutionContext *ctx, const ValueRef object, int propertyIndex, bool captureRequired)
+ReturnedValue Runtime::getQmlSingletonQObjectProperty(ExecutionEngine *engine, const ValueRef object, int propertyIndex, bool captureRequired)
{
- Scope scope(ctx);
+ Scope scope(engine);
QV4::Scoped<QmlTypeWrapper> wrapper(scope, object);
if (!wrapper) {
- ctx->throwTypeError(QStringLiteral("Cannot read property of null"));
+ scope.engine->throwTypeError(QStringLiteral("Cannot read property of null"));
return Encode::undefined();
}
+ ScopedContext ctx(scope, engine->currentContext());
return QV4::QObjectWrapper::getProperty(wrapper->singletonObject(), ctx, propertyIndex, captureRequired);
}
-void Runtime::setQmlQObjectProperty(ExecutionContext *ctx, const ValueRef object, int propertyIndex, const ValueRef value)
+void Runtime::setQmlQObjectProperty(ExecutionEngine *engine, const ValueRef object, int propertyIndex, const ValueRef value)
{
- Scope scope(ctx);
+ Scope scope(engine);
QV4::Scoped<QObjectWrapper> wrapper(scope, object);
if (!wrapper) {
- ctx->throwTypeError(QStringLiteral("Cannot write property of null"));
+ engine->throwTypeError(QStringLiteral("Cannot write property of null"));
return;
}
+ ScopedContext ctx(scope, engine->currentContext());
wrapper->setProperty(ctx, propertyIndex, value);
}
-ReturnedValue Runtime::getQmlImportedScripts(NoThrowContext *ctx)
+ReturnedValue Runtime::getQmlImportedScripts(NoThrowEngine *engine)
{
- QQmlContextData *context = QmlContextWrapper::callingContext(ctx->engine());
+ QQmlContextData *context = QmlContextWrapper::callingContext(engine);
if (!context)
return Encode::undefined();
return context->importedScripts.value();
}
-QV4::ReturnedValue Runtime::getQmlSingleton(QV4::NoThrowContext *ctx, String *name)
+QV4::ReturnedValue Runtime::getQmlSingleton(QV4::NoThrowEngine *engine, int nameIndex)
{
- return static_cast<QmlContextWrapper *>(ctx->engine()->qmlContextObject()->getPointer())->qmlSingletonWrapper(ctx->engine()->v8Engine, name);
+ Scope scope(engine);
+ ScopedString name(scope, engine->currentContext()->compilationUnit->runtimeStrings[nameIndex]);
+ Scoped<QmlContextWrapper> wrapper(scope, engine->qmlContextObject());
+ return wrapper->qmlSingletonWrapper(engine, name);
}
-void Runtime::convertThisToObject(ExecutionContext *ctx)
+void Runtime::convertThisToObject(ExecutionEngine *engine)
{
- Value *t = &ctx->d()->callData->thisObject;
+ Value *t = &engine->currentContext()->callData->thisObject;
if (t->isObject())
return;
if (t->isNullOrUndefined()) {
- *t = ctx->engine()->globalObject->asReturnedValue();
+ *t = engine->globalObject()->asReturnedValue();
} else {
- *t = t->toObject(ctx)->asReturnedValue();
+ *t = t->toObject(engine)->asReturnedValue();
}
}
diff --git a/src/qml/jsruntime/qv4runtime_p.h b/src/qml/jsruntime/qv4runtime_p.h
index 6042420291..4d70a66156 100644
--- a/src/qml/jsruntime/qv4runtime_p.h
+++ b/src/qml/jsruntime/qv4runtime_p.h
@@ -35,20 +35,11 @@
#include "qv4global_p.h"
#include "qv4value_inl_p.h"
-#include "qv4math_p.h"
-#include "qv4scopedvalue_p.h"
#include "qv4context_p.h"
+#include "qv4math_p.h"
-#include <QtCore/QString>
#include <QtCore/qnumeric.h>
-#include <QtCore/QDebug>
-#include <QtCore/qurl.h>
-#include <cmath>
-#include <cassert>
-#include <limits>
-
-//#include <wtf/MathExtras.h>
QT_BEGIN_NAMESPACE
@@ -91,67 +82,68 @@ enum TypeHint {
// This is a trick to tell the code generators that functions taking a NoThrowContext won't
// throw exceptions and therefore don't need a check after the call.
-struct NoThrowContext : public ExecutionContext
+struct NoThrowEngine : public ExecutionEngine
{
};
struct Q_QML_PRIVATE_EXPORT Runtime {
// call
- static ReturnedValue callGlobalLookup(ExecutionContext *context, uint index, CallData *callData);
- static ReturnedValue callActivationProperty(ExecutionContext *, String *name, CallData *callData);
- static ReturnedValue callProperty(ExecutionContext *context, String *name, CallData *callData);
- static ReturnedValue callPropertyLookup(ExecutionContext *context, uint index, CallData *callData);
- static ReturnedValue callElement(ExecutionContext *context, const ValueRef index, CallData *callData);
- static ReturnedValue callValue(ExecutionContext *context, const ValueRef func, CallData *callData);
+ static ReturnedValue callGlobalLookup(ExecutionEngine *engine, uint index, CallData *callData);
+ static ReturnedValue callActivationProperty(ExecutionEngine *engine, int nameIndex, CallData *callData);
+ static ReturnedValue callProperty(ExecutionEngine *engine, int nameIndex, CallData *callData);
+ static ReturnedValue callPropertyLookup(ExecutionEngine *engine, uint index, CallData *callData);
+ static ReturnedValue callElement(ExecutionEngine *engine, const ValueRef index, CallData *callData);
+ static ReturnedValue callValue(ExecutionEngine *engine, const ValueRef func, CallData *callData);
// construct
- static ReturnedValue constructGlobalLookup(ExecutionContext *context, uint index, CallData *callData);
- static ReturnedValue constructActivationProperty(ExecutionContext *, String *name, CallData *callData);
- static ReturnedValue constructProperty(ExecutionContext *context, String *name, CallData *callData);
- static ReturnedValue constructPropertyLookup(ExecutionContext *context, uint index, CallData *callData);
- static ReturnedValue constructValue(ExecutionContext *context, const ValueRef func, CallData *callData);
+ static ReturnedValue constructGlobalLookup(ExecutionEngine *engine, uint index, CallData *callData);
+ static ReturnedValue constructActivationProperty(ExecutionEngine *engine, int nameIndex, CallData *callData);
+ static ReturnedValue constructProperty(ExecutionEngine *engine, int nameIndex, CallData *callData);
+ static ReturnedValue constructPropertyLookup(ExecutionEngine *engine, uint index, CallData *callData);
+ static ReturnedValue constructValue(ExecutionEngine *engine, const ValueRef func, CallData *callData);
// set & get
- static void setActivationProperty(ExecutionContext *ctx, String *name, const ValueRef value);
- static void setProperty(ExecutionContext *ctx, const ValueRef object, String *name, const ValueRef value);
- static void setElement(ExecutionContext *ctx, const ValueRef object, const ValueRef index, const ValueRef value);
- static ReturnedValue getProperty(ExecutionContext *ctx, const ValueRef object, String *name);
- static ReturnedValue getActivationProperty(ExecutionContext *ctx, String *name);
- static ReturnedValue getElement(ExecutionContext *ctx, const ValueRef object, const ValueRef index);
+ static void setActivationProperty(ExecutionEngine *engine, int nameIndex, const ValueRef value);
+ static void setProperty(ExecutionEngine *engine, const ValueRef object, int nameIndex, const ValueRef value);
+ static void setElement(ExecutionEngine *engine, const ValueRef object, const ValueRef index, const ValueRef value);
+ static ReturnedValue getProperty(ExecutionEngine *engine, const ValueRef object, int nameIndex);
+ static ReturnedValue getActivationProperty(ExecutionEngine *engine, int nameIndex);
+ static ReturnedValue getElement(ExecutionEngine *engine, const ValueRef object, const ValueRef index);
// typeof
- static ReturnedValue typeofValue(ExecutionContext *ctx, const ValueRef val);
- static ReturnedValue typeofName(ExecutionContext *context, String *name);
- static ReturnedValue typeofMember(ExecutionContext* context, const ValueRef base, String *name);
- static ReturnedValue typeofElement(ExecutionContext* context, const ValueRef base, const ValueRef index);
+ static ReturnedValue typeofValue(ExecutionEngine *engine, const ValueRef val);
+ static ReturnedValue typeofName(ExecutionEngine *engine, int nameIndex);
+ static ReturnedValue typeofMember(ExecutionEngine *engine, const ValueRef base, int nameIndex);
+ static ReturnedValue typeofElement(ExecutionEngine *engine, const ValueRef base, const ValueRef index);
// delete
- static ReturnedValue deleteElement(ExecutionContext *ctx, const ValueRef base, const ValueRef index);
- static ReturnedValue deleteMember(ExecutionContext *ctx, const ValueRef base, String *name);
- static ReturnedValue deleteName(ExecutionContext *ctx, String *name);
+ static ReturnedValue deleteElement(ExecutionEngine *engine, const ValueRef base, const ValueRef index);
+ static ReturnedValue deleteMember(ExecutionEngine *engine, const ValueRef base, int nameIndex);
+ static ReturnedValue deleteMemberString(ExecutionEngine *engine, const ValueRef base, String *name);
+ static ReturnedValue deleteName(ExecutionEngine *engine, int nameIndex);
// exceptions & scopes
- static void throwException(ExecutionContext*, const ValueRef value);
- static ReturnedValue unwindException(ExecutionContext *ctx);
- static ExecutionContext *pushWithScope(const ValueRef o, ExecutionContext *ctx);
- static ExecutionContext *pushCatchScope(ExecutionContext *ctx, String *exceptionVarName);
- static ExecutionContext *popScope(ExecutionContext *ctx);
+ static void throwException(ExecutionEngine *engine, const ValueRef value);
+ static ReturnedValue unwindException(ExecutionEngine *engine);
+ static void pushWithScope(const ValueRef o, ExecutionEngine *engine);
+ static void pushCatchScope(NoThrowEngine *engine, int exceptionVarNameIndex);
+ static void popScope(ExecutionEngine *engine);
// closures
- static ReturnedValue closure(ExecutionContext *ctx, int functionId);
+ static ReturnedValue closure(ExecutionEngine *engine, int functionId);
// function header
- static void declareVar(ExecutionContext *ctx, bool deletable, String *name);
- static ReturnedValue setupArgumentsObject(ExecutionContext *ctx);
- static void convertThisToObject(ExecutionContext *ctx);
+ static void declareVar(ExecutionEngine *engine, bool deletable, int nameIndex);
+ static ReturnedValue setupArgumentsObject(ExecutionEngine *engine);
+ static void convertThisToObject(ExecutionEngine *engine);
// literals
- static ReturnedValue arrayLiteral(ExecutionContext *ctx, Value *values, uint length);
- static ReturnedValue objectLiteral(ExecutionContext *ctx, const Value *args, int classId, int arrayValueCount, int arrayGetterSetterCountAndFlags);
- static ReturnedValue regexpLiteral(ExecutionContext *ctx, int id);
+ static ReturnedValue arrayLiteral(ExecutionEngine *engine, Value *values, uint length);
+ static ReturnedValue objectLiteral(ExecutionEngine *engine, const Value *args, int classId, int arrayValueCount, int arrayGetterSetterCountAndFlags);
+ static ReturnedValue regexpLiteral(ExecutionEngine *engine, int id);
// foreach
- static ReturnedValue foreachIterator(ExecutionContext *ctx, const ValueRef in);
+ static ReturnedValue foreachIterator(ExecutionEngine *engine, const ValueRef in);
static ReturnedValue foreachNextPropertyName(const ValueRef foreach_iterator);
// unary operators
@@ -165,12 +157,12 @@ struct Q_QML_PRIVATE_EXPORT Runtime {
// binary operators
typedef ReturnedValue (*BinaryOperation)(const ValueRef left, const ValueRef right);
- typedef ReturnedValue (*BinaryOperationContext)(ExecutionContext *ctx, const ValueRef left, const ValueRef right);
+ typedef ReturnedValue (*BinaryOperationContext)(ExecutionEngine *engine, const ValueRef left, const ValueRef right);
- static ReturnedValue instanceof(ExecutionContext *ctx, const ValueRef left, const ValueRef right);
- static ReturnedValue in(ExecutionContext *ctx, const ValueRef left, const ValueRef right);
- static ReturnedValue add(ExecutionContext *ctx, const ValueRef left, const ValueRef right);
- static ReturnedValue addString(ExecutionContext *ctx, const ValueRef left, const ValueRef right);
+ static ReturnedValue instanceof(ExecutionEngine *engine, const ValueRef left, const ValueRef right);
+ static ReturnedValue in(ExecutionEngine *engine, const ValueRef left, const ValueRef right);
+ static ReturnedValue add(ExecutionEngine *engine, const ValueRef left, const ValueRef right);
+ static ReturnedValue addString(ExecutionEngine *engine, const ValueRef left, const ValueRef right);
static ReturnedValue bitOr(const ValueRef left, const ValueRef right);
static ReturnedValue bitXor(const ValueRef left, const ValueRef right);
static ReturnedValue bitAnd(const ValueRef left, const ValueRef right);
@@ -201,9 +193,9 @@ struct Q_QML_PRIVATE_EXPORT Runtime {
static Bool compareStrictEqual(const ValueRef left, const ValueRef right);
static Bool compareStrictNotEqual(const ValueRef left, const ValueRef right);
- typedef Bool (*CompareOperationContext)(ExecutionContext *ctx, const ValueRef left, const ValueRef right);
- static Bool compareInstanceof(ExecutionContext *ctx, const ValueRef left, const ValueRef right);
- static Bool compareIn(ExecutionContext *ctx, const ValueRef left, const ValueRef right);
+ typedef Bool (*CompareOperationContext)(ExecutionEngine *engine, const ValueRef left, const ValueRef right);
+ static Bool compareInstanceof(ExecutionEngine *engine, const ValueRef left, const ValueRef right);
+ static Bool compareIn(ExecutionEngine *engine, const ValueRef left, const ValueRef right);
// conversions
static Bool toBoolean(const ValueRef value);
@@ -214,15 +206,15 @@ struct Q_QML_PRIVATE_EXPORT Runtime {
static unsigned doubleToUInt(const double &d);
// qml
- static ReturnedValue getQmlIdArray(NoThrowContext *ctx);
- static ReturnedValue getQmlImportedScripts(NoThrowContext *ctx);
- static ReturnedValue getQmlContextObject(NoThrowContext *ctx);
- static ReturnedValue getQmlScopeObject(NoThrowContext *ctx);
- static ReturnedValue getQmlSingleton(NoThrowContext *ctx, String *name);
- static ReturnedValue getQmlAttachedProperty(ExecutionContext *ctx, int attachedPropertiesId, int propertyIndex);
- static ReturnedValue getQmlQObjectProperty(ExecutionContext *ctx, const ValueRef object, int propertyIndex, bool captureRequired);
- static ReturnedValue getQmlSingletonQObjectProperty(ExecutionContext *ctx, const ValueRef object, int propertyIndex, bool captureRequired);
- static void setQmlQObjectProperty(ExecutionContext *ctx, const ValueRef object, int propertyIndex, const ValueRef value);
+ static ReturnedValue getQmlIdArray(NoThrowEngine *ctx);
+ static ReturnedValue getQmlImportedScripts(NoThrowEngine *ctx);
+ static ReturnedValue getQmlContextObject(NoThrowEngine *ctx);
+ static ReturnedValue getQmlScopeObject(NoThrowEngine *ctx);
+ static ReturnedValue getQmlSingleton(NoThrowEngine *ctx, int nameIndex);
+ static ReturnedValue getQmlAttachedProperty(ExecutionEngine *engine, int attachedPropertiesId, int propertyIndex);
+ static ReturnedValue getQmlQObjectProperty(ExecutionEngine *engine, const ValueRef object, int propertyIndex, bool captureRequired);
+ static ReturnedValue getQmlSingletonQObjectProperty(ExecutionEngine *engine, const ValueRef object, int propertyIndex, bool captureRequired);
+ static void setQmlQObjectProperty(ExecutionEngine *engine, const ValueRef object, int propertyIndex, const ValueRef value);
};
struct Q_QML_PRIVATE_EXPORT RuntimeHelpers {
@@ -230,20 +222,20 @@ struct Q_QML_PRIVATE_EXPORT RuntimeHelpers {
static ReturnedValue toPrimitive(const ValueRef value, int typeHint);
static double stringToNumber(const QString &s);
- static Returned<String> *stringFromNumber(ExecutionContext *ctx, double number);
+ static Heap::String *stringFromNumber(ExecutionEngine *engine, double number);
static double toNumber(const ValueRef value);
static void numberToString(QString *result, double num, int radix = 10);
- static ReturnedValue toString(ExecutionContext *ctx, const ValueRef value);
- static Returned<String> *convertToString(ExecutionContext *ctx, const ValueRef value);
+ static ReturnedValue toString(ExecutionEngine *engine, const ValueRef value);
+ static Heap::String *convertToString(ExecutionEngine *engine, const ValueRef value);
- static ReturnedValue toObject(ExecutionContext *ctx, const ValueRef value);
- static Returned<Object> *convertToObject(ExecutionContext *ctx, const ValueRef value);
+ static ReturnedValue toObject(ExecutionEngine *engine, const ValueRef value);
+ static Heap::Object *convertToObject(ExecutionEngine *engine, const ValueRef value);
static Bool equalHelper(const ValueRef x, const ValueRef y);
static Bool strictEqual(const ValueRef x, const ValueRef y);
- static ReturnedValue addHelper(ExecutionContext *ctx, const ValueRef left, const ValueRef right);
+ static ReturnedValue addHelper(ExecutionEngine *engine, const ValueRef left, const ValueRef right);
};
@@ -334,7 +326,7 @@ inline ReturnedValue Runtime::bitAnd(const ValueRef left, const ValueRef right)
}
#ifndef V4_BOOTSTRAP
-inline ReturnedValue Runtime::add(ExecutionContext *ctx, const ValueRef left, const ValueRef right)
+inline ReturnedValue Runtime::add(ExecutionEngine *engine, const ValueRef left, const ValueRef right)
{
TRACE2(left, right);
@@ -343,7 +335,7 @@ inline ReturnedValue Runtime::add(ExecutionContext *ctx, const ValueRef left, co
if (left->isNumber() && right->isNumber())
return Primitive::fromDouble(left->asDouble() + right->asDouble()).asReturnedValue();
- return RuntimeHelpers::addHelper(ctx, left, right);
+ return RuntimeHelpers::addHelper(engine, left, right);
}
#endif // V4_BOOTSTRAP
@@ -470,7 +462,7 @@ inline Bool Runtime::compareEqual(const ValueRef left, const ValueRef right)
if (!left->isManaged())
return false;
if (left->isString() == right->isString())
- return left->managed()->isEqualTo(right->managed());
+ return left->cast<Managed>()->isEqualTo(right->cast<Managed>());
}
return RuntimeHelpers::equalHelper(left, right);
@@ -529,27 +521,6 @@ inline Bool Runtime::compareStrictNotEqual(const ValueRef left, const ValueRef r
return ! RuntimeHelpers::strictEqual(left, right);
}
-#ifndef V4_BOOTSTRAP
-inline Bool Runtime::compareInstanceof(ExecutionContext *ctx, const ValueRef left, const ValueRef right)
-{
- TRACE2(left, right);
-
- Scope scope(ctx);
- ScopedValue v(scope, Runtime::instanceof(ctx, left, right));
- return v->booleanValue();
-}
-
-inline uint Runtime::compareIn(ExecutionContext *ctx, const ValueRef left, const ValueRef right)
-{
- TRACE2(left, right);
-
- Scope scope(ctx);
- ScopedValue v(scope, Runtime::in(ctx, left, right));
- return v->booleanValue();
-}
-
-#endif // V4_BOOTSTRAP
-
inline Bool Runtime::toBoolean(const ValueRef value)
{
return value->toBoolean();
diff --git a/src/qml/jsruntime/qv4scopedvalue_p.h b/src/qml/jsruntime/qv4scopedvalue_p.h
index b1b4d5da8d..e12b91340d 100644
--- a/src/qml/jsruntime/qv4scopedvalue_p.h
+++ b/src/qml/jsruntime/qv4scopedvalue_p.h
@@ -36,6 +36,11 @@
#include "qv4engine_p.h"
#include "qv4value_p.h"
#include "qv4persistent_p.h"
+#include "qv4property_p.h"
+
+#ifdef V4_USE_VALGRIND
+#include <valgrind/memcheck.h>
+#endif
QT_BEGIN_NAMESPACE
@@ -47,7 +52,15 @@ namespace QV4 {
struct ScopedValue;
struct Scope {
- inline explicit Scope(ExecutionContext *ctx);
+ inline Scope(ExecutionContext *ctx)
+ : engine(ctx->d()->engine)
+#ifndef QT_NO_DEBUG
+ , size(0)
+#endif
+ {
+ mark = engine->jsStackTop;
+ }
+
explicit Scope(ExecutionEngine *e)
: engine(e)
#ifndef QT_NO_DEBUG
@@ -62,15 +75,19 @@ struct Scope {
Q_ASSERT(engine->jsStackTop >= mark);
memset(mark, 0, (engine->jsStackTop - mark)*sizeof(Value));
#endif
+#ifdef V4_USE_VALGRIND
+ VALGRIND_MAKE_MEM_UNDEFINED(mark, engine->jsStackLimit - mark);
+#endif
engine->jsStackTop = mark;
}
Value *alloc(int nValues) {
- Value *ptr = engine->jsStackTop;
- engine->jsStackTop += nValues;
#ifndef QT_NO_DEBUG
size += nValues;
#endif
+ Value *ptr = engine->jsStackTop;
+ engine->jsStackTop = ptr + nValues;
+ memset(ptr, 0, nValues*sizeof(Value));
return ptr;
}
@@ -95,6 +112,7 @@ struct ScopedValue
ScopedValue(const Scope &scope)
{
ptr = scope.engine->jsStackTop++;
+ ptr->val = 0;
#ifndef QT_NO_DEBUG
++scope.size;
#endif
@@ -109,10 +127,10 @@ struct ScopedValue
#endif
}
- ScopedValue(const Scope &scope, HeapObject *o)
+ ScopedValue(const Scope &scope, Heap::Base *o)
{
ptr = scope.engine->jsStackTop++;
- ptr->m = reinterpret_cast<Managed *>(o);
+ ptr->m = o;
#if QT_POINTER_SIZE == 4
ptr->tag = QV4::Value::Managed_Type;
#endif
@@ -139,23 +157,13 @@ struct ScopedValue
#endif
}
- template<typename T>
- ScopedValue(const Scope &scope, Returned<T> *t)
- {
- ptr = scope.engine->jsStackTop++;
- *ptr = t->getPointer() ? Value::fromManaged(t->getPointer()) : Primitive::undefinedValue();
-#ifndef QT_NO_DEBUG
- ++scope.size;
-#endif
- }
-
ScopedValue &operator=(const Value &v) {
*ptr = v;
return *this;
}
- ScopedValue &operator=(HeapObject *o) {
- ptr->m = reinterpret_cast<Managed *>(o);
+ ScopedValue &operator=(Heap::Base *o) {
+ ptr->m = o;
#if QT_POINTER_SIZE == 4
ptr->tag = QV4::Value::Managed_Type;
#endif
@@ -172,12 +180,6 @@ struct ScopedValue
return *this;
}
- template<typename T>
- ScopedValue &operator=(Returned<T> *t) {
- *ptr = t->getPointer() ? Value::fromManaged(t->getPointer()) : Primitive::undefinedValue();
- return *this;
- }
-
ScopedValue &operator=(const ScopedValue &other) {
*ptr = *other.ptr;
return *this;
@@ -204,15 +206,19 @@ struct Scoped
inline void setPointer(Managed *p) {
#if QT_POINTER_SIZE == 8
- ptr->val = (quint64)p;
+ ptr->m = p ? p->m : 0;
#else
- *ptr = p ? QV4::Value::fromManaged(p) : QV4::Primitive::undefinedValue();
+ *ptr = QV4::Value::fromManaged(p);
#endif
}
Scoped(const Scope &scope)
{
ptr = scope.engine->jsStackTop++;
+ ptr->m = 0;
+#if QT_POINTER_SIZE == 4
+ ptr->tag = QV4::Value::Managed_Type;
+#endif
#ifndef QT_NO_DEBUG
++scope.size;
#endif
@@ -227,10 +233,10 @@ struct Scoped
++scope.size;
#endif
}
- Scoped(const Scope &scope, HeapObject *o)
+ Scoped(const Scope &scope, Heap::Base *o)
{
Value v;
- v.m = reinterpret_cast<Managed *>(o);
+ v.m = o;
#if QT_POINTER_SIZE == 4
v.tag = QV4::Value::Managed_Type;
#endif
@@ -268,31 +274,19 @@ struct Scoped
++scope.size;
#endif
}
- template<typename X>
- Scoped(const Scope &scope, X *t, _Cast)
+ Scoped(const Scope &scope, typename T::Data *t)
{
ptr = scope.engine->jsStackTop++;
- setPointer(managed_cast<T>(t));
+ *ptr = t;
#ifndef QT_NO_DEBUG
++scope.size;
#endif
}
-
template<typename X>
- Scoped(const Scope &scope, Returned<X> *x)
- {
- ptr = scope.engine->jsStackTop++;
- setPointer(Returned<T>::getPointer(x));
-#ifndef QT_NO_DEBUG
- ++scope.size;
-#endif
- }
-
- template<typename X>
- Scoped(const Scope &scope, Returned<X> *x, _Cast)
+ Scoped(const Scope &scope, X *t, _Cast)
{
ptr = scope.engine->jsStackTop++;
- setPointer(managed_cast<T>(x->getPointer()));
+ setPointer(managed_cast<T>(t));
#ifndef QT_NO_DEBUG
++scope.size;
#endif
@@ -315,15 +309,19 @@ struct Scoped
#endif
}
- Scoped<T> &operator=(HeapObject *o) {
+ Scoped<T> &operator=(Heap::Base *o) {
Value v;
- v.m = reinterpret_cast<Managed *>(o);
+ v.m = o;
#if QT_POINTER_SIZE == 4
v.tag = QV4::Value::Managed_Type;
#endif
setPointer(value_cast<T>(v));
return *this;
}
+ Scoped<T> &operator=(typename T::Data *t) {
+ *ptr = t;
+ return *this;
+ }
Scoped<T> &operator=(const Value &v) {
setPointer(value_cast<T>(v));
return *this;
@@ -346,30 +344,27 @@ struct Scoped
return *this;
}
- template<typename X>
- Scoped<T> &operator=(Returned<X> *x) {
- setPointer(Returned<T>::getPointer(x));
- return *this;
- }
-
operator T *() {
return static_cast<T *>(ptr->managed());
}
T *operator->() {
- return static_cast<T *>(ptr->managed());
+ return ptr->cast<T>();
}
bool operator!() const {
- return !ptr->managed();
+ return !ptr->m;
}
operator void *() const {
- return ptr->managed();
+ return ptr->m;
}
T *getPointer() {
return static_cast<T *>(ptr->managed());
}
+ typename T::Data **getRef() {
+ return reinterpret_cast<typename T::Data **>(&ptr->m);
+ }
ReturnedValue asReturnedValue() const {
#if QT_POINTER_SIZE == 8
@@ -382,36 +377,13 @@ struct Scoped
Value *ptr;
};
-struct CallData
-{
- // below is to be compatible with Value. Initialize tag to 0
-#if Q_BYTE_ORDER != Q_LITTLE_ENDIAN
- uint tag;
-#endif
- int argc;
-#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
- uint tag;
-#endif
- inline ReturnedValue argument(int i) {
- return i < argc ? args[i].asReturnedValue() : Primitive::undefinedValue().asReturnedValue();
- }
-
- Value thisObject;
- Value args[1];
-};
-
struct ScopedCallData {
- ScopedCallData(Scope &scope, int argc)
+ ScopedCallData(Scope &scope, int argc = 0)
{
int size = qMax(argc, (int)QV4::Global::ReservedArgumentCount) + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value);
- ptr = reinterpret_cast<CallData *>(scope.engine->stackPush(size));
+ ptr = reinterpret_cast<CallData *>(scope.alloc(size));
ptr->tag = QV4::Value::Integer_Type;
ptr->argc = argc;
-#ifndef QT_NO_DEBUG
- scope.size += size;
- for (int ii = 0; ii < qMax(argc, (int)QV4::Global::ReservedArgumentCount); ++ii)
- ptr->args[ii] = QV4::Primitive::undefinedValue();
-#endif
}
CallData *operator->() {
@@ -443,13 +415,6 @@ inline Scoped<T> &Scoped<T>::operator=(const ValueRef &v)
return *this;
}
-template <typename T>
-inline Value &Value::operator=(Returned<T> *t)
-{
- val = t->getPointer()->asReturnedValue();
- return *this;
-}
-
inline Value &Value::operator =(const ScopedValue &v)
{
val = v.ptr->val;
@@ -470,15 +435,9 @@ inline Value &Value::operator=(const ValueRef v)
}
template<typename T>
-inline Returned<T> *Value::as()
-{
- return Returned<T>::create(value_cast<T>(*this));
-}
-
-template<typename T>
inline TypedValue<T> &TypedValue<T>::operator =(T *t)
{
- m = t;
+ m = t ? t->m : 0;
#if QT_POINTER_SIZE == 4
tag = Managed_Type;
#endif
@@ -488,20 +447,13 @@ inline TypedValue<T> &TypedValue<T>::operator =(T *t)
template<typename T>
inline TypedValue<T> &TypedValue<T>::operator =(const Scoped<T> &v)
{
- m = v.ptr->managed();
+ m = v.ptr->m;
#if QT_POINTER_SIZE == 4
tag = Managed_Type;
#endif
return *this;
}
-template<typename T>
-inline TypedValue<T> &TypedValue<T>::operator=(Returned<T> *t)
-{
- val = t->getPointer()->asReturnedValue();
- return *this;
-}
-
//template<typename T>
//inline TypedValue<T> &TypedValue<T>::operator =(const ManagedRef<T> &v)
//{
@@ -516,47 +468,6 @@ inline TypedValue<T> &TypedValue<T>::operator=(const TypedValue<T> &t)
return *this;
}
-template<typename T>
-inline Returned<T> * TypedValue<T>::ret() const
-{
- return Returned<T>::create(static_cast<T *>(managed()));
-}
-
-inline Primitive::operator ValueRef()
-{
- return ValueRef(this);
-}
-
-
-template<typename T>
-PersistentValue::PersistentValue(Returned<T> *obj)
- : d(new PersistentValuePrivate(QV4::Value::fromManaged(obj->getPointer())))
-{
-}
-
-template<typename T>
-inline PersistentValue &PersistentValue::operator=(Returned<T> *obj)
-{
- return operator=(QV4::Value::fromManaged(obj->getPointer()).asReturnedValue());
-}
-
-inline PersistentValue &PersistentValue::operator=(const ScopedValue &other)
-{
- return operator=(other.asReturnedValue());
-}
-
-template<typename T>
-inline WeakValue::WeakValue(Returned<T> *obj)
- : d(new PersistentValuePrivate(QV4::Value::fromManaged(obj->getPointer()), /*engine*/0, /*weak*/true))
-{
-}
-
-template<typename T>
-inline WeakValue &WeakValue::operator=(Returned<T> *obj)
-{
- return operator=(QV4::Value::fromManaged(obj->getPointer()).asReturnedValue());
-}
-
inline ValueRef::ValueRef(const ScopedValue &v)
: ptr(v.ptr)
{}
@@ -585,14 +496,47 @@ struct ScopedProperty
ScopedProperty(Scope &scope)
{
property = reinterpret_cast<Property*>(scope.alloc(sizeof(Property) / sizeof(Value)));
+ property->value = Encode::undefined();
+ property->set = Encode::undefined();
}
Property *operator->() { return property; }
- operator const Property &() { return *property; }
+ operator const Property *() const { return property; }
+ operator Property *() { return property; }
Property *property;
};
+struct ExecutionContextSaver
+{
+ ExecutionEngine *engine;
+ Value *savedContext;
+
+ ExecutionContextSaver(Scope &scope, ExecutionContext *context)
+ : engine(context->d()->engine)
+ , savedContext(scope.alloc(1))
+ {
+ savedContext->m = context->d();
+#if QT_POINTER_SIZE == 4
+ savedContext->tag = QV4::Value::Managed_Type;
+#endif
+ }
+ ExecutionContextSaver(Scope &scope, Heap::ExecutionContext *context)
+ : engine(context->engine)
+ , savedContext(scope.alloc(1))
+ {
+ savedContext->m = context;
+#if QT_POINTER_SIZE == 4
+ savedContext->tag = QV4::Value::Managed_Type;
+#endif
+ }
+ ~ExecutionContextSaver()
+ {
+ engine->current = static_cast<Heap::ExecutionContext *>(savedContext->heapObject());
+ }
+};
+
+
}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp
index fa4b4b1894..e8471ca019 100644
--- a/src/qml/jsruntime/qv4script.cpp
+++ b/src/qml/jsruntime/qv4script.cpp
@@ -51,44 +51,78 @@
#include <QtCore/QDebug>
#include <QtCore/QString>
+QT_BEGIN_NAMESPACE
+
+namespace QV4 {
+namespace Heap {
+
+struct CompilationUnitHolder : Object {
+ inline CompilationUnitHolder(ExecutionEngine *engine, CompiledData::CompilationUnit *unit);
+
+ QQmlRefPointer<CompiledData::CompilationUnit> unit;
+};
+
+}
+
+struct CompilationUnitHolder : public Object
+{
+ V4_OBJECT2(CompilationUnitHolder, Object)
+ V4_NEEDS_DESTROY
+};
+
+inline
+Heap::CompilationUnitHolder::CompilationUnitHolder(ExecutionEngine *engine, CompiledData::CompilationUnit *unit)
+ : Heap::Object(engine)
+ , unit(unit)
+{
+ setVTable(QV4::CompilationUnitHolder::staticVTable());
+}
+
+}
+
+QT_END_NAMESPACE
+
using namespace QV4;
-QmlBindingWrapper::Data::Data(ExecutionContext *scope, Function *f, Object *qml)
- : FunctionObject::Data(scope, scope->d()->engine->id_eval, /*createProto = */ false)
- , qml(qml)
+DEFINE_OBJECT_VTABLE(QmlBindingWrapper);
+DEFINE_OBJECT_VTABLE(CompilationUnitHolder);
+
+Heap::QmlBindingWrapper::QmlBindingWrapper(QV4::ExecutionContext *scope, Function *f, QV4::Object *qml)
+ : Heap::FunctionObject(scope, scope->d()->engine->id_eval, /*createProto = */ false)
+ , qml(qml->d())
{
Q_ASSERT(scope->inUse());
- setVTable(staticVTable());
+ setVTable(QV4::QmlBindingWrapper::staticVTable());
function = f;
if (function)
function->compilationUnit->addref();
- needsActivation = function ? function->needsActivation() : false;
Scope s(scope);
- Scoped<QmlBindingWrapper> o(s, this);
+ Scoped<QV4::QmlBindingWrapper> o(s, this);
o->defineReadonlyProperty(scope->d()->engine->id_length, Primitive::fromInt32(1));
- o->d()->qmlContext = reinterpret_cast<CallContext *>(s.engine->currentContext()->newQmlContext(o, qml));
+ ScopedContext ctx(s, s.engine->currentContext());
+ o->d()->qmlContext = ctx->newQmlContext(o, qml);
s.engine->popContext();
}
-QmlBindingWrapper::Data::Data(ExecutionContext *scope, Object *qml)
- : FunctionObject::Data(scope, scope->d()->engine->id_eval, /*createProto = */ false)
- , qml(qml)
+Heap::QmlBindingWrapper::QmlBindingWrapper(QV4::ExecutionContext *scope, QV4::Object *qml)
+ : Heap::FunctionObject(scope, scope->d()->engine->id_eval, /*createProto = */ false)
+ , qml(qml->d())
{
Q_ASSERT(scope->inUse());
- setVTable(staticVTable());
- needsActivation = false;
+ setVTable(QV4::QmlBindingWrapper::staticVTable());
Scope s(scope);
- Scoped<QmlBindingWrapper> o(s, this);
+ Scoped<QV4::QmlBindingWrapper> o(s, this);
o->defineReadonlyProperty(scope->d()->engine->id_length, Primitive::fromInt32(1));
- o->d()->qmlContext = reinterpret_cast<CallContext *>(s.engine->currentContext()->newQmlContext(o, qml));
+ ScopedContext ctx(s, s.engine->currentContext());
+ o->d()->qmlContext = ctx->newQmlContext(o, qml);
s.engine->popContext();
}
@@ -102,97 +136,73 @@ ReturnedValue QmlBindingWrapper::call(Managed *that, CallData *)
if (!This->function())
return QV4::Encode::undefined();
- CallContext *ctx = This->d()->qmlContext;
+ Scoped<CallContext> ctx(scope, This->d()->qmlContext);
std::fill(ctx->d()->locals, ctx->d()->locals + ctx->d()->function->varCount(), Primitive::undefinedValue());
engine->pushContext(ctx);
- ScopedValue result(scope, This->function()->code(ctx, This->function()->codeData));
+ ScopedValue result(scope, This->function()->code(engine, This->function()->codeData));
engine->popContext();
return result.asReturnedValue();
}
-void QmlBindingWrapper::markObjects(Managed *m, ExecutionEngine *e)
+void QmlBindingWrapper::markObjects(Heap::Base *m, ExecutionEngine *e)
{
- QmlBindingWrapper *wrapper = static_cast<QmlBindingWrapper*>(m);
- if (wrapper->d()->qml)
- wrapper->d()->qml->mark(e);
+ QmlBindingWrapper::Data *wrapper = static_cast<QmlBindingWrapper::Data *>(m);
+ if (wrapper->qml)
+ wrapper->qml->mark(e);
FunctionObject::markObjects(m, e);
- if (wrapper->d()->qmlContext)
- wrapper->d()->qmlContext->mark(e);
+ if (wrapper->qmlContext)
+ wrapper->qmlContext->mark(e);
}
static ReturnedValue signalParameterGetter(QV4::CallContext *ctx, uint parameterIndex)
{
- QV4::CallContext *signalEmittingContext = ctx->d()->parent->asCallContext();
- Q_ASSERT(signalEmittingContext);
+ QV4::Scope scope(ctx);
+ QV4::Scoped<CallContext> signalEmittingContext(scope, static_cast<Heap::CallContext *>(ctx->d()->parent));
+ Q_ASSERT(signalEmittingContext && signalEmittingContext->d()->type >= QV4::Heap::ExecutionContext::Type_SimpleCallContext);
return signalEmittingContext->argument(parameterIndex);
}
-Returned<FunctionObject> *QmlBindingWrapper::createQmlCallableForFunction(QQmlContextData *qmlContext, QObject *scopeObject, Function *runtimeFunction, const QList<QByteArray> &signalParameters, QString *error)
+Heap::FunctionObject *QmlBindingWrapper::createQmlCallableForFunction(QQmlContextData *qmlContext, QObject *scopeObject, Function *runtimeFunction, const QList<QByteArray> &signalParameters, QString *error)
{
ExecutionEngine *engine = QQmlEnginePrivate::getV4Engine(qmlContext->engine);
QV4::Scope valueScope(engine);
- QV4::ScopedObject qmlScopeObject(valueScope, QV4::QmlContextWrapper::qmlScope(engine->v8Engine, qmlContext, scopeObject));
- QV4::Scoped<QV4::QmlBindingWrapper> wrapper(valueScope, engine->memoryManager->alloc<QV4::QmlBindingWrapper>(engine->rootContext, qmlScopeObject));
+ QV4::ScopedObject qmlScopeObject(valueScope, QV4::QmlContextWrapper::qmlScope(engine, qmlContext, scopeObject));
+ ScopedContext global(valueScope, valueScope.engine->rootContext());
+ QV4::Scoped<QV4::QmlBindingWrapper> wrapper(valueScope, engine->memoryManager->alloc<QV4::QmlBindingWrapper>(global, qmlScopeObject));
+ QV4::Scoped<CallContext> wrapperContext(valueScope, wrapper->context());
if (!signalParameters.isEmpty()) {
if (error)
- QQmlPropertyCache::signalParameterStringForJS(qmlContext->engine, signalParameters, error);
+ QQmlPropertyCache::signalParameterStringForJS(engine, signalParameters, error);
QV4::ScopedProperty p(valueScope);
QV4::ScopedString s(valueScope);
int index = 0;
foreach (const QByteArray &param, signalParameters) {
- QV4::ScopedFunctionObject g(valueScope, engine->memoryManager->alloc<QV4::IndexedBuiltinFunction>(wrapper->context(), index++, signalParameterGetter));
+ QV4::ScopedFunctionObject g(valueScope, engine->memoryManager->alloc<QV4::IndexedBuiltinFunction>(wrapperContext, index++, signalParameterGetter));
p->setGetter(g);
p->setSetter(0);
s = engine->newString(QString::fromUtf8(param));
- qmlScopeObject->insertMember(s.getPointer(), p, QV4::Attr_Accessor|QV4::Attr_NotEnumerable|QV4::Attr_NotConfigurable);
+ qmlScopeObject->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotEnumerable|QV4::Attr_NotConfigurable);
}
}
- QV4::ScopedFunctionObject function(valueScope, QV4::FunctionObject::createScriptFunction(wrapper->context(), runtimeFunction));
- return function->asReturned<FunctionObject>();
+ QV4::ScopedFunctionObject function(valueScope, QV4::FunctionObject::createScriptFunction(wrapperContext, runtimeFunction));
+ return function->d();
}
-DEFINE_OBJECT_VTABLE(QmlBindingWrapper);
-
-struct CompilationUnitHolder : public Object
-{
- struct Data : Object::Data {
- Data(ExecutionEngine *engine, CompiledData::CompilationUnit *unit)
- : Object::Data(engine)
- , unit(unit)
- {
- setVTable(staticVTable());
- }
- QQmlRefPointer<QV4::CompiledData::CompilationUnit> unit;
- };
- V4_OBJECT(Object)
-
-
- static void destroy(Managed *that)
- {
- static_cast<CompilationUnitHolder*>(that)->d()->~Data();
- }
-
-};
-
-DEFINE_OBJECT_VTABLE(CompilationUnitHolder);
-
Script::Script(ExecutionEngine *v4, Object *qml, CompiledData::CompilationUnit *compilationUnit)
- : line(0), column(0), scope(v4->rootContext), strictMode(false), inheritContext(true), parsed(false)
- , qml(qml->asReturnedValue()), vmFunction(0), parseAsBinding(true)
+ : line(0), column(0), scope(v4->rootContext()), strictMode(false), inheritContext(true), parsed(false)
+ , qml(v4, qml->asReturnedValue()), vmFunction(0), parseAsBinding(true)
{
parsed = true;
- if (compilationUnit) {
- vmFunction = compilationUnit->linkToEngine(v4);
- Q_ASSERT(vmFunction);
+ vmFunction = compilationUnit ? compilationUnit->linkToEngine(v4) : 0;
+ if (vmFunction) {
Scope valueScope(v4);
ScopedObject holder(valueScope, v4->memoryManager->alloc<CompilationUnitHolder>(v4, compilationUnit));
- compilationUnitHolder = holder.asReturnedValue();
- } else
- vmFunction = 0;
+ compilationUnitHolder.set(v4, holder);
+ }
}
Script::~Script()
@@ -208,7 +218,7 @@ void Script::parse()
parsed = true;
- ExecutionEngine *v4 = scope->d()->engine;
+ ExecutionEngine *v4 = scope->engine;
Scope valueScope(v4);
MemoryManager::GCBlocker gcBlocker(v4->memoryManager);
@@ -224,7 +234,7 @@ void Script::parse()
foreach (const QQmlJS::DiagnosticMessage &m, parser.diagnosticMessages()) {
if (m.isError()) {
- scope->throwSyntaxError(m.message, sourceFile, m.loc.startLine, m.loc.startColumn);
+ valueScope.engine->throwSyntaxError(m.message, sourceFile, m.loc.startLine, m.loc.startColumn);
return;
} else {
qWarning() << sourceFile << ':' << m.loc.startLine << ':' << m.loc.startColumn
@@ -243,14 +253,14 @@ void Script::parse()
QStringList inheritedLocals;
if (inheritContext) {
- CallContext *ctx = scope->asCallContext();
+ Scoped<CallContext> ctx(valueScope, scope);
if (ctx) {
- for (String * const *i = ctx->variables(), * const *ei = i + ctx->variableCount(); i < ei; ++i)
- inheritedLocals.append(*i ? (*i)->toQString() : QString());
+ for (Identifier * const *i = ctx->variables(), * const *ei = i + ctx->variableCount(); i < ei; ++i)
+ inheritedLocals.append(*i ? (*i)->string : QString());
}
}
- RuntimeCodegen cg(scope, strictMode);
+ RuntimeCodegen cg(v4, strictMode);
cg.generateFromProgram(sourceFile, sourceCode, program, &module, QQmlJS::Codegen::EvalCode, inheritedLocals);
if (v4->hasException)
return;
@@ -262,13 +272,13 @@ void Script::parse()
QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit = isel->compile();
vmFunction = compilationUnit->linkToEngine(v4);
ScopedObject holder(valueScope, v4->memoryManager->alloc<CompilationUnitHolder>(v4, compilationUnit));
- compilationUnitHolder = holder.asReturnedValue();
+ compilationUnitHolder.set(v4, holder);
}
if (!vmFunction) {
// ### FIX file/line number
- Scoped<Object> error(valueScope, v4->newSyntaxErrorObject(QStringLiteral("Syntax error")));
- v4->currentContext()->throwError(error);
+ ScopedObject error(valueScope, v4->newSyntaxErrorObject(QStringLiteral("Syntax error")));
+ v4->throwError(error);
}
}
@@ -279,23 +289,24 @@ ReturnedValue Script::run()
if (!vmFunction)
return Encode::undefined();
- QV4::ExecutionEngine *engine = scope->d()->engine;
+ QV4::ExecutionEngine *engine = scope->engine;
QV4::Scope valueScope(engine);
if (qml.isUndefined()) {
TemporaryAssignment<Function*> savedGlobalCode(engine->globalCode, vmFunction);
- ExecutionContextSaver ctxSaver(scope);
- ContextStateSaver stateSaver(scope);
- scope->d()->strictMode = vmFunction->isStrict();
- scope->d()->lookups = vmFunction->compilationUnit->runtimeLookups;
- scope->d()->compilationUnit = vmFunction->compilationUnit;
+ ExecutionContextSaver ctxSaver(valueScope, scope);
+ ContextStateSaver stateSaver(valueScope, scope);
+ scope->strictMode = vmFunction->isStrict();
+ scope->lookups = vmFunction->compilationUnit->runtimeLookups;
+ scope->compilationUnit = vmFunction->compilationUnit;
- return vmFunction->code(scope, vmFunction->codeData);
+ return vmFunction->code(engine, vmFunction->codeData);
} else {
ScopedObject qmlObj(valueScope, qml.value());
- ScopedFunctionObject f(valueScope, engine->memoryManager->alloc<QmlBindingWrapper>(scope, vmFunction, qmlObj));
- ScopedCallData callData(valueScope, 0);
+ ScopedContext ctx(valueScope, scope);
+ ScopedFunctionObject f(valueScope, engine->memoryManager->alloc<QmlBindingWrapper>(ctx, vmFunction, qmlObj));
+ ScopedCallData callData(valueScope);
callData->thisObject = Primitive::undefinedValue();
return f->call(callData);
}
@@ -308,12 +319,14 @@ Function *Script::function()
return vmFunction;
}
-QQmlRefPointer<QV4::CompiledData::CompilationUnit> Script::precompile(IR::Module *module, Compiler::JSUnitGenerator *unitGenerator, ExecutionEngine *engine, const QUrl &url, const QString &source, QList<QQmlError> *reportedErrors)
+QQmlRefPointer<QV4::CompiledData::CompilationUnit> Script::precompile(IR::Module *module, Compiler::JSUnitGenerator *unitGenerator, ExecutionEngine *engine, const QUrl &url, const QString &source, QList<QQmlError> *reportedErrors, QQmlJS::Directives *directivesCollector)
{
using namespace QQmlJS;
using namespace QQmlJS::AST;
QQmlJS::Engine ee;
+ if (directivesCollector)
+ ee.setDirectives(directivesCollector);
QQmlJS::Lexer lexer(&ee);
lexer.setCode(source, /*line*/1, /*qml mode*/false);
QQmlJS::Parser parser(&ee);
@@ -367,10 +380,11 @@ ReturnedValue Script::qmlBinding()
{
if (!parsed)
parse();
- ExecutionEngine *v4 = scope->d()->engine;
+ ExecutionEngine *v4 = scope->engine;
Scope valueScope(v4);
ScopedObject qmlObj(valueScope, qml.value());
- ScopedObject v(valueScope, v4->memoryManager->alloc<QmlBindingWrapper>(scope, vmFunction, qmlObj));
+ ScopedContext ctx(valueScope, scope);
+ ScopedObject v(valueScope, v4->memoryManager->alloc<QmlBindingWrapper>(ctx, vmFunction, qmlObj));
return v.asReturnedValue();
}
@@ -379,13 +393,12 @@ QV4::ReturnedValue Script::evaluate(ExecutionEngine *engine, const QString &scr
QV4::Scope scope(engine);
QV4::Script qmlScript(engine, scopeObject, script, QString());
- QV4::ExecutionContext *ctx = engine->currentContext();
qmlScript.parse();
QV4::ScopedValue result(scope);
if (!scope.engine->hasException)
result = qmlScript.run();
if (scope.engine->hasException) {
- ctx->catchException();
+ scope.engine->catchException();
return Encode::undefined();
}
return result.asReturnedValue();
diff --git a/src/qml/jsruntime/qv4script_p.h b/src/qml/jsruntime/qv4script_p.h
index ed93ce49ae..f2fd9cb7fc 100644
--- a/src/qml/jsruntime/qv4script_p.h
+++ b/src/qml/jsruntime/qv4script_p.h
@@ -43,51 +43,69 @@ QT_BEGIN_NAMESPACE
class QQmlContextData;
-namespace QV4 {
+namespace QQmlJS {
+class Directives;
+}
-struct ExecutionContext;
+namespace QV4 {
struct ContextStateSaver {
- ExecutionContext *savedContext;
+ Value *savedContext;
bool strictMode;
Lookup *lookups;
CompiledData::CompilationUnit *compilationUnit;
int lineNumber;
- ContextStateSaver(ExecutionContext *context)
- : savedContext(context)
+ ContextStateSaver(Scope &scope, ExecutionContext *context)
+ : savedContext(scope.alloc(1))
, strictMode(context->d()->strictMode)
, lookups(context->d()->lookups)
, compilationUnit(context->d()->compilationUnit)
, lineNumber(context->d()->lineNumber)
- {}
+ {
+ savedContext->m = context->d();
+ }
+ ContextStateSaver(Scope &scope, Heap::ExecutionContext *context)
+ : savedContext(scope.alloc(1))
+ , strictMode(context->strictMode)
+ , lookups(context->lookups)
+ , compilationUnit(context->compilationUnit)
+ , lineNumber(context->lineNumber)
+ {
+ savedContext->m = context;
+ }
~ContextStateSaver()
{
- savedContext->d()->strictMode = strictMode;
- savedContext->d()->lookups = lookups;
- savedContext->d()->compilationUnit = compilationUnit;
- savedContext->d()->lineNumber = lineNumber;
+ Heap::ExecutionContext *ctx = static_cast<Heap::ExecutionContext *>(savedContext->m);
+ ctx->strictMode = strictMode;
+ ctx->lookups = lookups;
+ ctx->compilationUnit = compilationUnit;
+ ctx->lineNumber = lineNumber;
}
};
+namespace Heap {
+struct QmlBindingWrapper : Heap::FunctionObject {
+ QmlBindingWrapper(QV4::ExecutionContext *scope, Function *f, QV4::Object *qml);
+ // Constructor for QML functions and signal handlers, resulting binding wrapper is not callable!
+ QmlBindingWrapper(QV4::ExecutionContext *scope, QV4::Object *qml);
+ Object *qml;
+ CallContext *qmlContext;
+};
+
+}
+
struct Q_QML_EXPORT QmlBindingWrapper : FunctionObject {
- struct Data : FunctionObject::Data {
- Data(ExecutionContext *scope, Function *f, Object *qml);
- // Constructor for QML functions and signal handlers, resulting binding wrapper is not callable!
- Data(ExecutionContext *scope, Object *qml);
- Object *qml;
- CallContext *qmlContext;
- };
- V4_OBJECT(FunctionObject)
+ V4_OBJECT2(QmlBindingWrapper, FunctionObject)
static ReturnedValue call(Managed *that, CallData *);
- static void markObjects(Managed *m, ExecutionEngine *e);
+ static void markObjects(Heap::Base *m, ExecutionEngine *e);
- CallContext *context() const { return d()->qmlContext; }
+ Heap::CallContext *context() const { return d()->qmlContext; }
- static Returned<FunctionObject> *createQmlCallableForFunction(QQmlContextData *qmlContext, QObject *scopeObject, QV4::Function *runtimeFunction,
- const QList<QByteArray> &signalParameters = QList<QByteArray>(), QString *error = 0);
+ static Heap::FunctionObject *createQmlCallableForFunction(QQmlContextData *qmlContext, QObject *scopeObject, QV4::Function *runtimeFunction,
+ const QList<QByteArray> &signalParameters = QList<QByteArray>(), QString *error = 0);
private:
};
@@ -95,19 +113,20 @@ private:
struct Q_QML_EXPORT Script {
Script(ExecutionContext *scope, const QString &sourceCode, const QString &source = QString(), int line = 1, int column = 0)
: sourceFile(source), line(line), column(column), sourceCode(sourceCode)
- , scope(scope), strictMode(false), inheritContext(false), parsed(false)
+ , scope(scope->d()), strictMode(false), inheritContext(false), parsed(false)
, vmFunction(0), parseAsBinding(false) {}
Script(ExecutionEngine *engine, Object *qml, const QString &sourceCode, const QString &source = QString(), int line = 1, int column = 0)
: sourceFile(source), line(line), column(column), sourceCode(sourceCode)
- , scope(engine->rootContext), strictMode(false), inheritContext(true), parsed(false)
- , qml(qml->asReturnedValue()), vmFunction(0), parseAsBinding(true) {}
+ , scope(engine->rootContext()), strictMode(false), inheritContext(true), parsed(false)
+ , qml(engine, qml->asReturnedValue()), vmFunction(0), parseAsBinding(true) {}
Script(ExecutionEngine *engine, Object *qml, CompiledData::CompilationUnit *compilationUnit);
~Script();
QString sourceFile;
int line;
int column;
QString sourceCode;
- ExecutionContext *scope;
+ // ### GC
+ Heap::ExecutionContext *scope;
bool strictMode;
bool inheritContext;
bool parsed;
@@ -122,7 +141,8 @@ struct Q_QML_EXPORT Script {
Function *function();
- static QQmlRefPointer<CompiledData::CompilationUnit> precompile(IR::Module *module, Compiler::JSUnitGenerator *unitGenerator, ExecutionEngine *engine, const QUrl &url, const QString &source, QList<QQmlError> *reportedErrors = 0);
+ static QQmlRefPointer<CompiledData::CompilationUnit> precompile(IR::Module *module, Compiler::JSUnitGenerator *unitGenerator, ExecutionEngine *engine, const QUrl &url, const QString &source,
+ QList<QQmlError> *reportedErrors = 0, QQmlJS::Directives *directivesCollector = 0);
static ReturnedValue evaluate(ExecutionEngine *engine, const QString &script, Object *scopeObject);
};
diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp
index 83bfb65658..8c6d28305f 100644
--- a/src/qml/jsruntime/qv4sequenceobject.cpp
+++ b/src/qml/jsruntime/qv4sequenceobject.cpp
@@ -39,7 +39,8 @@
#include <private/qv4arrayobject_p.h>
#include <private/qqmlengine_p.h>
#include <private/qv4scopedvalue_p.h>
-#include <private/qv4internalclass_p.h>
+#include "qv4runtime_p.h"
+#include "qv4objectiterator_p.h"
#include <algorithm>
@@ -48,15 +49,15 @@ QT_BEGIN_NAMESPACE
using namespace QV4;
// helper function to generate valid warnings if errors occur during sequence operations.
-static void generateWarning(QV4::ExecutionContext *ctx, const QString& description)
+static void generateWarning(QV4::ExecutionEngine *v4, const QString& description)
{
- QQmlEngine *engine = ctx->d()->engine->v8Engine->engine();
+ QQmlEngine *engine = v4->qmlEngine();
if (!engine)
return;
QQmlError retn;
retn.setDescription(description);
- QV4::StackFrame frame = ctx->d()->engine->currentStackFrame();
+ QV4::StackFrame frame = v4->currentStackFrame();
retn.setLine(frame.line);
retn.setUrl(QUrl(frame.source));
@@ -154,41 +155,31 @@ template <> bool convertValueToElement(const ValueRef value)
return value->toBoolean();
}
+namespace QV4 {
+
+template <typename Container> struct QQmlSequence;
+
+namespace Heap {
+
+template <typename Container>
+struct QQmlSequence : Object {
+ QQmlSequence(QV4::ExecutionEngine *engine, const Container &container);
+ QQmlSequence(QV4::ExecutionEngine *engine, QObject *object, int propertyIndex);
+
+ mutable Container container;
+ QPointer<QObject> object;
+ int propertyIndex;
+ bool isReference;
+};
+
+}
+
template <typename Container>
struct QQmlSequence : public QV4::Object
{
- struct Data : Object::Data {
- Data(QV4::ExecutionEngine *engine, const Container &container)
- : Object::Data(InternalClass::create(engine, staticVTable(), engine->sequencePrototype.asObject()))
- , container(container)
- , propertyIndex(-1)
- , isReference(false)
- {
- QV4::Scope scope(engine);
- QV4::Scoped<QQmlSequence<Container> > o(scope, this);
- o->setArrayType(ArrayData::Custom);
- o->init();
- }
-
- Data(QV4::ExecutionEngine *engine, QObject *object, int propertyIndex)
- : Object::Data(InternalClass::create(engine, staticVTable(), engine->sequencePrototype.asObject()))
- , object(object)
- , propertyIndex(propertyIndex)
- , isReference(true)
- {
- QV4::Scope scope(engine);
- QV4::Scoped<QQmlSequence<Container> > o(scope, this);
- o->setArrayType(ArrayData::Custom);
- o->loadReference();
- o->init();
- }
- mutable Container container;
- QPointer<QObject> object;
- int propertyIndex;
- bool isReference;
- };
- V4_OBJECT(QV4::Object)
+ V4_OBJECT2(QQmlSequence<Container>, QV4::Object)
Q_MANAGED_TYPE(QmlSequence)
+ V4_NEEDS_DESTROY
public:
void init()
@@ -200,7 +191,7 @@ public:
{
/* Qt containers have int (rather than uint) allowable indexes. */
if (index > INT_MAX) {
- generateWarning(engine()->currentContext(), QLatin1String("Index out of range during indexed get"));
+ generateWarning(engine(), QLatin1String("Index out of range during indexed get"));
if (hasProperty)
*hasProperty = false;
return Encode::undefined();
@@ -231,7 +222,7 @@ public:
/* Qt containers have int (rather than uint) allowable indexes. */
if (index > INT_MAX) {
- generateWarning(engine()->currentContext(), QLatin1String("Index out of range during indexed set"));
+ generateWarning(engine(), QLatin1String("Index out of range during indexed set"));
return;
}
@@ -269,7 +260,7 @@ public:
{
/* Qt containers have int (rather than uint) allowable indexes. */
if (index > INT_MAX) {
- generateWarning(engine()->currentContext(), QLatin1String("Index out of range during indexed query"));
+ generateWarning(engine(), QLatin1String("Index out of range during indexed query"));
return QV4::Attr_Invalid;
}
if (d()->isReference) {
@@ -281,9 +272,9 @@ public:
return (signedIdx < d()->container.count()) ? QV4::Attr_Data : QV4::Attr_Invalid;
}
- void containerAdvanceIterator(ObjectIterator *it, String *&name, uint *index, Property *p, PropertyAttributes *attrs)
+ void containerAdvanceIterator(ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attrs)
{
- name = (String *)0;
+ *name = (Heap::String *)0;
*index = UINT_MAX;
if (d()->isReference) {
@@ -365,7 +356,7 @@ public:
ScopedCallData callData(scope, 2);
callData->args[0] = convertElementToValue(this->m_ctx->d()->engine, lhs);
callData->args[1] = convertElementToValue(this->m_ctx->d()->engine, rhs);
- callData->thisObject = this->m_ctx->d()->engine->globalObject;
+ callData->thisObject = this->m_ctx->d()->engine->globalObject();
QV4::ScopedValue result(scope, compare->call(callData));
return result->toNumber() < 0;
}
@@ -401,7 +392,7 @@ public:
QV4::Scope scope(ctx);
QV4::Scoped<QQmlSequence<Container> > This(scope, ctx->d()->callData->thisObject.as<QQmlSequence<Container> >());
if (!This)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
if (This->d()->isReference) {
if (!This->d()->object)
@@ -416,12 +407,12 @@ public:
QV4::Scope scope(ctx);
QV4::Scoped<QQmlSequence<Container> > This(scope, ctx->d()->callData->thisObject.as<QQmlSequence<Container> >());
if (!This)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
quint32 newLength = ctx->d()->callData->args[0].toUInt32();
/* Qt containers have int (rather than uint) allowable indexes. */
if (newLength > INT_MAX) {
- generateWarning(ctx, QLatin1String("Index out of range during length set"));
+ generateWarning(scope.engine, QLatin1String("Index out of range during length set"));
return QV4::Encode::undefined();
}
/* Read the sequence from the QObject property if we're a reference */
@@ -473,7 +464,6 @@ public:
return QVariant::fromValue(result);
}
-private:
void loadReference() const
{
Q_ASSERT(d()->object);
@@ -502,15 +492,41 @@ private:
{ return static_cast<QQmlSequence<Container> *>(that)->containerDeleteIndexedProperty(index); }
static bool isEqualTo(Managed *that, Managed *other)
{ return static_cast<QQmlSequence<Container> *>(that)->containerIsEqualTo(other); }
- static void advanceIterator(Managed *that, ObjectIterator *it, String *&name, uint *index, Property *p, PropertyAttributes *attrs)
+ static void advanceIterator(Managed *that, ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attrs)
{ return static_cast<QQmlSequence<Container> *>(that)->containerAdvanceIterator(it, name, index, p, attrs); }
- static void destroy(Managed *that)
- {
- static_cast<QQmlSequence<Container> *>(that)->d()->~Data();
- }
};
+
+template <typename Container>
+Heap::QQmlSequence<Container>::QQmlSequence(QV4::ExecutionEngine *engine, const Container &container)
+ : Heap::Object(InternalClass::create(engine, QV4::QQmlSequence<Container>::staticVTable()), engine->sequencePrototype.asObject())
+ , container(container)
+ , propertyIndex(-1)
+ , isReference(false)
+{
+ QV4::Scope scope(engine);
+ QV4::Scoped<QV4::QQmlSequence<Container> > o(scope, this);
+ o->setArrayType(Heap::ArrayData::Custom);
+ o->init();
+}
+
+template <typename Container>
+Heap::QQmlSequence<Container>::QQmlSequence(QV4::ExecutionEngine *engine, QObject *object, int propertyIndex)
+ : Heap::Object(InternalClass::create(engine, QV4::QQmlSequence<Container>::staticVTable()), engine->sequencePrototype.asObject())
+ , object(object)
+ , propertyIndex(propertyIndex)
+ , isReference(true)
+{
+ QV4::Scope scope(engine);
+ QV4::Scoped<QV4::QQmlSequence<Container> > o(scope, this);
+ o->setArrayType(Heap::ArrayData::Custom);
+ o->loadReference();
+ o->init();
+}
+
+}
+
typedef QQmlSequence<QStringList> QQmlQStringList;
template<>
DEFINE_OBJECT_VTABLE(QQmlQStringList);
@@ -544,7 +560,7 @@ QV4::ReturnedValue SequencePrototype::method_sort(QV4::CallContext *ctx)
QV4::Scope scope(ctx);
QV4::ScopedObject o(scope, ctx->d()->callData->thisObject);
if (!o || !o->isListType())
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
if (ctx->d()->callData->argc >= 2)
return o.asReturnedValue();
@@ -574,7 +590,7 @@ bool SequencePrototype::isSequenceType(int sequenceTypeId)
#define NEW_REFERENCE_SEQUENCE(ElementType, ElementTypeName, SequenceType, unused) \
if (sequenceType == qMetaTypeId<SequenceType>()) { \
- QV4::Scoped<QV4::Object> obj(scope, engine->memoryManager->alloc<QQml##ElementTypeName##List>(engine, object, propertyIndex)); \
+ QV4::ScopedObject obj(scope, engine->memoryManager->alloc<QQml##ElementTypeName##List>(engine, object, propertyIndex)); \
return obj.asReturnedValue(); \
} else
@@ -592,7 +608,7 @@ ReturnedValue SequencePrototype::newSequence(QV4::ExecutionEngine *engine, int s
#define NEW_COPY_SEQUENCE(ElementType, ElementTypeName, SequenceType, unused) \
if (sequenceType == qMetaTypeId<SequenceType>()) { \
- QV4::Scoped<QV4::Object> obj(scope, engine->memoryManager->alloc<QQml##ElementTypeName##List>(engine, v.value<SequenceType >())); \
+ QV4::ScopedObject obj(scope, engine->memoryManager->alloc<QQml##ElementTypeName##List>(engine, v.value<SequenceType >())); \
return obj.asReturnedValue(); \
} else
@@ -634,7 +650,7 @@ QVariant SequencePrototype::toVariant(const QV4::ValueRef array, int typeHint, b
*succeeded = false;
return QVariant();
}
- QV4::Scope scope(array->engine());
+ QV4::Scope scope(array->asObject()->engine());
QV4::ScopedArrayObject a(scope, array);
FOREACH_QML_SEQUENCE_TYPE(SEQUENCE_TO_VARIANT) { /* else */ *succeeded = false; return QVariant(); }
diff --git a/src/qml/jsruntime/qv4sequenceobject_p.h b/src/qml/jsruntime/qv4sequenceobject_p.h
index be348e524c..8d08a90869 100644
--- a/src/qml/jsruntime/qv4sequenceobject_p.h
+++ b/src/qml/jsruntime/qv4sequenceobject_p.h
@@ -50,6 +50,7 @@
#include "qv4value_inl_p.h"
#include "qv4object_p.h"
+#include "qv4context_p.h"
QT_BEGIN_NAMESPACE
@@ -61,7 +62,7 @@ struct SequencePrototype : public QV4::Object
static ReturnedValue method_valueOf(QV4::CallContext *ctx)
{
- return ctx->d()->callData->thisObject.toString(ctx)->asReturnedValue();
+ return ctx->d()->callData->thisObject.toString(ctx->engine())->asReturnedValue();
}
static ReturnedValue method_sort(QV4::CallContext *ctx);
diff --git a/src/qml/jsruntime/qv4serialize.cpp b/src/qml/jsruntime/qv4serialize.cpp
index 4b93afbc3a..017a2cbdb1 100644
--- a/src/qml/jsruntime/qv4serialize.cpp
+++ b/src/qml/jsruntime/qv4serialize.cpp
@@ -139,10 +139,9 @@ static inline void *popPtr(const char *&data)
// serialization/deserialization failures
#define ALIGN(size) (((size) + 3) & ~3)
-void Serialize::serialize(QByteArray &data, const QV4::ValueRef v, QV8Engine *engine)
+void Serialize::serialize(QByteArray &data, const QV4::ValueRef v, ExecutionEngine *engine)
{
- QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
- QV4::Scope scope(v4);
+ QV4::Scope scope(engine);
if (v->isEmpty()) {
Q_ASSERT(!"Serialize: got empty value");
@@ -159,7 +158,7 @@ void Serialize::serialize(QByteArray &data, const QV4::ValueRef v, QV8Engine *en
push(data, valueheader(WorkerUndefined));
return;
}
- int utf16size = ALIGN(length * sizeof(uint16_t));
+ int utf16size = ALIGN(length * sizeof(quint16));
reserve(data, utf16size + sizeof(quint32));
push(data, valueheader(WorkerString, length));
@@ -175,7 +174,7 @@ void Serialize::serialize(QByteArray &data, const QV4::ValueRef v, QV8Engine *en
push(data, valueheader(WorkerUndefined));
} else if (v->asArrayObject()) {
QV4::ScopedArrayObject array(scope, v);
- uint32_t length = array->getLength();
+ uint length = array->getLength();
if (length > 0xFFFFFF) {
push(data, valueheader(WorkerUndefined));
return;
@@ -183,7 +182,7 @@ void Serialize::serialize(QByteArray &data, const QV4::ValueRef v, QV8Engine *en
reserve(data, sizeof(quint32) + length * sizeof(quint32));
push(data, valueheader(WorkerArray, length));
ScopedValue val(scope);
- for (uint32_t ii = 0; ii < length; ++ii)
+ for (uint ii = 0; ii < length; ++ii)
serialize(data, (val = array->getIndexed(ii)), engine);
} else if (v->isInteger()) {
reserve(data, 2 * sizeof(quint32));
@@ -210,7 +209,7 @@ void Serialize::serialize(QByteArray &data, const QV4::ValueRef v, QV8Engine *en
push(data, valueheader(WorkerUndefined));
return;
}
- int utf16size = ALIGN(length * sizeof(uint16_t));
+ int utf16size = ALIGN(length * sizeof(quint16));
reserve(data, sizeof(quint32) + utf16size);
push(data, valueheader(WorkerRegexp, flags));
@@ -239,8 +238,8 @@ void Serialize::serialize(QByteArray &data, const QV4::ValueRef v, QV8Engine *en
ScopedObject o(scope, v);
if (o->isListType()) {
// valid sequence. we generate a length (sequence length + 1 for the sequence type)
- uint32_t seqLength = ScopedValue(scope, o->get(v4->id_length))->toUInt32();
- uint32_t length = seqLength + 1;
+ uint seqLength = ScopedValue(scope, o->get(engine->id_length))->toUInt32();
+ uint length = seqLength + 1;
if (length > 0xFFFFFF) {
push(data, valueheader(WorkerUndefined));
return;
@@ -249,7 +248,7 @@ void Serialize::serialize(QByteArray &data, const QV4::ValueRef v, QV8Engine *en
push(data, valueheader(WorkerSequence, length));
serialize(data, QV4::Primitive::fromInt32(QV4::SequencePrototype::metaTypeForSequence(o)), engine); // sequence type
ScopedValue val(scope);
- for (uint32_t ii = 0; ii < seqLength; ++ii)
+ for (uint ii = 0; ii < seqLength; ++ii)
serialize(data, (val = o->getIndexed(ii)), engine); // sequence elements
return;
@@ -257,7 +256,7 @@ void Serialize::serialize(QByteArray &data, const QV4::ValueRef v, QV8Engine *en
// regular object
QV4::ScopedValue val(scope, *v);
- QV4::ScopedArrayObject properties(scope, QV4::ObjectPrototype::getOwnPropertyNames(v4, val));
+ QV4::ScopedArrayObject properties(scope, QV4::ObjectPrototype::getOwnPropertyNames(engine, val));
quint32 length = properties->getLength();
if (length > 0xFFFFFF) {
push(data, valueheader(WorkerUndefined));
@@ -271,11 +270,10 @@ void Serialize::serialize(QByteArray &data, const QV4::ValueRef v, QV8Engine *en
s = properties->getIndexed(ii);
serialize(data, s, engine);
- QV4::ExecutionContext *ctx = v4->currentContext();
str = s;
- val = o->get(str.getPointer());
+ val = o->get(str);
if (scope.hasException())
- ctx->catchException();
+ scope.engine->catchException();
serialize(data, val, engine);
}
@@ -285,13 +283,12 @@ void Serialize::serialize(QByteArray &data, const QV4::ValueRef v, QV8Engine *en
}
}
-ReturnedValue Serialize::deserialize(const char *&data, QV8Engine *engine)
+ReturnedValue Serialize::deserialize(const char *&data, ExecutionEngine *engine)
{
quint32 header = popUint32(data);
Type type = headertype(header);
- QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
- Scope scope(v4);
+ Scope scope(engine);
switch (type) {
case WorkerUndefined:
@@ -306,8 +303,8 @@ ReturnedValue Serialize::deserialize(const char *&data, QV8Engine *engine)
{
quint32 size = headersize(header);
QString qstr((QChar *)data, size);
- data += ALIGN(size * sizeof(uint16_t));
- return QV4::Encode(v4->newString(qstr));
+ data += ALIGN(size * sizeof(quint16));
+ return QV4::Encode(engine->newString(qstr));
}
case WorkerFunction:
Q_ASSERT(!"Unreachable");
@@ -315,7 +312,7 @@ ReturnedValue Serialize::deserialize(const char *&data, QV8Engine *engine)
case WorkerArray:
{
quint32 size = headersize(header);
- Scoped<ArrayObject> a(scope, v4->newArrayObject());
+ ScopedArrayObject a(scope, engine->newArrayObject());
ScopedValue v(scope);
for (quint32 ii = 0; ii < size; ++ii) {
v = deserialize(data, engine);
@@ -326,7 +323,7 @@ ReturnedValue Serialize::deserialize(const char *&data, QV8Engine *engine)
case WorkerObject:
{
quint32 size = headersize(header);
- Scoped<Object> o(scope, v4->newObject());
+ ScopedObject o(scope, engine->newObject());
ScopedValue name(scope);
ScopedString n(scope);
ScopedValue value(scope);
@@ -334,7 +331,7 @@ ReturnedValue Serialize::deserialize(const char *&data, QV8Engine *engine)
name = deserialize(data, engine);
value = deserialize(data, engine);
n = name.asReturnedValue();
- o->put(n.getPointer(), value);
+ o->put(n, value);
}
return o.asReturnedValue();
}
@@ -345,29 +342,29 @@ ReturnedValue Serialize::deserialize(const char *&data, QV8Engine *engine)
case WorkerNumber:
return QV4::Encode(popDouble(data));
case WorkerDate:
- return QV4::Encode(v4->newDateObject(QV4::Primitive::fromDouble(popDouble(data))));
+ return QV4::Encode(engine->newDateObject(QV4::Primitive::fromDouble(popDouble(data))));
case WorkerRegexp:
{
quint32 flags = headersize(header);
quint32 length = popUint32(data);
QString pattern = QString((QChar *)data, length - 1);
- data += ALIGN(length * sizeof(uint16_t));
- return Encode(v4->newRegExpObject(pattern, flags));
+ data += ALIGN(length * sizeof(quint16));
+ return Encode(engine->newRegExpObject(pattern, flags));
}
case WorkerListModel:
{
void *ptr = popPtr(data);
QQmlListModelWorkerAgent *agent = (QQmlListModelWorkerAgent *)ptr;
- QV4::ScopedValue rv(scope, QV4::QObjectWrapper::wrap(v4, agent));
+ QV4::ScopedValue rv(scope, QV4::QObjectWrapper::wrap(engine, agent));
// ### Find a better solution then the ugly property
QQmlListModelWorkerAgent::VariantRef ref(agent);
QVariant var = qVariantFromValue(ref);
- QV4::ScopedValue v(scope, engine->fromVariant((var)));
- QV4::ScopedString s(scope, v4->newString(QStringLiteral("__qml:hidden:ref")));
- rv->asObject()->defineReadonlyProperty(s.getPointer(), v);
+ QV4::ScopedValue v(scope, scope.engine->fromVariant(var));
+ QV4::ScopedString s(scope, engine->newString(QStringLiteral("__qml:hidden:ref")));
+ rv->asObject()->defineReadonlyProperty(s, v);
agent->release();
- agent->setV8Engine(engine);
+ agent->setEngine(engine);
return rv.asReturnedValue();
}
case WorkerSequence:
@@ -378,7 +375,7 @@ ReturnedValue Serialize::deserialize(const char *&data, QV8Engine *engine)
quint32 seqLength = length - 1;
value = deserialize(data, engine);
int sequenceType = value->integerValue();
- Scoped<ArrayObject> array(scope, v4->newArrayObject());
+ ScopedArrayObject array(scope, engine->newArrayObject());
array->arrayReserve(seqLength);
for (quint32 ii = 0; ii < seqLength; ++ii) {
value = deserialize(data, engine);
@@ -386,21 +383,21 @@ ReturnedValue Serialize::deserialize(const char *&data, QV8Engine *engine)
}
array->setArrayLengthUnchecked(seqLength);
QVariant seqVariant = QV4::SequencePrototype::toVariant(array, sequenceType, &succeeded);
- return QV4::SequencePrototype::fromVariant(v4, seqVariant, &succeeded);
+ return QV4::SequencePrototype::fromVariant(engine, seqVariant, &succeeded);
}
}
Q_ASSERT(!"Unreachable");
return QV4::Encode::undefined();
}
-QByteArray Serialize::serialize(const QV4::ValueRef value, QV8Engine *engine)
+QByteArray Serialize::serialize(const QV4::ValueRef value, ExecutionEngine *engine)
{
QByteArray rv;
serialize(rv, value, engine);
return rv;
}
-ReturnedValue Serialize::deserialize(const QByteArray &data, QV8Engine *engine)
+ReturnedValue Serialize::deserialize(const QByteArray &data, ExecutionEngine *engine)
{
const char *stream = data.constData();
return deserialize(stream, engine);
diff --git a/src/qml/jsruntime/qv4serialize_p.h b/src/qml/jsruntime/qv4serialize_p.h
index f46c30cd24..8cab3d58c5 100644
--- a/src/qml/jsruntime/qv4serialize_p.h
+++ b/src/qml/jsruntime/qv4serialize_p.h
@@ -57,12 +57,12 @@ namespace QV4 {
class Serialize {
public:
- static QByteArray serialize(const ValueRef, QV8Engine *);
- static ReturnedValue deserialize(const QByteArray &, QV8Engine *);
+ static QByteArray serialize(const ValueRef, ExecutionEngine *);
+ static ReturnedValue deserialize(const QByteArray &, ExecutionEngine *);
private:
- static void serialize(QByteArray &, const ValueRef, QV8Engine *);
- static ReturnedValue deserialize(const char *&, QV8Engine *);
+ static void serialize(QByteArray &, const ValueRef, ExecutionEngine *);
+ static ReturnedValue deserialize(const char *&, ExecutionEngine *);
};
}
diff --git a/src/qml/jsruntime/qv4string.cpp b/src/qml/jsruntime/qv4string.cpp
index bd8a5ffccb..de5c7ffa24 100644
--- a/src/qml/jsruntime/qv4string.cpp
+++ b/src/qml/jsruntime/qv4string.cpp
@@ -43,9 +43,8 @@
using namespace QV4;
-static uint toArrayIndex(const QChar *ch, const QChar *end, bool *ok)
+static uint toArrayIndex(const QChar *ch, const QChar *end)
{
- *ok = false;
uint i = ch->unicode() - '0';
if (i > 9)
return UINT_MAX;
@@ -65,15 +64,13 @@ static uint toArrayIndex(const QChar *ch, const QChar *end, bool *ok)
i = n;
++ch;
}
- *ok = true;
return i;
}
#ifndef V4_BOOTSTRAP
-static uint toArrayIndex(const char *ch, const char *end, bool *ok)
+static uint toArrayIndex(const char *ch, const char *end)
{
- *ok = false;
uint i = *ch - '0';
if (i > 9)
return UINT_MAX;
@@ -93,133 +90,19 @@ static uint toArrayIndex(const char *ch, const char *end, bool *ok)
i = n;
++ch;
}
- *ok = true;
return i;
}
-const ObjectVTable String::static_vtbl =
-{
- DEFINE_MANAGED_VTABLE_INT(String, 0),
- 0,
- 0,
- get,
- getIndexed,
- put,
- putIndexed,
- query,
- queryIndexed,
- deleteProperty,
- deleteIndexedProperty,
- 0 /*getLookup*/,
- 0 /*setLookup*/,
- 0,
- 0 /*advanceIterator*/,
-};
-
-void String::destroy(Managed *that)
-{
- static_cast<String*>(that)->d()->~Data();
-}
-
-void String::markObjects(Managed *that, ExecutionEngine *e)
-{
- String *s = static_cast<String *>(that);
- if (s->d()->largestSubLength) {
- s->d()->left->mark(e);
- s->d()->right->mark(e);
- }
-}
-
-ReturnedValue String::get(Managed *m, String *name, bool *hasProperty)
-{
- ExecutionEngine *v4 = m->engine();
- Scope scope(v4);
- ScopedString that(scope, static_cast<String *>(m));
-
- if (name->equals(v4->id_length)) {
- if (hasProperty)
- *hasProperty = true;
- return Primitive::fromInt32(that->d()->text->size).asReturnedValue();
- }
- PropertyAttributes attrs;
- Property *pd = v4->stringObjectClass->prototype->__getPropertyDescriptor__(name, &attrs);
- if (!pd || attrs.isGeneric()) {
- if (hasProperty)
- *hasProperty = false;
- return Primitive::undefinedValue().asReturnedValue();
- }
- if (hasProperty)
- *hasProperty = true;
- return v4->stringObjectClass->prototype->getValue(that, pd, attrs);
-}
+DEFINE_MANAGED_VTABLE(String);
-ReturnedValue String::getIndexed(Managed *m, uint index, bool *hasProperty)
+void String::markObjects(Heap::Base *that, ExecutionEngine *e)
{
- ExecutionEngine *engine = m->engine();
- Scope scope(engine);
- ScopedString that(scope, static_cast<String *>(m));
-
- if (index < static_cast<uint>(that->d()->text->size)) {
- if (hasProperty)
- *hasProperty = true;
- return Encode(engine->newString(that->toQString().mid(index, 1)));
- }
- PropertyAttributes attrs;
- Property *pd = engine->stringObjectClass->prototype->__getPropertyDescriptor__(index, &attrs);
- if (!pd || attrs.isGeneric()) {
- if (hasProperty)
- *hasProperty = false;
- return Primitive::undefinedValue().asReturnedValue();
+ String::Data *s = static_cast<String::Data *>(that);
+ if (s->largestSubLength) {
+ s->left->mark(e);
+ s->right->mark(e);
}
- if (hasProperty)
- *hasProperty = true;
- return engine->stringObjectClass->prototype->getValue(that, pd, attrs);
-}
-
-void String::put(Managed *m, String *name, const ValueRef value)
-{
- Scope scope(m->engine());
- if (scope.hasException())
- return;
- ScopedString that(scope, static_cast<String *>(m));
- Scoped<Object> o(scope, that->engine()->newStringObject(that));
- o->put(name, value);
-}
-
-void String::putIndexed(Managed *m, uint index, const ValueRef value)
-{
- Scope scope(m->engine());
- if (scope.hasException())
- return;
-
- ScopedString that(scope, static_cast<String *>(m));
- Scoped<Object> o(scope, that->engine()->newStringObject(that));
- o->putIndexed(index, value);
-}
-
-PropertyAttributes String::query(const Managed *m, String *name)
-{
- uint idx = name->asArrayIndex();
- if (idx != UINT_MAX)
- return queryIndexed(m, idx);
- return Attr_Invalid;
-}
-
-PropertyAttributes String::queryIndexed(const Managed *m, uint index)
-{
- const String *that = static_cast<const String *>(m);
- return (index < static_cast<uint>(that->d()->text->size)) ? Attr_NotConfigurable|Attr_NotWritable : Attr_Invalid;
-}
-
-bool String::deleteProperty(Managed *, String *)
-{
- return false;
-}
-
-bool String::deleteIndexedProperty(Managed *, uint)
-{
- return false;
}
bool String::isEqualTo(Managed *t, Managed *o)
@@ -230,23 +113,14 @@ bool String::isEqualTo(Managed *t, Managed *o)
if (!o->internalClass()->vtable->isString)
return false;
- String *that = static_cast<String *>(t);
- String *other = static_cast<String *>(o);
- if (that->hashValue() != other->hashValue())
- return false;
- if (that->identifier() && that->identifier() == other->identifier())
- return true;
- if (that->subtype() >= StringType_UInt && that->subtype() == other->subtype())
- return true;
-
- return that->toQString() == other->toQString();
+ return static_cast<String *>(t)->isEqualTo(static_cast<String *>(o));
}
-String::Data::Data(ExecutionEngine *engine, const QString &t)
- : Managed::Data(engine->stringClass)
+Heap::String::String(ExecutionEngine *engine, const QString &t)
+ : Heap::Base(engine->stringClass)
{
- subtype = StringType_Unknown;
+ subtype = String::StringType_Unknown;
text = const_cast<QString &>(t).data_ptr();
text->ref.ref();
@@ -256,21 +130,21 @@ String::Data::Data(ExecutionEngine *engine, const QString &t)
len = text->size;
}
-String::Data::Data(ExecutionEngine *engine, String *l, String *r)
- : Managed::Data(engine->stringClass)
+Heap::String::String(ExecutionEngine *engine, String *l, String *r)
+ : Heap::Base(engine->stringClass)
{
- subtype = StringType_Unknown;
+ subtype = String::StringType_Unknown;
left = l;
right = r;
stringHash = UINT_MAX;
- largestSubLength = qMax(l->d()->largestSubLength, r->d()->largestSubLength);
- len = l->d()->len + r->d()->len;
+ largestSubLength = qMax(l->largestSubLength, r->largestSubLength);
+ len = l->len + r->len;
- if (!l->d()->largestSubLength && l->d()->len > largestSubLength)
- largestSubLength = l->d()->len;
- if (!r->d()->largestSubLength && r->d()->len > largestSubLength)
- largestSubLength = r->d()->len;
+ if (!l->largestSubLength && l->len > largestSubLength)
+ largestSubLength = l->len;
+ if (!r->largestSubLength && r->len > largestSubLength)
+ largestSubLength = r->len;
// make sure we don't get excessive depth in our strings
if (len > 256 && len >= 2*largestSubLength)
@@ -281,12 +155,12 @@ uint String::toUInt(bool *ok) const
{
*ok = true;
- if (subtype() == StringType_Unknown)
- createHashValue();
- if (subtype() >= StringType_UInt)
+ if (subtype() == Heap::String::StringType_Unknown)
+ d()->createHashValue();
+ if (subtype() == Heap::String::StringType_ArrayIndex)
return d()->stringHash;
- // ### this conversion shouldn't be required
+ // required for UINT_MAX or numbers starting with a leading 0
double d = RuntimeHelpers::stringToNumber(toQString());
uint l = (uint)d;
if (d == l)
@@ -295,20 +169,6 @@ uint String::toUInt(bool *ok) const
return UINT_MAX;
}
-bool String::equals(String *other) const
-{
- if (this == other)
- return true;
- if (hashValue() != other->hashValue())
- return false;
- if (identifier() && identifier() == other->identifier())
- return true;
- if (subtype() >= StringType_UInt && subtype() == other->subtype())
- return true;
-
- return toQString() == other->toQString();
-}
-
void String::makeIdentifierImpl() const
{
if (d()->largestSubLength)
@@ -317,7 +177,7 @@ void String::makeIdentifierImpl() const
engine()->identifierTable->identifier(this);
}
-void String::Data::simplifyString() const
+void Heap::String::simplifyString() const
{
Q_ASSERT(largestSubLength);
@@ -331,19 +191,44 @@ void String::Data::simplifyString() const
largestSubLength = 0;
}
-void String::Data::append(const String::Data *data, QChar *ch)
+void Heap::String::createHashValue() const
+{
+ if (largestSubLength)
+ simplifyString();
+ Q_ASSERT(!largestSubLength);
+ const QChar *ch = reinterpret_cast<const QChar *>(text->data());
+ const QChar *end = ch + text->size;
+
+ // array indices get their number as hash value
+ stringHash = ::toArrayIndex(ch, end);
+ if (stringHash != UINT_MAX) {
+ subtype = Heap::String::StringType_ArrayIndex;
+ return;
+ }
+
+ uint h = 0xffffffff;
+ while (ch < end) {
+ h = 31 * h + ch->unicode();
+ ++ch;
+ }
+
+ stringHash = h;
+ subtype = Heap::String::StringType_Regular;
+}
+
+void Heap::String::append(const String *data, QChar *ch)
{
- std::vector<const String::Data *> worklist;
+ std::vector<const String *> worklist;
worklist.reserve(32);
worklist.push_back(data);
while (!worklist.empty()) {
- const String::Data *item = worklist.back();
+ const String *item = worklist.back();
worklist.pop_back();
if (item->largestSubLength) {
- worklist.push_back(item->right->d());
- worklist.push_back(item->left->d());
+ worklist.push_back(item->right);
+ worklist.push_back(item->left);
} else {
memcpy(ch, item->text->data(), item->text->size * sizeof(QChar));
ch += item->text->size;
@@ -352,40 +237,15 @@ void String::Data::append(const String::Data *data, QChar *ch)
}
-void String::createHashValue() const
-{
- if (d()->largestSubLength)
- d()->simplifyString();
- Q_ASSERT(!d()->largestSubLength);
- const QChar *ch = reinterpret_cast<const QChar *>(d()->text->data());
- const QChar *end = ch + d()->text->size;
-
- // array indices get their number as hash value
- bool ok;
- d()->stringHash = ::toArrayIndex(ch, end, &ok);
- if (ok) {
- setSubtype((d()->stringHash == UINT_MAX) ? StringType_UInt : StringType_ArrayIndex);
- return;
- }
-
- uint h = 0xffffffff;
- while (ch < end) {
- h = 31 * h + ch->unicode();
- ++ch;
- }
- d()->stringHash = h;
- setSubtype(StringType_Regular);
-}
uint String::createHashValue(const QChar *ch, int length)
{
const QChar *end = ch + length;
// array indices get their number as hash value
- bool ok;
- uint stringHash = ::toArrayIndex(ch, end, &ok);
- if (ok)
+ uint stringHash = ::toArrayIndex(ch, end);
+ if (stringHash != UINT_MAX)
return stringHash;
uint h = 0xffffffff;
@@ -402,9 +262,8 @@ uint String::createHashValue(const char *ch, int length)
const char *end = ch + length;
// array indices get their number as hash value
- bool ok;
- uint stringHash = ::toArrayIndex(ch, end, &ok);
- if (ok)
+ uint stringHash = ::toArrayIndex(ch, end);
+ if (stringHash != UINT_MAX)
return stringHash;
uint h = 0xffffffff;
@@ -427,7 +286,6 @@ uint String::getLength(const Managed *m)
uint String::toArrayIndex(const QString &str)
{
- bool ok;
- return ::toArrayIndex(str.constData(), str.constData() + str.length(), &ok);
+ return ::toArrayIndex(str.constData(), str.constData() + str.length());
}
diff --git a/src/qml/jsruntime/qv4string_p.h b/src/qml/jsruntime/qv4string_p.h
index ce0e1f9d73..e70af2462a 100644
--- a/src/qml/jsruntime/qv4string_p.h
+++ b/src/qml/jsruntime/qv4string_p.h
@@ -43,89 +43,112 @@ namespace QV4 {
struct ExecutionEngine;
struct Identifier;
-struct Q_QML_PRIVATE_EXPORT String : public Managed {
-#ifndef V4_BOOTSTRAP
- struct Q_QML_PRIVATE_EXPORT Data : Managed::Data {
- Data(ExecutionEngine *engine, const QString &text);
- Data(ExecutionEngine *engine, String *l, String *n);
- ~Data() {
- if (!largestSubLength && !text->ref.deref())
- QStringData::deallocate(text);
- }
- void simplifyString() const;
- int length() const {
- Q_ASSERT((largestSubLength &&
- (len == left->d()->len + right->d()->len)) ||
- len == (uint)text->size);
- return len;
- }
- union {
- mutable QStringData *text;
- mutable String *left;
- };
- union {
- mutable Identifier *identifier;
- mutable String *right;
- };
- mutable uint stringHash;
- mutable uint largestSubLength;
- uint len;
- private:
- static void append(const Data *data, QChar *ch);
- };
- // ### FIXME: Should this be a V4_OBJECT
- V4_OBJECT(QV4::Managed)
- Q_MANAGED_TYPE(String)
- enum {
- IsString = true
- };
+namespace Heap {
+#ifndef V4_BOOTSTRAP
+struct Q_QML_PRIVATE_EXPORT String : Base {
enum StringType {
StringType_Unknown,
StringType_Regular,
- StringType_UInt,
StringType_ArrayIndex
};
- bool equals(String *other) const;
+ String(ExecutionEngine *engine, const QString &text);
+ String(ExecutionEngine *engine, String *l, String *n);
+ ~String() {
+ if (!largestSubLength && !text->ref.deref())
+ QStringData::deallocate(text);
+ }
+ void simplifyString() const;
+ int length() const {
+ Q_ASSERT((largestSubLength &&
+ (len == left->len + right->len)) ||
+ len == (uint)text->size);
+ return len;
+ }
+ void createHashValue() const;
+ inline unsigned hashValue() const {
+ if (subtype == StringType_Unknown)
+ createHashValue();
+ Q_ASSERT(!largestSubLength);
+
+ return stringHash;
+ }
+ inline QString toQString() const {
+ if (largestSubLength)
+ simplifyString();
+ QStringDataPtr ptr = { text };
+ text->ref.ref();
+ return QString(ptr);
+ }
inline bool isEqualTo(const String *other) const {
if (this == other)
return true;
if (hashValue() != other->hashValue())
return false;
- Q_ASSERT(!d()->largestSubLength);
- if (d()->identifier && d()->identifier == other->d()->identifier)
+ Q_ASSERT(!largestSubLength);
+ if (identifier && identifier == other->identifier)
return true;
- if (subtype() >= StringType_UInt && subtype() == other->subtype())
+ if (subtype == Heap::String::StringType_ArrayIndex && other->subtype == Heap::String::StringType_ArrayIndex)
return true;
return toQString() == other->toQString();
}
+ union {
+ mutable QStringData *text;
+ mutable String *left;
+ };
+ union {
+ mutable Identifier *identifier;
+ mutable String *right;
+ };
+ mutable uint subtype;
+ mutable uint stringHash;
+ mutable uint largestSubLength;
+ uint len;
+private:
+ static void append(const String *data, QChar *ch);
+};
+#endif
+
+}
+
+struct Q_QML_PRIVATE_EXPORT String : public Managed {
+#ifndef V4_BOOTSTRAP
+ V4_MANAGED(String, Managed)
+ Q_MANAGED_TYPE(String)
+ V4_NEEDS_DESTROY
+ enum {
+ IsString = true
+ };
+
+ uchar subtype() const { return d()->subtype; }
+ void setSubtype(uchar subtype) const { d()->subtype = subtype; }
+
+ bool equals(String *other) const {
+ return d()->isEqualTo(other->d());
+ }
+ inline bool isEqualTo(const String *other) const {
+ return d()->isEqualTo(other->d());
+ }
+
inline bool compare(const String *other) {
return toQString() < other->toQString();
}
inline QString toQString() const {
- if (d()->largestSubLength)
- d()->simplifyString();
- QStringDataPtr ptr = { d()->text };
- d()->text->ref.ref();
- return QString(ptr);
+ return d()->toQString();
}
inline unsigned hashValue() const {
- if (subtype() == StringType_Unknown)
- createHashValue();
- Q_ASSERT(!d()->largestSubLength);
-
- return d()->stringHash;
+ return d()->hashValue();
}
uint asArrayIndex() const {
- if (subtype() == StringType_Unknown)
- createHashValue();
+ if (subtype() == Heap::String::StringType_Unknown)
+ d()->createHashValue();
Q_ASSERT(!d()->largestSubLength);
- if (subtype() == StringType_ArrayIndex)
+ if (subtype() == Heap::String::StringType_ArrayIndex)
return d()->stringHash;
return UINT_MAX;
}
@@ -139,30 +162,20 @@ struct Q_QML_PRIVATE_EXPORT String : public Managed {
void makeIdentifierImpl() const;
- void createHashValue() const;
static uint createHashValue(const QChar *ch, int length);
static uint createHashValue(const char *ch, int length);
bool startsWithUpper() const {
- const String *l = this;
- while (l->d()->largestSubLength)
- l = l->d()->left;
- return l->d()->text->size && QChar::isUpper(l->d()->text->data()[0]);
+ const String::Data *l = d();
+ while (l->largestSubLength)
+ l = l->left;
+ return l->text->size && QChar::isUpper(l->text->data()[0]);
}
Identifier *identifier() const { return d()->identifier; }
protected:
- static void destroy(Managed *);
- static void markObjects(Managed *that, ExecutionEngine *e);
- static ReturnedValue get(Managed *m, String *name, bool *hasProperty);
- static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty);
- static void put(Managed *m, String *name, const ValueRef value);
- static void putIndexed(Managed *m, uint index, const ValueRef value);
- static PropertyAttributes query(const Managed *m, String *name);
- static PropertyAttributes queryIndexed(const Managed *m, uint index);
- static bool deleteProperty(Managed *, String *);
- static bool deleteIndexedProperty(Managed *m, uint index);
+ static void markObjects(Heap::Base *that, ExecutionEngine *e);
static bool isEqualTo(Managed *that, Managed *o);
static uint getLength(const Managed *m);
#endif
@@ -171,20 +184,6 @@ public:
static uint toArrayIndex(const QString &str);
};
-#ifndef V4_BOOTSTRAP
-template<>
-inline String *value_cast(const Value &v) {
- return v.asString();
-}
-
-template<>
-inline ReturnedValue value_convert<String>(ExecutionEngine *e, const Value &v)
-{
- return v.toString(e)->asReturnedValue();
-}
-
-#endif
-
}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp
index 397a6efdf8..5fc6b884d0 100644
--- a/src/qml/jsruntime/qv4stringobject.cpp
+++ b/src/qml/jsruntime/qv4stringobject.cpp
@@ -33,6 +33,7 @@
#include "qv4stringobject_p.h"
+#include "qv4regexp_p.h"
#include "qv4regexpobject_p.h"
#include "qv4objectproto_p.h"
#include "qv4mm_p.h"
@@ -69,11 +70,11 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(StringObject);
-StringObject::Data::Data(InternalClass *ic)
- : Object::Data(ic)
+Heap::StringObject::StringObject(InternalClass *ic, QV4::Object *prototype)
+ : Heap::Object(ic, prototype)
{
- Q_ASSERT(internalClass->vtable == staticVTable());
- value = ic->engine->newString(QStringLiteral(""))->asReturnedValue();
+ Q_ASSERT(internalClass->vtable == QV4::StringObject::staticVTable());
+ value = ic->engine->newString()->asReturnedValue();
tmpProperty.value = Primitive::undefinedValue();
Scope scope(ic->engine);
@@ -81,26 +82,26 @@ StringObject::Data::Data(InternalClass *ic)
s->defineReadonlyProperty(ic->engine->id_length, Primitive::fromInt32(0));
}
-StringObject::Data::Data(ExecutionEngine *engine, const ValueRef val)
- : Object::Data(engine->stringObjectClass)
+Heap::StringObject::StringObject(ExecutionEngine *engine, const ValueRef val)
+ : Heap::Object(engine->stringObjectClass, engine->stringPrototype.asObject())
{
value = val;
Q_ASSERT(value.isString());
tmpProperty.value = Primitive::undefinedValue();
- setVTable(staticVTable());
+ setVTable(QV4::StringObject::staticVTable());
Scope scope(engine);
ScopedObject s(scope, this);
s->defineReadonlyProperty(engine->id_length, Primitive::fromUInt32(value.stringValue()->toQString().length()));
}
-Property *StringObject::getIndex(uint index) const
+Property *Heap::StringObject::getIndex(uint index) const
{
- QString str = d()->value.stringValue()->toQString();
+ QString str = value.stringValue()->toQString();
if (index >= (uint)str.length())
return 0;
- d()->tmpProperty.value = Encode(internalClass()->engine->newString(str.mid(index, 1)));
- return &d()->tmpProperty;
+ tmpProperty.value = Encode(internalClass->engine->newString(str.mid(index, 1)));
+ return &tmpProperty;
}
bool StringObject::deleteIndexedProperty(Managed *m, uint index)
@@ -109,21 +110,21 @@ bool StringObject::deleteIndexedProperty(Managed *m, uint index)
Scope scope(v4);
Scoped<StringObject> o(scope, m->asStringObject());
if (!o) {
- v4->currentContext()->throwTypeError();
+ v4->throwTypeError();
return false;
}
if (index < static_cast<uint>(o->d()->value.stringValue()->toQString().length())) {
- if (v4->currentContext()->d()->strictMode)
- v4->currentContext()->throwTypeError();
+ if (v4->currentContext()->strictMode)
+ v4->throwTypeError();
return false;
}
return true;
}
-void StringObject::advanceIterator(Managed *m, ObjectIterator *it, String *&name, uint *index, Property *p, PropertyAttributes *attrs)
+void StringObject::advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attrs)
{
- name = (String *)0;
+ *name = (Heap::String *)0;
StringObject *s = static_cast<StringObject *>(m);
uint slen = s->d()->value.stringValue()->toQString().length();
if (it->arrayIndex <= slen) {
@@ -134,7 +135,7 @@ void StringObject::advanceIterator(Managed *m, ObjectIterator *it, String *&name
Property *pd = s->__getOwnProperty__(*index, &a);
if (!(it->flags & ObjectIterator::EnumerableOnly) || a.isEnumerable()) {
*attrs = a;
- p->copy(*pd, a);
+ p->copy(pd, a);
return;
}
}
@@ -149,20 +150,20 @@ void StringObject::advanceIterator(Managed *m, ObjectIterator *it, String *&name
return Object::advanceIterator(m, it, name, index, p, attrs);
}
-void StringObject::markObjects(Managed *that, ExecutionEngine *e)
+void StringObject::markObjects(Heap::Base *that, ExecutionEngine *e)
{
- StringObject *o = static_cast<StringObject *>(that);
- o->d()->value.stringValue()->mark(e);
- o->d()->tmpProperty.value.mark(e);
+ StringObject::Data *o = static_cast<StringObject::Data *>(that);
+ o->value.stringValue()->mark(e);
+ o->tmpProperty.value.mark(e);
Object::markObjects(that, e);
}
DEFINE_OBJECT_VTABLE(StringCtor);
-StringCtor::Data::Data(ExecutionContext *scope)
- : FunctionObject::Data(scope, QStringLiteral("String"))
+Heap::StringCtor::StringCtor(QV4::ExecutionContext *scope)
+ : Heap::FunctionObject(scope, QStringLiteral("String"))
{
- setVTable(staticVTable());
+ setVTable(QV4::StringCtor::staticVTable());
}
ReturnedValue StringCtor::construct(Managed *m, CallData *callData)
@@ -171,9 +172,9 @@ ReturnedValue StringCtor::construct(Managed *m, CallData *callData)
Scope scope(v4);
ScopedValue value(scope);
if (callData->argc)
- value = callData->args[0].toString(v4->currentContext());
+ value = callData->args[0].toString(v4);
else
- value = v4->newString(QString());
+ value = v4->newString();
return Encode(v4->newStringObject(value));
}
@@ -183,9 +184,9 @@ ReturnedValue StringCtor::call(Managed *m, CallData *callData)
Scope scope(v4);
ScopedValue value(scope);
if (callData->argc)
- value = callData->args[0].toString(v4->currentContext());
+ value = callData->args[0].toString(v4);
else
- value = v4->newString(QString());
+ value = v4->newString();
return value.asReturnedValue();
}
@@ -230,7 +231,7 @@ static QString getThisString(ExecutionContext *ctx)
if (StringObject *thisString = t->asStringObject())
return thisString->d()->value.stringValue()->toQString();
if (t->isUndefined() || t->isNull()) {
- ctx->throwTypeError();
+ scope.engine->throwTypeError();
return QString();
}
return t->toQString();
@@ -243,7 +244,7 @@ ReturnedValue StringPrototype::method_toString(CallContext *context)
StringObject *o = context->d()->callData->thisObject.asStringObject();
if (!o)
- return context->throwTypeError();
+ return context->engine()->throwTypeError();
return o->d()->value.asReturnedValue();
}
@@ -291,7 +292,7 @@ ReturnedValue StringPrototype::method_concat(CallContext *context)
ScopedValue v(scope);
for (int i = 0; i < context->d()->callData->argc; ++i) {
- v = RuntimeHelpers::toString(context, ValueRef(&context->d()->callData->args[i]));
+ v = RuntimeHelpers::toString(scope.engine, ValueRef(&context->d()->callData->args[i]));
if (scope.hasException())
return Encode::undefined();
Q_ASSERT(v->isString());
@@ -309,7 +310,7 @@ ReturnedValue StringPrototype::method_indexOf(CallContext *context)
QString searchString;
if (context->d()->callData->argc)
- searchString = context->d()->callData->args[0].toString(context)->toQString();
+ searchString = context->d()->callData->args[0].toQString();
int pos = 0;
if (context->d()->callData->argc > 1)
@@ -365,10 +366,10 @@ ReturnedValue StringPrototype::method_localeCompare(CallContext *context)
ReturnedValue StringPrototype::method_match(CallContext *context)
{
if (context->d()->callData->thisObject.isUndefined() || context->d()->callData->thisObject.isNull())
- return context->throwTypeError();
+ return context->engine()->throwTypeError();
Scope scope(context);
- ScopedString s(scope, context->d()->callData->thisObject.toString(context));
+ ScopedString s(scope, context->d()->callData->thisObject.toString(scope.engine));
ScopedValue regexp(scope, context->d()->callData->argument(0));
Scoped<RegExpObject> rx(scope, regexp);
@@ -380,13 +381,13 @@ ReturnedValue StringPrototype::method_match(CallContext *context)
if (!rx)
// ### CHECK
- return context->throwTypeError();
+ return context->engine()->throwTypeError();
bool global = rx->global();
// ### use the standard builtin function, not the one that might be redefined in the proto
- ScopedString execString(scope, context->d()->engine->newString(QStringLiteral("exec")));
- Scoped<FunctionObject> exec(scope, context->d()->engine->regExpClass->prototype->get(execString.getPointer()));
+ ScopedString execString(scope, scope.engine->newString(QStringLiteral("exec")));
+ ScopedFunctionObject exec(scope, scope.engine->regExpPrototype.asObject()->get(execString));
ScopedCallData callData(scope, 1);
callData->thisObject = rx;
@@ -395,8 +396,8 @@ ReturnedValue StringPrototype::method_match(CallContext *context)
return exec->call(callData);
ScopedString lastIndex(scope, context->d()->engine->newString(QStringLiteral("lastIndex")));
- rx->put(lastIndex.getPointer(), ScopedValue(scope, Primitive::fromInt32(0)));
- Scoped<ArrayObject> a(scope, context->d()->engine->newArrayObject());
+ rx->put(lastIndex, ScopedValue(scope, Primitive::fromInt32(0)));
+ ScopedArrayObject a(scope, context->d()->engine->newArrayObject());
double previousLastIndex = 0;
uint n = 0;
@@ -408,11 +409,11 @@ ReturnedValue StringPrototype::method_match(CallContext *context)
if (result->isNull())
break;
assert(result->isObject());
- index = rx->get(lastIndex.getPointer(), 0);
+ index = rx->get(lastIndex, 0);
double thisIndex = index->toInteger();
if (previousLastIndex == thisIndex) {
previousLastIndex = thisIndex + 1;
- rx->put(lastIndex.getPointer(), ScopedValue(scope, Primitive::fromDouble(previousLastIndex)));
+ rx->put(lastIndex, ScopedValue(scope, Primitive::fromDouble(previousLastIndex)));
} else {
previousLastIndex = thisIndex;
}
@@ -480,7 +481,7 @@ ReturnedValue StringPrototype::method_replace(CallContext *ctx)
if (StringObject *thisString = ctx->d()->callData->thisObject.asStringObject())
string = thisString->d()->value.stringValue()->toQString();
else
- string = ctx->d()->callData->thisObject.toString(ctx)->toQString();
+ string = ctx->d()->callData->thisObject.toQString();
int numCaptures = 0;
int numStringMatches = 0;
@@ -517,12 +518,12 @@ ReturnedValue StringPrototype::method_replace(CallContext *ctx)
offset = qMax(offset + 1, matchOffsets[oldSize + 1]);
}
if (regExp->global())
- regExp->lastIndexProperty(ctx)->value = Primitive::fromUInt32(0);
+ regExp->lastIndexProperty()->value = Primitive::fromUInt32(0);
numStringMatches = nMatchOffsets / (regExp->value()->captureCount() * 2);
numCaptures = regExp->value()->captureCount();
} else {
numCaptures = 1;
- QString searchString = searchValue->toString(ctx)->toQString();
+ QString searchString = searchValue->toQString();
int idx = string.indexOf(searchString);
if (idx != -1) {
numStringMatches = 1;
@@ -535,7 +536,7 @@ ReturnedValue StringPrototype::method_replace(CallContext *ctx)
QString result;
ScopedValue replacement(scope);
ScopedValue replaceValue(scope, ctx->argument(1));
- Scoped<FunctionObject> searchCallback(scope, replaceValue);
+ ScopedFunctionObject searchCallback(scope, replaceValue);
if (!!searchCallback) {
result.reserve(string.length() + 10*numStringMatches);
ScopedCallData callData(scope, numCaptures + 2);
@@ -560,12 +561,12 @@ ReturnedValue StringPrototype::method_replace(CallContext *ctx)
replacement = searchCallback->call(callData);
result += string.midRef(lastEnd, matchStart - lastEnd);
- result += replacement->toString(ctx)->toQString();
+ result += replacement->toQString();
lastEnd = matchEnd;
}
result += string.midRef(lastEnd);
} else {
- QString newString = replaceValue->toString(ctx)->toQString();
+ QString newString = replaceValue->toQString();
result.reserve(string.length() + numStringMatches*newString.size());
int lastEnd = 0;
@@ -606,8 +607,9 @@ ReturnedValue StringPrototype::method_search(CallContext *ctx)
regExp = regExpValue->as<RegExpObject>();
Q_ASSERT(regExp);
}
+ Scoped<RegExp> re(scope, regExp->value());
uint* matchOffsets = (uint*)alloca(regExp->value()->captureCount() * 2 * sizeof(uint));
- uint result = regExp->value()->match(string, /*offset*/0, matchOffsets);
+ uint result = re->match(string, /*offset*/0, matchOffsets);
if (result == JSC::Yarr::offsetNoMatch)
return Encode(-1);
return Encode(result);
@@ -670,9 +672,9 @@ ReturnedValue StringPrototype::method_split(CallContext *ctx)
Scoped<RegExpObject> re(scope, separatorValue);
if (re) {
- if (re->value()->pattern().isEmpty()) {
+ if (re->value()->pattern.isEmpty()) {
re = (RegExpObject *)0;
- separatorValue = ctx->d()->engine->newString(QString());
+ separatorValue = ctx->d()->engine->newString();
}
}
@@ -681,7 +683,8 @@ ReturnedValue StringPrototype::method_split(CallContext *ctx)
uint offset = 0;
uint* matchOffsets = (uint*)alloca(re->value()->captureCount() * 2 * sizeof(uint));
while (true) {
- uint result = re->value()->match(text, offset, matchOffsets);
+ Scoped<RegExp> regexp(scope, re->value());
+ uint result = regexp->match(text, offset, matchOffsets);
if (result == JSC::Yarr::offsetNoMatch)
break;
@@ -702,7 +705,7 @@ ReturnedValue StringPrototype::method_split(CallContext *ctx)
if (array->getLength() < limit)
array->push_back((s = ctx->d()->engine->newString(text.mid(offset))));
} else {
- QString separator = separatorValue->toString(ctx)->toQString();
+ QString separator = separatorValue->toQString();
if (separator.isEmpty()) {
for (uint i = 0; i < qMin(limit, uint(text.length())); ++i)
array->push_back((s = ctx->d()->engine->newString(text.mid(i, 1))));
diff --git a/src/qml/jsruntime/qv4stringobject_p.h b/src/qml/jsruntime/qv4stringobject_p.h
index 5d3c0c9ccb..a5851cb9bb 100644
--- a/src/qml/jsruntime/qv4stringobject_p.h
+++ b/src/qml/jsruntime/qv4stringobject_p.h
@@ -41,33 +41,42 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
-struct StringObject: Object {
- struct Data : Object::Data {
- Data(ExecutionEngine *engine, const ValueRef value);
- Data(InternalClass *ic);
- Value value;
- // ### get rid of tmpProperty
- mutable Property tmpProperty;
- };
- V4_OBJECT(Object)
- Q_MANAGED_TYPE(StringObject)
+namespace Heap {
+struct StringObject : Object {
+ StringObject(InternalClass *ic, QV4::Object *prototype);
+ StringObject(ExecutionEngine *engine, const ValueRef value);
+ Value value;
Property *getIndex(uint index) const;
+ // ### get rid of tmpProperty
+ mutable Property tmpProperty;
+};
+
+struct StringCtor : FunctionObject {
+ StringCtor(QV4::ExecutionContext *scope);
+};
+
+}
+
+struct StringObject: Object {
+ V4_OBJECT2(StringObject, Object)
+ Q_MANAGED_TYPE(StringObject)
+
+ Property *getIndex(uint index) const {
+ return d()->getIndex(index);
+ }
static bool deleteIndexedProperty(Managed *m, uint index);
protected:
- static void advanceIterator(Managed *m, ObjectIterator *it, String *&name, uint *index, Property *p, PropertyAttributes *attrs);
- static void markObjects(Managed *that, ExecutionEngine *e);
+ static void advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attrs);
+ static void markObjects(Heap::Base *that, ExecutionEngine *e);
};
struct StringCtor: FunctionObject
{
- struct Data : FunctionObject::Data {
- Data(ExecutionContext *scope);
- };
- V4_OBJECT(FunctionObject)
+ V4_OBJECT2(StringCtor, FunctionObject)
static ReturnedValue construct(Managed *m, CallData *callData);
static ReturnedValue call(Managed *that, CallData *callData);
diff --git a/src/qml/jsruntime/qv4typedarray.cpp b/src/qml/jsruntime/qv4typedarray.cpp
new file mode 100644
index 0000000000..74adc2e38b
--- /dev/null
+++ b/src/qml/jsruntime/qv4typedarray.cpp
@@ -0,0 +1,572 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "qv4typedarray_p.h"
+#include "qv4arraybuffer_p.h"
+
+using namespace QV4;
+
+DEFINE_OBJECT_VTABLE(TypedArrayCtor);
+DEFINE_OBJECT_VTABLE(TypedArrayPrototype);
+DEFINE_OBJECT_VTABLE(TypedArray);
+
+Q_STATIC_ASSERT((int)ExecutionEngine::NTypedArrayTypes == (int)Heap::TypedArray::NTypes);
+
+ReturnedValue Int8ArrayRead(const char *data, int index)
+{
+ return Encode((int)(signed char)data[index]);
+}
+
+void Int8ArrayWrite(ExecutionEngine *e, char *data, int index, ValueRef value)
+{
+ signed char v = (signed char)value->toUInt32();
+ if (e->hasException)
+ return;
+ data[index] = v;
+}
+
+ReturnedValue UInt8ArrayRead(const char *data, int index)
+{
+ return Encode((int)(unsigned char)data[index]);
+}
+
+void UInt8ArrayWrite(ExecutionEngine *e, char *data, int index, ValueRef value)
+{
+ unsigned char v = (unsigned char)value->toUInt32();
+ if (e->hasException)
+ return;
+ data[index] = v;
+}
+
+void UInt8ClampedArrayWrite(ExecutionEngine *e, char *data, int index, ValueRef value)
+{
+ if (value->isInteger()) {
+ data[index] = (char)(unsigned char)qBound(0, value->integerValue(), 255);
+ return;
+ }
+ double d = value->toNumber();
+ if (e->hasException)
+ return;
+ // ### is there a way to optimise this?
+ if (d <= 0 || std::isnan(d)) {
+ data[index] = 0;
+ return;
+ }
+ if (d >= 255) {
+ data[index] = 255;
+ return;
+ }
+ double f = floor(d);
+ if (f + 0.5 < d) {
+ data[index] = (unsigned char)(f + 1);
+ return;
+ }
+ if (d < f + 0.5) {
+ data[index] = (unsigned char)(f);
+ return;
+ }
+ if (int(f) % 2) {
+ // odd number
+ data[index] = (unsigned char)(f + 1);
+ return;
+ }
+ data[index] = (unsigned char)(f);
+}
+
+ReturnedValue Int16ArrayRead(const char *data, int index)
+{
+ return Encode((int)*(short *)(data + index));
+}
+
+void Int16ArrayWrite(ExecutionEngine *e, char *data, int index, ValueRef value)
+{
+ short v = (short)value->toInt32();
+ if (e->hasException)
+ return;
+ *(short *)(data + index) = v;
+}
+
+ReturnedValue UInt16ArrayRead(const char *data, int index)
+{
+ return Encode((int)*(unsigned short *)(data + index));
+}
+
+void UInt16ArrayWrite(ExecutionEngine *e, char *data, int index, ValueRef value)
+{
+ unsigned short v = (unsigned short)value->toInt32();
+ if (e->hasException)
+ return;
+ *(unsigned short *)(data + index) = v;
+}
+
+ReturnedValue Int32ArrayRead(const char *data, int index)
+{
+ return Encode(*(int *)(data + index));
+}
+
+void Int32ArrayWrite(ExecutionEngine *e, char *data, int index, ValueRef value)
+{
+ int v = (int)value->toInt32();
+ if (e->hasException)
+ return;
+ *(int *)(data + index) = v;
+}
+
+ReturnedValue UInt32ArrayRead(const char *data, int index)
+{
+ return Encode(*(unsigned int *)(data + index));
+}
+
+void UInt32ArrayWrite(ExecutionEngine *e, char *data, int index, ValueRef value)
+{
+ unsigned int v = (unsigned int)value->toUInt32();
+ if (e->hasException)
+ return;
+ *(unsigned int *)(data + index) = v;
+}
+
+ReturnedValue Float32ArrayRead(const char *data, int index)
+{
+ return Encode(*(float *)(data + index));
+}
+
+void Float32ArrayWrite(ExecutionEngine *e, char *data, int index, ValueRef value)
+{
+ float v = value->toNumber();
+ if (e->hasException)
+ return;
+ *(float *)(data + index) = v;
+}
+
+ReturnedValue Float64ArrayRead(const char *data, int index)
+{
+ return Encode(*(double *)(data + index));
+}
+
+void Float64ArrayWrite(ExecutionEngine *e, char *data, int index, ValueRef value)
+{
+ double v = value->toNumber();
+ if (e->hasException)
+ return;
+ *(double *)(data + index) = v;
+}
+
+const TypedArrayOperations operations[Heap::TypedArray::NTypes] = {
+ { 1, "Int8Array", Int8ArrayRead, Int8ArrayWrite },
+ { 1, "Uint8Array", UInt8ArrayRead, UInt8ArrayWrite },
+ { 1, "Uint8ClampedArray", UInt8ArrayRead, UInt8ClampedArrayWrite },
+ { 2, "Int16Array", Int16ArrayRead, Int16ArrayWrite },
+ { 2, "Uint16Array", UInt16ArrayRead, UInt16ArrayWrite },
+ { 4, "Int32Array", Int32ArrayRead, Int32ArrayWrite },
+ { 4, "Uint32Array", UInt32ArrayRead, UInt32ArrayWrite },
+ { 4, "Float32Array", Float32ArrayRead, Float32ArrayWrite },
+ { 8, "Float64Array", Float64ArrayRead, Float64ArrayWrite },
+};
+
+
+Heap::TypedArrayCtor::TypedArrayCtor(QV4::ExecutionContext *scope, TypedArray::Type t)
+ : Heap::FunctionObject(scope, QLatin1String(operations[t].name))
+ , type(t)
+{
+ setVTable(QV4::TypedArrayCtor::staticVTable());
+}
+
+ReturnedValue TypedArrayCtor::construct(Managed *m, CallData *callData)
+{
+ Scope scope(m->engine());
+ Scoped<TypedArrayCtor> that(scope, static_cast<TypedArrayCtor *>(m));
+
+ if (!callData->argc || !callData->args[0].isObject()) {
+ // ECMA 6 22.2.1.1
+ double l = callData->argc ? callData->args[0].toNumber() : 0;
+ if (scope.engine->hasException)
+ return Encode::undefined();
+ uint len = (uint)l;
+ if (l != len)
+ scope.engine->throwRangeError(QStringLiteral("Non integer length for typed array."));
+ uint byteLength = len * operations[that->d()->type].bytesPerElement;
+ Scoped<ArrayBuffer> buffer(scope, scope.engine->memoryManager->alloc<ArrayBuffer>(scope.engine, byteLength));
+ if (scope.engine->hasException)
+ return Encode::undefined();
+
+ Scoped<TypedArray > array(scope, scope.engine->memoryManager->alloc<TypedArray>(scope.engine, that->d()->type));
+ array->d()->buffer = buffer->d();
+ array->d()->byteLength = byteLength;
+ array->d()->byteOffset = 0;
+
+ return array.asReturnedValue();
+ }
+ Scoped<TypedArray> typedArray(scope, callData->argument(0));
+ if (!!typedArray) {
+ // ECMA 6 22.2.1.2
+ Scoped<ArrayBuffer> buffer(scope, typedArray->d()->buffer);
+ uint srcElementSize = typedArray->d()->type->bytesPerElement;
+ uint destElementSize = operations[that->d()->type].bytesPerElement;
+ uint byteLength = typedArray->d()->byteLength;
+ uint destByteLength = byteLength*destElementSize/srcElementSize;
+
+ Scoped<ArrayBuffer> newBuffer(scope, scope.engine->memoryManager->alloc<ArrayBuffer>(scope.engine, destByteLength));
+ if (scope.engine->hasException)
+ return Encode::undefined();
+
+ Scoped<TypedArray > array(scope, scope.engine->memoryManager->alloc<TypedArray>(scope.engine, that->d()->type));
+ array->d()->buffer = newBuffer->d();
+ array->d()->byteLength = destByteLength;
+ array->d()->byteOffset = 0;
+
+ const char *src = buffer->d()->data->data() + typedArray->d()->byteOffset;
+ char *dest = newBuffer->d()->data->data();
+
+ // check if src and new type have the same size. In that case we can simply memcpy the data
+ if (srcElementSize == destElementSize) {
+ memcpy(dest, src, byteLength);
+ } else {
+ // not same size, we need to loop
+ uint l = typedArray->length();
+ TypedArrayRead read = typedArray->d()->type->read;
+ TypedArrayWrite write =array->d()->type->write;
+ for (uint i = 0; i < l; ++i) {
+ Primitive val;
+ val.val = read(src, i*srcElementSize);
+ write(scope.engine, dest, i*destElementSize, val);
+ }
+ }
+
+ return array.asReturnedValue();
+ }
+ Scoped<ArrayBuffer> buffer(scope, callData->argument(0));
+ if (!!buffer) {
+ // ECMA 6 22.2.1.4
+
+ double dbyteOffset = callData->argc > 1 ? callData->args[1].toInteger() : 0;
+ uint byteOffset = (uint)dbyteOffset;
+ uint elementSize = operations[that->d()->type].bytesPerElement;
+ if (dbyteOffset < 0 || (byteOffset % elementSize) || dbyteOffset > buffer->byteLength())
+ return scope.engine->throwRangeError(QStringLiteral("new TypedArray: invalid byteOffset"));
+
+ uint byteLength;
+ if (callData->argc < 3 || callData->args[2].isUndefined()) {
+ byteLength = buffer->byteLength() - byteOffset;
+ if (buffer->byteLength() < byteOffset || byteLength % elementSize)
+ return scope.engine->throwRangeError(QStringLiteral("new TypedArray: invalid length"));
+ } else {
+ double l = qBound(0., callData->args[2].toInteger(), (double)UINT_MAX);
+ if (scope.engine->hasException)
+ return Encode::undefined();
+ l *= elementSize;
+ if (buffer->byteLength() - byteOffset < l)
+ return scope.engine->throwRangeError(QStringLiteral("new TypedArray: invalid length"));
+ byteLength = (uint)l;
+ }
+
+ Scoped<TypedArray > array(scope, scope.engine->memoryManager->alloc<TypedArray>(scope.engine, that->d()->type));
+ array->d()->buffer = buffer->d();
+ array->d()->byteLength = byteLength;
+ array->d()->byteOffset = byteOffset;
+ return array.asReturnedValue();
+ }
+
+ // ECMA 6 22.2.1.3
+
+ ScopedObject o(scope, callData->argument(0));
+ uint l = (uint) qBound(0., ScopedValue(scope, o->get(scope.engine->id_length))->toInteger(), (double)UINT_MAX);
+ if (scope.engine->hasException)
+ return scope.engine->throwTypeError();
+
+ uint elementSize = operations[that->d()->type].bytesPerElement;
+ Scoped<ArrayBuffer> newBuffer(scope, scope.engine->memoryManager->alloc<ArrayBuffer>(scope.engine, l * elementSize));
+ if (scope.engine->hasException)
+ return Encode::undefined();
+
+ Scoped<TypedArray > array(scope, scope.engine->memoryManager->alloc<TypedArray>(scope.engine, that->d()->type));
+ array->d()->buffer = newBuffer->d();
+ array->d()->byteLength = l * elementSize;
+ array->d()->byteOffset = 0;
+
+ uint idx = 0;
+ char *b = newBuffer->d()->data->data();
+ ScopedValue val(scope);
+ while (idx < l) {
+ val = o->getIndexed(idx);
+ array->d()->type->write(scope.engine, b, 0, val);
+ if (scope.engine->hasException)
+ return Encode::undefined();
+ ++idx;
+ b += elementSize;
+ }
+
+
+ return array.asReturnedValue();
+}
+
+ReturnedValue TypedArrayCtor::call(Managed *that, CallData *callData)
+{
+ return construct(that, callData);
+}
+
+Heap::TypedArray::TypedArray(ExecutionEngine *e, Type t)
+ : Heap::Object(e->typedArrayClasses[t], e->typedArrayPrototype[t].asObject()),
+ type(operations + t)
+{
+}
+
+void TypedArray::markObjects(Heap::Base *that, ExecutionEngine *e)
+{
+ static_cast<TypedArray::Data *>(that)->buffer->mark(e);
+ Object::markObjects(that, e);
+}
+
+ReturnedValue TypedArray::getIndexed(Managed *m, uint index, bool *hasProperty)
+{
+ Scope scope(m->engine());
+ Scoped<TypedArray> a(scope, static_cast<TypedArray *>(m));
+
+ uint bytesPerElement = a->d()->type->bytesPerElement;
+ uint byteOffset = a->d()->byteOffset + index * bytesPerElement;
+ if (byteOffset + bytesPerElement > (uint)a->d()->buffer->byteLength()) {
+ if (hasProperty)
+ *hasProperty = false;
+ return Encode::undefined();
+ }
+ if (hasProperty)
+ *hasProperty = true;
+ return a->d()->type->read(a->d()->buffer->data->data(), byteOffset);
+}
+
+void TypedArray::putIndexed(Managed *m, uint index, const ValueRef value)
+{
+ if (m->engine()->hasException)
+ return;
+
+ Scope scope(m->engine());
+ Scoped<TypedArray> a(scope, static_cast<TypedArray *>(m));
+
+ uint bytesPerElement = a->d()->type->bytesPerElement;
+ uint byteOffset = a->d()->byteOffset + index * bytesPerElement;
+ if (byteOffset + bytesPerElement > (uint)a->d()->buffer->byteLength())
+ goto reject;
+
+ a->d()->type->write(scope.engine, a->d()->buffer->data->data(), byteOffset, value);
+ return;
+
+reject:
+ if (scope.engine->currentContext()->strictMode)
+ scope.engine->throwTypeError();
+}
+
+void TypedArrayPrototype::init(ExecutionEngine *engine, TypedArrayCtor *ctor)
+{
+ Scope scope(engine);
+ ScopedObject o(scope);
+ ctor->defineReadonlyProperty(engine->id_length, Primitive::fromInt32(3));
+ ctor->defineReadonlyProperty(engine->id_prototype, (o = this));
+ ctor->defineReadonlyProperty(QStringLiteral("BYTES_PER_ELEMENT"), Primitive::fromInt32(operations[ctor->d()->type].bytesPerElement));
+ defineDefaultProperty(engine->id_constructor, (o = ctor));
+ defineAccessorProperty(QStringLiteral("buffer"), method_get_buffer, 0);
+ defineAccessorProperty(QStringLiteral("byteLength"), method_get_byteLength, 0);
+ defineAccessorProperty(QStringLiteral("byteOffset"), method_get_byteOffset, 0);
+ defineAccessorProperty(QStringLiteral("length"), method_get_length, 0);
+ defineReadonlyProperty(QStringLiteral("BYTES_PER_ELEMENT"), Primitive::fromInt32(operations[ctor->d()->type].bytesPerElement));
+
+ defineDefaultProperty(QStringLiteral("set"), method_set, 1);
+ defineDefaultProperty(QStringLiteral("subarray"), method_subarray, 0);
+}
+
+ReturnedValue TypedArrayPrototype::method_get_buffer(CallContext *ctx)
+{
+ Scope scope(ctx);
+ Scoped<TypedArray> v(scope, ctx->d()->callData->thisObject);
+ if (!v)
+ return scope.engine->throwTypeError();
+
+ return Encode(v->d()->buffer->asReturnedValue());
+}
+
+ReturnedValue TypedArrayPrototype::method_get_byteLength(CallContext *ctx)
+{
+ Scope scope(ctx);
+ Scoped<TypedArray> v(scope, ctx->d()->callData->thisObject);
+ if (!v)
+ return scope.engine->throwTypeError();
+
+ return Encode(v->d()->byteLength);
+}
+
+ReturnedValue TypedArrayPrototype::method_get_byteOffset(CallContext *ctx)
+{
+ Scope scope(ctx);
+ Scoped<TypedArray> v(scope, ctx->d()->callData->thisObject);
+ if (!v)
+ return scope.engine->throwTypeError();
+
+ return Encode(v->d()->byteOffset);
+}
+
+ReturnedValue TypedArrayPrototype::method_get_length(CallContext *ctx)
+{
+ Scope scope(ctx);
+ Scoped<TypedArray> v(scope, ctx->d()->callData->thisObject);
+ if (!v)
+ return scope.engine->throwTypeError();
+
+ return Encode(v->d()->byteLength/v->d()->type->bytesPerElement);
+}
+
+ReturnedValue TypedArrayPrototype::method_set(CallContext *ctx)
+{
+ Scope scope(ctx);
+ Scoped<TypedArray> a(scope, ctx->d()->callData->thisObject);
+ if (!a)
+ return scope.engine->throwTypeError();
+ Scoped<ArrayBuffer> buffer(scope, a->d()->buffer);
+ if (!buffer)
+ scope.engine->throwTypeError();
+
+ double doffset = ctx->d()->callData->argc >= 2 ? ctx->d()->callData->args[1].toInteger() : 0;
+ if (scope.engine->hasException)
+ return Encode::undefined();
+
+ if (doffset < 0 || doffset >= UINT_MAX)
+ return scope.engine->throwRangeError(QStringLiteral("TypedArray.set: out of range"));
+ uint offset = (uint)doffset;
+ uint elementSize = a->d()->type->bytesPerElement;
+
+ Scoped<TypedArray> srcTypedArray(scope, ctx->d()->callData->args[0]);
+ if (!srcTypedArray) {
+ // src is a regular object
+ ScopedObject o(scope, ctx->d()->callData->args[0].toObject(scope.engine));
+ if (scope.engine->hasException || !o)
+ return scope.engine->throwTypeError();
+
+ double len = ScopedValue(scope, o->get(scope.engine->id_length))->toNumber();
+ uint l = (uint)len;
+ if (scope.engine->hasException || l != len)
+ return scope.engine->throwTypeError();
+
+ if (offset + l > a->length())
+ return scope.engine->throwRangeError(QStringLiteral("TypedArray.set: out of range"));
+
+ uint idx = 0;
+ char *b = buffer->d()->data->data() + a->d()->byteOffset + offset*elementSize;
+ ScopedValue val(scope);
+ while (idx < l) {
+ val = o->getIndexed(idx);
+ a->d()->type->write(scope.engine, b, 0, val);
+ if (scope.engine->hasException)
+ return Encode::undefined();
+ ++idx;
+ b += elementSize;
+ }
+ return Encode::undefined();
+ }
+
+ // src is a typed array
+ Scoped<ArrayBuffer> srcBuffer(scope, srcTypedArray->d()->buffer);
+ if (!srcBuffer)
+ return scope.engine->throwTypeError();
+
+ uint l = srcTypedArray->length();
+ if (offset + l > a->length())
+ return scope.engine->throwRangeError(QStringLiteral("TypedArray.set: out of range"));
+
+ char *dest = buffer->d()->data->data() + a->d()->byteOffset + offset*elementSize;
+ const char *src = srcBuffer->d()->data->data() + srcTypedArray->d()->byteOffset;
+ if (srcTypedArray->d()->type == a->d()->type) {
+ // same type of typed arrays, use memmove (as srcbuffer and buffer could be the same)
+ memmove(dest, src, srcTypedArray->d()->byteLength);
+ return Encode::undefined();
+ }
+
+ char *srcCopy = 0;
+ if (buffer->d() == srcBuffer->d()) {
+ // same buffer, need to take a temporary copy, to not run into problems
+ srcCopy = new char[srcTypedArray->d()->byteLength];
+ memcpy(srcCopy, src, srcTypedArray->d()->byteLength);
+ src = srcCopy;
+ }
+
+ // typed arrays of different kind, need to manually loop
+ uint srcElementSize = srcTypedArray->d()->type->bytesPerElement;
+ TypedArrayRead read = srcTypedArray->d()->type->read;
+ TypedArrayWrite write = a->d()->type->write;
+ for (uint i = 0; i < l; ++i) {
+ Primitive val;
+ val.val = read(src, i*srcElementSize);
+ write(scope.engine, dest, i*elementSize, val);
+ }
+
+ if (srcCopy)
+ delete [] srcCopy;
+
+ return Encode::undefined();
+}
+
+ReturnedValue TypedArrayPrototype::method_subarray(CallContext *ctx)
+{
+ Scope scope(ctx);
+ Scoped<TypedArray> a(scope, ctx->d()->callData->thisObject);
+
+ if (!a)
+ return scope.engine->throwTypeError();
+
+ Scoped<ArrayBuffer> buffer(scope, a->d()->buffer);
+ if (!buffer)
+ return scope.engine->throwTypeError();
+
+ int len = a->length();
+ double b = ctx->d()->callData->argc > 0 ? ctx->d()->callData->args[0].toInteger() : 0;
+ if (b < 0)
+ b = len + b;
+ uint begin = (uint)qBound(0., b, (double)len);
+
+ double e = ctx->d()->callData->argc < 2 || ctx->d()->callData->args[1].isUndefined() ? len : ctx->d()->callData->args[1].toInteger();
+ if (e < 0)
+ e = len + e;
+ uint end = (uint)qBound(0., e, (double)len);
+ if (end < begin)
+ end = begin;
+
+ if (scope.engine->hasException)
+ return Encode::undefined();
+
+ int newLen = end - begin;
+
+ ScopedFunctionObject constructor(scope, a->get(scope.engine->id_constructor));
+ if (!constructor)
+ return scope.engine->throwTypeError();
+
+ ScopedCallData callData(scope, 3);
+ callData->args[0] = buffer;
+ callData->args[1] = Encode(a->d()->byteOffset + begin*a->d()->type->bytesPerElement);
+ callData->args[2] = Encode(newLen);
+ return constructor->construct(callData);
+}
diff --git a/src/qml/jsruntime/qv4typedarray_p.h b/src/qml/jsruntime/qv4typedarray_p.h
new file mode 100644
index 0000000000..adc3368243
--- /dev/null
+++ b/src/qml/jsruntime/qv4typedarray_p.h
@@ -0,0 +1,143 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QV4TYPEDARRAY_H
+#define QV4TYPEDARRAY_H
+
+#include "qv4object_p.h"
+#include "qv4functionobject_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace QV4 {
+
+struct ArrayBuffer;
+
+typedef ReturnedValue (*TypedArrayRead)(const char *data, int index);
+typedef void (*TypedArrayWrite)(ExecutionEngine *engine, char *data, int index, ValueRef value);
+
+struct TypedArrayOperations {
+ int bytesPerElement;
+ const char *name;
+ TypedArrayRead read;
+ TypedArrayWrite write;
+};
+
+namespace Heap {
+
+struct TypedArray : Object {
+ enum Type {
+ Int8Array,
+ UInt8Array,
+ UInt8ClampedArray,
+ Int16Array,
+ UInt16Array,
+ Int32Array,
+ UInt32Array,
+ Float32Array,
+ Float64Array,
+ NTypes
+ };
+
+ TypedArray(ExecutionEngine *e, Type t);
+
+ const TypedArrayOperations *type;
+ ArrayBuffer *buffer;
+ uint byteLength;
+ uint byteOffset;
+};
+
+struct TypedArrayCtor : FunctionObject {
+ TypedArrayCtor(QV4::ExecutionContext *scope, TypedArray::Type t);
+
+ TypedArray::Type type;
+};
+
+struct TypedArrayPrototype : Object {
+ inline TypedArrayPrototype(ExecutionEngine *e, TypedArray::Type t);
+ TypedArray::Type type;
+};
+
+
+}
+
+struct TypedArray : Object
+{
+ V4_OBJECT2(TypedArray, Object)
+
+ uint length() const {
+ return d()->byteLength/d()->type->bytesPerElement;
+ }
+
+
+ static void markObjects(Heap::Base *that, ExecutionEngine *e);
+ static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty);
+ static void putIndexed(Managed *m, uint index, const ValueRef value);
+};
+
+struct TypedArrayCtor: FunctionObject
+{
+ V4_OBJECT2(TypedArrayCtor, FunctionObject)
+
+ static ReturnedValue construct(Managed *m, CallData *callData);
+ static ReturnedValue call(Managed *that, CallData *callData);
+};
+
+
+struct TypedArrayPrototype : Object
+{
+ V4_OBJECT2(TypedArrayPrototype, Object)
+
+ void init(ExecutionEngine *engine, TypedArrayCtor *ctor);
+
+ static ReturnedValue method_get_buffer(CallContext *ctx);
+ static ReturnedValue method_get_byteLength(CallContext *ctx);
+ static ReturnedValue method_get_byteOffset(CallContext *ctx);
+ static ReturnedValue method_get_length(CallContext *ctx);
+
+ static ReturnedValue method_set(CallContext *ctx);
+ static ReturnedValue method_subarray(CallContext *ctx);
+};
+
+inline
+Heap::TypedArrayPrototype::TypedArrayPrototype(ExecutionEngine *e, TypedArray::Type t)
+ : Heap::Object(e)
+ , type(t)
+{
+ setVTable(QV4::TypedArrayPrototype::staticVTable());
+}
+
+} // namespace QV4
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/qml/jsruntime/qv4value.cpp b/src/qml/jsruntime/qv4value.cpp
index 0293054457..d1289bba7f 100644
--- a/src/qml/jsruntime/qv4value.cpp
+++ b/src/qml/jsruntime/qv4value.cpp
@@ -31,6 +31,7 @@
**
****************************************************************************/
#include <qv4engine_p.h>
+#include <qv4runtime_p.h>
#ifndef V4_BOOTSTRAP
#include <qv4object_p.h>
#include <qv4objectproto_p.h>
@@ -87,9 +88,10 @@ double Value::toNumberImpl() const
if (isString())
return RuntimeHelpers::stringToNumber(stringValue()->toQString());
{
- ExecutionContext *ctx = objectValue()->internalClass()->engine->currentContext();
- Scope scope(ctx);
+ Scope scope(managed()->engine());
ScopedValue prim(scope, RuntimeHelpers::toPrimitive(ValueRef::fromRawValue(this), NUMBER_HINT));
+ if (scope.engine->hasException)
+ return 0;
return prim->toNumber();
}
#endif
@@ -121,13 +123,12 @@ QString Value::toQStringNoThrow() const
if (isString())
return stringValue()->toQString();
{
- ExecutionContext *ctx = objectValue()->internalClass()->engine->currentContext();
- Scope scope(ctx);
+ Scope scope(managed()->engine());
ScopedValue ex(scope);
bool caughtException = false;
ScopedValue prim(scope, RuntimeHelpers::toPrimitive(ValueRef::fromRawValue(this), STRING_HINT));
if (scope.hasException()) {
- ex = ctx->catchException();
+ ex = scope.engine->catchException();
caughtException = true;
} else if (prim->isPrimitive()) {
return prim->toQStringNoThrow();
@@ -136,7 +137,7 @@ QString Value::toQStringNoThrow() const
if (caughtException) {
ScopedValue prim(scope, RuntimeHelpers::toPrimitive(ex, STRING_HINT));
if (scope.hasException()) {
- ex = ctx->catchException();
+ ex = scope.engine->catchException();
} else if (prim->isPrimitive()) {
return prim->toQStringNoThrow();
}
@@ -174,8 +175,7 @@ QString Value::toQString() const
if (isString())
return stringValue()->toQString();
{
- ExecutionContext *ctx = objectValue()->internalClass()->engine->currentContext();
- Scope scope(ctx);
+ Scope scope(managed()->engine());
ScopedValue prim(scope, RuntimeHelpers::toPrimitive(ValueRef::fromRawValue(this), STRING_HINT));
return prim->toQString();
}
@@ -264,23 +264,18 @@ double Primitive::toInteger(double number)
}
#ifndef V4_BOOTSTRAP
-String *Value::toString(ExecutionEngine *e) const
-{
- return toString(e->currentContext());
-}
-
-String *Value::toString(ExecutionContext *ctx) const
+Heap::String *Value::toString(ExecutionEngine *e) const
{
if (isString())
- return stringValue();
- return RuntimeHelpers::convertToString(ctx, ValueRef::fromRawValue(this))->getPointer();
+ return stringValue()->d();
+ return RuntimeHelpers::convertToString(e, ValueRef::fromRawValue(this));
}
-Object *Value::toObject(ExecutionContext *ctx) const
+Heap::Object *Value::toObject(ExecutionEngine *e) const
{
if (isObject())
- return objectValue();
- return RuntimeHelpers::convertToObject(ctx, ValueRef::fromRawValue(this))->getPointer();
+ return objectValue()->d();
+ return RuntimeHelpers::convertToObject(e, ValueRef::fromRawValue(this));
}
#endif // V4_BOOTSTRAP
diff --git a/src/qml/jsruntime/qv4value_inl_p.h b/src/qml/jsruntime/qv4value_inl_p.h
index 045eaccfaf..a551ac7e6b 100644
--- a/src/qml/jsruntime/qv4value_inl_p.h
+++ b/src/qml/jsruntime/qv4value_inl_p.h
@@ -35,18 +35,11 @@
#include <cmath> // this HAS to come
-#include <QtCore/QString>
-#include <QtCore/qnumeric.h>
-#include "qv4global_p.h"
+#include "qv4value_p.h"
+
#include "qv4string_p.h"
-#include <QtCore/QDebug>
#include "qv4managed_p.h"
#include "qv4engine_p.h"
-#include <private/qtqmlglobal_p.h>
-
-//#include <wtf/MathExtras.h>
-
-#include "qv4value_p.h"
QT_BEGIN_NAMESPACE
@@ -56,13 +49,13 @@ inline bool Value::isString() const
{
if (!isManaged())
return false;
- return managed() && managed()->internalClass()->vtable->isString;
+ return m && m->internalClass->vtable->isString;
}
inline bool Value::isObject() const
{
if (!isManaged())
return false;
- return managed() && managed()->internalClass()->vtable->isObject;
+ return m && m->internalClass->vtable->isObject;
}
inline bool Value::isPrimitive() const
@@ -70,10 +63,11 @@ inline bool Value::isPrimitive() const
return !isObject();
}
-inline ExecutionEngine *Value::engine() const
+inline String *Value::asString() const
{
- Managed *m = asManaged();
- return m ? m->engine() : 0;
+ if (isString())
+ return stringValue();
+ return 0;
}
inline void Value::mark(ExecutionEngine *e) const
@@ -275,6 +269,21 @@ inline ErrorObject *Value::asErrorObject() const
template<typename T>
inline T *Value::as() const { Managed *m = isObject() ? managed() : 0; return m ? m->as<T>() : 0; }
+#ifndef V4_BOOTSTRAP
+
+template<>
+inline String *value_cast(const Value &v) {
+ return v.asString();
+}
+
+template<>
+inline ReturnedValue value_convert<String>(ExecutionEngine *e, const Value &v)
+{
+ return v.toString(e)->asReturnedValue();
+}
+
+#endif
+
#endif
} // namespace QV4
diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h
index 59a4543538..8fff22ed86 100644
--- a/src/qml/jsruntime/qv4value_p.h
+++ b/src/qml/jsruntime/qv4value_p.h
@@ -44,19 +44,62 @@ namespace QV4 {
typedef uint Bool;
-template <typename T>
-struct Returned : private T
-{
- static Returned<T> *create(T *t) { return static_cast<Returned<T> *>(t); }
- T *getPointer() { return this; }
- template<typename X>
- static T *getPointer(Returned<X> *x) { return x->getPointer(); }
- template<typename X>
- Returned<X> *as() { return Returned<X>::create(Returned<X>::getPointer(this)); }
- using T::asReturnedValue;
+namespace Heap {
+
+struct Q_QML_EXPORT Base {
+ Base() {}
+ Base(InternalClass *internal)
+ : internalClass(internal)
+ {
+ Q_ASSERT(inUse() && !isMarked());
+ // ####
+ // Q_ASSERT(internal && internal->vtable);
+ }
+ union {
+ InternalClass *internalClass;
+ quintptr mm_data;
+ };
+
+ void setVTable(const ManagedVTable *vt);
+ inline ReturnedValue asReturnedValue() const;
+ inline void mark(QV4::ExecutionEngine *engine);
+
+ enum {
+ MarkBit = 0x1,
+ NotInUse = 0x2,
+ PointerMask = ~0x3
+ };
+
+ InternalClass *gcGetInternalClass() const {
+ return reinterpret_cast<InternalClass *>(mm_data & PointerMask);
+ }
+ inline bool isMarked() const {
+ return mm_data & MarkBit;
+ }
+ inline void setMarkBit() {
+ mm_data |= MarkBit;
+ }
+ inline void clearMarkBit() {
+ mm_data &= ~MarkBit;
+ }
+
+ inline bool inUse() const {
+ return !(mm_data & NotInUse);
+ }
+
+ Base *nextFree() {
+ return reinterpret_cast<Base *>(mm_data & PointerMask);
+ }
+ void setNextFree(Base *m) {
+ mm_data = (reinterpret_cast<quintptr>(m) | NotInUse);
+ }
+
+ void *operator new(size_t, Managed *m) { return m; }
+ void *operator new(size_t, Heap::Base *m) { return m; }
+ void operator delete(void *, Heap::Base *) {}
};
-struct HeapObject {};
+}
struct Q_QML_PRIVATE_EXPORT Value
{
@@ -86,9 +129,7 @@ struct Q_QML_PRIVATE_EXPORT Value
union {
quint64 val;
#if QT_POINTER_SIZE == 8
- Managed *m;
- Object *o;
- String *s;
+ Heap::Base *m;
#else
double dbl;
#endif
@@ -100,9 +141,7 @@ struct Q_QML_PRIVATE_EXPORT Value
uint uint_32;
int int_32;
#if QT_POINTER_SIZE == 4
- Managed *m;
- Object *o;
- String *s;
+ Heap::Base *m;
#endif
};
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
@@ -222,7 +261,7 @@ struct Q_QML_PRIVATE_EXPORT Value
val = v.i ^ NaNEncodeMask;
Q_ASSERT(isDouble());
}
- bool isNaN() const { return (tag & 0x7fff8000) == 0x00078000; }
+ inline bool isNaN() const { return (tag & 0x7fff8000) == 0x00078000; }
#else
inline bool isInteger() const { return tag == _Integer_Type; }
inline bool isDouble() const { return (tag & NotDouble_Mask) != NotDouble_Mask; }
@@ -238,7 +277,7 @@ struct Q_QML_PRIVATE_EXPORT Value
}
double doubleValue() const { Q_ASSERT(isDouble()); return dbl; }
void setDouble(double d) { dbl = d; Q_ASSERT(isDouble()); }
- bool isNaN() const { return (tag & QV4::Value::NotDouble_Mask) == QV4::Value::NaN_Mask; }
+ inline bool isNaN() const { return (tag & QV4::Value::NotDouble_Mask) == QV4::Value::NaN_Mask; }
#endif
inline bool isString() const;
inline bool isObject() const;
@@ -270,12 +309,15 @@ struct Q_QML_PRIVATE_EXPORT Value
}
String *stringValue() const {
- return s;
+ return m ? reinterpret_cast<String*>(const_cast<Value *>(this)) : 0;
}
Object *objectValue() const {
- return o;
+ return m ? reinterpret_cast<Object*>(const_cast<Value *>(this)) : 0;
}
Managed *managed() const {
+ return m ? reinterpret_cast<Managed*>(const_cast<Value *>(this)) : 0;
+ }
+ Heap::Base *heapObject() const {
return m;
}
@@ -283,7 +325,17 @@ struct Q_QML_PRIVATE_EXPORT Value
return val;
}
- static inline Value fromManaged(Managed *o);
+ static inline Value fromHeapObject(Heap::Base *m)
+ {
+ Value v;
+ v.m = m;
+#if QT_POINTER_SIZE == 4
+ v.tag = Managed_Type;
+#endif
+ return v;
+ }
+
+ static inline Value fromManaged(Managed *m);
int toUInt16() const;
inline int toInt32() const;
@@ -295,9 +347,8 @@ struct Q_QML_PRIVATE_EXPORT Value
double toNumberImpl() const;
QString toQStringNoThrow() const;
QString toQString() const;
- String *toString(ExecutionEngine *e) const;
- String *toString(ExecutionContext *ctx) const;
- Object *toObject(ExecutionContext *ctx) const;
+ Heap::String *toString(ExecutionEngine *e) const;
+ Heap::Object *toObject(ExecutionEngine *e) const;
inline bool isPrimitive() const;
inline bool tryIntegerConversion() {
@@ -318,12 +369,16 @@ struct Q_QML_PRIVATE_EXPORT Value
inline ErrorObject *asErrorObject() const;
template<typename T> inline T *as() const;
+ template<typename T> inline T *cast() {
+ return static_cast<T *>(managed());
+ }
+ template<typename T> inline const T *cast() const {
+ return static_cast<const T *>(managed());
+ }
inline uint asArrayIndex() const;
inline uint asArrayLength(bool *ok) const;
- inline ExecutionEngine *engine() const;
-
ReturnedValue asReturnedValue() const { return val; }
static Value fromReturnedValue(ReturnedValue val) { Value v; v.val = val; return v; }
@@ -334,15 +389,15 @@ struct Q_QML_PRIVATE_EXPORT Value
Value &operator =(const ScopedValue &v);
Value &operator=(ReturnedValue v) { val = v; return *this; }
- template<typename T>
- Value &operator=(Returned<T> *t);
- template<typename T>
- Value &operator=(T *t) {
- val = Value::fromManaged(t).val;
+ Value &operator=(Managed *m) {
+ val = Value::fromManaged(m).val;
return *this;
}
- Value &operator=(HeapObject *o) {
- m = reinterpret_cast<Managed *>(o);
+ Value &operator=(Heap::Base *o) {
+ m = o;
+#if QT_POINTER_SIZE == 4
+ tag = Managed_Type;
+#endif
return *this;
}
@@ -353,8 +408,6 @@ struct Q_QML_PRIVATE_EXPORT Value
val = v.val;
return *this;
}
- template<typename T>
- inline Returned<T> *as();
};
inline Managed *Value::asManaged() const
@@ -364,13 +417,6 @@ inline Managed *Value::asManaged() const
return 0;
}
-inline String *Value::asString() const
-{
- if (isString())
- return stringValue();
- return 0;
-}
-
struct Q_QML_PRIVATE_EXPORT Primitive : public Value
{
inline static Primitive emptyValue();
@@ -409,20 +455,6 @@ inline Primitive Primitive::emptyValue()
return v;
}
-inline Value Value::fromManaged(Managed *m)
-{
- if (!m)
- return QV4::Primitive::undefinedValue();
- Value v;
-#if QT_POINTER_SIZE == 8
- v.m = m;
-#else
- v.tag = Managed_Type;
- v.m = m;
-#endif
- return v;
-}
-
template <typename T>
struct TypedValue : public Value
{
@@ -432,11 +464,11 @@ struct TypedValue : public Value
#if QT_POINTER_SIZE == 4
tag = Managed_Type;
#endif
+ return *this;
}
TypedValue &operator =(T *t);
TypedValue &operator =(const Scoped<T> &v);
// TypedValue &operator =(const ManagedRef<T> &v);
- TypedValue &operator =(Returned<T> *t);
TypedValue &operator =(const TypedValue<T> &t);
@@ -446,7 +478,6 @@ struct TypedValue : public Value
T *operator->() { return static_cast<T *>(managed()); }
const T *operator->() const { return static_cast<T *>(managed()); }
T *getPointer() const { return static_cast<T *>(managed()); }
- Returned<T> *ret() const;
void mark(ExecutionEngine *e) { if (managed()) managed()->mark(e); }
};
@@ -485,9 +516,9 @@ struct Encode {
val = v;
}
- template<typename T>
- Encode(Returned<T> *t) {
- val = t->getPointer()->asReturnedValue();
+ Encode(Heap::Base *o) {
+ Q_ASSERT(o);
+ val = Value::fromHeapObject(o).asReturnedValue();
}
operator ReturnedValue() const {
@@ -516,11 +547,6 @@ struct ValueRef {
ptr->val = v;
return *this;
}
- template <typename T>
- ValueRef &operator=(Returned<T> *v) {
- ptr->val = v->asReturnedValue();
- return *this;
- }
operator const Value *() const {
return ptr;
@@ -546,11 +572,22 @@ struct ValueRef {
ReturnedValue asReturnedValue() const { return ptr->val; }
// ### get rid of this one!
- ValueRef(Value *v) { ptr = reinterpret_cast<Value *>(v); }
+ ValueRef(Value *v) { ptr = v; }
private:
Value *ptr;
};
+inline Primitive::operator ValueRef()
+{
+ return ValueRef(this);
+}
+
+inline
+ReturnedValue Heap::Base::asReturnedValue() const
+{
+ return Value::fromHeapObject(const_cast<Heap::Base *>(this)).asReturnedValue();
+}
+
template<typename T>
T *value_cast(const Value &v)
@@ -561,8 +598,6 @@ T *value_cast(const Value &v)
template<typename T>
ReturnedValue value_convert(ExecutionEngine *e, const Value &v);
-
-
}
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4variantobject.cpp b/src/qml/jsruntime/qv4variantobject.cpp
index 3cde96992e..5397b96c73 100644
--- a/src/qml/jsruntime/qv4variantobject.cpp
+++ b/src/qml/jsruntime/qv4variantobject.cpp
@@ -43,53 +43,20 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(VariantObject);
-VariantObject::Data::Data(InternalClass *ic)
- : Object::Data(ic)
-{
-}
-
-VariantObject::Data::Data(ExecutionEngine *engine, const QVariant &value)
- : Object::Data(engine->variantClass)
+Heap::VariantObject::VariantObject(QV4::ExecutionEngine *engine, const QVariant &value)
+ : Heap::Object(engine->variantClass, engine->variantPrototype.asObject())
{
data = value;
if (isScarce())
engine->scarceResources.insert(this);
}
-QVariant VariantObject::toVariant(const QV4::ValueRef v)
-{
- if (v->asObject())
- return v->engine()->v8Engine->toVariant(v, /*typeHint*/ -1, /*createJSValueForObjects*/ false);
-
- if (v->isString())
- return QVariant(v->stringValue()->toQString());
- if (v->isBoolean())
- return QVariant(v->booleanValue());
- if (v->isNumber()) {
- QV4::Value val;
- val = v;
- if (val.isInt32())
- return QVariant(val.integerValue());
- return QVariant(v->asDouble());
- }
- if (v->isNull())
- return QVariant(QMetaType::VoidStar, 0);
- Q_ASSERT(v->isUndefined());
- return QVariant();
-}
-
bool VariantObject::Data::isScarce() const
{
QVariant::Type t = data.type();
return t == QVariant::Pixmap || t == QVariant::Image;
}
-void VariantObject::destroy(Managed *that)
-{
- VariantObject *v = static_cast<VariantObject *>(that);
- v->d()->~Data();
-}
-
bool VariantObject::isEqualTo(Managed *m, Managed *other)
{
Q_ASSERT(m->as<QV4::VariantObject>());
@@ -98,7 +65,7 @@ bool VariantObject::isEqualTo(Managed *m, Managed *other)
if (QV4::VariantObject *rv = other->as<QV4::VariantObject>())
return lv->d()->data == rv->d()->data;
- if (QV4::QmlValueTypeWrapper *v = other->as<QmlValueTypeWrapper>())
+ if (QV4::QQmlValueTypeWrapper *v = other->as<QQmlValueTypeWrapper>())
return v->isEqual(lv->d()->data);
return false;
@@ -185,6 +152,8 @@ QV4::ReturnedValue VariantPrototype::method_valueOf(CallContext *ctx)
case QVariant::Bool:
return Encode(v.toBool());
default:
+ if (QMetaType::typeFlags(v.userType()) & QMetaType::IsEnumeration)
+ return Encode(v.toInt());
break;
}
}
diff --git a/src/qml/jsruntime/qv4variantobject_p.h b/src/qml/jsruntime/qv4variantobject_p.h
index ef7554d7ab..a7a4209913 100644
--- a/src/qml/jsruntime/qv4variantobject_p.h
+++ b/src/qml/jsruntime/qv4variantobject_p.h
@@ -56,27 +56,32 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
+namespace Heap {
+
+struct VariantObject : Object, public ExecutionEngine::ScarceResourceData
+{
+ VariantObject(InternalClass *ic, QV4::Object *prototype)
+ : Object(ic, prototype)
+ {}
+ VariantObject(QV4::ExecutionEngine *engine, const QVariant &value);
+ ~VariantObject() {
+ if (isScarce())
+ node.remove();
+ }
+ bool isScarce() const;
+ int vmePropertyReferenceCount;
+};
+
+}
+
struct VariantObject : Object
{
- struct Data : Object::Data, public ExecutionEngine::ScarceResourceData
- {
- Data(InternalClass *ic);
- Data(ExecutionEngine *engine, const QVariant &value);
- ~Data() {
- if (isScarce())
- node.remove();
- }
- bool isScarce() const;
- int vmePropertyReferenceCount;
- };
- V4_OBJECT(Object)
-
- static QVariant toVariant(const ValueRef v);
+ V4_OBJECT2(VariantObject, Object)
+ V4_NEEDS_DESTROY
void addVmePropertyReference();
void removeVmePropertyReference();
- static void destroy(Managed *that);
static bool isEqualTo(Managed *m, Managed *other);
};
diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index cd73314bce..e86c673bf1 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -42,9 +42,11 @@
#include "qv4alloca_p.h"
+#undef DO_TRACE_INSTR // define to enable instruction tracing
+
#ifdef DO_TRACE_INSTR
-# define TRACE_INSTR(I) fprintf(stderr, "executing a %s\n", #I);
-# define TRACE(n, str, ...) { char buf[4096]; snprintf(buf, 4096, str, __VA_ARGS__); fprintf(stderr, " %s : %s\n", #n, buf); }
+# define TRACE_INSTR(I) qDebug("executing a %s\n", #I);
+# define TRACE(n, str, ...) { char buf[4096]; snprintf(buf, 4096, str, __VA_ARGS__); qDebug(" %s : %s", #n, buf); }
#else
# define TRACE_INSTR(I)
# define TRACE(n, str, ...)
@@ -79,59 +81,23 @@ using namespace QV4::Moth;
#endif
-#ifdef WITH_STATS
-namespace {
-struct VMStats {
- quint64 paramIsValue;
- quint64 paramIsArg;
- quint64 paramIsLocal;
- quint64 paramIsTemp;
- quint64 paramIsScopedLocal;
-
- VMStats()
- : paramIsValue(0)
- , paramIsArg(0)
- , paramIsLocal(0)
- , paramIsTemp(0)
- , paramIsScopedLocal(0)
- {}
-
- ~VMStats()
- { show(); }
-
- void show() {
- fprintf(stderr, "VM stats:\n");
- fprintf(stderr, " value: %lu\n", paramIsValue);
- fprintf(stderr, " arg: %lu\n", paramIsArg);
- fprintf(stderr, " local: %lu\n", paramIsLocal);
- fprintf(stderr, " temp: %lu\n", paramIsTemp);
- fprintf(stderr, " scoped local: %lu\n", paramIsScopedLocal);
- }
-};
-static VMStats vmStats;
-#define VMSTATS(what) ++vmStats.what
-}
-#else // !WITH_STATS
-#define VMSTATS(what) {}
-#endif // WITH_STATS
-
#ifdef DO_TRACE_INSTR
Param traceParam(const Param &param)
{
if (param.isConstant()) {
- fprintf(stderr, " constant\n");
+ qDebug(" constant\n");
} else if (param.isArgument()) {
- fprintf(stderr, " argument %d@%d\n", param.index, param.scope);
+ qDebug(" argument %d@%d\n", param.index, param.scope);
} else if (param.isLocal()) {
- fprintf(stderr, " local %d\n", param.index);
+ qDebug(" local %d\n", param.index);
} else if (param.isTemp()) {
- fprintf(stderr, " temp %d\n", param.index);
+ qDebug(" temp %d\n", param.index);
} else if (param.isScopedLocal()) {
- fprintf(stderr, " temp %d@%d\n", param.index, param.scope);
+ qDebug(" temp %d@%d\n", param.index, param.scope);
} else {
Q_ASSERT(!"INVALID");
}
- return Param
+ return param;
}
# define VALUE(param) (*VALUEPTR(param))
# define VALUEPTR(param) (scopes[traceParam(param).scope] + param.index)
@@ -150,7 +116,7 @@ Param traceParam(const Param &param)
if (engine->hasException) \
goto catchException
-QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code
+QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
#ifdef MOTH_THREADED_INTERPRETER
, void ***storeJumpTable
#endif
@@ -177,22 +143,21 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code
const uchar *exceptionHandler = 0;
- context->d()->lineNumber = -1;
- QV4::ExecutionEngine *engine = context->d()->engine;
+ QV4::Scope scope(engine);
+ QV4::ScopedContext context(scope, engine->currentContext());
+ engine->currentContext()->lineNumber = -1;
#ifdef DO_TRACE_INSTR
qDebug("Starting VME with context=%p and code=%p", context, code);
#endif // DO_TRACE_INSTR
- QV4::StringValue * const runtimeStrings = context->d()->compilationUnit->runtimeStrings;
-
// setup lookup scopes
int scopeDepth = 0;
{
- QV4::ExecutionContext *scope = context;
+ QV4::Heap::ExecutionContext *scope = context->d();
while (scope) {
++scopeDepth;
- scope = scope->d()->outer;
+ scope = scope->outer;
}
}
@@ -201,19 +166,19 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code
scopes[0] = const_cast<QV4::Value *>(context->d()->compilationUnit->data->constants());
// stack gets setup in push instruction
scopes[1] = 0;
- QV4::ExecutionContext *scope = context;
+ QV4::Heap::ExecutionContext *scope = context->d();
int i = 0;
while (scope) {
- if (scope->d()->type >= QV4::ExecutionContext::Type_SimpleCallContext) {
- QV4::CallContext *cc = static_cast<QV4::CallContext *>(scope);
- scopes[2*i + 2] = cc->d()->callData->args;
- scopes[2*i + 3] = cc->d()->locals;
+ if (scope->type >= QV4::Heap::ExecutionContext::Type_SimpleCallContext) {
+ QV4::Heap::CallContext *cc = static_cast<QV4::Heap::CallContext *>(scope);
+ scopes[2*i + 2] = cc->callData->args;
+ scopes[2*i + 3] = cc->locals;
} else {
scopes[2*i + 2] = 0;
scopes[2*i + 3] = 0;
}
++i;
- scope = scope->d()->outer;
+ scope = scope->outer;
}
}
@@ -240,7 +205,7 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code
MOTH_BEGIN_INSTR(LoadRuntimeString)
// TRACE(value, "%s", instr.value.toString(context)->toQString().toUtf8().constData());
- VALUE(instr.result) = runtimeStrings[instr.stringId].asReturnedValue();
+ VALUE(instr.result) = context->d()->compilationUnit->runtimeStrings[instr.stringId];
MOTH_END_INSTR(LoadRuntimeString)
MOTH_BEGIN_INSTR(LoadRegExp)
@@ -249,28 +214,27 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code
MOTH_END_INSTR(LoadRegExp)
MOTH_BEGIN_INSTR(LoadClosure)
- STOREVALUE(instr.result, Runtime::closure(context, instr.value));
+ STOREVALUE(instr.result, Runtime::closure(engine, instr.value));
MOTH_END_INSTR(LoadClosure)
MOTH_BEGIN_INSTR(LoadName)
TRACE(inline, "property name = %s", runtimeStrings[instr.name]->toQString().toUtf8().constData());
- STOREVALUE(instr.result, Runtime::getActivationProperty(context, runtimeStrings[instr.name]));
+ STOREVALUE(instr.result, Runtime::getActivationProperty(engine, instr.name));
MOTH_END_INSTR(LoadName)
MOTH_BEGIN_INSTR(GetGlobalLookup)
- TRACE(inline, "property name = %s", runtimeStrings[instr.name]->toQString().toUtf8().constData());
QV4::Lookup *l = context->d()->lookups + instr.index;
- STOREVALUE(instr.result, l->globalGetter(l, context));
+ STOREVALUE(instr.result, l->globalGetter(l, engine));
MOTH_END_INSTR(GetGlobalLookup)
MOTH_BEGIN_INSTR(StoreName)
TRACE(inline, "property name = %s", runtimeStrings[instr.name]->toQString().toUtf8().constData());
- Runtime::setActivationProperty(context, runtimeStrings[instr.name], VALUEPTR(instr.source));
+ Runtime::setActivationProperty(engine, instr.name, VALUEPTR(instr.source));
CHECK_EXCEPTION;
MOTH_END_INSTR(StoreName)
MOTH_BEGIN_INSTR(LoadElement)
- STOREVALUE(instr.result, Runtime::getElement(context, VALUEPTR(instr.base), VALUEPTR(instr.index)));
+ STOREVALUE(instr.result, Runtime::getElement(engine, VALUEPTR(instr.base), VALUEPTR(instr.index)));
MOTH_END_INSTR(LoadElement)
MOTH_BEGIN_INSTR(LoadElementLookup)
@@ -279,7 +243,7 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code
MOTH_END_INSTR(LoadElementLookup)
MOTH_BEGIN_INSTR(StoreElement)
- Runtime::setElement(context, VALUEPTR(instr.base), VALUEPTR(instr.index), VALUEPTR(instr.source));
+ Runtime::setElement(engine, VALUEPTR(instr.base), VALUEPTR(instr.index), VALUEPTR(instr.source));
CHECK_EXCEPTION;
MOTH_END_INSTR(StoreElement)
@@ -290,49 +254,46 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code
MOTH_END_INSTR(StoreElementLookup)
MOTH_BEGIN_INSTR(LoadProperty)
- STOREVALUE(instr.result, Runtime::getProperty(context, VALUEPTR(instr.base), runtimeStrings[instr.name]));
+ STOREVALUE(instr.result, Runtime::getProperty(engine, VALUEPTR(instr.base), instr.name));
MOTH_END_INSTR(LoadProperty)
MOTH_BEGIN_INSTR(GetLookup)
QV4::Lookup *l = context->d()->lookups + instr.index;
- STOREVALUE(instr.result, l->getter(l, VALUEPTR(instr.base)));
+ STOREVALUE(instr.result, l->getter(l, engine, VALUEPTR(instr.base)));
MOTH_END_INSTR(GetLookup)
MOTH_BEGIN_INSTR(StoreProperty)
- Runtime::setProperty(context, VALUEPTR(instr.base), runtimeStrings[instr.name], VALUEPTR(instr.source));
+ Runtime::setProperty(engine, VALUEPTR(instr.base), instr.name, VALUEPTR(instr.source));
CHECK_EXCEPTION;
MOTH_END_INSTR(StoreProperty)
MOTH_BEGIN_INSTR(SetLookup)
QV4::Lookup *l = context->d()->lookups + instr.index;
- l->setter(l, VALUEPTR(instr.base), VALUEPTR(instr.source));
+ l->setter(l, engine, VALUEPTR(instr.base), VALUEPTR(instr.source));
CHECK_EXCEPTION;
MOTH_END_INSTR(SetLookup)
MOTH_BEGIN_INSTR(StoreQObjectProperty)
- Runtime::setQmlQObjectProperty(context, VALUEPTR(instr.base), instr.propertyIndex, VALUEPTR(instr.source));
+ Runtime::setQmlQObjectProperty(engine, VALUEPTR(instr.base), instr.propertyIndex, VALUEPTR(instr.source));
CHECK_EXCEPTION;
MOTH_END_INSTR(StoreQObjectProperty)
MOTH_BEGIN_INSTR(LoadQObjectProperty)
- STOREVALUE(instr.result, Runtime::getQmlQObjectProperty(context, VALUEPTR(instr.base), instr.propertyIndex, instr.captureRequired));
+ STOREVALUE(instr.result, Runtime::getQmlQObjectProperty(engine, VALUEPTR(instr.base), instr.propertyIndex, instr.captureRequired));
MOTH_END_INSTR(LoadQObjectProperty)
MOTH_BEGIN_INSTR(LoadAttachedQObjectProperty)
- STOREVALUE(instr.result, Runtime::getQmlAttachedProperty(context, instr.attachedPropertiesId, instr.propertyIndex));
+ STOREVALUE(instr.result, Runtime::getQmlAttachedProperty(engine, instr.attachedPropertiesId, instr.propertyIndex));
MOTH_END_INSTR(LoadAttachedQObjectProperty)
MOTH_BEGIN_INSTR(LoadSingletonQObjectProperty)
- STOREVALUE(instr.result, Runtime::getQmlSingletonQObjectProperty(context, VALUEPTR(instr.base), instr.propertyIndex, instr.captureRequired));
+ STOREVALUE(instr.result, Runtime::getQmlSingletonQObjectProperty(engine, VALUEPTR(instr.base), instr.propertyIndex, instr.captureRequired));
MOTH_END_INSTR(LoadSingletonQObjectProperty)
MOTH_BEGIN_INSTR(Push)
TRACE(inline, "stack size: %u", instr.value);
stackSize = instr.value;
- stack = context->engine()->stackPush(stackSize);
-#ifndef QT_NO_DEBUG
- memset(stack, 0, stackSize * sizeof(QV4::Value));
-#endif
+ stack = scope.alloc(stackSize);
scopes[1] = stack;
MOTH_END_INSTR(Push)
@@ -352,7 +313,7 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code
callData->tag = QV4::Value::Integer_Type;
callData->argc = instr.argc;
callData->thisObject = QV4::Primitive::undefinedValue();
- STOREVALUE(instr.result, Runtime::callValue(context, VALUEPTR(instr.dest), callData));
+ STOREVALUE(instr.result, Runtime::callValue(engine, VALUEPTR(instr.dest), callData));
MOTH_END_INSTR(CallValue)
MOTH_BEGIN_INSTR(CallProperty)
@@ -362,17 +323,16 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code
callData->tag = QV4::Value::Integer_Type;
callData->argc = instr.argc;
callData->thisObject = VALUE(instr.base);
- STOREVALUE(instr.result, Runtime::callProperty(context, runtimeStrings[instr.name], callData));
+ STOREVALUE(instr.result, Runtime::callProperty(engine, instr.name, callData));
MOTH_END_INSTR(CallProperty)
MOTH_BEGIN_INSTR(CallPropertyLookup)
- TRACE(property name, "%s, args=%u, argc=%u, this=%s", qPrintable(runtimeStrings[instr.name]->toQString()), instr.callData, instr.argc, (VALUE(instr.base)).toString(context)->toQString().toUtf8().constData());
Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
callData->tag = QV4::Value::Integer_Type;
callData->argc = instr.argc;
callData->thisObject = VALUE(instr.base);
- STOREVALUE(instr.result, Runtime::callPropertyLookup(context, instr.lookupIndex, callData));
+ STOREVALUE(instr.result, Runtime::callPropertyLookup(engine, instr.lookupIndex, callData));
MOTH_END_INSTR(CallPropertyLookup)
MOTH_BEGIN_INSTR(CallElement)
@@ -381,27 +341,25 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code
callData->tag = QV4::Value::Integer_Type;
callData->argc = instr.argc;
callData->thisObject = VALUE(instr.base);
- STOREVALUE(instr.result, Runtime::callElement(context, VALUEPTR(instr.index), callData));
+ STOREVALUE(instr.result, Runtime::callElement(engine, VALUEPTR(instr.index), callData));
MOTH_END_INSTR(CallElement)
MOTH_BEGIN_INSTR(CallActivationProperty)
- TRACE(args, "starting at %d, length %d", instr.args, instr.argc);
Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
callData->tag = QV4::Value::Integer_Type;
callData->argc = instr.argc;
callData->thisObject = QV4::Primitive::undefinedValue();
- STOREVALUE(instr.result, Runtime::callActivationProperty(context, runtimeStrings[instr.name], callData));
+ STOREVALUE(instr.result, Runtime::callActivationProperty(engine, instr.name, callData));
MOTH_END_INSTR(CallActivationProperty)
MOTH_BEGIN_INSTR(CallGlobalLookup)
- TRACE(args, "starting at %d, length %d", instr.args, instr.argc);
Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
callData->tag = QV4::Value::Integer_Type;
callData->argc = instr.argc;
callData->thisObject = QV4::Primitive::undefinedValue();
- STOREVALUE(instr.result, Runtime::callGlobalLookup(context, instr.index, callData));
+ STOREVALUE(instr.result, Runtime::callGlobalLookup(engine, instr.index, callData));
MOTH_END_INSTR(CallGlobalLookup)
MOTH_BEGIN_INSTR(SetExceptionHandler)
@@ -409,28 +367,32 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code
MOTH_END_INSTR(SetExceptionHandler)
MOTH_BEGIN_INSTR(CallBuiltinThrow)
- Runtime::throwException(context, VALUEPTR(instr.arg));
+ Runtime::throwException(engine, VALUEPTR(instr.arg));
CHECK_EXCEPTION;
MOTH_END_INSTR(CallBuiltinThrow)
MOTH_BEGIN_INSTR(CallBuiltinUnwindException)
- STOREVALUE(instr.result, Runtime::unwindException(context));
+ STOREVALUE(instr.result, Runtime::unwindException(engine));
MOTH_END_INSTR(CallBuiltinUnwindException)
MOTH_BEGIN_INSTR(CallBuiltinPushCatchScope)
- context = Runtime::pushCatchScope(context, runtimeStrings[instr.name]);
+ Runtime::pushCatchScope(static_cast<QV4::NoThrowEngine*>(engine), instr.name);
+ context = engine->currentContext();
MOTH_END_INSTR(CallBuiltinPushCatchScope)
MOTH_BEGIN_INSTR(CallBuiltinPushScope)
- context = Runtime::pushWithScope(VALUEPTR(instr.arg), context);
+ Runtime::pushWithScope(VALUEPTR(instr.arg), engine);
+ context = engine->currentContext();
+ CHECK_EXCEPTION;
MOTH_END_INSTR(CallBuiltinPushScope)
MOTH_BEGIN_INSTR(CallBuiltinPopScope)
- context = Runtime::popScope(context);
+ Runtime::popScope(engine);
+ context = engine->currentContext();
MOTH_END_INSTR(CallBuiltinPopScope)
MOTH_BEGIN_INSTR(CallBuiltinForeachIteratorObject)
- STOREVALUE(instr.result, Runtime::foreachIterator(context, VALUEPTR(instr.arg)));
+ STOREVALUE(instr.result, Runtime::foreachIterator(engine, VALUEPTR(instr.arg)));
MOTH_END_INSTR(CallBuiltinForeachIteratorObject)
MOTH_BEGIN_INSTR(CallBuiltinForeachNextPropertyName)
@@ -438,54 +400,54 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code
MOTH_END_INSTR(CallBuiltinForeachNextPropertyName)
MOTH_BEGIN_INSTR(CallBuiltinDeleteMember)
- STOREVALUE(instr.result, Runtime::deleteMember(context, VALUEPTR(instr.base), runtimeStrings[instr.member]));
+ STOREVALUE(instr.result, Runtime::deleteMember(engine, VALUEPTR(instr.base), instr.member));
MOTH_END_INSTR(CallBuiltinDeleteMember)
MOTH_BEGIN_INSTR(CallBuiltinDeleteSubscript)
- STOREVALUE(instr.result, Runtime::deleteElement(context, VALUEPTR(instr.base), VALUEPTR(instr.index)));
+ STOREVALUE(instr.result, Runtime::deleteElement(engine, VALUEPTR(instr.base), VALUEPTR(instr.index)));
MOTH_END_INSTR(CallBuiltinDeleteSubscript)
MOTH_BEGIN_INSTR(CallBuiltinDeleteName)
- STOREVALUE(instr.result, Runtime::deleteName(context, runtimeStrings[instr.name]));
+ STOREVALUE(instr.result, Runtime::deleteName(engine, instr.name));
MOTH_END_INSTR(CallBuiltinDeleteName)
MOTH_BEGIN_INSTR(CallBuiltinTypeofMember)
- STOREVALUE(instr.result, Runtime::typeofMember(context, VALUEPTR(instr.base), runtimeStrings[instr.member]));
+ STOREVALUE(instr.result, Runtime::typeofMember(engine, VALUEPTR(instr.base), instr.member));
MOTH_END_INSTR(CallBuiltinTypeofMember)
MOTH_BEGIN_INSTR(CallBuiltinTypeofSubscript)
- STOREVALUE(instr.result, Runtime::typeofElement(context, VALUEPTR(instr.base), VALUEPTR(instr.index)));
+ STOREVALUE(instr.result, Runtime::typeofElement(engine, VALUEPTR(instr.base), VALUEPTR(instr.index)));
MOTH_END_INSTR(CallBuiltinTypeofSubscript)
MOTH_BEGIN_INSTR(CallBuiltinTypeofName)
- STOREVALUE(instr.result, Runtime::typeofName(context, runtimeStrings[instr.name]));
+ STOREVALUE(instr.result, Runtime::typeofName(engine, instr.name));
MOTH_END_INSTR(CallBuiltinTypeofName)
MOTH_BEGIN_INSTR(CallBuiltinTypeofValue)
- STOREVALUE(instr.result, Runtime::typeofValue(context, VALUEPTR(instr.value)));
+ STOREVALUE(instr.result, Runtime::typeofValue(engine, VALUEPTR(instr.value)));
MOTH_END_INSTR(CallBuiltinTypeofValue)
MOTH_BEGIN_INSTR(CallBuiltinDeclareVar)
- Runtime::declareVar(context, instr.isDeletable, runtimeStrings[instr.varName]);
+ Runtime::declareVar(engine, instr.isDeletable, instr.varName);
MOTH_END_INSTR(CallBuiltinDeclareVar)
MOTH_BEGIN_INSTR(CallBuiltinDefineArray)
Q_ASSERT(instr.args + instr.argc <= stackSize);
QV4::Value *args = stack + instr.args;
- STOREVALUE(instr.result, Runtime::arrayLiteral(context, args, instr.argc));
+ STOREVALUE(instr.result, Runtime::arrayLiteral(engine, args, instr.argc));
MOTH_END_INSTR(CallBuiltinDefineArray)
MOTH_BEGIN_INSTR(CallBuiltinDefineObjectLiteral)
QV4::Value *args = stack + instr.args;
- STOREVALUE(instr.result, Runtime::objectLiteral(context, args, instr.internalClassId, instr.arrayValueCount, instr.arrayGetterSetterCountAndFlags));
+ STOREVALUE(instr.result, Runtime::objectLiteral(engine, args, instr.internalClassId, instr.arrayValueCount, instr.arrayGetterSetterCountAndFlags));
MOTH_END_INSTR(CallBuiltinDefineObjectLiteral)
MOTH_BEGIN_INSTR(CallBuiltinSetupArgumentsObject)
- STOREVALUE(instr.result, Runtime::setupArgumentsObject(context));
+ STOREVALUE(instr.result, Runtime::setupArgumentsObject(engine));
MOTH_END_INSTR(CallBuiltinSetupArgumentsObject)
MOTH_BEGIN_INSTR(CallBuiltinConvertThisToObject)
- Runtime::convertThisToObject(context);
+ Runtime::convertThisToObject(engine);
CHECK_EXCEPTION;
MOTH_END_INSTR(CallBuiltinConvertThisToObject)
@@ -495,7 +457,7 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code
callData->tag = QV4::Value::Integer_Type;
callData->argc = instr.argc;
callData->thisObject = QV4::Primitive::undefinedValue();
- STOREVALUE(instr.result, Runtime::constructValue(context, VALUEPTR(instr.func), callData));
+ STOREVALUE(instr.result, Runtime::constructValue(engine, VALUEPTR(instr.func), callData));
MOTH_END_INSTR(CreateValue)
MOTH_BEGIN_INSTR(CreateProperty)
@@ -504,7 +466,7 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code
callData->tag = QV4::Value::Integer_Type;
callData->argc = instr.argc;
callData->thisObject = VALUE(instr.base);
- STOREVALUE(instr.result, Runtime::constructProperty(context, runtimeStrings[instr.name], callData));
+ STOREVALUE(instr.result, Runtime::constructProperty(engine, instr.name, callData));
MOTH_END_INSTR(CreateProperty)
MOTH_BEGIN_INSTR(ConstructPropertyLookup)
@@ -513,27 +475,25 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code
callData->tag = QV4::Value::Integer_Type;
callData->argc = instr.argc;
callData->thisObject = VALUE(instr.base);
- STOREVALUE(instr.result, Runtime::constructPropertyLookup(context, instr.index, callData));
+ STOREVALUE(instr.result, Runtime::constructPropertyLookup(engine, instr.index, callData));
MOTH_END_INSTR(ConstructPropertyLookup)
MOTH_BEGIN_INSTR(CreateActivationProperty)
- TRACE(inline, "property name = %s, args = %d, argc = %d", runtimeStrings[instr.name]->toQString().toUtf8().constData(), instr.args, instr.argc);
Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
callData->tag = QV4::Value::Integer_Type;
callData->argc = instr.argc;
callData->thisObject = QV4::Primitive::undefinedValue();
- STOREVALUE(instr.result, Runtime::constructActivationProperty(context, runtimeStrings[instr.name], callData));
+ STOREVALUE(instr.result, Runtime::constructActivationProperty(engine, instr.name, callData));
MOTH_END_INSTR(CreateActivationProperty)
MOTH_BEGIN_INSTR(ConstructGlobalLookup)
- TRACE(inline, "property name = %s, args = %d, argc = %d", runtimeStrings[instr.name]->toQString().toUtf8().constData(), instr.args, instr.argc);
Q_ASSERT(instr.callData + instr.argc + qOffsetOf(QV4::CallData, args)/sizeof(QV4::Value) <= stackSize);
QV4::CallData *callData = reinterpret_cast<QV4::CallData *>(stack + instr.callData);
callData->tag = QV4::Value::Integer_Type;
callData->argc = instr.argc;
callData->thisObject = QV4::Primitive::undefinedValue();
- STOREVALUE(instr.result, Runtime::constructGlobalLookup(context, instr.index, callData));
+ STOREVALUE(instr.result, Runtime::constructGlobalLookup(engine, instr.index, callData));
MOTH_END_INSTR(ConstructGlobalLookup)
MOTH_BEGIN_INSTR(Jump)
@@ -592,7 +552,7 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code
MOTH_END_INSTR(Binop)
MOTH_BEGIN_INSTR(Add)
- STOREVALUE(instr.result, Runtime::add(context, VALUEPTR(instr.lhs), VALUEPTR(instr.rhs)));
+ STOREVALUE(instr.result, Runtime::add(engine, VALUEPTR(instr.lhs), VALUEPTR(instr.rhs)));
MOTH_END_INSTR(Add)
MOTH_BEGIN_INSTR(BitAnd)
@@ -647,24 +607,23 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code
MOTH_END_INSTR(Sub)
MOTH_BEGIN_INSTR(BinopContext)
- STOREVALUE(instr.result, instr.alu(context, VALUEPTR(instr.lhs), VALUEPTR(instr.rhs)));
+ STOREVALUE(instr.result, instr.alu(engine, VALUEPTR(instr.lhs), VALUEPTR(instr.rhs)));
MOTH_END_INSTR(BinopContext)
MOTH_BEGIN_INSTR(Ret)
- context->engine()->stackPop(stackSize);
// TRACE(Ret, "returning value %s", result.toString(context)->toQString().toUtf8().constData());
return VALUE(instr.result).asReturnedValue();
MOTH_END_INSTR(Ret)
MOTH_BEGIN_INSTR(Debug)
- context->d()->lineNumber = instr.lineNumber;
+ engine->currentContext()->lineNumber = instr.lineNumber;
QV4::Debugging::Debugger *debugger = context->engine()->debugger;
if (debugger && debugger->pauseAtNextOpportunity())
debugger->maybeBreakAtInstruction();
MOTH_END_INSTR(Debug)
MOTH_BEGIN_INSTR(Line)
- context->d()->lineNumber = instr.lineNumber;
+ engine->currentContext()->lineNumber = instr.lineNumber;
MOTH_END_INSTR(Debug)
MOTH_BEGIN_INSTR(LoadThis)
@@ -672,23 +631,23 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code
MOTH_END_INSTR(LoadThis)
MOTH_BEGIN_INSTR(LoadQmlIdArray)
- VALUE(instr.result) = Runtime::getQmlIdArray(static_cast<QV4::NoThrowContext*>(context));
+ VALUE(instr.result) = Runtime::getQmlIdArray(static_cast<QV4::NoThrowEngine*>(engine));
MOTH_END_INSTR(LoadQmlIdArray)
MOTH_BEGIN_INSTR(LoadQmlImportedScripts)
- VALUE(instr.result) = Runtime::getQmlImportedScripts(static_cast<QV4::NoThrowContext*>(context));
+ VALUE(instr.result) = Runtime::getQmlImportedScripts(static_cast<QV4::NoThrowEngine*>(engine));
MOTH_END_INSTR(LoadQmlImportedScripts)
MOTH_BEGIN_INSTR(LoadQmlContextObject)
- VALUE(instr.result) = Runtime::getQmlContextObject(static_cast<QV4::NoThrowContext*>(context));
+ VALUE(instr.result) = Runtime::getQmlContextObject(static_cast<QV4::NoThrowEngine*>(engine));
MOTH_END_INSTR(LoadContextObject)
MOTH_BEGIN_INSTR(LoadQmlScopeObject)
- VALUE(instr.result) = Runtime::getQmlScopeObject(static_cast<QV4::NoThrowContext*>(context));
+ VALUE(instr.result) = Runtime::getQmlScopeObject(static_cast<QV4::NoThrowEngine*>(engine));
MOTH_END_INSTR(LoadScopeObject)
MOTH_BEGIN_INSTR(LoadQmlSingleton)
- VALUE(instr.result) = Runtime::getQmlSingleton(static_cast<QV4::NoThrowContext*>(context), runtimeStrings[instr.name]);
+ VALUE(instr.result) = Runtime::getQmlSingleton(static_cast<QV4::NoThrowEngine*>(engine), instr.name);
MOTH_END_INSTR(LoadQmlSingleton)
#ifdef MOTH_THREADED_INTERPRETER
@@ -703,10 +662,8 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code
Q_ASSERT(false);
catchException:
Q_ASSERT(context->engine()->hasException);
- if (!exceptionHandler) {
- context->engine()->stackPop(stackSize);
+ if (!exceptionHandler)
return QV4::Encode::undefined();
- }
code = exceptionHandler;
}
@@ -725,13 +682,13 @@ void **VME::instructionJumpTable()
}
#endif
-QV4::ReturnedValue VME::exec(QV4::ExecutionContext *ctxt, const uchar *code)
+QV4::ReturnedValue VME::exec(ExecutionEngine *engine, const uchar *code)
{
VME vme;
- QV4::Debugging::Debugger *debugger = ctxt->engine()->debugger;
+ QV4::Debugging::Debugger *debugger = engine->debugger;
if (debugger)
debugger->enteringFunction();
- QV4::ReturnedValue retVal = vme.run(ctxt, code);
+ QV4::ReturnedValue retVal = vme.run(engine, code);
if (debugger)
debugger->leavingFunction(retVal);
return retVal;
diff --git a/src/qml/jsruntime/qv4vme_moth_p.h b/src/qml/jsruntime/qv4vme_moth_p.h
index 731fb0f9a9..859208cd34 100644
--- a/src/qml/jsruntime/qv4vme_moth_p.h
+++ b/src/qml/jsruntime/qv4vme_moth_p.h
@@ -45,14 +45,14 @@ namespace Moth {
class VME
{
public:
- static QV4::ReturnedValue exec(QV4::ExecutionContext *, const uchar *);
+ static QV4::ReturnedValue exec(QV4::ExecutionEngine *, const uchar *);
#ifdef MOTH_THREADED_INTERPRETER
static void **instructionJumpTable();
#endif
private:
- QV4::ReturnedValue run(QV4::ExecutionContext *, const uchar *code
+ QV4::ReturnedValue run(QV4::ExecutionEngine *, const uchar *code
#ifdef MOTH_THREADED_INTERPRETER
, void ***storeJumpTable = 0
#endif
diff --git a/src/qml/parser/qqmljsengine_p.cpp b/src/qml/parser/qqmljsengine_p.cpp
index 7ac5dbc9bb..fac2d82ff2 100644
--- a/src/qml/parser/qqmljsengine_p.cpp
+++ b/src/qml/parser/qqmljsengine_p.cpp
@@ -114,7 +114,7 @@ double integerFromString(const QString &str, int radix)
Engine::Engine()
- : _lexer(0)
+ : _lexer(0), _directives(0)
{ }
Engine::~Engine()
@@ -135,6 +135,12 @@ Lexer *Engine::lexer() const
void Engine::setLexer(Lexer *lexer)
{ _lexer = lexer; }
+Directives *Engine::directives() const
+{ return _directives; }
+
+void Engine::setDirectives(Directives *directives)
+{ _directives = directives; }
+
MemoryPool *Engine::pool()
{ return &_pool; }
diff --git a/src/qml/parser/qqmljsengine_p.h b/src/qml/parser/qqmljsengine_p.h
index 661681d19c..81b2aa88e7 100644
--- a/src/qml/parser/qqmljsengine_p.h
+++ b/src/qml/parser/qqmljsengine_p.h
@@ -57,6 +57,7 @@ QT_QML_BEGIN_NAMESPACE
namespace QQmlJS {
class Lexer;
+class Directives;
class MemoryPool;
class QML_PARSER_EXPORT DiagnosticMessage
@@ -84,6 +85,7 @@ public:
class QML_PARSER_EXPORT Engine
{
Lexer *_lexer;
+ Directives *_directives;
MemoryPool _pool;
QList<AST::SourceLocation> _comments;
QString _extraCode;
@@ -102,6 +104,9 @@ public:
Lexer *lexer() const;
void setLexer(Lexer *lexer);
+ Directives *directives() const;
+ void setDirectives(Directives *directives);
+
MemoryPool *pool();
inline QStringRef midRef(int position, int size) { return _code.midRef(position, size); }
diff --git a/src/qml/parser/qqmljslexer.cpp b/src/qml/parser/qqmljslexer.cpp
index 416a6ee745..a69fa21c32 100644
--- a/src/qml/parser/qqmljslexer.cpp
+++ b/src/qml/parser/qqmljslexer.cpp
@@ -887,8 +887,7 @@ again:
int Lexer::scanNumber(QChar ch)
{
if (ch != QLatin1Char('0')) {
- QByteArray buf;
- buf.reserve(64);
+ QVarLengthArray<char, 64> buf;
buf += ch.toLatin1();
QChar n = _char;
@@ -1225,12 +1224,60 @@ bool Lexer::canInsertAutomaticSemicolon(int token) const
|| _followsClosingBrace;
}
-bool Lexer::scanDirectives(Directives *directives)
+static const int uriTokens[] = {
+ QQmlJSGrammar::T_IDENTIFIER,
+ QQmlJSGrammar::T_PROPERTY,
+ QQmlJSGrammar::T_SIGNAL,
+ QQmlJSGrammar::T_READONLY,
+ QQmlJSGrammar::T_ON,
+ QQmlJSGrammar::T_BREAK,
+ QQmlJSGrammar::T_CASE,
+ QQmlJSGrammar::T_CATCH,
+ QQmlJSGrammar::T_CONTINUE,
+ QQmlJSGrammar::T_DEFAULT,
+ QQmlJSGrammar::T_DELETE,
+ QQmlJSGrammar::T_DO,
+ QQmlJSGrammar::T_ELSE,
+ QQmlJSGrammar::T_FALSE,
+ QQmlJSGrammar::T_FINALLY,
+ QQmlJSGrammar::T_FOR,
+ QQmlJSGrammar::T_FUNCTION,
+ QQmlJSGrammar::T_IF,
+ QQmlJSGrammar::T_IN,
+ QQmlJSGrammar::T_INSTANCEOF,
+ QQmlJSGrammar::T_NEW,
+ QQmlJSGrammar::T_NULL,
+ QQmlJSGrammar::T_RETURN,
+ QQmlJSGrammar::T_SWITCH,
+ QQmlJSGrammar::T_THIS,
+ QQmlJSGrammar::T_THROW,
+ QQmlJSGrammar::T_TRUE,
+ QQmlJSGrammar::T_TRY,
+ QQmlJSGrammar::T_TYPEOF,
+ QQmlJSGrammar::T_VAR,
+ QQmlJSGrammar::T_VOID,
+ QQmlJSGrammar::T_WHILE,
+ QQmlJSGrammar::T_CONST,
+ QQmlJSGrammar::T_DEBUGGER,
+ QQmlJSGrammar::T_RESERVED_WORD,
+ QQmlJSGrammar::T_WITH,
+
+ QQmlJSGrammar::EOF_SYMBOL
+};
+static inline bool isUriToken(int token)
{
- if (_qmlMode) {
- // the directives are a Javascript-only extension.
- return false;
+ const int *current = uriTokens;
+ while (*current != QQmlJSGrammar::EOF_SYMBOL) {
+ if (*current == token)
+ return true;
+ ++current;
}
+ return false;
+}
+
+bool Lexer::scanDirectives(Directives *directives, DiagnosticMessage *error)
+{
+ Q_ASSERT(!_qmlMode);
lex(); // fetch the first token
@@ -1238,24 +1285,33 @@ bool Lexer::scanDirectives(Directives *directives)
return true;
do {
- lex(); // skip T_DOT
-
const int lineNumber = tokenStartLine();
+ const int column = tokenStartColumn();
+
+ lex(); // skip T_DOT
if (! (_tokenKind == T_IDENTIFIER || _tokenKind == T_RESERVED_WORD))
- return false; // expected a valid QML/JS directive
+ return true; // expected a valid QML/JS directive
const QString directiveName = tokenText();
if (! (directiveName == QLatin1String("pragma") ||
- directiveName == QLatin1String("import")))
+ directiveName == QLatin1String("import"))) {
+ error->message = QCoreApplication::translate("QQmlParser", "Syntax error");
+ error->loc.startLine = tokenStartLine();
+ error->loc.startColumn = tokenStartColumn();
return false; // not a valid directive name
+ }
// it must be a pragma or an import directive.
if (directiveName == QLatin1String("pragma")) {
// .pragma library
- if (! (lex() == T_IDENTIFIER && tokenText() == QLatin1String("library")))
+ if (! (lex() == T_IDENTIFIER && tokenText() == QLatin1String("library"))) {
+ error->message = QCoreApplication::translate("QQmlParser", "Syntax error");
+ error->loc.startLine = tokenStartLine();
+ error->loc.startColumn = tokenStartColumn();
return false; // expected `library
+ }
// we found a .pragma library directive
directives->pragmaLibrary();
@@ -1274,22 +1330,53 @@ bool Lexer::scanDirectives(Directives *directives)
fileImport = true;
pathOrUri = tokenText();
+ if (!pathOrUri.endsWith(QLatin1String("js"))) {
+ error->message = QCoreApplication::translate("QQmlParser","Imported file must be a script");
+ error->loc.startLine = tokenStartLine();
+ error->loc.startColumn = tokenStartColumn();
+ return false;
+ }
+
} else if (_tokenKind == T_IDENTIFIER) {
// .import T_IDENTIFIER (. T_IDENTIFIER)* T_NUMERIC_LITERAL as T_IDENTIFIER
- pathOrUri = tokenText();
+ while (true) {
+ if (!isUriToken(_tokenKind)) {
+ error->message = QCoreApplication::translate("QQmlParser","Invalid module URI");
+ error->loc.startLine = tokenStartLine();
+ error->loc.startColumn = tokenStartColumn();
+ return false;
+ }
- lex(); // skip the first T_IDENTIFIER
- for (; _tokenKind == T_DOT; lex()) {
- if (lex() != T_IDENTIFIER)
+ pathOrUri.append(tokenText());
+
+ lex();
+ if (tokenStartLine() != lineNumber) {
+ error->message = QCoreApplication::translate("QQmlParser","Invalid module URI");
+ error->loc.startLine = tokenStartLine();
+ error->loc.startColumn = tokenStartColumn();
return false;
+ }
+ if (_tokenKind != QQmlJSGrammar::T_DOT)
+ break;
+
+ pathOrUri.append(QLatin1Char('.'));
- pathOrUri += QLatin1Char('.');
- pathOrUri += tokenText();
+ lex();
+ if (tokenStartLine() != lineNumber) {
+ error->message = QCoreApplication::translate("QQmlParser","Invalid module URI");
+ error->loc.startLine = tokenStartLine();
+ error->loc.startColumn = tokenStartColumn();
+ return false;
+ }
}
- if (_tokenKind != T_NUMERIC_LITERAL)
+ if (_tokenKind != T_NUMERIC_LITERAL) {
+ error->message = QCoreApplication::translate("QQmlParser","Module import requires a version");
+ error->loc.startLine = tokenStartLine();
+ error->loc.startColumn = tokenStartColumn();
return false; // expected the module version number
+ }
version = tokenText();
}
@@ -1297,22 +1384,51 @@ bool Lexer::scanDirectives(Directives *directives)
//
// recognize the mandatory `as' followed by the module name
//
- if (! (lex() == T_IDENTIFIER && tokenText() == QLatin1String("as")))
+ if (! (lex() == T_IDENTIFIER && tokenText() == QLatin1String("as") && tokenStartLine() == lineNumber)) {
+ if (fileImport)
+ error->message = QCoreApplication::translate("QQmlParser", "File import requires a qualifier");
+ else
+ error->message = QCoreApplication::translate("QQmlParser", "Module import requires a qualifier");
+ if (tokenStartLine() != lineNumber) {
+ error->loc.startLine = lineNumber;
+ error->loc.startColumn = column;
+ } else {
+ error->loc.startLine = tokenStartLine();
+ error->loc.startColumn = tokenStartColumn();
+ }
return false; // expected `as'
+ }
- if (lex() != T_IDENTIFIER)
+ if (lex() != T_IDENTIFIER || tokenStartLine() != lineNumber) {
+ if (fileImport)
+ error->message = QCoreApplication::translate("QQmlParser", "File import requires a qualifier");
+ else
+ error->message = QCoreApplication::translate("QQmlParser", "Module import requires a qualifier");
+ error->loc.startLine = tokenStartLine();
+ error->loc.startColumn = tokenStartColumn();
return false; // expected module name
+ }
const QString module = tokenText();
+ if (!module.at(0).isUpper()) {
+ error->message = QCoreApplication::translate("QQmlParser","Invalid import qualifier");
+ error->loc.startLine = tokenStartLine();
+ error->loc.startColumn = tokenStartColumn();
+ return false;
+ }
if (fileImport)
- directives->importFile(pathOrUri, module);
+ directives->importFile(pathOrUri, module, lineNumber, column);
else
- directives->importModule(pathOrUri, version, module);
+ directives->importModule(pathOrUri, version, module, lineNumber, column);
}
- if (tokenStartLine() != lineNumber)
+ if (tokenStartLine() != lineNumber) {
+ error->message = QCoreApplication::translate("QQmlParser", "Syntax error");
+ error->loc.startLine = tokenStartLine();
+ error->loc.startColumn = tokenStartColumn();
return false; // the directives cannot span over multiple lines
+ }
// fetch the first token after the .pragma/.import directive
lex();
diff --git a/src/qml/parser/qqmljslexer_p.h b/src/qml/parser/qqmljslexer_p.h
index 9106c94477..b5415f8777 100644
--- a/src/qml/parser/qqmljslexer_p.h
+++ b/src/qml/parser/qqmljslexer_p.h
@@ -55,6 +55,7 @@ QT_QML_BEGIN_NAMESPACE
namespace QQmlJS {
class Engine;
+class DiagnosticMessage;
class QML_PARSER_EXPORT Directives {
public:
@@ -64,17 +65,21 @@ public:
{
}
- virtual void importFile(const QString &jsfile, const QString &module)
+ virtual void importFile(const QString &jsfile, const QString &module, int line, int column)
{
Q_UNUSED(jsfile);
Q_UNUSED(module);
+ Q_UNUSED(line);
+ Q_UNUSED(column);
}
- virtual void importModule(const QString &uri, const QString &version, const QString &module)
+ virtual void importModule(const QString &uri, const QString &version, const QString &module, int line, int column)
{
Q_UNUSED(uri);
Q_UNUSED(version);
Q_UNUSED(module);
+ Q_UNUSED(line);
+ Q_UNUSED(column);
}
};
@@ -146,7 +151,7 @@ public:
int lex();
bool scanRegExp(RegExpBodyPrefix prefix = NoPrefix);
- bool scanDirectives(Directives *directives);
+ bool scanDirectives(Directives *directives, DiagnosticMessage *error);
int regExpFlags() const { return _patternFlags; }
QString regExpPattern() const { return _tokenText; }
diff --git a/src/qml/parser/qqmljsparser.cpp b/src/qml/parser/qqmljsparser.cpp
index 762e60c827..35eb0e3ad5 100644
--- a/src/qml/parser/qqmljsparser.cpp
+++ b/src/qml/parser/qqmljsparser.cpp
@@ -161,7 +161,24 @@ bool Parser::parse(int startToken)
token_buffer[0].token = startToken;
first_token = &token_buffer[0];
- last_token = &token_buffer[1];
+ if (startToken == T_FEED_JS_PROGRAM && !lexer->qmlMode()) {
+ Directives ignoreDirectives;
+ Directives *directives = driver->directives();
+ if (!directives)
+ directives = &ignoreDirectives;
+ DiagnosticMessage error;
+ if (!lexer->scanDirectives(directives, &error)) {
+ diagnostic_messages.append(error);
+ return false;
+ }
+ token_buffer[1].token = lexer->tokenKind();
+ token_buffer[1].dval = lexer->tokenValue();
+ token_buffer[1].loc = location(lexer);
+ token_buffer[1].spell = lexer->tokenSpell();
+ last_token = &token_buffer[2];
+ } else {
+ last_token = &token_buffer[1];
+ }
tos = -1;
program = 0;
diff --git a/src/qml/qml/ftw/ftw.pri b/src/qml/qml/ftw/ftw.pri
index 00d56263c6..74a922dc5e 100644
--- a/src/qml/qml/ftw/ftw.pri
+++ b/src/qml/qml/ftw/ftw.pri
@@ -13,7 +13,6 @@ HEADERS += \
$$PWD/qdeletewatcher_p.h \
$$PWD/qrecyclepool_p.h \
$$PWD/qflagpointer_p.h \
- $$PWD/qqmltrace_p.h \
$$PWD/qpointervaluepair_p.h \
$$PWD/qlazilyallocated_p.h \
@@ -22,7 +21,6 @@ SOURCES += \
$$PWD/qhashedstring.cpp \
$$PWD/qqmlpool.cpp \
$$PWD/qqmlthread.cpp \
- $$PWD/qqmltrace.cpp \
# mirrors logic in $$QT_SOURCE_TREE/config.tests/unix/clock-gettime/clock-gettime.pri
# clock_gettime() is implemented in librt on these systems
diff --git a/src/qml/qml/ftw/qqmltrace.cpp b/src/qml/qml/ftw/qqmltrace.cpp
deleted file mode 100644
index 104ff2e117..0000000000
--- a/src/qml/qml/ftw/qqmltrace.cpp
+++ /dev/null
@@ -1,147 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qqmltrace_p.h"
-
-#ifdef QML_ENABLE_TRACE
-#include <stdio.h>
-#include <unistd.h>
-#endif
-
-QT_BEGIN_NAMESPACE
-
-#ifdef QML_ENABLE_TRACE
-
-QQmlTrace::Pool QQmlTrace::logPool;
-QQmlTrace::Entry *QQmlTrace::first = 0;
-QQmlTrace::Entry *QQmlTrace::last = 0;
-
-static qint64 toNsecs(QQmlTrace::TimeType time)
-{
-#ifdef Q_OS_MAC
- static mach_timebase_info_data_t info = {0,0};
- if (info.denom == 0)
- mach_timebase_info(&info);
- return time * info.numer / info.denom;
-#else
- qint64 rv = time.tv_sec * 1000000000 + time.tv_nsec;
- return rv;
-#endif
-}
-
-QQmlTrace::Pool::Pool()
-{
- first = New<Entry>();
- last = first;
-}
-
-QQmlTrace::Pool::~Pool()
-{
- char buffer[128];
- sprintf(buffer, "qml.%d.log", ::getpid());
- FILE *out = fopen(buffer, "w");
- if (!out) {
- fprintf (stderr, "QML Log: Could not open %s\n", buffer);
- return;
- } else {
- fprintf (stderr, "QML Log: Writing log to %s\n", buffer);
- }
-
- QQmlTrace::Entry *cur = QQmlTrace::first;
- QByteArray indent;
- int depth = -1;
-
- qint64 firstTime = -1;
-
- while (cur) {
-
- switch (cur->type) {
- case QQmlTrace::Entry::RangeStart: {
- RangeStart *rs = static_cast<QQmlTrace::RangeStart *>(cur);
-
- qint64 nsecs = toNsecs(rs->time);
-
- if (firstTime == -1)
- firstTime = nsecs;
-
- nsecs -= firstTime;
-
- depth++;
- indent = QByteArray(depth * 4, ' ');
- fprintf(out, "%s%s @%lld (%lld ns)\n", indent.constData(),
- rs->description, nsecs, toNsecs(rs->end->time) - nsecs - firstTime);
- } break;
- case QQmlTrace::Entry::RangeEnd:
- depth--;
- indent = QByteArray(depth * 4, ' ');
- break;
- case QQmlTrace::Entry::Detail:
- fprintf(out, "%s %s\n", indent.constData(),
- static_cast<QQmlTrace::Detail *>(cur)->description);
- break;
- case QQmlTrace::Entry::IntDetail:
- fprintf(out, "%s %s: %d\n", indent.constData(),
- static_cast<QQmlTrace::Detail *>(cur)->description,
- static_cast<QQmlTrace::IntDetail *>(cur)->value);
- break;
- case QQmlTrace::Entry::StringDetail: {
- QByteArray vLatin1 = static_cast<QQmlTrace::StringDetail *>(cur)->value->toLatin1();
- fprintf(out, "%s %s: %s\n", indent.constData(),
- static_cast<QQmlTrace::Detail *>(cur)->description,
- vLatin1.constData());
- } break;
- case QQmlTrace::Entry::UrlDetail: {
- QByteArray vLatin1 = static_cast<QQmlTrace::UrlDetail *>(cur)->value->toString().toLatin1();
- fprintf(out, "%s %s: %s\n", indent.constData(),
- static_cast<QQmlTrace::Detail *>(cur)->description,
- vLatin1.constData());
- } break;
- case QQmlTrace::Entry::Event: {
- Event *ev = static_cast<QQmlTrace::Event *>(cur);
- qint64 nsecs = toNsecs(ev->time) - firstTime;
- fprintf(out, "%s + %s @%lld +%lld ns\n", indent.constData(),
- ev->description, nsecs, nsecs - (toNsecs(ev->start->time) - firstTime));
- } break;
- case QQmlTrace::Entry::Null:
- default:
- break;
- }
- cur = cur->next;
- }
- fclose(out);
-}
-
-#endif
-
-QT_END_NAMESPACE
-
diff --git a/src/qml/qml/ftw/qqmltrace_p.h b/src/qml/qml/ftw/qqmltrace_p.h
deleted file mode 100644
index 19e81965dd..0000000000
--- a/src/qml/qml/ftw/qqmltrace_p.h
+++ /dev/null
@@ -1,286 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QQMLTRACE_P_H
-#define QQMLTRACE_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtCore/qglobal.h>
-#include <private/qqmlpool_p.h>
-
-// #define QML_ENABLE_TRACE
-
-#if defined(QML_ENABLE_TRACE) && defined(Q_OS_MAC)
-#include <mach/mach_time.h>
-#endif
-
-QT_BEGIN_NAMESPACE
-
-class QUrl;
-class QQmlTrace
-{
-public:
- inline QQmlTrace(const char *desc);
- inline ~QQmlTrace();
-
- inline void addDetail(const char *);
- inline void addDetail(const char *, int);
- inline void addDetail(const char *, const QString &);
- inline void addDetail(const char *, const QUrl &);
-
- inline void event(const char *desc);
-
-#ifdef QML_ENABLE_TRACE
-
-#ifdef Q_OS_MAC
- typedef uint64_t TimeType;
-#else
- typedef timespec TimeType;
-#endif
-
- struct Entry : public QQmlPool::POD {
- enum Type { Null, RangeStart, RangeEnd, Detail, IntDetail, StringDetail, UrlDetail, Event };
- inline Entry();
- inline Entry(Type);
- Type type;
- Entry *next;
- };
- struct RangeEnd : public Entry {
- inline RangeEnd();
- TimeType time;
- };
- struct RangeStart : public Entry {
- inline RangeStart();
- const char *description;
- TimeType time;
- QQmlTrace::RangeEnd *end;
- };
- struct Detail : public Entry {
- inline Detail();
- inline Detail(Type t);
- const char *description;
- };
- struct IntDetail : public Detail {
- inline IntDetail();
- int value;
- };
- struct StringDetail : public Detail {
- inline StringDetail();
- QString *value;
- };
- struct UrlDetail : public Detail {
- inline UrlDetail();
- QUrl *value;
- };
- struct Event : public Entry {
- inline Event();
- const char *description;
- TimeType time;
- QQmlTrace::RangeStart *start;
- };
-
- struct Pool : public QQmlPool {
- Pool();
- ~Pool();
- };
-
- static Pool logPool;
- static Entry *first;
- static Entry *last;
-
-private:
- RangeStart *start;
-
- static TimeType gettime() {
-#ifdef Q_OS_MAC
- return mach_absolute_time();
-#else
- TimeType ts;
- clock_gettime(CLOCK_MONOTONIC, &ts);
- return ts;
-#endif
- }
-#endif
-};
-
-#ifdef QML_ENABLE_TRACE
-QQmlTrace::Entry::Entry()
-: type(Null), next(0)
-{
-}
-
-QQmlTrace::Entry::Entry(Type type)
-: type(type), next(0)
-{
- QQmlTrace::last->next = this;
- QQmlTrace::last = this;
-}
-
-QQmlTrace::RangeEnd::RangeEnd()
-: QQmlTrace::Entry(QQmlTrace::Entry::RangeEnd),
- time(gettime())
-{
-}
-
-QQmlTrace::RangeStart::RangeStart()
-: QQmlTrace::Entry(QQmlTrace::Entry::RangeStart),
- description(0), time(gettime())
-{
-}
-
-QQmlTrace::Detail::Detail()
-: QQmlTrace::Entry(QQmlTrace::Entry::Detail),
- description(0)
-{
-}
-
-QQmlTrace::Detail::Detail(Type type)
-: QQmlTrace::Entry(type), description(0)
-{
-}
-
-QQmlTrace::IntDetail::IntDetail()
-: QQmlTrace::Detail(QQmlTrace::Entry::IntDetail),
- value(0)
-{
-}
-
-QQmlTrace::StringDetail::StringDetail()
-: QQmlTrace::Detail(QQmlTrace::Entry::StringDetail),
- value(0)
-{
-}
-
-QQmlTrace::UrlDetail::UrlDetail()
-: QQmlTrace::Detail(QQmlTrace::Entry::UrlDetail),
- value(0)
-{
-}
-
-QQmlTrace::Event::Event()
-: QQmlTrace::Entry(QQmlTrace::Entry::Event),
- description(0), time(gettime()), start(0)
-{
-}
-#endif
-
-QQmlTrace::QQmlTrace(const char *desc)
-{
-#ifdef QML_ENABLE_TRACE
- RangeStart *e = logPool.New<RangeStart>();
- e->description = desc;
- e->end = 0;
- start = e;
-#else
- Q_UNUSED(desc);
-#endif
-}
-
-QQmlTrace::~QQmlTrace()
-{
-#ifdef QML_ENABLE_TRACE
- RangeEnd *e = logPool.New<RangeEnd>();
- start->end = e;
-#endif
-}
-
-void QQmlTrace::addDetail(const char *desc)
-{
-#ifdef QML_ENABLE_TRACE
- Detail *e = logPool.New<Detail>();
- e->description = desc;
-#else
- Q_UNUSED(desc);
-#endif
-}
-
-void QQmlTrace::addDetail(const char *desc, int v)
-{
-#ifdef QML_ENABLE_TRACE
- IntDetail *e = logPool.New<IntDetail>();
- e->description = desc;
- e->value = v;
-#else
- Q_UNUSED(desc);
- Q_UNUSED(v);
-#endif
-}
-
-void QQmlTrace::addDetail(const char *desc, const QString &v)
-{
-#ifdef QML_ENABLE_TRACE
- StringDetail *e = logPool.New<StringDetail>();
- e->description = desc;
- e->value = logPool.NewString(v);
-#else
- Q_UNUSED(desc);
- Q_UNUSED(v);
-#endif
-}
-
-void QQmlTrace::addDetail(const char *desc, const QUrl &v)
-{
-#ifdef QML_ENABLE_TRACE
- UrlDetail *e = logPool.New<UrlDetail>();
- e->description = desc;
- e->value = logPool.NewUrl(v);
-#else
- Q_UNUSED(desc);
- Q_UNUSED(v);
-#endif
-}
-
-void QQmlTrace::event(const char *desc)
-{
-#ifdef QML_ENABLE_TRACE
- Event *e = logPool.New<Event>();
- e->start = start;
- e->description = desc;
-#else
- Q_UNUSED(desc);
-#endif
-}
-
-QT_END_NAMESPACE
-
-#endif // QQMLTRACE_P_H
diff --git a/src/qml/qml/qml.pri b/src/qml/qml/qml.pri
index 013f757c90..cad839ba9d 100644
--- a/src/qml/qml/qml.pri
+++ b/src/qml/qml/qml.pri
@@ -49,7 +49,6 @@ SOURCES += \
$$PWD/qqmlvaluetypeproxybinding.cpp \
$$PWD/qqmlglobal.cpp \
$$PWD/qqmlfile.cpp \
- $$PWD/qqmlbundle.cpp \
$$PWD/qqmlmemoryprofiler.cpp \
$$PWD/qqmlplatform.cpp \
$$PWD/qqmlbinding.cpp \
@@ -121,7 +120,6 @@ HEADERS += \
$$PWD/qqmlabstractbinding_p.h \
$$PWD/qqmlvaluetypeproxybinding_p.h \
$$PWD/qqmlfile.h \
- $$PWD/qqmlbundle_p.h \
$$PWD/qqmlmemoryprofiler_p.h \
$$PWD/qqmlplatform_p.h \
$$PWD/qqmlbinding_p.h \
diff --git a/src/qml/qml/qqmlabstractbinding.cpp b/src/qml/qml/qqmlabstractbinding.cpp
index 71169abc98..51471d3b89 100644
--- a/src/qml/qml/qqmlabstractbinding.cpp
+++ b/src/qml/qml/qqmlabstractbinding.cpp
@@ -75,15 +75,12 @@ void QQmlAbstractBinding::addToObject()
QObject *obj = object();
Q_ASSERT(obj);
- int index = propertyIndex();
-
QQmlData *data = QQmlData::get(obj, true);
- if (index & 0xFFFF0000) {
+ int coreIndex;
+ if (QQmlPropertyData::decodeValueTypePropertyIndex(propertyIndex(), &coreIndex) != -1) {
// Value type
- int coreIndex = index & 0x0000FFFF;
-
// Find the value type proxy (if there is one)
QQmlValueTypeProxyBinding *proxy = 0;
if (data->hasBindingBit(coreIndex)) {
@@ -110,7 +107,7 @@ void QQmlAbstractBinding::addToObject()
setNextBinding(data->bindings);
data->bindings = this;
- data->setBindingBit(obj, index);
+ data->setBindingBit(obj, coreIndex);
}
setAddedToObject(true);
@@ -123,16 +120,15 @@ void QQmlAbstractBinding::removeFromObject()
{
if (isAddedToObject()) {
QObject *obj = object();
- int index = propertyIndex();
-
QQmlData *data = QQmlData::get(obj, false);
Q_ASSERT(data);
- if (index & 0xFFFF0000) {
+ int coreIndex;
+ if (QQmlPropertyData::decodeValueTypePropertyIndex(propertyIndex(), &coreIndex) != -1) {
// Find the value type binding
QQmlAbstractBinding *vtbinding = data->bindings;
- while (vtbinding->propertyIndex() != (index & 0x0000FFFF)) {
+ while (vtbinding->propertyIndex() != coreIndex) {
vtbinding = vtbinding->nextBinding();
Q_ASSERT(vtbinding);
}
@@ -169,7 +165,7 @@ void QQmlAbstractBinding::removeFromObject()
binding->setNextBinding(nextBinding());
}
- data->clearBindingBit(index);
+ data->clearBindingBit(coreIndex);
}
setNextBinding(0);
diff --git a/src/qml/qml/qqmlbinding.cpp b/src/qml/qml/qqmlbinding.cpp
index 7babcd2f4e..91fa2aa7bd 100644
--- a/src/qml/qml/qqmlbinding.cpp
+++ b/src/qml/qml/qqmlbinding.cpp
@@ -39,7 +39,6 @@
#include "qqmlcompiler_p.h"
#include "qqmldata_p.h"
#include <private/qqmlprofiler_p.h>
-#include <private/qqmltrace_p.h>
#include <private/qqmlexpression_p.h>
#include <private/qqmlscriptstring_p.h>
#include <private/qqmlcontextwrapper_p.h>
@@ -75,7 +74,8 @@ QQmlBinding::QQmlBinding(const QString &str, QObject *obj, QQmlContext *ctxt)
QQmlAbstractExpression::setContext(QQmlContextData::get(ctxt));
setScopeObject(obj);
- v4function = qmlBinding(context(), obj, str, QString(), 0);
+ QV4::ExecutionEngine *v4 = QQmlEnginePrivate::get(context()->engine)->v4engine();
+ v4function.set(v4, qmlBinding(context(), obj, str, QString(), 0));
}
QQmlBinding::QQmlBinding(const QQmlScriptString &script, QObject *obj, QQmlContext *ctxt)
@@ -103,11 +103,12 @@ QQmlBinding::QQmlBinding(const QQmlScriptString &script, QObject *obj, QQmlConte
QQmlAbstractExpression::setContext(QQmlContextData::get(ctxt ? ctxt : scriptPrivate->context));
setScopeObject(obj ? obj : scriptPrivate->scope);
+ QV4::ExecutionEngine *v4 = QQmlEnginePrivate::get(context()->engine)->v4engine();
if (runtimeFunction) {
- v4function = QV4::QmlBindingWrapper::createQmlCallableForFunction(ctxtdata, scopeObject(), runtimeFunction);
+ v4function.set(v4, QV4::QmlBindingWrapper::createQmlCallableForFunction(ctxtdata, scopeObject(), runtimeFunction));
} else {
QString code = scriptPrivate->script;
- v4function = qmlBinding(context(), scopeObject(), code, url, scriptPrivate->lineNumber);
+ v4function.set(v4, qmlBinding(context(), scopeObject(), code, url, scriptPrivate->lineNumber));
}
}
@@ -118,7 +119,8 @@ QQmlBinding::QQmlBinding(const QString &str, QObject *obj, QQmlContextData *ctxt
QQmlAbstractExpression::setContext(ctxt);
setScopeObject(obj);
- v4function = qmlBinding(ctxt, obj, str, QString(), 0);
+ QV4::ExecutionEngine *v4 = QQmlEnginePrivate::get(context()->engine)->v4engine();
+ v4function.set(v4, qmlBinding(ctxt, obj, str, QString(), 0));
}
QQmlBinding::QQmlBinding(const QString &str, QObject *obj,
@@ -131,7 +133,8 @@ QQmlBinding::QQmlBinding(const QString &str, QObject *obj,
QQmlAbstractExpression::setContext(ctxt);
setScopeObject(obj);
- v4function = qmlBinding(ctxt, obj, str, url, lineNumber);
+ QV4::ExecutionEngine *v4 = QQmlEnginePrivate::get(context()->engine)->v4engine();
+ v4function.set(v4, qmlBinding(ctxt, obj, str, url, lineNumber));
}
QQmlBinding::QQmlBinding(const QV4::ValueRef functionPtr, QObject *obj, QQmlContextData *ctxt)
@@ -141,7 +144,7 @@ QQmlBinding::QQmlBinding(const QV4::ValueRef functionPtr, QObject *obj, QQmlCont
QQmlAbstractExpression::setContext(ctxt);
setScopeObject(obj);
- v4function = functionPtr;
+ v4function.set(functionPtr->asObject()->engine(), functionPtr);
}
QQmlBinding::~QQmlBinding()
@@ -170,9 +173,9 @@ void QQmlBinding::update(QQmlPropertyPrivate::WriteFlags flags)
QV4::Scope scope(ep->v4engine());
QV4::ScopedFunctionObject f(scope, v4function.value());
Q_ASSERT(f);
- if (f->bindingKeyFlag()) {
+ if (f->isBinding()) {
Q_ASSERT(f->as<QV4::QQmlBindingFunction>());
- QQmlSourceLocation loc = static_cast<QV4::QQmlBindingFunction *>(f.getPointer())->d()->bindingLocation;
+ QQmlSourceLocation loc = static_cast<QV4::Heap::QQmlBindingFunction *>(f->d())->bindingLocation;
url = loc.sourceFile;
lineNumber = loc.line;
columnNumber = loc.column;
@@ -188,11 +191,6 @@ void QQmlBinding::update(QQmlPropertyPrivate::WriteFlags flags)
int lineNo = qmlSourceCoordinate(lineNumber);
int columnNo = qmlSourceCoordinate(columnNumber);
- QQmlTrace trace("General Binding Update");
- trace.addDetail("URL", url);
- trace.addDetail("Line", lineNo);
- trace.addDetail("Column", columnNo);
-
if (!updatingFlag()) {
QQmlBindingProfiler prof(ep->profiler, url, lineNo, columnNo);
setUpdatingFlag(true);
@@ -216,8 +214,6 @@ void QQmlBinding::update(QQmlPropertyPrivate::WriteFlags flags)
QV4::ScopedValue result(scope, QQmlJavaScriptExpression::evaluate(context(), f, &isUndefined));
- trace.event("writing binding result");
-
bool needsErrorLocationData = false;
if (!watcher.wasDeleted() && !hasError())
needsErrorLocationData = !QQmlPropertyPrivate::writeBinding(*m_coreObject, m_core, context(),
@@ -260,7 +256,7 @@ QVariant QQmlBinding::evaluate()
ep->dereferenceScarceResources();
- return ep->v8engine()->toVariant(result, qMetaTypeId<QList<QObject*> >());
+ return scope.engine->toVariant(result, qMetaTypeId<QList<QObject*> >());
}
QString QQmlBinding::expressionIdentifier(QQmlJavaScriptExpression *e)
diff --git a/src/qml/qml/qqmlboundsignal.cpp b/src/qml/qml/qqmlboundsignal.cpp
index 26fe659616..811efcaef5 100644
--- a/src/qml/qml/qqmlboundsignal.cpp
+++ b/src/qml/qml/qqmlboundsignal.cpp
@@ -76,8 +76,8 @@ QQmlBoundSignalExpression::QQmlBoundSignalExpression(QObject *target, int index,
const QString &handlerName,
const QString &parameterString)
: QQmlJavaScriptExpression(&QQmlBoundSignalExpression_jsvtable),
- m_target(target),
m_index(index),
+ m_target(target),
m_extra(new ExtraData(handlerName, parameterString, expression, fileName, line, column))
{
setExpressionFunctionValid(false);
@@ -88,9 +88,9 @@ QQmlBoundSignalExpression::QQmlBoundSignalExpression(QObject *target, int index,
QQmlBoundSignalExpression::QQmlBoundSignalExpression(QObject *target, int index, QQmlContextData *ctxt, QObject *scope, const QV4::ValueRef &function)
: QQmlJavaScriptExpression(&QQmlBoundSignalExpression_jsvtable),
- m_v8function(function),
- m_target(target),
m_index(index),
+ m_function(function->asObject()->engine(), function),
+ m_target(target),
m_extra(0)
{
setExpressionFunctionValid(true);
@@ -101,8 +101,8 @@ QQmlBoundSignalExpression::QQmlBoundSignalExpression(QObject *target, int index,
QQmlBoundSignalExpression::QQmlBoundSignalExpression(QObject *target, int index, QQmlContextData *ctxt, QObject *scope, QV4::Function *runtimeFunction)
: QQmlJavaScriptExpression(&QQmlBoundSignalExpression_jsvtable),
- m_target(target),
m_index(index),
+ m_target(target),
m_extra(0)
{
setExpressionFunctionValid(true);
@@ -113,7 +113,8 @@ QQmlBoundSignalExpression::QQmlBoundSignalExpression(QObject *target, int index,
QMetaMethod signal = QMetaObjectPrivate::signal(m_target->metaObject(), m_index);
QString error;
- m_v8function = QV4::QmlBindingWrapper::createQmlCallableForFunction(ctxt, scope, runtimeFunction, signal.parameterNames(), &error);
+ QV4::ExecutionEngine *engine = QQmlEnginePrivate::getV4Engine(ctxt->engine);
+ m_function.set(engine, QV4::QmlBindingWrapper::createQmlCallableForFunction(ctxt, scope, runtimeFunction, signal.parameterNames(), &error));
if (!error.isEmpty()) {
qmlInfo(scopeObject()) << error;
setInvalidParameterName(true);
@@ -168,7 +169,7 @@ QString QQmlBoundSignalExpression::expression() const
if (expressionFunctionValid()) {
Q_ASSERT (context() && engine());
QV4::Scope scope(QQmlEnginePrivate::get(engine())->v4engine());
- QV4::ScopedValue v(scope, m_v8function.value());
+ QV4::ScopedValue v(scope, m_function.value());
return v->toQStringNoThrow();
} else {
Q_ASSERT(!m_extra.isNull());
@@ -181,7 +182,7 @@ QV4::Function *QQmlBoundSignalExpression::function() const
if (expressionFunctionValid()) {
Q_ASSERT (context() && engine());
QV4::Scope scope(QQmlEnginePrivate::get(engine())->v4engine());
- QV4::Scoped<QV4::FunctionObject> v(scope, m_v8function.value());
+ QV4::ScopedFunctionObject v(scope, m_function.value());
return v ? v->function() : 0;
}
return 0;
@@ -217,7 +218,7 @@ void QQmlBoundSignalExpression::evaluate(void **a)
//TODO: look at using the property cache here (as in the compiler)
// for further optimization
QMetaMethod signal = QMetaObjectPrivate::signal(m_target->metaObject(), m_index);
- expression += QQmlPropertyCache::signalParameterStringForJS(engine(), signal.parameterNames(), &error);
+ expression += QQmlPropertyCache::signalParameterStringForJS(scope.engine, signal.parameterNames(), &error);
if (!error.isEmpty()) {
qmlInfo(scopeObject()) << error;
@@ -236,10 +237,10 @@ void QQmlBoundSignalExpression::evaluate(void **a)
m_extra->m_handlerName.clear();
m_extra->m_parameterString.clear();
- m_v8function = evalFunction(context(), scopeObject(), expression,
- m_extra->m_sourceLocation.sourceFile, m_extra->m_sourceLocation.line, &m_extra->m_v8qmlscope);
+ m_function.set(scope.engine, evalFunction(context(), scopeObject(), expression,
+ m_extra->m_sourceLocation.sourceFile, m_extra->m_sourceLocation.line, &m_extra->m_v8qmlscope));
- if (m_v8function.isNullOrUndefined()) {
+ if (m_function.isNullOrUndefined()) {
ep->dereferenceScarceResources();
return; // could not evaluate function. Not valid.
}
@@ -247,14 +248,13 @@ void QQmlBoundSignalExpression::evaluate(void **a)
setExpressionFunctionValid(true);
}
- QV8Engine *engine = ep->v8engine();
QVarLengthArray<int, 9> dummy;
//TODO: lookup via signal index rather than method index as an optimization
int methodIndex = QMetaObjectPrivate::signal(m_target->metaObject(), m_index).methodIndex();
- int *argsTypes = QQmlPropertyCache::methodParameterTypes(m_target, methodIndex, dummy, 0);
+ int *argsTypes = QQmlMetaObject(m_target).methodParameterTypes(methodIndex, dummy, 0);
int argCount = argsTypes ? *argsTypes : 0;
- QV4::ScopedValue f(scope, m_v8function.value());
+ QV4::ScopedValue f(scope, m_function.value());
QV4::ScopedCallData callData(scope, argCount);
for (int ii = 0; ii < argCount; ++ii) {
int type = argsTypes[ii + 1];
@@ -262,7 +262,7 @@ void QQmlBoundSignalExpression::evaluate(void **a)
// for several cases (such as QVariant type and QObject-derived types)
//args[ii] = engine->metaTypeToJS(type, a[ii + 1]);
if (type == QMetaType::QVariant) {
- callData->args[ii] = engine->fromVariant(*((QVariant *)a[ii + 1]));
+ callData->args[ii] = scope.engine->fromVariant(*((QVariant *)a[ii + 1]));
} else if (type == QMetaType::Int) {
//### optimization. Can go away if we switch to metaTypeToJS, or be expanded otherwise
callData->args[ii] = QV4::Primitive::fromInt32(*reinterpret_cast<const int*>(a[ii + 1]));
@@ -274,7 +274,7 @@ void QQmlBoundSignalExpression::evaluate(void **a)
else
callData->args[ii] = QV4::QObjectWrapper::wrap(ep->v4engine(), *reinterpret_cast<QObject* const *>(a[ii + 1]));
} else {
- callData->args[ii] = engine->fromVariant(QVariant(type, a[ii + 1]));
+ callData->args[ii] = scope.engine->fromVariant(QVariant(type, a[ii + 1]));
}
}
diff --git a/src/qml/qml/qqmlboundsignal_p.h b/src/qml/qml/qqmlboundsignal_p.h
index b9f519a920..6e0fbe90e6 100644
--- a/src/qml/qml/qqmlboundsignal_p.h
+++ b/src/qml/qml/qqmlboundsignal_p.h
@@ -98,10 +98,10 @@ private:
bool invalidParameterName() const { return m_extra.flag2(); }
void setInvalidParameterName(bool v) { m_extra.setFlag2Value(v); }
- QV4::PersistentValue m_v8function;
+ int m_index;
+ QV4::PersistentValue m_function;
QObject *m_target;
- int m_index;
// only needed when !expressionFunctionValid()
struct ExtraData {
diff --git a/src/qml/qml/qqmlbundle.cpp b/src/qml/qml/qqmlbundle.cpp
deleted file mode 100644
index 1034dd1b4c..0000000000
--- a/src/qml/qml/qqmlbundle.cpp
+++ /dev/null
@@ -1,310 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qqmlbundle_p.h"
-#include <iostream>
-#include <cstdlib>
-
-static const unsigned char qmlBundleHeaderData[] = { 255, 'q', 'm', 'l', 'd', 'i', 'r', 255 };
-static const unsigned int qmlBundleHeaderLength = 8;
-
-//
-// Entries
-//
-QString QQmlBundle::FileEntry::fileName() const
-{
- return QString((QChar *)&data[0], fileNameLength / sizeof(QChar));
-}
-
-bool QQmlBundle::FileEntry::isFileName(const QString &fileName) const
-{
- return fileName.length() * sizeof(QChar) == (unsigned)fileNameLength &&
- 0 == ::memcmp(fileName.constData(), &data[0], fileNameLength);
-}
-
-const char *QQmlBundle::FileEntry::contents() const {
- return &data[fileNameLength];
-}
-
-quint32 QQmlBundle::FileEntry::fileSize() const
-{
- return size - (sizeof(FileEntry) + fileNameLength);
-}
-
-
-//
-// QQmlBundle
-//
-QQmlBundle::QQmlBundle(const QString &fileName)
-: file(fileName),
- buffer(0),
- bufferSize(0),
- opened(false),
- headerWritten(false)
-{
-}
-
-QQmlBundle::~QQmlBundle()
-{
- close();
-}
-
-bool QQmlBundle::open(QIODevice::OpenMode mode)
-{
- if (!opened) {
- if (!file.open(mode))
- return false;
-
- bufferSize = file.size();
- buffer = file.map(0, bufferSize);
-
- if (bufferSize == 0 ||
- (bufferSize >= 8 && 0 == ::memcmp(buffer, qmlBundleHeaderData, qmlBundleHeaderLength))) {
- opened = true;
- headerWritten = false;
- return true;
- } else {
- close();
- return false;
- }
- }
- return true;
-}
-
-void QQmlBundle::close()
-{
- if (opened) {
- opened = false;
- headerWritten = false;
- file.unmap(buffer);
- file.close();
- }
-}
-
-QList<const QQmlBundle::FileEntry *> QQmlBundle::files() const
-{
- QList<const FileEntry *> files;
- const char *ptr = (const char *) buffer + qmlBundleHeaderLength;
- const char *end = (const char *) buffer + bufferSize;
-
- while (ptr < end) {
- const Entry *cmd = (const Entry *) ptr;
-
- switch (static_cast<Entry::Kind>(cmd->kind)) {
- case Entry::File: {
- const FileEntry *f = reinterpret_cast<const FileEntry *>(cmd);
- files.append(f);
- } break;
-
- case Entry::Link:
- case Entry::Skip: {
- // Skip
- } break;
-
- default:
- // throw an error
- return QList<const FileEntry *>();
- } // switch
-
- ptr += cmd->size;
- Q_ASSERT(ptr <= end); // throw an error
- }
- return files;
-}
-
-void QQmlBundle::remove(const FileEntry *entry)
-{
- Q_ASSERT(entry->kind == Entry::File); // ### throw an error
- Q_ASSERT(file.isWritable());
- const_cast<FileEntry *>(entry)->kind = Entry::Skip;
-}
-
-int QQmlBundle::bundleHeaderLength()
-{
- return qmlBundleHeaderLength;
-}
-
-bool QQmlBundle::isBundleHeader(const char *data, int size)
-{
- if ((unsigned int)size < qmlBundleHeaderLength)
- return false;
-
- return 0 == ::memcmp(data, qmlBundleHeaderData, qmlBundleHeaderLength);
-}
-
-//
-// find a some empty space we can use to insert new entries.
-//
-const QQmlBundle::Entry *QQmlBundle::findInsertPoint(quint32 size, qint32 *offset)
-{
- const char *ptr = (const char *) buffer + qmlBundleHeaderLength;
- const char *end = (const char *) buffer + bufferSize;
-
- while (ptr < end) {
- const Entry *cmd = (const Entry *) ptr;
-
- if (cmd->kind == Entry::Skip && size + sizeof(RawEntry) < cmd->size) {
- *offset = ptr - ((const char *) buffer + qmlBundleHeaderLength);
- return cmd;
- }
-
- ptr += cmd->size;
- Q_ASSERT(ptr <= end); // throw an error
- }
-
- return 0;
-}
-
-const QQmlBundle::FileEntry *QQmlBundle::find(const QString &fileName) const
-{
- const char *ptr = (const char *) buffer + qmlBundleHeaderLength;
- const char *end = (const char *) buffer + bufferSize;
-
- while (ptr < end) {
- const Entry *cmd = (const Entry *) ptr;
-
- if (cmd->kind == Entry::File) {
- const FileEntry *fileEntry = static_cast<const FileEntry *>(cmd);
-
- if (fileEntry->isFileName(fileName))
- return fileEntry;
- }
-
- ptr += cmd->size;
- Q_ASSERT(ptr <= end); // throw an error
- }
-
- return 0;
-}
-
-const QQmlBundle::FileEntry *QQmlBundle::link(const FileEntry *entry, const QString &linkName) const
-{
- const char *ptr = (const char *) buffer + entry->link;
-
- while (ptr != (const char *)buffer) {
- const Entry *cmd = (const Entry *) ptr;
- Q_ASSERT(cmd->kind == Entry::Link);
-
- const FileEntry *fileEntry = static_cast<const FileEntry *>(cmd);
- if (fileEntry->fileName() == linkName)
- return fileEntry;
-
- ptr = (const char *) buffer + fileEntry->link;
- }
-
- return 0;
-}
-
-const QQmlBundle::FileEntry *QQmlBundle::find(const QChar *fileName, int length) const
-{
- return find(QString::fromRawData(fileName, length));
-}
-
-bool QQmlBundle::add(const QString &name, const QString &fileName)
-{
- if (!file.isWritable())
- return false;
- else if (find(fileName))
- return false;
-
- QFile inputFile(fileName);
- if (!inputFile.open(QFile::ReadOnly))
- return false;
-
- // ### use best-fit algorithm
- if (!file.atEnd())
- file.seek(file.size());
-
- FileEntry cmd;
- const quint32 inputFileSize = inputFile.size();
-
- cmd.kind = Entry::File;
- cmd.link = 0;
- cmd.size = sizeof(FileEntry) + name.length() * sizeof(QChar) + inputFileSize;
- cmd.fileNameLength = name.length() * sizeof(QChar);
-
- if (bufferSize == 0 && headerWritten == false) {
- file.write((const char *)qmlBundleHeaderData, qmlBundleHeaderLength);
- headerWritten = true;
- }
-
- file.write((const char *) &cmd, sizeof(FileEntry));
- file.write((const char *) name.constData(), name.length() * sizeof(QChar));
-
- uchar *source = inputFile.map(0, inputFileSize);
- file.write((const char *) source, inputFileSize);
- inputFile.unmap(source);
- return true;
-}
-
-bool QQmlBundle::add(const QString &fileName)
-{
- return add(fileName, fileName);
-}
-
-bool QQmlBundle::addMetaLink(const QString &fileName,
- const QString &linkName,
- const QByteArray &data)
-{
- if (!file.isWritable())
- return false;
-
- const FileEntry *fileEntry = find(fileName);
- if (!fileEntry)
- return false;
-
- // ### use best-fit algorithm
- if (!file.atEnd())
- file.seek(file.size());
-
- FileEntry cmd;
-
- const quint32 inputFileSize = data.size();
-
- cmd.kind = Entry::Link;
- cmd.link = fileEntry->link;
- cmd.size = sizeof(FileEntry) + linkName.length() * sizeof(QChar) + inputFileSize;
- cmd.fileNameLength = linkName.length() * sizeof(QChar);
-
- if (bufferSize == 0 && headerWritten == false) {
- file.write((const char *)qmlBundleHeaderData, qmlBundleHeaderLength);
- headerWritten = true;
- }
-
- const_cast<FileEntry *>(fileEntry)->link = file.size();
-
- file.write((const char *) &cmd, sizeof(FileEntry));
- file.write((const char *) linkName.constData(), linkName.length() * sizeof(QChar));
- file.write((const char *) data.constData(), inputFileSize);
- return true;
-}
diff --git a/src/qml/qml/qqmlbundle_p.h b/src/qml/qml/qqmlbundle_p.h
deleted file mode 100644
index e1066ed378..0000000000
--- a/src/qml/qml/qqmlbundle_p.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QQMLBUNDLE_P_H
-#define QQMLBUNDLE_P_H
-
-#include <QtCore/qfile.h>
-#include <QtCore/qstring.h>
-#include <private/qtqmlglobal_p.h>
-
-#ifdef Q_CC_MSVC
-// nonstandard extension used : zero-sized array in struct/union.
-# pragma warning( disable : 4200 )
-#endif
-
-QT_BEGIN_NAMESPACE
-
-class Q_QML_PRIVATE_EXPORT QQmlBundle
-{
- Q_DISABLE_COPY(QQmlBundle)
-public:
- struct Q_QML_PRIVATE_EXPORT Entry
- {
- enum Kind {
- File = 123, // Normal file
- Skip, // Empty space
- Link // A meta data linked file
-
- // ### add entries for qmldir, index, ...
- };
-
- int kind;
- quint32 size;
- };
-
- struct Q_QML_PRIVATE_EXPORT RawEntry : public Entry
- {
- char data[]; // trailing data
- };
-
- struct Q_QML_PRIVATE_EXPORT FileEntry : public Entry
- {
- quint32 link;
- int fileNameLength;
- char data[]; // trailing data
-
- QString fileName() const;
- bool isFileName(const QString &) const;
-
- quint32 fileSize() const;
- const char *contents() const;
- };
-
- QQmlBundle(const QString &fileName);
- ~QQmlBundle();
-
- bool open(QIODevice::OpenMode mode = QIODevice::ReadWrite);
- void close();
-
- QList<const FileEntry *> files() const;
- void remove(const FileEntry *entry);
- bool add(const QString &fileName);
- bool add(const QString &name, const QString &fileName);
-
- bool addMetaLink(const QString &fileName,
- const QString &linkName,
- const QByteArray &data);
-
- const FileEntry *find(const QString &fileName) const;
- const FileEntry *find(const QChar *fileName, int length) const;
-
- const FileEntry *link(const FileEntry *, const QString &linkName) const;
-
- static int bundleHeaderLength();
- static bool isBundleHeader(const char *, int size);
-private:
- const Entry *findInsertPoint(quint32 size, qint32 *offset);
-
-private:
- QFile file;
- uchar *buffer;
- quint32 bufferSize;
- bool opened:1;
- bool headerWritten:1;
-};
-
-QT_END_NAMESPACE
-
-#endif // QQMLBUNDLE_P_H
diff --git a/src/qml/qml/qqmlcompiler_p.h b/src/qml/qml/qqmlcompiler_p.h
index 5e76533739..3569a106c9 100644
--- a/src/qml/qml/qqmlcompiler_p.h
+++ b/src/qml/qml/qqmlcompiler_p.h
@@ -84,7 +84,7 @@ public:
QQmlEngine *engine;
QString fileName() const { return compilationUnit->fileName(); }
- QUrl url() const { return QUrl(fileName()); }
+ QUrl url() const { return compilationUnit->url(); }
QQmlTypeNameCache *importCache;
int metaTypeId;
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index 63a43966b1..8f146b7a8a 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -87,12 +87,12 @@ QT_BEGIN_NAMESPACE
class QQmlComponentExtension : public QV8Engine::Deletable
{
public:
- QQmlComponentExtension(QV8Engine *);
+ QQmlComponentExtension(QV4::ExecutionEngine *v4);
virtual ~QQmlComponentExtension();
QV4::PersistentValue incubationProto;
};
-V8_DEFINE_EXTENSION(QQmlComponentExtension, componentExtension);
+V4_DEFINE_EXTENSION(QQmlComponentExtension, componentExtension);
/*!
\class QQmlComponent
@@ -675,9 +675,9 @@ void QQmlComponentPrivate::loadUrl(const QUrl &newUrl, QQmlComponent::Compilatio
emit q->progressChanged(progress);
}
- QQmlDataLoader::Mode loaderMode = (mode == QQmlComponent::Asynchronous)
- ? QQmlDataLoader::Asynchronous
- : QQmlDataLoader::PreferSynchronous;
+ QQmlTypeLoader::Mode loaderMode = (mode == QQmlComponent::Asynchronous)
+ ? QQmlTypeLoader::Asynchronous
+ : QQmlTypeLoader::PreferSynchronous;
QQmlTypeData *data = QQmlEnginePrivate::get(engine)->typeLoader.getType(url, loaderMode);
@@ -1070,18 +1070,25 @@ void QQmlComponent::create(QQmlIncubator &incubator, QQmlContext *context,
class QQmlComponentIncubator;
+namespace QV4 {
+
+namespace Heap {
+
+struct QmlIncubatorObject : Object {
+ QmlIncubatorObject(QV4::ExecutionEngine *engine, QQmlIncubator::IncubationMode = QQmlIncubator::Asynchronous);
+ QScopedPointer<QQmlComponentIncubator> incubator;
+ QPointer<QObject> parent;
+ QV4::Value valuemap;
+ QV4::Value qmlGlobal;
+ QV4::Value statusChanged;
+};
+
+}
+
struct QmlIncubatorObject : public QV4::Object
{
- struct Data : QV4::Object::Data {
- Data(QV8Engine *engine, QQmlIncubator::IncubationMode = QQmlIncubator::Asynchronous);
- QScopedPointer<QQmlComponentIncubator> incubator;
- QV8Engine *v8;
- QPointer<QObject> parent;
- QV4::Value valuemap;
- QV4::Value qmlGlobal;
- QV4::Value statusChanged;
- };
- V4_OBJECT(QV4::Object)
+ V4_OBJECT2(QmlIncubatorObject, Object)
+ V4_NEEDS_DESTROY
static QV4::ReturnedValue method_get_statusChanged(QV4::CallContext *ctx);
static QV4::ReturnedValue method_set_statusChanged(QV4::CallContext *ctx);
@@ -1089,36 +1096,37 @@ struct QmlIncubatorObject : public QV4::Object
static QV4::ReturnedValue method_get_object(QV4::CallContext *ctx);
static QV4::ReturnedValue method_forceCompletion(QV4::CallContext *ctx);
- static void destroy(Managed *that);
- static void markObjects(Managed *that, QV4::ExecutionEngine *e);
+ static void markObjects(QV4::Heap::Base *that, QV4::ExecutionEngine *e);
void statusChanged(QQmlIncubator::Status);
void setInitialState(QObject *);
};
-DEFINE_OBJECT_VTABLE(QmlIncubatorObject);
+}
+
+DEFINE_OBJECT_VTABLE(QV4::QmlIncubatorObject);
class QQmlComponentIncubator : public QQmlIncubator
{
public:
- QQmlComponentIncubator(QmlIncubatorObject::Data *inc, IncubationMode mode)
+ QQmlComponentIncubator(QV4::Heap::QmlIncubatorObject *inc, IncubationMode mode)
: QQmlIncubator(mode)
, incubatorObject(inc)
{}
virtual void statusChanged(Status s) {
QV4::Scope scope(incubatorObject->internalClass->engine);
- QV4::Scoped<QmlIncubatorObject> i(scope, incubatorObject);
+ QV4::Scoped<QV4::QmlIncubatorObject> i(scope, incubatorObject);
i->statusChanged(s);
}
virtual void setInitialState(QObject *o) {
QV4::Scope scope(incubatorObject->internalClass->engine);
- QV4::Scoped<QmlIncubatorObject> i(scope, incubatorObject);
+ QV4::Scoped<QV4::QmlIncubatorObject> i(scope, incubatorObject);
i->setInitialState(o);
}
- QmlIncubatorObject::Data *incubatorObject;
+ QV4::Heap::QmlIncubatorObject *incubatorObject;
};
@@ -1236,7 +1244,7 @@ void QQmlComponent::createObject(QQmlV4Function *args)
QV4::ScopedValue f(scope, QV4::Script::evaluate(v4, QString::fromLatin1(INITIALPROPERTIES_SOURCE), qmlglobal));
Q_ASSERT(f->asFunctionObject());
QV4::ScopedCallData callData(scope, 2);
- callData->thisObject = v4->globalObject;
+ callData->thisObject = v4->globalObject();
callData->args[0] = object;
callData->args[1] = valuemap;
f->asFunctionObject()->call(callData);
@@ -1352,11 +1360,11 @@ void QQmlComponent::incubateObject(QQmlV4Function *args)
mode = QQmlIncubator::AsynchronousIfNested;
}
- QQmlComponentExtension *e = componentExtension(args->engine());
+ QQmlComponentExtension *e = componentExtension(args->v4engine());
- QV4::Scoped<QmlIncubatorObject> r(scope, v4->memoryManager->alloc<QmlIncubatorObject>(args->engine(), mode));
+ QV4::Scoped<QV4::QmlIncubatorObject> r(scope, v4->memoryManager->alloc<QV4::QmlIncubatorObject>(args->v4engine(), mode));
QV4::ScopedObject p(scope, e->incubationProto.value());
- r->setPrototype(p.getPointer());
+ r->setPrototype(p);
if (!valuemap->isUndefined()) {
r->d()->valuemap = valuemap;
@@ -1364,7 +1372,7 @@ void QQmlComponent::incubateObject(QQmlV4Function *args)
}
r->d()->parent = parent;
- QQmlIncubator *incubator = r.getPointer()->d()->incubator.data();
+ QQmlIncubator *incubator = r->d()->incubator.data();
create(*incubator, creationContext());
if (incubator->status() == QQmlIncubator::Null) {
@@ -1378,8 +1386,7 @@ void QQmlComponent::incubateObject(QQmlV4Function *args)
void QQmlComponentPrivate::initializeObjectWithInitialProperties(const QV4::ValueRef qmlGlobal, const QV4::ValueRef valuemap, QObject *toCreate)
{
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine);
- QV8Engine *v8engine = ep->v8engine();
- QV4::ExecutionEngine *v4engine = QV8Engine::getV4(v8engine);
+ QV4::ExecutionEngine *v4engine = QV8Engine::getV4(ep->v8engine());
QV4::Scope scope(v4engine);
QV4::ScopedValue object(scope, QV4::QObjectWrapper::wrap(v4engine, toCreate));
@@ -1387,78 +1394,77 @@ void QQmlComponentPrivate::initializeObjectWithInitialProperties(const QV4::Valu
if (!valuemap->isUndefined()) {
QV4::ScopedObject qmlGlobalObj(scope, qmlGlobal);
- QV4::Scoped<QV4::FunctionObject> f(scope, QV4::Script::evaluate(QV8Engine::getV4(v8engine),
- QString::fromLatin1(INITIALPROPERTIES_SOURCE), qmlGlobalObj));
+ QV4::ScopedFunctionObject f(scope, QV4::Script::evaluate(v4engine,
+ QString::fromLatin1(INITIALPROPERTIES_SOURCE), qmlGlobalObj));
QV4::ScopedCallData callData(scope, 2);
- callData->thisObject = v4engine->globalObject;
+ callData->thisObject = v4engine->globalObject();
callData->args[0] = object;
callData->args[1] = valuemap;
f->call(callData);
}
}
-QQmlComponentExtension::QQmlComponentExtension(QV8Engine *engine)
+QQmlComponentExtension::QQmlComponentExtension(QV4::ExecutionEngine *v4)
{
- QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
QV4::Scope scope(v4);
- QV4::Scoped<QV4::Object> proto(scope, v4->newObject());
+ QV4::ScopedObject proto(scope, v4->newObject());
proto->defineAccessorProperty(QStringLiteral("onStatusChanged"),
- QmlIncubatorObject::method_get_statusChanged, QmlIncubatorObject::method_set_statusChanged);
- proto->defineAccessorProperty(QStringLiteral("status"), QmlIncubatorObject::method_get_status, 0);
- proto->defineAccessorProperty(QStringLiteral("object"), QmlIncubatorObject::method_get_object, 0);
- proto->defineDefaultProperty(QStringLiteral("forceCompletion"), QmlIncubatorObject::method_forceCompletion);
+ QV4::QmlIncubatorObject::method_get_statusChanged, QV4::QmlIncubatorObject::method_set_statusChanged);
+ proto->defineAccessorProperty(QStringLiteral("status"), QV4::QmlIncubatorObject::method_get_status, 0);
+ proto->defineAccessorProperty(QStringLiteral("object"), QV4::QmlIncubatorObject::method_get_object, 0);
+ proto->defineDefaultProperty(QStringLiteral("forceCompletion"), QV4::QmlIncubatorObject::method_forceCompletion);
- incubationProto = proto;
+ incubationProto.set(v4, proto);
}
-QV4::ReturnedValue QmlIncubatorObject::method_get_object(QV4::CallContext *ctx)
+QV4::ReturnedValue QV4::QmlIncubatorObject::method_get_object(QV4::CallContext *ctx)
{
QV4::Scope scope(ctx);
QV4::Scoped<QmlIncubatorObject> o(scope, ctx->d()->callData->thisObject.as<QmlIncubatorObject>());
if (!o)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
return QV4::QObjectWrapper::wrap(ctx->d()->engine, o->d()->incubator->object());
}
-QV4::ReturnedValue QmlIncubatorObject::method_forceCompletion(QV4::CallContext *ctx)
+QV4::ReturnedValue QV4::QmlIncubatorObject::method_forceCompletion(QV4::CallContext *ctx)
{
QV4::Scope scope(ctx);
QV4::Scoped<QmlIncubatorObject> o(scope, ctx->d()->callData->thisObject.as<QmlIncubatorObject>());
if (!o)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
o->d()->incubator->forceCompletion();
return QV4::Encode::undefined();
}
-QV4::ReturnedValue QmlIncubatorObject::method_get_status(QV4::CallContext *ctx)
+QV4::ReturnedValue QV4::QmlIncubatorObject::method_get_status(QV4::CallContext *ctx)
{
QV4::Scope scope(ctx);
QV4::Scoped<QmlIncubatorObject> o(scope, ctx->d()->callData->thisObject.as<QmlIncubatorObject>());
if (!o)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
return QV4::Encode(o->d()->incubator->status());
}
-QV4::ReturnedValue QmlIncubatorObject::method_get_statusChanged(QV4::CallContext *ctx)
+QV4::ReturnedValue QV4::QmlIncubatorObject::method_get_statusChanged(QV4::CallContext *ctx)
{
QV4::Scope scope(ctx);
QV4::Scoped<QmlIncubatorObject> o(scope, ctx->d()->callData->thisObject.as<QmlIncubatorObject>());
if (!o)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
return o->d()->statusChanged.asReturnedValue();
}
-QV4::ReturnedValue QmlIncubatorObject::method_set_statusChanged(QV4::CallContext *ctx)
+QV4::ReturnedValue QV4::QmlIncubatorObject::method_set_statusChanged(QV4::CallContext *ctx)
{
QV4::Scope scope(ctx);
QV4::Scoped<QmlIncubatorObject> o(scope, ctx->d()->callData->thisObject.as<QmlIncubatorObject>());
if (!o || ctx->d()->callData->argc < 1)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
o->d()->statusChanged = ctx->d()->callData->args[0];
@@ -1469,53 +1475,46 @@ QQmlComponentExtension::~QQmlComponentExtension()
{
}
-QmlIncubatorObject::Data::Data(QV8Engine *engine, QQmlIncubator::IncubationMode m)
- : Object::Data(QV8Engine::getV4(engine))
- , v8(engine)
+QV4::Heap::QmlIncubatorObject::QmlIncubatorObject(ExecutionEngine *engine, QQmlIncubator::IncubationMode m)
+ : QV4::Heap::Object(engine)
, valuemap(QV4::Primitive::undefinedValue())
, qmlGlobal(QV4::Primitive::undefinedValue())
, statusChanged(QV4::Primitive::undefinedValue())
{
- setVTable(staticVTable());
+ setVTable(QV4::QmlIncubatorObject::staticVTable());
incubator.reset(new QQmlComponentIncubator(this, m));
}
-void QmlIncubatorObject::setInitialState(QObject *o)
+void QV4::QmlIncubatorObject::setInitialState(QObject *o)
{
QQmlComponent_setQmlParent(o, d()->parent);
if (!d()->valuemap.isUndefined()) {
- QV4::ExecutionEngine *v4 = QV8Engine::getV4(d()->v8);
+ QV4::ExecutionEngine *v4 = engine();
QV4::Scope scope(v4);
- QV4::Scoped<QV4::FunctionObject> f(scope, QV4::Script::evaluate(v4, QString::fromLatin1(INITIALPROPERTIES_SOURCE), d()->qmlGlobal.asObject()));
+ QV4::ScopedFunctionObject f(scope, QV4::Script::evaluate(v4, QString::fromLatin1(INITIALPROPERTIES_SOURCE), d()->qmlGlobal.asObject()));
QV4::ScopedCallData callData(scope, 2);
- callData->thisObject = v4->globalObject;
+ callData->thisObject = v4->globalObject();
callData->args[0] = QV4::QObjectWrapper::wrap(v4, o);
callData->args[1] = d()->valuemap;
f->call(callData);
}
}
-void QmlIncubatorObject::destroy(Managed *that)
-{
- static_cast<QmlIncubatorObject *>(that)->d()->~Data();
-}
-
-void QmlIncubatorObject::markObjects(QV4::Managed *that, QV4::ExecutionEngine *e)
+void QV4::QmlIncubatorObject::markObjects(QV4::Heap::Base *that, QV4::ExecutionEngine *e)
{
- QmlIncubatorObject *o = static_cast<QmlIncubatorObject *>(that);
- Q_ASSERT(that->as<QmlIncubatorObject>());
- o->d()->valuemap.mark(e);
- o->d()->qmlGlobal.mark(e);
- o->d()->statusChanged.mark(e);
+ QmlIncubatorObject::Data *o = static_cast<QmlIncubatorObject::Data *>(that);
+ o->valuemap.mark(e);
+ o->qmlGlobal.mark(e);
+ o->statusChanged.mark(e);
Object::markObjects(that, e);
}
-void QmlIncubatorObject::statusChanged(QQmlIncubator::Status s)
+void QV4::QmlIncubatorObject::statusChanged(QQmlIncubator::Status s)
{
- QV4::Scope scope(QV8Engine::getV4(d()->v8));
+ QV4::Scope scope(engine());
// hold the incubated object in a scoped value to prevent it's destruction before this method returns
QV4::ScopedObject incubatedObject(scope, QV4::QObjectWrapper::wrap(scope.engine, d()->incubator->object()));
@@ -1527,14 +1526,13 @@ void QmlIncubatorObject::statusChanged(QQmlIncubator::Status s)
QV4::ScopedFunctionObject f(scope, d()->statusChanged);
if (f) {
- QV4::ExecutionContext *ctx = scope.engine->currentContext();
QV4::ScopedCallData callData(scope, 1);
callData->thisObject = this;
callData->args[0] = QV4::Primitive::fromUInt32(s);
f->call(callData);
if (scope.hasException()) {
- QQmlError error = QV4::ExecutionEngine::catchExceptionAsQmlError(ctx);
- QQmlEnginePrivate::warning(QQmlEnginePrivate::get(d()->v8->engine()), error);
+ QQmlError error = scope.engine->catchExceptionAsQmlError();
+ QQmlEnginePrivate::warning(QQmlEnginePrivate::get(scope.engine->qmlEngine()), error);
}
}
}
diff --git a/src/qml/qml/qqmlcontextwrapper.cpp b/src/qml/qml/qqmlcontextwrapper.cpp
index 0816bc05df..78a77f79d4 100644
--- a/src/qml/qml/qqmlcontextwrapper.cpp
+++ b/src/qml/qml/qqmlcontextwrapper.cpp
@@ -53,35 +53,33 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(QmlContextWrapper);
-QmlContextWrapper::Data::Data(QV8Engine *engine, QQmlContextData *context, QObject *scopeObject, bool ownsContext)
- : Object::Data(QV8Engine::getV4(engine))
+Heap::QmlContextWrapper::QmlContextWrapper(QV4::ExecutionEngine *engine, QQmlContextData *context, QObject *scopeObject, bool ownsContext)
+ : Heap::Object(engine)
, readOnly(true)
, ownsContext(ownsContext)
, isNullWrapper(false)
, context(context)
, scopeObject(scopeObject)
{
- setVTable(staticVTable());
+ setVTable(QV4::QmlContextWrapper::staticVTable());
}
-QmlContextWrapper::Data::~Data()
+Heap::QmlContextWrapper::~QmlContextWrapper()
{
if (context && ownsContext)
context->destroy();
}
-ReturnedValue QmlContextWrapper::qmlScope(QV8Engine *v8, QQmlContextData *ctxt, QObject *scope)
+ReturnedValue QmlContextWrapper::qmlScope(ExecutionEngine *v4, QQmlContextData *ctxt, QObject *scope)
{
- ExecutionEngine *v4 = QV8Engine::getV4(v8);
Scope valueScope(v4);
- Scoped<QmlContextWrapper> w(valueScope, v4->memoryManager->alloc<QmlContextWrapper>(v8, ctxt, scope));
+ Scoped<QmlContextWrapper> w(valueScope, v4->memoryManager->alloc<QmlContextWrapper>(v4, ctxt, scope));
return w.asReturnedValue();
}
-ReturnedValue QmlContextWrapper::urlScope(QV8Engine *v8, const QUrl &url)
+ReturnedValue QmlContextWrapper::urlScope(ExecutionEngine *v4, const QUrl &url)
{
- ExecutionEngine *v4 = QV8Engine::getV4(v8);
Scope scope(v4);
QQmlContextData *context = new QQmlContextData;
@@ -89,7 +87,7 @@ ReturnedValue QmlContextWrapper::urlScope(QV8Engine *v8, const QUrl &url)
context->isInternal = true;
context->isJSContext = true;
- Scoped<QmlContextWrapper> w(scope, v4->memoryManager->alloc<QmlContextWrapper>(v8, context, (QObject*)0, true));
+ Scoped<QmlContextWrapper> w(scope, v4->memoryManager->alloc<QmlContextWrapper>(v4, context, (QObject*)0, true));
w->d()->isNullWrapper = true;
return w.asReturnedValue();
}
@@ -97,17 +95,17 @@ ReturnedValue QmlContextWrapper::urlScope(QV8Engine *v8, const QUrl &url)
QQmlContextData *QmlContextWrapper::callingContext(ExecutionEngine *v4)
{
Scope scope(v4);
- QV4::Scoped<QmlContextWrapper> c(scope, v4->qmlContextObject(), QV4::Scoped<QmlContextWrapper>::Cast);
+ QV4::Scoped<QmlContextWrapper> c(scope, v4->qmlContextObject());
return !!c ? c->getContext() : 0;
}
QQmlContextData *QmlContextWrapper::getContext(const ValueRef value)
{
- QV4::ExecutionEngine *v4 = value->engine();
- if (!v4)
+ if (!value->isObject())
return 0;
+ QV4::ExecutionEngine *v4 = value->asObject()->engine();
Scope scope(v4);
QV4::Scoped<QmlContextWrapper> c(scope, value);
@@ -116,9 +114,9 @@ QQmlContextData *QmlContextWrapper::getContext(const ValueRef value)
void QmlContextWrapper::takeContextOwnership(const ValueRef qmlglobal)
{
- QV4::ExecutionEngine *v4 = qmlglobal->engine();
- Q_ASSERT(v4);
+ Q_ASSERT(qmlglobal->isObject());
+ QV4::ExecutionEngine *v4 = qmlglobal->asObject()->engine();
Scope scope(v4);
QV4::Scoped<QmlContextWrapper> c(scope, qmlglobal);
Q_ASSERT(c);
@@ -136,7 +134,7 @@ ReturnedValue QmlContextWrapper::get(Managed *m, String *name, bool *hasProperty
// In V8 the JS global object would come _before_ the QML global object,
// so simulate that here.
bool hasProp;
- QV4::ScopedValue result(scope, v4->globalObject->get(name, &hasProp));
+ QV4::ScopedValue result(scope, v4->globalObject()->get(name, &hasProp));
if (hasProp) {
if (hasProperty)
*hasProperty = hasProp;
@@ -175,8 +173,6 @@ ReturnedValue QmlContextWrapper::get(Managed *m, String *name, bool *hasProperty
// context = context->parent
// }
- QV8Engine *engine = v4->v8Engine;
-
QObject *scopeObject = resource->getScopeObject();
if (context->imports && name->startsWithUpper()) {
@@ -190,9 +186,9 @@ ReturnedValue QmlContextWrapper::get(Managed *m, String *name, bool *hasProperty
QV4::ScopedObject scripts(scope, context->importedScripts);
return scripts->getIndexed(r.scriptIndex);
} else if (r.type) {
- return QmlTypeWrapper::create(engine, scopeObject, r.type);
+ return QmlTypeWrapper::create(v4, scopeObject, r.type);
} else if (r.importNamespace) {
- return QmlTypeWrapper::create(engine, scopeObject, context->imports, r.importNamespace);
+ return QmlTypeWrapper::create(v4, scopeObject, context->imports, r.importNamespace);
}
Q_ASSERT(!"Unreachable");
}
@@ -200,7 +196,7 @@ ReturnedValue QmlContextWrapper::get(Managed *m, String *name, bool *hasProperty
// Fall through
}
- QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine->engine());
+ QQmlEnginePrivate *ep = QQmlEnginePrivate::get(v4->qmlEngine());
while (context) {
// Search context properties
@@ -229,9 +225,9 @@ ReturnedValue QmlContextWrapper::get(Managed *m, String *name, bool *hasProperty
QQmlListProperty<QObject> prop(context->asQQmlContext(), (void*) qintptr(propertyIdx),
QQmlContextPrivate::context_count,
QQmlContextPrivate::context_at);
- return QmlListWrapper::create(engine, prop, qMetaTypeId<QQmlListProperty<QObject> >());
+ return QmlListWrapper::create(v4, prop, qMetaTypeId<QQmlListProperty<QObject> >());
} else {
- return engine->fromVariant(cp->propertyValues.at(propertyIdx));
+ return scope.engine->fromVariant(cp->propertyValues.at(propertyIdx));
}
}
}
@@ -240,7 +236,7 @@ ReturnedValue QmlContextWrapper::get(Managed *m, String *name, bool *hasProperty
// Search scope object
if (scopeObject) {
bool hasProp = false;
- QV4::ScopedValue result(scope, QV4::QObjectWrapper::getQmlProperty(v4->currentContext(), context, scopeObject,
+ QV4::ScopedValue result(scope, QV4::QObjectWrapper::getQmlProperty(v4, context, scopeObject,
name, QV4::QObjectWrapper::CheckRevision, &hasProp));
if (hasProp) {
if (hasProperty)
@@ -254,7 +250,7 @@ ReturnedValue QmlContextWrapper::get(Managed *m, String *name, bool *hasProperty
// Search context object
if (context->contextObject) {
bool hasProp = false;
- result = QV4::QObjectWrapper::getQmlProperty(v4->currentContext(), context, context->contextObject, name, QV4::QObjectWrapper::CheckRevision, &hasProp);
+ result = QV4::QObjectWrapper::getQmlProperty(v4, context, context->contextObject, name, QV4::QObjectWrapper::CheckRevision, &hasProp);
if (hasProp) {
if (hasProperty)
*hasProperty = true;
@@ -290,8 +286,8 @@ void QmlContextWrapper::put(Managed *m, String *name, const ValueRef value)
if (wrapper && wrapper->d()->readOnly) {
QString error = QLatin1String("Invalid write to global property \"") + name->toQString() +
QLatin1Char('"');
- Scoped<String> e(scope, v4->currentContext()->d()->engine->newString(error));
- v4->currentContext()->throwError(e);
+ ScopedString e(scope, v4->currentContext()->engine->newString(error));
+ v4->throwError(e);
return;
}
@@ -318,13 +314,13 @@ void QmlContextWrapper::put(Managed *m, String *name, const ValueRef value)
// Search scope object
if (scopeObject &&
- QV4::QObjectWrapper::setQmlProperty(v4->currentContext(), context, scopeObject, name, QV4::QObjectWrapper::CheckRevision, value))
+ QV4::QObjectWrapper::setQmlProperty(v4, context, scopeObject, name, QV4::QObjectWrapper::CheckRevision, value))
return;
scopeObject = 0;
// Search context object
if (context->contextObject &&
- QV4::QObjectWrapper::setQmlProperty(v4->currentContext(), context, context->contextObject, name, QV4::QObjectWrapper::CheckRevision, value))
+ QV4::QObjectWrapper::setQmlProperty(v4, context, context->contextObject, name, QV4::QObjectWrapper::CheckRevision, value))
return;
context = context->parent;
@@ -335,23 +331,18 @@ void QmlContextWrapper::put(Managed *m, String *name, const ValueRef value)
if (wrapper->d()->readOnly) {
QString error = QLatin1String("Invalid write to global property \"") + name->toQString() +
QLatin1Char('"');
- v4->currentContext()->throwError(error);
+ v4->throwError(error);
return;
}
Object::put(m, name, value);
}
-void QmlContextWrapper::destroy(Managed *that)
-{
- static_cast<QmlContextWrapper *>(that)->d()->~Data();
-}
-
-void QmlContextWrapper::markObjects(Managed *m, ExecutionEngine *engine)
+void QmlContextWrapper::markObjects(Heap::Base *m, ExecutionEngine *engine)
{
- QmlContextWrapper *This = static_cast<QmlContextWrapper*>(m);
- if (This->d()->idObjectsWrapper)
- This->d()->idObjectsWrapper->mark(engine);
+ QmlContextWrapper::Data *This = static_cast<QmlContextWrapper::Data *>(m);
+ if (This->idObjectsWrapper)
+ This->idObjectsWrapper->mark(engine);
Object::markObjects(m, engine);
}
@@ -360,7 +351,7 @@ void QmlContextWrapper::registerQmlDependencies(ExecutionEngine *engine, const C
// Let the caller check and avoid the function call :)
Q_ASSERT(compiledFunction->hasQmlDependencies());
- QQmlEnginePrivate *ep = engine->v8Engine->engine() ? QQmlEnginePrivate::get(engine->v8Engine->engine()) : 0;
+ QQmlEnginePrivate *ep = engine->qmlEngine() ? QQmlEnginePrivate::get(engine->qmlEngine()) : 0;
if (!ep)
return;
QQmlEnginePrivate::PropertyCapture *capture = ep->propertyCapture;
@@ -368,7 +359,7 @@ void QmlContextWrapper::registerQmlDependencies(ExecutionEngine *engine, const C
return;
QV4::Scope scope(engine);
- QV4::Scoped<QmlContextWrapper> contextWrapper(scope, engine->qmlContextObject(), QV4::Scoped<QmlContextWrapper>::Cast);
+ QV4::Scoped<QmlContextWrapper> contextWrapper(scope, engine->qmlContextObject());
QQmlContextData *qmlContext = contextWrapper->getContext();
const quint32 *idObjectDependency = compiledFunction->qmlIdObjectDependencyTable();
@@ -402,14 +393,12 @@ ReturnedValue QmlContextWrapper::idObjectsArray()
{
if (!d()->idObjectsWrapper) {
ExecutionEngine *v4 = engine();
- Scope scope(v4);
- Scoped<QQmlIdObjectsArray> a(scope, v4->memoryManager->alloc<QQmlIdObjectsArray>(v4, this));
- d()->idObjectsWrapper = a.getPointer();
+ d()->idObjectsWrapper = v4->memoryManager->alloc<QQmlIdObjectsArray>(v4, this);
}
return d()->idObjectsWrapper->asReturnedValue();
}
-ReturnedValue QmlContextWrapper::qmlSingletonWrapper(QV8Engine *v8, String *name)
+ReturnedValue QmlContextWrapper::qmlSingletonWrapper(ExecutionEngine *v4, String *name)
{
if (!d()->context->imports)
return Encode::undefined();
@@ -419,9 +408,9 @@ ReturnedValue QmlContextWrapper::qmlSingletonWrapper(QV8Engine *v8, String *name
Q_ASSERT(r.isValid());
Q_ASSERT(r.type);
Q_ASSERT(r.type->isSingleton());
- Q_ASSERT(v8);
+ Q_ASSERT(v4);
- QQmlEngine *e = v8->engine();
+ QQmlEngine *e = v4->qmlEngine();
QQmlType::SingletonInstanceInfo *siinfo = r.type->singletonInstanceInfo();
siinfo->init(e);
@@ -432,17 +421,19 @@ ReturnedValue QmlContextWrapper::qmlSingletonWrapper(QV8Engine *v8, String *name
DEFINE_OBJECT_VTABLE(QQmlIdObjectsArray);
-QQmlIdObjectsArray::Data::Data(ExecutionEngine *engine, QmlContextWrapper *contextWrapper)
- : Object::Data(engine)
- , contextWrapper(contextWrapper)
+Heap::QQmlIdObjectsArray::QQmlIdObjectsArray(ExecutionEngine *engine, QV4::QmlContextWrapper *contextWrapper)
+ : Heap::Object(engine)
+ , contextWrapper(contextWrapper->d())
{
- setVTable(staticVTable());
+ setVTable(QV4::QQmlIdObjectsArray::staticVTable());
}
ReturnedValue QQmlIdObjectsArray::getIndexed(Managed *m, uint index, bool *hasProperty)
{
- QQmlIdObjectsArray *This = static_cast<QQmlIdObjectsArray*>(m);
- QQmlContextData *context = This->d()->contextWrapper->getContext();
+ Scope scope(m->engine());
+ Scoped<QQmlIdObjectsArray> This(scope, static_cast<QV4::QQmlIdObjectsArray*>(m));
+ Scoped<QmlContextWrapper> contextWrapper(scope, This->d()->contextWrapper);
+ QQmlContextData *context = contextWrapper->getContext();
if (!context) {
if (hasProperty)
*hasProperty = false;
@@ -458,17 +449,17 @@ ReturnedValue QQmlIdObjectsArray::getIndexed(Managed *m, uint index, bool *hasPr
*hasProperty = true;
ExecutionEngine *v4 = m->engine();
- QQmlEnginePrivate *ep = v4->v8Engine->engine() ? QQmlEnginePrivate::get(v4->v8Engine->engine()) : 0;
+ QQmlEnginePrivate *ep = v4->qmlEngine() ? QQmlEnginePrivate::get(v4->qmlEngine()) : 0;
if (ep)
ep->captureProperty(&context->idValues[index].bindings);
return QObjectWrapper::wrap(This->engine(), context->idValues[index].data());
}
-void QQmlIdObjectsArray::markObjects(Managed *that, ExecutionEngine *engine)
+void QQmlIdObjectsArray::markObjects(Heap::Base *that, ExecutionEngine *engine)
{
- QQmlIdObjectsArray *This = static_cast<QQmlIdObjectsArray*>(that);
- This->d()->contextWrapper->mark(engine);
+ QQmlIdObjectsArray::Data *This = static_cast<QQmlIdObjectsArray::Data *>(that);
+ This->contextWrapper->mark(engine);
Object::markObjects(that, engine);
}
diff --git a/src/qml/qml/qqmlcontextwrapper_p.h b/src/qml/qml/qqmlcontextwrapper_p.h
index cae6800f48..96c7bc9af4 100644
--- a/src/qml/qml/qqmlcontextwrapper_p.h
+++ b/src/qml/qml/qqmlcontextwrapper_p.h
@@ -61,25 +61,38 @@ namespace CompiledData {
struct Function;
}
+struct QmlContextWrapper;
+
+namespace Heap {
+
struct QQmlIdObjectsArray;
+struct QmlContextWrapper : Object {
+ QmlContextWrapper(ExecutionEngine *engine, QQmlContextData *context, QObject *scopeObject, bool ownsContext = false);
+ ~QmlContextWrapper();
+ bool readOnly;
+ bool ownsContext;
+ bool isNullWrapper;
+
+ QQmlGuardedContextData context;
+ QPointer<QObject> scopeObject;
+ QQmlIdObjectsArray *idObjectsWrapper;
+};
+
+struct QQmlIdObjectsArray : Object {
+ QQmlIdObjectsArray(QV4::ExecutionEngine *engine, QV4::QmlContextWrapper *contextWrapper);
+ QmlContextWrapper *contextWrapper;
+};
+
+}
+
struct Q_QML_EXPORT QmlContextWrapper : Object
{
- struct Data : Object::Data {
- Data(QV8Engine *engine, QQmlContextData *context, QObject *scopeObject, bool ownsContext = false);
- ~Data();
- bool readOnly;
- bool ownsContext;
- bool isNullWrapper;
-
- QQmlGuardedContextData context;
- QPointer<QObject> scopeObject;
- QQmlIdObjectsArray *idObjectsWrapper;
- };
- V4_OBJECT(Object)
-
- static ReturnedValue qmlScope(QV8Engine *e, QQmlContextData *ctxt, QObject *scope);
- static ReturnedValue urlScope(QV8Engine *e, const QUrl &);
+ V4_OBJECT2(QmlContextWrapper, Object)
+ V4_NEEDS_DESTROY
+
+ static ReturnedValue qmlScope(ExecutionEngine *e, QQmlContextData *ctxt, QObject *scope);
+ static ReturnedValue urlScope(ExecutionEngine *v4, const QUrl &);
static QQmlContextData *callingContext(ExecutionEngine *v4);
static void takeContextOwnership(const ValueRef qmlglobal);
@@ -92,26 +105,21 @@ struct Q_QML_EXPORT QmlContextWrapper : Object
static ReturnedValue get(Managed *m, String *name, bool *hasProperty);
static void put(Managed *m, String *name, const ValueRef value);
- static void destroy(Managed *that);
- static void markObjects(Managed *m, ExecutionEngine *engine);
+ static void markObjects(Heap::Base *m, ExecutionEngine *engine);
static void registerQmlDependencies(ExecutionEngine *context, const CompiledData::Function *compiledFunction);
ReturnedValue idObjectsArray();
- ReturnedValue qmlSingletonWrapper(QV8Engine *e, String *name);
+ ReturnedValue qmlSingletonWrapper(ExecutionEngine *e, String *name);
};
struct QQmlIdObjectsArray : public Object
{
- struct Data : Object::Data {
- Data(ExecutionEngine *engine, QmlContextWrapper *contextWrapper);
- QmlContextWrapper *contextWrapper;
- };
- V4_OBJECT(Object)
+ V4_OBJECT2(QQmlIdObjectsArray, Object)
static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty);
- static void markObjects(Managed *that, ExecutionEngine *engine);
+ static void markObjects(Heap::Base *that, ExecutionEngine *engine);
};
diff --git a/src/qml/qml/qqmldata_p.h b/src/qml/qml/qqmldata_p.h
index 1a7cb92b49..c4aa4828ba 100644
--- a/src/qml/qml/qqmldata_p.h
+++ b/src/qml/qml/qqmldata_p.h
@@ -216,7 +216,7 @@ public:
static inline void flushPendingBinding(QObject *, int coreIndex);
- static void ensurePropertyCache(QQmlEngine *engine, QObject *object);
+ static void ensurePropertyCache(QJSEngine *engine, QObject *object);
private:
// For attachedProperties
diff --git a/src/qml/qml/qqmldirparser.cpp b/src/qml/qml/qqmldirparser.cpp
index 83e1c9c757..5995b834f6 100644
--- a/src/qml/qml/qqmldirparser.cpp
+++ b/src/qml/qml/qqmldirparser.cpp
@@ -55,6 +55,19 @@ static int parseInt(const QStringRef &str, bool *ok)
return number;
}
+static bool parseVersion(const QString &str, int *major, int *minor)
+{
+ const int dotIndex = str.indexOf(QLatin1Char('.'));
+ if (dotIndex != -1 && str.indexOf(QLatin1Char('.'), dotIndex + 1) == -1) {
+ bool ok = false;
+ *major = parseInt(QStringRef(&str, 0, dotIndex), &ok);
+ if (ok)
+ *minor = parseInt(QStringRef(&str, dotIndex + 1, str.length() - dotIndex - 1), &ok);
+ return ok;
+ }
+ return false;
+}
+
QQmlDirParser::QQmlDirParser() : _designerSupported(false)
{
}
@@ -192,27 +205,14 @@ bool QQmlDirParser::parse(const QString &source)
} else {
// handle qmldir module listing case where singleton is defined in the following pattern:
// singleton TestSingletonType 2.0 TestSingletonType20.qml
- const QString &version = sections[2];
- const int dotIndex = version.indexOf(QLatin1Char('.'));
-
- if (dotIndex == -1) {
- reportError(lineNumber, 0, QLatin1String("expected '.'"));
- } else if (version.indexOf(QLatin1Char('.'), dotIndex + 1) != -1) {
- reportError(lineNumber, 0, QLatin1String("unexpected '.'"));
+ int major, minor;
+ if (parseVersion(sections[2], &major, &minor)) {
+ const QString &fileName = sections[3];
+ Component entry(sections[1], fileName, major, minor);
+ entry.singleton = true;
+ _components.insertMulti(entry.typeName, entry);
} else {
- bool validVersionNumber = false;
- const int majorVersion = parseInt(QStringRef(&version, 0, dotIndex), &validVersionNumber);
-
- if (validVersionNumber) {
- const int minorVersion = parseInt(QStringRef(&version, dotIndex+1, version.length()-dotIndex-1), &validVersionNumber);
-
- if (validVersionNumber) {
- const QString &fileName = sections[3];
- Component entry(sections[1], fileName, majorVersion, minorVersion);
- entry.singleton = true;
- _components.insertMulti(entry.typeName, entry);
- }
- }
+ reportError(lineNumber, 0, QStringLiteral("invalid version %1, expected <major>.<minor>").arg(sections[2]));
}
}
} else if (sections[0] == QLatin1String("typeinfo")) {
@@ -238,53 +238,33 @@ bool QQmlDirParser::parse(const QString &source)
continue;
}
- const QString &version = sections[2];
- const int dotIndex = version.indexOf(QLatin1Char('.'));
- bool validVersionNumber = false;
- const int majorVersion = parseInt(QStringRef(&version, 0, dotIndex), &validVersionNumber);
- if (validVersionNumber) {
- const int minorVersion = parseInt(QStringRef(&version, dotIndex+1, version.length()-dotIndex-1), &validVersionNumber);
-
- if (validVersionNumber) {
- Component entry(sections[1], QString(), majorVersion, minorVersion);
- entry.internal = true;
- _dependencies.insert(entry.typeName, entry);
- }
+ int major, minor;
+ if (parseVersion(sections[2], &major, &minor)) {
+ Component entry(sections[1], QString(), major, minor);
+ entry.internal = true;
+ _dependencies.insert(entry.typeName, entry);
} else {
- reportError(lineNumber, 0, QString(QLatin1String("invalid version %1")).arg(version));
+ reportError(lineNumber, 0, QStringLiteral("invalid version %1, expected <major>.<minor>").arg(sections[2]));
}
} else if (sectionCount == 2) {
// No version specified (should only be used for relative qmldir files)
const Component entry(sections[0], sections[1], -1, -1);
_components.insertMulti(entry.typeName, entry);
} else if (sectionCount == 3) {
- const QString &version = sections[1];
- const int dotIndex = version.indexOf(QLatin1Char('.'));
-
- if (dotIndex == -1) {
- reportError(lineNumber, 0, QLatin1String("expected '.'"));
- } else if (version.indexOf(QLatin1Char('.'), dotIndex + 1) != -1) {
- reportError(lineNumber, 0, QLatin1String("unexpected '.'"));
- } else {
- bool validVersionNumber = false;
- const int majorVersion = parseInt(QStringRef(&version, 0, dotIndex), &validVersionNumber);
-
- if (validVersionNumber) {
- const int minorVersion = parseInt(QStringRef(&version, dotIndex+1, version.length()-dotIndex-1), &validVersionNumber);
-
- if (validVersionNumber) {
- const QString &fileName = sections[2];
-
- if (fileName.endsWith(QLatin1String(".js"))) {
- // A 'js' extension indicates a namespaced script import
- const Script entry(sections[0], fileName, majorVersion, minorVersion);
- _scripts.append(entry);
- } else {
- const Component entry(sections[0], fileName, majorVersion, minorVersion);
- _components.insertMulti(entry.typeName, entry);
- }
- }
+ int major, minor;
+ if (parseVersion(sections[1], &major, &minor)) {
+ const QString &fileName = sections[2];
+
+ if (fileName.endsWith(QLatin1String(".js"))) {
+ // A 'js' extension indicates a namespaced script import
+ const Script entry(sections[0], fileName, major, minor);
+ _scripts.append(entry);
+ } else {
+ const Component entry(sections[0], fileName, major, minor);
+ _components.insertMulti(entry.typeName, entry);
}
+ } else {
+ reportError(lineNumber, 0, QStringLiteral("invalid version %1, expected <major>.<minor>").arg(sections[1]));
}
} else {
reportError(lineNumber, 0,
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index 04a2f9cadd..aececf915f 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -553,15 +553,14 @@ the same object as is returned from the Qt.include() call.
QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e)
: propertyCapture(0), rootContext(0), isDebugging(false),
- profiler(0), outputWarningsToStdErr(true),
+ profiler(0), outputWarningsToMsgLog(true),
cleanup(0), erroredBindings(0), inProgressCreations(0),
workerScriptEngine(0),
activeObjectCreator(0),
networkAccessManager(0), networkAccessManagerFactory(0), urlInterceptor(0),
scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1),
- incubatorCount(0), incubationController(0), mutex(QMutex::Recursive)
+ incubatorCount(0), incubationController(0)
{
- useNewCompiler = true;
}
QQmlEnginePrivate::~QQmlEnginePrivate()
@@ -583,8 +582,6 @@ QQmlEnginePrivate::~QQmlEnginePrivate()
if (incubationController) incubationController->d = 0;
incubationController = 0;
- for(QHash<const QMetaObject *, QQmlPropertyCache *>::Iterator iter = propertyCache.begin(); iter != propertyCache.end(); ++iter)
- (*iter)->release();
for(QHash<QPair<QQmlType *, int>, QQmlPropertyCache *>::Iterator iter = typePropertyCache.begin(); iter != typePropertyCache.end(); ++iter)
(*iter)->release();
for (QHash<int, QQmlCompiledData *>::Iterator iter = m_compositeTypes.begin(); iter != m_compositeTypes.end(); ++iter)
@@ -1181,7 +1178,7 @@ void QQmlEngine::setBaseUrl(const QUrl &url)
bool QQmlEngine::outputWarningsToStandardError() const
{
Q_D(const QQmlEngine);
- return d->outputWarningsToStdErr;
+ return d->outputWarningsToMsgLog;
}
/*!
@@ -1197,7 +1194,7 @@ bool QQmlEngine::outputWarningsToStandardError() const
void QQmlEngine::setOutputWarningsToStandardError(bool enabled)
{
Q_D(QQmlEngine);
- d->outputWarningsToStdErr = enabled;
+ d->outputWarningsToMsgLog = enabled;
}
/*!
@@ -1449,9 +1446,31 @@ QQmlDebuggingEnabler::QQmlDebuggingEnabler(bool printWarning)
qDebug("QML debugging is enabled. Only use this in a safe environment.");
}
QQmlEnginePrivate::qml_debugging_enabled = true;
+#else
+ Q_UNUSED(printWarning);
#endif
}
+/*!
+ * Enables debugging for QML engines created after calling this function. The debug server will
+ * listen on \a port at \a hostName and block the QML engine until it receives a connection if
+ * \a block is true. If \a block is not specified it won't block and if \a hostName isn't specified
+ * it will listen on all available interfaces. You can only start one debug server at a time. A
+ * debug server may have already been started if the -qmljsdebugger= command line argument was
+ * given. This method returns \c true if a new debug server was successfully started, or \c false
+ * otherwise.
+ */
+bool QQmlDebuggingEnabler::startTcpDebugServer(int port, bool block, const QString &hostName)
+{
+#ifndef QQML_NO_DEBUG_PROTOCOL
+ return QQmlDebugServer::enable(port, port, block, hostName);
+#else
+ Q_UNUSED(port);
+ Q_UNUSED(block);
+ Q_UNUSED(hostName);
+ return false;
+#endif
+}
class QQmlDataExtended {
public:
@@ -1732,13 +1751,13 @@ void QQmlData::setPendingBindingBit(QObject *obj, int coreIndex)
QQmlData_setBit(this, obj, coreIndex * 2 + 1);
}
-void QQmlData::ensurePropertyCache(QQmlEngine *engine, QObject *object)
+void QQmlData::ensurePropertyCache(QJSEngine *engine, QObject *object)
{
Q_ASSERT(engine);
QQmlData *ddata = QQmlData::get(object, /*create*/true);
if (ddata->propertyCache)
return;
- ddata->propertyCache = QQmlEnginePrivate::get(engine)->cache(object);
+ ddata->propertyCache = QJSEnginePrivate::get(engine)->cache(object);
if (ddata->propertyCache) ddata->propertyCache->addref();
}
@@ -1768,7 +1787,7 @@ void QQmlEnginePrivate::warning(const QQmlError &error)
{
Q_Q(QQmlEngine);
q->warnings(QList<QQmlError>() << error);
- if (outputWarningsToStdErr)
+ if (outputWarningsToMsgLog)
dumpwarning(error);
}
@@ -1776,7 +1795,7 @@ void QQmlEnginePrivate::warning(const QList<QQmlError> &errors)
{
Q_Q(QQmlEngine);
q->warnings(errors);
- if (outputWarningsToStdErr)
+ if (outputWarningsToMsgLog)
dumpwarning(errors);
}
@@ -1980,7 +1999,7 @@ void QQmlEngine::setPluginPathList(const QStringList &paths)
bool QQmlEngine::importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors)
{
Q_D(QQmlEngine);
- return d->importDatabase.importDynamicPlugin(filePath, uri, QString(), errors);
+ return d->importDatabase.importDynamicPlugin(filePath, uri, QString(), -1, errors);
}
/*!
@@ -2022,22 +2041,6 @@ QString QQmlEngine::offlineStoragePath() const
return d->offlineStoragePath;
}
-QQmlPropertyCache *QQmlEnginePrivate::createCache(const QMetaObject *mo)
-{
- Q_Q(QQmlEngine);
-
- if (!mo->superClass()) {
- QQmlPropertyCache *rv = new QQmlPropertyCache(q, mo);
- propertyCache.insert(mo, rv);
- return rv;
- } else {
- QQmlPropertyCache *super = cache(mo->superClass());
- QQmlPropertyCache *rv = super->copyAndAppend(q, mo);
- propertyCache.insert(mo, rv);
- return rv;
- }
-}
-
QQmlPropertyCache *QQmlEnginePrivate::createCache(QQmlType *type, int minorVersion,
QQmlError &error)
{
@@ -2244,16 +2247,12 @@ void QQmlEnginePrivate::registerInternalCompositeType(QQmlCompiledData *data)
QByteArray lst = "QQmlListProperty<" + name + '>';
int ptr_type = QMetaType::registerNormalizedType(ptr,
- QtMetaTypePrivate::QMetaTypeFunctionHelper<QObject*>::Delete,
- QtMetaTypePrivate::QMetaTypeFunctionHelper<QObject*>::Create,
QtMetaTypePrivate::QMetaTypeFunctionHelper<QObject*>::Destruct,
QtMetaTypePrivate::QMetaTypeFunctionHelper<QObject*>::Construct,
sizeof(QObject*),
static_cast<QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags<QObject*>::Flags),
0);
int lst_type = QMetaType::registerNormalizedType(lst,
- QtMetaTypePrivate::QMetaTypeFunctionHelper<QQmlListProperty<QObject> >::Delete,
- QtMetaTypePrivate::QMetaTypeFunctionHelper<QQmlListProperty<QObject> >::Create,
QtMetaTypePrivate::QMetaTypeFunctionHelper<QQmlListProperty<QObject> >::Destruct,
QtMetaTypePrivate::QMetaTypeFunctionHelper<QQmlListProperty<QObject> >::Construct,
sizeof(QQmlListProperty<QObject>),
diff --git a/src/qml/qml/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h
index f19bfc84b3..de2a2d3e1d 100644
--- a/src/qml/qml/qqmlengine_p.h
+++ b/src/qml/qml/qqmlengine_p.h
@@ -138,11 +138,10 @@ public:
QQmlContext *rootContext;
bool isDebugging;
- bool useNewCompiler;
QQmlProfiler *profiler;
void enableProfiler();
- bool outputWarningsToStdErr;
+ bool outputWarningsToMsgLog;
// Registered cleanup handlers
QQmlCleanup *cleanup;
@@ -209,9 +208,8 @@ public:
inline static void deleteInEngineThread(QQmlEngine *, T *);
// These methods may be called from the loader thread
- inline QQmlPropertyCache *cache(QObject *obj);
- inline QQmlPropertyCache *cache(const QMetaObject *);
inline QQmlPropertyCache *cache(QQmlType *, int, QQmlError &error);
+ using QJSEnginePrivate::cache;
// These methods may be called from the loader thread
bool isQObject(int);
@@ -261,40 +259,13 @@ public:
static bool qml_debugging_enabled;
mutable QMutex networkAccessManagerMutex;
- mutable QMutex mutex;
private:
- // Locker locks the QQmlEnginePrivate data structures for read and write, if necessary.
- // Currently, locking is only necessary if the threaded loader is running concurrently. If it is
- // either idle, or is running with the main thread blocked, no locking is necessary. This way
- // we only pay for locking when we have to.
- // Consequently, this class should only be used to protect simple accesses or modifications of the
- // QQmlEnginePrivate structures or operations that can be guaranteed not to start activity
- // on the loader thread.
- // The Locker API is identical to QMutexLocker. Locker reuses the QQmlEnginePrivate::mutex
- // QMutex instance and multiple Lockers are recursive in the same thread.
- class Locker
- {
- public:
- inline Locker(const QQmlEngine *);
- inline Locker(const QQmlEnginePrivate *);
- inline ~Locker();
-
- inline void unlock();
- inline void relock();
-
- private:
- const QQmlEnginePrivate *m_ep;
- quint32 m_locked:1;
- };
-
// Must be called locked
- QQmlPropertyCache *createCache(const QMetaObject *);
QQmlPropertyCache *createCache(QQmlType *, int, QQmlError &error);
// These members must be protected by a QQmlEnginePrivate::Locker as they are required by
// the threaded loader. Only access them through their respective accessor methods.
- QHash<const QMetaObject *, QQmlPropertyCache *> propertyCache;
QHash<QPair<QQmlType *, int>, QQmlPropertyCache *> typePropertyCache;
QHash<int, int> m_qmlLists;
QHash<int, QQmlCompiledData *> m_compositeTypes;
@@ -307,40 +278,6 @@ private:
void doDeleteInEngineThread();
};
-QQmlEnginePrivate::Locker::Locker(const QQmlEngine *e)
-: m_ep(QQmlEnginePrivate::get(e))
-{
- relock();
-}
-
-QQmlEnginePrivate::Locker::Locker(const QQmlEnginePrivate *e)
-: m_ep(e), m_locked(false)
-{
- relock();
-}
-
-QQmlEnginePrivate::Locker::~Locker()
-{
- unlock();
-}
-
-void QQmlEnginePrivate::Locker::unlock()
-{
- if (m_locked) {
- m_ep->mutex.unlock();
- m_locked = false;
- }
-}
-
-void QQmlEnginePrivate::Locker::relock()
-{
- Q_ASSERT(!m_locked);
- if (m_ep->typeLoader.isConcurrent()) {
- m_ep->mutex.lock();
- m_locked = true;
- }
-}
-
/*!
Returns true if the calling thread is the QQmlEngine thread.
*/
@@ -405,52 +342,6 @@ void QQmlEnginePrivate::deleteInEngineThread(QQmlEngine *engine, T *value)
}
/*!
-Returns a QQmlPropertyCache for \a obj if one is available.
-
-If \a obj is null, being deleted or contains a dynamic meta object 0
-is returned.
-
-The returned cache is not referenced, so if it is to be stored, call addref().
-
-XXX thread There is a potential future race condition in this and all the cache()
-functions. As the QQmlPropertyCache is returned unreferenced, when called
-from the loader thread, it is possible that the cache will have been dereferenced
-and deleted before the loader thread has a chance to use or reference it. This
-can't currently happen as the cache holds a reference to the
-QQmlPropertyCache until the QQmlEngine is destroyed.
-*/
-QQmlPropertyCache *QQmlEnginePrivate::cache(QObject *obj)
-{
- if (!obj || QObjectPrivate::get(obj)->metaObject || QObjectPrivate::get(obj)->wasDeleted)
- return 0;
-
- Locker locker(this);
- const QMetaObject *mo = obj->metaObject();
- QQmlPropertyCache *rv = propertyCache.value(mo);
- if (!rv) rv = createCache(mo);
- return rv;
-}
-
-/*!
-Returns a QQmlPropertyCache for \a metaObject.
-
-As the cache is persisted for the life of the engine, \a metaObject must be
-a static "compile time" meta-object, or a meta-object that is otherwise known to
-exist for the lifetime of the QQmlEngine.
-
-The returned cache is not referenced, so if it is to be stored, call addref().
-*/
-QQmlPropertyCache *QQmlEnginePrivate::cache(const QMetaObject *metaObject)
-{
- Q_ASSERT(metaObject);
-
- Locker locker(this);
- QQmlPropertyCache *rv = propertyCache.value(metaObject);
- if (!rv) rv = createCache(metaObject);
- return rv;
-}
-
-/*!
Returns a QQmlPropertyCache for \a type with \a minorVersion.
The returned cache is not referenced, so if it is to be stored, call addref().
diff --git a/src/qml/qml/qqmlexpression.cpp b/src/qml/qml/qqmlexpression.cpp
index 947b55f15d..ba561ad8e5 100644
--- a/src/qml/qml/qqmlexpression.cpp
+++ b/src/qml/qml/qqmlexpression.cpp
@@ -73,7 +73,8 @@ void QQmlExpressionPrivate::init(QQmlContextData *ctxt, const QString &expr, QOb
void QQmlExpressionPrivate::init(QQmlContextData *ctxt, QV4::Function *runtimeFunction, QObject *me)
{
expressionFunctionValid = true;
- function = QV4::QmlBindingWrapper::createQmlCallableForFunction(ctxt, me, runtimeFunction);
+ QV4::ExecutionEngine *engine = QQmlEnginePrivate::getV4Engine(ctxt->engine);
+ function.set(engine, QV4::QmlBindingWrapper::createQmlCallableForFunction(ctxt, me, runtimeFunction));
QQmlAbstractExpression::setContext(ctxt);
setScopeObject(me);
@@ -247,12 +248,13 @@ QV4::ReturnedValue QQmlExpressionPrivate::v4value(bool *isUndefined)
{
Q_Q(QQmlExpression);
+ QV4::ExecutionEngine *v4 = QQmlEnginePrivate::get(q->engine())->v4engine();
+
if (!expressionFunctionValid) {
- function = qmlBinding(context(), scopeObject(), expression, url, line, &qmlscope);
+ function.set(v4, qmlBinding(context(), scopeObject(), expression, url, line, &qmlscope));
expressionFunctionValid = true;
}
- QV4::ExecutionEngine *v4 = QQmlEnginePrivate::get(q->engine())->v4engine();
QV4::Scope scope(v4);
QV4::ScopedValue f(scope, function.value());
return evaluate(context(), f, isUndefined);
@@ -275,7 +277,8 @@ QVariant QQmlExpressionPrivate::value(bool *isUndefined)
{
QV4::Scope scope(QV8Engine::getV4(ep->v8engine()));
QV4::ScopedValue result(scope, v4value(isUndefined));
- rv = ep->v8engine()->toVariant(result, -1);
+ if (!hasError())
+ rv = scope.engine->toVariant(result, -1);
}
ep->dereferenceScarceResources(); // "release" scarce resources if top-level expression evaluation is complete.
diff --git a/src/qml/qml/qqmlfile.cpp b/src/qml/qml/qqmlfile.cpp
index 1aa350acc8..fe3c83cd3a 100644
--- a/src/qml/qml/qqmlfile.cpp
+++ b/src/qml/qml/qqmlfile.cpp
@@ -36,6 +36,7 @@
#include <QtCore/qurl.h>
#include <QtCore/qobject.h>
#include <QtCore/qmetaobject.h>
+#include <QtCore/qfile.h>
#include <private/qqmlengine_p.h>
#include <private/qqmlglobal_p.h>
@@ -45,7 +46,7 @@
\internal
-Supports file://, qrc:/, bundle:// uris and whatever QNetworkAccessManager supports.
+Supports file:// and qrc:/ uris and whatever QNetworkAccessManager supports.
*/
#define QQMLFILE_MAX_REDIRECT_RECURSION 16
@@ -54,7 +55,6 @@ QT_BEGIN_NAMESPACE
static char qrc_string[] = "qrc";
static char file_string[] = "file";
-static char bundle_string[] = "bundle";
#if defined(Q_OS_ANDROID)
static char assets_string[] = "assets";
@@ -100,9 +100,6 @@ public:
mutable QUrl url;
mutable QString urlString;
- QQmlBundleData *bundle;
- const QQmlBundle::FileEntry *file;
-
QByteArray data;
enum Error {
@@ -199,7 +196,7 @@ void QQmlFileNetworkReply::networkDownloadProgress(qint64 a, qint64 b)
}
QQmlFilePrivate::QQmlFilePrivate()
-: bundle(0), file(0), error(None), reply(0)
+: error(None), reply(0)
{
}
@@ -222,11 +219,7 @@ QQmlFile::QQmlFile(QQmlEngine *e, const QString &url)
QQmlFile::~QQmlFile()
{
- if (d->reply)
- delete d->reply;
- if (d->bundle)
- d->bundle->release();
-
+ delete d->reply;
delete d;
d = 0;
}
@@ -287,31 +280,17 @@ QString QQmlFile::error() const
qint64 QQmlFile::size() const
{
- if (d->file) return d->file->fileSize();
- else return d->data.size();
+ return d->data.size();
}
const char *QQmlFile::data() const
{
- if (d->file) return d->file->contents();
- else return d->data.constData();
+ return d->data.constData();
}
QByteArray QQmlFile::dataByteArray() const
{
- if (d->file) return QByteArray(d->file->contents(), d->file->fileSize());
- else return d->data;
-}
-
-QByteArray QQmlFile::metaData(const QString &name) const
-{
- if (d->file) {
- Q_ASSERT(d->bundle);
- const QQmlBundle::FileEntry *meta = d->bundle->link(d->file, name);
- if (meta)
- return QByteArray::fromRawData(meta->contents(), meta->fileSize());
- }
- return QByteArray();
+ return d->data;
}
void QQmlFile::load(QQmlEngine *engine, const QUrl &url)
@@ -321,25 +300,7 @@ void QQmlFile::load(QQmlEngine *engine, const QUrl &url)
clear();
d->url = url;
- if (isBundle(url)) {
- // Bundle
- QQmlEnginePrivate *p = QQmlEnginePrivate::get(engine);
- QQmlBundleData *bundle = p->typeLoader.getBundle(url.host());
-
- d->error = QQmlFilePrivate::NotFound;
-
- if (bundle) {
- QString filename = url.path().mid(1);
- const QQmlBundle::FileEntry *entry = bundle->find(filename);
- if (entry) {
- d->file = entry;
- d->bundle = bundle;
- d->bundle->addref();
- d->error = QQmlFilePrivate::None;
- }
- bundle->release();
- }
- } else if (isLocalFile(url)) {
+ if (isLocalFile(url)) {
QString lf = urlToLocalFileOrQrc(url);
if (!QQml_isFileCaseCorrect(lf)) {
@@ -366,33 +327,7 @@ void QQmlFile::load(QQmlEngine *engine, const QString &url)
d->urlString = url;
- if (isBundle(url)) {
- // Bundle
- QQmlEnginePrivate *p = QQmlEnginePrivate::get(engine);
-
- d->error = QQmlFilePrivate::NotFound;
-
- int index = url.indexOf(QLatin1Char('/'), 9);
- if (index == -1)
- return;
-
- QStringRef identifier(&url, 9, index - 9);
-
- QQmlBundleData *bundle = p->typeLoader.getBundle(identifier);
-
- d->error = QQmlFilePrivate::NotFound;
-
- if (bundle) {
- QString filename = url.mid(index);
- const QQmlBundle::FileEntry *entry = bundle->find(filename);
- if (entry) {
- d->data = QByteArray(entry->contents(), entry->fileSize());
- d->error = QQmlFilePrivate::None;
- }
- bundle->release();
- }
-
- } else if (isLocalFile(url)) {
+ if (isLocalFile(url)) {
QString lf = urlToLocalFileOrQrc(url);
if (!QQml_isFileCaseCorrect(lf)) {
@@ -419,9 +354,6 @@ void QQmlFile::clear()
d->url = QUrl();
d->urlString = QString();
d->data = QByteArray();
- if (d->bundle) d->bundle->release();
- d->bundle = 0;
- d->file = 0;
d->error = QQmlFilePrivate::None;
}
@@ -477,7 +409,7 @@ bool QQmlFile::connectDownloadProgress(QObject *object, int method)
/*!
Returns true if QQmlFile will open \a url synchronously.
-Synchronous urls have a qrc:/, file://, or bundle:// scheme.
+Synchronous urls have a qrc:/ or file:// scheme.
\note On Android, urls with assets:/ scheme are also considered synchronous.
*/
@@ -486,7 +418,6 @@ bool QQmlFile::isSynchronous(const QUrl &url)
QString scheme = url.scheme();
if ((scheme.length() == 4 && 0 == scheme.compare(QLatin1String(file_string), Qt::CaseInsensitive)) ||
- (scheme.length() == 6 && 0 == scheme.compare(QLatin1String(bundle_string), Qt::CaseInsensitive)) ||
(scheme.length() == 3 && 0 == scheme.compare(QLatin1String(qrc_string), Qt::CaseInsensitive))) {
return true;
@@ -503,7 +434,7 @@ bool QQmlFile::isSynchronous(const QUrl &url)
/*!
Returns true if QQmlFile will open \a url synchronously.
-Synchronous urls have a qrc:/, file://, or bundle:// scheme.
+Synchronous urls have a qrc:/ or file:// scheme.
\note On Android, urls with assets:/ scheme are also considered synchronous.
*/
@@ -520,12 +451,6 @@ bool QQmlFile::isSynchronous(const QString &url)
url.startsWith(QLatin1String(file_string), Qt::CaseInsensitive) &&
url[4] == QLatin1Char(':') && url[5] == QLatin1Char('/') && url[6] == QLatin1Char('/');
- } else if (f == QLatin1Char('b') || f == QLatin1Char('B')) {
-
- return url.length() >= 9 /* bundle:// */ &&
- url.startsWith(QLatin1String(bundle_string), Qt::CaseInsensitive) &&
- url[6] == QLatin1Char(':') && url[7] == QLatin1Char('/') && url[8] == QLatin1Char('/');
-
} else if (f == QLatin1Char('q') || f == QLatin1Char('Q')) {
return url.length() >= 5 /* qrc:/ */ &&
@@ -547,29 +472,6 @@ bool QQmlFile::isSynchronous(const QString &url)
}
/*!
-Returns true if \a url is a bundle.
-
-Bundle urls have a bundle:// scheme.
-*/
-bool QQmlFile::isBundle(const QString &url)
-{
- return url.length() >= 9 && url.startsWith(QLatin1String(bundle_string), Qt::CaseInsensitive) &&
- url[6] == QLatin1Char(':') && url[7] == QLatin1Char('/') && url[8] == QLatin1Char('/');
-}
-
-/*!
-Returns true if \a url is a bundle.
-
-Bundle urls have a bundle:// scheme.
-*/
-bool QQmlFile::isBundle(const QUrl &url)
-{
- QString scheme = url.scheme();
-
- return scheme.length() == 6 && 0 == scheme.compare(QLatin1String(bundle_string), Qt::CaseInsensitive);
-}
-
-/*!
Returns true if \a url is a local file that can be opened with QFile.
Local file urls have either a qrc:/ or file:// scheme.
@@ -688,162 +590,6 @@ QString QQmlFile::urlToLocalFileOrQrc(const QString& url)
return toLocalFile(url);
}
-bool QQmlFile::bundleDirectoryExists(const QString &dir, QQmlEngine *e)
-{
- if (!isBundle(dir))
- return false;
-
- int index = dir.indexOf(QLatin1Char('/'), 9);
-
- if (index == -1 && dir.length() > 9) // We accept "bundle://<blah>" with no extra path
- index = dir.length();
-
- if (index == -1)
- return false;
-
- QStringRef identifier(&dir, 9, index - 9);
-
- QQmlBundleData *bundle = QQmlEnginePrivate::get(e)->typeLoader.getBundle(identifier);
-
- if (bundle) {
- int lastIndex = dir.lastIndexOf(QLatin1Char('/'));
-
- if (lastIndex <= index) {
- bundle->release();
- return true;
- }
-
- QStringRef d(&dir, index + 1, lastIndex - index);
-
- QList<const QQmlBundle::FileEntry *> entries = bundle->files();
-
- for (int ii = 0; ii < entries.count(); ++ii) {
- QString name = entries.at(ii)->fileName();
- if (name.startsWith(d)) {
- bundle->release();
- return true;
- }
- }
-
- bundle->release();
- }
-
- return false;
-}
-
-bool QQmlFile::bundleDirectoryExists(const QUrl &url, QQmlEngine *e)
-{
- if (!isBundle(url))
- return false;
-
- QQmlBundleData *bundle = QQmlEnginePrivate::get(e)->typeLoader.getBundle(url.host());
-
- if (bundle) {
- QString path = url.path();
-
- int lastIndex = path.lastIndexOf(QLatin1Char('/'));
-
- if (lastIndex == -1) {
- bundle->release();
- return true;
- }
-
- QStringRef d(&path, 0, lastIndex);
-
- QList<const QQmlBundle::FileEntry *> entries = bundle->files();
-
- for (int ii = 0; ii < entries.count(); ++ii) {
- QString name = entries.at(ii)->fileName();
- if (name.startsWith(d)) {
- bundle->release();
- return true;
- }
- }
-
- bundle->release();
- }
-
- return false;
-}
-
-bool QQmlFile::bundleFileExists(const QString &file, QQmlEngine *e)
-{
- if (!isBundle(file))
- return false;
-
- int index = file.indexOf(QLatin1Char('/'), 9);
-
- if (index == -1)
- return false;
-
- QStringRef identifier(&file, 9, index - 9);
- QStringRef path(&file, index + 1, file.length() - index - 1);
-
- QQmlBundleData *bundle = QQmlEnginePrivate::get(e)->typeLoader.getBundle(identifier);
-
- if (bundle) {
- const QQmlBundle::FileEntry *entry = bundle->find(path.constData(), path.length());
- bundle->release();
-
- return entry != 0;
- }
-
- return false;
-}
-
-bool QQmlFile::bundleFileExists(const QUrl &, QQmlEngine *)
-{
- qFatal("Not implemented");
- return true;
-}
-
-/*!
-Returns the file name for the bundle file referenced by \a url or an
-empty string if \a url isn't a bundle url.
-*/
-QString QQmlFile::bundleFileName(const QString &url, QQmlEngine *e)
-{
- if (!isBundle(url))
- return QString();
-
- int index = url.indexOf(QLatin1Char('/'), 9);
-
- if (index == -1)
- index = url.length();
-
- QStringRef identifier(&url, 9, index - 9);
-
- QQmlBundleData *bundle = QQmlEnginePrivate::get(e)->typeLoader.getBundle(identifier);
-
- if (bundle) {
- QString rv = bundle->fileName;
- bundle->release();
- return rv;
- }
-
- return QString();
-}
-
-/*!
-Returns the file name for the bundle file referenced by \a url or an
-empty string if \a url isn't a bundle url.
-*/
-QString QQmlFile::bundleFileName(const QUrl &url, QQmlEngine *e)
-{
- if (!isBundle(url))
- return QString();
-
- QQmlBundleData *bundle = QQmlEnginePrivate::get(e)->typeLoader.getBundle(url.host());
-
- if (bundle) {
- QString rv = bundle->fileName;
- bundle->release();
- return rv;
- }
-
- return QString();
-}
-
QT_END_NAMESPACE
#include "qqmlfile.moc"
diff --git a/src/qml/qml/qqmlfile.h b/src/qml/qml/qqmlfile.h
index 3d27224500..482d3242c9 100644
--- a/src/qml/qml/qqmlfile.h
+++ b/src/qml/qml/qqmlfile.h
@@ -68,8 +68,6 @@ public:
const char *data() const;
QByteArray dataByteArray() const;
- QByteArray metaData(const QString &) const;
-
void load(QQmlEngine *, const QUrl &);
void load(QQmlEngine *, const QString &);
@@ -84,24 +82,11 @@ public:
static bool isSynchronous(const QString &url);
static bool isSynchronous(const QUrl &url);
- static bool isBundle(const QString &url);
- static bool isBundle(const QUrl &url);
-
static bool isLocalFile(const QString &url);
static bool isLocalFile(const QUrl &url);
static QString urlToLocalFileOrQrc(const QString &);
static QString urlToLocalFileOrQrc(const QUrl &);
-
- static bool bundleDirectoryExists(const QString &, QQmlEngine *);
- static bool bundleDirectoryExists(const QUrl &, QQmlEngine *);
-
- static bool bundleFileExists(const QString &, QQmlEngine *);
- static bool bundleFileExists(const QUrl &, QQmlEngine *);
-
- static QString bundleFileName(const QString &, QQmlEngine *);
- static QString bundleFileName(const QUrl &, QQmlEngine *);
-
private:
Q_DISABLE_COPY(QQmlFile)
QQmlFilePrivate *d;
diff --git a/src/qml/qml/qqmlglobal.cpp b/src/qml/qml/qqmlglobal.cpp
index 492836ae03..82c1b68715 100644
--- a/src/qml/qml/qqmlglobal.cpp
+++ b/src/qml/qml/qqmlglobal.cpp
@@ -50,14 +50,12 @@ QQmlValueTypeProvider::~QQmlValueTypeProvider()
QQml_removeValueTypeProvider(this);
}
-QQmlValueType *QQmlValueTypeProvider::createValueType(int type)
+const QMetaObject *QQmlValueTypeProvider::metaObjectForMetaType(int type)
{
- QQmlValueType *value = 0;
-
QQmlValueTypeProvider *p = this;
do {
- if (p->create(type, value))
- return value;
+ if (const QMetaObject *mo = p->getMetaObjectForMetaType(type))
+ return mo;
} while ((p = p->next));
return 0;
@@ -173,7 +171,7 @@ QVariant QQmlValueTypeProvider::createVariantFromString(int type, const QString
return QVariant();
}
-QVariant QQmlValueTypeProvider::createVariantFromJsObject(int type, QQmlV4Handle obj, QV8Engine *e, bool *ok)
+QVariant QQmlValueTypeProvider::createVariantFromJsObject(int type, QQmlV4Handle obj, QV4::ExecutionEngine *e, bool *ok)
{
QVariant v;
@@ -245,7 +243,7 @@ bool QQmlValueTypeProvider::writeValueType(int type, const void *src, void *dst,
return false;
}
-bool QQmlValueTypeProvider::create(int, QQmlValueType *&) { return false; }
+const QMetaObject *QQmlValueTypeProvider::getMetaObjectForMetaType(int) { return 0; }
bool QQmlValueTypeProvider::init(int, void *, size_t) { return false; }
bool QQmlValueTypeProvider::destroy(int, void *, size_t) { return false; }
bool QQmlValueTypeProvider::copy(int, const void *, void *, size_t) { return false; }
@@ -254,7 +252,7 @@ bool QQmlValueTypeProvider::createFromString(int, const QString &, void *, size_
bool QQmlValueTypeProvider::createStringFrom(int, const void *, QString *) { return false; }
bool QQmlValueTypeProvider::variantFromString(const QString &, QVariant *) { return false; }
bool QQmlValueTypeProvider::variantFromString(int, const QString &, QVariant *) { return false; }
-bool QQmlValueTypeProvider::variantFromJsObject(int, QQmlV4Handle, QV8Engine *, QVariant *) { return false; }
+bool QQmlValueTypeProvider::variantFromJsObject(int, QQmlV4Handle, QV4::ExecutionEngine *, QVariant *) { return false; }
bool QQmlValueTypeProvider::equal(int, const void *, const void *, size_t) { return false; }
bool QQmlValueTypeProvider::store(int, const void *, void *, size_t) { return false; }
bool QQmlValueTypeProvider::read(int, const void *, size_t, int, void *) { return false; }
diff --git a/src/qml/qml/qqmlglobal_p.h b/src/qml/qml/qqmlglobal_p.h
index 1d0bf59670..da09956530 100644
--- a/src/qml/qml/qqmlglobal_p.h
+++ b/src/qml/qml/qqmlglobal_p.h
@@ -215,7 +215,6 @@ inline void QQml_setParent_noEvent(QObject *object, QObject *parent)
}
-class QQmlValueType;
class QV8Engine;
class Q_QML_PRIVATE_EXPORT QQmlValueTypeProvider
{
@@ -223,7 +222,7 @@ public:
QQmlValueTypeProvider();
virtual ~QQmlValueTypeProvider();
- QQmlValueType *createValueType(int);
+ const QMetaObject *metaObjectForMetaType(int);
bool initValueType(int, void *, size_t);
bool destroyValueType(int, void *, size_t);
@@ -235,7 +234,7 @@ public:
QVariant createVariantFromString(const QString &);
QVariant createVariantFromString(int, const QString &, bool *);
- QVariant createVariantFromJsObject(int, QQmlV4Handle, QV8Engine *, bool*);
+ QVariant createVariantFromJsObject(int, QQmlV4Handle, QV4::ExecutionEngine *, bool*);
bool equalValueType(int, const void *, const void *, size_t);
bool storeValueType(int, const void *, void *, size_t);
@@ -243,8 +242,7 @@ public:
bool writeValueType(int, const void *, void *, size_t);
private:
- virtual bool create(int, QQmlValueType *&);
-
+ virtual const QMetaObject *getMetaObjectForMetaType(int);
virtual bool init(int, void *, size_t);
virtual bool destroy(int, void *, size_t);
virtual bool copy(int, const void *, void *, size_t);
@@ -255,7 +253,7 @@ private:
virtual bool variantFromString(const QString &, QVariant *);
virtual bool variantFromString(int, const QString &, QVariant *);
- virtual bool variantFromJsObject(int, QQmlV4Handle, QV8Engine *, QVariant *);
+ virtual bool variantFromJsObject(int, QQmlV4Handle, QV4::ExecutionEngine *, QVariant *);
virtual bool equal(int, const void *, const void *, size_t);
virtual bool store(int, const void *, void *, size_t);
diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp
index 807eb05362..20bc28d886 100644
--- a/src/qml/qml/qqmlimport.cpp
+++ b/src/qml/qml/qqmlimport.cpp
@@ -668,13 +668,9 @@ bool QQmlImportNamespace::Import::resolveType(QQmlTypeLoader *typeLoader,
for (uint i = 0; i < sizeof(urlsToTry) / sizeof(urlsToTry[0]); ++i) {
const QString url = urlsToTry[i];
- if (QQmlFile::isBundle(url)) {
- exists = QQmlFile::bundleFileExists(url, typeLoader->engine());
- } else {
- exists = !typeLoader->absoluteFilePath(QQmlFile::urlToLocalFileOrQrc(url)).isEmpty();
- if (!exists)
- exists = QQmlMetaType::findCachedCompilationUnit(QUrl(url));
- }
+ exists = !typeLoader->absoluteFilePath(QQmlFile::urlToLocalFileOrQrc(url)).isEmpty();
+ if (!exists)
+ exists = QQmlMetaType::findCachedCompilationUnit(QUrl(url));
if (exists) {
qmlUrl = url;
@@ -879,7 +875,7 @@ bool QQmlImportsPrivate::populatePluginPairVector(QVector<StaticPluginPair> &res
/*!
Import an extension defined by a qmldir file.
-\a qmldirFilePath is either a raw file path, or a bundle url.
+\a qmldirFilePath is a raw file path.
*/
bool QQmlImportsPrivate::importExtension(const QString &qmldirFilePath,
const QString &uri,
@@ -930,7 +926,7 @@ bool QQmlImportsPrivate::importExtension(const QString &qmldirFilePath,
QString resolvedFilePath = database->resolvePlugin(typeLoader, qmldirPath, plugin.path, plugin.name);
if (!resolvedFilePath.isEmpty()) {
dynamicPluginsFound++;
- if (!database->importDynamicPlugin(resolvedFilePath, uri, typeNamespace, errors)) {
+ if (!database->importDynamicPlugin(resolvedFilePath, uri, typeNamespace, vmaj, errors)) {
if (errors) {
// XXX TODO: should we leave the import plugin error alone?
// Here, we pop it off the top and coalesce it into this error's message.
@@ -966,7 +962,7 @@ bool QQmlImportsPrivate::importExtension(const QString &qmldirFilePath,
if (versionUri == metaTagUri.toString()) {
staticPluginsFound++;
QObject *instance = pair.first.instance();
- if (!database->importStaticPlugin(instance, basePath, uri, typeNamespace, errors)) {
+ if (!database->importStaticPlugin(instance, basePath, uri, typeNamespace, vmaj, errors)) {
if (errors) {
QQmlError poppedError = errors->takeFirst();
QQmlError error;
@@ -1012,17 +1008,11 @@ bool QQmlImportsPrivate::getQmldirContent(const QString &qmldirIdentifier, const
Q_ASSERT(errors);
Q_ASSERT(qmldir);
- *qmldir = typeLoader->qmldirContent(qmldirIdentifier, uri);
+ *qmldir = typeLoader->qmldirContent(qmldirIdentifier);
if (*qmldir) {
// Ensure that parsing was successful
if ((*qmldir)->hasError()) {
- QUrl url;
-
- if (QQmlFile::isBundle(qmldirIdentifier))
- url = QUrl(qmldirIdentifier);
- else
- url = QUrl::fromLocalFile(qmldirIdentifier);
-
+ QUrl url = QUrl::fromLocalFile(qmldirIdentifier);
const QList<QQmlError> qmldirErrors = (*qmldir)->errors(uri);
for (int i = 0; i < qmldirErrors.size(); ++i) {
QQmlError error = qmldirErrors.at(i);
@@ -1328,30 +1318,7 @@ bool QQmlImportsPrivate::addFileImport(const QString& uri, const QString &prefix
QString qmldirIdentifier;
- if (QQmlFile::isBundle(qmldirUrl)) {
-
- QString dir = resolveLocalUrl(base, importUri);
- Q_ASSERT(QQmlFile::isBundle(dir));
- if (!QQmlFile::bundleDirectoryExists(dir, typeLoader->engine())) {
- if (!isImplicitImport) {
- QQmlError error;
- error.setDescription(QQmlImportDatabase::tr("\"%1\": no such directory").arg(uri));
- error.setUrl(QUrl(qmldirUrl));
- errors->prepend(error);
- }
- return false;
- }
-
- // Transforms the (possible relative) uri into our best guess relative to the
- // import paths.
- importUri = resolvedUri(dir, database);
- if (importUri.endsWith(Slash))
- importUri.chop(1);
-
- if (QQmlFile::bundleFileExists(qmldirUrl, typeLoader->engine()))
- qmldirIdentifier = qmldirUrl;
-
- } else if (QQmlFile::isLocalFile(qmldirUrl)) {
+ if (QQmlFile::isLocalFile(qmldirUrl)) {
QString localFileOrQrc = QQmlFile::urlToLocalFileOrQrc(qmldirUrl);
Q_ASSERT(!localFileOrQrc.isEmpty());
@@ -1555,12 +1522,12 @@ bool QQmlImports::locateQmldir(QQmlImportDatabase *importDb,
bool QQmlImports::isLocal(const QString &url)
{
- return QQmlFile::isBundle(url) || !QQmlFile::urlToLocalFileOrQrc(url).isEmpty();
+ return !QQmlFile::urlToLocalFileOrQrc(url).isEmpty();
}
bool QQmlImports::isLocal(const QUrl &url)
{
- return QQmlFile::isBundle(url) || !QQmlFile::urlToLocalFileOrQrc(url).isEmpty();
+ return !QQmlFile::urlToLocalFileOrQrc(url).isEmpty();
}
void QQmlImports::setDesignerSupportRequired(bool b)
@@ -1844,7 +1811,7 @@ void QQmlImportDatabase::setImportPathList(const QStringList &paths)
\internal
*/
bool QQmlImportDatabase::registerPluginTypes(QObject *instance, const QString &basePath,
- const QString &uri, const QString &typeNamespace, QList<QQmlError> *errors)
+ const QString &uri, const QString &typeNamespace, int vmaj, QList<QQmlError> *errors)
{
if (qmlImportTrace())
qDebug().nospace() << "QQmlImportDatabase::registerPluginTypes: " << uri << " from " << basePath;
@@ -1880,7 +1847,7 @@ bool QQmlImportDatabase::registerPluginTypes(QObject *instance, const QString &b
return false;
}
- if (QQmlMetaType::namespaceContainsRegistrations(typeNamespace)) {
+ if (QQmlMetaType::namespaceContainsRegistrations(typeNamespace, vmaj)) {
// Other modules have already installed to this namespace
if (errors) {
QQmlError error;
@@ -1927,7 +1894,7 @@ bool QQmlImportDatabase::registerPluginTypes(QObject *instance, const QString &b
\internal
*/
bool QQmlImportDatabase::importStaticPlugin(QObject *instance, const QString &basePath,
- const QString &uri, const QString &typeNamespace, QList<QQmlError> *errors)
+ const QString &uri, const QString &typeNamespace, int vmaj, QList<QQmlError> *errors)
{
#ifndef QT_NO_LIBRARY
// Dynamic plugins are differentiated by their filepath. For static plugins we
@@ -1951,7 +1918,7 @@ bool QQmlImportDatabase::importStaticPlugin(QObject *instance, const QString &ba
plugin.loader = 0;
plugins->insert(uniquePluginID, plugin);
- if (!registerPluginTypes(instance, basePath, uri, typeNamespace, errors))
+ if (!registerPluginTypes(instance, basePath, uri, typeNamespace, vmaj, errors))
return false;
}
@@ -1974,7 +1941,7 @@ bool QQmlImportDatabase::importStaticPlugin(QObject *instance, const QString &ba
\internal
*/
bool QQmlImportDatabase::importDynamicPlugin(const QString &filePath, const QString &uri,
- const QString &typeNamespace, QList<QQmlError> *errors)
+ const QString &typeNamespace, int vmaj, QList<QQmlError> *errors)
{
#ifndef QT_NO_LIBRARY
QFileInfo fileInfo(filePath);
@@ -2028,7 +1995,7 @@ bool QQmlImportDatabase::importDynamicPlugin(const QString &filePath, const QStr
plugins->insert(absoluteFilePath, plugin);
// Continue with shared code path for dynamic and static plugins:
- if (!registerPluginTypes(instance, fileInfo.absolutePath(), uri, typeNamespace, errors))
+ if (!registerPluginTypes(instance, fileInfo.absolutePath(), uri, typeNamespace, vmaj, errors))
return false;
}
diff --git a/src/qml/qml/qqmlimport_p.h b/src/qml/qml/qqmlimport_p.h
index 26eab669bc..353349182e 100644
--- a/src/qml/qml/qqmlimport_p.h
+++ b/src/qml/qml/qqmlimport_p.h
@@ -145,7 +145,7 @@ public:
QQmlImportDatabase(QQmlEngine *);
~QQmlImportDatabase();
- bool importDynamicPlugin(const QString &filePath, const QString &uri, const QString &importNamespace, QList<QQmlError> *errors);
+ bool importDynamicPlugin(const QString &filePath, const QString &uri, const QString &importNamespace, int vmaj, QList<QQmlError> *errors);
QStringList importPathList(PathType type = LocalOrRemote) const;
void setImportPathList(const QStringList &paths);
@@ -165,9 +165,9 @@ private:
const QString &qmldirPath, const QString &qmldirPluginPath,
const QString &baseName);
bool importStaticPlugin(QObject *instance, const QString &basePath, const QString &uri,
- const QString &typeNamespace, QList<QQmlError> *errors);
+ const QString &typeNamespace, int vmaj, QList<QQmlError> *errors);
bool registerPluginTypes(QObject *instance, const QString &basePath,
- const QString &uri, const QString &typeNamespace, QList<QQmlError> *errors);
+ const QString &uri, const QString &typeNamespace, int vmaj, QList<QQmlError> *errors);
void clearDirCache();
struct QmldirCache {
diff --git a/src/qml/qml/qqmljavascriptexpression.cpp b/src/qml/qml/qqmljavascriptexpression.cpp
index 7425509b40..5f8190b8dc 100644
--- a/src/qml/qml/qqmljavascriptexpression.cpp
+++ b/src/qml/qml/qqmljavascriptexpression.cpp
@@ -76,9 +76,9 @@ void QQmlDelayedError::setErrorObject(QObject *object)
m_error.setObject(object);
}
-void QQmlDelayedError::catchJavaScriptException(QV4::ExecutionContext *context)
+void QQmlDelayedError::catchJavaScriptException(QV4::ExecutionEngine *engine)
{
- m_error = QV4::ExecutionEngine::catchExceptionAsQmlError(context);
+ m_error = engine->catchExceptionAsQmlError();
}
@@ -110,7 +110,7 @@ QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QQmlContextData *context,
{
QV4::ExecutionEngine *v4 = QV8Engine::getV4(context->engine);
QV4::Scope scope(v4);
- QV4::ScopedCallData callData(scope, 0);
+ QV4::ScopedCallData callData(scope);
return evaluate(context, function, callData, isUndefined);
}
@@ -147,10 +147,9 @@ QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QQmlContextData *context,
QV4::ExecutionEngine *v4 = QV8Engine::getV4(ep->v8engine());
QV4::Scope scope(v4);
QV4::ScopedValue result(scope, QV4::Primitive::undefinedValue());
- QV4::ExecutionContext *ctx = v4->currentContext();
- callData->thisObject = v4->globalObject;
+ callData->thisObject = v4->globalObject();
if (scopeObject()) {
- QV4::ScopedValue value(scope, QV4::QObjectWrapper::wrap(ctx->d()->engine, scopeObject()));
+ QV4::ScopedValue value(scope, QV4::QObjectWrapper::wrap(v4, scopeObject()));
if (value->isObject())
callData->thisObject = value;
}
@@ -158,9 +157,9 @@ QV4::ReturnedValue QQmlJavaScriptExpression::evaluate(QQmlContextData *context,
result = function->asFunctionObject()->call(callData);
if (scope.hasException()) {
if (watcher.wasDeleted())
- ctx->catchException(); // ignore exception
+ scope.engine->catchException(); // ignore exception
else
- delayedError()->catchJavaScriptException(ctx);
+ delayedError()->catchJavaScriptException(scope.engine);
if (isUndefined)
*isUndefined = true;
} else {
@@ -288,17 +287,16 @@ QQmlJavaScriptExpression::evalFunction(QQmlContextData *ctxt, QObject *scopeObje
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine);
QV4::ExecutionEngine *v4 = QV8Engine::getV4(ep->v8engine());
- QV4::ExecutionContext *ctx = v4->currentContext();
QV4::Scope scope(v4);
- QV4::ScopedObject qmlScopeObject(scope, QV4::QmlContextWrapper::qmlScope(ep->v8engine(), ctxt, scopeObject));
+ QV4::ScopedObject qmlScopeObject(scope, QV4::QmlContextWrapper::qmlScope(v4, ctxt, scopeObject));
QV4::Script script(v4, qmlScopeObject, code, filename, line);
QV4::ScopedValue result(scope);
script.parse();
if (!v4->hasException)
result = script.run();
if (v4->hasException) {
- QQmlError error = QV4::ExecutionEngine::catchExceptionAsQmlError(ctx);
+ QQmlError error = v4->catchExceptionAsQmlError();
if (error.description().isEmpty())
error.setDescription(QLatin1String("Exception occurred during function evaluation"));
if (error.line() == -1)
@@ -310,7 +308,7 @@ QQmlJavaScriptExpression::evalFunction(QQmlContextData *ctxt, QObject *scopeObje
return QV4::Encode::undefined();
}
if (qmlscope)
- *qmlscope = qmlScopeObject;
+ qmlscope->set(v4, qmlScopeObject);
return result.asReturnedValue();
}
@@ -322,17 +320,16 @@ QV4::ReturnedValue QQmlJavaScriptExpression::qmlBinding(QQmlContextData *ctxt, Q
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine);
QV4::ExecutionEngine *v4 = QV8Engine::getV4(ep->v8engine());
- QV4::ExecutionContext *ctx = v4->currentContext();
QV4::Scope scope(v4);
- QV4::ScopedObject qmlScopeObject(scope, QV4::QmlContextWrapper::qmlScope(ep->v8engine(), ctxt, qmlScope));
+ QV4::ScopedObject qmlScopeObject(scope, QV4::QmlContextWrapper::qmlScope(v4, ctxt, qmlScope));
QV4::Script script(v4, qmlScopeObject, code, filename, line);
QV4::ScopedValue result(scope);
script.parse();
if (!v4->hasException)
result = script.qmlBinding();
if (v4->hasException) {
- QQmlError error = QV4::ExecutionEngine::catchExceptionAsQmlError(ctx);
+ QQmlError error = v4->catchExceptionAsQmlError();
if (error.description().isEmpty())
error.setDescription(QLatin1String("Exception occurred during function evaluation"));
if (error.line() == -1)
@@ -344,7 +341,7 @@ QV4::ReturnedValue QQmlJavaScriptExpression::qmlBinding(QQmlContextData *ctxt, Q
return QV4::Encode::undefined();
}
if (qmlscope)
- *qmlscope = qmlScopeObject;
+ qmlscope->set(v4, qmlScopeObject);
return result.asReturnedValue();
}
diff --git a/src/qml/qml/qqmljavascriptexpression_p.h b/src/qml/qml/qqmljavascriptexpression_p.h
index 2c78a745fc..dc48c2458d 100644
--- a/src/qml/qml/qqmljavascriptexpression_p.h
+++ b/src/qml/qml/qqmljavascriptexpression_p.h
@@ -52,10 +52,6 @@
QT_BEGIN_NAMESPACE
-namespace QV4 {
-struct ExecutionContext;
-}
-
class QQmlDelayedError
{
public:
@@ -81,7 +77,7 @@ public:
void setErrorObject(QObject *object);
// Call only from catch(...) -- will re-throw if no JS exception
- void catchJavaScriptException(QV4::ExecutionContext *context);
+ void catchJavaScriptException(QV4::ExecutionEngine *engine);
private:
diff --git a/src/qml/qml/qqmllistwrapper.cpp b/src/qml/qml/qqmllistwrapper.cpp
index 13e5e49b55..b2e84c0724 100644
--- a/src/qml/qml/qqmllistwrapper.cpp
+++ b/src/qml/qml/qqmllistwrapper.cpp
@@ -35,6 +35,7 @@
#include <private/qv8engine_p.h>
#include <private/qqmllist_p.h>
#include <private/qv4objectproto_p.h>
+#include <qv4objectiterator_p.h>
#include <private/qv4functionobject_p.h>
@@ -44,30 +45,28 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(QmlListWrapper);
-QmlListWrapper::Data::Data(QV8Engine *engine)
- : Object::Data(QV8Engine::getV4(engine))
- , v8(engine)
+Heap::QmlListWrapper::QmlListWrapper(ExecutionEngine *engine)
+ : Heap::Object(engine)
{
- setVTable(staticVTable());
+ setVTable(QV4::QmlListWrapper::staticVTable());
- QV4::Scope scope(QV8Engine::getV4(engine));
+ QV4::Scope scope(engine);
QV4::ScopedObject o(scope, this);
- o->setArrayType(ArrayData::Custom);
+ o->setArrayType(Heap::ArrayData::Custom);
}
-QmlListWrapper::Data::~Data()
+Heap::QmlListWrapper::~QmlListWrapper()
{
}
-ReturnedValue QmlListWrapper::create(QV8Engine *v8, QObject *object, int propId, int propType)
+ReturnedValue QmlListWrapper::create(ExecutionEngine *engine, QObject *object, int propId, int propType)
{
if (!object || propId == -1)
return Encode::null();
- ExecutionEngine *v4 = QV8Engine::getV4(v8);
- Scope scope(v4);
+ Scope scope(engine);
- Scoped<QmlListWrapper> r(scope, v4->memoryManager->alloc<QmlListWrapper>(v8));
+ Scoped<QmlListWrapper> r(scope, engine->memoryManager->alloc<QmlListWrapper>(engine));
r->d()->object = object;
r->d()->propertyType = propType;
void *args[] = { &r->d()->property, 0 };
@@ -75,12 +74,11 @@ ReturnedValue QmlListWrapper::create(QV8Engine *v8, QObject *object, int propId,
return r.asReturnedValue();
}
-ReturnedValue QmlListWrapper::create(QV8Engine *v8, const QQmlListProperty<QObject> &prop, int propType)
+ReturnedValue QmlListWrapper::create(ExecutionEngine *engine, const QQmlListProperty<QObject> &prop, int propType)
{
- ExecutionEngine *v4 = QV8Engine::getV4(v8);
- Scope scope(v4);
+ Scope scope(engine);
- Scoped<QmlListWrapper> r(scope, v4->memoryManager->alloc<QmlListWrapper>(v8));
+ Scoped<QmlListWrapper> r(scope, engine->memoryManager->alloc<QmlListWrapper>(engine));
r->d()->object = prop.object;
r->d()->property = prop;
r->d()->propertyType = propType;
@@ -92,7 +90,7 @@ QVariant QmlListWrapper::toVariant() const
if (!d()->object)
return QVariant();
- return QVariant::fromValue(QQmlListReferencePrivate::init(d()->property, d()->propertyType, d()->v8->engine()));
+ return QVariant::fromValue(QQmlListReferencePrivate::init(d()->property, d()->propertyType, engine()->qmlEngine()));
}
@@ -142,15 +140,9 @@ void QmlListWrapper::put(Managed *m, String *name, const ValueRef value)
Q_UNUSED(value);
}
-void QmlListWrapper::destroy(Managed *that)
+void QmlListWrapper::advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attrs)
{
- Q_ASSERT(that->as<QmlListWrapper>());
- static_cast<QmlListWrapper *>(that)->d()->~Data();
-}
-
-void QmlListWrapper::advanceIterator(Managed *m, ObjectIterator *it, String *&name, uint *index, Property *p, PropertyAttributes *attrs)
-{
- name = (String *)0;
+ *name = (Heap::String *)0;
*index = UINT_MAX;
Q_ASSERT(m->as<QmlListWrapper>());
QmlListWrapper *w = static_cast<QmlListWrapper *>(m);
diff --git a/src/qml/qml/qqmllistwrapper_p.h b/src/qml/qml/qqmllistwrapper_p.h
index fe78079bac..1c2ad03992 100644
--- a/src/qml/qml/qqmllistwrapper_p.h
+++ b/src/qml/qml/qqmllistwrapper_p.h
@@ -59,28 +59,32 @@ class QV8Engine;
namespace QV4 {
+namespace Heap {
+
+struct QmlListWrapper : Object {
+ QmlListWrapper(ExecutionEngine *engine);
+ ~QmlListWrapper();
+ QPointer<QObject> object;
+ QQmlListProperty<QObject> property;
+ int propertyType;
+};
+
+}
+
struct Q_QML_EXPORT QmlListWrapper : Object
{
- struct Data : Object::Data {
- Data(QV8Engine *engine);
- ~Data();
- QV8Engine *v8;
- QPointer<QObject> object;
- QQmlListProperty<QObject> property;
- int propertyType;
- };
- V4_OBJECT(Object)
-
- static ReturnedValue create(QV8Engine *v8, QObject *object, int propId, int propType);
- static ReturnedValue create(QV8Engine *v8, const QQmlListProperty<QObject> &prop, int propType);
+ V4_OBJECT2(QmlListWrapper, Object)
+ V4_NEEDS_DESTROY
+
+ static ReturnedValue create(ExecutionEngine *engine, QObject *object, int propId, int propType);
+ static ReturnedValue create(ExecutionEngine *engine, const QQmlListProperty<QObject> &prop, int propType);
QVariant toVariant() const;
static ReturnedValue get(Managed *m, String *name, bool *hasProperty);
static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty);
static void put(Managed *m, String *name, const ValueRef value);
- static void advanceIterator(Managed *m, ObjectIterator *it, String *&name, uint *index, Property *p, PropertyAttributes *attributes);
- static void destroy(Managed *that);
+ static void advanceIterator(Managed *m, ObjectIterator *it, Heap::String **name, uint *index, Property *p, PropertyAttributes *attributes);
};
}
diff --git a/src/qml/qml/qqmllocale.cpp b/src/qml/qml/qqmllocale.cpp
index 6df0bd0e1d..05cfd2e2a1 100644
--- a/src/qml/qml/qqmllocale.cpp
+++ b/src/qml/qml/qqmllocale.cpp
@@ -46,6 +46,8 @@
QT_BEGIN_NAMESPACE
+using namespace QV4;
+
DEFINE_OBJECT_VTABLE(QQmlLocaleData);
#define GET_LOCALE_DATA_RESOURCE(OBJECT) \
@@ -63,9 +65,9 @@ static bool isLocaleObject(const QV4::ValueRef val)
void QQmlDateExtension::registerExtension(QV4::ExecutionEngine *engine)
{
- engine->dateClass->prototype->defineDefaultProperty(QStringLiteral("toLocaleString"), method_toLocaleString);
- engine->dateClass->prototype->defineDefaultProperty(QStringLiteral("toLocaleTimeString"), method_toLocaleTimeString);
- engine->dateClass->prototype->defineDefaultProperty(QStringLiteral("toLocaleDateString"), method_toLocaleDateString);
+ engine->datePrototype.asObject()->defineDefaultProperty(QStringLiteral("toLocaleString"), method_toLocaleString);
+ engine->datePrototype.asObject()->defineDefaultProperty(QStringLiteral("toLocaleTimeString"), method_toLocaleTimeString);
+ engine->datePrototype.asObject()->defineDefaultProperty(QStringLiteral("toLocaleDateString"), method_toLocaleDateString);
engine->dateCtor.objectValue()->defineDefaultProperty(QStringLiteral("fromLocaleString"), method_fromLocaleString);
engine->dateCtor.objectValue()->defineDefaultProperty(QStringLiteral("fromLocaleTimeString"), method_fromLocaleTimeString);
engine->dateCtor.objectValue()->defineDefaultProperty(QStringLiteral("fromLocaleDateString"), method_fromLocaleDateString);
@@ -345,8 +347,8 @@ QV4::ReturnedValue QQmlDateExtension::method_timeZoneUpdated(QV4::CallContext *c
void QQmlNumberExtension::registerExtension(QV4::ExecutionEngine *engine)
{
- engine->numberClass->prototype->defineDefaultProperty(QStringLiteral("toLocaleString"), method_toLocaleString);
- engine->numberClass->prototype->defineDefaultProperty(QStringLiteral("toLocaleCurrencyString"), method_toLocaleCurrencyString);
+ engine->numberPrototype.asObject()->defineDefaultProperty(QStringLiteral("toLocaleString"), method_toLocaleString);
+ engine->numberPrototype.asObject()->defineDefaultProperty(QStringLiteral("toLocaleCurrencyString"), method_toLocaleCurrencyString);
engine->numberCtor.objectValue()->defineDefaultProperty(QStringLiteral("fromLocaleString"), method_fromLocaleString);
}
@@ -374,9 +376,9 @@ QV4::ReturnedValue QQmlNumberExtension::method_toLocaleString(QV4::CallContext *
if (ctx->d()->callData->argc > 1) {
if (!ctx->d()->callData->args[1].isString())
V4THROW_ERROR("Locale: Number.toLocaleString(): Invalid arguments");
- QV4::String *fs = ctx->d()->callData->args[1].toString(ctx);
- if (fs->d()->length())
- format = fs->toQString().at(0).unicode();
+ QString fs = ctx->d()->callData->args[1].toQString();
+ if (fs.length())
+ format = fs.at(0).unicode();
}
int prec = 2;
if (ctx->d()->callData->argc > 2) {
@@ -438,12 +440,12 @@ QV4::ReturnedValue QQmlNumberExtension::method_fromLocaleString(QV4::CallContext
numberIdx = 1;
}
- QV4::String *ns = ctx->d()->callData->args[numberIdx].toString(ctx);
- if (!ns->d()->length())
+ QString ns = ctx->d()->callData->args[numberIdx].toQString();
+ if (!ns.length())
return QV4::Encode(Q_QNAN);
bool ok = false;
- double val = locale.toDouble(ns->toQString(), &ok);
+ double val = locale.toDouble(ns, &ok);
if (!ok)
V4THROW_ERROR("Locale: Number.fromLocaleString(): Invalid format")
@@ -491,7 +493,7 @@ QV4::ReturnedValue QQmlLocaleData::method_get_weekDays(QV4::CallContext *ctx)
QList<Qt::DayOfWeek> days = locale->weekdays();
- QV4::Scoped<QV4::ArrayObject> result(scope, ctx->d()->engine->newArrayObject());
+ QV4::ScopedArrayObject result(scope, ctx->d()->engine->newArrayObject());
result->arrayReserve(days.size());
for (int i = 0; i < days.size(); ++i) {
int day = days.at(i);
@@ -512,7 +514,7 @@ QV4::ReturnedValue QQmlLocaleData::method_get_uiLanguages(QV4::CallContext *ctx)
return QV4::Encode::undefined();
QStringList langs = locale->uiLanguages();
- QV4::Scoped<QV4::ArrayObject> result(scope, ctx->d()->engine->newArrayObject());
+ QV4::ScopedArrayObject result(scope, ctx->d()->engine->newArrayObject());
result->arrayReserve(langs.size());
QV4::ScopedValue v(scope);
for (int i = 0; i < langs.size(); ++i)
@@ -641,20 +643,19 @@ LOCALE_STRING_PROPERTY(exponential)
LOCALE_STRING_PROPERTY(amText)
LOCALE_STRING_PROPERTY(pmText)
-class QV8LocaleDataDeletable : public QV8Engine::Deletable
+class QV4LocaleDataDeletable : public QV8Engine::Deletable
{
public:
- QV8LocaleDataDeletable(QV8Engine *engine);
- ~QV8LocaleDataDeletable();
+ QV4LocaleDataDeletable(QV4::ExecutionEngine *engine);
+ ~QV4LocaleDataDeletable();
QV4::PersistentValue prototype;
};
-QV8LocaleDataDeletable::QV8LocaleDataDeletable(QV8Engine *engine)
+QV4LocaleDataDeletable::QV4LocaleDataDeletable(QV4::ExecutionEngine *engine)
{
- QV4::ExecutionEngine *eng = QV8Engine::getV4(engine);
- QV4::Scope scope(eng);
- QV4::Scoped<QV4::Object> o(scope, eng->newObject());
+ QV4::Scope scope(engine);
+ QV4::Scoped<QV4::Object> o(scope, engine->newObject());
o->defineDefaultProperty(QStringLiteral("dateFormat"), QQmlLocaleData::method_dateFormat, 0);
o->defineDefaultProperty(QStringLiteral("standaloneDayName"), QQmlLocaleData::method_standaloneDayName, 0);
@@ -682,14 +683,14 @@ QV8LocaleDataDeletable::QV8LocaleDataDeletable(QV8Engine *engine)
o->defineAccessorProperty(QStringLiteral("measurementSystem"), QQmlLocaleData::method_get_measurementSystem, 0);
o->defineAccessorProperty(QStringLiteral("exponential"), QQmlLocaleData::method_get_exponential, 0);
- prototype = o;
+ prototype.set(engine, o);
}
-QV8LocaleDataDeletable::~QV8LocaleDataDeletable()
+QV4LocaleDataDeletable::~QV4LocaleDataDeletable()
{
}
-V8_DEFINE_EXTENSION(QV8LocaleDataDeletable, localeV8Data);
+V4_DEFINE_EXTENSION(QV4LocaleDataDeletable, localeV4Data);
/*!
\qmltype Locale
@@ -793,29 +794,28 @@ QQmlLocale::~QQmlLocale()
{
}
-QV4::ReturnedValue QQmlLocale::locale(QV8Engine *v8engine, const QString &localeName)
+QV4::ReturnedValue QQmlLocale::locale(ExecutionEngine *engine, const QString &localeName)
{
QLocale qlocale;
if (!localeName.isEmpty())
qlocale = localeName;
- return wrap(v8engine, qlocale);
+ return wrap(engine, qlocale);
}
-QV4::ReturnedValue QQmlLocale::wrap(QV8Engine *engine, const QLocale &locale)
+QV4::ReturnedValue QQmlLocale::wrap(ExecutionEngine *v4, const QLocale &locale)
{
- QV8LocaleDataDeletable *d = localeV8Data(engine);
- QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
QV4::Scope scope(v4);
+ QV4LocaleDataDeletable *d = localeV4Data(scope.engine);
QV4::Scoped<QQmlLocaleData> wrapper(scope, v4->memoryManager->alloc<QQmlLocaleData>(v4));
wrapper->d()->locale = locale;
QV4::ScopedObject p(scope, d->prototype.value());
- wrapper->setPrototype(p.getPointer());
+ wrapper->setPrototype(p);
return wrapper.asReturnedValue();
}
void QQmlLocale::registerStringLocaleCompare(QV4::ExecutionEngine *engine)
{
- engine->stringObjectClass->prototype->defineDefaultProperty(QStringLiteral("localeCompare"), method_localeCompare);
+ engine->stringPrototype.asObject()->defineDefaultProperty(QStringLiteral("localeCompare"), method_localeCompare);
}
QV4::ReturnedValue QQmlLocale::method_localeCompare(QV4::CallContext *ctx)
diff --git a/src/qml/qml/qqmllocale_p.h b/src/qml/qml/qqmllocale_p.h
index 3787517038..f294137340 100644
--- a/src/qml/qml/qqmllocale_p.h
+++ b/src/qml/qml/qqmllocale_p.h
@@ -38,8 +38,7 @@
#include <QtCore/qlocale.h>
#include <QtCore/qobject.h>
-#include <private/qv8engine_p.h>
-
+#include <private/qqmlglobal_p.h>
QT_BEGIN_NAMESPACE
@@ -110,8 +109,8 @@ public:
Saturday = Qt::Saturday
};
- static QV4::ReturnedValue locale(QV8Engine *v8engine, const QString &localeName);
- static QV4::ReturnedValue wrap(QV8Engine *engine, const QLocale &locale);
+ static QV4::ReturnedValue locale(QV4::ExecutionEngine *engine, const QString &localeName);
+ static QV4::ReturnedValue wrap(QV4::ExecutionEngine *engine, const QLocale &locale);
static void registerStringLocaleCompare(QV4::ExecutionEngine *engine);
@@ -121,23 +120,27 @@ private:
static QV4::ReturnedValue method_localeCompare(QV4::CallContext *ctx);
};
+namespace QV4 {
+
+namespace Heap {
+
+struct QQmlLocaleData : Object {
+ inline QQmlLocaleData(ExecutionEngine *engine);
+ QLocale locale;
+};
+
+}
+
struct QQmlLocaleData : public QV4::Object
{
- struct Data : Object::Data {
- Data(QV4::ExecutionEngine *engine)
- : Object::Data(engine)
- {
- setVTable(staticVTable());
- }
- QLocale locale;
- };
- V4_OBJECT(Object)
+ V4_OBJECT2(QQmlLocaleData, Object)
+ V4_NEEDS_DESTROY
static QLocale *getThisLocale(QV4::CallContext *ctx) {
QV4::Object *o = ctx->d()->callData->thisObject.asObject();
QQmlLocaleData *thisObject = o ? o->as<QQmlLocaleData>() : 0;
if (!thisObject) {
- ctx->throwTypeError();
+ ctx->engine()->throwTypeError();
return 0;
}
return &thisObject->d()->locale;
@@ -170,14 +173,16 @@ struct QQmlLocaleData : public QV4::Object
static QV4::ReturnedValue method_get_exponential(QV4::CallContext *ctx);
static QV4::ReturnedValue method_get_amText(QV4::CallContext *ctx);
static QV4::ReturnedValue method_get_pmText(QV4::CallContext *ctx);
-
-private:
- static void destroy(Managed *that)
- {
- static_cast<QQmlLocaleData *>(that)->d()->~Data();
- }
};
+Heap::QQmlLocaleData::QQmlLocaleData(ExecutionEngine *engine)
+ : Heap::Object(engine)
+{
+ setVTable(QV4::QQmlLocaleData::staticVTable());
+}
+
+}
+
QT_END_NAMESPACE
#endif
diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp
index d20fe72d09..00fe233124 100644
--- a/src/qml/qml/qqmlmetatype.cpp
+++ b/src/qml/qml/qqmlmetatype.cpp
@@ -1391,14 +1391,14 @@ bool qmlProtectModule(const char *uri, int majVersion)
return false;
}
-bool QQmlMetaType::namespaceContainsRegistrations(const QString &uri)
+bool QQmlMetaType::namespaceContainsRegistrations(const QString &uri, int majorVersion)
{
QQmlMetaTypeData *data = metaTypeData();
// Has any type previously been installed to this namespace?
QHashedString nameSpace(uri);
foreach (const QQmlType *type, data->types)
- if (type->module() == nameSpace)
+ if (type->module() == nameSpace && type->majorVersion() == majorVersion)
return true;
return false;
diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h
index ac408836fa..2fcd113183 100644
--- a/src/qml/qml/qqmlmetatype_p.h
+++ b/src/qml/qml/qqmlmetatype_p.h
@@ -114,7 +114,7 @@ public:
static const QQmlPrivate::CachedQmlUnit *findCachedCompilationUnit(const QUrl &uri);
- static bool namespaceContainsRegistrations(const QString &);
+ static bool namespaceContainsRegistrations(const QString &, int majorVersion);
static void protectNamespace(const QString &);
diff --git a/src/qml/qml/qqmlnotifier_p.h b/src/qml/qml/qqmlnotifier_p.h
index 1cfde3da06..43eed3052a 100644
--- a/src/qml/qml/qqmlnotifier_p.h
+++ b/src/qml/qml/qqmlnotifier_p.h
@@ -72,8 +72,7 @@ public:
None = 0,
QQmlBoundSignal = 1,
QQmlJavaScriptExpressionGuard = 2,
- QQmlVMEMetaObjectEndpoint = 3,
- QV4BindingsSubscription = 4
+ QQmlVMEMetaObjectEndpoint = 3
};
inline void setCallback(Callback c) { callback = c; }
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp
index 42cac66fbd..8c34fc3997 100644
--- a/src/qml/qml/qqmlobjectcreator.cpp
+++ b/src/qml/qml/qqmlobjectcreator.cpp
@@ -41,7 +41,6 @@
#include <private/qqmlbinding_p.h>
#include <private/qqmlstringconverters_p.h>
#include <private/qqmlboundsignal_p.h>
-#include <private/qqmltrace_p.h>
#include <private/qqmlcomponentattached_p.h>
#include <private/qqmlcomponent_p.h>
#include <private/qqmlcustomparser_p.h>
@@ -65,9 +64,8 @@ struct ActiveOCRestorer
static void removeBindingOnProperty(QObject *o, int index)
{
- int coreIndex = index & 0x0000FFFF;
- int valueTypeIndex = (index & 0xFFFF0000 ? index >> 16 : -1);
-
+ int coreIndex;
+ int valueTypeIndex = QQmlPropertyData::decodeValueTypePropertyIndex(index, &coreIndex);
QQmlAbstractBinding *binding = QQmlPropertyPrivate::setBinding(o, coreIndex, valueTypeIndex, 0);
if (binding) binding->destroy();
}
@@ -210,7 +208,7 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlI
if (subComponentIndex == -1) {
QV4::ScopedObject scripts(scope, v4->newArrayObject(compiledData->scripts.count()));
- context->importedScripts = scripts;
+ context->importedScripts.set(v4, scripts);
for (int i = 0; i < compiledData->scripts.count(); ++i) {
QQmlScriptData *s = compiledData->scripts.at(i);
scripts->putIndexed(i, s->scriptValueForContext(context));
@@ -265,9 +263,11 @@ bool QQmlObjectCreator::populateDeferredProperties(QObject *instance)
Q_ASSERT(!sharedState->allJavaScriptObjects);
sharedState->allJavaScriptObjects = valueScope.alloc(compiledData->totalObjectCount);
- QV4::ScopedObject qmlScope(valueScope, QV4::QmlContextWrapper::qmlScope(QV8Engine::get(engine), context, _scopeObject));
- QV4::Scoped<QV4::QmlBindingWrapper> qmlBindingWrapper(valueScope, v4->memoryManager->alloc<QV4::QmlBindingWrapper>(v4->rootContext, qmlScope));
- QV4::ExecutionContext *qmlContext = qmlBindingWrapper->context();
+ QV4::ScopedObject qmlScope(valueScope, QV4::QmlContextWrapper::qmlScope(v4, context, _scopeObject));
+ QV4::ScopedContext global(valueScope, valueScope.engine->rootContext());
+ QV4::Scoped<QV4::QmlBindingWrapper> qmlBindingWrapper(valueScope, v4->memoryManager->alloc<QV4::QmlBindingWrapper>(global, qmlScope));
+ // ### GC
+ QV4::ExecutionContext *qmlContext = QV4::ScopedContext(valueScope, qmlBindingWrapper->context());
qSwap(_qmlContext, qmlContext);
@@ -1175,9 +1175,11 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
ref = QV4::QObjectWrapper::wrap(v4, instance);
QV4::Scope valueScope(v4);
- QV4::ScopedObject qmlScope(valueScope, QV4::QmlContextWrapper::qmlScope(QV8Engine::get(engine), context, _scopeObject));
- QV4::Scoped<QV4::QmlBindingWrapper> qmlBindingWrapper(valueScope, v4->memoryManager->alloc<QV4::QmlBindingWrapper>(v4->rootContext, qmlScope));
- QV4::ExecutionContext *qmlContext = qmlBindingWrapper->context();
+ QV4::ScopedObject qmlScope(valueScope, QV4::QmlContextWrapper::qmlScope(v4, context, _scopeObject));
+ QV4::ScopedContext global(valueScope, valueScope.engine->rootContext());
+ QV4::Scoped<QV4::QmlBindingWrapper> qmlBindingWrapper(valueScope, v4->memoryManager->alloc<QV4::QmlBindingWrapper>(global, qmlScope));
+ // ### GC
+ QV4::ExecutionContext *qmlContext = QV4::ScopedContext(valueScope, qmlBindingWrapper->context());
qSwap(_qmlContext, qmlContext);
@@ -1197,10 +1199,6 @@ QQmlContextData *QQmlObjectCreator::finalize(QQmlInstantiationInterrupt &interru
QQmlObjectCreatorRecursionWatcher watcher(this);
ActiveOCRestorer ocRestorer(this, QQmlEnginePrivate::get(engine));
- {
- QQmlTrace trace("VME Binding Enable");
- trace.event("begin binding eval");
-
while (!sharedState->allCreatedBindings.isEmpty()) {
QQmlAbstractBinding *b = sharedState->allCreatedBindings.pop();
if (!b)
@@ -1215,10 +1213,8 @@ QQmlContextData *QQmlObjectCreator::finalize(QQmlInstantiationInterrupt &interru
if (watcher.hasRecursed() || interrupt.shouldInterrupt())
return 0;
}
- }
if (QQmlVME::componentCompleteEnabled()) { // the qml designer does the component complete later
- QQmlTrace trace("VME Component Complete");
while (!sharedState->allParserStatusCallbacks.isEmpty()) {
QQmlObjectCompletionProfiler profiler(&sharedState->profiler);
QQmlParserStatus *status = sharedState->allParserStatusCallbacks.pop();
@@ -1233,8 +1229,6 @@ QQmlContextData *QQmlObjectCreator::finalize(QQmlInstantiationInterrupt &interru
}
}
- {
- QQmlTrace trace("VME Finalize Callbacks");
for (int ii = 0; ii < sharedState->finalizeCallbacks.count(); ++ii) {
QQmlEnginePrivate::FinalizeCallback callback = sharedState->finalizeCallbacks.at(ii);
QObject *obj = callback.first;
@@ -1246,10 +1240,7 @@ QQmlContextData *QQmlObjectCreator::finalize(QQmlInstantiationInterrupt &interru
return 0;
}
sharedState->finalizeCallbacks.clear();
- }
- {
- QQmlTrace trace("VME Component.onCompleted Callbacks");
while (sharedState->componentAttached) {
QQmlComponentAttached *a = sharedState->componentAttached;
a->rem();
@@ -1263,7 +1254,6 @@ QQmlContextData *QQmlObjectCreator::finalize(QQmlInstantiationInterrupt &interru
if (watcher.hasRecursed() || interrupt.shouldInterrupt())
return 0;
}
- }
phase = Done;
diff --git a/src/qml/qml/qqmlopenmetaobject.cpp b/src/qml/qml/qqmlopenmetaobject.cpp
index f4d050a1d7..e234a0bfbe 100644
--- a/src/qml/qml/qqmlopenmetaobject.cpp
+++ b/src/qml/qml/qqmlopenmetaobject.cpp
@@ -35,6 +35,7 @@
#include <private/qqmlpropertycache_p.h>
#include <private/qqmldata_p.h>
#include <private/qmetaobjectbuilder_p.h>
+#include <qqmlengine.h>
#include <qdebug.h>
QT_BEGIN_NAMESPACE
@@ -119,7 +120,7 @@ int QQmlOpenMetaObjectType::createProperty(const QByteArray &name)
QQmlOpenMetaObject *omo = *it;
*static_cast<QMetaObject *>(omo) = *d->mem;
if (d->cache)
- d->cache->update(d->engine, omo);
+ d->cache->update(omo);
++it;
}
diff --git a/src/qml/qml/qqmlproperty.cpp b/src/qml/qml/qqmlproperty.cpp
index 2a888b7a1e..a4c46a1705 100644
--- a/src/qml/qml/qqmlproperty.cpp
+++ b/src/qml/qml/qqmlproperty.cpp
@@ -276,7 +276,7 @@ void QQmlPropertyPrivate::initProperty(QObject *obj, const QString &name)
QQmlPropertyData local;
QQmlPropertyData *property =
- QQmlPropertyCache::property(engine, obj, pathName, context, local);
+ QQmlPropertyCache::property(engine, currentObject, pathName, context, local);
if (!property) return; // Not a property
if (property->isFunction())
@@ -284,13 +284,13 @@ void QQmlPropertyPrivate::initProperty(QObject *obj, const QString &name)
if (ii == (path.count() - 2) && QQmlValueTypeFactory::isValueType(property->propType)) {
// We're now at a value type property
- QObject *typeObject = QQmlValueTypeFactory::valueType(property->propType);
- if (!typeObject) return; // Not a value type
+ const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(property->propType);
+ if (!valueTypeMetaObject) return; // Not a value type
- int idx = typeObject->metaObject()->indexOfProperty(path.last().toUtf8().constData());
+ int idx = valueTypeMetaObject->indexOfProperty(path.last().toUtf8().constData());
if (idx == -1) return; // Value type property does not exist
- QMetaProperty vtProp = typeObject->metaObject()->property(idx);
+ QMetaProperty vtProp = valueTypeMetaObject->property(idx);
Q_ASSERT(QQmlPropertyData::flagsForProperty(vtProp) <= QQmlPropertyData::ValueTypeFlagMask);
Q_ASSERT(vtProp.userType() <= 0x0000FFFF);
@@ -463,9 +463,9 @@ const char *QQmlProperty::propertyTypeName() const
if (!d)
return 0;
if (d->isValueType()) {
- QQmlValueType *valueType = QQmlValueTypeFactory::valueType(d->core.propType);
- Q_ASSERT(valueType);
- return valueType->metaObject()->property(d->core.valueTypeCoreIndex).typeName();
+ const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(d->core.propType);
+ Q_ASSERT(valueTypeMetaObject);
+ return valueTypeMetaObject->property(d->core.valueTypeCoreIndex).typeName();
} else if (d->object && type() & Property && d->core.isValid()) {
return d->object->metaObject()->property(d->core.coreIndex).typeName();
} else {
@@ -642,10 +642,10 @@ QString QQmlProperty::name() const
} else if (d->isValueType()) {
QString rv = d->core.name(d->object) + QLatin1Char('.');
- QQmlValueType *valueType = QQmlValueTypeFactory::valueType(d->core.propType);
- Q_ASSERT(valueType);
+ const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(d->core.propType);
+ Q_ASSERT(valueTypeMetaObject);
- const char *vtName = valueType->metaObject()->property(d->core.valueTypeCoreIndex).name();
+ const char *vtName = valueTypeMetaObject->property(d->core.valueTypeCoreIndex).name();
rv += QString::fromUtf8(vtName);
d->nameCache = rv;
@@ -734,8 +734,8 @@ QQmlPropertyPrivate::setBinding(const QQmlProperty &that,
QObject *object = newBinding->object();
int pi = newBinding->propertyIndex();
- int core = pi & 0x0000FFFF;
- int vt = (pi & 0xFFFF0000)?(pi >> 16):-1;
+ int core;
+ int vt = QQmlPropertyData::decodeValueTypePropertyIndex(pi, &core);
return setBinding(object, core, vt, newBinding, flags);
} else {
@@ -776,7 +776,7 @@ QQmlPropertyPrivate::binding(QObject *object, int coreIndex, int valueTypeIndex)
if (binding && valueTypeIndex != -1) {
if (binding->bindingType() == QQmlAbstractBinding::ValueTypeProxy) {
- int index = coreIndex | (valueTypeIndex << 16);
+ int index = QQmlPropertyData::encodeValueTypePropertyIndex(coreIndex, valueTypeIndex);
binding = static_cast<QQmlValueTypeProxyBinding *>(binding)->binding(index);
}
}
@@ -787,8 +787,8 @@ QQmlPropertyPrivate::binding(QObject *object, int coreIndex, int valueTypeIndex)
void QQmlPropertyPrivate::findAliasTarget(QObject *object, int bindingIndex,
QObject **targetObject, int *targetBindingIndex)
{
- int coreIndex = bindingIndex & 0x0000FFFF;
- int valueTypeIndex = (bindingIndex & 0xFFFF0000)?(bindingIndex >> 16):-1;
+ int coreIndex;
+ int valueTypeIndex = QQmlPropertyData::decodeValueTypePropertyIndex(bindingIndex, &coreIndex);
QQmlData *data = QQmlData::get(object, false);
if (data) {
@@ -804,9 +804,9 @@ void QQmlPropertyPrivate::findAliasTarget(QObject *object, int bindingIndex,
int aBindingIndex = aCoreIndex;
if (aValueTypeIndex != -1)
- aBindingIndex |= aValueTypeIndex << 16;
+ aBindingIndex = QQmlPropertyData::encodeValueTypePropertyIndex(aBindingIndex, aValueTypeIndex);
else if (valueTypeIndex != -1)
- aBindingIndex |= valueTypeIndex << 16;
+ aBindingIndex = QQmlPropertyData::encodeValueTypePropertyIndex(aBindingIndex, valueTypeIndex);
findAliasTarget(aObject, aBindingIndex, targetObject, targetBindingIndex);
return;
@@ -853,7 +853,7 @@ QQmlPropertyPrivate::setBinding(QObject *object, int coreIndex, int valueTypeInd
int index = coreIndex;
if (valueTypeIndex != -1)
- index |= (valueTypeIndex << 16);
+ index = QQmlPropertyData::encodeValueTypePropertyIndex(index, valueTypeIndex);
if (binding && valueTypeIndex != -1 && binding->bindingType() == QQmlAbstractBinding::ValueTypeProxy)
binding = static_cast<QQmlValueTypeProxyBinding *>(binding)->binding(index);
@@ -912,7 +912,7 @@ QQmlPropertyPrivate::setBindingNoEnable(QObject *object, int coreIndex, int valu
int index = coreIndex;
if (valueTypeIndex != -1)
- index |= (valueTypeIndex << 16);
+ index = QQmlPropertyData::encodeValueTypePropertyIndex(index, valueTypeIndex);
if (binding && valueTypeIndex != -1 && binding->bindingType() == QQmlAbstractBinding::ValueTypeProxy)
binding = static_cast<QQmlValueTypeProxyBinding *>(binding)->binding(index);
@@ -1513,20 +1513,20 @@ bool QQmlPropertyPrivate::writeBinding(QObject *object,
if (isUndefined) {
} else if (core.isQList()) {
- value = v8engine->toVariant(result, qMetaTypeId<QList<QObject *> >());
+ value = QV8Engine::getV4(v8engine)->toVariant(result, qMetaTypeId<QList<QObject *> >());
} else if (result->isNull() && core.isQObject()) {
value = QVariant::fromValue((QObject *)0);
} else if (core.propType == qMetaTypeId<QList<QUrl> >()) {
- value = resolvedUrlSequence(v8engine->toVariant(result, qMetaTypeId<QList<QUrl> >()), context);
+ value = resolvedUrlSequence(QV8Engine::getV4(v8engine)->toVariant(result, qMetaTypeId<QList<QUrl> >()), context);
} else if (!isVarProperty && type != qMetaTypeId<QJSValue>()) {
- value = v8engine->toVariant(result, type);
+ value = QV8Engine::getV4(v8engine)->toVariant(result, type);
}
if (expression->hasError()) {
return false;
} else if (isVarProperty) {
QV4::FunctionObject *f = result->asFunctionObject();
- if (f && f->bindingKeyFlag()) {
+ if (f && f->isBinding()) {
// we explicitly disallow this case to avoid confusion. Users can still store one
// in an array in a var property if they need to, but the common case is user error.
expression->delayedError()->setErrorDescription(QLatin1String("Invalid use of Qt.binding() in a binding declaration."));
@@ -1544,7 +1544,7 @@ bool QQmlPropertyPrivate::writeBinding(QObject *object,
writeValueProperty(object, core, QVariant(), context, flags);
} else if (type == qMetaTypeId<QJSValue>()) {
QV4::FunctionObject *f = result->asFunctionObject();
- if (f && f->bindingKeyFlag()) {
+ if (f && f->isBinding()) {
expression->delayedError()->setErrorDescription(QLatin1String("Invalid use of Qt.binding() in a binding declaration."));
expression->delayedError()->setErrorObject(object);
return false;
@@ -1562,7 +1562,7 @@ bool QQmlPropertyPrivate::writeBinding(QObject *object,
expression->delayedError()->setErrorObject(object);
return false;
} else if (QV4::FunctionObject *f = result->asFunctionObject()) {
- if (f->bindingKeyFlag())
+ if (f->isBinding())
expression->delayedError()->setErrorDescription(QLatin1String("Invalid use of Qt.binding() in a binding declaration."));
else
expression->delayedError()->setErrorDescription(QLatin1String("Unable to assign a function to a property of any type other than var."));
diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp
index dbb85f8b03..9f96e36572 100644
--- a/src/qml/qml/qqmlpropertycache.cpp
+++ b/src/qml/qml/qqmlpropertycache.cpp
@@ -140,10 +140,8 @@ QQmlPropertyData::flagsForProperty(const QMetaProperty &p, QQmlEngine *engine)
return fastFlagsForProperty(p) | flagsForPropertyType(p.userType(), engine);
}
-void QQmlPropertyData::lazyLoad(const QMetaProperty &p, QQmlEngine *engine)
+void QQmlPropertyData::lazyLoad(const QMetaProperty &p)
{
- Q_UNUSED(engine);
-
coreIndex = p.propertyIndex();
notifyIndex = QMetaObjectPrivate::signalIndex(p.notifySignal());
Q_ASSERT(p.revision() <= Q_INT16_MAX);
@@ -233,7 +231,7 @@ void QQmlPropertyData::lazyLoad(const QMetaMethod &m)
/*!
Creates a new empty QQmlPropertyCache.
*/
-QQmlPropertyCache::QQmlPropertyCache(QQmlEngine *e)
+QQmlPropertyCache::QQmlPropertyCache(QJSEngine *e)
: engine(e), _parent(0), propertyIndexCacheStart(0), methodIndexCacheStart(0),
signalHandlerIndexCacheStart(0), _hasPropertyOverrides(false), _ownMetaObject(false),
_metaObject(0), argumentsCache(0)
@@ -244,7 +242,7 @@ QQmlPropertyCache::QQmlPropertyCache(QQmlEngine *e)
/*!
Creates a new QQmlPropertyCache of \a metaObject.
*/
-QQmlPropertyCache::QQmlPropertyCache(QQmlEngine *e, const QMetaObject *metaObject)
+QQmlPropertyCache::QQmlPropertyCache(QJSEngine *e, const QMetaObject *metaObject)
: engine(e), _parent(0), propertyIndexCacheStart(0), methodIndexCacheStart(0),
signalHandlerIndexCacheStart(0), _hasPropertyOverrides(false), _ownMetaObject(false),
_metaObject(0), argumentsCache(0)
@@ -252,7 +250,7 @@ QQmlPropertyCache::QQmlPropertyCache(QQmlEngine *e, const QMetaObject *metaObjec
Q_ASSERT(engine);
Q_ASSERT(metaObject);
- update(engine, metaObject);
+ update(metaObject);
}
QQmlPropertyCache::~QQmlPropertyCache()
@@ -281,7 +279,6 @@ QQmlPropertyCache::~QQmlPropertyCache()
void QQmlPropertyCache::destroy()
{
- Q_ASSERT(engine);
delete this;
}
@@ -313,7 +310,7 @@ QQmlPropertyCache *QQmlPropertyCache::copy()
return copy(0);
}
-QQmlPropertyCache *QQmlPropertyCache::copyAndReserve(QQmlEngine *, int propertyCount, int methodCount,
+QQmlPropertyCache *QQmlPropertyCache::copyAndReserve(int propertyCount, int methodCount,
int signalCount)
{
QQmlPropertyCache *rv = copy(propertyCount + methodCount + signalCount);
@@ -548,16 +545,16 @@ const QMetaObject *QQmlPropertyCache::firstCppMetaObject() const
}
QQmlPropertyCache *
-QQmlPropertyCache::copyAndAppend(QQmlEngine *engine, const QMetaObject *metaObject,
+QQmlPropertyCache::copyAndAppend(const QMetaObject *metaObject,
QQmlPropertyData::Flag propertyFlags,
QQmlPropertyData::Flag methodFlags,
QQmlPropertyData::Flag signalFlags)
{
- return copyAndAppend(engine, metaObject, -1, propertyFlags, methodFlags, signalFlags);
+ return copyAndAppend(metaObject, -1, propertyFlags, methodFlags, signalFlags);
}
QQmlPropertyCache *
-QQmlPropertyCache::copyAndAppend(QQmlEngine *engine, const QMetaObject *metaObject,
+QQmlPropertyCache::copyAndAppend(const QMetaObject *metaObject,
int revision,
QQmlPropertyData::Flag propertyFlags,
QQmlPropertyData::Flag methodFlags,
@@ -572,12 +569,12 @@ QQmlPropertyCache::copyAndAppend(QQmlEngine *engine, const QMetaObject *metaObje
QMetaObjectPrivate::get(metaObject)->signalCount +
QMetaObjectPrivate::get(metaObject)->propertyCount);
- rv->append(engine, metaObject, revision, propertyFlags, methodFlags, signalFlags);
+ rv->append(metaObject, revision, propertyFlags, methodFlags, signalFlags);
return rv;
}
-void QQmlPropertyCache::append(QQmlEngine *engine, const QMetaObject *metaObject,
+void QQmlPropertyCache::append(const QMetaObject *metaObject,
int revision,
QQmlPropertyData::Flag propertyFlags,
QQmlPropertyData::Flag methodFlags,
@@ -630,6 +627,8 @@ void QQmlPropertyCache::append(QQmlEngine *engine, const QMetaObject *metaObject
static const int destroyedIdx1 = QObject::staticMetaObject.indexOfSignal("destroyed(QObject*)");
static const int destroyedIdx2 = QObject::staticMetaObject.indexOfSignal("destroyed()");
static const int deleteLaterIdx = QObject::staticMetaObject.indexOfSlot("deleteLater()");
+ // These indices don't apply to gadgets, so don't block them.
+ const bool preventDestruction = metaObject->superClass() || metaObject == &QObject::staticMetaObject;
int methodOffset = metaObject->methodOffset();
int signalOffset = signalCount - QMetaObjectPrivate::get(metaObject)->signalCount;
@@ -640,7 +639,7 @@ void QQmlPropertyCache::append(QQmlEngine *engine, const QMetaObject *metaObject
signalHandlerIndexCache.resize(signalCount - signalHandlerIndexCacheStart);
int signalHandlerIndex = signalOffset;
for (int ii = methodOffset; ii < methodCount; ++ii) {
- if (ii == destroyedIdx1 || ii == destroyedIdx2 || ii == deleteLaterIdx)
+ if (preventDestruction && (ii == destroyedIdx1 || ii == destroyedIdx2 || ii == deleteLaterIdx))
continue;
QMetaMethod m = metaObject->method(ii);
if (m.access() == QMetaMethod::Private)
@@ -745,7 +744,7 @@ void QQmlPropertyCache::append(QQmlEngine *engine, const QMetaObject *metaObject
QQmlPropertyData *data = &propertyIndexCache[ii - propertyIndexCacheStart];
- data->lazyLoad(p, engine);
+ data->lazyLoad(p);
data->flags |= propertyFlags;
if (!dynamicMetaObject)
@@ -797,25 +796,46 @@ void QQmlPropertyCache::resolve(QQmlPropertyData *data) const
data->propType = QMetaType::type(data->propTypeName);
- if (!data->isFunction())
- data->flags |= flagsForPropertyType(data->propType, engine);
+ if (!data->isFunction()) {
+ if (data->propType == QMetaType::UnknownType) {
+ const QMetaObject *mo = _metaObject;
+ QQmlPropertyCache *p = _parent;
+ while (p && (!mo || _ownMetaObject)) {
+ mo = p->_metaObject;
+ p = p->_parent;
+ }
+
+ int propOffset = mo->propertyOffset();
+ if (mo && data->coreIndex < propOffset + mo->propertyCount()) {
+ while (data->coreIndex < propOffset) {
+ mo = mo->superClass();
+ propOffset = mo->propertyOffset();
+ }
+
+ int registerResult = -1;
+ void *argv[] = { &registerResult };
+ mo->static_metacall(QMetaObject::RegisterPropertyMetaType, data->coreIndex - propOffset, argv);
+ data->propType = registerResult == -1 ? QMetaType::UnknownType : registerResult;
+ }
+ }
+ data->flags |= flagsForPropertyType(data->propType, qobject_cast<QQmlEngine*>(engine));
+ }
data->flags &= ~QQmlPropertyData::NotFullyResolved;
}
-void QQmlPropertyCache::updateRecur(QQmlEngine *engine, const QMetaObject *metaObject)
+void QQmlPropertyCache::updateRecur(const QMetaObject *metaObject)
{
if (!metaObject)
return;
- updateRecur(engine, metaObject->superClass());
+ updateRecur(metaObject->superClass());
- append(engine, metaObject, -1);
+ append(metaObject, -1);
}
-void QQmlPropertyCache::update(QQmlEngine *engine, const QMetaObject *metaObject)
+void QQmlPropertyCache::update(const QMetaObject *metaObject)
{
- Q_ASSERT(engine);
Q_ASSERT(metaObject);
Q_ASSERT(stringCache.isEmpty());
@@ -833,14 +853,14 @@ void QQmlPropertyCache::update(QQmlEngine *engine, const QMetaObject *metaObject
// cached in a parent cache.
stringCache.reserve(pc + mc + sc);
- updateRecur(engine,metaObject);
+ updateRecur(metaObject);
}
/*! \internal
invalidates and updates the PropertyCache if the QMetaObject has changed.
This function is used in the tooling to update dynamic properties.
*/
-void QQmlPropertyCache::invalidate(QQmlEngine *engine, const QMetaObject *metaObject)
+void QQmlPropertyCache::invalidate(const QMetaObject *metaObject)
{
stringCache.clear();
propertyIndexCache.clear();
@@ -860,12 +880,12 @@ void QQmlPropertyCache::invalidate(QQmlEngine *engine, const QMetaObject *metaOb
methodIndexCacheStart = parent()->methodIndexCache.count() + parent()->methodIndexCacheStart;
signalHandlerIndexCacheStart = parent()->signalHandlerIndexCache.count() + parent()->signalHandlerIndexCacheStart;
stringCache.linkAndReserve(parent()->stringCache, reserve);
- append(engine, metaObject, -1);
+ append(metaObject, -1);
} else {
propertyIndexCacheStart = 0;
methodIndexCacheStart = 0;
signalHandlerIndexCacheStart = 0;
- update(engine, metaObject);
+ update(metaObject);
}
}
@@ -1115,7 +1135,7 @@ QString QQmlPropertyCache::signalParameterStringForJS(int index, QString *errorS
}
QString error;
- QString parameters = signalParameterStringForJS(engine, parameterNameList, &error);
+ QString parameters = signalParameterStringForJS(QV8Engine::getV4(engine), parameterNameList, &error);
A *arguments = static_cast<A *>(signalData->arguments);
arguments->signalParameterStringForJS = new QString(!error.isEmpty() ? error : parameters);
@@ -1128,11 +1148,10 @@ QString QQmlPropertyCache::signalParameterStringForJS(int index, QString *errorS
return *arguments->signalParameterStringForJS;
}
-QString QQmlPropertyCache::signalParameterStringForJS(QQmlEngine *engine, const QList<QByteArray> &parameterNameList, QString *errorString)
+QString QQmlPropertyCache::signalParameterStringForJS(QV4::ExecutionEngine *engine, const QList<QByteArray> &parameterNameList, QString *errorString)
{
- QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine);
bool unnamedParameter = false;
- const QSet<QString> &illegalNames = ep->v8engine()->illegalNames();
+ const QSet<QString> &illegalNames = engine->v8Engine->illegalNames();
QString error;
QString parameters;
@@ -1157,146 +1176,6 @@ QString QQmlPropertyCache::signalParameterStringForJS(QQmlEngine *engine, const
return parameters;
}
-// Returns an array of the arguments for method \a index. The first entry in the array
-// is the number of arguments.
-int *QQmlPropertyCache::methodParameterTypes(QObject *object, int index,
- QVarLengthArray<int, 9> &dummy,
- QByteArray *unknownTypeError)
-{
- Q_ASSERT(object && index >= 0);
-
- QQmlData *ddata = QQmlData::get(object, false);
-
- if (ddata && ddata->propertyCache) {
- typedef QQmlPropertyCacheMethodArguments A;
-
- QQmlPropertyCache *c = ddata->propertyCache;
- Q_ASSERT(index < c->methodIndexCacheStart + c->methodIndexCache.count());
-
- while (index < c->methodIndexCacheStart)
- c = c->_parent;
-
- QQmlPropertyData *rv = const_cast<QQmlPropertyData *>(&c->methodIndexCache.at(index - c->methodIndexCacheStart));
-
- if (rv->arguments && static_cast<A *>(rv->arguments)->argumentsValid)
- return static_cast<A *>(rv->arguments)->arguments;
-
- const QMetaObject *metaObject = c->createMetaObject();
- Q_ASSERT(metaObject);
- QMetaMethod m = metaObject->method(index);
-
- int argc = m.parameterCount();
- if (!rv->arguments) {
- A *args = c->createArgumentsObject(argc, m.parameterNames());
- rv->arguments = args;
- }
- A *args = static_cast<A *>(rv->arguments);
-
- QList<QByteArray> argTypeNames; // Only loaded if needed
-
- for (int ii = 0; ii < argc; ++ii) {
- int type = m.parameterType(ii);
- QMetaType::TypeFlags flags = QMetaType::typeFlags(type);
- if (flags & QMetaType::IsEnumeration)
- type = QVariant::Int;
- else if (type == QMetaType::UnknownType ||
- (type >= (int)QVariant::UserType && !(flags & QMetaType::PointerToQObject) &&
- type != qMetaTypeId<QJSValue>())) {
- //the UserType clause is to catch registered QFlags
- if (argTypeNames.isEmpty())
- argTypeNames = m.parameterTypes();
- type = EnumType(object->metaObject(), argTypeNames.at(ii), type);
- }
- if (type == QMetaType::UnknownType) {
- if (unknownTypeError) *unknownTypeError = argTypeNames.at(ii);
- return 0;
- }
- args->arguments[ii + 1] = type;
- }
- args->argumentsValid = true;
- return static_cast<A *>(rv->arguments)->arguments;
-
- } else {
- QMetaMethod m = object->metaObject()->method(index);
- int argc = m.parameterCount();
- dummy.resize(argc + 1);
- dummy[0] = argc;
- QList<QByteArray> argTypeNames; // Only loaded if needed
-
- for (int ii = 0; ii < argc; ++ii) {
- int type = m.parameterType(ii);
- QMetaType::TypeFlags flags = QMetaType::typeFlags(type);
- if (flags & QMetaType::IsEnumeration)
- type = QVariant::Int;
- else if (type == QMetaType::UnknownType ||
- (type >= (int)QVariant::UserType && !(flags & QMetaType::PointerToQObject) &&
- type != qMetaTypeId<QJSValue>())) {
- //the UserType clause is to catch registered QFlags)
- if (argTypeNames.isEmpty())
- argTypeNames = m.parameterTypes();
- type = EnumType(object->metaObject(), argTypeNames.at(ii), type);
- }
- if (type == QMetaType::UnknownType) {
- if (unknownTypeError) *unknownTypeError = argTypeNames.at(ii);
- return 0;
- }
- dummy[ii + 1] = type;
- }
-
- return dummy.data();
- }
-}
-
-// Returns the return type of the method.
-int QQmlPropertyCache::methodReturnType(QObject *object, const QQmlPropertyData &data,
- QByteArray *unknownTypeError)
-{
- Q_ASSERT(object && data.coreIndex >= 0);
-
- int type = data.propType;
-
- const char *propTypeName = 0;
-
- if (type == QMetaType::UnknownType) {
- // Find the return type name from the method info
- QMetaMethod m;
-
- QQmlData *ddata = QQmlData::get(object, false);
- if (ddata && ddata->propertyCache) {
- QQmlPropertyCache *c = ddata->propertyCache;
- Q_ASSERT(data.coreIndex < c->methodIndexCacheStart + c->methodIndexCache.count());
-
- while (data.coreIndex < c->methodIndexCacheStart)
- c = c->_parent;
-
- const QMetaObject *metaObject = c->createMetaObject();
- Q_ASSERT(metaObject);
- m = metaObject->method(data.coreIndex);
- } else {
- m = object->metaObject()->method(data.coreIndex);
- }
-
- type = m.returnType();
- propTypeName = m.typeName();
- }
-
- QMetaType::TypeFlags flags = QMetaType::typeFlags(type);
- if (flags & QMetaType::IsEnumeration) {
- type = QVariant::Int;
- } else if (type == QMetaType::UnknownType ||
- (type >= (int)QVariant::UserType && !(flags & QMetaType::PointerToQObject) &&
- type != qMetaTypeId<QJSValue>())) {
- //the UserType clause is to catch registered QFlags
- type = EnumType(object->metaObject(), propTypeName, type);
- }
-
- if (type == QMetaType::UnknownType) {
- if (unknownTypeError) *unknownTypeError = propTypeName;
- }
-
- return type;
-}
-
int QQmlPropertyCache::originalClone(int index)
{
while (signal(index)->isCloned())
@@ -1332,12 +1211,14 @@ QQmlPropertyData qQmlPropertyCacheCreate(const QMetaObject *metaObject, const QS
static const int destroyedIdx1 = QObject::staticMetaObject.indexOfSignal("destroyed(QObject*)");
static const int destroyedIdx2 = QObject::staticMetaObject.indexOfSignal("destroyed()");
static const int deleteLaterIdx = QObject::staticMetaObject.indexOfSlot("deleteLater()");
+ // These indices don't apply to gadgets, so don't block them.
+ const bool preventDestruction = metaObject->superClass() || metaObject == &QObject::staticMetaObject;
const QByteArray propertyName = property.toUtf8();
int methodCount = metaObject->methodCount();
for (int ii = methodCount - 1; ii >= 0; --ii) {
- if (ii == destroyedIdx1 || ii == destroyedIdx2 || ii == deleteLaterIdx)
+ if (preventDestruction && (ii == destroyedIdx1 || ii == destroyedIdx2 || ii == deleteLaterIdx))
continue;
QMetaMethod m = metaObject->method(ii);
if (m.access() == QMetaMethod::Private)
@@ -1388,7 +1269,7 @@ inline QString qQmlPropertyCacheToString(const QV4::String *string)
template<typename T>
QQmlPropertyData *
-qQmlPropertyCacheProperty(QQmlEngine *engine, QObject *obj, T name,
+qQmlPropertyCacheProperty(QJSEngine *engine, QObject *obj, T name,
QQmlContextData *context, QQmlPropertyData &local)
{
QQmlPropertyCache *cache = 0;
@@ -1398,7 +1279,7 @@ qQmlPropertyCacheProperty(QQmlEngine *engine, QObject *obj, T name,
if (ddata && ddata->propertyCache) {
cache = ddata->propertyCache;
} else if (engine) {
- QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine);
+ QJSEnginePrivate *ep = QJSEnginePrivate::get(engine);
cache = ep->cache(obj);
if (cache) {
ddata = QQmlData::get(obj, true);
@@ -1421,14 +1302,14 @@ qQmlPropertyCacheProperty(QQmlEngine *engine, QObject *obj, T name,
}
QQmlPropertyData *
-QQmlPropertyCache::property(QQmlEngine *engine, QObject *obj, const QV4::String *name,
+QQmlPropertyCache::property(QJSEngine *engine, QObject *obj, const QV4::String *name,
QQmlContextData *context, QQmlPropertyData &local)
{
return qQmlPropertyCacheProperty<const QV4::String *>(engine, obj, name, context, local);
}
QQmlPropertyData *
-QQmlPropertyCache::property(QQmlEngine *engine, QObject *obj,
+QQmlPropertyCache::property(QJSEngine *engine, QObject *obj,
const QString &name, QQmlContextData *context, QQmlPropertyData &local)
{
return qQmlPropertyCacheProperty<const QString &>(engine, obj, name, context, local);
@@ -1629,6 +1510,41 @@ bool QQmlMetaObject::canConvert(const QQmlMetaObject &from, const QQmlMetaObject
return false;
}
+void QQmlMetaObject::resolveGadgetMethodOrPropertyIndex(QMetaObject::Call type, const QMetaObject **metaObject, int *index)
+{
+ int offset;
+
+ switch (type) {
+ case QMetaObject::ReadProperty:
+ case QMetaObject::WriteProperty:
+ case QMetaObject::ResetProperty:
+ case QMetaObject::QueryPropertyDesignable:
+ case QMetaObject::QueryPropertyEditable:
+ case QMetaObject::QueryPropertyScriptable:
+ case QMetaObject::QueryPropertyStored:
+ case QMetaObject::QueryPropertyUser:
+ offset = (*metaObject)->propertyOffset();
+ while (*index < offset) {
+ *metaObject = (*metaObject)->superClass();
+ offset = (*metaObject)->propertyOffset();
+ }
+ break;
+ case QMetaObject::InvokeMetaMethod:
+ offset = (*metaObject)->methodOffset();
+ while (*index < offset) {
+ *metaObject = (*metaObject)->superClass();
+ offset = (*metaObject)->methodOffset();
+ }
+ break;
+ default:
+ offset = 0;
+ Q_UNIMPLEMENTED();
+ offset = INT_MAX;
+ }
+
+ *index -= offset;
+}
+
QQmlPropertyCache *QQmlMetaObject::propertyCache(QQmlEnginePrivate *e) const
{
if (_m.isNull()) return 0;
@@ -1636,4 +1552,146 @@ QQmlPropertyCache *QQmlMetaObject::propertyCache(QQmlEnginePrivate *e) const
else return e->cache(_m.asT2());
}
+int QQmlMetaObject::methodReturnType(const QQmlPropertyData &data, QByteArray *unknownTypeError) const
+{
+ Q_ASSERT(!_m.isNull() && data.coreIndex >= 0);
+
+ int type = data.propType;
+
+ const char *propTypeName = 0;
+
+ if (type == QMetaType::UnknownType) {
+ // Find the return type name from the method info
+ QMetaMethod m;
+
+ if (_m.isT1()) {
+ QQmlPropertyCache *c = _m.asT1();
+ Q_ASSERT(data.coreIndex < c->methodIndexCacheStart + c->methodIndexCache.count());
+
+ while (data.coreIndex < c->methodIndexCacheStart)
+ c = c->_parent;
+
+ const QMetaObject *metaObject = c->createMetaObject();
+ Q_ASSERT(metaObject);
+ m = metaObject->method(data.coreIndex);
+ } else {
+ m = _m.asT2()->method(data.coreIndex);
+ }
+
+ type = m.returnType();
+ propTypeName = m.typeName();
+ }
+
+ QMetaType::TypeFlags flags = QMetaType::typeFlags(type);
+ if (flags & QMetaType::IsEnumeration) {
+ type = QVariant::Int;
+ } else if (type == QMetaType::UnknownType ||
+ (type >= (int)QVariant::UserType && !(flags & QMetaType::PointerToQObject) &&
+ type != qMetaTypeId<QJSValue>())) {
+ //the UserType clause is to catch registered QFlags
+ type = EnumType(metaObject(), propTypeName, type);
+ }
+
+ if (type == QMetaType::UnknownType) {
+ if (unknownTypeError) *unknownTypeError = propTypeName;
+ }
+
+ return type;
+}
+
+int *QQmlMetaObject::methodParameterTypes(int index, QVarLengthArray<int, 9> &dummy, QByteArray *unknownTypeError) const
+{
+ Q_ASSERT(!_m.isNull() && index >= 0);
+
+ if (_m.isT1()) {
+ typedef QQmlPropertyCacheMethodArguments A;
+
+ QQmlPropertyCache *c = _m.asT1();
+ Q_ASSERT(index < c->methodIndexCacheStart + c->methodIndexCache.count());
+
+ while (index < c->methodIndexCacheStart)
+ c = c->_parent;
+
+ QQmlPropertyData *rv = const_cast<QQmlPropertyData *>(&c->methodIndexCache.at(index - c->methodIndexCacheStart));
+
+ if (rv->arguments && static_cast<A *>(rv->arguments)->argumentsValid)
+ return static_cast<A *>(rv->arguments)->arguments;
+
+ const QMetaObject *metaObject = c->createMetaObject();
+ Q_ASSERT(metaObject);
+ QMetaMethod m = metaObject->method(index);
+
+ int argc = m.parameterCount();
+ if (!rv->arguments) {
+ A *args = c->createArgumentsObject(argc, m.parameterNames());
+ rv->arguments = args;
+ }
+ A *args = static_cast<A *>(rv->arguments);
+
+ QList<QByteArray> argTypeNames; // Only loaded if needed
+
+ for (int ii = 0; ii < argc; ++ii) {
+ int type = m.parameterType(ii);
+ QMetaType::TypeFlags flags = QMetaType::typeFlags(type);
+ if (flags & QMetaType::IsEnumeration)
+ type = QVariant::Int;
+ else if (type == QMetaType::UnknownType ||
+ (type >= (int)QVariant::UserType && !(flags & QMetaType::PointerToQObject) &&
+ type != qMetaTypeId<QJSValue>())) {
+ //the UserType clause is to catch registered QFlags
+ if (argTypeNames.isEmpty())
+ argTypeNames = m.parameterTypes();
+ type = EnumType(metaObject, argTypeNames.at(ii), type);
+ }
+ if (type == QMetaType::UnknownType) {
+ if (unknownTypeError) *unknownTypeError = argTypeNames.at(ii);
+ return 0;
+ }
+ args->arguments[ii + 1] = type;
+ }
+ args->argumentsValid = true;
+ return static_cast<A *>(rv->arguments)->arguments;
+
+ } else {
+ QMetaMethod m = _m.asT2()->method(index);
+ int argc = m.parameterCount();
+ dummy.resize(argc + 1);
+ dummy[0] = argc;
+ QList<QByteArray> argTypeNames; // Only loaded if needed
+
+ for (int ii = 0; ii < argc; ++ii) {
+ int type = m.parameterType(ii);
+ QMetaType::TypeFlags flags = QMetaType::typeFlags(type);
+ if (flags & QMetaType::IsEnumeration)
+ type = QVariant::Int;
+ else if (type == QMetaType::UnknownType ||
+ (type >= (int)QVariant::UserType && !(flags & QMetaType::PointerToQObject) &&
+ type != qMetaTypeId<QJSValue>())) {
+ //the UserType clause is to catch registered QFlags)
+ if (argTypeNames.isEmpty())
+ argTypeNames = m.parameterTypes();
+ type = EnumType(_m.asT2(), argTypeNames.at(ii), type);
+ }
+ if (type == QMetaType::UnknownType) {
+ if (unknownTypeError) *unknownTypeError = argTypeNames.at(ii);
+ return 0;
+ }
+ dummy[ii + 1] = type;
+ }
+
+ return dummy.data();
+ }
+}
+
+void QQmlObjectOrGadget::metacall(QMetaObject::Call type, int index, void **argv) const
+{
+ if (ptr.isT1())
+ QMetaObject::metacall(ptr.asT1(), type, index, argv);
+ else {
+ const QMetaObject *metaObject = _m.asT1()->metaObject();
+ QQmlMetaObject::resolveGadgetMethodOrPropertyIndex(type, &metaObject, &index);
+ metaObject->d.static_metacall(reinterpret_cast<QObject*>(ptr.asT2()), type, index, argv);
+ }
+}
+
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlpropertycache_p.h b/src/qml/qml/qqmlpropertycache_p.h
index 8bd7cd5f56..2b8a129803 100644
--- a/src/qml/qml/qqmlpropertycache_p.h
+++ b/src/qml/qml/qqmlpropertycache_p.h
@@ -61,6 +61,7 @@ QT_BEGIN_NAMESPACE
class QV8Engine;
class QMetaProperty;
class QQmlEngine;
+class QJSEngine;
class QQmlPropertyData;
class QQmlAccessors;
class QMetaObjectBuilder;
@@ -160,8 +161,14 @@ public:
inline int getValueTypeCoreIndex() const;
// Returns the "encoded" index for use with bindings. Encoding is:
- // coreIndex | (valueTypeCoreIndex << 16)
+ // coreIndex | ((valueTypeCoreIndex + 1) << 16)
inline int encodedIndex() const;
+ static int encodeValueTypePropertyIndex(int coreIndex, int valueTypeCoreIndex)
+ { return coreIndex | ((valueTypeCoreIndex + 1) << 16); }
+ static int decodeValueTypePropertyIndex(int index, int *coreIndex = 0) {
+ if (coreIndex) *coreIndex = index & 0xffff;
+ return (index >> 16) - 1;
+ }
union {
int propType; // When !NotFullyResolved
@@ -227,7 +234,7 @@ public:
private:
friend class QQmlPropertyCache;
- void lazyLoad(const QMetaProperty &, QQmlEngine *engine = 0);
+ void lazyLoad(const QMetaProperty &);
void lazyLoad(const QMetaMethod &);
bool notFullyResolved() const { return flags & NotFullyResolved; }
};
@@ -236,25 +243,27 @@ class QQmlPropertyCacheMethodArguments;
class Q_QML_PRIVATE_EXPORT QQmlPropertyCache : public QQmlRefCount, public QQmlCleanup
{
public:
- QQmlPropertyCache(QQmlEngine *);
- QQmlPropertyCache(QQmlEngine *, const QMetaObject *);
+ QQmlPropertyCache(QJSEngine *);
+ QQmlPropertyCache(QJSEngine *, const QMetaObject *);
virtual ~QQmlPropertyCache();
- void update(QQmlEngine *, const QMetaObject *);
- void invalidate(QQmlEngine *, const QMetaObject *);
+ void update(const QMetaObject *);
+ void invalidate(const QMetaObject *);
+ // Used by qmlpuppet. Remove as soon Creator requires Qt 5.5.
+ void invalidate(void *, const QMetaObject *mo) { invalidate(mo); }
QQmlPropertyCache *copy();
- QQmlPropertyCache *copyAndAppend(QQmlEngine *, const QMetaObject *,
+ QQmlPropertyCache *copyAndAppend(const QMetaObject *,
QQmlPropertyData::Flag propertyFlags = QQmlPropertyData::NoFlags,
QQmlPropertyData::Flag methodFlags = QQmlPropertyData::NoFlags,
QQmlPropertyData::Flag signalFlags = QQmlPropertyData::NoFlags);
- QQmlPropertyCache *copyAndAppend(QQmlEngine *, const QMetaObject *, int revision,
+ QQmlPropertyCache *copyAndAppend(const QMetaObject *, int revision,
QQmlPropertyData::Flag propertyFlags = QQmlPropertyData::NoFlags,
QQmlPropertyData::Flag methodFlags = QQmlPropertyData::NoFlags,
QQmlPropertyData::Flag signalFlags = QQmlPropertyData::NoFlags);
- QQmlPropertyCache *copyAndReserve(QQmlEngine *, int propertyCount,
+ QQmlPropertyCache *copyAndReserve(int propertyCount,
int methodCount, int signalCount);
void appendProperty(const QString &,
quint32 flags, int coreIndex, int propType, int notifyIndex);
@@ -294,15 +303,10 @@ public:
inline QQmlPropertyData *overrideData(QQmlPropertyData *) const;
inline bool isAllowedInRevision(QQmlPropertyData *) const;
- inline QQmlEngine *qmlEngine() const;
- static QQmlPropertyData *property(QQmlEngine *, QObject *, const QString &,
+ static QQmlPropertyData *property(QJSEngine *, QObject *, const QString &,
QQmlContextData *, QQmlPropertyData &);
- static QQmlPropertyData *property(QQmlEngine *, QObject *, const QV4::String *,
+ static QQmlPropertyData *property(QJSEngine *, QObject *, const QV4::String *,
QQmlContextData *, QQmlPropertyData &);
- static int *methodParameterTypes(QObject *, int index, QVarLengthArray<int, 9> &dummy,
- QByteArray *unknownTypeError);
- static int methodReturnType(QObject *, const QQmlPropertyData &data,
- QByteArray *unknownTypeError);
//see QMetaObjectPrivate::originalClone
int originalClone(int index);
@@ -310,7 +314,7 @@ public:
QList<QByteArray> signalParameterNames(int index) const;
QString signalParameterStringForJS(int index, QString *errorString = 0);
- static QString signalParameterStringForJS(QQmlEngine *engine, const QList<QByteArray> &parameterNameList, QString *errorString = 0);
+ static QString signalParameterStringForJS(QV4::ExecutionEngine *engine, const QList<QByteArray> &parameterNameList, QString *errorString = 0);
const char *className() const;
@@ -334,10 +338,11 @@ private:
friend class QQmlCompiler;
friend class QQmlPropertyCacheCreator;
friend class QQmlComponentAndAliasResolver;
+ friend class QQmlMetaObject;
inline QQmlPropertyCache *copy(int reserve);
- void append(QQmlEngine *, const QMetaObject *, int revision,
+ void append(const QMetaObject *, int revision,
QQmlPropertyData::Flag propertyFlags = QQmlPropertyData::NoFlags,
QQmlPropertyData::Flag methodFlags = QQmlPropertyData::NoFlags,
QQmlPropertyData::Flag signalFlags = QQmlPropertyData::NoFlags);
@@ -356,7 +361,7 @@ private:
QQmlPropertyData *ensureResolved(QQmlPropertyData*) const;
void resolve(QQmlPropertyData *) const;
- void updateRecur(QQmlEngine *, const QMetaObject *);
+ void updateRecur(const QMetaObject *);
template<typename K>
QQmlPropertyData *findNamedProperty(const K &key)
@@ -372,7 +377,7 @@ private:
_hasPropertyOverrides |= isOverride;
}
- QQmlEngine *engine;
+ QJSEngine *engine;
QQmlPropertyCache *_parent;
int propertyIndexCacheStart;
@@ -422,12 +427,37 @@ public:
QQmlPropertyCache *propertyCache(QQmlEnginePrivate *) const;
+ int methodReturnType(const QQmlPropertyData &data, QByteArray *unknownTypeError) const;
+ int *methodParameterTypes(int index, QVarLengthArray<int, 9> &dummy, QByteArray *unknownTypeError) const;
+
static bool canConvert(const QQmlMetaObject &from, const QQmlMetaObject &to);
-private:
+ // static_metacall (on Gadgets) doesn't call the base implementation and therefore
+ // we need a helper to find the correct meta object and property/method index.
+ static void resolveGadgetMethodOrPropertyIndex(QMetaObject::Call type, const QMetaObject **metaObject, int *index);
+
+protected:
QBiPointer<QQmlPropertyCache, const QMetaObject> _m;
};
+class QQmlObjectOrGadget: public QQmlMetaObject
+{
+public:
+ QQmlObjectOrGadget(QObject *obj)
+ : QQmlMetaObject(obj),
+ ptr(obj)
+ {}
+ QQmlObjectOrGadget(QQmlPropertyCache *propertyCache, void *gadget)
+ : QQmlMetaObject(propertyCache)
+ , ptr(gadget)
+ {}
+
+ void metacall(QMetaObject::Call type, int index, void **argv) const;
+
+private:
+ QBiPointer<QObject, void> ptr;
+};
+
QQmlPropertyData::QQmlPropertyData()
{
propType = 0;
@@ -464,7 +494,7 @@ int QQmlPropertyRawData::getValueTypeCoreIndex() const
int QQmlPropertyRawData::encodedIndex() const
{
- return isValueTypeVirtual()?(coreIndex | (valueTypeCoreIndex << 16)):coreIndex;
+ return isValueTypeVirtual()?QQmlPropertyData::encodeValueTypePropertyIndex(coreIndex, valueTypeCoreIndex):coreIndex;
}
QQmlPropertyData *
@@ -485,11 +515,6 @@ bool QQmlPropertyCache::isAllowedInRevision(QQmlPropertyData *data) const
(allowedRevisionCache[data->metaObjectOffset] >= data->revision);
}
-QQmlEngine *QQmlPropertyCache::qmlEngine() const
-{
- return engine;
-}
-
int QQmlPropertyCache::propertyCount() const
{
return propertyIndexCacheStart + propertyIndexCache.count();
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index 1b222fe1a3..2a000e34e1 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -79,8 +79,8 @@
#ifdef DATABLOB_DEBUG
-#define ASSERT_MAINTHREAD() do { if(m_thread->isThisThread()) qFatal("QQmlDataLoader: Caller not in main thread"); } while(false)
-#define ASSERT_LOADTHREAD() do { if(!m_thread->isThisThread()) qFatal("QQmlDataLoader: Caller not in load thread"); } while(false)
+#define ASSERT_MAINTHREAD() do { if (m_thread->isThisThread()) qFatal("QQmlTypeLoader: Caller not in main thread"); } while (false)
+#define ASSERT_LOADTHREAD() do { if (!m_thread->isThisThread()) qFatal("QQmlTypeLoader: Caller not in load thread"); } while (false)
#define ASSERT_CALLBACK() do { if(!m_manager || !m_manager->m_thread->isThisThread()) qFatal("QQmlDataBlob: An API call was made outside a callback"); } while(false)
#else
@@ -108,14 +108,14 @@ namespace {
// This is a lame object that we need to ensure that slots connected to
// QNetworkReply get called in the correct thread (the loader thread).
-// As QQmlDataLoader lives in the main thread, and we can't use
+// As QQmlTypeLoader lives in the main thread, and we can't use
// Qt::DirectConnection connections from a QNetworkReply (because then
// sender() wont work), we need to insert this object in the middle.
-class QQmlDataLoaderNetworkReplyProxy : public QObject
+class QQmlTypeLoaderNetworkReplyProxy : public QObject
{
Q_OBJECT
public:
- QQmlDataLoaderNetworkReplyProxy(QQmlDataLoader *l);
+ QQmlTypeLoaderNetworkReplyProxy(QQmlTypeLoader *l);
public slots:
void finished();
@@ -123,17 +123,17 @@ public slots:
void manualFinished(QNetworkReply*);
private:
- QQmlDataLoader *l;
+ QQmlTypeLoader *l;
};
-class QQmlDataLoaderThread : public QQmlThread
+class QQmlTypeLoaderThread : public QQmlThread
{
- typedef QQmlDataLoaderThread This;
+ typedef QQmlTypeLoaderThread This;
public:
- QQmlDataLoaderThread(QQmlDataLoader *loader);
+ QQmlTypeLoaderThread(QQmlTypeLoader *loader);
QNetworkAccessManager *networkAccessManager() const;
- QQmlDataLoaderNetworkReplyProxy *networkReplyProxy() const;
+ QQmlTypeLoaderNetworkReplyProxy *networkReplyProxy() const;
void load(QQmlDataBlob *b);
void loadAsync(QQmlDataBlob *b);
@@ -156,18 +156,18 @@ private:
void callDownloadProgressChangedMain(QQmlDataBlob *b, qreal p);
void initializeEngineMain(QQmlExtensionInterface *iface, const char *uri);
- QQmlDataLoader *m_loader;
+ QQmlTypeLoader *m_loader;
mutable QNetworkAccessManager *m_networkAccessManager;
- mutable QQmlDataLoaderNetworkReplyProxy *m_networkReplyProxy;
+ mutable QQmlTypeLoaderNetworkReplyProxy *m_networkReplyProxy;
};
-QQmlDataLoaderNetworkReplyProxy::QQmlDataLoaderNetworkReplyProxy(QQmlDataLoader *l)
+QQmlTypeLoaderNetworkReplyProxy::QQmlTypeLoaderNetworkReplyProxy(QQmlTypeLoader *l)
: l(l)
{
}
-void QQmlDataLoaderNetworkReplyProxy::finished()
+void QQmlTypeLoaderNetworkReplyProxy::finished()
{
Q_ASSERT(sender());
Q_ASSERT(qobject_cast<QNetworkReply *>(sender()));
@@ -175,7 +175,7 @@ void QQmlDataLoaderNetworkReplyProxy::finished()
l->networkReplyFinished(reply);
}
-void QQmlDataLoaderNetworkReplyProxy::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
+void QQmlTypeLoaderNetworkReplyProxy::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
{
Q_ASSERT(sender());
Q_ASSERT(qobject_cast<QNetworkReply *>(sender()));
@@ -184,7 +184,7 @@ void QQmlDataLoaderNetworkReplyProxy::downloadProgress(qint64 bytesReceived, qin
}
// This function is for when you want to shortcut the signals and call directly
-void QQmlDataLoaderNetworkReplyProxy::manualFinished(QNetworkReply *reply)
+void QQmlTypeLoaderNetworkReplyProxy::manualFinished(QNetworkReply *reply)
{
qint64 replySize = reply->size();
l->networkReplyProgress(reply, replySize, replySize);
@@ -194,12 +194,12 @@ void QQmlDataLoaderNetworkReplyProxy::manualFinished(QNetworkReply *reply)
/*!
\class QQmlDataBlob
-\brief The QQmlDataBlob encapsulates a data request that can be issued to a QQmlDataLoader.
+\brief The QQmlDataBlob encapsulates a data request that can be issued to a QQmlTypeLoader.
\internal
-QQmlDataBlob's are loaded by a QQmlDataLoader. The user creates the QQmlDataBlob
-and then calls QQmlDataLoader::load() or QQmlDataLoader::loadWithStaticData() to load it.
-The QQmlDataLoader invokes callbacks on the QQmlDataBlob as data becomes available.
+QQmlDataBlob's are loaded by a QQmlTypeLoader. The user creates the QQmlDataBlob
+and then calls QQmlTypeLoader::load() or QQmlTypeLoader::loadWithStaticData() to load it.
+The QQmlTypeLoader invokes callbacks on the QQmlDataBlob as data becomes available.
*/
/*!
@@ -208,7 +208,7 @@ The QQmlDataLoader invokes callbacks on the QQmlDataBlob as data becomes availab
This enum describes the status of the data blob.
\list
-\li Null The blob has not yet been loaded by a QQmlDataLoader
+\li Null The blob has not yet been loaded by a QQmlTypeLoader
\li Loading The blob is loading network data. The QQmlDataBlob::setData() callback has not yet been
invoked or has not yet returned.
\li WaitingForDependencies The blob is waiting for dependencies to be done before continueing. This status
@@ -252,7 +252,7 @@ QQmlDataBlob::~QQmlDataBlob()
Sets the manager, and does stuff like selection which needs access to the manager.
Must be called before loading can occur.
*/
-void QQmlDataBlob::startLoading(QQmlDataLoader *manager)
+void QQmlDataBlob::startLoading(QQmlTypeLoader *manager)
{
Q_ASSERT(status() == QQmlDataBlob::Null);
Q_ASSERT(m_manager == 0);
@@ -725,86 +725,86 @@ void QQmlDataBlob::ThreadData::setProgress(quint8 v)
}
}
-QQmlDataLoaderThread::QQmlDataLoaderThread(QQmlDataLoader *loader)
+QQmlTypeLoaderThread::QQmlTypeLoaderThread(QQmlTypeLoader *loader)
: m_loader(loader), m_networkAccessManager(0), m_networkReplyProxy(0)
{
// Do that after initializing all the members.
startup();
}
-QNetworkAccessManager *QQmlDataLoaderThread::networkAccessManager() const
+QNetworkAccessManager *QQmlTypeLoaderThread::networkAccessManager() const
{
Q_ASSERT(isThisThread());
if (!m_networkAccessManager) {
m_networkAccessManager = QQmlEnginePrivate::get(m_loader->engine())->createNetworkAccessManager(0);
- m_networkReplyProxy = new QQmlDataLoaderNetworkReplyProxy(m_loader);
+ m_networkReplyProxy = new QQmlTypeLoaderNetworkReplyProxy(m_loader);
}
return m_networkAccessManager;
}
-QQmlDataLoaderNetworkReplyProxy *QQmlDataLoaderThread::networkReplyProxy() const
+QQmlTypeLoaderNetworkReplyProxy *QQmlTypeLoaderThread::networkReplyProxy() const
{
Q_ASSERT(isThisThread());
Q_ASSERT(m_networkReplyProxy); // Must call networkAccessManager() first
return m_networkReplyProxy;
}
-void QQmlDataLoaderThread::load(QQmlDataBlob *b)
+void QQmlTypeLoaderThread::load(QQmlDataBlob *b)
{
b->addref();
callMethodInThread(&This::loadThread, b);
}
-void QQmlDataLoaderThread::loadAsync(QQmlDataBlob *b)
+void QQmlTypeLoaderThread::loadAsync(QQmlDataBlob *b)
{
b->addref();
postMethodToThread(&This::loadThread, b);
}
-void QQmlDataLoaderThread::loadWithStaticData(QQmlDataBlob *b, const QByteArray &d)
+void QQmlTypeLoaderThread::loadWithStaticData(QQmlDataBlob *b, const QByteArray &d)
{
b->addref();
callMethodInThread(&This::loadWithStaticDataThread, b, d);
}
-void QQmlDataLoaderThread::loadWithStaticDataAsync(QQmlDataBlob *b, const QByteArray &d)
+void QQmlTypeLoaderThread::loadWithStaticDataAsync(QQmlDataBlob *b, const QByteArray &d)
{
b->addref();
postMethodToThread(&This::loadWithStaticDataThread, b, d);
}
-void QQmlDataLoaderThread::loadWithCachedUnit(QQmlDataBlob *b, const QQmlPrivate::CachedQmlUnit *unit)
+void QQmlTypeLoaderThread::loadWithCachedUnit(QQmlDataBlob *b, const QQmlPrivate::CachedQmlUnit *unit)
{
b->addref();
callMethodInThread(&This::loadWithCachedUnitThread, b, unit);
}
-void QQmlDataLoaderThread::loadWithCachedUnitAsync(QQmlDataBlob *b, const QQmlPrivate::CachedQmlUnit *unit)
+void QQmlTypeLoaderThread::loadWithCachedUnitAsync(QQmlDataBlob *b, const QQmlPrivate::CachedQmlUnit *unit)
{
b->addref();
postMethodToThread(&This::loadWithCachedUnitThread, b, unit);
}
-void QQmlDataLoaderThread::callCompleted(QQmlDataBlob *b)
+void QQmlTypeLoaderThread::callCompleted(QQmlDataBlob *b)
{
b->addref();
postMethodToMain(&This::callCompletedMain, b);
}
-void QQmlDataLoaderThread::callDownloadProgressChanged(QQmlDataBlob *b, qreal p)
+void QQmlTypeLoaderThread::callDownloadProgressChanged(QQmlDataBlob *b, qreal p)
{
b->addref();
postMethodToMain(&This::callDownloadProgressChangedMain, b, p);
}
-void QQmlDataLoaderThread::initializeEngine(QQmlExtensionInterface *iface,
+void QQmlTypeLoaderThread::initializeEngine(QQmlExtensionInterface *iface,
const char *uri)
{
callMethodInMain(&This::initializeEngineMain, iface, uri);
}
-void QQmlDataLoaderThread::shutdownThread()
+void QQmlTypeLoaderThread::shutdownThread()
{
delete m_networkAccessManager;
m_networkAccessManager = 0;
@@ -812,45 +812,45 @@ void QQmlDataLoaderThread::shutdownThread()
m_networkReplyProxy = 0;
}
-void QQmlDataLoaderThread::loadThread(QQmlDataBlob *b)
+void QQmlTypeLoaderThread::loadThread(QQmlDataBlob *b)
{
m_loader->loadThread(b);
b->release();
}
-void QQmlDataLoaderThread::loadWithStaticDataThread(QQmlDataBlob *b, const QByteArray &d)
+void QQmlTypeLoaderThread::loadWithStaticDataThread(QQmlDataBlob *b, const QByteArray &d)
{
m_loader->loadWithStaticDataThread(b, d);
b->release();
}
-void QQmlDataLoaderThread::loadWithCachedUnitThread(QQmlDataBlob *b, const QQmlPrivate::CachedQmlUnit *unit)
+void QQmlTypeLoaderThread::loadWithCachedUnitThread(QQmlDataBlob *b, const QQmlPrivate::CachedQmlUnit *unit)
{
m_loader->loadWithCachedUnitThread(b, unit);
b->release();
}
-void QQmlDataLoaderThread::callCompletedMain(QQmlDataBlob *b)
+void QQmlTypeLoaderThread::callCompletedMain(QQmlDataBlob *b)
{
QML_MEMORY_SCOPE_URL(b->url());
#ifdef DATABLOB_DEBUG
- qWarning("QQmlDataLoaderThread: %s completed() callback", qPrintable(b->url().toString()));
+ qWarning("QQmlTypeLoaderThread: %s completed() callback", qPrintable(b->url().toString()));
#endif
b->completed();
b->release();
}
-void QQmlDataLoaderThread::callDownloadProgressChangedMain(QQmlDataBlob *b, qreal p)
+void QQmlTypeLoaderThread::callDownloadProgressChangedMain(QQmlDataBlob *b, qreal p)
{
#ifdef DATABLOB_DEBUG
- qWarning("QQmlDataLoaderThread: %s downloadProgressChanged(%f) callback",
+ qWarning("QQmlTypeLoaderThread: %s downloadProgressChanged(%f) callback",
qPrintable(b->url().toString()), p);
#endif
b->downloadProgressChanged(p);
b->release();
}
-void QQmlDataLoaderThread::initializeEngineMain(QQmlExtensionInterface *iface,
+void QQmlTypeLoaderThread::initializeEngineMain(QQmlExtensionInterface *iface,
const char *uri)
{
Q_ASSERT(m_loader->engine()->thread() == QThread::currentThread());
@@ -858,14 +858,14 @@ void QQmlDataLoaderThread::initializeEngineMain(QQmlExtensionInterface *iface,
}
/*!
-\class QQmlDataLoader
-\brief The QQmlDataLoader class abstracts loading files and their dependencies over the network.
+\class QQmlTypeLoader
+\brief The QQmlTypeLoader class abstracts loading files and their dependencies over the network.
\internal
-The QQmlDataLoader class is provided for the exclusive use of the QQmlTypeLoader class.
+The QQmlTypeLoader class is provided for the exclusive use of the QQmlTypeLoader class.
-Clients create QQmlDataBlob instances and submit them to the QQmlDataLoader class
-through the QQmlDataLoader::load() or QQmlDataLoader::loadWithStaticData() methods.
+Clients create QQmlDataBlob instances and submit them to the QQmlTypeLoader class
+through the QQmlTypeLoader::load() or QQmlTypeLoader::loadWithStaticData() methods.
The loader then fetches the data over the network or from the local file system in an efficient way.
QQmlDataBlob is an abstract class, so should always be specialized.
@@ -887,21 +887,7 @@ one of these three preconditions are met.
Thus QQmlDataBlob::done() will always eventually be called, even if the blob has an error set.
*/
-/*!
-Create a new QQmlDataLoader for \a engine.
-*/
-QQmlDataLoader::QQmlDataLoader(QQmlEngine *engine)
-: m_engine(engine), m_thread(new QQmlDataLoaderThread(this))
-{
-}
-
-/*! \internal */
-QQmlDataLoader::~QQmlDataLoader()
-{
- invalidate();
-}
-
-void QQmlDataLoader::invalidate()
+void QQmlTypeLoader::invalidate()
{
for (NetworkReplies::Iterator iter = m_networkReplies.begin(); iter != m_networkReplies.end(); ++iter)
(*iter)->release();
@@ -914,12 +900,12 @@ void QQmlDataLoader::invalidate()
}
}
-void QQmlDataLoader::lock()
+void QQmlTypeLoader::lock()
{
m_thread->lock();
}
-void QQmlDataLoader::unlock()
+void QQmlTypeLoader::unlock()
{
m_thread->unlock();
}
@@ -929,10 +915,10 @@ Load the provided \a blob from the network or filesystem.
The loader must be locked.
*/
-void QQmlDataLoader::load(QQmlDataBlob *blob, Mode mode)
+void QQmlTypeLoader::load(QQmlDataBlob *blob, Mode mode)
{
#ifdef DATABLOB_DEBUG
- qWarning("QQmlDataLoader::load(%s): %s thread", qPrintable(blob->m_url.toString()),
+ qWarning("QQmlTypeLoader::load(%s): %s thread", qPrintable(blob->m_url.toString()),
m_thread->isThisThread()?"Compile":"Engine");
#endif
blob->startLoading(this);
@@ -961,10 +947,10 @@ Load the provided \a blob with \a data. The blob's URL is not used by the data
The loader must be locked.
*/
-void QQmlDataLoader::loadWithStaticData(QQmlDataBlob *blob, const QByteArray &data, Mode mode)
+void QQmlTypeLoader::loadWithStaticData(QQmlDataBlob *blob, const QByteArray &data, Mode mode)
{
#ifdef DATABLOB_DEBUG
- qWarning("QQmlDataLoader::loadWithStaticData(%s, data): %s thread", qPrintable(blob->m_url.toString()),
+ qWarning("QQmlTypeLoader::loadWithStaticData(%s, data): %s thread", qPrintable(blob->m_url.toString()),
m_thread->isThisThread()?"Compile":"Engine");
#endif
@@ -989,10 +975,10 @@ void QQmlDataLoader::loadWithStaticData(QQmlDataBlob *blob, const QByteArray &da
}
}
-void QQmlDataLoader::loadWithCachedUnit(QQmlDataBlob *blob, const QQmlPrivate::CachedQmlUnit *unit, Mode mode)
+void QQmlTypeLoader::loadWithCachedUnit(QQmlDataBlob *blob, const QQmlPrivate::CachedQmlUnit *unit, Mode mode)
{
#ifdef DATABLOB_DEBUG
- qWarning("QQmlDataLoader::loadWithUnitFcatory(%s, data): %s thread", qPrintable(blob->m_url.toString()),
+ qWarning("QQmlTypeLoader::loadWithUnitFcatory(%s, data): %s thread", qPrintable(blob->m_url.toString()),
m_thread->isThisThread()?"Compile":"Engine");
#endif
@@ -1017,21 +1003,21 @@ void QQmlDataLoader::loadWithCachedUnit(QQmlDataBlob *blob, const QQmlPrivate::C
}
}
-void QQmlDataLoader::loadWithStaticDataThread(QQmlDataBlob *blob, const QByteArray &data)
+void QQmlTypeLoader::loadWithStaticDataThread(QQmlDataBlob *blob, const QByteArray &data)
{
ASSERT_LOADTHREAD();
setData(blob, data);
}
-void QQmlDataLoader::loadWithCachedUnitThread(QQmlDataBlob *blob, const QQmlPrivate::CachedQmlUnit *unit)
+void QQmlTypeLoader::loadWithCachedUnitThread(QQmlDataBlob *blob, const QQmlPrivate::CachedQmlUnit *unit)
{
ASSERT_LOADTHREAD();
setCachedUnit(blob, unit);
}
-void QQmlDataLoader::loadThread(QQmlDataBlob *blob)
+void QQmlTypeLoader::loadThread(QQmlDataBlob *blob)
{
ASSERT_LOADTHREAD();
@@ -1086,7 +1072,7 @@ void QQmlDataLoader::loadThread(QQmlDataBlob *blob)
} else {
QNetworkReply *reply = m_thread->networkAccessManager()->get(QNetworkRequest(blob->m_url));
- QQmlDataLoaderNetworkReplyProxy *nrp = m_thread->networkReplyProxy();
+ QQmlTypeLoaderNetworkReplyProxy *nrp = m_thread->networkReplyProxy();
blob->addref();
m_networkReplies.insert(reply, blob);
@@ -1108,7 +1094,7 @@ void QQmlDataLoader::loadThread(QQmlDataBlob *blob)
#define DATALOADER_MAXIMUM_REDIRECT_RECURSION 16
-void QQmlDataLoader::networkReplyFinished(QNetworkReply *reply)
+void QQmlTypeLoader::networkReplyFinished(QNetworkReply *reply)
{
Q_ASSERT(m_thread->isThisThread());
@@ -1147,7 +1133,7 @@ void QQmlDataLoader::networkReplyFinished(QNetworkReply *reply)
blob->release();
}
-void QQmlDataLoader::networkReplyProgress(QNetworkReply *reply,
+void QQmlTypeLoader::networkReplyProgress(QNetworkReply *reply,
qint64 bytesReceived, qint64 bytesTotal)
{
Q_ASSERT(m_thread->isThisThread());
@@ -1167,7 +1153,7 @@ void QQmlDataLoader::networkReplyProgress(QNetworkReply *reply,
/*!
Return the QQmlEngine associated with this loader
*/
-QQmlEngine *QQmlDataLoader::engine() const
+QQmlEngine *QQmlTypeLoader::engine() const
{
return m_engine;
}
@@ -1176,7 +1162,7 @@ QQmlEngine *QQmlDataLoader::engine() const
Call the initializeEngine() method on \a iface. Used by QQmlImportDatabase to ensure it
gets called in the correct thread.
*/
-void QQmlDataLoader::initializeEngine(QQmlExtensionInterface *iface,
+void QQmlTypeLoader::initializeEngine(QQmlExtensionInterface *iface,
const char *uri)
{
Q_ASSERT(m_thread->isThisThread() || engine()->thread() == QThread::currentThread());
@@ -1190,7 +1176,7 @@ void QQmlDataLoader::initializeEngine(QQmlExtensionInterface *iface,
}
-void QQmlDataLoader::setData(QQmlDataBlob *blob, const QByteArray &data)
+void QQmlTypeLoader::setData(QQmlDataBlob *blob, const QByteArray &data)
{
QML_MEMORY_SCOPE_URL(blob->url());
QQmlDataBlob::Data d;
@@ -1198,7 +1184,7 @@ void QQmlDataLoader::setData(QQmlDataBlob *blob, const QByteArray &data)
setData(blob, d);
}
-void QQmlDataLoader::setData(QQmlDataBlob *blob, QQmlFile *file)
+void QQmlTypeLoader::setData(QQmlDataBlob *blob, QQmlFile *file)
{
QML_MEMORY_SCOPE_URL(blob->url());
QQmlDataBlob::Data d;
@@ -1206,7 +1192,7 @@ void QQmlDataLoader::setData(QQmlDataBlob *blob, QQmlFile *file)
setData(blob, d);
}
-void QQmlDataLoader::setData(QQmlDataBlob *blob, const QQmlDataBlob::Data &d)
+void QQmlTypeLoader::setData(QQmlDataBlob *blob, const QQmlDataBlob::Data &d)
{
QML_MEMORY_SCOPE_URL(blob->url());
blob->m_inCallback = true;
@@ -1224,7 +1210,7 @@ void QQmlDataLoader::setData(QQmlDataBlob *blob, const QQmlDataBlob::Data &d)
blob->tryDone();
}
-void QQmlDataLoader::setCachedUnit(QQmlDataBlob *blob, const QQmlPrivate::CachedQmlUnit *unit)
+void QQmlTypeLoader::setCachedUnit(QQmlDataBlob *blob, const QQmlPrivate::CachedQmlUnit *unit)
{
QML_MEMORY_SCOPE_URL(blob->url());
blob->m_inCallback = true;
@@ -1242,7 +1228,7 @@ void QQmlDataLoader::setCachedUnit(QQmlDataBlob *blob, const QQmlPrivate::Cached
blob->tryDone();
}
-void QQmlDataLoader::shutdownThread()
+void QQmlTypeLoader::shutdownThread()
{
if (m_thread && !m_thread->isShutdown())
m_thread->shutdown();
@@ -1302,7 +1288,7 @@ bool QQmlTypeLoader::Blob::updateQmldir(QQmlQmldirData *data, const QV4::Compile
if (!importQualifier.isEmpty()) {
// Does this library contain any qualified scripts?
QUrl libraryUrl(qmldirUrl);
- const QmldirContent *qmldir = typeLoader()->qmldirContent(qmldirIdentifier, qmldirUrl);
+ const QmldirContent *qmldir = typeLoader()->qmldirContent(qmldirIdentifier);
foreach (const QQmlDirParser::Script &script, qmldir->scripts()) {
QUrl scriptUrl = libraryUrl.resolved(QUrl(script.fileName));
QQmlScriptBlob *blob = typeLoader()->getScript(scriptUrl);
@@ -1349,7 +1335,7 @@ bool QQmlTypeLoader::Blob::addImport(const QV4::CompiledData::Import *import, QL
if (!importQualifier.isEmpty()) {
// Does this library contain any qualified scripts?
QUrl libraryUrl(qmldirUrl);
- const QmldirContent *qmldir = typeLoader()->qmldirContent(qmldirFilePath, qmldirUrl);
+ const QmldirContent *qmldir = typeLoader()->qmldirContent(qmldirFilePath);
foreach (const QQmlDirParser::Script &script, qmldir->scripts()) {
QUrl scriptUrl = libraryUrl.resolved(QUrl(script.fileName));
QQmlScriptBlob *blob = typeLoader()->getScript(scriptUrl);
@@ -1582,7 +1568,7 @@ bool QQmlTypeLoader::QmldirContent::designerSupported() const
Constructs a new type loader that uses the given \a engine.
*/
QQmlTypeLoader::QQmlTypeLoader(QQmlEngine *engine)
-: QQmlDataLoader(engine)
+ : m_engine(engine), m_thread(new QQmlTypeLoaderThread(this))
{
}
@@ -1596,6 +1582,8 @@ QQmlTypeLoader::~QQmlTypeLoader()
shutdownThread();
clearCache();
+
+ invalidate();
}
QQmlImportDatabase *QQmlTypeLoader::importDatabase()
@@ -1621,9 +1609,9 @@ QQmlTypeData *QQmlTypeLoader::getType(const QUrl &url, Mode mode)
// TODO: if (compiledData == 0), is it safe to omit this insertion?
m_typeCache.insert(url, typeData);
if (const QQmlPrivate::CachedQmlUnit *cachedUnit = QQmlMetaType::findCachedCompilationUnit(url)) {
- QQmlDataLoader::loadWithCachedUnit(typeData, cachedUnit, mode);
+ QQmlTypeLoader::loadWithCachedUnit(typeData, cachedUnit, mode);
} else {
- QQmlDataLoader::load(typeData, mode);
+ QQmlTypeLoader::load(typeData, mode);
}
}
@@ -1641,7 +1629,7 @@ QQmlTypeData *QQmlTypeLoader::getType(const QByteArray &data, const QUrl &url)
LockHolder<QQmlTypeLoader> holder(this);
QQmlTypeData *typeData = new QQmlTypeData(url, this);
- QQmlDataLoader::loadWithStaticData(typeData, data);
+ QQmlTypeLoader::loadWithStaticData(typeData, data);
return typeData;
}
@@ -1664,9 +1652,9 @@ QQmlScriptBlob *QQmlTypeLoader::getScript(const QUrl &url)
m_scriptCache.insert(url, scriptBlob);
if (const QQmlPrivate::CachedQmlUnit *cachedUnit = QQmlMetaType::findCachedCompilationUnit(url)) {
- QQmlDataLoader::loadWithCachedUnit(scriptBlob, cachedUnit);
+ QQmlTypeLoader::loadWithCachedUnit(scriptBlob, cachedUnit);
} else {
- QQmlDataLoader::load(scriptBlob);
+ QQmlTypeLoader::load(scriptBlob);
}
}
@@ -1691,7 +1679,7 @@ QQmlQmldirData *QQmlTypeLoader::getQmldir(const QUrl &url)
if (!qmldirData) {
qmldirData = new QQmlQmldirData(url, this);
m_qmldirCache.insert(url, qmldirData);
- QQmlDataLoader::load(qmldirData);
+ QQmlTypeLoader::load(qmldirData);
}
qmldirData->addref();
@@ -1699,82 +1687,15 @@ QQmlQmldirData *QQmlTypeLoader::getQmldir(const QUrl &url)
return qmldirData;
}
+// #### Qt 6: Remove this function, it exists only for binary compatibility.
/*!
-Returns a QQmlBundleData for \a identifier.
-*/
-QQmlBundleData *QQmlTypeLoader::getBundle(const QString &identifier)
-{
- return getBundle(QHashedStringRef(identifier));
-}
-
-QQmlBundleData *QQmlTypeLoader::getBundle(const QHashedStringRef &identifier)
-{
- lock();
-
- QQmlBundleData *rv = 0;
- QQmlBundleData **bundle = m_bundleCache.value(identifier);
- if (bundle) {
- rv = *bundle;
- rv->addref();
- }
-
- unlock();
-
- return rv;
-}
-
-QQmlBundleData::QQmlBundleData(const QString &file)
-: QQmlBundle(file), fileName(file)
-{
-}
-
-// XXX check for errors etc.
-void QQmlTypeLoader::addBundle(const QString &identifier, const QString &fileName)
-{
- lock();
- addBundleNoLock(identifier, fileName);
- unlock();
-}
-
-void QQmlTypeLoader::addBundleNoLock(const QString &identifier, const QString &fileName)
-{
- QQmlBundleData *data = new QQmlBundleData(fileName);
- if (data->open()) {
-
- m_bundleCache.insert(identifier, data);
-
- } else {
- data->release();
- }
-}
-
-QString QQmlTypeLoader::bundleIdForQmldir(const QString &name, const QString &uriHint)
-{
- lock();
- QString *bundleId = m_qmldirBundleIdCache.value(name);
- if (!bundleId) {
- QString newBundleId = QLatin1String("qml.") + uriHint.toLower() /* XXX toLower()? */;
- if (m_qmldirBundleIdCache.contains(newBundleId))
- newBundleId += QString::number(m_qmldirBundleIdCache.count());
- m_qmldirBundleIdCache.insert(name, newBundleId);
- addBundleNoLock(newBundleId, name);
- unlock();
- return newBundleId;
- } else {
- unlock();
- return *bundleId;
- }
-}
-
+ * \internal
+ */
bool QQmlEngine::addNamedBundle(const QString &name, const QString &fileName)
{
- Q_D(QQmlEngine);
-
- if (name.startsWith(QLatin1String("qml."))) // reserved
- return false;
-
- d->typeLoader.addBundle(name, fileName);
- return true;
+ Q_UNUSED(name)
+ Q_UNUSED(fileName)
+ return false;
}
/*!
@@ -1893,20 +1814,20 @@ bool QQmlTypeLoader::directoryExists(const QString &path)
/*!
Return a QmldirContent for absoluteFilePath. The QmldirContent may be cached.
-\a filePath is either a bundle URL, or a local file path.
+\a filePath is a local file path.
It can also be a remote path for a remote directory import, but it will have been cached by now in this case.
*/
-const QQmlTypeLoader::QmldirContent *QQmlTypeLoader::qmldirContent(const QString &filePathIn, const QString &uriHint)
+const QQmlTypeLoader::QmldirContent *QQmlTypeLoader::qmldirContent(const QString &filePathIn)
{
- QUrl url(filePathIn); //May already contain bundle or http scheme
+ QUrl url(filePathIn); //May already contain http scheme
if (url.scheme() == QLatin1String("http") || url.scheme() == QLatin1String("https"))
return *(m_importQmlDirCache.value(filePathIn)); //Can't load the remote here, but should be cached
- else if (!QQmlFile::isBundle(filePathIn))
+ else
url = QUrl::fromLocalFile(filePathIn);
if (engine() && engine()->urlInterceptor())
url = engine()->urlInterceptor()->intercept(url, QQmlAbstractUrlInterceptor::QmldirFile);
- Q_ASSERT(url.scheme() == QLatin1String("file") || url.scheme() == QLatin1String("bundle"));
+ Q_ASSERT(url.scheme() == QLatin1String("file"));
QString filePath;
if (url.scheme() == QLatin1String("file"))
filePath = url.toLocalFile();
@@ -1922,45 +1843,14 @@ const QQmlTypeLoader::QmldirContent *QQmlTypeLoader::qmldirContent(const QString
#define NOT_READABLE_ERROR QString(QLatin1String("module \"$$URI$$\" definition \"%1\" not readable"))
#define CASE_MISMATCH_ERROR QString(QLatin1String("cannot load module \"$$URI$$\": File name case mismatch for \"%1\""))
- if (QQmlFile::isBundle(url.toString())) {
- QQmlFile file(engine(), url);
- if (file.isError()) {
- ERROR(NOT_READABLE_ERROR.arg(url.toString()));
- } else {
- QString content(QString::fromUtf8(file.data(), file.size()));
- qmldir->setContent(filePath, content);
- }
-
+ QFile file(filePath);
+ if (!QQml_isFileCaseCorrect(filePath)) {
+ ERROR(CASE_MISMATCH_ERROR.arg(filePath));
+ } else if (file.open(QFile::ReadOnly)) {
+ QByteArray data = file.readAll();
+ qmldir->setContent(filePath, QString::fromUtf8(data));
} else {
-
- QFile file(filePath);
- if (!QQml_isFileCaseCorrect(filePath)) {
- ERROR(CASE_MISMATCH_ERROR.arg(filePath));
- } else if (file.open(QFile::ReadOnly)) {
- QByteArray data = file.read(QQmlBundle::bundleHeaderLength());
-
- if (QQmlBundle::isBundleHeader(data.constData(), data.length())) {
- QString id = bundleIdForQmldir(filePath, uriHint);
-
- QString bundleUrl = QLatin1String("bundle://") + id + QLatin1Char('/');
-
- QUrl url(bundleUrl + QLatin1String("qmldir"));
-
- QQmlFile file(engine(), url);
- if (file.isError()) {
- ERROR(NOT_READABLE_ERROR.arg(filePath));
- } else {
- QString content(QString::fromUtf8(file.data(), file.size()));
- qmldir->setContent(QQmlFile::bundleFileName(bundleUrl, engine()), content);
- }
- } else {
- data += file.readAll();
- qmldir->setContent(filePath, QString::fromUtf8(data));
- }
- } else {
- ERROR(NOT_READABLE_ERROR.arg(filePath));
- }
-
+ ERROR(NOT_READABLE_ERROR.arg(filePath));
}
#undef ERROR
@@ -2220,10 +2110,6 @@ bool QQmlTypeData::loadImplicitImport()
void QQmlTypeData::dataReceived(const Data &data)
{
QString code = QString::fromUtf8(data.data(), data.size());
- QByteArray preparseData;
-
- if (data.isFile()) preparseData = data.asFile()->metaData(QLatin1String("qml:preparse"));
-
QQmlEngine *qmlEngine = typeLoader()->engine();
m_document.reset(new QmlIR::Document(QV8Engine::getV4(qmlEngine)->debugger != 0));
QmlIR::IRBuilder compiler(QV8Engine::get(qmlEngine)->illegalNames());
@@ -2576,7 +2462,6 @@ QV4::PersistentValue QQmlScriptData::scriptValueForContext(QQmlContextData *pare
Q_ASSERT(parentCtxt && parentCtxt->engine);
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(parentCtxt->engine);
- QV8Engine *v8engine = ep->v8engine();
QV4::ExecutionEngine *v4 = QV8Engine::getV4(parentCtxt->engine);
QV4::Scope scope(v4);
@@ -2619,7 +2504,7 @@ QV4::PersistentValue QQmlScriptData::scriptValueForContext(QQmlContextData *pare
QV4::ScopedObject scriptsArray(scope);
if (ctxt->importedScripts.isNullOrUndefined()) {
scriptsArray = v4->newArrayObject(scripts.count());
- ctxt->importedScripts = scriptsArray;
+ ctxt->importedScripts.set(v4, scriptsArray);
} else {
scriptsArray = ctxt->importedScripts;
}
@@ -2635,19 +2520,18 @@ QV4::PersistentValue QQmlScriptData::scriptValueForContext(QQmlContextData *pare
return QV4::PersistentValue();
}
- QV4::ScopedValue qmlglobal(scope, QV4::QmlContextWrapper::qmlScope(v8engine, ctxt, 0));
+ QV4::ScopedValue qmlglobal(scope, QV4::QmlContextWrapper::qmlScope(v4, ctxt, 0));
QV4::QmlContextWrapper::takeContextOwnership(qmlglobal);
- QV4::ExecutionContext *ctx = QV8Engine::getV4(v8engine)->currentContext();
- m_program->qml = qmlglobal;
+ m_program->qml.set(scope.engine, qmlglobal);
m_program->run();
if (scope.engine->hasException) {
- QQmlError error = QV4::ExecutionEngine::catchExceptionAsQmlError(ctx);
+ QQmlError error = scope.engine->catchExceptionAsQmlError();
if (error.isValid())
ep->warning(error);
}
- rv = qmlglobal;
+ rv.set(scope.engine, qmlglobal);
if (shared) {
m_value = rv;
m_loaded = true;
@@ -2689,33 +2573,34 @@ QQmlScriptData *QQmlScriptBlob::scriptData() const
return m_scriptData;
}
+struct EmptyCompilationUnit : public QV4::CompiledData::CompilationUnit
+{
+ virtual void linkBackendToEngine(QV4::ExecutionEngine *) {}
+};
+
void QQmlScriptBlob::dataReceived(const Data &data)
{
QString source = QString::fromUtf8(data.data(), data.size());
QV4::ExecutionEngine *v4 = QV8Engine::getV4(m_typeLoader->engine());
QmlIR::Document irUnit(v4->debugger != 0);
- QQmlJS::DiagnosticMessage metaDataError;
- irUnit.extractScriptMetaData(source, &metaDataError);
- if (!metaDataError.message.isEmpty()) {
- QQmlError e;
- e.setUrl(finalUrl());
- e.setLine(metaDataError.loc.startLine);
- e.setColumn(metaDataError.loc.startColumn);
- e.setDescription(metaDataError.message);
- setError(e);
- return;
- }
+ QmlIR::ScriptDirectivesCollector collector(&irUnit.jsParserEngine, &irUnit.jsGenerator);
QList<QQmlError> errors;
- QQmlRefPointer<QV4::CompiledData::CompilationUnit> unit = QV4::Script::precompile(&irUnit.jsModule, &irUnit.jsGenerator, v4, finalUrl(), source, &errors);
+ QQmlRefPointer<QV4::CompiledData::CompilationUnit> unit = QV4::Script::precompile(&irUnit.jsModule, &irUnit.jsGenerator, v4, finalUrl(), source, &errors, &collector);
// No need to addref on unit, it's initial refcount is 1
source.clear();
if (!errors.isEmpty()) {
setError(errors);
return;
}
+ if (!unit) {
+ unit.take(new EmptyCompilationUnit);
+ }
irUnit.javaScriptCompilationUnit = unit;
+ irUnit.imports = collector.imports;
+ if (collector.hasPragmaLibrary)
+ irUnit.unitFlags |= QV4::CompiledData::Unit::IsSharedLibrary;
QmlIR::QmlUnitGenerator qmlGenerator;
QV4::CompiledData::Unit *unitData = qmlGenerator.generate(irUnit);
diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h
index 3b5aa1ec7a..64e3937a74 100644
--- a/src/qml/qml/qqmltypeloader_p.h
+++ b/src/qml/qml/qqmltypeloader_p.h
@@ -57,7 +57,6 @@
#include <private/qqmlimport_p.h>
#include <private/qqmlcleanup_p.h>
#include <private/qqmldirparser_p.h>
-#include <private/qqmlbundle_p.h>
#include <private/qflagpointer_p.h>
#include <private/qqmlirbuilder_p.h>
@@ -73,7 +72,7 @@ class QQmlTypeLoader;
class QQmlCompiledData;
class QQmlComponentPrivate;
class QQmlTypeData;
-class QQmlDataLoader;
+class QQmlTypeLoader;
class QQmlExtensionInterface;
namespace QmlIR {
@@ -84,7 +83,7 @@ class Q_QML_PRIVATE_EXPORT QQmlDataBlob : public QQmlRefCount
{
public:
enum Status {
- Null, // Prior to QQmlDataLoader::load()
+ Null, // Prior to QQmlTypeLoader::load()
Loading, // Prior to data being received and dataReceived() being called
WaitingForDependencies, // While there are outstanding addDependency()s
Complete, // Finished
@@ -100,7 +99,7 @@ public:
QQmlDataBlob(const QUrl &, Type);
virtual ~QQmlDataBlob();
- void startLoading(QQmlDataLoader* manager);
+ void startLoading(QQmlTypeLoader* manager);
Type type() const;
@@ -132,7 +131,7 @@ public:
private:
friend class QQmlDataBlob;
- friend class QQmlDataLoader;
+ friend class QQmlTypeLoader;
inline Data();
Data(const Data &);
Data &operator=(const Data &);
@@ -158,8 +157,8 @@ protected:
virtual void downloadProgressChanged(qreal);
virtual void completed();
private:
- friend class QQmlDataLoader;
- friend class QQmlDataLoaderThread;
+ friend class QQmlTypeLoader;
+ friend class QQmlTypeLoaderThread;
void tryDone();
void cancelAllWaitingFor();
@@ -199,72 +198,20 @@ private:
QList<QQmlDataBlob *> m_waitingFor;
// Manager that is currently fetching data for me
- QQmlDataLoader *m_manager;
+ QQmlTypeLoader *m_manager;
int m_redirectCount:30;
bool m_inCallback:1;
bool m_isDone:1;
};
-class QQmlDataLoaderThread;
-class QQmlDataLoader
-{
-public:
- QQmlDataLoader(QQmlEngine *);
- ~QQmlDataLoader();
-
- void lock();
- void unlock();
-
- bool isConcurrent() const { return true; }
-
- enum Mode { PreferSynchronous, Asynchronous };
-
- void load(QQmlDataBlob *, Mode = PreferSynchronous);
- void loadWithStaticData(QQmlDataBlob *, const QByteArray &, Mode = PreferSynchronous);
- void loadWithCachedUnit(QQmlDataBlob *blob, const QQmlPrivate::CachedQmlUnit *unit, Mode mode = PreferSynchronous);
-
- QQmlEngine *engine() const;
- void initializeEngine(QQmlExtensionInterface *, const char *);
- void invalidate();
-
-protected:
- void shutdownThread();
-
-private:
- friend class QQmlDataBlob;
- friend class QQmlDataLoaderThread;
- friend class QQmlDataLoaderNetworkReplyProxy;
-
- void loadThread(QQmlDataBlob *);
- void loadWithStaticDataThread(QQmlDataBlob *, const QByteArray &);
- void loadWithCachedUnitThread(QQmlDataBlob *blob, const QQmlPrivate::CachedQmlUnit *unit);
- void networkReplyFinished(QNetworkReply *);
- void networkReplyProgress(QNetworkReply *, qint64, qint64);
-
- typedef QHash<QNetworkReply *, QQmlDataBlob *> NetworkReplies;
-
- void setData(QQmlDataBlob *, const QByteArray &);
- void setData(QQmlDataBlob *, QQmlFile *);
- void setData(QQmlDataBlob *, const QQmlDataBlob::Data &);
- void setCachedUnit(QQmlDataBlob *blob, const QQmlPrivate::CachedQmlUnit *unit);
-
- QQmlEngine *m_engine;
- QQmlDataLoaderThread *m_thread;
- NetworkReplies m_networkReplies;
-};
-
-class QQmlBundleData : public QQmlBundle,
- public QQmlRefCount
-{
-public:
- QQmlBundleData(const QString &);
- QString fileName;
-};
+class QQmlTypeLoaderThread;
-class Q_AUTOTEST_EXPORT QQmlTypeLoader : public QQmlDataLoader
+class Q_AUTOTEST_EXPORT QQmlTypeLoader
{
Q_DECLARE_TR_FUNCTIONS(QQmlTypeLoader)
public:
+ enum Mode { PreferSynchronous, Asynchronous };
+
class Q_QML_PRIVATE_EXPORT Blob : public QQmlDataBlob
{
public:
@@ -338,14 +285,10 @@ public:
QQmlScriptBlob *getScript(const QUrl &);
QQmlQmldirData *getQmldir(const QUrl &);
- QQmlBundleData *getBundle(const QString &);
- QQmlBundleData *getBundle(const QHashedStringRef &);
- void addBundle(const QString &, const QString &);
-
QString absoluteFilePath(const QString &path);
bool directoryExists(const QString &path);
- const QmldirContent *qmldirContent(const QString &filePath, const QString &uriHint);
+ const QmldirContent *qmldirContent(const QString &filePath);
void setQmldirContent(const QString &filePath, const QString &content);
void clearCache();
@@ -354,9 +297,36 @@ public:
bool isTypeLoaded(const QUrl &url) const;
bool isScriptLoaded(const QUrl &url) const;
+ void lock();
+ void unlock();
+
+ void load(QQmlDataBlob *, Mode = PreferSynchronous);
+ void loadWithStaticData(QQmlDataBlob *, const QByteArray &, Mode = PreferSynchronous);
+ void loadWithCachedUnit(QQmlDataBlob *blob, const QQmlPrivate::CachedQmlUnit *unit, Mode mode = PreferSynchronous);
+
+ QQmlEngine *engine() const;
+ void initializeEngine(QQmlExtensionInterface *, const char *);
+ void invalidate();
+
private:
- void addBundleNoLock(const QString &, const QString &);
- QString bundleIdForQmldir(const QString &qmldir, const QString &uriHint);
+ friend class QQmlDataBlob;
+ friend class QQmlTypeLoaderThread;
+ friend class QQmlTypeLoaderNetworkReplyProxy;
+
+ void shutdownThread();
+
+ void loadThread(QQmlDataBlob *);
+ void loadWithStaticDataThread(QQmlDataBlob *, const QByteArray &);
+ void loadWithCachedUnitThread(QQmlDataBlob *blob, const QQmlPrivate::CachedQmlUnit *unit);
+ void networkReplyFinished(QNetworkReply *);
+ void networkReplyProgress(QNetworkReply *, qint64, qint64);
+
+ typedef QHash<QNetworkReply *, QQmlDataBlob *> NetworkReplies;
+
+ void setData(QQmlDataBlob *, const QByteArray &);
+ void setData(QQmlDataBlob *, QQmlFile *);
+ void setData(QQmlDataBlob *, const QQmlDataBlob::Data &);
+ void setCachedUnit(QQmlDataBlob *blob, const QQmlPrivate::CachedQmlUnit *unit);
template<typename T>
struct TypedCallback
@@ -380,16 +350,15 @@ private:
typedef QStringHash<bool> StringSet;
typedef QStringHash<StringSet*> ImportDirCache;
typedef QStringHash<QmldirContent *> ImportQmlDirCache;
- typedef QStringHash<QQmlBundleData *> BundleCache;
- typedef QStringHash<QString> QmldirBundleIdCache;
+ QQmlEngine *m_engine;
+ QQmlTypeLoaderThread *m_thread;
+ NetworkReplies m_networkReplies;
TypeCache m_typeCache;
ScriptCache m_scriptCache;
QmldirCache m_qmldirCache;
ImportDirCache m_importDirCache;
ImportQmlDirCache m_importQmlDirCache;
- BundleCache m_bundleCache;
- QmldirBundleIdCache m_qmldirBundleIdCache;
};
class Q_AUTOTEST_EXPORT QQmlTypeData : public QQmlTypeLoader::Blob
diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp
index d8f282c030..44bb30bd37 100644
--- a/src/qml/qml/qqmltypewrapper.cpp
+++ b/src/qml/qml/qqmltypewrapper.cpp
@@ -48,15 +48,14 @@ using namespace QV4;
DEFINE_OBJECT_VTABLE(QmlTypeWrapper);
-QmlTypeWrapper::Data::Data(QV8Engine *engine)
- : Object::Data(QV8Engine::getV4(engine))
- , v8(engine)
+Heap::QmlTypeWrapper::QmlTypeWrapper(ExecutionEngine *engine)
+ : Heap::Object(engine)
, mode(IncludeEnums)
{
- setVTable(staticVTable());
+ setVTable(QV4::QmlTypeWrapper::staticVTable());
}
-QmlTypeWrapper::Data::~Data()
+Heap::QmlTypeWrapper::~QmlTypeWrapper()
{
if (typeNamespace)
typeNamespace->release();
@@ -72,7 +71,7 @@ QObject* QmlTypeWrapper::singletonObject() const
if (!isSingleton())
return 0;
- QQmlEngine *e = d()->v8->engine();
+ QQmlEngine *e = engine()->qmlEngine();
QQmlType::SingletonInstanceInfo *siinfo = d()->type->singletonInstanceInfo();
siinfo->init(e);
return siinfo->qobjectApi(e);
@@ -81,7 +80,7 @@ QObject* QmlTypeWrapper::singletonObject() const
QVariant QmlTypeWrapper::toVariant() const
{
if (d()->type && d()->type->isSingleton()) {
- QQmlEngine *e = d()->v8->engine();
+ QQmlEngine *e = engine()->qmlEngine();
QQmlType::SingletonInstanceInfo *siinfo = d()->type->singletonInstanceInfo();
siinfo->init(e); // note: this will also create QJSValue singleton which isn't strictly required.
QObject *qobjectSingleton = siinfo->qobjectApi(e);
@@ -96,27 +95,27 @@ QVariant QmlTypeWrapper::toVariant() const
// Returns a type wrapper for type t on o. This allows access of enums, and attached properties.
-ReturnedValue QmlTypeWrapper::create(QV8Engine *v8, QObject *o, QQmlType *t, TypeNameMode mode)
+ReturnedValue QmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o, QQmlType *t,
+ Heap::QmlTypeWrapper::TypeNameMode mode)
{
Q_ASSERT(t);
- ExecutionEngine *v4 = QV8Engine::getV4(v8);
- Scope scope(v4);
+ Scope scope(engine);
- Scoped<QmlTypeWrapper> w(scope, v4->memoryManager->alloc<QmlTypeWrapper>(v8));
+ Scoped<QmlTypeWrapper> w(scope, engine->memoryManager->alloc<QmlTypeWrapper>(engine));
w->d()->mode = mode; w->d()->object = o; w->d()->type = t;
return w.asReturnedValue();
}
// Returns a type wrapper for importNamespace (of t) on o. This allows nested resolution of a type in a
// namespace.
-ReturnedValue QmlTypeWrapper::create(QV8Engine *v8, QObject *o, QQmlTypeNameCache *t, const void *importNamespace, TypeNameMode mode)
+ReturnedValue QmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o, QQmlTypeNameCache *t, const void *importNamespace,
+ Heap::QmlTypeWrapper::TypeNameMode mode)
{
Q_ASSERT(t);
Q_ASSERT(importNamespace);
- ExecutionEngine *v4 = QV8Engine::getV4(v8);
- Scope scope(v4);
+ Scope scope(engine);
- Scoped<QmlTypeWrapper> w(scope, v4->memoryManager->alloc<QmlTypeWrapper>(v8));
+ Scoped<QmlTypeWrapper> w(scope, engine->memoryManager->alloc<QmlTypeWrapper>(engine));
w->d()->mode = mode; w->d()->object = o; w->d()->typeNamespace = t; w->d()->importNamespace = importNamespace;
t->addref();
return w.asReturnedValue();
@@ -135,8 +134,7 @@ ReturnedValue QmlTypeWrapper::get(Managed *m, String *name, bool *hasProperty)
if (hasProperty)
*hasProperty = true;
- QV8Engine *v8engine = w->d()->v8;
- QQmlContextData *context = v8engine->callingContext();
+ QQmlContextData *context = v4->v8Engine->callingContext();
QObject *object = w->d()->object;
@@ -145,7 +143,7 @@ ReturnedValue QmlTypeWrapper::get(Managed *m, String *name, bool *hasProperty)
// singleton types are handled differently to other types.
if (type->isSingleton()) {
- QQmlEngine *e = v8engine->engine();
+ QQmlEngine *e = v4->qmlEngine();
QQmlType::SingletonInstanceInfo *siinfo = type->singletonInstanceInfo();
siinfo->init(e);
@@ -153,7 +151,7 @@ ReturnedValue QmlTypeWrapper::get(Managed *m, String *name, bool *hasProperty)
if (qobjectSingleton) {
// check for enum value
if (name->startsWithUpper()) {
- if (w->d()->mode == IncludeEnums) {
+ if (w->d()->mode == Heap::QmlTypeWrapper::IncludeEnums) {
// ### Optimize
QByteArray enumName = name->toQString().toUtf8();
const QMetaObject *metaObject = qobjectSingleton->metaObject();
@@ -168,7 +166,7 @@ ReturnedValue QmlTypeWrapper::get(Managed *m, String *name, bool *hasProperty)
}
// check for property.
- return QV4::QObjectWrapper::getQmlProperty(v4->currentContext(), context, qobjectSingleton, name, QV4::QObjectWrapper::IgnoreRevision, hasProperty);
+ return QV4::QObjectWrapper::getQmlProperty(v4, context, qobjectSingleton, name, QV4::QObjectWrapper::IgnoreRevision, hasProperty);
} else if (!siinfo->scriptApi(e).isUndefined()) {
// NOTE: if used in a binding, changes will not trigger re-evaluation since non-NOTIFYable.
QV4::ScopedObject o(scope, QJSValuePrivate::get(siinfo->scriptApi(e))->getValue(v4));
@@ -191,7 +189,7 @@ ReturnedValue QmlTypeWrapper::get(Managed *m, String *name, bool *hasProperty)
} else if (w->d()->object) {
QObject *ao = qmlAttachedPropertiesObjectById(type->attachedPropertiesId(), object);
if (ao)
- return QV4::QObjectWrapper::getQmlProperty(v4->currentContext(), context, ao, name, QV4::QObjectWrapper::IgnoreRevision, hasProperty);
+ return QV4::QObjectWrapper::getQmlProperty(v4, context, ao, name, QV4::QObjectWrapper::IgnoreRevision, hasProperty);
// Fall through to base implementation
}
@@ -206,14 +204,13 @@ ReturnedValue QmlTypeWrapper::get(Managed *m, String *name, bool *hasProperty)
QQmlTypeNameCache::Result r = w->d()->typeNamespace->query(name, w->d()->importNamespace);
if (r.isValid()) {
- QQmlContextData *context = v8engine->callingContext();
if (r.type) {
- return create(w->d()->v8, object, r.type, w->d()->mode);
+ return create(scope.engine, object, r.type, w->d()->mode);
} else if (r.scriptIndex != -1) {
QV4::ScopedObject scripts(scope, context->importedScripts);
return scripts->getIndexed(r.scriptIndex);
} else if (r.importNamespace) {
- return create(w->d()->v8, object, context->imports, r.importNamespace);
+ return create(scope.engine, object, context->imports, r.importNamespace);
}
return QV4::Encode::undefined();
@@ -241,28 +238,27 @@ void QmlTypeWrapper::put(Managed *m, String *name, const ValueRef value)
return;
QV4::Scope scope(v4);
- QV8Engine *v8engine = v4->v8Engine;
- QQmlContextData *context = v8engine->callingContext();
+ QQmlContextData *context = v4->v8Engine->callingContext();
QQmlType *type = w->d()->type;
if (type && !type->isSingleton() && w->d()->object) {
QObject *object = w->d()->object;
QObject *ao = qmlAttachedPropertiesObjectById(type->attachedPropertiesId(), object);
if (ao)
- QV4::QObjectWrapper::setQmlProperty(v4->currentContext(), context, ao, name, QV4::QObjectWrapper::IgnoreRevision, value);
+ QV4::QObjectWrapper::setQmlProperty(v4, context, ao, name, QV4::QObjectWrapper::IgnoreRevision, value);
} else if (type && type->isSingleton()) {
- QQmlEngine *e = v8engine->engine();
+ QQmlEngine *e = scope.engine->qmlEngine();
QQmlType::SingletonInstanceInfo *siinfo = type->singletonInstanceInfo();
siinfo->init(e);
QObject *qobjectSingleton = siinfo->qobjectApi(e);
if (qobjectSingleton) {
- QV4::QObjectWrapper::setQmlProperty(v4->currentContext(), context, qobjectSingleton, name, QV4::QObjectWrapper::IgnoreRevision, value);
+ QV4::QObjectWrapper::setQmlProperty(v4, context, qobjectSingleton, name, QV4::QObjectWrapper::IgnoreRevision, value);
} else if (!siinfo->scriptApi(e).isUndefined()) {
QV4::ScopedObject apiprivate(scope, QJSValuePrivate::get(siinfo->scriptApi(e))->value);
if (!apiprivate) {
QString error = QLatin1String("Cannot assign to read-only property \"") + name->toQString() + QLatin1Char('\"');
- v4->currentContext()->throwError(error);
+ v4->throwError(error);
return;
} else {
apiprivate->put(name, value);
@@ -279,11 +275,6 @@ PropertyAttributes QmlTypeWrapper::query(const Managed *m, String *name)
return hasProperty ? Attr_Data : Attr_Invalid;
}
-void QmlTypeWrapper::destroy(Managed *that)
-{
- static_cast<QmlTypeWrapper *>(that)->d()->~Data();
-}
-
bool QmlTypeWrapper::isEqualTo(Managed *a, Managed *b)
{
Q_ASSERT(a->as<QV4::QmlTypeWrapper>());
diff --git a/src/qml/qml/qqmltypewrapper_p.h b/src/qml/qml/qqmltypewrapper_p.h
index 995e88ecf4..321e0cf0ec 100644
--- a/src/qml/qml/qqmltypewrapper_p.h
+++ b/src/qml/qml/qqmltypewrapper_p.h
@@ -58,40 +58,45 @@ class QQmlTypeNameCache;
namespace QV4 {
-struct Q_QML_EXPORT QmlTypeWrapper : Object
-{
- enum TypeNameMode { IncludeEnums, ExcludeEnums };
-
- struct Data : Object::Data {
- Data(QV8Engine *engine);
- ~Data();
- QV8Engine *v8;
- TypeNameMode mode;
- QPointer<QObject> object;
-
- QQmlType *type;
- QQmlTypeNameCache *typeNamespace;
- const void *importNamespace;
+namespace Heap {
+
+struct QmlTypeWrapper : Object {
+ enum TypeNameMode {
+ IncludeEnums,
+ ExcludeEnums
};
- V4_OBJECT(Object)
-private:
-public:
+ QmlTypeWrapper(QV4::ExecutionEngine *engine);
+ ~QmlTypeWrapper();
+ TypeNameMode mode;
+ QPointer<QObject> object;
+
+ QQmlType *type;
+ QQmlTypeNameCache *typeNamespace;
+ const void *importNamespace;
+};
+
+}
+
+struct Q_QML_EXPORT QmlTypeWrapper : Object
+{
+ V4_OBJECT2(QmlTypeWrapper, Object)
+ V4_NEEDS_DESTROY
bool isSingleton() const;
QObject *singletonObject() const;
QVariant toVariant() const;
- static ReturnedValue create(QV8Engine *, QObject *, QQmlType *, TypeNameMode = IncludeEnums);
- static ReturnedValue create(QV8Engine *, QObject *, QQmlTypeNameCache *, const void *, TypeNameMode = IncludeEnums);
+ static ReturnedValue create(ExecutionEngine *, QObject *, QQmlType *,
+ Heap::QmlTypeWrapper::TypeNameMode = Heap::QmlTypeWrapper::IncludeEnums);
+ static ReturnedValue create(ExecutionEngine *, QObject *, QQmlTypeNameCache *, const void *,
+ Heap::QmlTypeWrapper::TypeNameMode = Heap::QmlTypeWrapper::IncludeEnums);
static ReturnedValue get(Managed *m, String *name, bool *hasProperty);
static void put(Managed *m, String *name, const ValueRef value);
static PropertyAttributes query(const Managed *, String *name);
- static void destroy(Managed *that);
-
static bool isEqualTo(Managed *that, Managed *o);
};
diff --git a/src/qml/qml/qqmlvaluetype.cpp b/src/qml/qml/qqmlvaluetype.cpp
index f73b50ad46..7f0e3a3a61 100644
--- a/src/qml/qml/qqmlvaluetype.cpp
+++ b/src/qml/qml/qqmlvaluetype.cpp
@@ -36,6 +36,7 @@
#include <private/qqmlglobal_p.h>
#include <QtCore/qdebug.h>
+#include <private/qmetaobjectbuilder_p.h>
QT_BEGIN_NAMESPACE
@@ -48,7 +49,7 @@ struct QQmlValueTypeFactoryImpl
bool isValueType(int idx);
- QQmlValueType *createValueType(int);
+ const QMetaObject *metaObjectForMetaType(int);
QQmlValueType *valueType(int);
QQmlValueType *valueTypes[QVariant::UserType];
@@ -83,39 +84,33 @@ bool QQmlValueTypeFactoryImpl::isValueType(int idx)
return false;
}
-QQmlValueType *QQmlValueTypeFactoryImpl::createValueType(int t)
+const QMetaObject *QQmlValueTypeFactoryImpl::metaObjectForMetaType(int t)
{
- QQmlValueType *rv = 0;
-
switch (t) {
case QVariant::Point:
- rv = new QQmlPointValueType;
- break;
+ return &QQmlPointValueType::staticMetaObject;
case QVariant::PointF:
- rv = new QQmlPointFValueType;
- break;
+ return &QQmlPointFValueType::staticMetaObject;
case QVariant::Size:
- rv = new QQmlSizeValueType;
- break;
+ return &QQmlSizeValueType::staticMetaObject;
case QVariant::SizeF:
- rv = new QQmlSizeFValueType;
- break;
+ return &QQmlSizeFValueType::staticMetaObject;
case QVariant::Rect:
- rv = new QQmlRectValueType;
- break;
+ return &QQmlRectValueType::staticMetaObject;
case QVariant::RectF:
- rv = new QQmlRectFValueType;
- break;
+ return &QQmlRectFValueType::staticMetaObject;
case QVariant::EasingCurve:
- rv = new QQmlEasingValueType;
- break;
+ return &QQmlEasingValueType::staticMetaObject;
default:
- rv = QQml_valueTypeProvider()->createValueType(t);
+ if (const QMetaObject *mo = QQml_valueTypeProvider()->metaObjectForMetaType(t))
+ return mo;
break;
}
- Q_ASSERT(!rv || rv->metaObject()->propertyCount() < 32);
- return rv;
+ QMetaType metaType(t);
+ if (metaType.flags() & QMetaType::IsGadget)
+ return metaType.metaObject();
+ return 0;
}
QQmlValueType *QQmlValueTypeFactoryImpl::valueType(int idx)
@@ -126,7 +121,10 @@ QQmlValueType *QQmlValueTypeFactoryImpl::valueType(int idx)
QHash<int, QQmlValueType *>::iterator it = userTypes.find(idx);
if (it == userTypes.end()) {
- it = userTypes.insert(idx, createValueType(idx));
+ QQmlValueType *vt = 0;
+ if (const QMetaObject *mo = metaObjectForMetaType(idx))
+ vt = new QQmlValueType(idx, mo);
+ it = userTypes.insert(idx, vt);
}
mutex.unlock();
@@ -139,7 +137,8 @@ QQmlValueType *QQmlValueTypeFactoryImpl::valueType(int idx)
// TODO: Investigate the performance/memory characteristics of
// removing the preallocated array
- if ((rv = createValueType(idx))) {
+ if (const QMetaObject *mo = metaObjectForMetaType(idx)) {
+ rv = new QQmlValueType(idx, mo);
valueTypes[idx] = rv;
}
}
@@ -161,20 +160,81 @@ QQmlValueType *QQmlValueTypeFactory::valueType(int idx)
return factoryImpl()->valueType(idx);
}
+const QMetaObject *QQmlValueTypeFactory::metaObjectForMetaType(int type)
+{
+ return factoryImpl()->metaObjectForMetaType(type);
+}
+
void QQmlValueTypeFactory::registerValueTypes(const char *uri, int versionMajor, int versionMinor)
{
qmlRegisterValueTypeEnums<QQmlEasingValueType>(uri, versionMajor, versionMinor, "Easing");
}
+QQmlValueType::QQmlValueType(int typeId, const QMetaObject *gadgetMetaObject)
+ : typeId(typeId)
+ , gadgetPtr(QMetaType::create(typeId))
+{
+ QObjectPrivate *op = QObjectPrivate::get(this);
+ Q_ASSERT(!op->metaObject);
+ op->metaObject = this;
+
+ QMetaObjectBuilder builder(gadgetMetaObject);
+ _metaObject = builder.toMetaObject();
+
+ *static_cast<QMetaObject*>(this) = *_metaObject;
+}
+
+QQmlValueType::~QQmlValueType()
+{
+ QObjectPrivate *op = QObjectPrivate::get(this);
+ Q_ASSERT(op->metaObject == this);
+ op->metaObject = 0;
+ ::free((void*)_metaObject);
+ QMetaType::destroy(typeId, gadgetPtr);
+}
+
+void QQmlValueType::read(QObject *obj, int idx)
+{
+ void *a[] = { gadgetPtr, 0 };
+ QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a);
+}
+
+void QQmlValueType::write(QObject *obj, int idx, QQmlPropertyPrivate::WriteFlags flags)
+{
+ Q_ASSERT(gadgetPtr);
+ int status = -1;
+ void *a[] = { gadgetPtr, 0, &status, &flags };
+ QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a);
+}
+
+QVariant QQmlValueType::value()
+{
+ Q_ASSERT(gadgetPtr);
+ return QVariant(typeId, gadgetPtr);
+}
+
+void QQmlValueType::setValue(const QVariant &value)
+{
+ Q_ASSERT(typeId == value.userType());
+ QMetaType::destruct(typeId, gadgetPtr);
+ QMetaType::construct(typeId, gadgetPtr, value.constData());
+}
+
+QAbstractDynamicMetaObject *QQmlValueType::toDynamicMetaObject(QObject *)
+{
+ return this;
+}
-QQmlValueType::QQmlValueType(int userType, QObject *parent)
-: QObject(parent), m_userType(userType)
+void QQmlValueType::objectDestroyed(QObject *)
{
}
-QQmlPointFValueType::QQmlPointFValueType(QObject *parent)
- : QQmlValueTypeBase<QPointF>(QMetaType::QPointF, parent)
+int QQmlValueType::metaCall(QObject *, QMetaObject::Call type, int _id, void **argv)
{
+ const QMetaObject *mo = _metaObject;
+ QQmlMetaObject::resolveGadgetMethodOrPropertyIndex(type, &mo, &_id);
+ mo->d.static_metacall(reinterpret_cast<QObject*>(gadgetPtr), type, _id, argv);
+ return _id;
}
QString QQmlPointFValueType::toString() const
@@ -203,16 +263,6 @@ void QQmlPointFValueType::setY(qreal y)
}
-QQmlPointValueType::QQmlPointValueType(QObject *parent)
- : QQmlValueTypeBase<QPoint>(QMetaType::QPoint, parent)
-{
-}
-
-QString QQmlPointValueType::toString() const
-{
- return QString(QLatin1String("QPoint(%1, %2)")).arg(v.x()).arg(v.y());
-}
-
int QQmlPointValueType::x() const
{
return v.x();
@@ -234,11 +284,6 @@ void QQmlPointValueType::setY(int y)
}
-QQmlSizeFValueType::QQmlSizeFValueType(QObject *parent)
- : QQmlValueTypeBase<QSizeF>(QMetaType::QSizeF, parent)
-{
-}
-
QString QQmlSizeFValueType::toString() const
{
return QString(QLatin1String("QSizeF(%1, %2)")).arg(v.width()).arg(v.height());
@@ -265,16 +310,6 @@ void QQmlSizeFValueType::setHeight(qreal h)
}
-QQmlSizeValueType::QQmlSizeValueType(QObject *parent)
- : QQmlValueTypeBase<QSize>(QMetaType::QSize, parent)
-{
-}
-
-QString QQmlSizeValueType::toString() const
-{
- return QString(QLatin1String("QSize(%1, %2)")).arg(v.width()).arg(v.height());
-}
-
int QQmlSizeValueType::width() const
{
return v.width();
@@ -295,12 +330,6 @@ void QQmlSizeValueType::setHeight(int h)
v.setHeight(h);
}
-
-QQmlRectFValueType::QQmlRectFValueType(QObject *parent)
- : QQmlValueTypeBase<QRectF>(QMetaType::QRectF, parent)
-{
-}
-
QString QQmlRectFValueType::toString() const
{
return QString(QLatin1String("QRectF(%1, %2, %3, %4)")).arg(v.x()).arg(v.y()).arg(v.width()).arg(v.height());
@@ -346,17 +375,6 @@ void QQmlRectFValueType::setHeight(qreal h)
v.setHeight(h);
}
-
-QQmlRectValueType::QQmlRectValueType(QObject *parent)
- : QQmlValueTypeBase<QRect>(QMetaType::QRect, parent)
-{
-}
-
-QString QQmlRectValueType::toString() const
-{
- return QString(QLatin1String("QRect(%1, %2, %3, %4)")).arg(v.x()).arg(v.y()).arg(v.width()).arg(v.height());
-}
-
int QQmlRectValueType::x() const
{
return v.x();
@@ -398,16 +416,6 @@ void QQmlRectValueType::setHeight(int h)
}
-QQmlEasingValueType::QQmlEasingValueType(QObject *parent)
- : QQmlValueTypeBase<QEasingCurve>(QMetaType::QEasingCurve, parent)
-{
-}
-
-QString QQmlEasingValueType::toString() const
-{
- return QString(QLatin1String("QEasingCurve(%1, %2, %3, %4)")).arg(v.type()).arg(v.amplitude()).arg(v.overshoot()).arg(v.period());
-}
-
QQmlEasingValueType::Type QQmlEasingValueType::type() const
{
return (QQmlEasingValueType::Type)v.type();
diff --git a/src/qml/qml/qqmlvaluetype_p.h b/src/qml/qml/qqmlvaluetype_p.h
index 5a6bcdd003..5c411f0e57 100644
--- a/src/qml/qml/qqmlvaluetype_p.h
+++ b/src/qml/qml/qqmlvaluetype_p.h
@@ -57,97 +57,26 @@
QT_BEGIN_NAMESPACE
-class Q_QML_PRIVATE_EXPORT QQmlValueType : public QObject
+class Q_QML_PRIVATE_EXPORT QQmlValueType : public QObject, public QAbstractDynamicMetaObject
{
- Q_OBJECT
public:
- QQmlValueType(int userType, QObject *parent = 0);
- virtual void read(QObject *, int) = 0;
- virtual void readVariantValue(QObject *, int, QVariant *) = 0;
- virtual void write(QObject *, int, QQmlPropertyPrivate::WriteFlags flags) = 0;
- virtual void writeVariantValue(QObject *, int, QQmlPropertyPrivate::WriteFlags, QVariant *) = 0;
- virtual QVariant value() = 0;
- virtual void setValue(const QVariant &) = 0;
-
- virtual QString toString() const = 0;
- virtual bool isEqual(const QVariant &value) const = 0;
-
- virtual void onLoad() {}
-
- inline int userType() const
- {
- return m_userType;
- }
-
-protected:
- inline void readProperty(QObject *obj, int idx, void *p)
- {
- void *a[] = { p, 0 };
- QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a);
- onLoad();
- }
-
- inline void writeProperty(QObject *obj, int idx, QQmlPropertyPrivate::WriteFlags flags, void *p)
- {
- int status = -1;
- void *a[] = { p, 0, &status, &flags };
- QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a);
- }
+ QQmlValueType(int userType, const QMetaObject *metaObject);
+ ~QQmlValueType();
+ void read(QObject *, int);
+ void write(QObject *, int, QQmlPropertyPrivate::WriteFlags flags);
+ QVariant value();
+ void setValue(const QVariant &);
+
+ // ---- dynamic meta object data interface
+ virtual QAbstractDynamicMetaObject *toDynamicMetaObject(QObject *);
+ virtual void objectDestroyed(QObject *);
+ virtual int metaCall(QObject *obj, QMetaObject::Call type, int _id, void **argv);
+ // ----
private:
- int m_userType;
-};
-
-template <typename T>
-class QQmlValueTypeBase : public QQmlValueType
-{
-public:
- typedef T ValueType;
-
- QQmlValueTypeBase(int userType, QObject *parent)
- : QQmlValueType(userType, parent)
- {
- }
-
- virtual void read(QObject *obj, int idx)
- {
- readProperty(obj, idx, &v);
- }
-
- virtual void readVariantValue(QObject *obj, int idx, QVariant *into)
- {
- // important: must not change the userType of the variant
- readProperty(obj, idx, into);
- }
-
- virtual void write(QObject *obj, int idx, QQmlPropertyPrivate::WriteFlags flags)
- {
- writeProperty(obj, idx, flags, &v);
- }
-
- virtual void writeVariantValue(QObject *obj, int idx, QQmlPropertyPrivate::WriteFlags flags, QVariant *from)
- {
- writeProperty(obj, idx, flags, from);
- }
-
- virtual QVariant value()
- {
- return QVariant::fromValue(v);
- }
-
- virtual void setValue(const QVariant &value)
- {
- v = qvariant_cast<T>(value);
- onLoad();
- }
-
- virtual bool isEqual(const QVariant &other) const
- {
- return QVariant::fromValue(v) == other;
- }
-
-protected:
- ValueType v;
+ const QMetaObject *_metaObject;
+ int typeId;
+ void *gadgetPtr;
};
class Q_QML_PRIVATE_EXPORT QQmlValueTypeFactory
@@ -155,86 +84,75 @@ class Q_QML_PRIVATE_EXPORT QQmlValueTypeFactory
public:
static bool isValueType(int);
static QQmlValueType *valueType(int idx);
+ static const QMetaObject *metaObjectForMetaType(int type);
static void registerValueTypes(const char *uri, int versionMajor, int versionMinor);
};
-class Q_QML_PRIVATE_EXPORT QQmlPointFValueType : public QQmlValueTypeBase<QPointF>
+struct QQmlPointFValueType
{
+ QPointF v;
Q_PROPERTY(qreal x READ x WRITE setX FINAL)
Q_PROPERTY(qreal y READ y WRITE setY FINAL)
- Q_OBJECT
+ Q_GADGET
public:
- QQmlPointFValueType(QObject *parent = 0);
-
- virtual QString toString() const;
-
+ Q_INVOKABLE QString toString() const;
qreal x() const;
qreal y() const;
void setX(qreal);
void setY(qreal);
};
-class Q_QML_PRIVATE_EXPORT QQmlPointValueType : public QQmlValueTypeBase<QPoint>
+struct QQmlPointValueType
{
+ QPoint v;
Q_PROPERTY(int x READ x WRITE setX FINAL)
Q_PROPERTY(int y READ y WRITE setY FINAL)
- Q_OBJECT
+ Q_GADGET
public:
- QQmlPointValueType(QObject *parent = 0);
-
- virtual QString toString() const;
-
int x() const;
int y() const;
void setX(int);
void setY(int);
};
-class Q_QML_PRIVATE_EXPORT QQmlSizeFValueType : public QQmlValueTypeBase<QSizeF>
+struct QQmlSizeFValueType
{
+ QSizeF v;
Q_PROPERTY(qreal width READ width WRITE setWidth FINAL)
Q_PROPERTY(qreal height READ height WRITE setHeight FINAL)
- Q_OBJECT
+ Q_GADGET
public:
- QQmlSizeFValueType(QObject *parent = 0);
-
- virtual QString toString() const;
-
+ Q_INVOKABLE QString toString() const;
qreal width() const;
qreal height() const;
void setWidth(qreal);
void setHeight(qreal);
};
-class Q_QML_PRIVATE_EXPORT QQmlSizeValueType : public QQmlValueTypeBase<QSize>
+struct QQmlSizeValueType
{
+ QSize v;
Q_PROPERTY(int width READ width WRITE setWidth FINAL)
Q_PROPERTY(int height READ height WRITE setHeight FINAL)
- Q_OBJECT
+ Q_GADGET
public:
- QQmlSizeValueType(QObject *parent = 0);
-
- virtual QString toString() const;
-
int width() const;
int height() const;
void setWidth(int);
void setHeight(int);
};
-class Q_QML_PRIVATE_EXPORT QQmlRectFValueType : public QQmlValueTypeBase<QRectF>
+struct QQmlRectFValueType
{
+ QRectF v;
Q_PROPERTY(qreal x READ x WRITE setX FINAL)
Q_PROPERTY(qreal y READ y WRITE setY FINAL)
Q_PROPERTY(qreal width READ width WRITE setWidth FINAL)
Q_PROPERTY(qreal height READ height WRITE setHeight FINAL)
- Q_OBJECT
+ Q_GADGET
public:
- QQmlRectFValueType(QObject *parent = 0);
-
- virtual QString toString() const;
-
+ Q_INVOKABLE QString toString() const;
qreal x() const;
qreal y() const;
void setX(qreal);
@@ -246,18 +164,15 @@ public:
void setHeight(qreal);
};
-class Q_QML_PRIVATE_EXPORT QQmlRectValueType : public QQmlValueTypeBase<QRect>
+struct QQmlRectValueType
{
+ QRect v;
Q_PROPERTY(int x READ x WRITE setX FINAL)
Q_PROPERTY(int y READ y WRITE setY FINAL)
Q_PROPERTY(int width READ width WRITE setWidth FINAL)
Q_PROPERTY(int height READ height WRITE setHeight FINAL)
- Q_OBJECT
+ Q_GADGET
public:
- QQmlRectValueType(QObject *parent = 0);
-
- virtual QString toString() const;
-
int x() const;
int y() const;
void setX(int);
@@ -269,9 +184,10 @@ public:
void setHeight(int);
};
-class Q_QML_PRIVATE_EXPORT QQmlEasingValueType : public QQmlValueTypeBase<QEasingCurve>
+struct QQmlEasingValueType
{
- Q_OBJECT
+ QEasingCurve v;
+ Q_GADGET
Q_ENUMS(Type)
Q_PROPERTY(QQmlEasingValueType::Type type READ type WRITE setType FINAL)
@@ -307,10 +223,6 @@ public:
Bezier = QEasingCurve::BezierSpline
};
- QQmlEasingValueType(QObject *parent = 0);
-
- virtual QString toString() const;
-
Type type() const;
qreal amplitude() const;
qreal overshoot() const;
diff --git a/src/qml/qml/qqmlvaluetypeproxybinding.cpp b/src/qml/qml/qqmlvaluetypeproxybinding.cpp
index 9e8d9198ee..875a9382f2 100644
--- a/src/qml/qml/qqmlvaluetypeproxybinding.cpp
+++ b/src/qml/qml/qqmlvaluetypeproxybinding.cpp
@@ -123,7 +123,8 @@ void QQmlValueTypeProxyBinding::removeBindings(quint32 mask)
QQmlAbstractBinding *lastBinding = 0;
while (binding) {
- if (mask & (1 << (binding->propertyIndex() >> 16))) {
+ int valueTypeIndex = QQmlPropertyData::decodeValueTypePropertyIndex(binding->propertyIndex());
+ if (valueTypeIndex != -1 && (mask & (1 << valueTypeIndex))) {
QQmlAbstractBinding *remove = binding;
binding = remove->nextBinding();
diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp
index b0125b4c13..b72b89c11d 100644
--- a/src/qml/qml/qqmlvaluetypewrapper.cpp
+++ b/src/qml/qml/qqmlvaluetypewrapper.cpp
@@ -47,373 +47,389 @@
QT_BEGIN_NAMESPACE
-using namespace QV4;
-DEFINE_OBJECT_VTABLE(QmlValueTypeWrapper);
+DEFINE_OBJECT_VTABLE(QV4::QQmlValueTypeWrapper);
+
+namespace QV4 {
+namespace Heap {
-struct QmlValueTypeReference : public QmlValueTypeWrapper
+struct QQmlValueTypeReference : QQmlValueTypeWrapper
{
- struct Data : QmlValueTypeWrapper::Data
- {
- Data(QV8Engine *engine);
- QPointer<QObject> object;
- int property;
- };
- V4_OBJECT(QmlValueTypeWrapper)
+ QQmlValueTypeReference(ExecutionEngine *engine);
+ QPointer<QObject> object;
+ int property;
};
-DEFINE_OBJECT_VTABLE(QmlValueTypeReference);
+}
-struct QmlValueTypeCopy : public QmlValueTypeWrapper
+struct QQmlValueTypeReference : public QQmlValueTypeWrapper
{
- struct Data : QmlValueTypeWrapper::Data
- {
- Data(QV8Engine *engine);
- QVariant value;
- };
- V4_OBJECT(QmlValueTypeWrapper)
+ V4_OBJECT2(QQmlValueTypeReference, QQmlValueTypeWrapper)
+
+ static void destroy(Heap::Base *that);
+
+ bool readReferenceValue() const;
};
-DEFINE_OBJECT_VTABLE(QmlValueTypeCopy);
+}
+
+DEFINE_OBJECT_VTABLE(QV4::QQmlValueTypeReference);
+
+using namespace QV4;
+
+Heap::QQmlValueTypeWrapper::QQmlValueTypeWrapper(ExecutionEngine *engine)
+ : Heap::Object(engine)
+ , gadgetPtr(0)
+{
+ setVTable(QV4::QQmlValueTypeWrapper::staticVTable());
+}
-QmlValueTypeWrapper::Data::Data(QV8Engine *engine, ObjectType objectType)
- : Object::Data(QV8Engine::getV4(engine))
- , v8(engine)
- , objectType(objectType)
+Heap::QQmlValueTypeWrapper::~QQmlValueTypeWrapper()
{
- setVTable(staticVTable());
+ if (gadgetPtr)
+ QMetaType::destroy(metaType, gadgetPtr);
}
-QmlValueTypeReference::Data::Data(QV8Engine *engine)
- : QmlValueTypeWrapper::Data(engine, Reference)
+void Heap::QQmlValueTypeWrapper::setValue(const QVariant &value) const
{
+ Q_ASSERT(metaType == value.userType());
+ QMetaType::destruct(metaType, gadgetPtr);
+ QMetaType::construct(metaType, gadgetPtr, value.constData());
}
-QmlValueTypeCopy::Data::Data(QV8Engine *engine)
- : QmlValueTypeWrapper::Data(engine, Copy)
+QVariant Heap::QQmlValueTypeWrapper::toVariant() const
{
+ Q_ASSERT(gadgetPtr);
+ return QVariant(metaType, gadgetPtr);
}
-static bool readReferenceValue(const QmlValueTypeReference *reference)
+Heap::QQmlValueTypeReference::QQmlValueTypeReference(ExecutionEngine *engine)
+ : Heap::QQmlValueTypeWrapper(engine)
{
+ setVTable(QV4::QQmlValueTypeReference::staticVTable());
+}
+
+bool QQmlValueTypeReference::readReferenceValue() const
+{
+ if (!d()->object)
+ return false;
// A reference resource may be either a "true" reference (eg, to a QVector3D property)
// or a "variant" reference (eg, to a QVariant property which happens to contain a value-type).
- QMetaProperty writebackProperty = reference->d()->object->metaObject()->property(reference->d()->property);
+ QMetaProperty writebackProperty = d()->object->metaObject()->property(d()->property);
if (writebackProperty.userType() == QMetaType::QVariant) {
// variant-containing-value-type reference
QVariant variantReferenceValue;
- reference->d()->type->readVariantValue(reference->d()->object, reference->d()->property, &variantReferenceValue);
+
+ void *a[] = { &variantReferenceValue, 0 };
+ QMetaObject::metacall(d()->object, QMetaObject::ReadProperty, d()->property, a);
+
int variantReferenceType = variantReferenceValue.userType();
- if (variantReferenceType != reference->d()->type->userType()) {
+ if (variantReferenceType != d()->metaType) {
// This is a stale VariantReference. That is, the variant has been
// overwritten with a different type in the meantime.
// We need to modify this reference to the updated value type, if
// possible, or return false if it is not a value type.
if (QQmlValueTypeFactory::isValueType(variantReferenceType)) {
- reference->d()->type = QQmlValueTypeFactory::valueType(variantReferenceType);
- if (!reference->d()->type) {
+ QQmlPropertyCache *cache = 0;
+ if (const QMetaObject *mo = QQmlValueTypeFactory::metaObjectForMetaType(variantReferenceType))
+ cache = QJSEnginePrivate::get(engine())->cache(mo);
+ if (d()->gadgetPtr)
+ QMetaType::destroy(d()->metaType, d()->gadgetPtr);
+ d()->gadgetPtr = 0;
+ d()->propertyCache = cache;
+ d()->metaType = variantReferenceType;
+ if (cache) {
+ d()->gadgetPtr = QMetaType::create(d()->metaType);
+ } else {
return false;
}
} else {
return false;
}
}
- reference->d()->type->setValue(variantReferenceValue);
+ d()->setValue(variantReferenceValue);
} else {
// value-type reference
- reference->d()->type->read(reference->d()->object, reference->d()->property);
+ void *args[] = { d()->gadget(), 0 };
+ QMetaObject::metacall(d()->object, QMetaObject::ReadProperty, d()->property, args);
}
return true;
}
-void QmlValueTypeWrapper::initProto(ExecutionEngine *v4)
+void QQmlValueTypeWrapper::initProto(ExecutionEngine *v4)
{
if (v4->qmlExtensions()->valueTypeWrapperPrototype)
return;
Scope scope(v4);
- Scoped<Object> o(scope, v4->newObject());
+ ScopedObject o(scope, v4->newObject());
o->defineDefaultProperty(v4->id_toString, method_toString, 1);
- v4->qmlExtensions()->valueTypeWrapperPrototype = o.getPointer();
+ v4->qmlExtensions()->valueTypeWrapperPrototype = o->d();
}
-ReturnedValue QmlValueTypeWrapper::create(QV8Engine *v8, QObject *object, int property, QQmlValueType *type)
+ReturnedValue QQmlValueTypeWrapper::create(ExecutionEngine *engine, QObject *object, int property, const QMetaObject *metaObject, int typeId)
{
- ExecutionEngine *v4 = QV8Engine::getV4(v8);
- Scope scope(v4);
- initProto(v4);
-
- QmlValueTypeReference *r = v4->memoryManager->alloc<QmlValueTypeReference>(v8);
- r->d()->internalClass = r->d()->internalClass->changePrototype(v4->qmlExtensions()->valueTypeWrapperPrototype);
- r->d()->type = type; r->d()->object = object; r->d()->property = property;
+ Scope scope(engine);
+ initProto(engine);
+
+ Scoped<QQmlValueTypeReference> r(scope, engine->memoryManager->alloc<QQmlValueTypeReference>(engine));
+ ScopedObject proto(scope, engine->qmlExtensions()->valueTypeWrapperPrototype);
+ r->setPrototype(proto);
+ r->d()->object = object; r->d()->property = property;
+ r->d()->propertyCache = QJSEnginePrivate::get(engine)->cache(metaObject);
+ r->d()->metaType = typeId;
+ r->d()->gadgetPtr = QMetaType::create(r->d()->metaType);
return r->asReturnedValue();
}
-ReturnedValue QmlValueTypeWrapper::create(QV8Engine *v8, const QVariant &value, QQmlValueType *type)
+ReturnedValue QQmlValueTypeWrapper::create(ExecutionEngine *engine, const QVariant &value, const QMetaObject *metaObject, int typeId)
{
- ExecutionEngine *v4 = QV8Engine::getV4(v8);
- Scope scope(v4);
- initProto(v4);
-
- QmlValueTypeCopy *r = v4->memoryManager->alloc<QmlValueTypeCopy>(v8);
- r->d()->internalClass = r->d()->internalClass->changePrototype(v4->qmlExtensions()->valueTypeWrapperPrototype);
- r->d()->type = type; r->d()->value = value;
+ Scope scope(engine);
+ initProto(engine);
+
+ Scoped<QQmlValueTypeWrapper> r(scope, engine->memoryManager->alloc<QQmlValueTypeWrapper>(engine));
+ ScopedObject proto(scope, engine->qmlExtensions()->valueTypeWrapperPrototype);
+ r->setPrototype(proto);
+ r->d()->propertyCache = QJSEnginePrivate::get(engine)->cache(metaObject);
+ r->d()->metaType = typeId;
+ r->d()->gadgetPtr = QMetaType::create(r->d()->metaType);
+ r->d()->setValue(value);
return r->asReturnedValue();
}
-QVariant QmlValueTypeWrapper::toVariant() const
+QVariant QQmlValueTypeWrapper::toVariant() const
{
- if (d()->objectType == QmlValueTypeWrapper::Reference) {
- const QmlValueTypeReference *reference = static_cast<const QmlValueTypeReference *>(this);
-
- if (reference->d()->object && readReferenceValue(reference)) {
- return reference->d()->type->value();
- } else {
+ if (const QQmlValueTypeReference *ref = as<const QQmlValueTypeReference>())
+ if (!ref->readReferenceValue())
return QVariant();
- }
- } else {
- Q_ASSERT(d()->objectType == QmlValueTypeWrapper::Copy);
- return static_cast<const QmlValueTypeCopy *>(this)->d()->value;
- }
+ return d()->toVariant();
+}
+
+void QQmlValueTypeWrapper::toGadget(void *data) const
+{
+ int typeId = d()->metaType;
+ QMetaType::destruct(typeId, data);
+ QMetaType::construct(typeId, data, d()->gadget());
}
-void QmlValueTypeWrapper::destroy(Managed *that)
+void QQmlValueTypeWrapper::destroy(Heap::Base *that)
{
- Q_ASSERT(that->as<QmlValueTypeWrapper>());
- QmlValueTypeWrapper *w = static_cast<QmlValueTypeWrapper *>(that);
- if (w->d()->objectType == Reference)
- static_cast<QmlValueTypeReference *>(w)->d()->~Data();
- else
- static_cast<QmlValueTypeCopy *>(w)->d()->~Data();
+ Heap::QQmlValueTypeWrapper *w = static_cast<Heap::QQmlValueTypeWrapper *>(that);
+ w->Heap::QQmlValueTypeWrapper::~QQmlValueTypeWrapper();
}
-bool QmlValueTypeWrapper::isEqualTo(Managed *m, Managed *other)
+bool QQmlValueTypeWrapper::isEqualTo(Managed *m, Managed *other)
{
- Q_ASSERT(m && m->as<QmlValueTypeWrapper>() && other);
- QV4::QmlValueTypeWrapper *lv = static_cast<QmlValueTypeWrapper *>(m);
+ Q_ASSERT(m && m->as<QQmlValueTypeWrapper>() && other);
+ QV4::QQmlValueTypeWrapper *lv = static_cast<QQmlValueTypeWrapper *>(m);
if (QV4::VariantObject *rv = other->as<VariantObject>())
return lv->isEqual(rv->d()->data);
- if (QV4::QmlValueTypeWrapper *v = other->as<QmlValueTypeWrapper>())
+ if (QV4::QQmlValueTypeWrapper *v = other->as<QQmlValueTypeWrapper>())
return lv->isEqual(v->toVariant());
return false;
}
-PropertyAttributes QmlValueTypeWrapper::query(const Managed *m, String *name)
+PropertyAttributes QQmlValueTypeWrapper::query(const Managed *m, String *name)
{
- Q_ASSERT(m->as<const QmlValueTypeWrapper>());
- const QmlValueTypeWrapper *r = static_cast<const QmlValueTypeWrapper *>(m);
-
- QQmlPropertyData local;
- QQmlPropertyData *result = 0;
- {
- QQmlData *ddata = QQmlData::get(r->d()->type, false);
- if (ddata && ddata->propertyCache)
- result = ddata->propertyCache->property(name, 0, 0);
- else
- result = QQmlPropertyCache::property(r->d()->v8->engine(), r->d()->type, name, 0, local);
- }
+ Q_ASSERT(m->as<const QQmlValueTypeWrapper>());
+ const QQmlValueTypeWrapper *r = static_cast<const QQmlValueTypeWrapper *>(m);
+
+ QQmlPropertyData *result = r->d()->propertyCache->property(name, 0, 0);
return result ? Attr_Data : Attr_Invalid;
}
-bool QmlValueTypeWrapper::isEqual(const QVariant& value)
+bool QQmlValueTypeWrapper::isEqual(const QVariant& value)
{
- if (d()->objectType == QmlValueTypeWrapper::Reference) {
- QmlValueTypeReference *reference = static_cast<QmlValueTypeReference *>(this);
- if (reference->d()->object && readReferenceValue(reference)) {
- return reference->d()->type->isEqual(value);
- } else {
+ if (QQmlValueTypeReference *ref = as<QQmlValueTypeReference>())
+ if (!ref->readReferenceValue())
return false;
- }
- } else {
- Q_ASSERT(d()->objectType == QmlValueTypeWrapper::Copy);
- QmlValueTypeCopy *copy = static_cast<QmlValueTypeCopy *>(this);
- d()->type->setValue(copy->d()->value);
- if (d()->type->isEqual(value))
- return true;
- return (value == copy->d()->value);
- }
+ return (value == d()->toVariant());
}
-ReturnedValue QmlValueTypeWrapper::method_toString(CallContext *ctx)
+ReturnedValue QQmlValueTypeWrapper::method_toString(CallContext *ctx)
{
Object *o = ctx->d()->callData->thisObject.asObject();
if (!o)
- return ctx->throwTypeError();
- QmlValueTypeWrapper *w = o->as<QmlValueTypeWrapper>();
+ return ctx->engine()->throwTypeError();
+ QQmlValueTypeWrapper *w = o->as<QQmlValueTypeWrapper>();
if (!w)
- return ctx->throwTypeError();
-
- if (w->d()->objectType == QmlValueTypeWrapper::Reference) {
- QmlValueTypeReference *reference = static_cast<QmlValueTypeReference *>(w);
- if (reference->d()->object && readReferenceValue(reference)) {
- return w->d()->v8->toString(w->d()->type->toString());
- } else {
- return QV4::Encode::undefined();
- }
- } else {
- Q_ASSERT(w->d()->objectType == QmlValueTypeWrapper::Copy);
- QmlValueTypeCopy *copy = static_cast<QmlValueTypeCopy *>(w);
- w->d()->type->setValue(copy->d()->value);
- return w->d()->v8->toString(w->d()->type->toString());
+ return ctx->engine()->throwTypeError();
+
+ if (QQmlValueTypeReference *ref = w->as<QQmlValueTypeReference>())
+ if (!ref->readReferenceValue())
+ return Encode::undefined();
+
+ QString result = QString::fromUtf8(QMetaType::typeName(w->d()->metaType));
+ result += QLatin1Char('(');
+ const QMetaObject *mo = w->d()->propertyCache->metaObject();
+ const int propCount = mo->propertyCount();
+ for (int i = 0; i < propCount; ++i) {
+ QVariant value = mo->property(i).readOnGadget(w->d()->gadget());
+ result += value.toString();
+ if (i < propCount - 1)
+ result += QStringLiteral(", ");
}
+ result += QLatin1Char(')');
+ return Encode(ctx->engine()->newString(result));
}
-ReturnedValue QmlValueTypeWrapper::get(Managed *m, String *name, bool *hasProperty)
+ReturnedValue QQmlValueTypeWrapper::get(Managed *m, String *name, bool *hasProperty)
{
- Q_ASSERT(m->as<QmlValueTypeWrapper>());
- QmlValueTypeWrapper *r = static_cast<QmlValueTypeWrapper *>(m);
+ Q_ASSERT(m->as<QQmlValueTypeWrapper>());
+ QQmlValueTypeWrapper *r = static_cast<QQmlValueTypeWrapper *>(m);
QV4::ExecutionEngine *v4 = m->engine();
// Note: readReferenceValue() can change the reference->type.
- if (r->d()->objectType == QmlValueTypeWrapper::Reference) {
- QmlValueTypeReference *reference = static_cast<QmlValueTypeReference *>(r);
-
- if (!reference->d()->object || !readReferenceValue(reference))
+ if (QQmlValueTypeReference *reference = r->as<QQmlValueTypeReference>()) {
+ if (!reference->readReferenceValue())
return Primitive::undefinedValue().asReturnedValue();
-
- } else {
- Q_ASSERT(r->d()->objectType == QmlValueTypeWrapper::Copy);
-
- QmlValueTypeCopy *copy = static_cast<QmlValueTypeCopy *>(r);
-
- r->d()->type->setValue(copy->d()->value);
- }
-
- QQmlPropertyData local;
- QQmlPropertyData *result = 0;
- {
- QQmlData *ddata = QQmlData::get(r->d()->type, false);
- if (ddata && ddata->propertyCache)
- result = ddata->propertyCache->property(name, 0, 0);
- else
- result = QQmlPropertyCache::property(r->d()->v8->engine(), r->d()->type, name, 0, local);
}
+ QQmlPropertyData *result = r->d()->propertyCache->property(name, 0, 0);
if (!result)
return Object::get(m, name, hasProperty);
+ if (hasProperty)
+ *hasProperty = true;
+
if (result->isFunction()) {
// calling a Q_INVOKABLE function of a value type
- QQmlContextData *qmlContext = QV4::QmlContextWrapper::callingContext(v4);
- return QV4::QObjectWrapper::getQmlProperty(v4->currentContext(), qmlContext, r->d()->type, name, QV4::QObjectWrapper::IgnoreRevision);
+ Scope scope(v4);
+ ScopedContext c(scope, v4->rootContext());
+ return QV4::QObjectMethod::create(c, r, result->coreIndex);
}
#define VALUE_TYPE_LOAD(metatype, cpptype, constructor) \
if (result->propType == metatype) { \
cpptype v; \
void *args[] = { &v, 0 }; \
- r->d()->type->qt_metacall(QMetaObject::ReadProperty, result->coreIndex, args); \
- return constructor(v); \
+ metaObject->d.static_metacall(reinterpret_cast<QObject*>(gadget), QMetaObject::ReadProperty, index, args); \
+ return QV4::Encode(constructor(v)); \
}
+ const QMetaObject *metaObject = r->d()->propertyCache->metaObject();
+
+ int index = result->coreIndex;
+ QQmlMetaObject::resolveGadgetMethodOrPropertyIndex(QMetaObject::ReadProperty, &metaObject, &index);
+
+ void *gadget = r->d()->gadget();
+
// These four types are the most common used by the value type wrappers
- VALUE_TYPE_LOAD(QMetaType::QReal, qreal, QV4::Encode);
- VALUE_TYPE_LOAD(QMetaType::Int, int, QV4::Encode);
- VALUE_TYPE_LOAD(QMetaType::QString, QString, r->d()->v8->toString);
- VALUE_TYPE_LOAD(QMetaType::Bool, bool, QV4::Encode);
+ VALUE_TYPE_LOAD(QMetaType::QReal, qreal, qreal);
+ VALUE_TYPE_LOAD(QMetaType::Int, int, int);
+ VALUE_TYPE_LOAD(QMetaType::QString, QString, v4->newString);
+ VALUE_TYPE_LOAD(QMetaType::Bool, bool, bool);
QVariant v(result->propType, (void *)0);
void *args[] = { v.data(), 0 };
- r->d()->type->qt_metacall(QMetaObject::ReadProperty, result->coreIndex, args);
- return r->d()->v8->fromVariant(v);
+ metaObject->d.static_metacall(reinterpret_cast<QObject*>(gadget), QMetaObject::ReadProperty, index, args);
+ return v4->fromVariant(v);
#undef VALUE_TYPE_ACCESSOR
}
-void QmlValueTypeWrapper::put(Managed *m, String *name, const ValueRef value)
+void QQmlValueTypeWrapper::put(Managed *m, String *name, const ValueRef value)
{
- Q_ASSERT(m->as<QmlValueTypeWrapper>());
+ Q_ASSERT(m->as<QQmlValueTypeWrapper>());
ExecutionEngine *v4 = m->engine();
Scope scope(v4);
if (scope.hasException())
return;
- Scoped<QmlValueTypeWrapper> r(scope, static_cast<QmlValueTypeWrapper *>(m));
+ Scoped<QQmlValueTypeWrapper> r(scope, static_cast<QQmlValueTypeWrapper *>(m));
+ Scoped<QQmlValueTypeReference> reference(scope, m->d());
- QByteArray propName = name->toQString().toUtf8();
- if (r->d()->objectType == QmlValueTypeWrapper::Reference) {
- QmlValueTypeReference *reference = static_cast<QmlValueTypeReference *>(r.getPointer());
+ int writeBackPropertyType = -1;
+
+ if (reference) {
QMetaProperty writebackProperty = reference->d()->object->metaObject()->property(reference->d()->property);
- if (!reference->d()->object || !writebackProperty.isWritable() || !readReferenceValue(reference))
+ if (!writebackProperty.isWritable() || !reference->readReferenceValue())
return;
- // we lookup the index after readReferenceValue() since it can change the reference->type.
- int index = r->d()->type->metaObject()->indexOfProperty(propName.constData());
- if (index == -1)
+ writeBackPropertyType = writebackProperty.userType();
+ }
+
+ const QMetaObject *metaObject = r->d()->propertyCache->metaObject();
+ const QQmlPropertyData *pd = r->d()->propertyCache->property(name, 0, 0);
+ if (!pd)
+ return;
+ QMetaProperty property = metaObject->property(pd->coreIndex);
+ Q_ASSERT(property.isValid());
+
+ QQmlBinding *newBinding = 0;
+
+ QV4::ScopedFunctionObject f(scope, value);
+ if (reference && f) {
+ if (!f->isBinding()) {
+ // assigning a JS function to a non-var-property is not allowed.
+ QString error = QStringLiteral("Cannot assign JavaScript function to value-type property");
+ ScopedString e(scope, v4->newString(error));
+ v4->throwError(e);
return;
- QMetaProperty p = r->d()->type->metaObject()->property(index);
-
- QQmlBinding *newBinding = 0;
-
- QV4::ScopedFunctionObject f(scope, value);
- if (f) {
- if (!f->bindingKeyFlag()) {
- // assigning a JS function to a non-var-property is not allowed.
- QString error = QLatin1String("Cannot assign JavaScript function to value-type property");
- Scoped<String> e(scope, r->d()->v8->toString(error));
- v4->currentContext()->throwError(e);
- return;
- }
+ }
- QQmlContextData *context = r->d()->v8->callingContext();
+ QQmlContextData *context = QmlContextWrapper::callingContext(v4);
- QQmlPropertyData cacheData;
- cacheData.setFlags(QQmlPropertyData::IsWritable |
- QQmlPropertyData::IsValueTypeVirtual);
- cacheData.propType = reference->d()->object->metaObject()->property(reference->d()->property).userType();
- cacheData.coreIndex = reference->d()->property;
- cacheData.valueTypeFlags = 0;
- cacheData.valueTypeCoreIndex = index;
- cacheData.valueTypePropType = p.userType();
+ QQmlPropertyData cacheData;
+ cacheData.setFlags(QQmlPropertyData::IsWritable |
+ QQmlPropertyData::IsValueTypeVirtual);
+ cacheData.propType = writeBackPropertyType;
+ cacheData.coreIndex = reference->d()->property;
+ cacheData.valueTypeFlags = 0;
+ cacheData.valueTypeCoreIndex = pd->coreIndex;
+ cacheData.valueTypePropType = property.userType();
- QV4::Scoped<QQmlBindingFunction> bindingFunction(scope, f);
- bindingFunction->initBindingLocation();
+ QV4::Scoped<QQmlBindingFunction> bindingFunction(scope, f);
+ bindingFunction->initBindingLocation();
- newBinding = new QQmlBinding(value, reference->d()->object, context);
- newBinding->setTarget(reference->d()->object, cacheData, context);
- }
+ newBinding = new QQmlBinding(value, reference->d()->object, context);
+ newBinding->setTarget(reference->d()->object, cacheData, context);
+ }
+ if (reference) {
QQmlAbstractBinding *oldBinding =
- QQmlPropertyPrivate::setBinding(reference->d()->object, reference->d()->property, index, newBinding);
+ QQmlPropertyPrivate::setBinding(reference->d()->object, reference->d()->property, pd->coreIndex, newBinding);
if (oldBinding)
oldBinding->destroy();
+ }
- if (!f) {
- QVariant v = r->d()->v8->toVariant(value, -1);
+ if (newBinding)
+ return;
- if (p.isEnumType() && (QMetaType::Type)v.type() == QMetaType::Double)
- v = v.toInt();
+ QVariant v = v4->toVariant(value, property.userType());
- p.write(reference->d()->type, v);
+ if (property.isEnumType() && (QMetaType::Type)v.type() == QMetaType::Double)
+ v = v.toInt();
- if (writebackProperty.userType() == QMetaType::QVariant) {
- QVariant variantReferenceValue = r->d()->type->value();
- reference->d()->type->writeVariantValue(reference->d()->object, reference->d()->property, 0, &variantReferenceValue);
- } else {
- reference->d()->type->write(reference->d()->object, reference->d()->property, 0);
- }
- }
+ void *gadget = r->d()->gadget();
+ property.writeOnGadget(gadget, v);
- } else {
- Q_ASSERT(r->d()->objectType == QmlValueTypeWrapper::Copy);
-
- QmlValueTypeCopy *copy = static_cast<QmlValueTypeCopy *>(r.getPointer());
- int index = r->d()->type->metaObject()->indexOfProperty(propName.constData());
- if (index == -1)
- return;
+ if (reference) {
+ if (writeBackPropertyType == QMetaType::QVariant) {
+ QVariant variantReferenceValue = r->d()->toVariant();
- QVariant v = r->d()->v8->toVariant(value, -1);
+ int flags = 0;
+ int status = -1;
+ void *a[] = { &variantReferenceValue, 0, &status, &flags };
+ QMetaObject::metacall(reference->d()->object, QMetaObject::WriteProperty, reference->d()->property, a);
- r->d()->type->setValue(copy->d()->value);
- QMetaProperty p = r->d()->type->metaObject()->property(index);
- p.write(r->d()->type, v);
- copy->d()->value = r->d()->type->value();
+ } else {
+ int flags = 0;
+ int status = -1;
+ void *a[] = { r->d()->gadget(), 0, &status, &flags };
+ QMetaObject::metacall(reference->d()->object, QMetaObject::WriteProperty, reference->d()->property, a);
+ }
}
}
+void QQmlValueTypeReference::destroy(Heap::Base *that)
+{
+ static_cast<Heap::QQmlValueTypeReference*>(that)->Heap::QQmlValueTypeReference::~QQmlValueTypeReference();
+}
+
QT_END_NAMESPACE
diff --git a/src/qml/qml/qqmlvaluetypewrapper_p.h b/src/qml/qml/qqmlvaluetypewrapper_p.h
index c155b88cc0..2d0fbcbf52 100644
--- a/src/qml/qml/qqmlvaluetypewrapper_p.h
+++ b/src/qml/qml/qqmlvaluetypewrapper_p.h
@@ -53,33 +53,42 @@
QT_BEGIN_NAMESPACE
-class QQmlValueType;
class QV8Engine;
namespace QV4 {
-struct Q_QML_EXPORT QmlValueTypeWrapper : Object
+namespace Heap {
+
+struct QQmlValueTypeWrapper : Object {
+ QQmlValueTypeWrapper(ExecutionEngine *engine);
+ ~QQmlValueTypeWrapper();
+ mutable QQmlRefPointer<QQmlPropertyCache> propertyCache;
+ mutable void *gadgetPtr;
+ mutable int metaType;
+
+ void setValue(const QVariant &value) const;
+ QVariant toVariant() const;
+ void *gadget() const { return gadgetPtr; }
+};
+
+}
+
+struct Q_QML_EXPORT QQmlValueTypeWrapper : Object
{
- enum ObjectType { Reference, Copy };
- struct Data : Object::Data {
- Data(QV8Engine *engine, ObjectType type);
- QV8Engine *v8;
- ObjectType objectType;
- mutable QQmlValueType *type;
- };
- V4_OBJECT(Object)
+ V4_OBJECT2(QQmlValueTypeWrapper, Object)
+ static void destroy(Heap::Base *b);
public:
- static ReturnedValue create(QV8Engine *v8, QObject *, int, QQmlValueType *);
- static ReturnedValue create(QV8Engine *v8, const QVariant &, QQmlValueType *);
+ static ReturnedValue create(ExecutionEngine *engine, QObject *, int, const QMetaObject *metaObject, int typeId);
+ static ReturnedValue create(ExecutionEngine *engine, const QVariant &, const QMetaObject *metaObject, int typeId);
QVariant toVariant() const;
+ void toGadget(void *data) const;
bool isEqual(const QVariant& value);
static ReturnedValue get(Managed *m, String *name, bool *hasProperty);
static void put(Managed *m, String *name, const ValueRef value);
- static void destroy(Managed *that);
static bool isEqualTo(Managed *m, Managed *other);
static PropertyAttributes query(const Managed *, String *name);
diff --git a/src/qml/qml/qqmlvme_p.h b/src/qml/qml/qqmlvme_p.h
index e819a19ebf..bd84a2b8a3 100644
--- a/src/qml/qml/qqmlvme_p.h
+++ b/src/qml/qml/qqmlvme_p.h
@@ -58,7 +58,6 @@
#include <private/qqmlengine_p.h>
#include <private/qfinitestack_p.h>
-#include <private/qqmltrace_p.h>
#include <private/qqmlprofiler_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp
index f6d72c00b1..40ae8ce35a 100644
--- a/src/qml/qml/qqmlvmemetaobject.cpp
+++ b/src/qml/qml/qqmlvmemetaobject.cpp
@@ -608,7 +608,7 @@ QQmlVMEMetaObject::QQmlVMEMetaObject(QObject *obj,
QV4::Function *runtimeFunction = compilationUnit->runtimeFunctions[data->runtimeFunctionIndex];
o = QV4::FunctionObject::createScriptFunction(qmlBindingContext, runtimeFunction);
- v8methods[index] = o;
+ v8methods[index].set(qmlBindingContext->engine(), o);
}
}
}
@@ -926,7 +926,7 @@ int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
QV4::Scope scope(ep->v4engine());
- QV4::Scoped<QV4::FunctionObject> function(scope, method(id));
+ QV4::ScopedFunctionObject function(scope, method(id));
if (!function) {
// The function was not compiled. There are some exceptional cases which the
// expression rewriter does not rewrite properly (e.g., \r-terminated lines
@@ -945,18 +945,17 @@ int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
callData->thisObject = ep->v8engine()->global();
for (int ii = 0; ii < data->parameterCount; ++ii)
- callData->args[ii] = ep->v8engine()->fromVariant(*(QVariant *)a[ii + 1]);
+ callData->args[ii] = scope.engine->fromVariant(*(QVariant *)a[ii + 1]);
QV4::ScopedValue result(scope);
- QV4::ExecutionContext *ctx = function->engine()->currentContext();
result = function->call(callData);
if (scope.hasException()) {
- QQmlError error = QV4::ExecutionEngine::catchExceptionAsQmlError(ctx);
+ QQmlError error = scope.engine->catchExceptionAsQmlError();
if (error.isValid())
ep->warning(error);
if (a[0]) *(QVariant *)a[0] = QVariant();
} else {
- if (a[0]) *(QVariant *)a[0] = ep->v8engine()->toVariant(result, 0);
+ if (a[0]) *(QVariant *)a[0] = scope.engine->toVariant(result, 0);
}
ep->dereferenceScarceResources(); // "release" scarce resources if top-level expression evaluation is complete.
@@ -1005,7 +1004,7 @@ QVariant QQmlVMEMetaObject::readPropertyAsVariant(int id)
QV4::Scope scope(v4);
QV4::ScopedObject o(scope, varProperties.value());
QV4::ScopedValue val(scope, o->getIndexed(id - firstVarPropertyIndex));
- return v4->v8Engine->toVariant(val, -1);
+ return scope.engine->toVariant(val, -1);
}
return QVariant();
} else {
@@ -1078,7 +1077,7 @@ void QQmlVMEMetaObject::writeProperty(int id, const QVariant &value)
// And, if the new value is a scarce resource, we need to ensure that it does not get
// automatically released by the engine until no other references to it exist.
- QV4::ScopedValue newv(scope, QQmlEnginePrivate::get(ctxt->engine)->v8engine()->fromVariant(value));
+ QV4::ScopedValue newv(scope, scope.engine->fromVariant(value));
QV4::Scoped<QV4::VariantObject> v(scope, newv);
if (!!v)
v->addVmePropertyReference();
@@ -1184,7 +1183,7 @@ void QQmlVMEMetaObject::setVmeMethod(int index, QV4::ValueRef function)
v8methods = new QV4::PersistentValue[metaData->methodCount];
int methodIndex = index - methodOffset() - plainSignals;
- v8methods[methodIndex] = function;
+ v8methods[methodIndex].set(function->asObject()->engine(), function);
}
QV4::ReturnedValue QQmlVMEMetaObject::vmeProperty(int index)
@@ -1254,7 +1253,7 @@ void QQmlVMEMetaObject::allocateVarPropertiesArray()
assert(qml);
QV4::ExecutionEngine *v4 = QV8Engine::getV4(qml->handle());
QV4::Scope scope(v4);
- varProperties = QV4::ScopedValue(scope, v4->newArrayObject(metaData->varPropertyCount));
+ varProperties.set(scope.engine, v4->newArrayObject(metaData->varPropertyCount));
varPropertiesInitialized = true;
}
diff --git a/src/qml/qml/qqmlvmemetaobject_p.h b/src/qml/qml/qqmlvmemetaobject_p.h
index a8a9a02102..a7df7c6e53 100644
--- a/src/qml/qml/qqmlvmemetaobject_p.h
+++ b/src/qml/qml/qqmlvmemetaobject_p.h
@@ -90,19 +90,21 @@ struct QQmlVMEMetaData
return propertyIdx == -1;
}
bool isPropertyAlias() const {
- return !isObjectAlias() && !(propertyIdx & 0xFFFF0000);
+ return !isObjectAlias() && valueTypeIndex() == -1;
}
bool isValueTypeAlias() const {
- return !isObjectAlias() && (propertyIdx & 0xFFFF0000);
+ return !isObjectAlias() && valueTypeIndex() != -1;
}
int propertyIndex() const {
- return propertyIdx & 0x0000FFFF;
+ int index;
+ QQmlPropertyData::decodeValueTypePropertyIndex(propertyIdx, &index);
+ return index;
}
int valueTypeIndex() const {
- return (propertyIdx & 0xFFFF0000) >> 16;
+ return QQmlPropertyData::decodeValueTypePropertyIndex(propertyIdx);
}
int valueType() const {
- return (propertyIdx & 0xFFFF0000) ? propType : 0;
+ return (valueTypeIndex() != -1) ? propType : 0;
}
};
diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp
index 0730cbc363..f5451a2976 100644
--- a/src/qml/qml/qqmlxmlhttprequest.cpp
+++ b/src/qml/qml/qqmlxmlhttprequest.cpp
@@ -55,6 +55,7 @@
#include <QtCore/qxmlstream.h>
#include <QtCore/qstack.h>
#include <QtCore/qdebug.h>
+#include <QtCore/qbuffer.h>
#include <private/qv4objectproto_p.h>
#include <private/qv4scopedvalue_p.h>
@@ -64,8 +65,8 @@ using namespace QV4;
#ifndef QT_NO_XMLSTREAMREADER
#define V4THROW_REFERENCE(string) { \
- Scoped<Object> error(scope, ctx->engine()->newReferenceErrorObject(QStringLiteral(string))); \
- return ctx->throwError(error); \
+ ScopedObject error(scope, ctx->engine()->newReferenceErrorObject(QStringLiteral(string))); \
+ return ctx->engine()->throwError(error); \
}
QT_BEGIN_NAMESPACE
@@ -87,19 +88,18 @@ struct QQmlXMLHttpRequestData {
PersistentValue documentPrototype;
};
-static inline QQmlXMLHttpRequestData *xhrdata(QV8Engine *engine)
+static inline QQmlXMLHttpRequestData *xhrdata(ExecutionEngine *v4)
{
- return (QQmlXMLHttpRequestData *)engine->xmlHttpRequestData();
+ return (QQmlXMLHttpRequestData *)v4->v8Engine->xmlHttpRequestData();
}
-static ReturnedValue constructMeObject(const ValueRef thisObj, QV8Engine *e)
+static ReturnedValue constructMeObject(const ValueRef thisObj, ExecutionEngine *v4)
{
- ExecutionEngine *v4 = QV8Engine::getV4(e);
Scope scope(v4);
- Scoped<Object> meObj(scope, v4->newObject());
- meObj->put(ScopedString(scope, v4->newString(QStringLiteral("ThisObject"))).getPointer(), thisObj);
- ScopedValue v(scope, QmlContextWrapper::qmlScope(e, e->callingContext(), 0));
- meObj->put(ScopedString(scope, v4->newString(QStringLiteral("ActivationObject"))).getPointer(), v);
+ ScopedObject meObj(scope, v4->newObject());
+ meObj->put(ScopedString(scope, v4->newString(QStringLiteral("ThisObject"))), thisObj);
+ ScopedValue v(scope, QmlContextWrapper::qmlScope(v4, v4->v8Engine->callingContext(), 0));
+ meObj->put(ScopedString(scope, v4->newString(QStringLiteral("ActivationObject"))), v);
return meObj.asReturnedValue();
}
@@ -111,7 +111,7 @@ QQmlXMLHttpRequestData::~QQmlXMLHttpRequestData()
{
}
-namespace {
+namespace QV4 {
class DocumentImpl;
class NodeImpl
@@ -175,103 +175,100 @@ public:
void release() { QQmlRefCount::release(); }
};
+namespace Heap {
+
+struct NamedNodeMap : Object {
+ NamedNodeMap(ExecutionEngine *engine, NodeImpl *data, const QList<NodeImpl *> &list);
+ ~NamedNodeMap() {
+ if (d)
+ d->release();
+ }
+ QList<NodeImpl *> list; // Only used in NamedNodeMap
+ NodeImpl *d;
+};
+
+struct NodeList : Object {
+ NodeList(ExecutionEngine *engine, NodeImpl *data);
+ ~NodeList() {
+ if (d)
+ d->release();
+ }
+ NodeImpl *d;
+};
+
+struct NodePrototype : Object {
+ NodePrototype(ExecutionEngine *engine);
+};
+
+struct Node : Object {
+ Node(ExecutionEngine *engine, NodeImpl *data);
+ ~Node() {
+ if (d)
+ d->release();
+ }
+ NodeImpl *d;
+};
+
+}
+
class NamedNodeMap : public Object
{
public:
- struct Data : Object::Data {
- Data(ExecutionEngine *engine, NodeImpl *data, const QList<NodeImpl *> &list)
- : Object::Data(engine)
- , list(list)
- , d(data)
- {
- setVTable(staticVTable());
-
- if (d)
- d->addref();
- }
- ~Data() {
- if (d)
- d->release();
- }
- QList<NodeImpl *> list; // Only used in NamedNodeMap
- NodeImpl *d;
- };
- V4_OBJECT(Object)
+ V4_OBJECT2(NamedNodeMap, Object)
+ V4_NEEDS_DESTROY
// C++ API
- static ReturnedValue create(QV8Engine *, NodeImpl *, const QList<NodeImpl *> &);
+ static ReturnedValue create(ExecutionEngine *, NodeImpl *, const QList<NodeImpl *> &);
// JS API
- static void destroy(Managed *that) {
- static_cast<NamedNodeMap *>(that)->d()->~Data();
- }
static ReturnedValue get(Managed *m, String *name, bool *hasProperty);
static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty);
};
+Heap::NamedNodeMap::NamedNodeMap(ExecutionEngine *engine, NodeImpl *data, const QList<NodeImpl *> &list)
+ : Heap::Object(engine)
+ , list(list)
+ , d(data)
+{
+ setVTable(QV4::NamedNodeMap::staticVTable());
+
+ if (d)
+ d->addref();
+}
+
DEFINE_OBJECT_VTABLE(NamedNodeMap);
class NodeList : public Object
{
public:
- struct Data : Object::Data {
- Data(ExecutionEngine *engine, NodeImpl *data)
- : Object::Data(engine)
- , d(data)
- {
- setVTable(staticVTable());
-
- if (d)
- d->addref();
- }
- ~Data() {
- if (d)
- d->release();
- }
- NodeImpl *d;
- };
- V4_OBJECT(Object)
+ V4_OBJECT2(NodeList, Object)
+ V4_NEEDS_DESTROY
// JS API
- static void destroy(Managed *that) {
- static_cast<NodeList *>(that)->d()->~Data();
- }
static ReturnedValue get(Managed *m, String *name, bool *hasProperty);
static ReturnedValue getIndexed(Managed *m, uint index, bool *hasProperty);
// C++ API
- static ReturnedValue create(QV8Engine *, NodeImpl *);
+ static ReturnedValue create(ExecutionEngine *, NodeImpl *);
};
+Heap::NodeList::NodeList(ExecutionEngine *engine, NodeImpl *data)
+ : Heap::Object(engine)
+ , d(data)
+{
+ setVTable(QV4::NodeList::staticVTable());
+
+ if (d)
+ d->addref();
+}
+
DEFINE_OBJECT_VTABLE(NodeList);
class NodePrototype : public Object
{
public:
- struct Data : Object::Data {
- Data(ExecutionEngine *engine)
- : Object::Data(engine)
- {
- setVTable(staticVTable());
-
- Scope scope(engine);
- ScopedObject o(scope, this);
-
- o->defineAccessorProperty(QStringLiteral("nodeName"), method_get_nodeName, 0);
- o->defineAccessorProperty(QStringLiteral("nodeValue"), method_get_nodeValue, 0);
- o->defineAccessorProperty(QStringLiteral("nodeType"), method_get_nodeType, 0);
-
- o->defineAccessorProperty(QStringLiteral("parentNode"), method_get_parentNode, 0);
- o->defineAccessorProperty(QStringLiteral("childNodes"), method_get_childNodes, 0);
- o->defineAccessorProperty(QStringLiteral("firstChild"), method_get_firstChild, 0);
- o->defineAccessorProperty(QStringLiteral("lastChild"), method_get_lastChild, 0);
- o->defineAccessorProperty(QStringLiteral("previousSibling"), method_get_previousSibling, 0);
- o->defineAccessorProperty(QStringLiteral("nextSibling"), method_get_nextSibling, 0);
- o->defineAccessorProperty(QStringLiteral("attributes"), method_get_attributes, 0);
- }
- };
- V4_OBJECT(Object)
+ V4_OBJECT2(NodePrototype, Object)
static void initClass(ExecutionEngine *engine);
@@ -299,36 +296,37 @@ public:
};
-DEFINE_OBJECT_VTABLE(NodePrototype);
-
-struct Node : public Object
+Heap::NodePrototype::NodePrototype(ExecutionEngine *engine)
+ : Heap::Object(engine)
{
- struct Data : Object::Data {
- Data(ExecutionEngine *engine, NodeImpl *data)
- : Object::Data(engine)
- , d(data)
- {
- setVTable(staticVTable());
+ setVTable(QV4::NodePrototype::staticVTable());
- if (d)
- d->addref();
- }
- ~Data() {
- if (d)
- d->release();
- }
- NodeImpl *d;
- };
- V4_OBJECT(Object)
+ Scope scope(engine);
+ ScopedObject o(scope, this);
+ o->defineAccessorProperty(QStringLiteral("nodeName"), QV4::NodePrototype::method_get_nodeName, 0);
+ o->defineAccessorProperty(QStringLiteral("nodeValue"), QV4::NodePrototype::method_get_nodeValue, 0);
+ o->defineAccessorProperty(QStringLiteral("nodeType"), QV4::NodePrototype::method_get_nodeType, 0);
- // JS API
- static void destroy(Managed *that) {
- static_cast<Node *>(that)->d()->~Data();
- }
+ o->defineAccessorProperty(QStringLiteral("parentNode"), QV4::NodePrototype::method_get_parentNode, 0);
+ o->defineAccessorProperty(QStringLiteral("childNodes"), QV4::NodePrototype::method_get_childNodes, 0);
+ o->defineAccessorProperty(QStringLiteral("firstChild"), QV4::NodePrototype::method_get_firstChild, 0);
+ o->defineAccessorProperty(QStringLiteral("lastChild"), QV4::NodePrototype::method_get_lastChild, 0);
+ o->defineAccessorProperty(QStringLiteral("previousSibling"), QV4::NodePrototype::method_get_previousSibling, 0);
+ o->defineAccessorProperty(QStringLiteral("nextSibling"), QV4::NodePrototype::method_get_nextSibling, 0);
+ o->defineAccessorProperty(QStringLiteral("attributes"), QV4::NodePrototype::method_get_attributes, 0);
+}
+
+
+DEFINE_OBJECT_VTABLE(NodePrototype);
+
+struct Node : public Object
+{
+ V4_OBJECT2(Node, Object)
+ V4_NEEDS_DESTROY
// C++ API
- static ReturnedValue create(QV8Engine *, NodeImpl *);
+ static ReturnedValue create(ExecutionEngine *v4, NodeImpl *);
bool isNull() const;
@@ -337,6 +335,16 @@ private:
Node(const Node &o);
};
+Heap::Node::Node(ExecutionEngine *engine, NodeImpl *data)
+ : Heap::Object(engine)
+ , d(data)
+{
+ setVTable(QV4::Node::staticVTable());
+
+ if (d)
+ d->addref();
+}
+
DEFINE_OBJECT_VTABLE(Node);
class Element : public Node
@@ -400,7 +408,7 @@ public:
// C++ API
static ReturnedValue prototype(ExecutionEngine *);
- static ReturnedValue load(QV8Engine *engine, const QByteArray &data);
+ static ReturnedValue load(ExecutionEngine *engine, const QByteArray &data);
};
}
@@ -420,7 +428,7 @@ ReturnedValue NodePrototype::method_get_nodeName(CallContext *ctx)
Scope scope(ctx);
Scoped<Node> r(scope, ctx->d()->callData->thisObject.as<Node>());
if (!r)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
QString name;
switch (r->d()->d->type) {
@@ -445,7 +453,7 @@ ReturnedValue NodePrototype::method_get_nodeValue(CallContext *ctx)
Scope scope(ctx);
Scoped<Node> r(scope, ctx->d()->callData->thisObject.as<Node>());
if (!r)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
if (r->d()->d->type == NodeImpl::Document ||
r->d()->d->type == NodeImpl::DocumentFragment ||
@@ -464,7 +472,7 @@ ReturnedValue NodePrototype::method_get_nodeType(CallContext *ctx)
Scope scope(ctx);
Scoped<Node> r(scope, ctx->d()->callData->thisObject.as<Node>());
if (!r)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
return Encode(r->d()->d->type);
}
@@ -474,12 +482,10 @@ ReturnedValue NodePrototype::method_get_parentNode(CallContext *ctx)
Scope scope(ctx);
Scoped<Node> r(scope, ctx->d()->callData->thisObject.as<Node>());
if (!r)
- return ctx->throwTypeError();
-
- QV8Engine *engine = ctx->d()->engine->v8Engine;
+ return ctx->engine()->throwTypeError();
if (r->d()->d->parent)
- return Node::create(engine, r->d()->d->parent);
+ return Node::create(scope.engine, r->d()->d->parent);
else
return Encode::null();
}
@@ -489,11 +495,9 @@ ReturnedValue NodePrototype::method_get_childNodes(CallContext *ctx)
Scope scope(ctx);
Scoped<Node> r(scope, ctx->d()->callData->thisObject.as<Node>());
if (!r)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
- QV8Engine *engine = ctx->d()->engine->v8Engine;
-
- return NodeList::create(engine, r->d()->d);
+ return NodeList::create(scope.engine, r->d()->d);
}
ReturnedValue NodePrototype::method_get_firstChild(CallContext *ctx)
@@ -501,14 +505,12 @@ ReturnedValue NodePrototype::method_get_firstChild(CallContext *ctx)
Scope scope(ctx);
Scoped<Node> r(scope, ctx->d()->callData->thisObject.as<Node>());
if (!r)
- return ctx->throwTypeError();
-
- QV8Engine *engine = ctx->d()->engine->v8Engine;
+ return ctx->engine()->throwTypeError();
if (r->d()->d->children.isEmpty())
return Encode::null();
else
- return Node::create(engine, r->d()->d->children.first());
+ return Node::create(scope.engine, r->d()->d->children.first());
}
ReturnedValue NodePrototype::method_get_lastChild(CallContext *ctx)
@@ -516,14 +518,12 @@ ReturnedValue NodePrototype::method_get_lastChild(CallContext *ctx)
Scope scope(ctx);
Scoped<Node> r(scope, ctx->d()->callData->thisObject.as<Node>());
if (!r)
- return ctx->throwTypeError();
-
- QV8Engine *engine = ctx->d()->engine->v8Engine;
+ return ctx->engine()->throwTypeError();
if (r->d()->d->children.isEmpty())
return Encode::null();
else
- return Node::create(engine, r->d()->d->children.last());
+ return Node::create(scope.engine, r->d()->d->children.last());
}
ReturnedValue NodePrototype::method_get_previousSibling(CallContext *ctx)
@@ -531,9 +531,7 @@ ReturnedValue NodePrototype::method_get_previousSibling(CallContext *ctx)
Scope scope(ctx);
Scoped<Node> r(scope, ctx->d()->callData->thisObject.as<Node>());
if (!r)
- return ctx->throwTypeError();
-
- QV8Engine *engine = ctx->d()->engine->v8Engine;
+ return ctx->engine()->throwTypeError();
if (!r->d()->d->parent)
return Encode::null();
@@ -543,7 +541,7 @@ ReturnedValue NodePrototype::method_get_previousSibling(CallContext *ctx)
if (ii == 0)
return Encode::null();
else
- return Node::create(engine, r->d()->d->parent->children.at(ii - 1));
+ return Node::create(scope.engine, r->d()->d->parent->children.at(ii - 1));
}
}
@@ -555,9 +553,7 @@ ReturnedValue NodePrototype::method_get_nextSibling(CallContext *ctx)
Scope scope(ctx);
Scoped<Node> r(scope, ctx->d()->callData->thisObject.as<Node>());
if (!r)
- return ctx->throwTypeError();
-
- QV8Engine *engine = ctx->d()->engine->v8Engine;
+ return ctx->engine()->throwTypeError();
if (!r->d()->d->parent)
return Encode::null();
@@ -567,7 +563,7 @@ ReturnedValue NodePrototype::method_get_nextSibling(CallContext *ctx)
if ((ii + 1) == r->d()->d->parent->children.count())
return Encode::null();
else
- return Node::create(engine, r->d()->d->parent->children.at(ii + 1));
+ return Node::create(scope.engine, r->d()->d->parent->children.at(ii + 1));
}
}
@@ -579,31 +575,28 @@ ReturnedValue NodePrototype::method_get_attributes(CallContext *ctx)
Scope scope(ctx);
Scoped<Node> r(scope, ctx->d()->callData->thisObject.as<Node>());
if (!r)
- return ctx->throwTypeError();
-
- QV8Engine *engine = ctx->d()->engine->v8Engine;
+ return ctx->engine()->throwTypeError();
if (r->d()->d->type != NodeImpl::Element)
return Encode::null();
else
- return NamedNodeMap::create(engine, r->d()->d, r->d()->d->attributes);
+ return NamedNodeMap::create(scope.engine, r->d()->d, r->d()->d->attributes);
}
ReturnedValue NodePrototype::getProto(ExecutionEngine *v4)
{
Scope scope(v4);
- QQmlXMLHttpRequestData *d = xhrdata(v4->v8Engine);
+ QQmlXMLHttpRequestData *d = xhrdata(v4);
if (d->nodePrototype.isUndefined()) {
ScopedObject p(scope, v4->memoryManager->alloc<NodePrototype>(v4));
- d->nodePrototype = p;
+ d->nodePrototype.set(v4, p);
v4->v8Engine->freezeObject(p);
}
return d->nodePrototype.value();
}
-ReturnedValue Node::create(QV8Engine *engine, NodeImpl *data)
+ReturnedValue Node::create(ExecutionEngine *v4, NodeImpl *data)
{
- ExecutionEngine *v4 = QV8Engine::getV4(engine);
Scope scope(v4);
Scoped<Node> instance(scope, v4->memoryManager->alloc<Node>(v4, data));
@@ -611,7 +604,7 @@ ReturnedValue Node::create(QV8Engine *engine, NodeImpl *data)
switch (data->type) {
case NodeImpl::Attr:
- instance->setPrototype((p = Attr::prototype(v4)).getPointer());
+ instance->setPrototype((p = Attr::prototype(v4)));
break;
case NodeImpl::Comment:
case NodeImpl::Document:
@@ -623,13 +616,13 @@ ReturnedValue Node::create(QV8Engine *engine, NodeImpl *data)
case NodeImpl::ProcessingInstruction:
return Encode::undefined();
case NodeImpl::CDATA:
- instance->setPrototype((p = CDATA::prototype(v4)).getPointer());
+ instance->setPrototype((p = CDATA::prototype(v4)));
break;
case NodeImpl::Text:
- instance->setPrototype((p = Text::prototype(v4)).getPointer());
+ instance->setPrototype((p = Text::prototype(v4)));
break;
case NodeImpl::Element:
- instance->setPrototype((p = Element::prototype(v4)).getPointer());
+ instance->setPrototype((p = Element::prototype(v4)));
break;
}
@@ -638,14 +631,14 @@ ReturnedValue Node::create(QV8Engine *engine, NodeImpl *data)
ReturnedValue Element::prototype(ExecutionEngine *engine)
{
- QQmlXMLHttpRequestData *d = xhrdata(engine->v8Engine);
+ QQmlXMLHttpRequestData *d = xhrdata(engine);
if (d->elementPrototype.isUndefined()) {
Scope scope(engine);
ScopedObject p(scope, engine->newObject());
ScopedObject pp(scope);
- p->setPrototype((pp = NodePrototype::getProto(engine)).getPointer());
+ p->setPrototype((pp = NodePrototype::getProto(engine)));
p->defineAccessorProperty(QStringLiteral("tagName"), NodePrototype::method_get_nodeName, 0);
- d->elementPrototype = p;
+ d->elementPrototype.set(engine, p);
engine->v8Engine->freezeObject(p);
}
return d->elementPrototype.value();
@@ -653,16 +646,16 @@ ReturnedValue Element::prototype(ExecutionEngine *engine)
ReturnedValue Attr::prototype(ExecutionEngine *engine)
{
- QQmlXMLHttpRequestData *d = xhrdata(engine->v8Engine);
+ QQmlXMLHttpRequestData *d = xhrdata(engine);
if (d->attrPrototype.isUndefined()) {
Scope scope(engine);
- Scoped<Object> p(scope, engine->newObject());
+ ScopedObject p(scope, engine->newObject());
ScopedObject pp(scope);
- p->setPrototype((pp = NodePrototype::getProto(engine)).getPointer());
+ p->setPrototype((pp = NodePrototype::getProto(engine)));
p->defineAccessorProperty(QStringLiteral("name"), method_name, 0);
p->defineAccessorProperty(QStringLiteral("value"), method_value, 0);
p->defineAccessorProperty(QStringLiteral("ownerElement"), method_ownerElement, 0);
- d->attrPrototype = p;
+ d->attrPrototype.set(engine, p);
engine->v8Engine->freezeObject(p);
}
return d->attrPrototype.value();
@@ -674,9 +667,8 @@ ReturnedValue Attr::method_name(CallContext *ctx)
Scoped<Node> r(scope, ctx->d()->callData->thisObject.as<Node>());
if (!r)
return Encode::undefined();
- QV8Engine *engine = ctx->d()->engine->v8Engine;
- return engine->toString(r->d()->d->name);
+ return QV4::Encode(scope.engine->newString(r->d()->d->name));
}
ReturnedValue Attr::method_value(CallContext *ctx)
@@ -685,9 +677,8 @@ ReturnedValue Attr::method_value(CallContext *ctx)
Scoped<Node> r(scope, ctx->d()->callData->thisObject.as<Node>());
if (!r)
return Encode::undefined();
- QV8Engine *engine = ctx->d()->engine->v8Engine;
- return engine->toString(r->d()->d->data);
+ return QV4::Encode(scope.engine->newString(r->d()->d->data));
}
ReturnedValue Attr::method_ownerElement(CallContext *ctx)
@@ -696,9 +687,8 @@ ReturnedValue Attr::method_ownerElement(CallContext *ctx)
Scoped<Node> r(scope, ctx->d()->callData->thisObject.as<Node>());
if (!r)
return Encode::undefined();
- QV8Engine *engine = ctx->d()->engine->v8Engine;
- return Node::create(engine, r->d()->d->parent);
+ return Node::create(scope.engine, r->d()->d->parent);
}
ReturnedValue CharacterData::method_length(CallContext *ctx)
@@ -707,22 +697,21 @@ ReturnedValue CharacterData::method_length(CallContext *ctx)
Scoped<Node> r(scope, ctx->d()->callData->thisObject.as<Node>());
if (!r)
return Encode::undefined();
- QV8Engine *engine = ctx->d()->engine->v8Engine;
- Q_UNUSED(engine)
+
return Encode(r->d()->d->data.length());
}
ReturnedValue CharacterData::prototype(ExecutionEngine *v4)
{
- QQmlXMLHttpRequestData *d = xhrdata(v4->v8Engine);
+ QQmlXMLHttpRequestData *d = xhrdata(v4);
if (d->characterDataPrototype.isUndefined()) {
Scope scope(v4);
- Scoped<Object> p(scope, v4->newObject());
+ ScopedObject p(scope, v4->newObject());
ScopedObject pp(scope);
- p->setPrototype((pp = NodePrototype::getProto(v4)).getPointer());
+ p->setPrototype((pp = NodePrototype::getProto(v4)));
p->defineAccessorProperty(QStringLiteral("data"), NodePrototype::method_get_nodeValue, 0);
p->defineAccessorProperty(QStringLiteral("length"), method_length, 0);
- d->characterDataPrototype = p;
+ d->characterDataPrototype.set(v4, p);
v4->v8Engine->freezeObject(p);
}
return d->characterDataPrototype.value();
@@ -743,22 +732,21 @@ ReturnedValue Text::method_wholeText(CallContext *ctx)
Scoped<Node> r(scope, ctx->d()->callData->thisObject.as<Node>());
if (!r)
return Encode::undefined();
- QV8Engine *engine = ctx->d()->engine->v8Engine;
- return engine->toString(r->d()->d->data);
+ return QV4::Encode(scope.engine->newString(r->d()->d->data));
}
ReturnedValue Text::prototype(ExecutionEngine *v4)
{
- QQmlXMLHttpRequestData *d = xhrdata(v4->v8Engine);
+ QQmlXMLHttpRequestData *d = xhrdata(v4);
if (d->textPrototype.isUndefined()) {
Scope scope(v4);
- Scoped<Object> p(scope, v4->newObject());
+ ScopedObject p(scope, v4->newObject());
ScopedObject pp(scope);
- p->setPrototype((pp = CharacterData::prototype(v4)).getPointer());
+ p->setPrototype((pp = CharacterData::prototype(v4)));
p->defineAccessorProperty(QStringLiteral("isElementContentWhitespace"), method_isElementContentWhitespace, 0);
p->defineAccessorProperty(QStringLiteral("wholeText"), method_wholeText, 0);
- d->textPrototype = p;
+ d->textPrototype.set(v4, p);
v4->v8Engine->freezeObject(p);
}
return d->textPrototype.value();
@@ -767,13 +755,13 @@ ReturnedValue Text::prototype(ExecutionEngine *v4)
ReturnedValue CDATA::prototype(ExecutionEngine *v4)
{
// ### why not just use TextProto???
- QQmlXMLHttpRequestData *d = xhrdata(v4->v8Engine);
+ QQmlXMLHttpRequestData *d = xhrdata(v4);
if (d->cdataPrototype.isUndefined()) {
Scope scope(v4);
- Scoped<Object> p(scope, v4->newObject());
+ ScopedObject p(scope, v4->newObject());
ScopedObject pp(scope);
- p->setPrototype((pp = Text::prototype(v4)).getPointer());
- d->cdataPrototype = p;
+ p->setPrototype((pp = Text::prototype(v4)));
+ d->cdataPrototype.set(v4, p);
v4->v8Engine->freezeObject(p);
}
return d->cdataPrototype.value();
@@ -781,26 +769,24 @@ ReturnedValue CDATA::prototype(ExecutionEngine *v4)
ReturnedValue Document::prototype(ExecutionEngine *v4)
{
- QQmlXMLHttpRequestData *d = xhrdata(v4->v8Engine);
+ QQmlXMLHttpRequestData *d = xhrdata(v4);
if (d->documentPrototype.isUndefined()) {
Scope scope(v4);
- Scoped<Object> p(scope, v4->newObject());
+ ScopedObject p(scope, v4->newObject());
ScopedObject pp(scope);
- p->setPrototype((pp = NodePrototype::getProto(v4)).getPointer());
+ p->setPrototype((pp = NodePrototype::getProto(v4)));
p->defineAccessorProperty(QStringLiteral("xmlVersion"), method_xmlVersion, 0);
p->defineAccessorProperty(QStringLiteral("xmlEncoding"), method_xmlEncoding, 0);
p->defineAccessorProperty(QStringLiteral("xmlStandalone"), method_xmlStandalone, 0);
p->defineAccessorProperty(QStringLiteral("documentElement"), method_documentElement, 0);
- d->documentPrototype = p;
+ d->documentPrototype.set(v4, p);
v4->v8Engine->freezeObject(p);
}
return d->documentPrototype.value();
}
-ReturnedValue Document::load(QV8Engine *engine, const QByteArray &data)
+ReturnedValue Document::load(ExecutionEngine *v4, const QByteArray &data)
{
- Q_ASSERT(engine);
- ExecutionEngine *v4 = QV8Engine::getV4(engine);
Scope scope(v4);
DocumentImpl *document = 0;
@@ -883,7 +869,7 @@ ReturnedValue Document::load(QV8Engine *engine, const QByteArray &data)
ScopedObject instance(scope, v4->memoryManager->alloc<Node>(v4, document));
ScopedObject p(scope);
- instance->setPrototype((p = Document::prototype(v4)).getPointer());
+ instance->setPrototype((p = Document::prototype(v4)));
return instance.asReturnedValue();
}
@@ -899,15 +885,13 @@ ReturnedValue NamedNodeMap::getIndexed(Managed *m, uint index, bool *hasProperty
if (!r) {
if (hasProperty)
*hasProperty = false;
- return v4->currentContext()->throwTypeError();
+ return v4->throwTypeError();
}
- QV8Engine *engine = v4->v8Engine;
-
if ((int)index < r->d()->list.count()) {
if (hasProperty)
*hasProperty = true;
- return Node::create(engine, r->d()->list.at(index));
+ return Node::create(v4, r->d()->list.at(index));
}
if (hasProperty)
*hasProperty = false;
@@ -924,14 +908,12 @@ ReturnedValue NamedNodeMap::get(Managed *m, String *name, bool *hasProperty)
if (name->equals(v4->id_length))
return Primitive::fromInt32(r->d()->list.count()).asReturnedValue();
- QV8Engine *engine = v4->v8Engine;
-
QString str = name->toQString();
for (int ii = 0; ii < r->d()->list.count(); ++ii) {
if (r->d()->list.at(ii)->name == str) {
if (hasProperty)
*hasProperty = true;
- return Node::create(engine, r->d()->list.at(ii));
+ return Node::create(v4, r->d()->list.at(ii));
}
}
@@ -940,9 +922,8 @@ ReturnedValue NamedNodeMap::get(Managed *m, String *name, bool *hasProperty)
return Encode::undefined();
}
-ReturnedValue NamedNodeMap::create(QV8Engine *engine, NodeImpl *data, const QList<NodeImpl *> &list)
+ReturnedValue NamedNodeMap::create(ExecutionEngine *v4, NodeImpl *data, const QList<NodeImpl *> &list)
{
- ExecutionEngine *v4 = QV8Engine::getV4(engine);
return (v4->memoryManager->alloc<NamedNodeMap>(v4, data, list))->asReturnedValue();
}
@@ -952,12 +933,10 @@ ReturnedValue NodeList::getIndexed(Managed *m, uint index, bool *hasProperty)
QV4::ExecutionEngine *v4 = m->engine();
NodeList *r = static_cast<NodeList *>(m);
- QV8Engine *engine = v4->v8Engine;
-
if ((int)index < r->d()->d->children.count()) {
if (hasProperty)
*hasProperty = true;
- return Node::create(engine, r->d()->d->children.at(index));
+ return Node::create(v4, r->d()->d->children.at(index));
}
if (hasProperty)
*hasProperty = false;
@@ -977,9 +956,8 @@ ReturnedValue NodeList::get(Managed *m, String *name, bool *hasProperty)
return Object::get(m, name, hasProperty);
}
-ReturnedValue NodeList::create(QV8Engine *engine, NodeImpl *data)
+ReturnedValue NodeList::create(ExecutionEngine *v4, NodeImpl *data)
{
- ExecutionEngine *v4 = QV8Engine::getV4(engine);
return (v4->memoryManager->alloc<NodeList>(v4, data))->asReturnedValue();
}
@@ -989,9 +967,8 @@ ReturnedValue Document::method_documentElement(CallContext *ctx)
Scoped<Node> r(scope, ctx->d()->callData->thisObject.as<Node>());
if (!r || r->d()->d->type != NodeImpl::Document)
return Encode::undefined();
- QV8Engine *engine = ctx->d()->engine->v8Engine;
- return Node::create(engine, static_cast<DocumentImpl *>(r->d()->d)->root);
+ return Node::create(scope.engine, static_cast<DocumentImpl *>(r->d()->d)->root);
}
ReturnedValue Document::method_xmlStandalone(CallContext *ctx)
@@ -1000,8 +977,7 @@ ReturnedValue Document::method_xmlStandalone(CallContext *ctx)
Scoped<Node> r(scope, ctx->d()->callData->thisObject.as<Node>());
if (!r || r->d()->d->type != NodeImpl::Document)
return Encode::undefined();
- QV8Engine *engine = ctx->d()->engine->v8Engine;
- Q_UNUSED(engine)
+
return Encode(static_cast<DocumentImpl *>(r->d()->d)->isStandalone);
}
@@ -1011,9 +987,8 @@ ReturnedValue Document::method_xmlVersion(CallContext *ctx)
Scoped<Node> r(scope, ctx->d()->callData->thisObject.as<Node>());
if (!r || r->d()->d->type != NodeImpl::Document)
return Encode::undefined();
- QV8Engine *engine = ctx->d()->engine->v8Engine;
- return engine->toString(static_cast<DocumentImpl *>(r->d()->d)->version);
+ return QV4::Encode(scope.engine->newString(static_cast<DocumentImpl *>(r->d()->d)->version));
}
ReturnedValue Document::method_xmlEncoding(CallContext *ctx)
@@ -1022,20 +997,23 @@ ReturnedValue Document::method_xmlEncoding(CallContext *ctx)
Scoped<Node> r(scope, ctx->d()->callData->thisObject.as<Node>());
if (!r || r->d()->d->type != NodeImpl::Document)
return Encode::undefined();
- QV8Engine *engine = ctx->d()->engine->v8Engine;
- return engine->toString(static_cast<DocumentImpl *>(r->d()->d)->encoding);
+ return QV4::Encode(scope.engine->newString(static_cast<DocumentImpl *>(r->d()->d)->encoding));
}
class QQmlXMLHttpRequest : public QObject
{
Q_OBJECT
public:
+ enum LoadType {
+ AsynchronousLoad,
+ SynchronousLoad
+ };
enum State { Unsent = 0,
Opened = 1, HeadersReceived = 2,
Loading = 3, Done = 4 };
- QQmlXMLHttpRequest(QV8Engine *engine, QNetworkAccessManager *manager);
+ QQmlXMLHttpRequest(ExecutionEngine *engine, QNetworkAccessManager *manager);
virtual ~QQmlXMLHttpRequest();
bool sendFlag() const;
@@ -1044,7 +1022,7 @@ public:
int replyStatus() const;
QString replyStatusText() const;
- ReturnedValue open(const ValueRef me, const QString &, const QUrl &);
+ ReturnedValue open(const ValueRef me, const QString &, const QUrl &, LoadType);
ReturnedValue send(const ValueRef me, const QByteArray &);
ReturnedValue abort(const ValueRef me);
@@ -1106,8 +1084,8 @@ private:
QNetworkAccessManager *networkAccessManager() { return m_nam; }
};
-QQmlXMLHttpRequest::QQmlXMLHttpRequest(QV8Engine *engine, QNetworkAccessManager *manager)
- : v4(QV8Engine::getV4(engine))
+QQmlXMLHttpRequest::QQmlXMLHttpRequest(ExecutionEngine *engine, QNetworkAccessManager *manager)
+ : v4(engine)
, m_state(Unsent), m_errorFlag(false), m_sendFlag(false)
, m_redirectCount(0), m_gotXml(false), m_textCodec(0), m_network(0), m_nam(manager)
{
@@ -1143,7 +1121,7 @@ QString QQmlXMLHttpRequest::replyStatusText() const
return m_statusText;
}
-ReturnedValue QQmlXMLHttpRequest::open(const ValueRef me, const QString &method, const QUrl &url)
+ReturnedValue QQmlXMLHttpRequest::open(const ValueRef me, const QString &method, const QUrl &url, LoadType loadType)
{
destroyNetwork();
m_sendFlag = false;
@@ -1151,6 +1129,7 @@ ReturnedValue QQmlXMLHttpRequest::open(const ValueRef me, const QString &method,
m_responseEntityBody = QByteArray();
m_method = method;
m_url = url;
+ m_request.setAttribute(QNetworkRequest::SynchronousRequestAttribute, loadType == SynchronousLoad);
m_state = Opened;
m_addedHeaders.clear();
dispatchCallback(me);
@@ -1249,23 +1228,42 @@ void QQmlXMLHttpRequest::requestFromUrl(const QUrl &url)
}
}
- if (m_method == QLatin1String("GET"))
+ if (m_method == QLatin1String("GET")) {
m_network = networkAccessManager()->get(request);
- else if (m_method == QLatin1String("HEAD"))
+ } else if (m_method == QLatin1String("HEAD")) {
m_network = networkAccessManager()->head(request);
- else if (m_method == QLatin1String("POST"))
+ } else if (m_method == QLatin1String("POST")) {
m_network = networkAccessManager()->post(request, m_data);
- else if (m_method == QLatin1String("PUT"))
+ } else if (m_method == QLatin1String("PUT")) {
m_network = networkAccessManager()->put(request, m_data);
- else if (m_method == QLatin1String("DELETE"))
+ } else if (m_method == QLatin1String("DELETE")) {
m_network = networkAccessManager()->deleteResource(request);
+ } else if (m_method == QLatin1String("OPTIONS")) {
+ QBuffer *buffer = new QBuffer;
+ buffer->setData(m_data);
+ buffer->open(QIODevice::ReadOnly);
+ m_network = networkAccessManager()->sendCustomRequest(request, QByteArrayLiteral("OPTIONS"), buffer);
+ buffer->setParent(m_network);
+ }
- QObject::connect(m_network, SIGNAL(readyRead()),
- this, SLOT(readyRead()));
- QObject::connect(m_network, SIGNAL(error(QNetworkReply::NetworkError)),
- this, SLOT(error(QNetworkReply::NetworkError)));
- QObject::connect(m_network, SIGNAL(finished()),
- this, SLOT(finished()));
+ if (m_request.attribute(QNetworkRequest::SynchronousRequestAttribute).toBool()) {
+ if (m_network->bytesAvailable() > 0)
+ readyRead();
+
+ QNetworkReply::NetworkError networkError = m_network->error();
+ if (networkError != QNetworkReply::NoError) {
+ error(networkError);
+ } else {
+ finished();
+ }
+ } else {
+ QObject::connect(m_network, SIGNAL(readyRead()),
+ this, SLOT(readyRead()));
+ QObject::connect(m_network, SIGNAL(error(QNetworkReply::NetworkError)),
+ this, SLOT(error(QNetworkReply::NetworkError)));
+ QObject::connect(m_network, SIGNAL(finished()),
+ this, SLOT(finished()));
+ }
}
ReturnedValue QQmlXMLHttpRequest::send(const ValueRef me, const QByteArray &data)
@@ -1310,7 +1308,7 @@ ReturnedValue QQmlXMLHttpRequest::getMe() const
void QQmlXMLHttpRequest::setMe(const ValueRef me)
{
- m_me = me;
+ m_me.set(v4, me);
}
void QQmlXMLHttpRequest::readyRead()
@@ -1522,38 +1520,37 @@ const QByteArray &QQmlXMLHttpRequest::rawResponseBody() const
void QQmlXMLHttpRequest::dispatchCallbackImpl(const ValueRef me)
{
- ExecutionContext *ctx = v4->currentContext();
QV4::Scope scope(v4);
- Scoped<Object> o(scope, me);
+ ScopedObject o(scope, me);
if (!o) {
- ctx->throwError(QStringLiteral("QQmlXMLHttpRequest: internal error: empty ThisObject"));
+ v4->throwError(QStringLiteral("QQmlXMLHttpRequest: internal error: empty ThisObject"));
return;
}
ScopedString s(scope, v4->newString(QStringLiteral("ThisObject")));
- Scoped<Object> thisObj(scope, o->get(s.getPointer()));
+ ScopedObject thisObj(scope, o->get(s));
if (!thisObj) {
- ctx->throwError(QStringLiteral("QQmlXMLHttpRequest: internal error: empty ThisObject"));
+ v4->throwError(QStringLiteral("QQmlXMLHttpRequest: internal error: empty ThisObject"));
return;
}
s = v4->newString(QStringLiteral("onreadystatechange"));
- Scoped<FunctionObject> callback(scope, thisObj->get(s.getPointer()));
+ ScopedFunctionObject callback(scope, thisObj->get(s));
if (!callback) {
// not an error, but no onreadystatechange function to call.
return;
}
s = v4->newString(QStringLiteral("ActivationObject"));
- Scoped<Object> activationObject(scope, o->get(s.getPointer()));
+ ScopedObject activationObject(scope, o->get(s));
if (!activationObject) {
- v4->currentContext()->throwError(QStringLiteral("QQmlXMLHttpRequest: internal error: empty ActivationObject"));
+ v4->throwError(QStringLiteral("QQmlXMLHttpRequest: internal error: empty ActivationObject"));
return;
}
QQmlContextData *callingContext = QmlContextWrapper::getContext(activationObject);
if (callingContext) {
- QV4::ScopedCallData callData(scope, 0);
+ QV4::ScopedCallData callData(scope);
callData->thisObject = activationObject.asReturnedValue();
callback->call(callData);
}
@@ -1567,11 +1564,10 @@ void QQmlXMLHttpRequest::dispatchCallbackImpl(const ValueRef me)
void QQmlXMLHttpRequest::dispatchCallback(const ValueRef me)
{
- ExecutionContext *ctx = v4->currentContext();
dispatchCallbackImpl(me);
if (v4->hasException) {
- QQmlError error = QV4::ExecutionEngine::catchExceptionAsQmlError(ctx);
- QQmlEnginePrivate::warning(QQmlEnginePrivate::get(v4->v8Engine->engine()), error);
+ QQmlError error = v4->catchExceptionAsQmlError();
+ QQmlEnginePrivate::warning(QQmlEnginePrivate::get(v4->qmlEngine()), error);
}
}
@@ -1584,57 +1580,45 @@ void QQmlXMLHttpRequest::destroyNetwork()
}
}
+namespace QV4 {
+namespace Heap {
+
+struct QQmlXMLHttpRequestWrapper : Object {
+ QQmlXMLHttpRequestWrapper(ExecutionEngine *engine, QQmlXMLHttpRequest *request);
+ ~QQmlXMLHttpRequestWrapper() {
+ delete request;
+ }
+ QQmlXMLHttpRequest *request;
+};
+
+struct QQmlXMLHttpRequestCtor : FunctionObject {
+ QQmlXMLHttpRequestCtor(ExecutionEngine *engine);
+
+ Object *proto;
+};
+
+}
struct QQmlXMLHttpRequestWrapper : public Object
{
- struct Data : Object::Data {
- Data(ExecutionEngine *engine, QQmlXMLHttpRequest *request)
- : Object::Data(engine)
- , request(request)
- {
- setVTable(staticVTable());
- }
- ~Data() {
- delete request;
- }
- QQmlXMLHttpRequest *request;
- };
- V4_OBJECT(Object)
-
- static void destroy(Managed *that) {
- static_cast<QQmlXMLHttpRequestWrapper *>(that)->d()->~Data();
- }
+ V4_OBJECT2(QQmlXMLHttpRequestWrapper, Object)
+ V4_NEEDS_DESTROY
};
-DEFINE_OBJECT_VTABLE(QQmlXMLHttpRequestWrapper);
+Heap::QQmlXMLHttpRequestWrapper::QQmlXMLHttpRequestWrapper(ExecutionEngine *engine, QQmlXMLHttpRequest *request)
+ : Heap::Object(engine)
+ , request(request)
+{
+ setVTable(QV4::QQmlXMLHttpRequestWrapper::staticVTable());
+}
struct QQmlXMLHttpRequestCtor : public FunctionObject
{
- struct Data : FunctionObject::Data {
- Data(ExecutionEngine *engine)
- : FunctionObject::Data(engine->rootContext, QStringLiteral("XMLHttpRequest"))
- {
- setVTable(staticVTable());
- Scope scope(engine);
- Scoped<QQmlXMLHttpRequestCtor> ctor(scope, this);
-
- ctor->defineReadonlyProperty(QStringLiteral("UNSENT"), Primitive::fromInt32(0));
- ctor->defineReadonlyProperty(QStringLiteral("OPENED"), Primitive::fromInt32(1));
- ctor->defineReadonlyProperty(QStringLiteral("HEADERS_RECEIVED"), Primitive::fromInt32(2));
- ctor->defineReadonlyProperty(QStringLiteral("LOADING"), Primitive::fromInt32(3));
- ctor->defineReadonlyProperty(QStringLiteral("DONE"), Primitive::fromInt32(4));
- if (!ctor->d()->proto)
- ctor->setupProto();
- ScopedString s(scope, engine->id_prototype);
- ctor->defineDefaultProperty(s.getPointer(), ScopedObject(scope, ctor->d()->proto));
- }
- Object *proto;
- };
- V4_OBJECT(FunctionObject)
- static void markObjects(Managed *that, ExecutionEngine *e) {
- QQmlXMLHttpRequestCtor *c = static_cast<QQmlXMLHttpRequestCtor *>(that);
- if (c->d()->proto)
- c->d()->proto->mark(e);
+ V4_OBJECT2(QQmlXMLHttpRequestCtor, FunctionObject)
+ static void markObjects(Heap::Base *that, ExecutionEngine *e) {
+ QQmlXMLHttpRequestCtor::Data *c = static_cast<QQmlXMLHttpRequestCtor::Data *>(that);
+ if (c->proto)
+ c->proto->mark(e);
FunctionObject::markObjects(that, e);
}
static ReturnedValue construct(Managed *that, QV4::CallData *)
@@ -1642,12 +1626,12 @@ struct QQmlXMLHttpRequestCtor : public FunctionObject
Scope scope(that->engine());
Scoped<QQmlXMLHttpRequestCtor> ctor(scope, that->as<QQmlXMLHttpRequestCtor>());
if (!ctor)
- return that->engine()->currentContext()->throwTypeError();
+ return that->engine()->throwTypeError();
- QV8Engine *engine = that->engine()->v8Engine;
- QQmlXMLHttpRequest *r = new QQmlXMLHttpRequest(engine, engine->networkAccessManager());
+ QQmlXMLHttpRequest *r = new QQmlXMLHttpRequest(scope.engine, scope.engine->v8Engine->networkAccessManager());
Scoped<QQmlXMLHttpRequestWrapper> w(scope, that->engine()->memoryManager->alloc<QQmlXMLHttpRequestWrapper>(that->engine(), r));
- w->setPrototype(ctor->d()->proto);
+ ScopedObject proto(scope, ctor->d()->proto);
+ w->setPrototype(proto);
return w.asReturnedValue();
}
@@ -1671,36 +1655,58 @@ struct QQmlXMLHttpRequestCtor : public FunctionObject
static ReturnedValue method_get_responseXML(CallContext *ctx);
};
+}
+
+DEFINE_OBJECT_VTABLE(QQmlXMLHttpRequestWrapper);
+
+Heap::QQmlXMLHttpRequestCtor::QQmlXMLHttpRequestCtor(ExecutionEngine *engine)
+ : Heap::FunctionObject(engine->rootContext(), QStringLiteral("XMLHttpRequest"))
+{
+ setVTable(QV4::QQmlXMLHttpRequestCtor::staticVTable());
+ Scope scope(engine);
+ Scoped<QV4::QQmlXMLHttpRequestCtor> ctor(scope, this);
+
+ ctor->defineReadonlyProperty(QStringLiteral("UNSENT"), Primitive::fromInt32(0));
+ ctor->defineReadonlyProperty(QStringLiteral("OPENED"), Primitive::fromInt32(1));
+ ctor->defineReadonlyProperty(QStringLiteral("HEADERS_RECEIVED"), Primitive::fromInt32(2));
+ ctor->defineReadonlyProperty(QStringLiteral("LOADING"), Primitive::fromInt32(3));
+ ctor->defineReadonlyProperty(QStringLiteral("DONE"), Primitive::fromInt32(4));
+ if (!ctor->d()->proto)
+ ctor->setupProto();
+ ScopedString s(scope, engine->id_prototype);
+ ctor->defineDefaultProperty(s, ScopedObject(scope, ctor->d()->proto));
+}
+
DEFINE_OBJECT_VTABLE(QQmlXMLHttpRequestCtor);
void QQmlXMLHttpRequestCtor::setupProto()
{
ExecutionEngine *v4 = engine();
Scope scope(v4);
- Scoped<Object> p(scope, v4->newObject());
- d()->proto = p.getPointer();
+ ScopedObject p(scope, v4->newObject());
+ d()->proto = p->d();
// Methods
- d()->proto->defineDefaultProperty(QStringLiteral("open"), method_open);
- d()->proto->defineDefaultProperty(QStringLiteral("setRequestHeader"), method_setRequestHeader);
- d()->proto->defineDefaultProperty(QStringLiteral("send"), method_send);
- d()->proto->defineDefaultProperty(QStringLiteral("abort"), method_abort);
- d()->proto->defineDefaultProperty(QStringLiteral("getResponseHeader"), method_getResponseHeader);
- d()->proto->defineDefaultProperty(QStringLiteral("getAllResponseHeaders"), method_getAllResponseHeaders);
+ p->defineDefaultProperty(QStringLiteral("open"), method_open);
+ p->defineDefaultProperty(QStringLiteral("setRequestHeader"), method_setRequestHeader);
+ p->defineDefaultProperty(QStringLiteral("send"), method_send);
+ p->defineDefaultProperty(QStringLiteral("abort"), method_abort);
+ p->defineDefaultProperty(QStringLiteral("getResponseHeader"), method_getResponseHeader);
+ p->defineDefaultProperty(QStringLiteral("getAllResponseHeaders"), method_getAllResponseHeaders);
// Read-only properties
- d()->proto->defineAccessorProperty(QStringLiteral("readyState"), method_get_readyState, 0);
- d()->proto->defineAccessorProperty(QStringLiteral("status"),method_get_status, 0);
- d()->proto->defineAccessorProperty(QStringLiteral("statusText"),method_get_statusText, 0);
- d()->proto->defineAccessorProperty(QStringLiteral("responseText"),method_get_responseText, 0);
- d()->proto->defineAccessorProperty(QStringLiteral("responseXML"),method_get_responseXML, 0);
+ p->defineAccessorProperty(QStringLiteral("readyState"), method_get_readyState, 0);
+ p->defineAccessorProperty(QStringLiteral("status"),method_get_status, 0);
+ p->defineAccessorProperty(QStringLiteral("statusText"),method_get_statusText, 0);
+ p->defineAccessorProperty(QStringLiteral("responseText"),method_get_responseText, 0);
+ p->defineAccessorProperty(QStringLiteral("responseXML"),method_get_responseXML, 0);
// State values
- d()->proto->defineReadonlyProperty(QStringLiteral("UNSENT"), Primitive::fromInt32(0));
- d()->proto->defineReadonlyProperty(QStringLiteral("OPENED"), Primitive::fromInt32(1));
- d()->proto->defineReadonlyProperty(QStringLiteral("HEADERS_RECEIVED"), Primitive::fromInt32(2));
- d()->proto->defineReadonlyProperty(QStringLiteral("LOADING"), Primitive::fromInt32(3));
- d()->proto->defineReadonlyProperty(QStringLiteral("DONE"), Primitive::fromInt32(4));
+ p->defineReadonlyProperty(QStringLiteral("UNSENT"), Primitive::fromInt32(0));
+ p->defineReadonlyProperty(QStringLiteral("OPENED"), Primitive::fromInt32(1));
+ p->defineReadonlyProperty(QStringLiteral("HEADERS_RECEIVED"), Primitive::fromInt32(2));
+ p->defineReadonlyProperty(QStringLiteral("LOADING"), Primitive::fromInt32(3));
+ p->defineReadonlyProperty(QStringLiteral("DONE"), Primitive::fromInt32(4));
}
@@ -1716,26 +1722,27 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_open(CallContext *ctx)
if (ctx->d()->callData->argc < 2 || ctx->d()->callData->argc > 5)
V4THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Incorrect argument count");
- QV8Engine *engine = ctx->d()->engine->v8Engine;
-
// Argument 0 - Method
QString method = ctx->d()->callData->args[0].toQStringNoThrow().toUpper();
if (method != QLatin1String("GET") &&
method != QLatin1String("PUT") &&
method != QLatin1String("HEAD") &&
method != QLatin1String("POST") &&
- method != QLatin1String("DELETE"))
+ method != QLatin1String("DELETE") &&
+ method != QLatin1String("OPTIONS"))
V4THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Unsupported HTTP method type");
// Argument 1 - URL
QUrl url = QUrl(ctx->d()->callData->args[1].toQStringNoThrow());
if (url.isRelative())
- url = engine->callingContext()->resolvedUrl(url);
+ url = scope.engine->v8Engine->callingContext()->resolvedUrl(url);
+ bool async = true;
// Argument 2 - async (optional)
- if (ctx->d()->callData->argc > 2 && !ctx->d()->callData->args[2].booleanValue())
- V4THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "Synchronous XMLHttpRequest calls are not supported");
+ if (ctx->d()->callData->argc > 2) {
+ async = ctx->d()->callData->args[2].booleanValue();
+ }
// Argument 3/4 - user/pass (optional)
QString username, password;
@@ -1751,8 +1758,8 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_open(CallContext *ctx)
if (!username.isNull()) url.setUserName(username);
if (!password.isNull()) url.setPassword(password);
- ScopedValue meObject(scope, constructMeObject(ctx->d()->callData->thisObject, engine));
- return r->open(meObject, method, url);
+ ScopedValue meObject(scope, constructMeObject(ctx->d()->callData->thisObject, scope.engine));
+ return r->open(meObject, method, url, async ? QQmlXMLHttpRequest::AsynchronousLoad : QQmlXMLHttpRequest::SynchronousLoad);
}
ReturnedValue QQmlXMLHttpRequestCtor::method_setRequestHeader(CallContext *ctx)
@@ -1810,8 +1817,6 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_send(CallContext *ctx)
V4THROW_REFERENCE("Not an XMLHttpRequest object");
QQmlXMLHttpRequest *r = w->d()->request;
- QV8Engine *engine = ctx->d()->engine->v8Engine;
-
if (r->readyState() != QQmlXMLHttpRequest::Opened ||
r->sendFlag())
V4THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state");
@@ -1820,7 +1825,7 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_send(CallContext *ctx)
if (ctx->d()->callData->argc > 0)
data = ctx->d()->callData->args[0].toQStringNoThrow().toUtf8();
- ScopedValue meObject(scope, constructMeObject(ctx->d()->callData->thisObject, engine));
+ ScopedValue meObject(scope, constructMeObject(ctx->d()->callData->thisObject, scope.engine));
return r->send(meObject, data);
}
@@ -1832,7 +1837,7 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_abort(CallContext *ctx)
V4THROW_REFERENCE("Not an XMLHttpRequest object");
QQmlXMLHttpRequest *r = w->d()->request;
- ScopedValue meObject(scope, constructMeObject(ctx->d()->callData->thisObject, ctx->d()->engine->v8Engine));
+ ScopedValue meObject(scope, constructMeObject(ctx->d()->callData->thisObject, scope.engine));
return r->abort(meObject);
}
@@ -1844,8 +1849,6 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_getResponseHeader(CallContext *ctx)
V4THROW_REFERENCE("Not an XMLHttpRequest object");
QQmlXMLHttpRequest *r = w->d()->request;
- QV8Engine *engine = ctx->d()->engine->v8Engine;
-
if (ctx->d()->callData->argc != 1)
V4THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Incorrect argument count");
@@ -1854,7 +1857,7 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_getResponseHeader(CallContext *ctx)
r->readyState() != QQmlXMLHttpRequest::HeadersReceived)
V4THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state");
- return engine->toString(r->header(ctx->d()->callData->args[0].toQStringNoThrow()));
+ return QV4::Encode(scope.engine->newString(r->header(ctx->d()->callData->args[0].toQStringNoThrow())));
}
ReturnedValue QQmlXMLHttpRequestCtor::method_getAllResponseHeaders(CallContext *ctx)
@@ -1865,8 +1868,6 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_getAllResponseHeaders(CallContext *
V4THROW_REFERENCE("Not an XMLHttpRequest object");
QQmlXMLHttpRequest *r = w->d()->request;
- QV8Engine *engine = ctx->d()->engine->v8Engine;
-
if (ctx->d()->callData->argc != 0)
V4THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Incorrect argument count");
@@ -1875,7 +1876,7 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_getAllResponseHeaders(CallContext *
r->readyState() != QQmlXMLHttpRequest::HeadersReceived)
V4THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state");
- return engine->toString(r->headers());
+ return QV4::Encode(scope.engine->newString(r->headers()));
}
// XMLHttpRequest properties
@@ -1916,16 +1917,14 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_get_statusText(CallContext *ctx)
V4THROW_REFERENCE("Not an XMLHttpRequest object");
QQmlXMLHttpRequest *r = w->d()->request;
- QV8Engine *engine = ctx->d()->engine->v8Engine;
-
if (r->readyState() == QQmlXMLHttpRequest::Unsent ||
r->readyState() == QQmlXMLHttpRequest::Opened)
V4THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state");
if (r->errorFlag())
- return engine->toString(QString());
+ return QV4::Encode(scope.engine->newString(QString()));
else
- return engine->toString(r->replyStatusText());
+ return QV4::Encode(scope.engine->newString(r->replyStatusText()));
}
ReturnedValue QQmlXMLHttpRequestCtor::method_get_responseText(CallContext *ctx)
@@ -1936,13 +1935,11 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_get_responseText(CallContext *ctx)
V4THROW_REFERENCE("Not an XMLHttpRequest object");
QQmlXMLHttpRequest *r = w->d()->request;
- QV8Engine *engine = ctx->d()->engine->v8Engine;
-
if (r->readyState() != QQmlXMLHttpRequest::Loading &&
r->readyState() != QQmlXMLHttpRequest::Done)
- return engine->toString(QString());
+ return QV4::Encode(scope.engine->newString(QString()));
else
- return engine->toString(r->responseBody());
+ return QV4::Encode(scope.engine->newString(r->responseBody()));
}
ReturnedValue QQmlXMLHttpRequestCtor::method_get_responseXML(CallContext *ctx)
@@ -1958,24 +1955,23 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_get_responseXML(CallContext *ctx)
r->readyState() != QQmlXMLHttpRequest::Done)) {
return Encode::null();
} else {
- return Document::load(ctx->d()->engine->v8Engine, r->rawResponseBody());
+ return Document::load(scope.engine, r->rawResponseBody());
}
}
-void qt_rem_qmlxmlhttprequest(QV8Engine * /* engine */, void *d)
+void qt_rem_qmlxmlhttprequest(ExecutionEngine * /* engine */, void *d)
{
QQmlXMLHttpRequestData *data = (QQmlXMLHttpRequestData *)d;
delete data;
}
-void *qt_add_qmlxmlhttprequest(QV8Engine *engine)
+void *qt_add_qmlxmlhttprequest(ExecutionEngine *v4)
{
- ExecutionEngine *v4 = QV8Engine::getV4(engine);
Scope scope(v4);
Scoped<QQmlXMLHttpRequestCtor> ctor(scope, v4->memoryManager->alloc<QQmlXMLHttpRequestCtor>(v4));
ScopedString s(scope, v4->newString(QStringLiteral("XMLHttpRequest")));
- v4->globalObject->defineReadonlyProperty(s.getPointer(), ctor);
+ v4->globalObject()->defineReadonlyProperty(s, ctor);
QQmlXMLHttpRequestData *data = new QQmlXMLHttpRequestData;
return data;
diff --git a/src/qml/qml/qqmlxmlhttprequest_p.h b/src/qml/qml/qqmlxmlhttprequest_p.h
index a876c9381b..05f1b8b1f1 100644
--- a/src/qml/qml/qqmlxmlhttprequest_p.h
+++ b/src/qml/qml/qqmlxmlhttprequest_p.h
@@ -47,6 +47,7 @@
//
#include <QtCore/qglobal.h>
+#include <private/qqmlglobal_p.h>
#ifndef QT_NO_XMLSTREAMREADER
@@ -54,8 +55,8 @@ QT_BEGIN_NAMESPACE
class QV8Engine;
-void *qt_add_qmlxmlhttprequest(QV8Engine *engine);
-void qt_rem_qmlxmlhttprequest(QV8Engine *engine, void *);
+void *qt_add_qmlxmlhttprequest(QV4::ExecutionEngine *engine);
+void qt_rem_qmlxmlhttprequest(QV4::ExecutionEngine *engine, void *);
QT_END_NAMESPACE
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
index f222d59494..6cb7990dd6 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
@@ -78,10 +78,10 @@ struct StaticQtMetaObject : public QObject
{ return &staticQtMetaObject; }
};
-QV4::QtObject::Data::Data(ExecutionEngine *v4, QQmlEngine *qmlEngine)
- : Object::Data(v4)
+Heap::QtObject::QtObject(ExecutionEngine *v4, QQmlEngine *qmlEngine)
+ : Heap::Object(v4)
{
- setVTable(staticVTable());
+ setVTable(QV4::QtObject::staticVTable());
Scope scope(v4);
ScopedObject o(scope, this);
@@ -93,54 +93,54 @@ QV4::QtObject::Data::Data(ExecutionEngine *v4, QQmlEngine *qmlEngine)
for (int ii = 0; ii < qtMetaObject->enumeratorCount(); ++ii) {
QMetaEnum enumerator = qtMetaObject->enumerator(ii);
for (int jj = 0; jj < enumerator.keyCount(); ++jj) {
- o->put((str = v4->newString(QString::fromUtf8(enumerator.key(jj)))).getPointer(), (v = QV4::Primitive::fromInt32(enumerator.value(jj))));
+ o->put((str = v4->newString(QString::fromUtf8(enumerator.key(jj)))), (v = QV4::Primitive::fromInt32(enumerator.value(jj))));
}
}
- o->put((str = v4->newString(QStringLiteral("Asynchronous"))).getPointer(), (v = QV4::Primitive::fromInt32(0)));
- o->put((str = v4->newString(QStringLiteral("Synchronous"))).getPointer(), (v = QV4::Primitive::fromInt32(1)));
+ o->put((str = v4->newString(QStringLiteral("Asynchronous"))), (v = QV4::Primitive::fromInt32(0)));
+ o->put((str = v4->newString(QStringLiteral("Synchronous"))), (v = QV4::Primitive::fromInt32(1)));
o->defineDefaultProperty(QStringLiteral("include"), QV4Include::method_include);
- o->defineDefaultProperty(QStringLiteral("isQtObject"), method_isQtObject);
- o->defineDefaultProperty(QStringLiteral("rgba"), method_rgba);
- o->defineDefaultProperty(QStringLiteral("hsla"), method_hsla);
- o->defineDefaultProperty(QStringLiteral("colorEqual"), method_colorEqual);
- o->defineDefaultProperty(QStringLiteral("rect"), method_rect);
- o->defineDefaultProperty(QStringLiteral("point"), method_point);
- o->defineDefaultProperty(QStringLiteral("size"), method_size);
- o->defineDefaultProperty(QStringLiteral("font"), method_font);
-
- o->defineDefaultProperty(QStringLiteral("vector2d"), method_vector2d);
- o->defineDefaultProperty(QStringLiteral("vector3d"), method_vector3d);
- o->defineDefaultProperty(QStringLiteral("vector4d"), method_vector4d);
- o->defineDefaultProperty(QStringLiteral("quaternion"), method_quaternion);
- o->defineDefaultProperty(QStringLiteral("matrix4x4"), method_matrix4x4);
-
- o->defineDefaultProperty(QStringLiteral("formatDate"), method_formatDate);
- o->defineDefaultProperty(QStringLiteral("formatTime"), method_formatTime);
- o->defineDefaultProperty(QStringLiteral("formatDateTime"), method_formatDateTime);
-
- o->defineDefaultProperty(QStringLiteral("openUrlExternally"), method_openUrlExternally);
- o->defineDefaultProperty(QStringLiteral("fontFamilies"), method_fontFamilies);
- o->defineDefaultProperty(QStringLiteral("md5"), method_md5);
- o->defineDefaultProperty(QStringLiteral("btoa"), method_btoa);
- o->defineDefaultProperty(QStringLiteral("atob"), method_atob);
- o->defineDefaultProperty(QStringLiteral("resolvedUrl"), method_resolvedUrl);
- o->defineDefaultProperty(QStringLiteral("locale"), method_locale);
- o->defineDefaultProperty(QStringLiteral("binding"), method_binding);
+ o->defineDefaultProperty(QStringLiteral("isQtObject"), QV4::QtObject::method_isQtObject);
+ o->defineDefaultProperty(QStringLiteral("rgba"), QV4::QtObject::method_rgba);
+ o->defineDefaultProperty(QStringLiteral("hsla"), QV4::QtObject::method_hsla);
+ o->defineDefaultProperty(QStringLiteral("colorEqual"), QV4::QtObject::method_colorEqual);
+ o->defineDefaultProperty(QStringLiteral("rect"), QV4::QtObject::method_rect);
+ o->defineDefaultProperty(QStringLiteral("point"), QV4::QtObject::method_point);
+ o->defineDefaultProperty(QStringLiteral("size"), QV4::QtObject::method_size);
+ o->defineDefaultProperty(QStringLiteral("font"), QV4::QtObject::method_font);
+
+ o->defineDefaultProperty(QStringLiteral("vector2d"), QV4::QtObject::method_vector2d);
+ o->defineDefaultProperty(QStringLiteral("vector3d"), QV4::QtObject::method_vector3d);
+ o->defineDefaultProperty(QStringLiteral("vector4d"), QV4::QtObject::method_vector4d);
+ o->defineDefaultProperty(QStringLiteral("quaternion"), QV4::QtObject::method_quaternion);
+ o->defineDefaultProperty(QStringLiteral("matrix4x4"), QV4::QtObject::method_matrix4x4);
+
+ o->defineDefaultProperty(QStringLiteral("formatDate"), QV4::QtObject::method_formatDate);
+ o->defineDefaultProperty(QStringLiteral("formatTime"), QV4::QtObject::method_formatTime);
+ o->defineDefaultProperty(QStringLiteral("formatDateTime"), QV4::QtObject::method_formatDateTime);
+
+ o->defineDefaultProperty(QStringLiteral("openUrlExternally"), QV4::QtObject::method_openUrlExternally);
+ o->defineDefaultProperty(QStringLiteral("fontFamilies"), QV4::QtObject::method_fontFamilies);
+ o->defineDefaultProperty(QStringLiteral("md5"), QV4::QtObject::method_md5);
+ o->defineDefaultProperty(QStringLiteral("btoa"), QV4::QtObject::method_btoa);
+ o->defineDefaultProperty(QStringLiteral("atob"), QV4::QtObject::method_atob);
+ o->defineDefaultProperty(QStringLiteral("resolvedUrl"), QV4::QtObject::method_resolvedUrl);
+ o->defineDefaultProperty(QStringLiteral("locale"), QV4::QtObject::method_locale);
+ o->defineDefaultProperty(QStringLiteral("binding"), QV4::QtObject::method_binding);
if (qmlEngine) {
- o->defineDefaultProperty(QStringLiteral("lighter"), method_lighter);
- o->defineDefaultProperty(QStringLiteral("darker"), method_darker);
- o->defineDefaultProperty(QStringLiteral("tint"), method_tint);
- o->defineDefaultProperty(QStringLiteral("quit"), method_quit);
- o->defineDefaultProperty(QStringLiteral("createQmlObject"), method_createQmlObject);
- o->defineDefaultProperty(QStringLiteral("createComponent"), method_createComponent);
+ o->defineDefaultProperty(QStringLiteral("lighter"), QV4::QtObject::method_lighter);
+ o->defineDefaultProperty(QStringLiteral("darker"), QV4::QtObject::method_darker);
+ o->defineDefaultProperty(QStringLiteral("tint"), QV4::QtObject::method_tint);
+ o->defineDefaultProperty(QStringLiteral("quit"), QV4::QtObject::method_quit);
+ o->defineDefaultProperty(QStringLiteral("createQmlObject"), QV4::QtObject::method_createQmlObject);
+ o->defineDefaultProperty(QStringLiteral("createComponent"), QV4::QtObject::method_createComponent);
}
- o->defineAccessorProperty(QStringLiteral("platform"), method_get_platform, 0);
- o->defineAccessorProperty(QStringLiteral("application"), method_get_application, 0);
+ o->defineAccessorProperty(QStringLiteral("platform"), QV4::QtObject::method_get_platform, 0);
+ o->defineAccessorProperty(QStringLiteral("application"), QV4::QtObject::method_get_application, 0);
#ifndef QT_NO_IM
- o->defineAccessorProperty(QStringLiteral("inputMethod"), method_get_inputMethod, 0);
+ o->defineAccessorProperty(QStringLiteral("inputMethod"), QV4::QtObject::method_get_inputMethod, 0);
#endif
}
@@ -183,7 +183,7 @@ ReturnedValue QtObject::method_rgba(QV4::CallContext *ctx)
if (a < 0.0) a=0.0;
if (a > 1.0) a=1.0;
- return ctx->d()->engine->v8Engine->fromVariant(QQml_colorProvider()->fromRgbF(r, g, b, a));
+ return ctx->engine()->fromVariant(QQml_colorProvider()->fromRgbF(r, g, b, a));
}
/*!
@@ -212,7 +212,7 @@ ReturnedValue QtObject::method_hsla(QV4::CallContext *ctx)
if (a < 0.0) a=0.0;
if (a > 1.0) a=1.0;
- return ctx->d()->engine->v8Engine->fromVariant(QQml_colorProvider()->fromHslF(h, s, l, a));
+ return ctx->engine()->fromVariant(QQml_colorProvider()->fromHslF(h, s, l, a));
}
/*!
@@ -230,9 +230,7 @@ ReturnedValue QtObject::method_colorEqual(QV4::CallContext *ctx)
bool ok = false;
- QV8Engine *v8engine = ctx->d()->engine->v8Engine;
-
- QVariant lhs = v8engine->toVariant(ctx->d()->callData->args[0], -1);
+ QVariant lhs = ctx->d()->engine->toVariant(ctx->d()->callData->args[0], -1);
if (lhs.userType() == QVariant::String) {
lhs = QQmlStringConverters::colorFromString(lhs.toString(), &ok);
if (!ok) {
@@ -242,7 +240,7 @@ ReturnedValue QtObject::method_colorEqual(QV4::CallContext *ctx)
V4THROW_ERROR("Qt.colorEqual(): Invalid arguments");
}
- QVariant rhs = v8engine->toVariant(ctx->d()->callData->args[1], -1);
+ QVariant rhs = ctx->engine()->toVariant(ctx->d()->callData->args[1], -1);
if (rhs.userType() == QVariant::String) {
rhs = QQmlStringConverters::colorFromString(rhs.toString(), &ok);
if (!ok) {
@@ -273,7 +271,7 @@ ReturnedValue QtObject::method_rect(QV4::CallContext *ctx)
double w = ctx->d()->callData->args[2].toNumber();
double h = ctx->d()->callData->args[3].toNumber();
- return ctx->d()->engine->v8Engine->fromVariant(QVariant::fromValue(QRectF(x, y, w, h)));
+ return ctx->engine()->fromVariant(QVariant::fromValue(QRectF(x, y, w, h)));
}
/*!
@@ -288,7 +286,7 @@ ReturnedValue QtObject::method_point(QV4::CallContext *ctx)
double x = ctx->d()->callData->args[0].toNumber();
double y = ctx->d()->callData->args[1].toNumber();
- return ctx->d()->engine->v8Engine->fromVariant(QVariant::fromValue(QPointF(x, y)));
+ return ctx->engine()->fromVariant(QVariant::fromValue(QPointF(x, y)));
}
/*!
@@ -303,7 +301,7 @@ ReturnedValue QtObject::method_size(QV4::CallContext *ctx)
double w = ctx->d()->callData->args[0].toNumber();
double h = ctx->d()->callData->args[1].toNumber();
- return ctx->d()->engine->v8Engine->fromVariant(QVariant::fromValue(QSizeF(w, h)));
+ return ctx->engine()->fromVariant(QVariant::fromValue(QSizeF(w, h)));
}
/*!
@@ -319,12 +317,12 @@ ReturnedValue QtObject::method_font(QV4::CallContext *ctx)
if (ctx->d()->callData->argc != 1 || !ctx->d()->callData->args[0].isObject())
V4THROW_ERROR("Qt.font(): Invalid arguments");
- QV8Engine *v8engine = ctx->d()->engine->v8Engine;
+ QV4::ExecutionEngine *v4 = ctx->d()->engine;
bool ok = false;
- QVariant v = QQml_valueTypeProvider()->createVariantFromJsObject(QMetaType::QFont, QQmlV4Handle(ctx->d()->callData->args[0]), v8engine, &ok);
+ QVariant v = QQml_valueTypeProvider()->createVariantFromJsObject(QMetaType::QFont, QQmlV4Handle(ctx->d()->callData->args[0]), v4, &ok);
if (!ok)
V4THROW_ERROR("Qt.font(): Invalid argument: no valid font subproperties specified");
- return v8engine->fromVariant(v);
+ return ctx->engine()->fromVariant(v);
}
@@ -343,8 +341,7 @@ ReturnedValue QtObject::method_vector2d(QV4::CallContext *ctx)
xy[1] = ctx->d()->callData->args[1].toNumber();
const void *params[] = { xy };
- QV8Engine *v8engine = ctx->d()->engine->v8Engine;
- return v8engine->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QVector2D, 1, params));
+ return ctx->engine()->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QVector2D, 1, params));
}
/*!
@@ -362,8 +359,7 @@ ReturnedValue QtObject::method_vector3d(QV4::CallContext *ctx)
xyz[2] = ctx->d()->callData->args[2].toNumber();
const void *params[] = { xyz };
- QV8Engine *v8engine = ctx->d()->engine->v8Engine;
- return v8engine->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QVector3D, 1, params));
+ return ctx->engine()->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QVector3D, 1, params));
}
/*!
@@ -382,8 +378,7 @@ ReturnedValue QtObject::method_vector4d(QV4::CallContext *ctx)
xyzw[3] = ctx->d()->callData->args[3].toNumber();
const void *params[] = { xyzw };
- QV8Engine *v8engine = ctx->d()->engine->v8Engine;
- return v8engine->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QVector4D, 1, params));
+ return ctx->engine()->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QVector4D, 1, params));
}
/*!
@@ -402,8 +397,7 @@ ReturnedValue QtObject::method_quaternion(QV4::CallContext *ctx)
sxyz[3] = ctx->d()->callData->args[3].toNumber();
const void *params[] = { sxyz };
- QV8Engine *v8engine = ctx->d()->engine->v8Engine;
- return v8engine->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QQuaternion, 1, params));
+ return ctx->engine()->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QQuaternion, 1, params));
}
/*!
@@ -415,14 +409,14 @@ matrix values.
*/
ReturnedValue QtObject::method_matrix4x4(QV4::CallContext *ctx)
{
- QV8Engine *v8engine = ctx->d()->engine->v8Engine;
+ QV4::ExecutionEngine *v4 = ctx->d()->engine;
if (ctx->d()->callData->argc == 1 && ctx->d()->callData->args[0].isObject()) {
bool ok = false;
- QVariant v = QQml_valueTypeProvider()->createVariantFromJsObject(QMetaType::QMatrix4x4, QQmlV4Handle(ctx->d()->callData->args[0]), v8engine, &ok);
+ QVariant v = QQml_valueTypeProvider()->createVariantFromJsObject(QMetaType::QMatrix4x4, QQmlV4Handle(ctx->d()->callData->args[0]), v4, &ok);
if (!ok)
V4THROW_ERROR("Qt.matrix4x4(): Invalid argument: not a valid matrix4x4 values array");
- return v8engine->fromVariant(v);
+ return ctx->engine()->fromVariant(v);
}
if (ctx->d()->callData->argc != 16)
@@ -447,7 +441,7 @@ ReturnedValue QtObject::method_matrix4x4(QV4::CallContext *ctx)
vals[15] = ctx->d()->callData->args[15].toNumber();
const void *params[] = { vals };
- return v8engine->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QMatrix4x4, 1, params));
+ return ctx->engine()->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QMatrix4x4, 1, params));
}
/*!
@@ -469,8 +463,7 @@ ReturnedValue QtObject::method_lighter(QV4::CallContext *ctx)
if (ctx->d()->callData->argc != 1 && ctx->d()->callData->argc != 2)
V4THROW_ERROR("Qt.lighter(): Invalid arguments");
- QV8Engine *v8engine = ctx->d()->engine->v8Engine;
- QVariant v = v8engine->toVariant(ctx->d()->callData->args[0], -1);
+ QVariant v = ctx->engine()->toVariant(ctx->d()->callData->args[0], -1);
if (v.userType() == QVariant::String) {
bool ok = false;
v = QQmlStringConverters::colorFromString(v.toString(), &ok);
@@ -485,7 +478,7 @@ ReturnedValue QtObject::method_lighter(QV4::CallContext *ctx)
if (ctx->d()->callData->argc == 2)
factor = ctx->d()->callData->args[1].toNumber();
- return v8engine->fromVariant(QQml_colorProvider()->lighter(v, factor));
+ return ctx->engine()->fromVariant(QQml_colorProvider()->lighter(v, factor));
}
/*!
@@ -508,8 +501,7 @@ ReturnedValue QtObject::method_darker(QV4::CallContext *ctx)
if (ctx->d()->callData->argc != 1 && ctx->d()->callData->argc != 2)
V4THROW_ERROR("Qt.darker(): Invalid arguments");
- QV8Engine *v8engine = ctx->d()->engine->v8Engine;
- QVariant v = v8engine->toVariant(ctx->d()->callData->args[0], -1);
+ QVariant v = ctx->engine()->toVariant(ctx->d()->callData->args[0], -1);
if (v.userType() == QVariant::String) {
bool ok = false;
v = QQmlStringConverters::colorFromString(v.toString(), &ok);
@@ -524,7 +516,7 @@ ReturnedValue QtObject::method_darker(QV4::CallContext *ctx)
if (ctx->d()->callData->argc == 2)
factor = ctx->d()->callData->args[1].toNumber();
- return v8engine->fromVariant(QQml_colorProvider()->darker(v, factor));
+ return ctx->engine()->fromVariant(QQml_colorProvider()->darker(v, factor));
}
/*!
@@ -556,10 +548,8 @@ ReturnedValue QtObject::method_tint(QV4::CallContext *ctx)
if (ctx->d()->callData->argc != 2)
V4THROW_ERROR("Qt.tint(): Invalid arguments");
- QV8Engine *v8engine = ctx->d()->engine->v8Engine;
-
// base color
- QVariant v1 = v8engine->toVariant(ctx->d()->callData->args[0], -1);
+ QVariant v1 = ctx->engine()->toVariant(ctx->d()->callData->args[0], -1);
if (v1.userType() == QVariant::String) {
bool ok = false;
v1 = QQmlStringConverters::colorFromString(v1.toString(), &ok);
@@ -571,7 +561,7 @@ ReturnedValue QtObject::method_tint(QV4::CallContext *ctx)
}
// tint color
- QVariant v2 = v8engine->toVariant(ctx->d()->callData->args[1], -1);
+ QVariant v2 = ctx->engine()->toVariant(ctx->d()->callData->args[1], -1);
if (v2.userType() == QVariant::String) {
bool ok = false;
v2 = QQmlStringConverters::colorFromString(v2.toString(), &ok);
@@ -582,7 +572,7 @@ ReturnedValue QtObject::method_tint(QV4::CallContext *ctx)
return QV4::Encode::null();
}
- return v8engine->fromVariant(QQml_colorProvider()->tint(v1, v2));
+ return ctx->engine()->fromVariant(QQml_colorProvider()->tint(v1, v2));
}
/*!
@@ -607,10 +597,8 @@ ReturnedValue QtObject::method_formatDate(QV4::CallContext *ctx)
V4THROW_ERROR("Qt.formatDate(): Invalid arguments");
QV4::Scope scope(ctx);
- QV8Engine *v8engine = ctx->d()->engine->v8Engine;
-
Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate;
- QDate date = v8engine->toVariant(ctx->d()->callData->args[0], -1).toDateTime().date();
+ QDate date = ctx->engine()->toVariant(ctx->d()->callData->args[0], -1).toDateTime().date();
QString formattedDate;
if (ctx->d()->callData->argc == 2) {
QV4::ScopedString s(scope, ctx->d()->callData->args[1]);
@@ -652,9 +640,7 @@ ReturnedValue QtObject::method_formatTime(QV4::CallContext *ctx)
V4THROW_ERROR("Qt.formatTime(): Invalid arguments");
QV4::Scope scope(ctx);
- QV8Engine *v8engine = ctx->d()->engine->v8Engine;
-
- QVariant argVariant = v8engine->toVariant(ctx->d()->callData->args[0], -1);
+ QVariant argVariant = ctx->engine()->toVariant(ctx->d()->callData->args[0], -1);
QTime time;
if (ctx->d()->callData->args[0].asDateObject() || (argVariant.type() == QVariant::String))
time = argVariant.toDateTime().time();
@@ -778,10 +764,8 @@ ReturnedValue QtObject::method_formatDateTime(QV4::CallContext *ctx)
V4THROW_ERROR("Qt.formatDateTime(): Invalid arguments");
QV4::Scope scope(ctx);
- QV8Engine *v8engine = ctx->d()->engine->v8Engine;
-
Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate;
- QDateTime dt = v8engine->toVariant(ctx->d()->callData->args[0], -1).toDateTime();
+ QDateTime dt = ctx->engine()->toVariant(ctx->d()->callData->args[0], -1).toDateTime();
QString formattedDt;
if (ctx->d()->callData->argc == 2) {
QV4::ScopedString s(scope, ctx->d()->callData->args[1]);
@@ -811,10 +795,8 @@ ReturnedValue QtObject::method_openUrlExternally(QV4::CallContext *ctx)
if (ctx->d()->callData->argc != 1)
return QV4::Encode(false);
- QV8Engine *v8engine = ctx->d()->engine->v8Engine;
-
QUrl url(Value::fromReturnedValue(method_resolvedUrl(ctx)).toQStringNoThrow());
- return v8engine->fromVariant(QQml_guiProvider()->openUrlExternally(url));
+ return ctx->engine()->fromVariant(QQml_guiProvider()->openUrlExternally(url));
}
/*!
@@ -825,7 +807,7 @@ ReturnedValue QtObject::method_resolvedUrl(QV4::CallContext *ctx)
{
QV8Engine *v8engine = ctx->d()->engine->v8Engine;
- QUrl url = v8engine->toVariant(ctx->d()->callData->args[0], -1).toUrl();
+ QUrl url = ctx->engine()->toVariant(ctx->d()->callData->args[0], -1).toUrl();
QQmlEngine *e = v8engine->engine();
QQmlEnginePrivate *p = 0;
if (e) p = QQmlEnginePrivate::get(e);
@@ -849,8 +831,7 @@ ReturnedValue QtObject::method_fontFamilies(CallContext *ctx)
if (ctx->d()->callData->argc != 0)
V4THROW_ERROR("Qt.fontFamilies(): Invalid arguments");
- QV8Engine *v8engine = ctx->d()->engine->v8Engine;
- return v8engine->fromVariant(QVariant(QQml_guiProvider()->fontFamilies()));
+ return ctx->engine()->fromVariant(QVariant(QQml_guiProvider()->fontFamilies()));
}
/*!
@@ -904,9 +885,7 @@ QQmlEngine::quit() signal to the QCoreApplication::quit() slot.
*/
ReturnedValue QtObject::method_quit(CallContext *ctx)
{
- QV8Engine *v8engine = ctx->d()->engine->v8Engine;
-
- QQmlEnginePrivate::get(v8engine->engine())->sendQuit();
+ QQmlEnginePrivate::get(ctx->engine()->qmlEngine())->sendQuit();
return QV4::Encode::undefined();
}
@@ -945,7 +924,7 @@ ReturnedValue QtObject::method_createQmlObject(CallContext *ctx)
Scope scope(v4);
QString errorstr = QLatin1String("Qt.createQmlObject(): failed to create object: ");
- QV4::Scoped<ArrayObject> qmlerrors(scope, v4->newArrayObject());
+ QV4::ScopedArrayObject qmlerrors(scope, v4->newArrayObject());
QV4::ScopedObject qmlerror(scope);
QV4::ScopedString s(scope);
QV4::ScopedValue v(scope);
@@ -953,16 +932,16 @@ ReturnedValue QtObject::method_createQmlObject(CallContext *ctx)
const QQmlError &error = errors.at(ii);
errorstr += QLatin1String("\n ") + error.toString();
qmlerror = v4->newObject();
- qmlerror->put((s = v4->newString(QStringLiteral("lineNumber"))).getPointer(), (v = QV4::Primitive::fromInt32(error.line())));
- qmlerror->put((s = v4->newString(QStringLiteral("columnNumber"))).getPointer(), (v = QV4::Primitive::fromInt32(error.column())));
- qmlerror->put((s = v4->newString(QStringLiteral("fileName"))).getPointer(), (v = v4->newString(error.url().toString())));
- qmlerror->put((s = v4->newString(QStringLiteral("message"))).getPointer(), (v = v4->newString(error.description())));
+ qmlerror->put((s = v4->newString(QStringLiteral("lineNumber"))), (v = QV4::Primitive::fromInt32(error.line())));
+ qmlerror->put((s = v4->newString(QStringLiteral("columnNumber"))), (v = QV4::Primitive::fromInt32(error.column())));
+ qmlerror->put((s = v4->newString(QStringLiteral("fileName"))), (v = v4->newString(error.url().toString())));
+ qmlerror->put((s = v4->newString(QStringLiteral("message"))), (v = v4->newString(error.description())));
qmlerrors->putIndexed(ii, qmlerror);
}
v = v4->newString(errorstr);
- Scoped<Object> errorObject(scope, v4->newErrorObject(v));
- errorObject->put((s = v4->newString(QStringLiteral("qmlErrors"))).getPointer(), qmlerrors);
+ ScopedObject errorObject(scope, v4->newErrorObject(v));
+ errorObject->put((s = v4->newString(QStringLiteral("qmlErrors"))), qmlerrors);
return errorObject.asReturnedValue();
}
};
@@ -1004,7 +983,7 @@ ReturnedValue QtObject::method_createQmlObject(CallContext *ctx)
if (component.isError()) {
ScopedValue v(scope, Error::create(ctx->d()->engine, component.errors()));
- return ctx->throwError(v);
+ return ctx->engine()->throwError(v);
}
if (!component.isReady())
@@ -1028,7 +1007,7 @@ ReturnedValue QtObject::method_createQmlObject(CallContext *ctx)
if (component.isError()) {
ScopedValue v(scope, Error::create(ctx->d()->engine, component.errors()));
- return ctx->throwError(v);
+ return ctx->engine()->throwError(v);
}
Q_ASSERT(obj);
@@ -1070,7 +1049,7 @@ use \l{QtQml::Qt::createQmlObject()}{Qt.createQmlObject()}.
ReturnedValue QtObject::method_createComponent(CallContext *ctx)
{
if (ctx->d()->callData->argc < 1 || ctx->d()->callData->argc > 3)
- return ctx->throwError(QStringLiteral("Qt.createComponent(): Invalid arguments"));
+ return ctx->engine()->throwError(QStringLiteral("Qt.createComponent(): Invalid arguments"));
Scope scope(ctx);
@@ -1098,13 +1077,13 @@ ReturnedValue QtObject::method_createComponent(CallContext *ctx)
if (ctx->d()->callData->args[1].isInteger()) {
int mode = ctx->d()->callData->args[1].integerValue();
if (mode != int(QQmlComponent::PreferSynchronous) && mode != int(QQmlComponent::Asynchronous))
- return ctx->throwError(QStringLiteral("Qt.createComponent(): Invalid arguments"));
+ return ctx->engine()->throwError(QStringLiteral("Qt.createComponent(): Invalid arguments"));
compileMode = QQmlComponent::CompilationMode(mode);
consumedCount += 1;
} else {
// The second argument could be the parent only if there are exactly two args
if ((ctx->d()->callData->argc != 2) || !(lastArg->isObject() || lastArg->isNull()))
- return ctx->throwError(QStringLiteral("Qt.createComponent(): Invalid arguments"));
+ return ctx->engine()->throwError(QStringLiteral("Qt.createComponent(): Invalid arguments"));
}
if (consumedCount < ctx->d()->callData->argc) {
@@ -1113,11 +1092,11 @@ ReturnedValue QtObject::method_createComponent(CallContext *ctx)
if (qobjectWrapper)
parentArg = qobjectWrapper->object();
if (!parentArg)
- return ctx->throwError(QStringLiteral("Qt.createComponent(): Invalid parent object"));
+ return ctx->engine()->throwError(QStringLiteral("Qt.createComponent(): Invalid parent object"));
} else if (lastArg->isNull()) {
parentArg = 0;
} else {
- return ctx->throwError(QStringLiteral("Qt.createComponent(): Invalid parent object"));
+ return ctx->engine()->throwError(QStringLiteral("Qt.createComponent(): Invalid parent object"));
}
}
}
@@ -1159,19 +1138,17 @@ ReturnedValue QtObject::method_locale(CallContext *ctx)
if (ctx->d()->callData->argc == 1 && !ctx->d()->callData->args[0].isString())
V4THROW_TYPE("locale(): argument (locale code) must be a string");
- QV8Engine *v8engine = ctx->d()->engine->v8Engine;
if (ctx->d()->callData->argc == 1)
code = ctx->d()->callData->args[0].toQStringNoThrow();
- return QQmlLocale::locale(v8engine, code);
+ return QQmlLocale::locale(ctx->engine(), code);
}
-QQmlBindingFunction::Data::Data(FunctionObject *originalFunction)
- : QV4::FunctionObject::Data(originalFunction->scope(), originalFunction->name())
- , originalFunction(originalFunction)
+Heap::QQmlBindingFunction::QQmlBindingFunction(QV4::FunctionObject *originalFunction)
+ : QV4::Heap::FunctionObject(originalFunction->scope(), originalFunction->name())
+ , originalFunction(originalFunction->d())
{
- setVTable(staticVTable());
- bindingKeyFlag = true;
+ setVTable(QV4::QQmlBindingFunction::staticVTable());
}
void QQmlBindingFunction::initBindingLocation()
@@ -1183,14 +1160,15 @@ void QQmlBindingFunction::initBindingLocation()
ReturnedValue QQmlBindingFunction::call(Managed *that, CallData *callData)
{
- QQmlBindingFunction *This = static_cast<QQmlBindingFunction*>(that);
- return This->d()->originalFunction->call(callData);
+ Scope scope(that->engine());
+ ScopedFunctionObject function(scope, static_cast<QQmlBindingFunction*>(that)->d()->originalFunction);
+ return function->call(callData);
}
-void QQmlBindingFunction::markObjects(Managed *that, ExecutionEngine *e)
+void QQmlBindingFunction::markObjects(Heap::Base *that, ExecutionEngine *e)
{
- QQmlBindingFunction *This = static_cast<QQmlBindingFunction*>(that);
- This->d()->originalFunction->mark(e);
+ QQmlBindingFunction::Data *This = static_cast<QQmlBindingFunction::Data *>(that);
+ This->originalFunction->mark(e);
QV4::FunctionObject::markObjects(that, e);
}
@@ -1257,14 +1235,14 @@ ReturnedValue QtObject::method_get_platform(CallContext *ctx)
// ### inefficient. Should be just a value based getter
Object *o = ctx->d()->callData->thisObject.asObject();
if (!o)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
QtObject *qt = o->as<QtObject>();
if (!qt)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
if (!qt->d()->platform)
// Only allocate a platform object once
- qt->d()->platform = new QQmlPlatform(ctx->d()->engine->v8Engine->publicEngine());
+ qt->d()->platform = new QQmlPlatform(ctx->d()->engine->jsEngine());
return QV4::QObjectWrapper::wrap(ctx->d()->engine, qt->d()->platform);
}
@@ -1274,14 +1252,14 @@ ReturnedValue QtObject::method_get_application(CallContext *ctx)
// ### inefficient. Should be just a value based getter
Object *o = ctx->d()->callData->thisObject.asObject();
if (!o)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
QtObject *qt = o->as<QtObject>();
if (!qt)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
if (!qt->d()->application)
// Only allocate an application object once
- qt->d()->application = QQml_guiProvider()->application(ctx->d()->engine->v8Engine->publicEngine());
+ qt->d()->application = QQml_guiProvider()->application(ctx->d()->engine->jsEngine());
return QV4::QObjectWrapper::wrap(ctx->d()->engine, qt->d()->application);
}
@@ -1296,26 +1274,26 @@ ReturnedValue QtObject::method_get_inputMethod(CallContext *ctx)
#endif
-QV4::ConsoleObject::Data::Data(ExecutionEngine *v4)
- : Object::Data(v4)
+QV4::Heap::ConsoleObject::ConsoleObject(ExecutionEngine *v4)
+ : Heap::Object(v4)
{
QV4::Scope scope(v4);
QV4::ScopedObject o(scope, this);
- o->defineDefaultProperty(QStringLiteral("debug"), method_log);
- o->defineDefaultProperty(QStringLiteral("log"), method_log);
- o->defineDefaultProperty(QStringLiteral("info"), method_log);
- o->defineDefaultProperty(QStringLiteral("warn"), method_warn);
- o->defineDefaultProperty(QStringLiteral("error"), method_error);
- o->defineDefaultProperty(QStringLiteral("assert"), method_assert);
-
- o->defineDefaultProperty(QStringLiteral("count"), method_count);
- o->defineDefaultProperty(QStringLiteral("profile"), method_profile);
- o->defineDefaultProperty(QStringLiteral("profileEnd"), method_profileEnd);
- o->defineDefaultProperty(QStringLiteral("time"), method_time);
- o->defineDefaultProperty(QStringLiteral("timeEnd"), method_timeEnd);
- o->defineDefaultProperty(QStringLiteral("trace"), method_trace);
- o->defineDefaultProperty(QStringLiteral("exception"), method_exception);
+ o->defineDefaultProperty(QStringLiteral("debug"), QV4::ConsoleObject::method_log);
+ o->defineDefaultProperty(QStringLiteral("log"), QV4::ConsoleObject::method_log);
+ o->defineDefaultProperty(QStringLiteral("info"), QV4::ConsoleObject::method_log);
+ o->defineDefaultProperty(QStringLiteral("warn"), QV4::ConsoleObject::method_warn);
+ o->defineDefaultProperty(QStringLiteral("error"), QV4::ConsoleObject::method_error);
+ o->defineDefaultProperty(QStringLiteral("assert"), QV4::ConsoleObject::method_assert);
+
+ o->defineDefaultProperty(QStringLiteral("count"), QV4::ConsoleObject::method_count);
+ o->defineDefaultProperty(QStringLiteral("profile"), QV4::ConsoleObject::method_profile);
+ o->defineDefaultProperty(QStringLiteral("profileEnd"), QV4::ConsoleObject::method_profileEnd);
+ o->defineDefaultProperty(QStringLiteral("time"), QV4::ConsoleObject::method_time);
+ o->defineDefaultProperty(QStringLiteral("timeEnd"), QV4::ConsoleObject::method_timeEnd);
+ o->defineDefaultProperty(QStringLiteral("trace"), QV4::ConsoleObject::method_trace);
+ o->defineDefaultProperty(QStringLiteral("exception"), QV4::ConsoleObject::method_exception);
}
@@ -1423,7 +1401,7 @@ QV4::ReturnedValue ConsoleObject::method_profile(CallContext *ctx)
if (!QQmlDebugService::isDebuggingEnabled()) {
logger.warning("Cannot start profiling because debug service is disabled. Start with -qmljsdebugger=port:XXXXX.");
} else {
- QQmlProfilerService::instance()->startProfiling(v4->v8Engine->engine());
+ QQmlProfilerService::instance()->startProfiling(v4->qmlEngine());
logger.debug("Profiling started.");
}
@@ -1442,7 +1420,7 @@ QV4::ReturnedValue ConsoleObject::method_profileEnd(CallContext *ctx)
if (!QQmlDebugService::isDebuggingEnabled()) {
logger.warning("Ignoring console.profileEnd(): the debug service is disabled.");
} else {
- QQmlProfilerService::instance()->stopProfiling(v4->v8Engine->engine());
+ QQmlProfilerService::instance()->stopProfiling(v4->qmlEngine());
logger.debug("Profiling ended.");
}
@@ -1586,7 +1564,7 @@ void QV4::GlobalExtensions::init(QQmlEngine *qmlEngine, Object *globalObject)
globalObject->defineDefaultProperty(QStringLiteral("Qt"), qt);
// string prototype extension
- v4->stringObjectClass->prototype->defineDefaultProperty(QStringLiteral("arg"), method_string_arg);
+ v4->stringPrototype.asObject()->defineDefaultProperty(QStringLiteral("arg"), method_string_arg);
}
@@ -1699,6 +1677,7 @@ ReturnedValue GlobalExtensions::method_qsTr(CallContext *ctx)
if ((ctx->d()->callData->argc > 2) && !ctx->d()->callData->args[2].isNumber())
V4THROW_ERROR("qsTr(): third argument (n) must be a number");
+ Scope scope(ctx);
QV8Engine *v8engine = ctx->d()->engine->v8Engine;
QString context;
if (QQmlContextData *ctxt = v8engine->callingContext()) {
@@ -1707,7 +1686,8 @@ ReturnedValue GlobalExtensions::method_qsTr(CallContext *ctx)
int lastDot = path.lastIndexOf(QLatin1Char('.'));
int length = lastDot - (lastSlash + 1);
context = (lastSlash > -1) ? path.mid(lastSlash + 1, (length > -1) ? length : -1) : QString();
- } else if (QV4::ExecutionContext *parentCtx = ctx->d()->parent) {
+ } else if (ctx->d()->parent) {
+ ScopedContext parentCtx(scope, ctx->d()->parent);
// The first non-empty source URL in the call stack determines the translation context.
while (parentCtx && context.isEmpty()) {
if (QV4::CompiledData::CompilationUnit *unit = parentCtx->d()->compilationUnit) {
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
index f7728aa120..57fd290aef 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
@@ -55,15 +55,30 @@ class QV8Engine;
namespace QV4 {
+namespace Heap {
+
+struct QtObject : Object {
+ QtObject(ExecutionEngine *v4, QQmlEngine *qmlEngine);
+ QObject *platform;
+ QObject *application;
+};
+
+struct ConsoleObject : Object {
+ ConsoleObject(ExecutionEngine *engine);
+};
+
+struct QQmlBindingFunction : FunctionObject {
+ QQmlBindingFunction(QV4::FunctionObject *originalFunction);
+ FunctionObject *originalFunction;
+ // Set when the binding is created later
+ QQmlSourceLocation bindingLocation;
+};
+
+}
+
struct QtObject : Object
{
- struct Data : Object::Data {
- Data(ExecutionEngine *v4, QQmlEngine *qmlEngine);
- QObject *platform;
- QObject *application;
- };
- V4_OBJECT(Object)
-
+ V4_OBJECT2(QtObject, Object)
static ReturnedValue method_isQtObject(CallContext *ctx);
static ReturnedValue method_rgba(CallContext *ctx);
@@ -105,9 +120,9 @@ struct QtObject : Object
struct ConsoleObject : Object
{
- struct Data : Object::Data {
- Data(ExecutionEngine *engine);
- };
+ typedef Heap::ConsoleObject Data;
+ const Data *d() const { return static_cast<const Data *>(Object::d()); }
+ Data *d() { return static_cast<Data *>(Object::d()); }
static ReturnedValue method_error(CallContext *ctx);
static ReturnedValue method_log(CallContext *ctx);
@@ -143,23 +158,14 @@ struct GlobalExtensions {
struct QQmlBindingFunction : public QV4::FunctionObject
{
- struct Data : FunctionObject::Data {
- Data(FunctionObject *originalFunction);
- QV4::FunctionObject *originalFunction;
- // Set when the binding is created later
- QQmlSourceLocation bindingLocation;
- };
- V4_OBJECT(QV4::FunctionObject)
+ V4_OBJECT2(QQmlBindingFunction, FunctionObject)
+ V4_NEEDS_DESTROY
void initBindingLocation(); // from caller stack trace
static ReturnedValue call(Managed *that, CallData *callData);
- static void markObjects(Managed *that, ExecutionEngine *e);
- static void destroy(Managed *that) {
- static_cast<QQmlBindingFunction *>(that)->d()->~Data();
- }
-
+ static void markObjects(Heap::Base *that, ExecutionEngine *e);
};
}
diff --git a/src/qml/qml/v8/qv4domerrors.cpp b/src/qml/qml/v8/qv4domerrors.cpp
index cc7a6546f9..16359285a4 100644
--- a/src/qml/qml/v8/qv4domerrors.cpp
+++ b/src/qml/qml/v8/qv4domerrors.cpp
@@ -41,7 +41,7 @@ using namespace QV4;
void qt_add_domexceptions(ExecutionEngine *e)
{
Scope scope(e);
- Scoped<Object> domexception(scope, e->newObject());
+ ScopedObject domexception(scope, e->newObject());
domexception->defineReadonlyProperty(QStringLiteral("INDEX_SIZE_ERR"), Primitive::fromInt32(DOMEXCEPTION_INDEX_SIZE_ERR));
domexception->defineReadonlyProperty(QStringLiteral("DOMSTRING_SIZE_ERR"), Primitive::fromInt32(DOMEXCEPTION_DOMSTRING_SIZE_ERR));
domexception->defineReadonlyProperty(QStringLiteral("HIERARCHY_REQUEST_ERR"), Primitive::fromInt32(DOMEXCEPTION_HIERARCHY_REQUEST_ERR));
@@ -59,7 +59,7 @@ void qt_add_domexceptions(ExecutionEngine *e)
domexception->defineReadonlyProperty(QStringLiteral("INVALID_ACCESS_ERR"), Primitive::fromInt32(DOMEXCEPTION_INVALID_ACCESS_ERR));
domexception->defineReadonlyProperty(QStringLiteral("VALIDATION_ERR"), Primitive::fromInt32(DOMEXCEPTION_VALIDATION_ERR));
domexception->defineReadonlyProperty(QStringLiteral("TYPE_MISMATCH_ERR"), Primitive::fromInt32(DOMEXCEPTION_TYPE_MISMATCH_ERR));
- e->globalObject->defineDefaultProperty(QStringLiteral("DOMException"), domexception);
+ e->globalObject()->defineDefaultProperty(QStringLiteral("DOMException"), domexception);
}
QT_END_NAMESPACE
diff --git a/src/qml/qml/v8/qv4domerrors_p.h b/src/qml/qml/v8/qv4domerrors_p.h
index 59ed744f5e..dfa1675ee6 100644
--- a/src/qml/qml/v8/qv4domerrors_p.h
+++ b/src/qml/qml/v8/qv4domerrors_p.h
@@ -70,9 +70,9 @@ QT_BEGIN_NAMESPACE
#define V4THROW_DOM(error, string) { \
QV4::ScopedValue v(scope, scope.engine->newString(QStringLiteral(string))); \
- QV4::Scoped<Object> ex(scope, scope.engine->newErrorObject(v)); \
- ex->put(QV4::ScopedString(scope, scope.engine->newIdentifier(QStringLiteral("code"))).getPointer(), QV4::ScopedValue(scope, QV4::Primitive::fromInt32(error))); \
- return ctx->throwError(ex); \
+ QV4::ScopedObject ex(scope, scope.engine->newErrorObject(v)); \
+ ex->put(QV4::ScopedString(scope, scope.engine->newIdentifier(QStringLiteral("code"))), QV4::ScopedValue(scope, QV4::Primitive::fromInt32(error))); \
+ return ctx->engine()->throwError(ex); \
}
namespace QV4 {
diff --git a/src/qml/qml/v8/qv4sqlerrors.cpp b/src/qml/qml/v8/qv4sqlerrors.cpp
index e8e0462b6e..795ab5fb47 100644
--- a/src/qml/qml/v8/qv4sqlerrors.cpp
+++ b/src/qml/qml/v8/qv4sqlerrors.cpp
@@ -42,7 +42,7 @@ using namespace QV4;
void qt_add_sqlexceptions(QV4::ExecutionEngine *engine)
{
Scope scope(engine);
- Scoped<Object> sqlexception(scope, engine->newObject());
+ ScopedObject sqlexception(scope, engine->newObject());
sqlexception->defineReadonlyProperty(QStringLiteral("UNKNOWN_ERR"), Primitive::fromInt32(SQLEXCEPTION_UNKNOWN_ERR));
sqlexception->defineReadonlyProperty(QStringLiteral("DATABASE_ERR"), Primitive::fromInt32(SQLEXCEPTION_DATABASE_ERR));
sqlexception->defineReadonlyProperty(QStringLiteral("VERSION_ERR"), Primitive::fromInt32(SQLEXCEPTION_VERSION_ERR));
@@ -51,7 +51,7 @@ void qt_add_sqlexceptions(QV4::ExecutionEngine *engine)
sqlexception->defineReadonlyProperty(QStringLiteral("SYNTAX_ERR"), Primitive::fromInt32(SQLEXCEPTION_SYNTAX_ERR));
sqlexception->defineReadonlyProperty(QStringLiteral("CONSTRAINT_ERR"), Primitive::fromInt32(SQLEXCEPTION_CONSTRAINT_ERR));
sqlexception->defineReadonlyProperty(QStringLiteral("TIMEOUT_ERR"), Primitive::fromInt32(SQLEXCEPTION_TIMEOUT_ERR));
- engine->globalObject->defineDefaultProperty(QStringLiteral("SQLException"), sqlexception);
+ engine->globalObject()->defineDefaultProperty(QStringLiteral("SQLException"), sqlexception);
}
QT_END_NAMESPACE
diff --git a/src/qml/qml/v8/qv8engine.cpp b/src/qml/qml/v8/qv8engine.cpp
index 39b816f97c..d0c8c08fce 100644
--- a/src/qml/qml/v8/qv8engine.cpp
+++ b/src/qml/qml/v8/qv8engine.cpp
@@ -58,6 +58,7 @@
#include <QtCore/qjsonobject.h>
#include <QtCore/qjsonvalue.h>
#include <QtCore/qdatetime.h>
+#include <QtCore/qdatastream.h>
#include <private/qsimd_p.h>
#include <private/qv4value_inl_p.h>
@@ -151,7 +152,7 @@ QV8Engine::~QV8Engine()
delete m_extensionData[ii];
m_extensionData.clear();
- qt_rem_qmlxmlhttprequest(this, m_xmlHttpRequestData);
+ qt_rem_qmlxmlhttprequest(m_v4Engine, m_xmlHttpRequestData);
m_xmlHttpRequestData = 0;
delete m_listModelData;
m_listModelData = 0;
@@ -159,326 +160,6 @@ QV8Engine::~QV8Engine()
delete m_v4Engine;
}
-QVariant QV8Engine::toVariant(const QV4::ValueRef value, int typeHint, bool createJSValueForObjects, V8ObjectSet *visitedObjects)
-{
- Q_ASSERT (!value->isEmpty());
- QV4::Scope scope(m_v4Engine);
-
- if (QV4::VariantObject *v = value->as<QV4::VariantObject>())
- return v->d()->data;
-
- if (typeHint == QVariant::Bool)
- return QVariant(value->toBoolean());
-
- if (typeHint == QMetaType::QJsonValue)
- return QVariant::fromValue(QV4::JsonObject::toJsonValue(value));
-
- if (typeHint == qMetaTypeId<QJSValue>())
- return QVariant::fromValue(QJSValue(new QJSValuePrivate(m_v4Engine, value)));
-
- if (value->asObject()) {
- QV4::ScopedObject object(scope, value);
- if (typeHint == QMetaType::QJsonObject
- && !value->asArrayObject() && !value->asFunctionObject()) {
- return QVariant::fromValue(QV4::JsonObject::toJsonObject(object));
- } else if (QV4::QObjectWrapper *wrapper = object->as<QV4::QObjectWrapper>()) {
- return qVariantFromValue<QObject *>(wrapper->object());
- } else if (object->as<QV4::QmlContextWrapper>()) {
- return QVariant();
- } else if (QV4::QmlTypeWrapper *w = object->as<QV4::QmlTypeWrapper>()) {
- return w->toVariant();
- } else if (QV4::QmlValueTypeWrapper *v = object->as<QV4::QmlValueTypeWrapper>()) {
- return v->toVariant();
- } else if (QV4::QmlListWrapper *l = object->as<QV4::QmlListWrapper>()) {
- return l->toVariant();
- } else if (object->isListType())
- return QV4::SequencePrototype::toVariant(object);
- }
-
- if (value->asArrayObject()) {
- QV4::ScopedArrayObject a(scope, value);
- if (typeHint == qMetaTypeId<QList<QObject *> >()) {
- QList<QObject *> list;
- uint32_t length = a->getLength();
- QV4::Scoped<QV4::QObjectWrapper> qobjectWrapper(scope);
- for (uint32_t ii = 0; ii < length; ++ii) {
- qobjectWrapper = a->getIndexed(ii);
- if (!!qobjectWrapper) {
- list << qobjectWrapper->object();
- } else {
- list << 0;
- }
- }
-
- return qVariantFromValue<QList<QObject*> >(list);
- } else if (typeHint == QMetaType::QJsonArray) {
- return QVariant::fromValue(QV4::JsonObject::toJsonArray(a));
- }
-
- bool succeeded = false;
- QVariant retn = QV4::SequencePrototype::toVariant(value, typeHint, &succeeded);
- if (succeeded)
- return retn;
- }
-
- if (value->isUndefined())
- return QVariant();
- if (value->isNull())
- return QVariant(QMetaType::VoidStar, (void *)0);
- if (value->isBoolean())
- return value->booleanValue();
- if (value->isInteger())
- return value->integerValue();
- if (value->isNumber())
- return value->asDouble();
- if (value->isString())
- return value->stringValue()->toQString();
- if (QQmlLocaleData *ld = value->as<QQmlLocaleData>())
- return ld->d()->locale;
- if (QV4::DateObject *d = value->asDateObject())
- return d->toQDateTime();
- // NOTE: since we convert QTime to JS Date, round trip will change the variant type (to QDateTime)!
-
- QV4::ScopedObject o(scope, value);
- Q_ASSERT(o);
-
- if (QV4::RegExpObject *re = o->as<QV4::RegExpObject>())
- return re->toQRegExp();
-
- if (createJSValueForObjects)
- return QVariant::fromValue(QJSValue(new QJSValuePrivate(o->asReturnedValue())));
-
- return objectToVariant(o, visitedObjects);
-}
-
-QVariant QV8Engine::objectToVariant(QV4::Object *o, V8ObjectSet *visitedObjects)
-{
- Q_ASSERT(o);
-
- V8ObjectSet recursionGuardSet;
- if (!visitedObjects) {
- visitedObjects = &recursionGuardSet;
- } else if (visitedObjects->contains(o)) {
- // Avoid recursion.
- // For compatibility with QVariant{List,Map} conversion, we return an
- // empty object (and no error is thrown).
- if (o->asArrayObject())
- return QVariantList();
- return QVariantMap();
- }
- visitedObjects->insert(o);
-
- QVariant result;
-
- if (o->asArrayObject()) {
- QV4::Scope scope(m_v4Engine);
- QV4::ScopedArrayObject a(scope, o->asReturnedValue());
- QV4::ScopedValue v(scope);
- QVariantList list;
-
- int length = a->getLength();
- for (int ii = 0; ii < length; ++ii) {
- v = a->getIndexed(ii);
- list << toVariant(v, -1, /*createJSValueForObjects*/false, visitedObjects);
- }
-
- result = list;
- } else if (!o->asFunctionObject()) {
- QVariantMap map;
- QV4::Scope scope(m_v4Engine);
- QV4::ObjectIterator it(scope, o, QV4::ObjectIterator::EnumerableOnly);
- QV4::ScopedValue name(scope);
- QV4::ScopedValue val(scope);
- while (1) {
- name = it.nextPropertyNameAsString(val);
- if (name->isNull())
- break;
-
- QString key = name->toQStringNoThrow();
- map.insert(key, toVariant(val, /*type hint*/-1, /*createJSValueForObjects*/false, visitedObjects));
- }
-
- result = map;
- }
-
- visitedObjects->remove(o);
- return result;
-}
-
-static QV4::ReturnedValue arrayFromStringList(QV8Engine *engine, const QStringList &list)
-{
- QV4::ExecutionEngine *e = QV8Engine::getV4(engine);
- QV4::Scope scope(e);
- QV4::Scoped<QV4::ArrayObject> a(scope, e->newArrayObject());
- int len = list.count();
- a->arrayReserve(len);
- QV4::ScopedValue v(scope);
- for (int ii = 0; ii < len; ++ii)
- a->arrayPut(ii, (v = QV4::Encode(e->newString(list.at(ii)))));
-
- a->setArrayLengthUnchecked(len);
- return a.asReturnedValue();
-}
-
-static QV4::ReturnedValue arrayFromVariantList(QV8Engine *engine, const QVariantList &list)
-{
- QV4::ExecutionEngine *e = QV8Engine::getV4(engine);
- QV4::Scope scope(e);
- QV4::Scoped<QV4::ArrayObject> a(scope, e->newArrayObject());
- int len = list.count();
- a->arrayReserve(len);
- QV4::ScopedValue v(scope);
- for (int ii = 0; ii < len; ++ii)
- a->arrayPut(ii, (v = engine->fromVariant(list.at(ii))));
-
- a->setArrayLengthUnchecked(len);
- return a.asReturnedValue();
-}
-
-static QV4::ReturnedValue objectFromVariantMap(QV8Engine *engine, const QVariantMap &map)
-{
- QV4::ExecutionEngine *e = QV8Engine::getV4(engine);
- QV4::Scope scope(e);
- QV4::ScopedObject o(scope, e->newObject());
- QV4::ScopedString s(scope);
- QV4::ScopedValue v(scope);
- for (QVariantMap::ConstIterator iter = map.begin(); iter != map.end(); ++iter) {
- s = e->newString(iter.key());
- uint idx = s->asArrayIndex();
- if (idx > 16 && (!o->arrayData() || idx > o->arrayData()->length() * 2))
- o->initSparseArray();
- o->put(s.getPointer(), (v = engine->fromVariant(iter.value())));
- }
- return o.asReturnedValue();
-}
-
-Q_CORE_EXPORT QString qt_regexp_toCanonical(const QString &, QRegExp::PatternSyntax);
-
-QV4::ReturnedValue QV8Engine::fromVariant(const QVariant &variant)
-{
- int type = variant.userType();
- const void *ptr = variant.constData();
-
- if (type < QMetaType::User) {
- switch (QMetaType::Type(type)) {
- case QMetaType::UnknownType:
- case QMetaType::Void:
- return QV4::Encode::undefined();
- case QMetaType::VoidStar:
- return QV4::Encode::null();
- case QMetaType::Bool:
- return QV4::Encode(*reinterpret_cast<const bool*>(ptr));
- case QMetaType::Int:
- return QV4::Encode(*reinterpret_cast<const int*>(ptr));
- case QMetaType::UInt:
- return QV4::Encode(*reinterpret_cast<const uint*>(ptr));
- case QMetaType::LongLong:
- return QV4::Encode((double)*reinterpret_cast<const qlonglong*>(ptr));
- case QMetaType::ULongLong:
- return QV4::Encode((double)*reinterpret_cast<const qulonglong*>(ptr));
- case QMetaType::Double:
- return QV4::Encode(*reinterpret_cast<const double*>(ptr));
- case QMetaType::QString:
- return m_v4Engine->currentContext()->d()->engine->newString(*reinterpret_cast<const QString*>(ptr))->asReturnedValue();
- case QMetaType::Float:
- return QV4::Encode(*reinterpret_cast<const float*>(ptr));
- case QMetaType::Short:
- return QV4::Encode((int)*reinterpret_cast<const short*>(ptr));
- case QMetaType::UShort:
- return QV4::Encode((int)*reinterpret_cast<const unsigned short*>(ptr));
- case QMetaType::Char:
- return QV4::Encode((int)*reinterpret_cast<const char*>(ptr));
- case QMetaType::UChar:
- return QV4::Encode((int)*reinterpret_cast<const unsigned char*>(ptr));
- case QMetaType::QChar:
- return QV4::Encode((int)(*reinterpret_cast<const QChar*>(ptr)).unicode());
- case QMetaType::QDateTime:
- return QV4::Encode(m_v4Engine->newDateObject(*reinterpret_cast<const QDateTime *>(ptr)));
- case QMetaType::QDate:
- return QV4::Encode(m_v4Engine->newDateObject(QDateTime(*reinterpret_cast<const QDate *>(ptr))));
- case QMetaType::QTime:
- return QV4::Encode(m_v4Engine->newDateObject(QDateTime(QDate(1970,1,1), *reinterpret_cast<const QTime *>(ptr))));
- case QMetaType::QRegExp:
- return QV4::Encode(m_v4Engine->newRegExpObject(*reinterpret_cast<const QRegExp *>(ptr)));
- case QMetaType::QObjectStar:
- return QV4::QObjectWrapper::wrap(m_v4Engine, *reinterpret_cast<QObject* const *>(ptr));
- case QMetaType::QStringList:
- {
- bool succeeded = false;
- QV4::Scope scope(m_v4Engine);
- QV4::ScopedValue retn(scope, QV4::SequencePrototype::fromVariant(m_v4Engine, variant, &succeeded));
- if (succeeded)
- return retn.asReturnedValue();
- return arrayFromStringList(this, *reinterpret_cast<const QStringList *>(ptr));
- }
- case QMetaType::QVariantList:
- return arrayFromVariantList(this, *reinterpret_cast<const QVariantList *>(ptr));
- case QMetaType::QVariantMap:
- return objectFromVariantMap(this, *reinterpret_cast<const QVariantMap *>(ptr));
- case QMetaType::QJsonValue:
- return QV4::JsonObject::fromJsonValue(m_v4Engine, *reinterpret_cast<const QJsonValue *>(ptr));
- case QMetaType::QJsonObject:
- return QV4::JsonObject::fromJsonObject(m_v4Engine, *reinterpret_cast<const QJsonObject *>(ptr));
- case QMetaType::QJsonArray:
- return QV4::JsonObject::fromJsonArray(m_v4Engine, *reinterpret_cast<const QJsonArray *>(ptr));
- case QMetaType::QLocale:
- return QQmlLocale::wrap(this, *reinterpret_cast<const QLocale*>(ptr));
- default:
- break;
- }
-
- if (QQmlValueType *vt = QQmlValueTypeFactory::valueType(type))
- return QV4::QmlValueTypeWrapper::create(this, variant, vt);
- } else {
- QV4::Scope scope(m_v4Engine);
- if (type == qMetaTypeId<QQmlListReference>()) {
- typedef QQmlListReferencePrivate QDLRP;
- QDLRP *p = QDLRP::get((QQmlListReference*)ptr);
- if (p->object) {
- return QV4::QmlListWrapper::create(this, p->property, p->propertyType);
- } else {
- return QV4::Encode::null();
- }
- } else if (type == qMetaTypeId<QJSValue>()) {
- const QJSValue *value = reinterpret_cast<const QJSValue *>(ptr);
- QJSValuePrivate *valuep = QJSValuePrivate::get(*value);
- return valuep->getValue(m_v4Engine);
- } else if (type == qMetaTypeId<QList<QObject *> >()) {
- // XXX Can this be made more by using Array as a prototype and implementing
- // directly against QList<QObject*>?
- const QList<QObject *> &list = *(QList<QObject *>*)ptr;
- QV4::Scoped<QV4::ArrayObject> a(scope, m_v4Engine->newArrayObject());
- a->arrayReserve(list.count());
- QV4::ScopedValue v(scope);
- for (int ii = 0; ii < list.count(); ++ii)
- a->arrayPut(ii, (v = QV4::QObjectWrapper::wrap(m_v4Engine, list.at(ii))));
- a->setArrayLengthUnchecked(list.count());
- return a.asReturnedValue();
- } else if (QMetaType::typeFlags(type) & QMetaType::PointerToQObject) {
- return QV4::QObjectWrapper::wrap(m_v4Engine, *reinterpret_cast<QObject* const *>(ptr));
- }
-
- bool objOk;
- QObject *obj = QQmlMetaType::toQObject(variant, &objOk);
- if (objOk)
- return QV4::QObjectWrapper::wrap(m_v4Engine, obj);
-
- bool succeeded = false;
- QV4::ScopedValue retn(scope, QV4::SequencePrototype::fromVariant(m_v4Engine, variant, &succeeded));
- if (succeeded)
- return retn.asReturnedValue();
-
- if (QQmlValueType *vt = QQmlValueTypeFactory::valueType(type))
- return QV4::QmlValueTypeWrapper::create(this, variant, vt);
- }
-
- // XXX TODO: To be compatible, we still need to handle:
- // + QObjectList
- // + QList<int>
-
- return QV4::Encode(m_v4Engine->newVariantObject(variant));
-}
-
QNetworkAccessManager *QV8Engine::networkAccessManager()
{
return QQmlEnginePrivate::get(m_engine)->getNetworkAccessManager();
@@ -497,21 +178,21 @@ QQmlContextData *QV8Engine::callingContext()
void QV8Engine::initializeGlobal()
{
QV4::Scope scope(m_v4Engine);
- QV4::GlobalExtensions::init(m_engine, m_v4Engine->globalObject);
+ QV4::GlobalExtensions::init(m_engine, m_v4Engine->globalObject());
QQmlLocale::registerStringLocaleCompare(m_v4Engine);
QQmlDateExtension::registerExtension(m_v4Engine);
QQmlNumberExtension::registerExtension(m_v4Engine);
qt_add_domexceptions(m_v4Engine);
- m_xmlHttpRequestData = qt_add_qmlxmlhttprequest(this);
+ m_xmlHttpRequestData = qt_add_qmlxmlhttprequest(m_v4Engine);
qt_add_sqlexceptions(m_v4Engine);
{
- for (uint i = 0; i < m_v4Engine->globalObject->internalClass()->size; ++i) {
- if (m_v4Engine->globalObject->internalClass()->nameMap.at(i))
- m_illegalNames.insert(m_v4Engine->globalObject->internalClass()->nameMap.at(i)->toQString());
+ for (uint i = 0; i < m_v4Engine->globalObject()->internalClass()->size; ++i) {
+ if (m_v4Engine->globalObject()->internalClass()->nameMap.at(i))
+ m_illegalNames.insert(m_v4Engine->globalObject()->internalClass()->nameMap.at(i)->string);
}
}
@@ -534,9 +215,9 @@ void QV8Engine::initializeGlobal()
" }"\
"})"
- QV4::Scoped<QV4::FunctionObject> result(scope, QV4::Script::evaluate(m_v4Engine, QString::fromUtf8(FREEZE_SOURCE), 0));
+ QV4::ScopedFunctionObject result(scope, QV4::Script::evaluate(m_v4Engine, QString::fromUtf8(FREEZE_SOURCE), 0));
Q_ASSERT(!!result);
- m_freezeObject = result;
+ m_freezeObject.set(scope.engine, result);
#undef FREEZE_SOURCE
}
}
@@ -547,7 +228,7 @@ void QV8Engine::freezeObject(const QV4::ValueRef value)
QV4::ScopedFunctionObject f(scope, m_freezeObject.value());
QV4::ScopedCallData callData(scope, 1);
callData->args[0] = value;
- callData->thisObject = m_v4Engine->globalObject;
+ callData->thisObject = m_v4Engine->globalObject();
f->call(callData);
}
@@ -585,7 +266,7 @@ void QV8Engine::initQmlGlobalObject()
{
initializeGlobal();
QV4::Scope scope(m_v4Engine);
- QV4::ScopedValue v(scope, m_v4Engine->globalObject);
+ QV4::ScopedValue v(scope, m_v4Engine->globalObject());
freezeObject(v);
}
@@ -597,365 +278,7 @@ void QV8Engine::setEngine(QQmlEngine *engine)
QV4::ReturnedValue QV8Engine::global()
{
- return m_v4Engine->globalObject->asReturnedValue();
-}
-
-// Converts a QVariantList to JS.
-// The result is a new Array object with length equal to the length
-// of the QVariantList, and the elements being the QVariantList's
-// elements converted to JS, recursively.
-QV4::ReturnedValue QV8Engine::variantListToJS(const QVariantList &lst)
-{
- QV4::Scope scope(m_v4Engine);
- QV4::Scoped<QV4::ArrayObject> a(scope, m_v4Engine->newArrayObject());
- a->arrayReserve(lst.size());
- QV4::ScopedValue v(scope);
- for (int i = 0; i < lst.size(); i++)
- a->arrayPut(i, (v = variantToJS(lst.at(i))));
- a->setArrayLengthUnchecked(lst.size());
- return a.asReturnedValue();
-}
-
-// Converts a QVariantMap to JS.
-// The result is a new Object object with property names being
-// the keys of the QVariantMap, and values being the values of
-// the QVariantMap converted to JS, recursively.
-QV4::ReturnedValue QV8Engine::variantMapToJS(const QVariantMap &vmap)
-{
- QV4::Scope scope(m_v4Engine);
- QV4::Scoped<QV4::Object> o(scope, m_v4Engine->newObject());
- QVariantMap::const_iterator it;
- QV4::ScopedString s(scope);
- QV4::ScopedValue v(scope);
- for (it = vmap.constBegin(); it != vmap.constEnd(); ++it) {
- s = m_v4Engine->newIdentifier(it.key());
- v = variantToJS(it.value());
- uint idx = s->asArrayIndex();
- if (idx < UINT_MAX)
- o->arraySet(idx, v);
- else
- o->insertMember(s.getPointer(), v);
- }
- return o.asReturnedValue();
-}
-
-// Converts the meta-type defined by the given type and data to JS.
-// Returns the value if conversion succeeded, an empty handle otherwise.
-QV4::ReturnedValue QV8Engine::metaTypeToJS(int type, const void *data)
-{
- Q_ASSERT(data != 0);
-
- // check if it's one of the types we know
- switch (QMetaType::Type(type)) {
- case QMetaType::UnknownType:
- case QMetaType::Void:
- return QV4::Encode::undefined();
- case QMetaType::VoidStar:
- return QV4::Encode::null();
- case QMetaType::Bool:
- return QV4::Encode(*reinterpret_cast<const bool*>(data));
- case QMetaType::Int:
- return QV4::Encode(*reinterpret_cast<const int*>(data));
- case QMetaType::UInt:
- return QV4::Encode(*reinterpret_cast<const uint*>(data));
- case QMetaType::LongLong:
- return QV4::Encode(double(*reinterpret_cast<const qlonglong*>(data)));
- case QMetaType::ULongLong:
-#if defined(Q_OS_WIN) && defined(_MSC_FULL_VER) && _MSC_FULL_VER <= 12008804
-#pragma message("** NOTE: You need the Visual Studio Processor Pack to compile support for 64bit unsigned integers.")
- return QV4::Encode(double((qlonglong)*reinterpret_cast<const qulonglong*>(data)));
-#elif defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET)
- return QV4::Encode(double((qlonglong)*reinterpret_cast<const qulonglong*>(data)));
-#else
- return QV4::Encode(double(*reinterpret_cast<const qulonglong*>(data)));
-#endif
- case QMetaType::Double:
- return QV4::Encode(*reinterpret_cast<const double*>(data));
- case QMetaType::QString:
- return m_v4Engine->currentContext()->d()->engine->newString(*reinterpret_cast<const QString*>(data))->asReturnedValue();
- case QMetaType::Float:
- return QV4::Encode(*reinterpret_cast<const float*>(data));
- case QMetaType::Short:
- return QV4::Encode((int)*reinterpret_cast<const short*>(data));
- case QMetaType::UShort:
- return QV4::Encode((int)*reinterpret_cast<const unsigned short*>(data));
- case QMetaType::Char:
- return QV4::Encode((int)*reinterpret_cast<const char*>(data));
- case QMetaType::UChar:
- return QV4::Encode((int)*reinterpret_cast<const unsigned char*>(data));
- case QMetaType::QChar:
- return QV4::Encode((int)(*reinterpret_cast<const QChar*>(data)).unicode());
- case QMetaType::QStringList:
- return QV4::Encode(m_v4Engine->newArrayObject(*reinterpret_cast<const QStringList *>(data)));
- case QMetaType::QVariantList:
- return variantListToJS(*reinterpret_cast<const QVariantList *>(data));
- case QMetaType::QVariantMap:
- return variantMapToJS(*reinterpret_cast<const QVariantMap *>(data));
- case QMetaType::QDateTime:
- return QV4::Encode(m_v4Engine->newDateObject(*reinterpret_cast<const QDateTime *>(data)));
- case QMetaType::QDate:
- return QV4::Encode(m_v4Engine->newDateObject(QDateTime(*reinterpret_cast<const QDate *>(data))));
- case QMetaType::QRegExp:
- return QV4::Encode(m_v4Engine->newRegExpObject(*reinterpret_cast<const QRegExp *>(data)));
- case QMetaType::QObjectStar:
- return QV4::QObjectWrapper::wrap(m_v4Engine, *reinterpret_cast<QObject* const *>(data));
- case QMetaType::QVariant:
- return variantToJS(*reinterpret_cast<const QVariant*>(data));
- case QMetaType::QJsonValue:
- return QV4::JsonObject::fromJsonValue(m_v4Engine, *reinterpret_cast<const QJsonValue *>(data));
- case QMetaType::QJsonObject:
- return QV4::JsonObject::fromJsonObject(m_v4Engine, *reinterpret_cast<const QJsonObject *>(data));
- case QMetaType::QJsonArray:
- return QV4::JsonObject::fromJsonArray(m_v4Engine, *reinterpret_cast<const QJsonArray *>(data));
- default:
- if (type == qMetaTypeId<QJSValue>()) {
- return QJSValuePrivate::get(*reinterpret_cast<const QJSValue*>(data))->getValue(m_v4Engine);
- } else {
- QByteArray typeName = QMetaType::typeName(type);
- if (typeName.endsWith('*') && !*reinterpret_cast<void* const *>(data)) {
- return QV4::Encode::null();
- } else {
- // Fall back to wrapping in a QVariant.
- return QV4::Encode(m_v4Engine->newVariantObject(QVariant(type, data)));
- }
- }
- }
- Q_UNREACHABLE();
- return 0;
-}
-
-// Converts a JS value to a meta-type.
-// data must point to a place that can store a value of the given type.
-// Returns true if conversion succeeded, false otherwise.
-bool QV8Engine::metaTypeFromJS(const QV4::ValueRef value, int type, void *data)
-{
- QV4::Scope scope(QV8Engine::getV4(this));
-
- // check if it's one of the types we know
- switch (QMetaType::Type(type)) {
- case QMetaType::Bool:
- *reinterpret_cast<bool*>(data) = value->toBoolean();
- return true;
- case QMetaType::Int:
- *reinterpret_cast<int*>(data) = value->toInt32();
- return true;
- case QMetaType::UInt:
- *reinterpret_cast<uint*>(data) = value->toUInt32();
- return true;
- case QMetaType::LongLong:
- *reinterpret_cast<qlonglong*>(data) = qlonglong(value->toInteger());
- return true;
- case QMetaType::ULongLong:
- *reinterpret_cast<qulonglong*>(data) = qulonglong(value->toInteger());
- return true;
- case QMetaType::Double:
- *reinterpret_cast<double*>(data) = value->toNumber();
- return true;
- case QMetaType::QString:
- if (value->isUndefined() || value->isNull())
- *reinterpret_cast<QString*>(data) = QString();
- else
- *reinterpret_cast<QString*>(data) = value->toString(m_v4Engine->currentContext())->toQString();
- return true;
- case QMetaType::Float:
- *reinterpret_cast<float*>(data) = value->toNumber();
- return true;
- case QMetaType::Short:
- *reinterpret_cast<short*>(data) = short(value->toInt32());
- return true;
- case QMetaType::UShort:
- *reinterpret_cast<unsigned short*>(data) = value->toUInt16();
- return true;
- case QMetaType::Char:
- *reinterpret_cast<char*>(data) = char(value->toInt32());
- return true;
- case QMetaType::UChar:
- *reinterpret_cast<unsigned char*>(data) = (unsigned char)(value->toInt32());
- return true;
- case QMetaType::QChar:
- if (value->isString()) {
- QString str = value->stringValue()->toQString();
- *reinterpret_cast<QChar*>(data) = str.isEmpty() ? QChar() : str.at(0);
- } else {
- *reinterpret_cast<QChar*>(data) = QChar(ushort(value->toUInt16()));
- }
- return true;
- case QMetaType::QDateTime:
- if (QV4::DateObject *d = value->asDateObject()) {
- *reinterpret_cast<QDateTime *>(data) = d->toQDateTime();
- return true;
- } break;
- case QMetaType::QDate:
- if (QV4::DateObject *d = value->asDateObject()) {
- *reinterpret_cast<QDate *>(data) = d->toQDateTime().date();
- return true;
- } break;
- case QMetaType::QRegExp:
- if (QV4::RegExpObject *r = value->as<QV4::RegExpObject>()) {
- *reinterpret_cast<QRegExp *>(data) = r->toQRegExp();
- return true;
- } break;
- case QMetaType::QObjectStar: {
- QV4::QObjectWrapper *qobjectWrapper = value->as<QV4::QObjectWrapper>();
- if (qobjectWrapper || value->isNull()) {
- *reinterpret_cast<QObject* *>(data) = qtObjectFromJS(value);
- return true;
- } break;
- }
- case QMetaType::QStringList: {
- QV4::ScopedArrayObject a(scope, value);
- if (a) {
- *reinterpret_cast<QStringList *>(data) = a->toQStringList();
- return true;
- }
- break;
- }
- case QMetaType::QVariantList: {
- QV4::ScopedArrayObject a(scope, value);
- if (a) {
- *reinterpret_cast<QVariantList *>(data) = toVariant(a, /*typeHint*/-1, /*createJSValueForObjects*/false).toList();
- return true;
- }
- break;
- }
- case QMetaType::QVariantMap: {
- QV4::ScopedObject o(scope, value);
- if (o) {
- *reinterpret_cast<QVariantMap *>(data) = variantMapFromJS(o);
- return true;
- }
- break;
- }
- case QMetaType::QVariant:
- *reinterpret_cast<QVariant*>(data) = toVariant(value, /*typeHint*/-1, /*createJSValueForObjects*/false);
- return true;
- case QMetaType::QJsonValue:
- *reinterpret_cast<QJsonValue *>(data) = QV4::JsonObject::toJsonValue(value);
- return true;
- case QMetaType::QJsonObject: {
- QV4::ScopedObject o(scope, value);
- *reinterpret_cast<QJsonObject *>(data) = QV4::JsonObject::toJsonObject(o);
- return true;
- }
- case QMetaType::QJsonArray: {
- QV4::ScopedArrayObject a(scope, value);
- if (a) {
- *reinterpret_cast<QJsonArray *>(data) = QV4::JsonObject::toJsonArray(a);
- return true;
- }
- break;
- }
- default:
- ;
- }
-
-#if 0
- if (isQtVariant(value)) {
- const QVariant &var = variantValue(value);
- // ### Enable once constructInPlace() is in qt master.
- if (var.userType() == type) {
- QMetaType::constructInPlace(type, data, var.constData());
- return true;
- }
- if (var.canConvert(type)) {
- QVariant vv = var;
- vv.convert(type);
- Q_ASSERT(vv.userType() == type);
- QMetaType::constructInPlace(type, data, vv.constData());
- return true;
- }
-
- }
-#endif
-
- // Try to use magic; for compatibility with qscriptvalue_cast.
-
- QByteArray name = QMetaType::typeName(type);
- if (convertToNativeQObject(value, name, reinterpret_cast<void* *>(data)))
- return true;
- if (value->as<QV4::VariantObject>() && name.endsWith('*')) {
- int valueType = QMetaType::type(name.left(name.size()-1));
- QVariant &var = value->as<QV4::VariantObject>()->d()->data;
- if (valueType == var.userType()) {
- // We have T t, T* is requested, so return &t.
- *reinterpret_cast<void* *>(data) = var.data();
- return true;
- } else if (value->isObject()) {
- // Look in the prototype chain.
- QV4::ScopedObject proto(scope, value->objectValue()->prototype());
- while (proto) {
- bool canCast = false;
- if (QV4::VariantObject *vo = proto->as<QV4::VariantObject>()) {
- const QVariant &v = vo->d()->data;
- canCast = (type == v.userType()) || (valueType && (valueType == v.userType()));
- }
- else if (proto->as<QV4::QObjectWrapper>()) {
- QByteArray className = name.left(name.size()-1);
- QV4::ScopedObject p(scope, proto.getPointer());
- if (QObject *qobject = qtObjectFromJS(p))
- canCast = qobject->qt_metacast(className) != 0;
- }
- if (canCast) {
- QByteArray varTypeName = QMetaType::typeName(var.userType());
- if (varTypeName.endsWith('*'))
- *reinterpret_cast<void* *>(data) = *reinterpret_cast<void* *>(var.data());
- else
- *reinterpret_cast<void* *>(data) = var.data();
- return true;
- }
- proto = proto->prototype();
- }
- }
- } else if (value->isNull() && name.endsWith('*')) {
- *reinterpret_cast<void* *>(data) = 0;
- return true;
- } else if (type == qMetaTypeId<QJSValue>()) {
- *reinterpret_cast<QJSValue*>(data) = QJSValuePrivate::get(new QJSValuePrivate(m_v4Engine, value));
- return true;
- }
-
- return false;
-}
-
-// Converts a QVariant to JS.
-QV4::ReturnedValue QV8Engine::variantToJS(const QVariant &value)
-{
- return metaTypeToJS(value.userType(), value.constData());
-}
-
-bool QV8Engine::convertToNativeQObject(const QV4::ValueRef value, const QByteArray &targetType, void **result)
-{
- if (!targetType.endsWith('*'))
- return false;
- if (QObject *qobject = qtObjectFromJS(value)) {
- int start = targetType.startsWith("const ") ? 6 : 0;
- QByteArray className = targetType.mid(start, targetType.size()-start-1);
- if (void *instance = qobject->qt_metacast(className)) {
- *result = instance;
- return true;
- }
- }
- return false;
-}
-
-QObject *QV8Engine::qtObjectFromJS(const QV4::ValueRef value)
-{
- if (!value->isObject())
- return 0;
-
- QV4::Scope scope(m_v4Engine);
- QV4::Scoped<QV4::VariantObject> v(scope, value);
-
- if (v) {
- QVariant variant = v->d()->data;
- int type = variant.userType();
- if (type == QMetaType::QObjectStar)
- return *reinterpret_cast<QObject* const *>(variant.constData());
- }
- QV4::Scoped<QV4::QObjectWrapper> wrapper(scope, value);
- if (!wrapper)
- return 0;
- return wrapper->object();
+ return m_v4Engine->globalObject()->asReturnedValue();
}
void QV8Engine::startTimer(const QString &timerName)
@@ -985,10 +308,5 @@ int QV8Engine::consoleCountHelper(const QString &file, quint16 line, quint16 col
return number;
}
-QV4::ReturnedValue QV8Engine::toString(const QString &string)
-{
- return QV4::Encode(m_v4Engine->newString(string));
-}
-
QT_END_NAMESPACE
diff --git a/src/qml/qml/v8/qv8engine_p.h b/src/qml/qml/v8/qv8engine_p.h
index 51e857c8a2..1d3e427877 100644
--- a/src/qml/qml/v8/qv8engine_p.h
+++ b/src/qml/qml/v8/qv8engine_p.h
@@ -78,13 +78,13 @@ namespace QV4 {
// #define QML_GLOBAL_HANDLE_DEBUGGING
#define V4THROW_ERROR(string) \
- return ctx->throwError(QString::fromUtf8(string));
+ return ctx->engine()->throwError(QString::fromUtf8(string));
#define V4THROW_TYPE(string) \
- return ctx->throwTypeError(QStringLiteral(string));
+ return ctx->engine()->throwTypeError(QStringLiteral(string));
-#define V8_DEFINE_EXTENSION(dataclass, datafunction) \
- static inline dataclass *datafunction(QV8Engine *engine) \
+#define V4_DEFINE_EXTENSION(dataclass, datafunction) \
+ static inline dataclass *datafunction(QV4::ExecutionEngine *engine) \
{ \
static int extensionId = -1; \
if (extensionId == -1) { \
@@ -93,10 +93,10 @@ namespace QV4 {
extensionId = QV8Engine::registerExtension(); \
QV8Engine::registrationMutex()->unlock(); \
} \
- dataclass *rv = (dataclass *)engine->extensionData(extensionId); \
+ dataclass *rv = (dataclass *)engine->v8Engine->extensionData(extensionId); \
if (!rv) { \
rv = new dataclass(engine); \
- engine->setExtensionData(extensionId, rv); \
+ engine->v8Engine->setExtensionData(extensionId, rv); \
} \
return rv; \
} \
@@ -122,8 +122,7 @@ public:
QQmlContextData *context() { return ctx; }
QV4::ReturnedValue qmlGlobal() { return callData->thisObject.asReturnedValue(); }
void setReturnValue(QV4::ReturnedValue rv) { retVal = rv; }
- QV8Engine *engine() const { return e; }
- QV4::ExecutionEngine *v4engine() const;
+ QV4::ExecutionEngine *v4engine() const { return e; }
private:
friend struct QV4::QObjectMethod;
QQmlV4Function();
@@ -131,7 +130,7 @@ private:
QQmlV4Function &operator=(const QQmlV4Function &);
QQmlV4Function(QV4::CallData *callData, QV4::ValueRef retVal,
- const QV4::ValueRef global, QQmlContextData *c, QV8Engine *e)
+ const QV4::ValueRef global, QQmlContextData *c, QV4::ExecutionEngine *e)
: callData(callData), retVal(retVal), ctx(c), e(e)
{
callData->thisObject.val = global.asReturnedValue();
@@ -140,7 +139,7 @@ private:
QV4::CallData *callData;
QV4::ValueRef retVal;
QQmlContextData *ctx;
- QV8Engine *e;
+ QV4::ExecutionEngine *e;
};
class Q_QML_PRIVATE_EXPORT QQmlV4Handle
@@ -158,14 +157,14 @@ private:
class QObject;
class QQmlEngine;
-class QQmlValueType;
class QNetworkAccessManager;
class QQmlContextData;
class Q_QML_PRIVATE_EXPORT QV8Engine
{
friend class QJSEngine;
- typedef QSet<QV4::Object *> V8ObjectSet;
+ // ### GC
+ typedef QSet<QV4::Heap::Object *> V8ObjectSet;
public:
static QV8Engine* get(QJSEngine* q) { Q_ASSERT(q); return q->handle(); }
// static QJSEngine* get(QV8Engine* d) { Q_ASSERT(d); return d->q; }
@@ -197,16 +196,6 @@ public:
void freezeObject(const QV4::ValueRef value);
- QVariant toVariant(const QV4::ValueRef value, int typeHint, bool createJSValueForObjects = true, V8ObjectSet *visitedObjects = 0);
- QVariant objectToVariant(QV4::Object *o, V8ObjectSet *visitedObjects = 0);
- QV4::ReturnedValue fromVariant(const QVariant &);
-
- QVariantMap variantMapFromJS(QV4::Object *o)
- { return objectToVariant(o).toMap(); }
-
- // Return a JS string for the given QString \a string
- QV4::ReturnedValue toString(const QString &string);
-
// Return the network access manager for this engine. By default this returns the network
// access manager of the QQmlEngine. It is overridden in the case of a threaded v8
// instance (like in WorkerScript).
@@ -221,17 +210,7 @@ public:
inline Deletable *extensionData(int) const;
void setExtensionData(int, Deletable *);
- QV4::ReturnedValue variantListToJS(const QVariantList &lst);
- QV4::ReturnedValue variantMapToJS(const QVariantMap &vmap);
- QV4::ReturnedValue variantToJS(const QVariant &value);
-
- QV4::ReturnedValue metaTypeToJS(int type, const void *data);
- bool metaTypeFromJS(const QV4::ValueRef value, int type, void *data);
-
- bool convertToNativeQObject(const QV4::ValueRef value,
- const QByteArray &targetType,
- void **result);
-
+public:
// used for console.time(), console.timeEnd()
void startTimer(const QString &timerName);
qint64 stopTimer(const QString &timerName, bool *wasRunning);
@@ -239,8 +218,6 @@ public:
// used for console.count()
int consoleCountHelper(const QString &file, quint16 line, quint16 column);
- QObject *qtObjectFromJS(const QV4::ValueRef value);
-
protected:
QJSEngine* q;
QQmlEngine *m_engine;
@@ -275,10 +252,6 @@ inline QV8Engine::Deletable *QV8Engine::extensionData(int index) const
return 0;
}
-inline QV4::ExecutionEngine *QQmlV4Function::v4engine() const
-{
- return QV8Engine::getV4(e);
-}
QT_END_NAMESPACE
diff --git a/src/qml/qml/v8/v8.pri b/src/qml/qml/v8/v8.pri
index b4eb706574..3d6a012481 100644
--- a/src/qml/qml/v8/v8.pri
+++ b/src/qml/qml/v8/v8.pri
@@ -1,5 +1,4 @@
HEADERS += \
- $$PWD/qv8debug_p.h \
$$PWD/qv8engine_p.h \
$$PWD/qv4domerrors_p.h \
$$PWD/qv4sqlerrors_p.h \
diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp
index 8b65373133..8309df8403 100644
--- a/src/qml/types/qqmldelegatemodel.cpp
+++ b/src/qml/types/qqmldelegatemodel.cpp
@@ -46,35 +46,49 @@
#include <private/qv4value_inl_p.h>
#include <private/qv4functionobject_p.h>
+#include <qv4objectiterator_p.h>
QT_BEGIN_NAMESPACE
class QQmlDelegateModelItem;
-struct DelegateModelGroupFunction: QV4::FunctionObject
-{
- struct Data : FunctionObject::Data {
- Data(QV4::ExecutionContext *scope, uint flag, QV4::ReturnedValue (*code)(QQmlDelegateModelItem *item, uint flag, const QV4::ValueRef arg))
- : FunctionObject::Data(scope, QStringLiteral("DelegateModelGroupFunction"))
- , flag(flag)
- , code(code)
- {
- setVTable(staticVTable());
- }
+namespace QV4 {
+
+namespace Heap {
- uint flag;
- QV4::ReturnedValue (*code)(QQmlDelegateModelItem *item, uint flag, const QV4::ValueRef arg);
- };
- V4_OBJECT(QV4::FunctionObject)
+struct DelegateModelGroupFunction : FunctionObject {
+ DelegateModelGroupFunction(QV4::ExecutionContext *scope, uint flag, QV4::ReturnedValue (*code)(QQmlDelegateModelItem *item, uint flag, const QV4::ValueRef arg));
+
+ uint flag;
+ QV4::ReturnedValue (*code)(QQmlDelegateModelItem *item, uint flag, const QV4::ValueRef arg);
+};
- static DelegateModelGroupFunction *create(QV4::ExecutionContext *scope, uint flag, QV4::ReturnedValue (*code)(QQmlDelegateModelItem *item, uint flag, const QV4::ValueRef arg))
+struct QQmlDelegateModelGroupChange : Object {
+ QQmlDelegateModelGroupChange(QV4::ExecutionEngine *engine);
+
+ QQmlChangeSet::Change change;
+};
+
+struct QQmlDelegateModelGroupChangeArray : Object {
+ QQmlDelegateModelGroupChangeArray(QV4::ExecutionEngine *engine, const QVector<QQmlChangeSet::Change> &changes);
+ QVector<QQmlChangeSet::Change> changes;
+};
+
+
+}
+
+struct DelegateModelGroupFunction : QV4::FunctionObject
+{
+ V4_OBJECT2(DelegateModelGroupFunction, FunctionObject)
+
+ static Heap::DelegateModelGroupFunction *create(QV4::ExecutionContext *scope, uint flag, QV4::ReturnedValue (*code)(QQmlDelegateModelItem *item, uint flag, const QV4::ValueRef arg))
{
return scope->engine()->memoryManager->alloc<DelegateModelGroupFunction>(scope, flag, code);
}
static QV4::ReturnedValue construct(QV4::Managed *m, QV4::CallData *)
{
- return m->engine()->currentContext()->throwTypeError();
+ return m->engine()->throwTypeError();
}
static QV4::ReturnedValue call(QV4::Managed *that, QV4::CallData *callData)
@@ -84,21 +98,31 @@ struct DelegateModelGroupFunction: QV4::FunctionObject
QV4::Scoped<DelegateModelGroupFunction> f(scope, that, QV4::Scoped<DelegateModelGroupFunction>::Cast);
QV4::Scoped<QQmlDelegateModelItemObject> o(scope, callData->thisObject);
if (!o)
- return v4->currentContext()->throwTypeError(QStringLiteral("Not a valid VisualData object"));
+ return v4->throwTypeError(QStringLiteral("Not a valid VisualData object"));
QV4::ScopedValue v(scope, callData->argument(0));
return f->d()->code(o->d()->item, f->d()->flag, v);
}
};
-DEFINE_OBJECT_VTABLE(DelegateModelGroupFunction);
+Heap::DelegateModelGroupFunction::DelegateModelGroupFunction(QV4::ExecutionContext *scope, uint flag, QV4::ReturnedValue (*code)(QQmlDelegateModelItem *item, uint flag, const QV4::ValueRef arg))
+ : QV4::Heap::FunctionObject(scope, QStringLiteral("DelegateModelGroupFunction"))
+ , flag(flag)
+ , code(code)
+{
+ setVTable(QV4::DelegateModelGroupFunction::staticVTable());
+}
+
+}
+
+DEFINE_OBJECT_VTABLE(QV4::DelegateModelGroupFunction);
class QQmlDelegateModelEngineData : public QV8Engine::Deletable
{
public:
- QQmlDelegateModelEngineData(QV8Engine *engine);
+ QQmlDelegateModelEngineData(QV4::ExecutionEngine *v4);
~QQmlDelegateModelEngineData();
QV4::ReturnedValue array(QV8Engine *engine, const QVector<QQmlChangeSet::Change> &changes);
@@ -106,7 +130,7 @@ public:
QV4::PersistentValue changeProto;
};
-V8_DEFINE_EXTENSION(QQmlDelegateModelEngineData, engineData)
+V4_DEFINE_EXTENSION(QQmlDelegateModelEngineData, engineData)
void QQmlDelegateModelPartsMetaObject::propertyCreated(int, QMetaPropertyBuilder &prop)
@@ -1606,10 +1630,10 @@ bool QQmlDelegateModelPrivate::insert(Compositor::insert_iterator &before, const
QQmlDelegateModelItem *cacheItem = m_adaptorModel.createItem(m_cacheMetaType, m_context->engine(), -1);
if (!cacheItem)
return false;
- QV4::ExecutionEngine *v4 = object->engine();
- if (!v4)
+ if (!object->isObject())
return false;
+ QV4::ExecutionEngine *v4 = object->asObject()->engine();
QV4::Scope scope(v4);
QV4::ScopedObject o(scope, object);
if (!o)
@@ -1622,7 +1646,7 @@ bool QQmlDelegateModelPrivate::insert(Compositor::insert_iterator &before, const
propertyName = it.nextPropertyNameAsString(v);
if (propertyName->isNull())
break;
- cacheItem->setValue(propertyName->toQStringNoThrow(), m_cacheMetaType->v8Engine->toVariant(v, QVariant::Invalid));
+ cacheItem->setValue(propertyName->toQStringNoThrow(), scope.engine->toVariant(v, QVariant::Invalid));
}
cacheItem->groups = groups | Compositor::UnresolvedFlag | Compositor::CacheFlag;
@@ -1686,7 +1710,7 @@ void QQmlDelegateModelItemMetaType::initializePrototype()
QV4::ExecutionEngine *v4 = QV8Engine::getV4(v8Engine);
QV4::Scope scope(v4);
- QV4::Scoped<QV4::Object> proto(scope, v4->newObject());
+ QV4::ScopedObject proto(scope, v4->newObject());
proto->defineAccessorProperty(QStringLiteral("model"), QQmlDelegateModelItem::get_model, 0);
proto->defineAccessorProperty(QStringLiteral("groups"), QQmlDelegateModelItem::get_groups, QQmlDelegateModelItem::set_groups);
QV4::ScopedString s(scope);
@@ -1694,45 +1718,46 @@ void QQmlDelegateModelItemMetaType::initializePrototype()
s = v4->newString(QStringLiteral("isUnresolved"));
QV4::ScopedFunctionObject f(scope);
- p->setGetter((f = DelegateModelGroupFunction::create(v4->rootContext, 30, QQmlDelegateModelItem::get_member)));
+ QV4::ScopedContext global(scope, scope.engine->rootContext());
+ p->setGetter((f = QV4::DelegateModelGroupFunction::create(global, 30, QQmlDelegateModelItem::get_member)));
p->setSetter(0);
- proto->insertMember(s.getPointer(), p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
+ proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
s = v4->newString(QStringLiteral("inItems"));
- p->setGetter((f = DelegateModelGroupFunction::create(v4->rootContext, QQmlListCompositor::Default, QQmlDelegateModelItem::get_member)));
- p->setSetter((f = DelegateModelGroupFunction::create(v4->rootContext, QQmlListCompositor::Default, QQmlDelegateModelItem::set_member)));
- proto->insertMember(s.getPointer(), p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
+ p->setGetter((f = QV4::DelegateModelGroupFunction::create(global, QQmlListCompositor::Default, QQmlDelegateModelItem::get_member)));
+ p->setSetter((f = QV4::DelegateModelGroupFunction::create(global, QQmlListCompositor::Default, QQmlDelegateModelItem::set_member)));
+ proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
s = v4->newString(QStringLiteral("inPersistedItems"));
- p->setGetter((f = DelegateModelGroupFunction::create(v4->rootContext, QQmlListCompositor::Persisted, QQmlDelegateModelItem::get_member)));
- p->setSetter((f = DelegateModelGroupFunction::create(v4->rootContext, QQmlListCompositor::Persisted, QQmlDelegateModelItem::set_member)));
- proto->insertMember(s.getPointer(), p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
+ p->setGetter((f = QV4::DelegateModelGroupFunction::create(global, QQmlListCompositor::Persisted, QQmlDelegateModelItem::get_member)));
+ p->setSetter((f = QV4::DelegateModelGroupFunction::create(global, QQmlListCompositor::Persisted, QQmlDelegateModelItem::set_member)));
+ proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
s = v4->newString(QStringLiteral("itemsIndex"));
- p->setGetter((f = DelegateModelGroupFunction::create(v4->rootContext, QQmlListCompositor::Default, QQmlDelegateModelItem::get_index)));
- proto->insertMember(s.getPointer(), p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
+ p->setGetter((f = QV4::DelegateModelGroupFunction::create(global, QQmlListCompositor::Default, QQmlDelegateModelItem::get_index)));
+ proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
s = v4->newString(QStringLiteral("persistedItemsIndex"));
- p->setGetter((f = DelegateModelGroupFunction::create(v4->rootContext, QQmlListCompositor::Persisted, QQmlDelegateModelItem::get_index)));
+ p->setGetter((f = QV4::DelegateModelGroupFunction::create(global, QQmlListCompositor::Persisted, QQmlDelegateModelItem::get_index)));
p->setSetter(0);
- proto->insertMember(s.getPointer(), p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
+ proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
for (int i = 2; i < groupNames.count(); ++i) {
QString propertyName = QStringLiteral("in") + groupNames.at(i);
propertyName.replace(2, 1, propertyName.at(2).toUpper());
s = v4->newString(propertyName);
- p->setGetter((f = DelegateModelGroupFunction::create(v4->rootContext, i + 1, QQmlDelegateModelItem::get_member)));
- p->setSetter((f = DelegateModelGroupFunction::create(v4->rootContext, i + 1, QQmlDelegateModelItem::set_member)));
- proto->insertMember(s.getPointer(), p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
+ p->setGetter((f = QV4::DelegateModelGroupFunction::create(global, i + 1, QQmlDelegateModelItem::get_member)));
+ p->setSetter((f = QV4::DelegateModelGroupFunction::create(global, i + 1, QQmlDelegateModelItem::set_member)));
+ proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
}
for (int i = 2; i < groupNames.count(); ++i) {
const QString propertyName = groupNames.at(i) + QStringLiteral("Index");
s = v4->newString(propertyName);
- p->setGetter((f = DelegateModelGroupFunction::create(v4->rootContext, i + 1, QQmlDelegateModelItem::get_index)));
+ p->setGetter((f = QV4::DelegateModelGroupFunction::create(global, i + 1, QQmlDelegateModelItem::get_index)));
p->setSetter(0);
- proto->insertMember(s.getPointer(), p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
+ proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
}
- modelItemProto = proto;
+ modelItemProto.set(v4, proto);
}
int QQmlDelegateModelItemMetaType::parseGroups(const QStringList &groups) const
@@ -1780,7 +1805,7 @@ QV4::ReturnedValue QQmlDelegateModelItem::get_model(QV4::CallContext *ctx)
QV4::Scope scope(ctx);
QV4::Scoped<QQmlDelegateModelItemObject> o(scope, ctx->d()->callData->thisObject.as<QQmlDelegateModelItemObject>());
if (!o)
- return ctx->throwTypeError(QStringLiteral("Not a valid VisualData object"));
+ return ctx->engine()->throwTypeError(QStringLiteral("Not a valid VisualData object"));
if (!o->d()->item->metaType->model)
return QV4::Encode::undefined();
@@ -1792,7 +1817,7 @@ QV4::ReturnedValue QQmlDelegateModelItem::get_groups(QV4::CallContext *ctx)
QV4::Scope scope(ctx);
QV4::Scoped<QQmlDelegateModelItemObject> o(scope, ctx->d()->callData->thisObject.as<QQmlDelegateModelItemObject>());
if (!o)
- return ctx->throwTypeError(QStringLiteral("Not a valid VisualData object"));
+ return ctx->engine()->throwTypeError(QStringLiteral("Not a valid VisualData object"));
QStringList groups;
for (int i = 1; i < o->d()->item->metaType->groupCount; ++i) {
@@ -1800,7 +1825,7 @@ QV4::ReturnedValue QQmlDelegateModelItem::get_groups(QV4::CallContext *ctx)
groups.append(o->d()->item->metaType->groupNames.at(i - 1));
}
- return scope.engine->v8Engine->fromVariant(groups);
+ return scope.engine->fromVariant(groups);
}
QV4::ReturnedValue QQmlDelegateModelItem::set_groups(QV4::CallContext *ctx)
@@ -1808,9 +1833,9 @@ QV4::ReturnedValue QQmlDelegateModelItem::set_groups(QV4::CallContext *ctx)
QV4::Scope scope(ctx);
QV4::Scoped<QQmlDelegateModelItemObject> o(scope, ctx->d()->callData->thisObject.as<QQmlDelegateModelItemObject>());
if (!o)
- return ctx->throwTypeError(QStringLiteral("Not a valid VisualData object"));
+ return ctx->engine()->throwTypeError(QStringLiteral("Not a valid VisualData object"));
if (!ctx->d()->callData->argc)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
if (!o->d()->item->metaType->model)
return QV4::Encode::undefined();
@@ -1859,17 +1884,11 @@ QV4::ReturnedValue QQmlDelegateModelItem::get_index(QQmlDelegateModelItem *thisI
DEFINE_OBJECT_VTABLE(QQmlDelegateModelItemObject);
-QQmlDelegateModelItemObject::Data::~Data()
+QV4::Heap::QQmlDelegateModelItemObject::~QQmlDelegateModelItemObject()
{
item->Dispose();
}
-void QQmlDelegateModelItemObject::destroy(Managed *that)
-{
- static_cast<QQmlDelegateModelItemObject *>(that)->d()->~Data();
-}
-
-
QQmlDelegateModelItem::QQmlDelegateModelItem(
QQmlDelegateModelItemMetaType *metaType, int modelIndex)
@@ -2237,8 +2256,8 @@ void QQmlDelegateModelGroupPrivate::emitChanges(QV8Engine *engine)
Q_Q(QQmlDelegateModelGroup);
if (isChangedConnected() && !changeSet.isEmpty()) {
QV4::Scope scope(QV8Engine::getV4(engine));
- QV4::ScopedValue removed(scope, engineData(engine)->array(engine, changeSet.removes()));
- QV4::ScopedValue inserted(scope, engineData(engine)->array(engine, changeSet.inserts()));
+ QV4::ScopedValue removed(scope, engineData(scope.engine)->array(engine, changeSet.removes()));
+ QV4::ScopedValue inserted(scope, engineData(scope.engine)->array(engine, changeSet.inserts()));
emit q->changed(QQmlV4Handle(removed), QQmlV4Handle(inserted));
}
if (changeSet.difference() != 0)
@@ -2470,7 +2489,7 @@ QQmlV4Handle QQmlDelegateModelGroup::get(int index)
QV4::Scope scope(v4);
QV4::ScopedObject o(scope, v4->memoryManager->alloc<QQmlDelegateModelItemObject>(v4, cacheItem));
QV4::ScopedObject p(scope, model->m_cacheMetaType->modelItemProto.value());
- o->setPrototype(p.getPointer());
+ o->setPrototype(p);
++cacheItem->scriptRef;
return QQmlV4Handle(o);
@@ -2483,10 +2502,10 @@ bool QQmlDelegateModelGroupPrivate::parseIndex(const QV4::ValueRef value, int *i
return true;
}
- QV4::ExecutionEngine *v4 = value->engine();
- if (!v4)
+ if (!value->isObject())
return false;
+ QV4::ExecutionEngine *v4 = value->asObject()->engine();
QV4::Scope scope(v4);
QV4::Scoped<QQmlDelegateModelItemObject> object(scope, value);
@@ -2634,7 +2653,7 @@ void QQmlDelegateModelGroup::create(QQmlV4Function *args)
model->m_cache.at(it.cacheIndex)->releaseObject();
}
- args->setReturnValue(QV4::QObjectWrapper::wrap(QV8Engine::getV4(args->engine()), object));
+ args->setReturnValue(QV4::QObjectWrapper::wrap(args->v4engine(), object));
model->emitChanges();
}
@@ -3210,17 +3229,9 @@ void QQmlPartsModel::emitModelUpdated(const QQmlChangeSet &changeSet, bool reset
struct QQmlDelegateModelGroupChange : QV4::Object
{
- struct Data : QV4::Object::Data {
- Data(QV4::ExecutionEngine *engine)
- : Object::Data(engine)
- {
- setVTable(staticVTable());
- }
- QQmlChangeSet::Change change;
- };
- V4_OBJECT(QV4::Object)
+ V4_OBJECT2(QQmlDelegateModelGroupChange, QV4::Object)
- static QQmlDelegateModelGroupChange *create(QV4::ExecutionEngine *e) {
+ static QV4::Heap::QQmlDelegateModelGroupChange *create(QV4::ExecutionEngine *e) {
return e->memoryManager->alloc<QQmlDelegateModelGroupChange>(e);
}
@@ -3228,46 +3239,41 @@ struct QQmlDelegateModelGroupChange : QV4::Object
QV4::Scope scope(ctx);
QV4::Scoped<QQmlDelegateModelGroupChange> that(scope, ctx->d()->callData->thisObject.as<QQmlDelegateModelGroupChange>());
if (!that)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
return QV4::Encode(that->d()->change.index);
}
static QV4::ReturnedValue method_get_count(QV4::CallContext *ctx) {
QV4::Scope scope(ctx);
QV4::Scoped<QQmlDelegateModelGroupChange> that(scope, ctx->d()->callData->thisObject.as<QQmlDelegateModelGroupChange>());
if (!that)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
return QV4::Encode(that->d()->change.count);
}
static QV4::ReturnedValue method_get_moveId(QV4::CallContext *ctx) {
QV4::Scope scope(ctx);
QV4::Scoped<QQmlDelegateModelGroupChange> that(scope, ctx->d()->callData->thisObject.as<QQmlDelegateModelGroupChange>());
if (!that)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
if (that->d()->change.moveId < 0)
return QV4::Encode::undefined();
return QV4::Encode(that->d()->change.moveId);
}
};
+QV4::Heap::QQmlDelegateModelGroupChange::QQmlDelegateModelGroupChange(QV4::ExecutionEngine *engine)
+ : QV4::Heap::Object(engine)
+{
+ setVTable(::QQmlDelegateModelGroupChange::staticVTable());
+}
+
DEFINE_OBJECT_VTABLE(QQmlDelegateModelGroupChange);
struct QQmlDelegateModelGroupChangeArray : public QV4::Object
{
- struct Data : QV4::Object::Data {
- Data(QV4::ExecutionEngine *engine, const QVector<QQmlChangeSet::Change> &changes)
- : Object::Data(engine)
- , changes(changes)
- {
- setVTable(staticVTable());
- QV4::Scope scope(engine);
- QV4::ScopedObject o(scope, this);
- o->setArrayType(QV4::ArrayData::Custom);
- }
- QVector<QQmlChangeSet::Change> changes;
- };
- V4_OBJECT(QV4::Object)
+ V4_OBJECT2(QQmlDelegateModelGroupChangeArray, QV4::Object)
+ V4_NEEDS_DESTROY
public:
- static QQmlDelegateModelGroupChangeArray *create(QV4::ExecutionEngine *engine, const QVector<QQmlChangeSet::Change> &changes)
+ static QV4::Heap::QQmlDelegateModelGroupChangeArray *create(QV4::ExecutionEngine *engine, const QVector<QQmlChangeSet::Change> &changes)
{
return engine->memoryManager->alloc<QQmlDelegateModelGroupChangeArray>(engine, changes);
}
@@ -3290,9 +3296,9 @@ public:
const QQmlChangeSet::Change &change = array->at(index);
- QV4::ScopedObject changeProto(scope, engineData(v4->v8Engine)->changeProto.value());
+ QV4::ScopedObject changeProto(scope, engineData(v4)->changeProto.value());
QV4::Scoped<QQmlDelegateModelGroupChange> object(scope, QQmlDelegateModelGroupChange::create(v4));
- object->setPrototype(changeProto.getPointer());
+ object->setPrototype(changeProto);
object->d()->change = change;
if (hasProperty)
@@ -3313,24 +3319,29 @@ public:
return Object::get(m, name, hasProperty);
}
- static void destroy(Managed *that) {
- static_cast<QQmlDelegateModelGroupChangeArray *>(that)->d()->~Data();
- }
-
};
+QV4::Heap::QQmlDelegateModelGroupChangeArray::QQmlDelegateModelGroupChangeArray(QV4::ExecutionEngine *engine, const QVector<QQmlChangeSet::Change> &changes)
+ : QV4::Heap::Object(engine)
+ , changes(changes)
+{
+ setVTable(::QQmlDelegateModelGroupChangeArray::staticVTable());
+ QV4::Scope scope(engine);
+ QV4::ScopedObject o(scope, this);
+ o->setArrayType(QV4::Heap::ArrayData::Custom);
+}
+
DEFINE_OBJECT_VTABLE(QQmlDelegateModelGroupChangeArray);
-QQmlDelegateModelEngineData::QQmlDelegateModelEngineData(QV8Engine *e)
+QQmlDelegateModelEngineData::QQmlDelegateModelEngineData(QV4::ExecutionEngine *v4)
{
- QV4::ExecutionEngine *v4 = QV8Engine::getV4(e);
QV4::Scope scope(v4);
- QV4::Scoped<QV4::Object> proto(scope, v4->newObject());
+ QV4::ScopedObject proto(scope, v4->newObject());
proto->defineAccessorProperty(QStringLiteral("index"), QQmlDelegateModelGroupChange::method_get_index, 0);
proto->defineAccessorProperty(QStringLiteral("count"), QQmlDelegateModelGroupChange::method_get_count, 0);
proto->defineAccessorProperty(QStringLiteral("moveId"), QQmlDelegateModelGroupChange::method_get_moveId, 0);
- changeProto = proto;
+ changeProto.set(v4, proto);
}
QQmlDelegateModelEngineData::~QQmlDelegateModelEngineData()
diff --git a/src/qml/types/qqmldelegatemodel_p_p.h b/src/qml/types/qqmldelegatemodel_p_p.h
index a7def0ad50..8635795820 100644
--- a/src/qml/types/qqmldelegatemodel_p_p.h
+++ b/src/qml/types/qqmldelegatemodel_p_p.h
@@ -151,23 +151,30 @@ protected:
void objectDestroyed(QObject *);
};
+namespace QV4 {
+namespace Heap {
+struct QQmlDelegateModelItemObject : Object {
+ inline QQmlDelegateModelItemObject(QV4::ExecutionEngine *engine, QQmlDelegateModelItem *item);
+ ~QQmlDelegateModelItemObject();
+ QQmlDelegateModelItem *item;
+};
+
+}
+}
+
struct QQmlDelegateModelItemObject : QV4::Object
{
- struct Data : QV4::Object::Data {
- Data(QV4::ExecutionEngine *engine, QQmlDelegateModelItem *item)
- : Object::Data(engine)
- , item(item)
- {
- setVTable(staticVTable());
- }
- ~Data();
- QQmlDelegateModelItem *item;
- };
- V4_OBJECT(QV4::Object)
-
- static void destroy(Managed *that);
+ V4_OBJECT2(QQmlDelegateModelItemObject, QV4::Object)
+ V4_NEEDS_DESTROY
};
+QV4::Heap::QQmlDelegateModelItemObject::QQmlDelegateModelItemObject(QV4::ExecutionEngine *engine, QQmlDelegateModelItem *item)
+ : QV4::Heap::Object(engine)
+ , item(item)
+{
+ setVTable(::QQmlDelegateModelItemObject::staticVTable());
+}
+
class QQmlDelegateModelPrivate;
diff --git a/src/qml/types/qqmllistmodel.cpp b/src/qml/types/qqmllistmodel.cpp
index afd887ba53..0abc62b2bf 100644
--- a/src/qml/types/qqmllistmodel.cpp
+++ b/src/qml/types/qqmllistmodel.cpp
@@ -388,7 +388,7 @@ void ListModel::updateCacheIndices()
}
}
-QVariant ListModel::getProperty(int elementIndex, int roleIndex, const QQmlListModel *owner, QV8Engine *eng)
+QVariant ListModel::getProperty(int elementIndex, int roleIndex, const QQmlListModel *owner, QV4::ExecutionEngine *eng)
{
ListElement *e = elements[elementIndex];
const ListLayout::Role &r = m_layout->getExistingRole(roleIndex);
@@ -401,7 +401,7 @@ ListModel *ListModel::getListProperty(int elementIndex, const ListLayout::Role &
return e->getListProperty(role);
}
-void ListModel::set(int elementIndex, QV4::Object *object, QVector<int> *roles, QV8Engine *eng)
+void ListModel::set(int elementIndex, QV4::Object *object, QVector<int> *roles)
{
ListElement *e = elements[elementIndex];
@@ -410,7 +410,7 @@ void ListModel::set(int elementIndex, QV4::Object *object, QVector<int> *roles,
QV4::ScopedObject o(scope);
QV4::ObjectIterator it(scope, object, QV4::ObjectIterator::WithProtoChain|QV4::ObjectIterator::EnumerableOnly);
- QV4::Scoped<QV4::String> propertyName(scope);
+ QV4::ScopedString propertyName(scope);
QV4::ScopedValue propertyValue(scope);
QV4::ScopedString s(scope);
QV4::ScopedArrayObject a(scope);
@@ -424,40 +424,40 @@ void ListModel::set(int elementIndex, QV4::Object *object, QVector<int> *roles,
// Add the value now
if ((s = propertyValue)) {
- const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName.getPointer(), ListLayout::Role::String);
+ const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::String);
roleIndex = e->setStringProperty(r, s->toQString());
} else if (propertyValue->isNumber()) {
- const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName.getPointer(), ListLayout::Role::Number);
+ const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::Number);
roleIndex = e->setDoubleProperty(r, propertyValue->asDouble());
} else if ((a = propertyValue)) {
- const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName.getPointer(), ListLayout::Role::List);
+ const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::List);
ListModel *subModel = new ListModel(r.subLayout, 0, -1);
int arrayLength = a->getLength();
for (int j=0 ; j < arrayLength ; ++j) {
o = a->getIndexed(j);
- subModel->append(o, eng);
+ subModel->append(o);
}
roleIndex = e->setListProperty(r, subModel);
} else if (propertyValue->isBoolean()) {
- const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName.getPointer(), ListLayout::Role::Bool);
+ const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::Bool);
roleIndex = e->setBoolProperty(r, propertyValue->booleanValue());
} else if (QV4::DateObject *dd = propertyValue->asDateObject()) {
- const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName.getPointer(), ListLayout::Role::DateTime);
+ const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::DateTime);
QDateTime dt = dd->toQDateTime();
roleIndex = e->setDateTimeProperty(r, dt);
} else if (QV4::Object *o = propertyValue->asObject()) {
if (QV4::QObjectWrapper *wrapper = o->as<QV4::QObjectWrapper>()) {
QObject *o = wrapper->object();
- const ListLayout::Role &role = m_layout->getRoleOrCreate(propertyName.getPointer(), ListLayout::Role::QObject);
+ const ListLayout::Role &role = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::QObject);
if (role.type == ListLayout::Role::QObject)
roleIndex = e->setQObjectProperty(role, o);
} else {
const ListLayout::Role &role = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::VariantMap);
if (role.type == ListLayout::Role::VariantMap) {
QV4::ScopedObject obj(scope, o);
- roleIndex = e->setVariantMapProperty(role, obj, eng);
+ roleIndex = e->setVariantMapProperty(role, obj);
}
}
} else if (propertyValue->isNullOrUndefined()) {
@@ -475,7 +475,7 @@ void ListModel::set(int elementIndex, QV4::Object *object, QVector<int> *roles,
}
}
-void ListModel::set(int elementIndex, QV4::Object *object, QV8Engine *eng)
+void ListModel::set(int elementIndex, QV4::Object *object)
{
if (!object)
return;
@@ -486,7 +486,7 @@ void ListModel::set(int elementIndex, QV4::Object *object, QV8Engine *eng)
QV4::Scope scope(v4);
QV4::ObjectIterator it(scope, object, QV4::ObjectIterator::WithProtoChain|QV4::ObjectIterator::EnumerableOnly);
- QV4::Scoped<QV4::String> propertyName(scope);
+ QV4::ScopedString propertyName(scope);
QV4::ScopedValue propertyValue(scope);
QV4::ScopedObject o(scope);
QV4::ScopedArrayObject a(scope);
@@ -515,7 +515,7 @@ void ListModel::set(int elementIndex, QV4::Object *object, QV8Engine *eng)
int arrayLength = a->getLength();
for (int j=0 ; j < arrayLength ; ++j) {
o = a->getIndexed(j);
- subModel->append(o, eng);
+ subModel->append(o);
}
e->setListPropertyFast(r, subModel);
@@ -542,7 +542,7 @@ void ListModel::set(int elementIndex, QV4::Object *object, QV8Engine *eng)
} else {
const ListLayout::Role &role = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::VariantMap);
if (role.type == ListLayout::Role::VariantMap)
- e->setVariantMapFast(role, o, eng);
+ e->setVariantMapFast(role, o);
}
} else if (propertyValue->isNullOrUndefined()) {
const ListLayout::Role *r = m_layout->getExistingRole(propertyName);
@@ -572,16 +572,16 @@ void ListModel::remove(int index, int count)
updateCacheIndices();
}
-void ListModel::insert(int elementIndex, QV4::Object *object, QV8Engine *eng)
+void ListModel::insert(int elementIndex, QV4::Object *object)
{
insertElement(elementIndex);
- set(elementIndex, object, eng);
+ set(elementIndex, object);
}
-int ListModel::append(QV4::Object *object, QV8Engine *eng)
+int ListModel::append(QV4::Object *object)
{
int elementIndex = appendElement();
- set(elementIndex, object, eng);
+ set(elementIndex, object);
return elementIndex;
}
@@ -607,7 +607,7 @@ int ListModel::setOrCreateProperty(int elementIndex, const QString &key, const Q
return roleIndex;
}
-int ListModel::setExistingProperty(int elementIndex, const QString &key, const QV4::ValueRef data, QV8Engine *eng)
+int ListModel::setExistingProperty(int elementIndex, const QString &key, const QV4::ValueRef data, QV4::ExecutionEngine *eng)
{
int roleIndex = -1;
@@ -701,7 +701,7 @@ ListModel *ListElement::getListProperty(const ListLayout::Role &role)
return *value;
}
-QVariant ListElement::getProperty(const ListLayout::Role &role, const QQmlListModel *owner, QV8Engine *eng)
+QVariant ListElement::getProperty(const ListLayout::Role &role, const QQmlListModel *owner, QV4::ExecutionEngine *eng)
{
char *mem = getPropertyMemory(role);
@@ -875,7 +875,7 @@ int ListElement::setQObjectProperty(const ListLayout::Role &role, QObject *o)
return roleIndex;
}
-int ListElement::setVariantMapProperty(const ListLayout::Role &role, QV4::Object *o, QV8Engine *eng)
+int ListElement::setVariantMapProperty(const ListLayout::Role &role, QV4::Object *o)
{
int roleIndex = -1;
@@ -885,7 +885,7 @@ int ListElement::setVariantMapProperty(const ListLayout::Role &role, QV4::Object
QVariantMap *map = reinterpret_cast<QVariantMap *>(mem);
map->~QMap();
}
- new (mem) QVariantMap(eng->variantMapFromJS(o));
+ new (mem) QVariantMap(o->engine()->variantMapFromJS(o));
roleIndex = role.index;
}
@@ -962,11 +962,11 @@ void ListElement::setListPropertyFast(const ListLayout::Role &role, ListModel *m
*value = m;
}
-void ListElement::setVariantMapFast(const ListLayout::Role &role, QV4::Object *o, QV8Engine *eng)
+void ListElement::setVariantMapFast(const ListLayout::Role &role, QV4::Object *o)
{
char *mem = getPropertyMemory(role);
QVariantMap *map = new (mem) QVariantMap;
- *map = eng->variantMapFromJS(o);
+ *map = o->engine()->variantMapFromJS(o);
}
void ListElement::setDateTimePropertyFast(const ListLayout::Role &role, const QDateTime &dt)
@@ -997,7 +997,7 @@ void ListElement::clearProperty(const ListLayout::Role &role)
setDateTimeProperty(role, QDateTime());
break;
case ListLayout::Role::VariantMap:
- setVariantMapProperty(role, 0);
+ setVariantMapProperty(role, (QVariantMap *)0);
break;
default:
break;
@@ -1163,12 +1163,12 @@ int ListElement::setVariantProperty(const ListLayout::Role &role, const QVariant
return roleIndex;
}
-int ListElement::setJsProperty(const ListLayout::Role &role, const QV4::ValueRef d, QV8Engine *eng)
+int ListElement::setJsProperty(const ListLayout::Role &role, const QV4::ValueRef d, QV4::ExecutionEngine *eng)
{
// Check if this key exists yet
int roleIndex = -1;
- QV4::Scope scope(QV8Engine::getV4(eng));
+ QV4::Scope scope(eng);
// Add the value now
if (d->isString()) {
@@ -1180,13 +1180,13 @@ int ListElement::setJsProperty(const ListLayout::Role &role, const QV4::ValueRef
QV4::ScopedArrayObject a(scope, d);
if (role.type == ListLayout::Role::List) {
QV4::Scope scope(a->engine());
- QV4::Scoped<QV4::Object> o(scope);
+ QV4::ScopedObject o(scope);
ListModel *subModel = new ListModel(role.subLayout, 0, -1);
int arrayLength = a->getLength();
for (int j=0 ; j < arrayLength ; ++j) {
o = a->getIndexed(j);
- subModel->append(o, eng);
+ subModel->append(o);
}
roleIndex = setListProperty(role, subModel);
} else {
@@ -1205,7 +1205,7 @@ int ListElement::setJsProperty(const ListLayout::Role &role, const QV4::ValueRef
QObject *o = wrapper->object();
roleIndex = setQObjectProperty(role, o);
} else if (role.type == ListLayout::Role::VariantMap) {
- roleIndex = setVariantMapProperty(role, o, eng);
+ roleIndex = setVariantMapProperty(role, o);
}
} else if (d->isNullOrUndefined()) {
clearProperty(role);
@@ -1258,15 +1258,13 @@ void ModelNodeMetaObject::propertyWritten(int index)
if (!m_enabled)
return;
- QV8Engine *eng = m_obj->m_model->engine();
-
QString propName = QString::fromUtf8(name(index));
QVariant value = operator[](index);
- QV4::Scope scope(QV8Engine::getV4((eng)));
- QV4::ScopedValue v(scope, eng->fromVariant(value));
+ QV4::Scope scope(m_obj->m_model->engine());
+ QV4::ScopedValue v(scope, scope.engine->fromVariant(value));
- int roleIndex = m_obj->m_model->m_listModel->setExistingProperty(m_obj->m_elementIndex, propName, v, eng);
+ int roleIndex = m_obj->m_model->m_listModel->setExistingProperty(m_obj->m_elementIndex, propName, v, scope.engine);
if (roleIndex != -1) {
QVector<int> roles;
roles << roleIndex;
@@ -1542,7 +1540,7 @@ QQmlListModel::QQmlListModel(QObject *parent)
m_engine = 0;
}
-QQmlListModel::QQmlListModel(const QQmlListModel *owner, ListModel *data, QV8Engine *eng, QObject *parent)
+QQmlListModel::QQmlListModel(const QQmlListModel *owner, ListModel *data, QV4::ExecutionEngine *engine, QObject *parent)
: QAbstractListModel(parent)
{
m_mainThread = owner->m_mainThread;
@@ -1554,7 +1552,7 @@ QQmlListModel::QQmlListModel(const QQmlListModel *owner, ListModel *data, QV8Eng
m_layout = 0;
m_listModel = data;
- m_engine = eng;
+ m_engine = engine;
}
QQmlListModel::QQmlListModel(QQmlListModel *orig, QQmlListModelWorkerAgent *agent)
@@ -1614,10 +1612,10 @@ QQmlListModel *QQmlListModel::createWithOwner(QQmlListModel *newOwner)
return model;
}
-QV8Engine *QQmlListModel::engine() const
+QV4::ExecutionEngine *QQmlListModel::engine() const
{
if (m_engine == 0) {
- m_engine = QQmlEnginePrivate::getV8Engine(qmlEngine(this));
+ m_engine = QQmlEnginePrivate::get(qmlEngine(this))->v4engine();
}
return m_engine;
@@ -1985,9 +1983,9 @@ void QQmlListModel::insert(QQmlV4Function *args)
argObject = objectArray->getIndexed(i);
if (m_dynamicRoles) {
- m_modelObjects.insert(index+i, DynamicRoleModelNode::create(args->engine()->variantMapFromJS(argObject), this));
+ m_modelObjects.insert(index+i, DynamicRoleModelNode::create(scope.engine->variantMapFromJS(argObject), this));
} else {
- m_listModel->insert(index+i, argObject, args->engine());
+ m_listModel->insert(index+i, argObject);
}
}
emitItemsInserted(index, objectArrayLength);
@@ -1995,9 +1993,9 @@ void QQmlListModel::insert(QQmlV4Function *args)
emitItemsAboutToBeInserted(index, 1);
if (m_dynamicRoles) {
- m_modelObjects.insert(index, DynamicRoleModelNode::create(args->engine()->variantMapFromJS(argObject), this));
+ m_modelObjects.insert(index, DynamicRoleModelNode::create(scope.engine->variantMapFromJS(argObject), this));
} else {
- m_listModel->insert(index, argObject, args->engine());
+ m_listModel->insert(index, argObject);
}
emitItemsInserted(index, 1);
@@ -2084,7 +2082,7 @@ void QQmlListModel::append(QQmlV4Function *args)
QV4::ScopedArrayObject objectArray(scope, (*args)[0]);
if (objectArray) {
- QV4::Scoped<QV4::Object> argObject(scope);
+ QV4::ScopedObject argObject(scope);
int objectArrayLength = objectArray->getLength();
@@ -2095,9 +2093,9 @@ void QQmlListModel::append(QQmlV4Function *args)
argObject = objectArray->getIndexed(i);
if (m_dynamicRoles) {
- m_modelObjects.append(DynamicRoleModelNode::create(args->engine()->variantMapFromJS(argObject), this));
+ m_modelObjects.append(DynamicRoleModelNode::create(scope.engine->variantMapFromJS(argObject), this));
} else {
- m_listModel->append(argObject, args->engine());
+ m_listModel->append(argObject);
}
}
@@ -2108,11 +2106,11 @@ void QQmlListModel::append(QQmlV4Function *args)
if (m_dynamicRoles) {
index = m_modelObjects.count();
emitItemsAboutToBeInserted(index, 1);
- m_modelObjects.append(DynamicRoleModelNode::create(args->engine()->variantMapFromJS(argObject), this));
+ m_modelObjects.append(DynamicRoleModelNode::create(scope.engine->variantMapFromJS(argObject), this));
} else {
index = m_listModel->elementCount();
emitItemsAboutToBeInserted(index, 1);
- m_listModel->append(argObject, args->engine());
+ m_listModel->append(argObject);
}
emitItemsInserted(index, 1);
@@ -2157,18 +2155,17 @@ void QQmlListModel::append(QQmlV4Function *args)
*/
QQmlV4Handle QQmlListModel::get(int index) const
{
- QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine());
- QV4::Scope scope(v4);
+ QV4::Scope scope(engine());
QV4::ScopedValue result(scope, QV4::Primitive::undefinedValue());
if (index >= 0 && index < count()) {
if (m_dynamicRoles) {
DynamicRoleModelNode *object = m_modelObjects[index];
- result = QV4::QObjectWrapper::wrap(v4, object);
+ result = QV4::QObjectWrapper::wrap(scope.engine, object);
} else {
ModelObject *object = m_listModel->getOrCreateModelObject(const_cast<QQmlListModel *>(this), index);
- result = QV4::QObjectWrapper::wrap(v4, object);
+ result = QV4::QObjectWrapper::wrap(scope.engine, object);
}
}
@@ -2193,7 +2190,7 @@ QQmlV4Handle QQmlListModel::get(int index) const
*/
void QQmlListModel::set(int index, const QQmlV4Handle &handle)
{
- QV4::Scope scope(QV8Engine::getV4(engine()));
+ QV4::Scope scope(engine());
QV4::ScopedObject object(scope, handle);
if (!object) {
@@ -2210,9 +2207,9 @@ void QQmlListModel::set(int index, const QQmlV4Handle &handle)
emitItemsAboutToBeInserted(index, 1);
if (m_dynamicRoles) {
- m_modelObjects.append(DynamicRoleModelNode::create(engine()->variantMapFromJS(object), this));
+ m_modelObjects.append(DynamicRoleModelNode::create(scope.engine->variantMapFromJS(object), this));
} else {
- m_listModel->insert(index, object, engine());
+ m_listModel->insert(index, object);
}
emitItemsInserted(index, 1);
@@ -2221,9 +2218,9 @@ void QQmlListModel::set(int index, const QQmlV4Handle &handle)
QVector<int> roles;
if (m_dynamicRoles) {
- m_modelObjects[index]->updateValues(engine()->variantMapFromJS(object), roles);
+ m_modelObjects[index]->updateValues(scope.engine->variantMapFromJS(object), roles);
} else {
- m_listModel->set(index, object, &roles, engine());
+ m_listModel->set(index, object, &roles);
}
if (roles.count())
@@ -2414,8 +2411,7 @@ void QQmlListModelParser::applyBindings(QObject *obj, QQmlCompiledData *cdata, c
{
QQmlListModel *rv = static_cast<QQmlListModel *>(obj);
- QV8Engine *engine = QQmlEnginePrivate::getV8Engine(qmlEngine(rv));
- rv->m_engine = engine;
+ rv->m_engine = QV8Engine::getV4(qmlEngine(rv));
const QV4::CompiledData::Unit *qmlUnit = cdata->compilationUnit->data;
diff --git a/src/qml/types/qqmllistmodel_p.h b/src/qml/types/qqmllistmodel_p.h
index debe7ee98d..4dfd2028fe 100644
--- a/src/qml/types/qqmllistmodel_p.h
+++ b/src/qml/types/qqmllistmodel_p.h
@@ -44,7 +44,7 @@
#include <QtCore/QVariant>
#include <QtCore/qabstractitemmodel.h>
-#include <private/qv8engine_p.h>
+#include <private/qv4engine_p.h>
#include <private/qpodvector_p.h>
QT_BEGIN_NAMESPACE
@@ -102,14 +102,14 @@ private:
// Constructs a flat list model for a worker agent
QQmlListModel(QQmlListModel *orig, QQmlListModelWorkerAgent *agent);
- QQmlListModel(const QQmlListModel *owner, ListModel *data, QV8Engine *eng, QObject *parent=0);
+ QQmlListModel(const QQmlListModel *owner, ListModel *data, QV4::ExecutionEngine *engine, QObject *parent=0);
- QV8Engine *engine() const;
+ QV4::ExecutionEngine *engine() const;
inline bool canMove(int from, int to, int n) const { return !(from+n > count() || to+n > count() || from < 0 || to < 0 || n < 0); }
QQmlListModelWorkerAgent *m_agent;
- mutable QV8Engine *m_engine;
+ mutable QV4::ExecutionEngine *m_engine;
bool m_mainThread;
bool m_primary;
diff --git a/src/qml/types/qqmllistmodel_p_p.h b/src/qml/types/qqmllistmodel_p_p.h
index 9e70e6ad54..36d192f2fa 100644
--- a/src/qml/types/qqmllistmodel_p_p.h
+++ b/src/qml/types/qqmllistmodel_p_p.h
@@ -245,14 +245,14 @@ private:
int setVariantProperty(const ListLayout::Role &role, const QVariant &d);
- int setJsProperty(const ListLayout::Role &role, const QV4::ValueRef d, QV8Engine *eng);
+ int setJsProperty(const ListLayout::Role &role, const QV4::ValueRef d, QV4::ExecutionEngine *eng);
int setStringProperty(const ListLayout::Role &role, const QString &s);
int setDoubleProperty(const ListLayout::Role &role, double n);
int setBoolProperty(const ListLayout::Role &role, bool b);
int setListProperty(const ListLayout::Role &role, ListModel *m);
int setQObjectProperty(const ListLayout::Role &role, QObject *o);
- int setVariantMapProperty(const ListLayout::Role &role, QV4::Object *o, QV8Engine *eng);
+ int setVariantMapProperty(const ListLayout::Role &role, QV4::Object *o);
int setVariantMapProperty(const ListLayout::Role &role, QVariantMap *m);
int setDateTimeProperty(const ListLayout::Role &role, const QDateTime &dt);
@@ -261,12 +261,12 @@ private:
void setBoolPropertyFast(const ListLayout::Role &role, bool b);
void setQObjectPropertyFast(const ListLayout::Role &role, QObject *o);
void setListPropertyFast(const ListLayout::Role &role, ListModel *m);
- void setVariantMapFast(const ListLayout::Role &role, QV4::Object *o, QV8Engine *eng);
+ void setVariantMapFast(const ListLayout::Role &role, QV4::Object *o);
void setDateTimePropertyFast(const ListLayout::Role &role, const QDateTime &dt);
void clearProperty(const ListLayout::Role &role);
- QVariant getProperty(const ListLayout::Role &role, const QQmlListModel *owner, QV8Engine *eng);
+ QVariant getProperty(const ListLayout::Role &role, const QQmlListModel *owner, QV4::ExecutionEngine *eng);
ListModel *getListProperty(const ListLayout::Role &role);
QString *getStringProperty(const ListLayout::Role &role);
QObject *getQObjectProperty(const ListLayout::Role &role);
@@ -300,9 +300,9 @@ public:
void destroy();
int setOrCreateProperty(int elementIndex, const QString &key, const QVariant &data);
- int setExistingProperty(int uid, const QString &key, const QV4::ValueRef data, QV8Engine *eng);
+ int setExistingProperty(int uid, const QString &key, const QV4::ValueRef data, QV4::ExecutionEngine *eng);
- QVariant getProperty(int elementIndex, int roleIndex, const QQmlListModel *owner, QV8Engine *eng);
+ QVariant getProperty(int elementIndex, int roleIndex, const QQmlListModel *owner, QV4::ExecutionEngine *eng);
ListModel *getListProperty(int elementIndex, const ListLayout::Role &role);
int roleCount() const
@@ -325,11 +325,11 @@ public:
return elements.count();
}
- void set(int elementIndex, QV4::Object *object, QVector<int> *roles, QV8Engine *eng);
- void set(int elementIndex, QV4::Object *object, QV8Engine *eng);
+ void set(int elementIndex, QV4::Object *object, QVector<int> *roles);
+ void set(int elementIndex, QV4::Object *object);
- int append(QV4::Object *object, QV8Engine *eng);
- void insert(int elementIndex, QV4::Object *object, QV8Engine *eng);
+ int append(QV4::Object *object);
+ void insert(int elementIndex, QV4::Object *object);
void clear();
void remove(int index, int count);
diff --git a/src/qml/types/qqmllistmodelworkeragent.cpp b/src/qml/types/qqmllistmodelworkeragent.cpp
index 35369bfe87..05a5172c35 100644
--- a/src/qml/types/qqmllistmodelworkeragent.cpp
+++ b/src/qml/types/qqmllistmodelworkeragent.cpp
@@ -91,7 +91,7 @@ QQmlListModelWorkerAgent::~QQmlListModelWorkerAgent()
mutex.unlock();
}
-void QQmlListModelWorkerAgent::setV8Engine(QV8Engine *eng)
+void QQmlListModelWorkerAgent::setEngine(QV4::ExecutionEngine *eng)
{
m_copy->m_engine = eng;
}
diff --git a/src/qml/types/qqmllistmodelworkeragent_p.h b/src/qml/types/qqmllistmodelworkeragent_p.h
index 7a8f6e6593..ecee48e9bd 100644
--- a/src/qml/types/qqmllistmodelworkeragent_p.h
+++ b/src/qml/types/qqmllistmodelworkeragent_p.h
@@ -65,7 +65,7 @@ class QQmlListModelWorkerAgent : public QObject
public:
QQmlListModelWorkerAgent(QQmlListModel *);
~QQmlListModelWorkerAgent();
- void setV8Engine(QV8Engine *eng);
+ void setEngine(QV4::ExecutionEngine *eng);
void addref();
void release();
diff --git a/src/qml/types/qquickworkerscript.cpp b/src/qml/types/qquickworkerscript.cpp
index f2705aca44..4ad2c34247 100644
--- a/src/qml/types/qquickworkerscript.cpp
+++ b/src/qml/types/qquickworkerscript.cpp
@@ -221,18 +221,19 @@ void QQuickWorkerScriptEnginePrivate::WorkerEngine::init()
"})"
QV4::Scope scope(m_v4Engine);
- onmessage = QV4::Script(m_v4Engine->rootContext, QString::fromUtf8(CALL_ONMESSAGE_SCRIPT)).run(); // do not use QStringLiteral here, MSVC2012 cannot apply this cleanly to the macro
+ QV4::ScopedContext globalContext(scope, scope.engine->rootContext());
+ onmessage.set(scope.engine, QV4::Script(globalContext, QString::fromUtf8(CALL_ONMESSAGE_SCRIPT)).run()); // do not use QStringLiteral here, MSVC2012 cannot apply this cleanly to the macro
Q_ASSERT(!scope.engine->hasException);
- QV4::Script createsendscript(m_v4Engine->rootContext, QString::fromUtf8(SEND_MESSAGE_CREATE_SCRIPT)); // do not use QStringLiteral here, MSVC2012 cannot apply this cleanly to the macro
- QV4::Scoped<QV4::FunctionObject> createsendconstructor(scope, createsendscript.run());
+ QV4::Script createsendscript(globalContext, QString::fromUtf8(SEND_MESSAGE_CREATE_SCRIPT)); // do not use QStringLiteral here, MSVC2012 cannot apply this cleanly to the macro
+ QV4::ScopedFunctionObject createsendconstructor(scope, createsendscript.run());
Q_ASSERT(!scope.engine->hasException);
QV4::ScopedString name(scope, m_v4Engine->newString(QStringLiteral("sendMessage")));
- QV4::ScopedValue function(scope, QV4::BuiltinFunction::create(m_v4Engine->rootContext, name.getPointer(),
+ QV4::ScopedValue function(scope, QV4::BuiltinFunction::create(globalContext, name,
QQuickWorkerScriptEnginePrivate::method_sendMessage));
QV4::ScopedCallData callData(scope, 1);
callData->args[0] = function;
callData->thisObject = global();
- createsend = createsendconstructor->call(callData);
+ createsend.set(scope.engine, createsendconstructor->call(callData));
}
// Requires handle and context scope
@@ -244,7 +245,6 @@ QV4::ReturnedValue QQuickWorkerScriptEnginePrivate::WorkerEngine::sendFunction(i
QV4::Scope scope(v4);
QV4::ScopedFunctionObject f(scope, createsend.value());
- QV4::ExecutionContext *ctx = v4->currentContext();
QV4::ScopedValue v(scope);
QV4::ScopedCallData callData(scope, 1);
@@ -252,7 +252,7 @@ QV4::ReturnedValue QQuickWorkerScriptEnginePrivate::WorkerEngine::sendFunction(i
callData->thisObject = global();
v = f->call(callData);
if (scope.hasException())
- v = ctx->catchException();
+ v = scope.engine->catchException();
return v.asReturnedValue();
}
@@ -281,7 +281,7 @@ QV4::ReturnedValue QQuickWorkerScriptEnginePrivate::method_sendMessage(QV4::Call
QV4::Scope scope(ctx);
QV4::ScopedValue v(scope, ctx->d()->callData->argument(2));
- QByteArray data = QV4::Serialize::serialize(v, engine);
+ QByteArray data = QV4::Serialize::serialize(v, scope.engine);
QMutexLocker locker(&engine->p->m_lock);
WorkerScript *script = engine->p->workers.value(id);
@@ -300,16 +300,16 @@ QV4::ReturnedValue QQuickWorkerScriptEnginePrivate::getWorker(WorkerScript *scri
QV4::ExecutionEngine *v4 = QV8Engine::getV4(workerEngine);
QV4::Scope scope(v4);
- script->object = QV4::QmlContextWrapper::urlScope(workerEngine, script->source);
+ script->object.set(v4, QV4::QmlContextWrapper::urlScope(v4, script->source));
QV4::Scoped<QV4::QmlContextWrapper> w(scope, script->object.value());
Q_ASSERT(!!w);
w->setReadOnly(false);
- QV4::Scoped<QV4::Object> api(scope, v4->newObject());
- api->put(QV4::ScopedString(scope, v4->newString(QStringLiteral("sendMessage"))).getPointer(), QV4::ScopedValue(scope, workerEngine->sendFunction(script->id)));
+ QV4::ScopedObject api(scope, v4->newObject());
+ api->put(QV4::ScopedString(scope, v4->newString(QStringLiteral("sendMessage"))), QV4::ScopedValue(scope, workerEngine->sendFunction(script->id)));
- w->QV4::Object::put(QV4::ScopedString(scope, v4->newString(QStringLiteral("WorkerScript"))).getPointer(), api);
+ w->QV4::Object::put(QV4::ScopedString(scope, v4->newString(QStringLiteral("WorkerScript"))), api);
w->setReadOnly(true);
}
@@ -352,9 +352,8 @@ void QQuickWorkerScriptEnginePrivate::processMessage(int id, const QByteArray &d
QV4::ExecutionEngine *v4 = QV8Engine::getV4(workerEngine);
QV4::Scope scope(v4);
QV4::ScopedFunctionObject f(scope, workerEngine->onmessage.value());
- QV4::ExecutionContext *ctx = v4->currentContext();
- QV4::ScopedValue value(scope, QV4::Serialize::deserialize(data, workerEngine));
+ QV4::ScopedValue value(scope, QV4::Serialize::deserialize(data, v4));
QV4::ScopedCallData callData(scope, 2);
callData->thisObject = workerEngine->global();
@@ -362,7 +361,7 @@ void QQuickWorkerScriptEnginePrivate::processMessage(int id, const QByteArray &d
callData->args[1] = value;
f->call(callData);
if (scope.hasException()) {
- QQmlError error = QV4::ExecutionEngine::catchExceptionAsQmlError(ctx);
+ QQmlError error = scope.engine->catchExceptionAsQmlError();
reportScriptException(script, error);
}
}
@@ -383,7 +382,7 @@ void QQuickWorkerScriptEnginePrivate::processLoad(int id, const QUrl &url)
return;
script->source = url;
- QV4::Scoped<QV4::Object> activation(scope, getWorker(script));
+ QV4::ScopedObject activation(scope, getWorker(script));
if (!activation)
return;
@@ -409,8 +408,7 @@ void QQuickWorkerScriptEnginePrivate::processLoad(int id, const QUrl &url)
program->run();
if (v4->hasException) {
- QV4::ExecutionContext *ctx = v4->currentContext();
- QQmlError error = QV4::ExecutionEngine::catchExceptionAsQmlError(ctx);
+ QQmlError error = v4->catchExceptionAsQmlError();
reportScriptException(script, error);
}
}
@@ -684,7 +682,7 @@ void QQuickWorkerScript::sendMessage(QQmlV4Function *args)
if (args->length() != 0)
argument = (*args)[0];
- m_engine->sendMessage(m_scriptId, QV4::Serialize::serialize(argument, args->engine()));
+ m_engine->sendMessage(m_scriptId, QV4::Serialize::serialize(argument, scope.engine));
}
void QQuickWorkerScript::classBegin()
@@ -736,7 +734,7 @@ bool QQuickWorkerScript::event(QEvent *event)
WorkerDataEvent *workerEvent = static_cast<WorkerDataEvent *>(event);
QV8Engine *v8engine = QQmlEnginePrivate::get(engine)->v8engine();
QV4::Scope scope(QV8Engine::getV4(v8engine));
- QV4::ScopedValue value(scope, QV4::Serialize::deserialize(workerEvent->data(), v8engine));
+ QV4::ScopedValue value(scope, QV4::Serialize::deserialize(workerEvent->data(), scope.engine));
emit message(QQmlV4Handle(value));
}
return true;
diff --git a/src/qml/util/qqmladaptormodel.cpp b/src/qml/util/qqmladaptormodel.cpp
index b147f56bfa..4cf34ae078 100644
--- a/src/qml/util/qqmladaptormodel.cpp
+++ b/src/qml/util/qqmladaptormodel.cpp
@@ -46,21 +46,21 @@ QT_BEGIN_NAMESPACE
class QQmlAdaptorModelEngineData : public QV8Engine::Deletable
{
public:
- QQmlAdaptorModelEngineData(QV8Engine *engine);
+ QQmlAdaptorModelEngineData(QV4::ExecutionEngine *v4);
~QQmlAdaptorModelEngineData();
QV4::ExecutionEngine *v4;
QV4::PersistentValue listItemProto;
};
-V8_DEFINE_EXTENSION(QQmlAdaptorModelEngineData, engineData)
+V4_DEFINE_EXTENSION(QQmlAdaptorModelEngineData, engineData)
static QV4::ReturnedValue get_index(QV4::CallContext *ctx)
{
QV4::Scope scope(ctx);
QV4::Scoped<QQmlDelegateModelItemObject> o(scope, ctx->d()->callData->thisObject.as<QQmlDelegateModelItemObject>());
if (!o)
- return ctx->throwTypeError(QStringLiteral("Not a valid VisualData object"));
+ return ctx->engine()->throwTypeError(QStringLiteral("Not a valid VisualData object"));
return QV4::Encode(o->d()->item->index);
}
@@ -192,7 +192,7 @@ public:
QV4::Scope scope(ctx);
QV4::Scoped<QQmlDelegateModelItemObject> o(scope, ctx->d()->callData->thisObject.as<QQmlDelegateModelItemObject>());
if (!o)
- return ctx->throwTypeError(QStringLiteral("Not a valid VisualData object"));
+ return ctx->engine()->throwTypeError(QStringLiteral("Not a valid VisualData object"));
const QQmlAdaptorModel *const model = static_cast<QQmlDMCachedModelData *>(o->d()->item)->type->model;
if (o->d()->item->index >= 0 && *model) {
@@ -208,7 +208,7 @@ public:
{
QV4::ExecutionEngine *v4 = data->v4;
QV4::Scope scope(v4);
- QV4::Scoped<QV4::Object> proto(scope, v4->newObject());
+ QV4::ScopedObject proto(scope, v4->newObject());
proto->defineAccessorProperty(QStringLiteral("index"), get_index, 0);
proto->defineAccessorProperty(QStringLiteral("hasModelChildren"), get_hasModelChildren, 0);
QV4::ScopedProperty p(scope);
@@ -219,13 +219,14 @@ public:
const QByteArray &propertyName = it.key();
QV4::ScopedString name(scope, v4->newString(QString::fromUtf8(propertyName)));
- QV4::ScopedFunctionObject g(scope, v4->memoryManager->alloc<QV4::IndexedBuiltinFunction>(v4->rootContext, propertyId, QQmlDMCachedModelData::get_property));
- QV4::ScopedFunctionObject s(scope, v4->memoryManager->alloc<QV4::IndexedBuiltinFunction>(v4->rootContext, propertyId, QQmlDMCachedModelData::set_property));
+ QV4::ScopedContext global(scope, v4->rootContext());
+ QV4::ScopedFunctionObject g(scope, v4->memoryManager->alloc<QV4::IndexedBuiltinFunction>(global, propertyId, QQmlDMCachedModelData::get_property));
+ QV4::ScopedFunctionObject s(scope, v4->memoryManager->alloc<QV4::IndexedBuiltinFunction>(global, propertyId, QQmlDMCachedModelData::set_property));
p->setGetter(g);
p->setSetter(s);
- proto->insertMember(name.getPointer(), p, QV4::Attr_Accessor|QV4::Attr_NotEnumerable|QV4::Attr_NotConfigurable);
+ proto->insertMember(name, p, QV4::Attr_Accessor|QV4::Attr_NotEnumerable|QV4::Attr_NotConfigurable);
}
- prototype = proto;
+ prototype.set(v4, proto);
}
// QAbstractDynamicMetaObject
@@ -339,16 +340,16 @@ QV4::ReturnedValue QQmlDMCachedModelData::get_property(QV4::CallContext *ctx, ui
QV4::Scope scope(ctx);
QV4::Scoped<QQmlDelegateModelItemObject> o(scope, ctx->d()->callData->thisObject.as<QQmlDelegateModelItemObject>());
if (!o)
- return ctx->throwTypeError(QStringLiteral("Not a valid VisualData object"));
+ return ctx->engine()->throwTypeError(QStringLiteral("Not a valid VisualData object"));
QQmlDMCachedModelData *modelData = static_cast<QQmlDMCachedModelData *>(o->d()->item);
if (o->d()->item->index == -1) {
if (!modelData->cachedData.isEmpty()) {
- return ctx->d()->engine->v8Engine->fromVariant(
+ return scope.engine->fromVariant(
modelData->cachedData.at(modelData->type->hasModelData ? 0 : propertyId));
}
} else if (*modelData->type->model) {
- return ctx->d()->engine->v8Engine->fromVariant(
+ return scope.engine->fromVariant(
modelData->value(modelData->type->propertyRoles.at(propertyId)));
}
return QV4::Encode::undefined();
@@ -359,18 +360,18 @@ QV4::ReturnedValue QQmlDMCachedModelData::set_property(QV4::CallContext *ctx, ui
QV4::Scope scope(ctx);
QV4::Scoped<QQmlDelegateModelItemObject> o(scope, ctx->d()->callData->thisObject.as<QQmlDelegateModelItemObject>());
if (!o)
- return ctx->throwTypeError(QStringLiteral("Not a valid VisualData object"));
+ return ctx->engine()->throwTypeError(QStringLiteral("Not a valid VisualData object"));
if (!ctx->d()->callData->argc)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
if (o->d()->item->index == -1) {
QQmlDMCachedModelData *modelData = static_cast<QQmlDMCachedModelData *>(o->d()->item);
if (!modelData->cachedData.isEmpty()) {
if (modelData->cachedData.count() > 1) {
- modelData->cachedData[propertyId] = scope.engine->v8Engine->toVariant(ctx->d()->callData->args[0], QVariant::Invalid);
+ modelData->cachedData[propertyId] = scope.engine->toVariant(ctx->d()->callData->args[0], QVariant::Invalid);
QMetaObject::activate(o->d()->item, o->d()->item->metaObject(), propertyId, 0);
} else if (modelData->cachedData.count() == 1) {
- modelData->cachedData[0] = scope.engine->v8Engine->toVariant(ctx->d()->callData->args[0], QVariant::Invalid);
+ modelData->cachedData[0] = scope.engine->toVariant(ctx->d()->callData->args[0], QVariant::Invalid);
QMetaObject::activate(o->d()->item, o->d()->item->metaObject(), 0, 0);
QMetaObject::activate(o->d()->item, o->d()->item->metaObject(), 1, 0);
}
@@ -420,13 +421,13 @@ public:
QV4::ReturnedValue get()
{
if (type->prototype.isUndefined()) {
- QQmlAdaptorModelEngineData * const data = engineData(v4->v8Engine);
+ QQmlAdaptorModelEngineData * const data = engineData(v4);
type->initializeConstructor(data);
}
QV4::Scope scope(v4);
QV4::ScopedObject proto(scope, type->prototype.value());
QV4::ScopedObject o(scope, proto->engine()->memoryManager->alloc<QQmlDelegateModelItemObject>(proto->engine(), this));
- o->setPrototype(proto.getPointer());
+ o->setPrototype(proto);
++scriptRef;
return o.asReturnedValue();
}
@@ -581,9 +582,9 @@ public:
QV4::Scope scope(ctx);
QV4::Scoped<QQmlDelegateModelItemObject> o(scope, ctx->d()->callData->thisObject.as<QQmlDelegateModelItemObject>());
if (!o)
- return ctx->throwTypeError(QStringLiteral("Not a valid VisualData object"));
+ return ctx->engine()->throwTypeError(QStringLiteral("Not a valid VisualData object"));
- return scope.engine->v8Engine->fromVariant(static_cast<QQmlDMListAccessorData *>(o->d()->item)->cachedData);
+ return scope.engine->fromVariant(static_cast<QQmlDMListAccessorData *>(o->d()->item)->cachedData);
}
static QV4::ReturnedValue set_modelData(QV4::CallContext *ctx)
@@ -591,21 +592,21 @@ public:
QV4::Scope scope(ctx);
QV4::Scoped<QQmlDelegateModelItemObject> o(scope, ctx->d()->callData->thisObject.as<QQmlDelegateModelItemObject>());
if (!o)
- return ctx->throwTypeError(QStringLiteral("Not a valid VisualData object"));
+ return ctx->engine()->throwTypeError(QStringLiteral("Not a valid VisualData object"));
if (!ctx->d()->callData->argc)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
- static_cast<QQmlDMListAccessorData *>(o->d()->item)->setModelData(scope.engine->v8Engine->toVariant(ctx->d()->callData->args[0], QVariant::Invalid));
+ static_cast<QQmlDMListAccessorData *>(o->d()->item)->setModelData(scope.engine->toVariant(ctx->d()->callData->args[0], QVariant::Invalid));
return QV4::Encode::undefined();
}
QV4::ReturnedValue get()
{
- QQmlAdaptorModelEngineData *data = engineData(v4->v8Engine);
+ QQmlAdaptorModelEngineData *data = engineData(v4);
QV4::Scope scope(v4);
QV4::ScopedObject o(scope, v4->memoryManager->alloc<QQmlDelegateModelItemObject>(v4, this));
QV4::ScopedObject p(scope, data->listItemProto.value());
- o->setPrototype(p.getPointer());
+ o->setPrototype(p);
++scriptRef;
return o.asReturnedValue();
}
@@ -954,15 +955,15 @@ void QQmlAdaptorModel::objectDestroyed(QObject *)
setModel(QVariant(), 0, 0);
}
-QQmlAdaptorModelEngineData::QQmlAdaptorModelEngineData(QV8Engine *e)
- : v4(QV8Engine::getV4(e))
+QQmlAdaptorModelEngineData::QQmlAdaptorModelEngineData(QV4::ExecutionEngine *v4)
+ : v4(v4)
{
QV4::Scope scope(v4);
- QV4::Scoped<QV4::Object> proto(scope, v4->newObject());
+ QV4::ScopedObject proto(scope, v4->newObject());
proto->defineAccessorProperty(QStringLiteral("index"), get_index, 0);
proto->defineAccessorProperty(QStringLiteral("modelData"),
QQmlDMListAccessorData::get_modelData, QQmlDMListAccessorData::set_modelData);
- listItemProto = proto;
+ listItemProto.set(v4, proto);
}
QQmlAdaptorModelEngineData::~QQmlAdaptorModelEngineData()
diff --git a/src/qmltest/quicktest.cpp b/src/qmltest/quicktest.cpp
index bef20c6464..08329bbed7 100644
--- a/src/qmltest/quicktest.cpp
+++ b/src/qmltest/quicktest.cpp
@@ -215,9 +215,11 @@ int quick_test_main(int argc, char **argv, const char *name, const char *sourceD
// Look for QML-specific command-line options.
// -import dir Specify an import directory.
+ // -plugins dir Specify a directory where to search for plugins.
// -input dir Specify the input directory for test cases.
// -translation file Specify the translation file.
QStringList imports;
+ QStringList pluginPaths;
QString testPath;
QString translationFile;
int index = 1;
@@ -228,6 +230,9 @@ int quick_test_main(int argc, char **argv, const char *name, const char *sourceD
if (strcmp(argv[index], "-import") == 0 && (index + 1) < argc) {
imports += stripQuotes(QString::fromLocal8Bit(argv[index + 1]));
index += 2;
+ } else if (strcmp(argv[index], "-plugins") == 0 && (index + 1) < argc) {
+ pluginPaths += stripQuotes(QString::fromLocal8Bit(argv[index + 1]));
+ index += 2;
} else if (strcmp(argv[index], "-input") == 0 && (index + 1) < argc) {
testPath = stripQuotes(QString::fromLocal8Bit(argv[index + 1]));
index += 2;
@@ -327,6 +332,8 @@ int quick_test_main(int argc, char **argv, const char *name, const char *sourceD
(QLatin1String("qtest"), QTestRootObject::instance()); // Deprecated. Use QTestRootObject from Qt.test.qtestroot instead
foreach (const QString &path, imports)
view->engine()->addImportPath(path);
+ foreach (const QString &path, pluginPaths)
+ view->engine()->addPluginPath(path);
foreach (const QString &file, files) {
const QFileInfo fi(file);
if (!fi.exists())
diff --git a/src/qmltest/quicktestresult.cpp b/src/qmltest/quicktestresult.cpp
index 868a378318..8c2ac82df7 100644
--- a/src/qmltest/quicktestresult.cpp
+++ b/src/qmltest/quicktestresult.cpp
@@ -475,13 +475,12 @@ void QuickTestResult::stringify(QQmlV4Function *args)
QV4::ScopedValue value(scope, (*args)[0]);
QString result;
- QV8Engine *engine = args->engine();
//Check for Object Type
if (value->isObject()
&& !value->asFunctionObject()
&& !value->asArrayObject()) {
- QVariant v = engine->toVariant(value, QMetaType::UnknownType);
+ QVariant v = scope.engine->toVariant(value, QMetaType::UnknownType);
if (v.isValid()) {
switch (v.type()) {
case QVariant::Vector3D:
@@ -505,7 +504,7 @@ void QuickTestResult::stringify(QQmlV4Function *args)
result.append(tmp);
}
- args->setReturnValue(args->engine()->toString(result));
+ args->setReturnValue(QV4::Encode(args->v4engine()->newString(result)));
}
bool QuickTestResult::compare
diff --git a/src/quick/accessible/accessible.pri b/src/quick/accessible/accessible.pri
index 88ff747488..bff1325bd9 100644
--- a/src/quick/accessible/accessible.pri
+++ b/src/quick/accessible/accessible.pri
@@ -4,13 +4,11 @@ QT += core-private gui-private qml-private
#DEFINES+=Q_ACCESSIBLE_QUICK_ITEM_ENABLE_DEBUG_DESCRIPTION
SOURCES += \
- $$PWD/qqmlaccessible.cpp \
$$PWD/qaccessiblequickview.cpp \
$$PWD/qaccessiblequickitem.cpp \
$$PWD/qquickaccessiblefactory.cpp \
HEADERS += \
- $$PWD/qqmlaccessible_p.h \
$$PWD/qaccessiblequickview_p.h \
$$PWD/qaccessiblequickitem_p.h \
$$PWD/qquickaccessiblefactory_p.h \
diff --git a/src/quick/accessible/qaccessiblequickitem.cpp b/src/quick/accessible/qaccessiblequickitem.cpp
index e13224f6fb..f86dcc1f13 100644
--- a/src/quick/accessible/qaccessiblequickitem.cpp
+++ b/src/quick/accessible/qaccessiblequickitem.cpp
@@ -44,7 +44,7 @@ QT_BEGIN_NAMESPACE
#ifndef QT_NO_ACCESSIBILITY
QAccessibleQuickItem::QAccessibleQuickItem(QQuickItem *item)
- : QQmlAccessible(item), m_doc(textDocument())
+ : QAccessibleObject(item), m_doc(textDocument())
{
}
@@ -178,16 +178,22 @@ QAccessible::State QAccessibleQuickItem::state() const
if (!attached)
return QAccessible::State();
- QAccessible::State st = attached->state();
+ QAccessible::State state = attached->state();
- if (!item()->window() || !item()->window()->isVisible() ||!item()->isVisible() || qFuzzyIsNull(item()->opacity()))
- st.invisible = true;
+ QRect viewRect_ = viewRect();
+ QRect itemRect = rect();
- if (item()->activeFocusOnTab())
- st.focusable = true;
+ if (viewRect_.isNull() || itemRect.isNull() || !item()->window() || !item()->window()->isVisible() ||!item()->isVisible() || qFuzzyIsNull(item()->opacity()))
+ state.invisible = true;
+ if (!viewRect_.intersects(itemRect))
+ state.offscreen = true;
+ if ((role() == QAccessible::CheckBox || role() == QAccessible::RadioButton) && object()->property("checked").toBool())
+ state.checked = true;
+ if (item()->activeFocusOnTab() || role() == QAccessible::EditableText)
+ state.focusable = true;
if (item()->hasActiveFocus())
- st.focused = true;
- return st;
+ state.focused = true;
+ return state;
}
QAccessible::Role QAccessibleQuickItem::role() const
@@ -213,11 +219,29 @@ bool QAccessibleQuickItem::isAccessible() const
QStringList QAccessibleQuickItem::actionNames() const
{
- QStringList actions = QQmlAccessible::actionNames();
+ QStringList actions;
+ switch (role()) {
+ case QAccessible::PushButton:
+ actions << QAccessibleActionInterface::pressAction();
+ break;
+ case QAccessible::RadioButton:
+ case QAccessible::CheckBox:
+ actions << QAccessibleActionInterface::toggleAction()
+ << QAccessibleActionInterface::pressAction();
+ break;
+ case QAccessible::Slider:
+ case QAccessible::SpinBox:
+ case QAccessible::ScrollBar:
+ actions << QAccessibleActionInterface::increaseAction()
+ << QAccessibleActionInterface::decreaseAction();
+ break;
+ default:
+ break;
+ }
if (state().focusable)
actions.append(QAccessibleActionInterface::setFocusAction());
- // ### The following can lead to duplicate action names. We'll fix that when we kill QQmlAccessible
+ // ### The following can lead to duplicate action names.
if (QQuickAccessibleAttached *attached = QQuickAccessibleAttached::attachedProperties(item()))
attached->availableActions(&actions);
return actions;
@@ -232,13 +256,80 @@ void QAccessibleQuickItem::doAction(const QString &actionName)
}
if (QQuickAccessibleAttached *attached = QQuickAccessibleAttached::attachedProperties(item()))
accepted = attached->doAction(actionName);
- if (!accepted)
- QQmlAccessible::doAction(actionName);
+
+ if (accepted)
+ return;
+ // Look for and call the accessible[actionName]Action() function on the item.
+ // This allows for overriding the default action handling.
+ const QByteArray functionName = QByteArrayLiteral("accessible") + actionName.toLatin1() + QByteArrayLiteral("Action");
+ if (object()->metaObject()->indexOfMethod(QByteArray(functionName + QByteArrayLiteral("()"))) != -1) {
+ QMetaObject::invokeMethod(object(), functionName);
+ return;
+ }
+
+ // Role-specific default action handling follows. Items are expected to provide
+ // properties according to role conventions. These will then be read and/or updated
+ // by the accessibility system.
+ // Checkable roles : checked
+ // Value-based roles : (via the value interface: value, minimumValue, maximumValue), stepSize
+ switch (role()) {
+ case QAccessible::RadioButton:
+ case QAccessible::CheckBox: {
+ QVariant checked = object()->property("checked");
+ if (checked.isValid()) {
+ if (actionName == QAccessibleActionInterface::toggleAction() ||
+ actionName == QAccessibleActionInterface::pressAction()) {
+
+ object()->setProperty("checked", QVariant(!checked.toBool()));
+ }
+ }
+ break;
+ }
+ case QAccessible::Slider:
+ case QAccessible::SpinBox:
+ case QAccessible::Dial:
+ case QAccessible::ScrollBar: {
+ if (actionName != QAccessibleActionInterface::increaseAction() &&
+ actionName != QAccessibleActionInterface::decreaseAction())
+ break;
+
+ // Update the value using QAccessibleValueInterface, respecting
+ // the minimum and maximum value (if set). Also check for and
+ // use the "stepSize" property on the item
+ if (QAccessibleValueInterface *valueIface = valueInterface()) {
+ QVariant valueV = valueIface->currentValue();
+ qreal newValue = valueV.toReal();
+
+ QVariant stepSizeV = object()->property("stepSize");
+ qreal stepSize = stepSizeV.isValid() ? stepSizeV.toReal() : qreal(1.0);
+ if (actionName == QAccessibleActionInterface::increaseAction()) {
+ newValue += stepSize;
+ } else {
+ newValue -= stepSize;
+ }
+
+ QVariant minimumValueV = valueIface->minimumValue();
+ if (minimumValueV.isValid()) {
+ newValue = qMax(newValue, minimumValueV.toReal());
+ }
+ QVariant maximumValueV = valueIface->maximumValue();
+ if (maximumValueV.isValid()) {
+ newValue = qMin(newValue, maximumValueV.toReal());
+ }
+
+ valueIface->setCurrentValue(QVariant(newValue));
+ }
+ break;
+ }
+ default:
+ break;
+ }
}
QStringList QAccessibleQuickItem::keyBindingsForAction(const QString &actionName) const
{
- return QQmlAccessible::keyBindingsForAction(actionName);
+ Q_UNUSED(actionName)
+ return QStringList();
}
QString QAccessibleQuickItem::text(QAccessible::Text textType) const
@@ -287,6 +378,8 @@ QString QAccessibleQuickItem::text(QAccessible::Text textType) const
void *QAccessibleQuickItem::interface_cast(QAccessible::InterfaceType t)
{
QAccessible::Role r = role();
+ if (t == QAccessible::ActionInterface)
+ return static_cast<QAccessibleActionInterface*>(this);
if (t == QAccessible::ValueInterface &&
(r == QAccessible::Slider ||
r == QAccessible::SpinBox ||
@@ -298,7 +391,7 @@ void *QAccessibleQuickItem::interface_cast(QAccessible::InterfaceType t)
(r == QAccessible::EditableText))
return static_cast<QAccessibleTextInterface*>(this);
- return QQmlAccessible::interface_cast(t);
+ return QAccessibleObject::interface_cast(t);
}
QVariant QAccessibleQuickItem::currentValue() const
diff --git a/src/quick/accessible/qaccessiblequickitem_p.h b/src/quick/accessible/qaccessiblequickitem_p.h
index e8486721f3..5525e60493 100644
--- a/src/quick/accessible/qaccessiblequickitem_p.h
+++ b/src/quick/accessible/qaccessiblequickitem_p.h
@@ -36,7 +36,7 @@
#include <QtQuick/QQuickItem>
#include <QtQuick/QQuickView>
-#include <QtQuick/private/qqmlaccessible_p.h>
+#include <QtGui/qaccessibleobject.h>
QT_BEGIN_NAMESPACE
@@ -44,7 +44,7 @@ QT_BEGIN_NAMESPACE
class QTextDocument;
-class QAccessibleQuickItem : public QQmlAccessible, public QAccessibleValueInterface, public QAccessibleTextInterface
+class QAccessibleQuickItem : public QAccessibleObject, public QAccessibleActionInterface, public QAccessibleValueInterface, public QAccessibleTextInterface
{
public:
QAccessibleQuickItem(QQuickItem *item);
diff --git a/src/quick/accessible/qaccessiblequickview.cpp b/src/quick/accessible/qaccessiblequickview.cpp
index e3ee1d2722..3f6f53e6b5 100644
--- a/src/quick/accessible/qaccessiblequickview.cpp
+++ b/src/quick/accessible/qaccessiblequickview.cpp
@@ -39,7 +39,6 @@
#include <QtQuick/private/qquickitem_p.h>
#include "qaccessiblequickitem_p.h"
-#include "qqmlaccessible_p.h"
#ifndef QT_NO_ACCESSIBILITY
diff --git a/src/quick/accessible/qqmlaccessible.cpp b/src/quick/accessible/qqmlaccessible.cpp
deleted file mode 100644
index 53eb6a7a0d..0000000000
--- a/src/quick/accessible/qqmlaccessible.cpp
+++ /dev/null
@@ -1,195 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <qnamespace.h>
-#include "qqmlaccessible_p.h"
-
-#ifndef QT_NO_ACCESSIBILITY
-
-QT_BEGIN_NAMESPACE
-
-QQmlAccessible::QQmlAccessible(QObject *object)
- :QAccessibleObject(object)
-{
-}
-
-void *QQmlAccessible::interface_cast(QAccessible::InterfaceType t)
-{
- if (t == QAccessible::ActionInterface)
- return static_cast<QAccessibleActionInterface*>(this);
- return QAccessibleObject::interface_cast(t);
-}
-
-QQmlAccessible::~QQmlAccessible()
-{
-}
-
-QAccessible::State QQmlAccessible::state() const
-{
- QAccessible::State state;
-
- //QRect viewRect(QPoint(0, 0), m_implementation->size());
- //QRect itemRect(m_item->scenePos().toPoint(), m_item->boundingRect().size().toSize());
-
- QRect viewRect_ = viewRect();
- QRect itemRect = rect();
-
- // qDebug() << "viewRect" << viewRect << "itemRect" << itemRect;
- // error case:
- if (viewRect_.isNull() || itemRect.isNull()) {
- state.invisible = true;
- }
-
- if (!viewRect_.intersects(itemRect)) {
- state.offscreen = true;
- // state.invisible = true; // no set at this point to ease development
- }
-
- if (!object()->property("visible").toBool() || qFuzzyIsNull(object()->property("opacity").toDouble())) {
- state.invisible = true;
- }
-
- if ((role() == QAccessible::CheckBox || role() == QAccessible::RadioButton) && object()->property("checked").toBool()) {
- state.checked = true;
- }
-
- if (role() == QAccessible::EditableText)
- state.focusable = true;
-
- //qDebug() << "state?" << m_item->property("state").toString() << m_item->property("status").toString() << m_item->property("visible").toString();
-
- return state;
-}
-
-QStringList QQmlAccessible::actionNames() const
-{
- QStringList actions;
- switch (role()) {
- case QAccessible::PushButton:
- actions << QAccessibleActionInterface::pressAction();
- break;
- case QAccessible::RadioButton:
- case QAccessible::CheckBox:
- actions << QAccessibleActionInterface::toggleAction()
- << QAccessibleActionInterface::pressAction();
- break;
- case QAccessible::Slider:
- case QAccessible::SpinBox:
- case QAccessible::ScrollBar:
- actions << QAccessibleActionInterface::increaseAction()
- << QAccessibleActionInterface::decreaseAction();
- break;
- default:
- break;
- }
- return actions;
-}
-
-void QQmlAccessible::doAction(const QString &actionName)
-{
- // Look for and call the accessible[actionName]Action() function on the item.
- // This allows for overriding the default action handling.
- const QByteArray functionName = QByteArrayLiteral("accessible") + actionName.toLatin1() + QByteArrayLiteral("Action");
- if (object()->metaObject()->indexOfMethod(QByteArray(functionName + QByteArrayLiteral("()"))) != -1) {
- QMetaObject::invokeMethod(object(), functionName);
- return;
- }
-
- // Role-specific default action handling follows. Items are expected to provide
- // properties according to role conventions. These will then be read and/or updated
- // by the accessibility system.
- // Checkable roles : checked
- // Value-based roles : (via the value interface: value, minimumValue, maximumValue), stepSize
- switch (role()) {
- case QAccessible::RadioButton:
- case QAccessible::CheckBox: {
- QVariant checked = object()->property("checked");
- if (checked.isValid()) {
- if (actionName == QAccessibleActionInterface::toggleAction() ||
- actionName == QAccessibleActionInterface::pressAction()) {
-
- object()->setProperty("checked", QVariant(!checked.toBool()));
- }
- }
- break;
- }
- case QAccessible::Slider:
- case QAccessible::SpinBox:
- case QAccessible::Dial:
- case QAccessible::ScrollBar: {
- if (actionName != QAccessibleActionInterface::increaseAction() &&
- actionName != QAccessibleActionInterface::decreaseAction())
- break;
-
- // Update the value using QAccessibleValueInterface, respecting
- // the minimum and maximum value (if set). Also check for and
- // use the "stepSize" property on the item
- if (QAccessibleValueInterface *valueIface = valueInterface()) {
- QVariant valueV = valueIface->currentValue();
- qreal newValue = valueV.toReal();
-
- QVariant stepSizeV = object()->property("stepSize");
- qreal stepSize = stepSizeV.isValid() ? stepSizeV.toReal() : qreal(1.0);
- if (actionName == QAccessibleActionInterface::increaseAction()) {
- newValue += stepSize;
- } else {
- newValue -= stepSize;
- }
-
- QVariant minimumValueV = valueIface->minimumValue();
- if (minimumValueV.isValid()) {
- newValue = qMax(newValue, minimumValueV.toReal());
- }
- QVariant maximumValueV = valueIface->maximumValue();
- if (maximumValueV.isValid()) {
- newValue = qMin(newValue, maximumValueV.toReal());
- }
-
- valueIface->setCurrentValue(QVariant(newValue));
- }
- break;
- }
- default:
- break;
- }
-}
-
-QStringList QQmlAccessible::keyBindingsForAction(const QString &actionName) const
-{
- Q_UNUSED(actionName)
- return QStringList();
-}
-
-QT_END_NAMESPACE
-
-#endif // QT_NO_ACCESSIBILITY
diff --git a/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc b/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc
index 046c23f8f0..9b8b76da83 100644
--- a/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc
+++ b/src/quick/doc/src/concepts/visualcanvas/scenegraph.qdoc
@@ -244,18 +244,20 @@ animations, process events, etc.
\endlist
-The threaded renderer is currently used by default on Linux with
-non-Mesa based drivers, OS X and EGLFS based QPA platforms, but this
-is subject to change. It is possible to force use of the threaded
-renderer by setting \c {QSG_RENDER_LOOP=threaded} in the
-environment.
+The threaded renderer is currently used by default on Windows with
+opengl32.dll, Linux with non-Mesa based drivers, OS X and EGLFS but
+this is subject to change. It is possible to force use of the threaded
+renderer by setting \c {QSG_RENDER_LOOP=threaded} in the environment.
\section2 Non-threaded Render Loop
The non-threaded render loop is currently used by default on Windows
-and non-EGLFS based embedded platforms. This is mostly a precautionary
-measure, as not all combinations of OpenGL drivers and windowing
-systems have been tested.
+with ANGLE or a non-default opengl32 implementation and Linux with
+Mesa drivers. For the latter this is mostly a precautionary measure,
+as not all combinations of OpenGL drivers and windowing systems have
+been tested. At the same time implementations like ANGLE or Mesa
+llvmpipe are not able to function properly with threaded rendering at
+all so not using threaded rendering is essential for these.
Even when using the non-threaded render loop, you should write your
code as if you are using the threaded renderer, as failing to do so
diff --git a/src/quick/items/context2d/qquickcanvascontext_p.h b/src/quick/items/context2d/qquickcanvascontext_p.h
index e036e0b18d..04b2aa9ec2 100644
--- a/src/quick/items/context2d/qquickcanvascontext_p.h
+++ b/src/quick/items/context2d/qquickcanvascontext_p.h
@@ -60,7 +60,7 @@ public:
virtual void prepare(const QSize& canvasSize, const QSize& tileSize, const QRect& canvasWindow, const QRect& dirtyRect, bool smooth, bool antialiasing);
virtual void flush();
- virtual void setV8Engine(QV8Engine *engine) = 0;
+ virtual void setV4Engine(QV4::ExecutionEngine *engine) = 0;
virtual QV4::ReturnedValue v4value() const = 0;
virtual QImage toImage(const QRectF& bounds) = 0;
diff --git a/src/quick/items/context2d/qquickcanvasitem.cpp b/src/quick/items/context2d/qquickcanvasitem.cpp
index c31b7726c4..f8ed81d2a5 100644
--- a/src/quick/items/context2d/qquickcanvasitem.cpp
+++ b/src/quick/items/context2d/qquickcanvasitem.cpp
@@ -864,7 +864,7 @@ void QQuickCanvasItem::requestAnimationFrame(QQmlV4Function *args)
static int id = 0;
- d->animationCallbacks.insert(++id, QV4::PersistentValue(f));
+ d->animationCallbacks.insert(++id, QV4::PersistentValue(scope.engine, f));
if (isVisible())
polish();
@@ -1142,7 +1142,7 @@ void QQuickCanvasItem::initializeContext(QQuickCanvasContext *context, const QVa
d->context = context;
d->context->init(this, args);
- d->context->setV8Engine(QQmlEnginePrivate::getV8Engine(qmlEngine(this)));
+ d->context->setV4Engine(QQmlEnginePrivate::get(qmlEngine(this))->v4engine());
connect(d->context, SIGNAL(textureChanged()), SLOT(update()));
connect(d->context, SIGNAL(textureChanged()), SIGNAL(painted()));
emit contextChanged();
diff --git a/src/quick/items/context2d/qquickcanvasitem_p.h b/src/quick/items/context2d/qquickcanvasitem_p.h
index b3509a5e58..e490bdf9c3 100644
--- a/src/quick/items/context2d/qquickcanvasitem_p.h
+++ b/src/quick/items/context2d/qquickcanvasitem_p.h
@@ -162,12 +162,12 @@ private Q_SLOTS:
void invalidateSceneGraph();
protected:
- void componentComplete();
- void itemChange(QQuickItem::ItemChange, const QQuickItem::ItemChangeData &);
- void updatePolish();
- QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
- void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry);
- void releaseResources();
+ void componentComplete() Q_DECL_OVERRIDE;
+ void itemChange(QQuickItem::ItemChange, const QQuickItem::ItemChangeData &) Q_DECL_OVERRIDE;
+ void updatePolish() Q_DECL_OVERRIDE;
+ QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *) Q_DECL_OVERRIDE;
+ void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) Q_DECL_OVERRIDE;
+ void releaseResources() Q_DECL_OVERRIDE;
private:
Q_DECLARE_PRIVATE(QQuickCanvasItem)
Q_INVOKABLE void delayedCreate();
diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp
index 2d1bb4d933..bc5fd8504f 100644
--- a/src/quick/items/context2d/qquickcontext2d.cpp
+++ b/src/quick/items/context2d/qquickcontext2d.cpp
@@ -463,7 +463,7 @@ static QFont qt_font_from_string(const QString& fontString, const QFont &current
class QQuickContext2DEngineData : public QV8Engine::Deletable
{
public:
- QQuickContext2DEngineData(QV8Engine *engine);
+ QQuickContext2DEngineData(QV4::ExecutionEngine *engine);
~QQuickContext2DEngineData();
QV4::PersistentValue contextPrototype;
@@ -471,20 +471,47 @@ public:
QV4::PersistentValue pixelArrayProto;
};
-V8_DEFINE_EXTENSION(QQuickContext2DEngineData, engineData)
+V4_DEFINE_EXTENSION(QQuickContext2DEngineData, engineData)
+namespace QV4 {
+namespace Heap {
+
+struct QQuickJSContext2D : Object {
+ QQuickJSContext2D(QV4::ExecutionEngine *engine);
+ QQuickContext2D* context;
+};
+
+struct QQuickJSContext2DPrototype : Object {
+ QQuickJSContext2DPrototype(ExecutionEngine *e)
+ : Object(e) {}
+};
+
+struct QQuickContext2DStyle : Object {
+ QQuickContext2DStyle(QV4::ExecutionEngine *e);
+
+ QBrush brush;
+ bool patternRepeatX:1;
+ bool patternRepeatY:1;
+};
+
+struct QQuickJSContext2DPixelData : Object {
+ QQuickJSContext2DPixelData(QV4::ExecutionEngine *engine);
+
+ QImage image;
+};
+
+struct QQuickJSContext2DImageData : Object {
+ QQuickJSContext2DImageData(QV4::ExecutionEngine *engine);
+
+ QV4::Value pixelData;
+};
+
+}
+}
struct QQuickJSContext2D : public QV4::Object
{
- struct Data : Object::Data {
- Data(QV4::ExecutionEngine *engine)
- : Object::Data(engine)
- {
- setVTable(staticVTable());
- }
- QQuickContext2D* context;
- };
- V4_OBJECT(QV4::Object)
+ V4_OBJECT2(QQuickJSContext2D, QV4::Object)
static QV4::ReturnedValue method_get_globalAlpha(QV4::CallContext *ctx);
static QV4::ReturnedValue method_set_globalAlpha(QV4::CallContext *ctx);
@@ -527,17 +554,23 @@ struct QQuickJSContext2D : public QV4::Object
static QV4::ReturnedValue method_set_textBaseline(QV4::CallContext *ctx);
};
+QV4::Heap::QQuickJSContext2D::QQuickJSContext2D(QV4::ExecutionEngine *engine)
+ : QV4::Heap::Object(engine)
+{
+ setVTable(::QQuickJSContext2D::staticVTable());
+}
+
DEFINE_OBJECT_VTABLE(QQuickJSContext2D);
struct QQuickJSContext2DPrototype : public QV4::Object
{
- V4_OBJECT(QV4::Object)
+ V4_OBJECT2(QQuickJSContext2DPrototype, QV4::Object)
public:
- static QQuickJSContext2DPrototype *create(QV4::ExecutionEngine *engine)
+ static QV4::Heap::QQuickJSContext2DPrototype *create(QV4::ExecutionEngine *engine)
{
QV4::Scope scope(engine);
- QV4::ScopedObject o(scope, engine->memoryManager->alloc<QQuickJSContext2DPrototype>(engine));
+ QV4::Scoped<QQuickJSContext2DPrototype> o(scope, engine->memoryManager->alloc<QQuickJSContext2DPrototype>(engine));
o->defineDefaultProperty(QStringLiteral("quadraticCurveTo"), method_quadraticCurveTo, 0);
o->defineDefaultProperty(QStringLiteral("restore"), method_restore, 0);
@@ -584,7 +617,7 @@ public:
o->defineDefaultProperty(QStringLiteral("closePath"), method_closePath, 0);
o->defineAccessorProperty(QStringLiteral("canvas"), QQuickJSContext2DPrototype::method_get_canvas, 0);
- return static_cast<QQuickJSContext2DPrototype*>(o.getPointer());
+ return o->d();
}
static QV4::ReturnedValue method_get_canvas(QV4::CallContext *ctx);
@@ -639,28 +672,20 @@ DEFINE_OBJECT_VTABLE(QQuickJSContext2DPrototype);
struct QQuickContext2DStyle : public QV4::Object
{
- struct Data : Object::Data {
- Data(QV4::ExecutionEngine *e)
- : Object::Data(e)
- {
- patternRepeatX = false;
- patternRepeatY = false;
- setVTable(staticVTable());
- }
- QBrush brush;
- bool patternRepeatX:1;
- bool patternRepeatY:1;
- };
- V4_OBJECT(QV4::Object)
+ V4_OBJECT2(QQuickContext2DStyle, QV4::Object)
+ V4_NEEDS_DESTROY
static QV4::ReturnedValue gradient_proto_addColorStop(QV4::CallContext *ctx);
-protected:
- static void destroy(Managed *that)
- {
- static_cast<QQuickContext2DStyle *>(that)->d()->~Data();
- }
};
+QV4::Heap::QQuickContext2DStyle::QQuickContext2DStyle(QV4::ExecutionEngine *e)
+ : QV4::Heap::Object(e)
+{
+ patternRepeatX = false;
+ patternRepeatY = false;
+ setVTable(::QQuickContext2DStyle::staticVTable());
+}
+
DEFINE_OBJECT_VTABLE(QQuickContext2DStyle);
QImage qt_image_convolute_filter(const QImage& src, const QVector<qreal>& weights, int radius = 0)
@@ -860,70 +885,63 @@ static QString qt_composite_mode_to_string(QPainter::CompositionMode op)
struct QQuickJSContext2DPixelData : public QV4::Object
{
- struct Data : Object::Data {
- Data(QV4::ExecutionEngine *engine)
- : Object::Data(engine)
- {
- setVTable(staticVTable());
- QV4::Scope scope(engine);
- QV4::ScopedObject o(scope, this);
- o->setArrayType(QV4::ArrayData::Custom);
- }
- QImage image;
- };
- V4_OBJECT(QV4::Object)
+ V4_OBJECT2(QQuickJSContext2DPixelData, QV4::Object)
+ V4_NEEDS_DESTROY
- static void destroy(QV4::Managed *that) {
- static_cast<QQuickJSContext2DPixelData *>(that)->d()->~Data();
- }
static QV4::ReturnedValue getIndexed(QV4::Managed *m, uint index, bool *hasProperty);
static void putIndexed(QV4::Managed *m, uint index, const QV4::ValueRef value);
static QV4::ReturnedValue proto_get_length(QV4::CallContext *ctx);
};
+QV4::Heap::QQuickJSContext2DPixelData::QQuickJSContext2DPixelData(QV4::ExecutionEngine *engine)
+ : QV4::Heap::Object(engine)
+{
+ setVTable(::QQuickJSContext2DPixelData::staticVTable());
+ QV4::Scope scope(engine);
+ QV4::ScopedObject o(scope, this);
+ o->setArrayType(QV4::Heap::ArrayData::Custom);
+}
+
DEFINE_OBJECT_VTABLE(QQuickJSContext2DPixelData);
struct QQuickJSContext2DImageData : public QV4::Object
{
- struct Data : Object::Data {
- Data(QV4::ExecutionEngine *engine)
- : Object::Data(engine)
- {
- setVTable(staticVTable());
- pixelData = QV4::Primitive::undefinedValue();
-
- QV4::Scope scope(engine);
- QV4::ScopedObject o(scope, this);
-
- o->defineAccessorProperty(QStringLiteral("width"), method_get_width, 0);
- o->defineAccessorProperty(QStringLiteral("height"), method_get_height, 0);
- o->defineAccessorProperty(QStringLiteral("data"), method_get_data, 0);
- }
- QV4::Value pixelData;
- };
- V4_OBJECT(QV4::Object)
+ V4_OBJECT2(QQuickJSContext2DImageData, QV4::Object)
static QV4::ReturnedValue method_get_width(QV4::CallContext *ctx);
static QV4::ReturnedValue method_get_height(QV4::CallContext *ctx);
static QV4::ReturnedValue method_get_data(QV4::CallContext *ctx);
- static void markObjects(Managed *that, QV4::ExecutionEngine *engine) {
- static_cast<QQuickJSContext2DImageData *>(that)->d()->pixelData.mark(engine);
+ static void markObjects(QV4::Heap::Base *that, QV4::ExecutionEngine *engine) {
+ static_cast<QQuickJSContext2DImageData::Data *>(that)->pixelData.mark(engine);
QV4::Object::markObjects(that, engine);
}
};
+QV4::Heap::QQuickJSContext2DImageData::QQuickJSContext2DImageData(QV4::ExecutionEngine *engine)
+ : QV4::Heap::Object(engine)
+{
+ setVTable(::QQuickJSContext2DImageData::staticVTable());
+ pixelData = QV4::Primitive::undefinedValue();
+
+ QV4::Scope scope(engine);
+ QV4::ScopedObject o(scope, this);
+
+ o->defineAccessorProperty(QStringLiteral("width"), ::QQuickJSContext2DImageData::method_get_width, 0);
+ o->defineAccessorProperty(QStringLiteral("height"), ::QQuickJSContext2DImageData::method_get_height, 0);
+ o->defineAccessorProperty(QStringLiteral("data"), ::QQuickJSContext2DImageData::method_get_data, 0);
+}
+
DEFINE_OBJECT_VTABLE(QQuickJSContext2DImageData);
-static QV4::ReturnedValue qt_create_image_data(qreal w, qreal h, QV8Engine* engine, const QImage& image)
+static QV4::ReturnedValue qt_create_image_data(qreal w, qreal h, QV4::ExecutionEngine *v4, const QImage& image)
{
- QQuickContext2DEngineData *ed = engineData(engine);
- QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
QV4::Scope scope(v4);
+ QQuickContext2DEngineData *ed = engineData(scope.engine);
QV4::Scoped<QQuickJSContext2DPixelData> pixelData(scope, scope.engine->memoryManager->alloc<QQuickJSContext2DPixelData>(v4));
QV4::ScopedObject p(scope, ed->pixelArrayProto.value());
- pixelData->setPrototype(p.getPointer());
+ pixelData->setPrototype(p);
if (image.isNull()) {
pixelData->d()->image = QImage(w, h, QImage::Format_ARGB32);
@@ -1301,7 +1319,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_globalCompositeOperation(QV4::C
CHECK_CONTEXT_SETTER(r)
if (!ctx->d()->callData->argc)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
QString mode = ctx->d()->callData->args[0].toQString();
QPainter::CompositionMode cm = qt_composite_mode_from_string(mode);
@@ -1366,20 +1384,19 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_fillStyle(QV4::CallContext *ctx
CHECK_CONTEXT_SETTER(r)
QV4::ScopedValue value(scope, ctx->argument(0));
- QV8Engine *engine = scope.engine->v8Engine;
if (value->asObject()) {
- QColor color = engine->toVariant(value, qMetaTypeId<QColor>()).value<QColor>();
+ QColor color = scope.engine->toVariant(value, qMetaTypeId<QColor>()).value<QColor>();
if (color.isValid()) {
r->d()->context->state.fillStyle = color;
r->d()->context->buffer()->setFillStyle(color);
- r->d()->context->m_fillStyle = value;
+ r->d()->context->m_fillStyle.set(scope.engine, value);
} else {
QV4::Scoped<QQuickContext2DStyle> style(scope, value->as<QQuickContext2DStyle>());
if (style && style->d()->brush != r->d()->context->state.fillStyle) {
r->d()->context->state.fillStyle = style->d()->brush;
r->d()->context->buffer()->setFillStyle(style->d()->brush, style->d()->patternRepeatX, style->d()->patternRepeatY);
- r->d()->context->m_fillStyle = value;
+ r->d()->context->m_fillStyle.set(scope.engine, value);
r->d()->context->state.fillPatternRepeatX = style->d()->patternRepeatX;
r->d()->context->state.fillPatternRepeatY = style->d()->patternRepeatY;
}
@@ -1389,7 +1406,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_fillStyle(QV4::CallContext *ctx
if (color.isValid() && r->d()->context->state.fillStyle != QBrush(color)) {
r->d()->context->state.fillStyle = QBrush(color);
r->d()->context->buffer()->setFillStyle(r->d()->context->state.fillStyle);
- r->d()->context->m_fillStyle = value;
+ r->d()->context->m_fillStyle.set(scope.engine, value);
}
}
return QV4::Encode::undefined();
@@ -1412,8 +1429,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_get_fillRule(QV4::CallContext *ctx)
QV4::Scoped<QQuickJSContext2D> r(scope, ctx->d()->callData->thisObject.as<QQuickJSContext2D>());
CHECK_CONTEXT(r)
- QV8Engine *engine = scope.engine->v8Engine;
- return engine->fromVariant(r->d()->context->state.fillRule);
+ return scope.engine->fromVariant(r->d()->context->state.fillRule);
}
QV4::ReturnedValue QQuickJSContext2D::method_set_fillRule(QV4::CallContext *ctx)
@@ -1476,21 +1492,20 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_strokeStyle(QV4::CallContext *c
QV4::Scoped<QQuickJSContext2D> r(scope, ctx->d()->callData->thisObject.as<QQuickJSContext2D>());
CHECK_CONTEXT_SETTER(r)
- QV8Engine *engine = scope.engine->v8Engine;
QV4::ScopedValue value(scope, ctx->argument(0));
if (value->asObject()) {
- QColor color = engine->toVariant(value, qMetaTypeId<QColor>()).value<QColor>();
+ QColor color = scope.engine->toVariant(value, qMetaTypeId<QColor>()).value<QColor>();
if (color.isValid()) {
r->d()->context->state.fillStyle = color;
r->d()->context->buffer()->setStrokeStyle(color);
- r->d()->context->m_strokeStyle = value;
+ r->d()->context->m_strokeStyle.set(scope.engine, value);
} else {
QV4::Scoped<QQuickContext2DStyle> style(scope, value->as<QQuickContext2DStyle>());
if (style && style->d()->brush != r->d()->context->state.strokeStyle) {
r->d()->context->state.strokeStyle = style->d()->brush;
r->d()->context->buffer()->setStrokeStyle(style->d()->brush, style->d()->patternRepeatX, style->d()->patternRepeatY);
- r->d()->context->m_strokeStyle = value;
+ r->d()->context->m_strokeStyle.set(scope.engine, value);
r->d()->context->state.strokePatternRepeatX = style->d()->patternRepeatX;
r->d()->context->state.strokePatternRepeatY = style->d()->patternRepeatY;
@@ -1501,7 +1516,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_strokeStyle(QV4::CallContext *c
if (color.isValid() && r->d()->context->state.strokeStyle != QBrush(color)) {
r->d()->context->state.strokeStyle = QBrush(color);
r->d()->context->buffer()->setStrokeStyle(r->d()->context->state.strokeStyle);
- r->d()->context->m_strokeStyle = value;
+ r->d()->context->m_strokeStyle.set(scope.engine, value);
}
}
return QV4::Encode::undefined();
@@ -1530,9 +1545,6 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createLinearGradient(QV4::
QV4::Scoped<QQuickJSContext2D> r(scope, ctx->d()->callData->thisObject.as<QQuickJSContext2D>());
CHECK_CONTEXT(r)
-
- QV8Engine *engine = scope.engine->v8Engine;
-
if (ctx->d()->callData->argc >= 4) {
qreal x0 = ctx->d()->callData->args[0].toNumber();
qreal y0 = ctx->d()->callData->args[1].toNumber();
@@ -1545,11 +1557,11 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createLinearGradient(QV4::
|| !qIsFinite(y1)) {
V4THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "createLinearGradient(): Incorrect arguments")
}
- QQuickContext2DEngineData *ed = engineData(engine);
+ QQuickContext2DEngineData *ed = engineData(scope.engine);
QV4::Scoped<QQuickContext2DStyle> gradient(scope, scope.engine->memoryManager->alloc<QQuickContext2DStyle>(scope.engine));
QV4::ScopedObject p(scope, ed->gradientProto.value());
- gradient->setPrototype(p.getPointer());
+ gradient->setPrototype(p);
gradient->d()->brush = QLinearGradient(x0, y0, x1, y1);
return gradient.asReturnedValue();
}
@@ -1576,9 +1588,6 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createRadialGradient(QV4::
QV4::Scoped<QQuickJSContext2D> r(scope, ctx->d()->callData->thisObject.as<QQuickJSContext2D>());
CHECK_CONTEXT(r)
-
- QV8Engine *engine = scope.engine->v8Engine;
-
if (ctx->d()->callData->argc >= 6) {
qreal x0 = ctx->d()->callData->args[0].toNumber();
qreal y0 = ctx->d()->callData->args[1].toNumber();
@@ -1599,11 +1608,11 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createRadialGradient(QV4::
if (r0 < 0 || r1 < 0)
V4THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "createRadialGradient(): Incorrect arguments")
- QQuickContext2DEngineData *ed = engineData(engine);
+ QQuickContext2DEngineData *ed = engineData(scope.engine);
QV4::Scoped<QQuickContext2DStyle> gradient(scope, scope.engine->memoryManager->alloc<QQuickContext2DStyle>(scope.engine));
QV4::ScopedObject p(scope, ed->gradientProto.value());
- gradient->setPrototype(p.getPointer());
+ gradient->setPrototype(p);
gradient->d()->brush = QRadialGradient(QPointF(x1, y1), r0+r1, QPointF(x0, y0));
return gradient.asReturnedValue();
}
@@ -1630,9 +1639,6 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createConicalGradient(QV4:
QV4::Scoped<QQuickJSContext2D> r(scope, ctx->d()->callData->thisObject.as<QQuickJSContext2D>());
CHECK_CONTEXT(r)
-
- QV8Engine *engine = scope.engine->v8Engine;
-
if (ctx->d()->callData->argc >= 3) {
qreal x = ctx->d()->callData->args[0].toNumber();
qreal y = ctx->d()->callData->args[1].toNumber();
@@ -1645,11 +1651,11 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createConicalGradient(QV4:
V4THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "createConicalGradient(): Incorrect arguments");
}
- QQuickContext2DEngineData *ed = engineData(engine);
+ QQuickContext2DEngineData *ed = engineData(scope.engine);
QV4::Scoped<QQuickContext2DStyle> gradient(scope, scope.engine->memoryManager->alloc<QQuickContext2DStyle>(scope.engine));
QV4::ScopedObject p(scope, ed->gradientProto.value());
- gradient->setPrototype(p.getPointer());
+ gradient->setPrototype(p);
gradient->d()->brush = QConicalGradient(x, y, angle);
return gradient.asReturnedValue();
}
@@ -1705,12 +1711,10 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createPattern(QV4::CallCon
QV4::Scoped<QQuickJSContext2D> r(scope, ctx->d()->callData->thisObject);
CHECK_CONTEXT(r)
- QV8Engine *engine = scope.engine->v8Engine;
-
if (ctx->d()->callData->argc >= 2) {
QV4::Scoped<QQuickContext2DStyle> pattern(scope, scope.engine->memoryManager->alloc<QQuickContext2DStyle>(scope.engine));
- QColor color = engine->toVariant(ctx->d()->callData->args[0], qMetaTypeId<QColor>()).value<QColor>();
+ QColor color = scope.engine->toVariant(ctx->d()->callData->args[0], qMetaTypeId<QColor>()).value<QColor>();
if (color.isValid()) {
int patternMode = ctx->d()->callData->args[1].toInt32();
Qt::BrushStyle style = Qt::SolidPattern;
@@ -1723,7 +1727,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createPattern(QV4::CallCon
if (QV4::Object *o = ctx->d()->callData->args[0].asObject()) {
QV4::ScopedString s(scope, scope.engine->newString(QStringLiteral("data")));
- QV4::Scoped<QQuickJSContext2DPixelData> pixelData(scope, o->get(s.getPointer()));
+ QV4::Scoped<QQuickJSContext2DPixelData> pixelData(scope, o->get(s));
if (!!pixelData) {
patternTexture = pixelData->d()->image;
}
@@ -1853,7 +1857,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_lineJoin(QV4::CallContext *ctx)
CHECK_CONTEXT_SETTER(r)
if (!ctx->d()->callData->argc)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
QString lineJoin = ctx->d()->callData->args[0].toQString();
Qt::PenJoinStyle join;
@@ -2072,7 +2076,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_path(QV4::CallContext *ctx)
QString path =value->toQStringNoThrow();
QQuickSvgParser::parsePathDataFast(path, r->d()->context->m_path);
}
- r->d()->context->m_v4path = value;
+ r->d()->context->m_v4path.set(scope.engine, value);
return QV4::Encode::undefined();
}
@@ -2613,7 +2617,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_font(QV4::CallContext *ctx)
QV4::Scoped<QQuickJSContext2D> r(scope, ctx->d()->callData->thisObject);
CHECK_CONTEXT_SETTER(r)
- QV4::Scoped<QV4::String> s(scope, ctx->argument(0), QV4::Scoped<QV4::String>::Convert);
+ QV4::ScopedString s(scope, ctx->argument(0), QV4::ScopedString::Convert);
if (scope.engine->hasException)
return QV4::Encode::undefined();
QFont font = qt_font_from_string(s->toQString(), r->d()->context->state.font);
@@ -2665,7 +2669,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_textAlign(QV4::CallContext *ctx
QV4::Scoped<QQuickJSContext2D> r(scope, ctx->d()->callData->thisObject);
CHECK_CONTEXT_SETTER(r)
- QV4::Scoped<QV4::String> s(scope, ctx->argument(0), QV4::Scoped<QV4::String>::Convert);
+ QV4::ScopedString s(scope, ctx->argument(0), QV4::ScopedString::Convert);
if (scope.engine->hasException)
return QV4::Encode::undefined();
QString textAlign = s->toQString();
@@ -2732,7 +2736,7 @@ QV4::ReturnedValue QQuickJSContext2D::method_set_textBaseline(QV4::CallContext *
QV4::Scope scope(ctx);
QV4::Scoped<QQuickJSContext2D> r(scope, ctx->d()->callData->thisObject);
CHECK_CONTEXT_SETTER(r)
- QV4::Scoped<QV4::String> s(scope, ctx->argument(0), QV4::Scoped<QV4::String>::Convert);
+ QV4::ScopedString s(scope, ctx->argument(0), QV4::ScopedString::Convert);
if (scope.engine->hasException)
return QV4::Encode::undefined();
QString textBaseline = s->toQString();
@@ -2815,7 +2819,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_measureText(QV4::CallConte
if (ctx->d()->callData->argc >= 1) {
QFontMetrics fm(r->d()->context->state.font);
uint width = fm.width(ctx->d()->callData->args[0].toQStringNoThrow());
- QV4::Scoped<QV4::Object> tm(scope, scope.engine->newObject());
+ QV4::ScopedObject tm(scope, scope.engine->newObject());
tm->put(QV4::ScopedString(scope, scope.engine->newIdentifier(QStringLiteral("width"))).getPointer(),
QV4::ScopedValue(scope, QV4::Primitive::fromDouble(width)));
return tm.asReturnedValue();
@@ -3027,7 +3031,7 @@ QV4::ReturnedValue QQuickJSContext2DImageData::method_get_width(QV4::CallContext
QV4::Scope scope(ctx);
QV4::Scoped<QQuickJSContext2DImageData> imageData(scope, ctx->d()->callData->thisObject);
if (!imageData)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
QV4::Scoped<QQuickJSContext2DPixelData> r(scope, imageData->d()->pixelData.as<QQuickJSContext2DPixelData>());
if (!r)
return QV4::Encode(0);
@@ -3043,7 +3047,7 @@ QV4::ReturnedValue QQuickJSContext2DImageData::method_get_height(QV4::CallContex
QV4::Scope scope(ctx);
QV4::Scoped<QQuickJSContext2DImageData> imageData(scope, ctx->d()->callData->thisObject);
if (!imageData)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
QV4::Scoped<QQuickJSContext2DPixelData> r(scope, imageData->d()->pixelData.as<QQuickJSContext2DPixelData>());
if (!r)
return QV4::Encode(0);
@@ -3059,7 +3063,7 @@ QV4::ReturnedValue QQuickJSContext2DImageData::method_get_data(QV4::CallContext
QV4::Scope scope(ctx);
QV4::Scoped<QQuickJSContext2DImageData> imageData(scope, ctx->d()->callData->thisObject);
if (!imageData)
- return ctx->throwTypeError();
+ return ctx->engine()->throwTypeError();
return imageData->d()->pixelData.asReturnedValue();
}
@@ -3183,8 +3187,6 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createImageData(QV4::CallC
QV4::Scoped<QQuickJSContext2D> r(scope, ctx->d()->callData->thisObject.as<QQuickJSContext2D>());
CHECK_CONTEXT(r)
- QV8Engine *engine = scope.engine->v8Engine;
-
if (ctx->d()->callData->argc == 1) {
QV4::ScopedValue arg0(scope, ctx->d()->callData->args[0]);
QV4::Scoped<QQuickJSContext2DImageData> imgData(scope, arg0);
@@ -3193,11 +3195,11 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createImageData(QV4::CallC
if (pa) {
qreal w = pa->d()->image.width();
qreal h = pa->d()->image.height();
- return qt_create_image_data(w, h, engine, QImage());
+ return qt_create_image_data(w, h, scope.engine, QImage());
}
} else if (arg0->isString()) {
QImage image = r->d()->context->createPixmap(QUrl(arg0->toQStringNoThrow()))->image();
- return qt_create_image_data(image.width(), image.height(), engine, image);
+ return qt_create_image_data(image.width(), image.height(), scope.engine, image);
}
} else if (ctx->d()->callData->argc == 2) {
qreal w = ctx->d()->callData->args[0].toNumber();
@@ -3207,7 +3209,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_createImageData(QV4::CallC
V4THROW_DOM(DOMEXCEPTION_NOT_SUPPORTED_ERR, "createImageData(): invalid arguments");
if (w > 0 && h > 0)
- return qt_create_image_data(w, h, engine, QImage());
+ return qt_create_image_data(w, h, scope.engine, QImage());
else
V4THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "createImageData(): invalid arguments");
}
@@ -3224,7 +3226,6 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_getImageData(QV4::CallCont
QV4::Scoped<QQuickJSContext2D> r(scope, ctx->d()->callData->thisObject.as<QQuickJSContext2D>());
CHECK_CONTEXT(r)
- QV8Engine *engine = scope.engine->v8Engine;
if (ctx->d()->callData->argc >= 4) {
qreal x = ctx->d()->callData->args[0].toNumber();
qreal y = ctx->d()->callData->args[1].toNumber();
@@ -3237,7 +3238,7 @@ QV4::ReturnedValue QQuickJSContext2DPrototype::method_getImageData(QV4::CallCont
V4THROW_DOM(DOMEXCEPTION_INDEX_SIZE_ERR, "getImageData(): Invalid arguments");
QImage image = r->d()->context->canvas()->toImage(QRectF(x, y, w, h));
- return qt_create_image_data(w, h, engine, image);
+ return qt_create_image_data(w, h, scope.engine, image);
}
return QV4::Encode::null();
}
@@ -3354,8 +3355,6 @@ QV4::ReturnedValue QQuickContext2DStyle::gradient_proto_addColorStop(QV4::CallCo
if (!style)
V4THROW_ERROR("Not a CanvasGradient object");
- QV8Engine *engine = scope.engine->v8Engine;
-
if (ctx->d()->callData->argc == 2) {
if (!style->d()->brush.gradient())
@@ -3365,7 +3364,7 @@ QV4::ReturnedValue QQuickContext2DStyle::gradient_proto_addColorStop(QV4::CallCo
QColor color;
if (ctx->d()->callData->args[1].asObject()) {
- color = engine->toVariant(ctx->d()->callData->args[1], qMetaTypeId<QColor>()).value<QColor>();
+ color = scope.engine->toVariant(ctx->d()->callData->args[1], qMetaTypeId<QColor>()).value<QColor>();
} else {
color = qt_color_from_string(ctx->d()->callData->args[1]);
}
@@ -4011,7 +4010,7 @@ QMutex QQuickContext2D::mutex;
QQuickContext2D::QQuickContext2D(QObject *parent)
: QQuickCanvasContext(parent)
, m_buffer(new QQuickContext2DCommandBuffer)
- , m_v8engine(0)
+ , m_v4engine(0)
, m_surface(0)
, m_glContext(0)
, m_thread(0)
@@ -4213,12 +4212,11 @@ QImage QQuickContext2D::toImage(const QRectF& bounds)
}
-QQuickContext2DEngineData::QQuickContext2DEngineData(QV8Engine *engine)
+QQuickContext2DEngineData::QQuickContext2DEngineData(QV4::ExecutionEngine *v4)
{
- QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine);
QV4::Scope scope(v4);
- QV4::Scoped<QV4::Object> proto(scope, QQuickJSContext2DPrototype::create(v4));
+ QV4::ScopedObject proto(scope, QQuickJSContext2DPrototype::create(v4));
proto->defineAccessorProperty(QStringLiteral("strokeStyle"), QQuickJSContext2D::method_get_strokeStyle, QQuickJSContext2D::method_set_strokeStyle);
proto->defineAccessorProperty(QStringLiteral("font"), QQuickJSContext2D::method_get_font, QQuickJSContext2D::method_set_font);
proto->defineAccessorProperty(QStringLiteral("fillRule"), QQuickJSContext2D::method_get_fillRule, QQuickJSContext2D::method_set_fillRule);
@@ -4322,20 +4320,19 @@ void QQuickContext2D::reset()
m_buffer->clearRect(QRectF(0, 0, m_canvas->width(), m_canvas->height()));
}
-void QQuickContext2D::setV8Engine(QV8Engine *engine)
+void QQuickContext2D::setV4Engine(QV4::ExecutionEngine *engine)
{
- if (m_v8engine != engine) {
- m_v8engine = engine;
+ if (m_v4engine != engine) {
+ m_v4engine = engine;
- if (m_v8engine == 0)
+ if (m_v4engine == 0)
return;
QQuickContext2DEngineData *ed = engineData(engine);
- QV4::ExecutionEngine *v4Engine = QV8Engine::getV4(engine);
- QV4::Scope scope(v4Engine);
- QV4::Scoped<QQuickJSContext2D> wrapper(scope, v4Engine->memoryManager->alloc<QQuickJSContext2D>(v4Engine));
+ QV4::Scope scope(engine);
+ QV4::Scoped<QQuickJSContext2D> wrapper(scope, engine->memoryManager->alloc<QQuickJSContext2D>(engine));
QV4::ScopedObject p(scope, ed->contextPrototype.value());
- wrapper->setPrototype(p.getPointer());
+ wrapper->setPrototype(p);
wrapper->d()->context = this;
m_v4value = wrapper;
}
diff --git a/src/quick/items/context2d/qquickcontext2d_p.h b/src/quick/items/context2d/qquickcontext2d_p.h
index dcfe6cfe50..9360489260 100644
--- a/src/quick/items/context2d/qquickcontext2d_p.h
+++ b/src/quick/items/context2d/qquickcontext2d_p.h
@@ -173,7 +173,7 @@ public:
QImage toImage(const QRectF& bounds);
QV4::ReturnedValue v4value() const;
- void setV8Engine(QV8Engine *eng);
+ void setV4Engine(QV4::ExecutionEngine *eng);
QQuickCanvasItem* canvas() const { return m_canvas; }
QQuickContext2DCommandBuffer* buffer() const { return m_buffer; }
@@ -234,7 +234,7 @@ public:
QV4::PersistentValue m_fillStyle;
QV4::PersistentValue m_strokeStyle;
QV4::PersistentValue m_v4path;
- QV8Engine *m_v8engine;
+ QV4::ExecutionEngine *m_v4engine;
QScopedPointer<QOffscreenSurface> m_surface;
QOpenGLContext *m_glContext;
QV4::PersistentValue m_v4value;
diff --git a/src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp b/src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp
index a52f1c8cd2..eac5e2cef8 100644
--- a/src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp
+++ b/src/quick/items/context2d/qquickcontext2dcommandbuffer.cpp
@@ -93,7 +93,7 @@ namespace {
}
void paint(QPainter *p) const { p->fillRect(m_rect, m_brush); }
- QRectF boundingRect() const { return m_rect; }
+ QRectF boundingRect() const Q_DECL_OVERRIDE { return m_rect; }
private:
QRectF m_rect;
@@ -110,7 +110,7 @@ namespace {
}
void paint(QPainter *p) const { p->fillPath(m_path, m_brush); }
- QRectF boundingRect() const { return m_path.boundingRect(); }
+ QRectF boundingRect() const Q_DECL_OVERRIDE { return m_path.boundingRect(); }
private:
QPainterPath m_path;
@@ -128,7 +128,7 @@ namespace {
void paint(QPainter *p) const { p->strokePath(m_path, m_pen); }
- QRectF boundingRect() const
+ QRectF boundingRect() const Q_DECL_OVERRIDE
{
qreal d = qMax(qreal(1), m_pen.widthF());
return m_path.boundingRect().adjusted(-d, -d, d, d);
@@ -150,7 +150,7 @@ namespace {
void paint(QPainter *p) const { p->drawImage(m_offset, m_image); }
- QRectF boundingRect() const { return QRectF(m_image.rect()).translated(m_offset); }
+ QRectF boundingRect() const Q_DECL_OVERRIDE { return QRectF(m_image.rect()).translated(m_offset); }
private:
QImage m_image;
diff --git a/src/quick/items/qquickaccessibleattached.cpp b/src/quick/items/qquickaccessibleattached.cpp
index abb763c2eb..a7641523ea 100644
--- a/src/quick/items/qquickaccessibleattached.cpp
+++ b/src/quick/items/qquickaccessibleattached.cpp
@@ -291,11 +291,59 @@ QT_BEGIN_NAMESPACE
The corresponding handler is \c onDecreaseAction.
*/
+/*!
+ \qmlsignal QtQuick::Accessible::scrollUpAction()
+
+ This signal is emitted when a scroll up action is received from an assistive tool such as a screen-reader.
+
+ The corresponding handler is \c onScrollUpAction.
+*/
+/*!
+ \qmlsignal QtQuick::Accessible::scrollDownAction()
+
+ This signal is emitted when a scroll down action is received from an assistive tool such as a screen-reader.
+
+ The corresponding handler is \c onScrollDownAction.
+*/
+/*!
+ \qmlsignal QtQuick::Accessible::scrollLeftAction()
+
+ This signal is emitted when a scroll left action is received from an assistive tool such as a screen-reader.
+
+ The corresponding handler is \c onScrollLeftAction.
+*/
+/*!
+ \qmlsignal QtQuick::Accessible::scrollRightAction()
+
+ This signal is emitted when a scroll right action is received from an assistive tool such as a screen-reader.
+
+ The corresponding handler is \c onScrollRightAction.
+*/
+/*!
+ \qmlsignal QtQuick::Accessible::previousPageAction()
+
+ This signal is emitted when a previous page action is received from an assistive tool such as a screen-reader.
+
+ The corresponding handler is \c onPreviousPageAction.
+*/
+/*!
+ \qmlsignal QtQuick::Accessible::nextPageAction()
+
+ This signal is emitted when a next page action is received from an assistive tool such as a screen-reader.
+
+ The corresponding handler is \c onNextPageAction.
+*/
QMetaMethod QQuickAccessibleAttached::sigPress;
QMetaMethod QQuickAccessibleAttached::sigToggle;
QMetaMethod QQuickAccessibleAttached::sigIncrease;
QMetaMethod QQuickAccessibleAttached::sigDecrease;
+QMetaMethod QQuickAccessibleAttached::sigScrollUp;
+QMetaMethod QQuickAccessibleAttached::sigScrollDown;
+QMetaMethod QQuickAccessibleAttached::sigScrollLeft;
+QMetaMethod QQuickAccessibleAttached::sigScrollRight;
+QMetaMethod QQuickAccessibleAttached::sigPreviousPage;
+QMetaMethod QQuickAccessibleAttached::sigNextPage;
QQuickAccessibleAttached::QQuickAccessibleAttached(QObject *parent)
: QObject(parent), m_role(QAccessible::NoRole)
@@ -323,6 +371,12 @@ QQuickAccessibleAttached::QQuickAccessibleAttached(QObject *parent)
sigToggle = QMetaMethod::fromSignal(&QQuickAccessibleAttached::toggleAction);
sigIncrease = QMetaMethod::fromSignal(&QQuickAccessibleAttached::increaseAction);
sigDecrease = QMetaMethod::fromSignal(&QQuickAccessibleAttached::decreaseAction);
+ sigScrollUp = QMetaMethod::fromSignal(&QQuickAccessibleAttached::scrollUpAction);
+ sigScrollDown = QMetaMethod::fromSignal(&QQuickAccessibleAttached::scrollDownAction);
+ sigScrollLeft = QMetaMethod::fromSignal(&QQuickAccessibleAttached::scrollLeftAction);
+ sigScrollRight = QMetaMethod::fromSignal(&QQuickAccessibleAttached::scrollRightAction);
+ sigPreviousPage = QMetaMethod::fromSignal(&QQuickAccessibleAttached::previousPageAction);
+ sigNextPage= QMetaMethod::fromSignal(&QQuickAccessibleAttached::nextPageAction);
}
}
@@ -359,7 +413,18 @@ bool QQuickAccessibleAttached::doAction(const QString &actionName)
sig = &sigIncrease;
else if (actionName == QAccessibleActionInterface::decreaseAction())
sig = &sigDecrease;
-
+ else if (actionName == QAccessibleActionInterface::scrollUpAction())
+ sig = &sigScrollUp;
+ else if (actionName == QAccessibleActionInterface::scrollDownAction())
+ sig = &sigScrollDown;
+ else if (actionName == QAccessibleActionInterface::scrollLeftAction())
+ sig = &sigScrollLeft;
+ else if (actionName == QAccessibleActionInterface::scrollRightAction())
+ sig = &sigScrollRight;
+ else if (actionName == QAccessibleActionInterface::previousPageAction())
+ sig = &sigPreviousPage;
+ else if (actionName == QAccessibleActionInterface::nextPageAction())
+ sig = &sigNextPage;
if (sig && isSignalConnected(*sig))
return sig->invoke(this);
return false;
@@ -375,6 +440,18 @@ void QQuickAccessibleAttached::availableActions(QStringList *actions) const
actions->append(QAccessibleActionInterface::increaseAction());
if (isSignalConnected(sigDecrease))
actions->append(QAccessibleActionInterface::decreaseAction());
+ if (isSignalConnected(sigScrollUp))
+ actions->append(QAccessibleActionInterface::scrollUpAction());
+ if (isSignalConnected(sigScrollDown))
+ actions->append(QAccessibleActionInterface::scrollDownAction());
+ if (isSignalConnected(sigScrollLeft))
+ actions->append(QAccessibleActionInterface::scrollLeftAction());
+ if (isSignalConnected(sigScrollRight))
+ actions->append(QAccessibleActionInterface::scrollRightAction());
+ if (isSignalConnected(sigPreviousPage))
+ actions->append(QAccessibleActionInterface::previousPageAction());
+ if (isSignalConnected(sigNextPage))
+ actions->append(QAccessibleActionInterface::nextPageAction());
}
QT_END_NAMESPACE
diff --git a/src/quick/items/qquickaccessibleattached_p.h b/src/quick/items/qquickaccessibleattached_p.h
index ad6165f936..6286c56d2c 100644
--- a/src/quick/items/qquickaccessibleattached_p.h
+++ b/src/quick/items/qquickaccessibleattached_p.h
@@ -212,6 +212,12 @@ Q_SIGNALS:
void toggleAction();
void increaseAction();
void decreaseAction();
+ void scrollUpAction();
+ void scrollDownAction();
+ void scrollLeftAction();
+ void scrollRightAction();
+ void previousPageAction();
+ void nextPageAction();
private:
QQuickItem *item() const { return static_cast<QQuickItem*>(parent()); }
@@ -225,6 +231,12 @@ private:
static QMetaMethod sigToggle;
static QMetaMethod sigIncrease;
static QMetaMethod sigDecrease;
+ static QMetaMethod sigScrollUp;
+ static QMetaMethod sigScrollDown;
+ static QMetaMethod sigScrollLeft;
+ static QMetaMethod sigScrollRight;
+ static QMetaMethod sigPreviousPage;
+ static QMetaMethod sigNextPage;
public:
using QObject::property;
diff --git a/src/quick/items/qquickanchors_p_p.h b/src/quick/items/qquickanchors_p_p.h
index d07b4369f5..cd5f32c266 100644
--- a/src/quick/items/qquickanchors_p_p.h
+++ b/src/quick/items/qquickanchors_p_p.h
@@ -126,8 +126,8 @@ public:
void updateMe();
// QQuickItemGeometryListener interface
- void itemGeometryChanged(QQuickItem *, const QRectF &, const QRectF &);
- QQuickAnchorsPrivate *anchorPrivate() { return this; }
+ void itemGeometryChanged(QQuickItem *, const QRectF &, const QRectF &) Q_DECL_OVERRIDE;
+ QQuickAnchorsPrivate *anchorPrivate() Q_DECL_OVERRIDE { return this; }
bool checkHValid() const;
bool checkVValid() const;
diff --git a/src/quick/items/qquickanimatedimage_p.h b/src/quick/items/qquickanimatedimage_p.h
index 789f56e6f7..d04cbdf851 100644
--- a/src/quick/items/qquickanimatedimage_p.h
+++ b/src/quick/items/qquickanimatedimage_p.h
@@ -71,7 +71,7 @@ public:
int frameCount() const;
// Extends QQuickImage's src property
- virtual void setSource(const QUrl&);
+ void setSource(const QUrl&) Q_DECL_OVERRIDE;
virtual QSize sourceSize();
Q_SIGNALS:
@@ -86,8 +86,8 @@ private Q_SLOTS:
void playingStatusChanged();
protected:
- virtual void load();
- void componentComplete();
+ void load() Q_DECL_OVERRIDE;
+ void componentComplete() Q_DECL_OVERRIDE;
private:
Q_DISABLE_COPY(QQuickAnimatedImage)
diff --git a/src/quick/items/qquickanimatedsprite.cpp b/src/quick/items/qquickanimatedsprite.cpp
index 5ca17aecec..4d1d8b251e 100644
--- a/src/quick/items/qquickanimatedsprite.cpp
+++ b/src/quick/items/qquickanimatedsprite.cpp
@@ -54,9 +54,9 @@ class QQuickAnimatedSpriteMaterial : public QSGMaterial
public:
QQuickAnimatedSpriteMaterial();
~QQuickAnimatedSpriteMaterial();
- virtual QSGMaterialType *type() const { static QSGMaterialType type; return &type; }
- virtual QSGMaterialShader *createShader() const;
- virtual int compare(const QSGMaterial *other) const
+ QSGMaterialType *type() const Q_DECL_OVERRIDE { static QSGMaterialType type; return &type; }
+ QSGMaterialShader *createShader() const Q_DECL_OVERRIDE;
+ int compare(const QSGMaterial *other) const Q_DECL_OVERRIDE
{
return this - static_cast<const QQuickAnimatedSpriteMaterial *>(other);
}
@@ -100,7 +100,7 @@ public:
setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/items/shaders/sprite.frag"));
}
- virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *)
+ void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *) Q_DECL_OVERRIDE
{
QQuickAnimatedSpriteMaterial *m = static_cast<QQuickAnimatedSpriteMaterial *>(newEffect);
m->texture->bind();
@@ -113,14 +113,14 @@ public:
program()->setUniformValue(m_matrix_id, state.combinedMatrix());
}
- virtual void initialize() {
+ void initialize() Q_DECL_OVERRIDE {
m_matrix_id = program()->uniformLocation("qt_Matrix");
m_opacity_id = program()->uniformLocation("qt_Opacity");
m_animData_id = program()->uniformLocation("animData");
m_animPos_id = program()->uniformLocation("animPos");
}
- virtual char const *const *attributeNames() const {
+ char const *const *attributeNames() const Q_DECL_OVERRIDE {
static const char *attr[] = {
"vPos",
"vTex",
@@ -388,8 +388,8 @@ void QQuickAnimatedSprite::advance(int frames)
//TODO-C: May not work when running - only when paused
m_curFrame += frames;
while (m_curFrame < 0)
- m_curFrame += m_sprite->frames();
- m_curFrame = m_curFrame % m_sprite->frames();
+ m_curFrame += m_spriteEngine->maxFrames();
+ m_curFrame = m_curFrame % m_spriteEngine->maxFrames();
emit currentFrameChanged(m_curFrame);
}
@@ -529,7 +529,6 @@ QSGGeometryNode* QQuickAnimatedSprite::buildNode()
indices[5] = 2;
- m_timestamp.start();
m_node = new QSGGeometryNode();
m_node->setGeometry(g);
m_node->setMaterial(m_material);
@@ -574,43 +573,47 @@ void QQuickAnimatedSprite::prepareNextFrame()
int timeInt = m_timestamp.elapsed() + m_pauseOffset;
qreal time = timeInt / 1000.;
- double frameAt; //double just for modf
+ int frameAt;
qreal progress = 0.0;
int lastFrame = m_curFrame;
- if (!m_paused) {
+ if (m_running && !m_paused) {
+ const int nColumns = int(m_sheetSize.width()) / m_spriteEngine->spriteWidth();
//Advance State (keeps time for psuedostates)
m_spriteEngine->updateSprites(timeInt);
//Advance AnimatedSprite
qreal animT = m_spriteEngine->spriteStart()/1000.0;
- qreal frameCount = m_spriteEngine->spriteFrames();
- qreal frameDuration = m_spriteEngine->spriteDuration()/frameCount;
+ const int frameCountInRow = m_spriteEngine->spriteFrames();
+ const qreal frameDuration = m_spriteEngine->spriteDuration()/frameCountInRow;
if (frameDuration > 0) {
qreal frame = (time - animT)/(frameDuration / 1000.0);
bool lastLoop = m_loops > 0 && m_curLoop == m_loops-1;
//don't visually interpolate for the last frame of the last loop
- qreal max = lastLoop ? frameCount - qreal(1.0) : frameCount;
- frame = qBound(qreal(0.0), frame, max);
- progress = modf(frame,&frameAt);
- if (m_curFrame > frameAt) //went around
+ const int max = lastLoop ? frameCountInRow - 1 : frameCountInRow;
+ frame = qBound(qreal(0.0), frame, qreal(max));
+ double intpart;
+ progress = modf(frame,&intpart);
+ frameAt = (int)intpart;
+ const int rowIndex = m_spriteEngine->spriteY()/frameHeight();
+ const int newFrame = rowIndex * nColumns + frameAt;
+ if (m_curFrame > newFrame) //went around
m_curLoop++;
- m_curFrame = frameAt;
+ m_curFrame = newFrame;
} else {
m_curFrame++;
- if (m_curFrame >= frameCount){
+ if (m_curFrame >= m_spriteEngine->maxFrames()) { // maxFrames: total number of frames including all rows
m_curFrame = 0;
m_curLoop++;
- m_spriteEngine->advance();
}
- frameAt = m_curFrame;
+ frameAt = m_curFrame % nColumns;
+ if (frameAt == 0)
+ m_spriteEngine->advance();
progress = 0;
}
if (m_loops > 0 && m_curLoop >= m_loops) {
frameAt = 0;
- if (m_running) {
- m_running = false;
- emit runningChanged(false);
- }
+ m_running = false;
+ emit runningChanged(false);
}
} else {
frameAt = m_curFrame;
diff --git a/src/quick/items/qquickanimatedsprite_p.h b/src/quick/items/qquickanimatedsprite_p.h
index 0bc2c65b7c..546d239034 100644
--- a/src/quick/items/qquickanimatedsprite_p.h
+++ b/src/quick/items/qquickanimatedsprite_p.h
@@ -343,8 +343,8 @@ private Q_SLOTS:
protected:
void reset();
- void componentComplete();
- QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
+ void componentComplete() Q_DECL_OVERRIDE;
+ QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *) Q_DECL_OVERRIDE;
private:
bool isCurrentFrameChangedConnected();
void prepareNextFrame();
diff --git a/src/quick/items/qquickborderimage_p.h b/src/quick/items/qquickborderimage_p.h
index 6a2469adc2..e998646e48 100644
--- a/src/quick/items/qquickborderimage_p.h
+++ b/src/quick/items/qquickborderimage_p.h
@@ -66,7 +66,7 @@ public:
TileMode verticalTileMode() const;
void setVerticalTileMode(TileMode);
- void setSource(const QUrl &url);
+ void setSource(const QUrl &url) Q_DECL_OVERRIDE;
Q_SIGNALS:
void horizontalTileModeChanged();
@@ -74,16 +74,16 @@ Q_SIGNALS:
void sourceSizeChanged();
protected:
- virtual void load();
- virtual void pixmapChange();
- virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
+ void load() Q_DECL_OVERRIDE;
+ void pixmapChange() Q_DECL_OVERRIDE;
+ QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *) Q_DECL_OVERRIDE;
private:
void setGridScaledImage(const QQuickGridScaledImage& sci);
private Q_SLOTS:
void doUpdate();
- void requestFinished();
+ void requestFinished() Q_DECL_OVERRIDE;
void sciRequestFinished();
private:
diff --git a/src/quick/items/qquickdrag.cpp b/src/quick/items/qquickdrag.cpp
index 5641c323ab..e49347351c 100644
--- a/src/quick/items/qquickdrag.cpp
+++ b/src/quick/items/qquickdrag.cpp
@@ -71,7 +71,7 @@ public:
{
}
- void itemGeometryChanged(QQuickItem *, const QRectF &, const QRectF &);
+ void itemGeometryChanged(QQuickItem *, const QRectF &, const QRectF &) Q_DECL_OVERRIDE;
void itemParentChanged(QQuickItem *, QQuickItem *parent);
void updatePosition();
void restartDrag();
diff --git a/src/quick/items/qquickdroparea_p.h b/src/quick/items/qquickdroparea_p.h
index a0c985ddf7..35a5f3c880 100644
--- a/src/quick/items/qquickdroparea_p.h
+++ b/src/quick/items/qquickdroparea_p.h
@@ -160,10 +160,10 @@ Q_SIGNALS:
void dropped(QQuickDropEvent *drop);
protected:
- void dragMoveEvent(QDragMoveEvent *event);
- void dragEnterEvent(QDragEnterEvent *event);
- void dragLeaveEvent(QDragLeaveEvent *event);
- void dropEvent(QDropEvent *event);
+ void dragMoveEvent(QDragMoveEvent *event) Q_DECL_OVERRIDE;
+ void dragEnterEvent(QDragEnterEvent *event) Q_DECL_OVERRIDE;
+ void dragLeaveEvent(QDragLeaveEvent *event) Q_DECL_OVERRIDE;
+ void dropEvent(QDropEvent *event) Q_DECL_OVERRIDE;
private:
Q_DISABLE_COPY(QQuickDropArea)
diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp
index 9f1de39186..f851ef1bac 100644
--- a/src/quick/items/qquickflickable.cpp
+++ b/src/quick/items/qquickflickable.cpp
@@ -180,7 +180,7 @@ public:
}
protected:
- virtual void finished() {
+ void finished() Q_DECL_OVERRIDE {
if (!flickable)
return;
axisData->move.setValue(axisData->transitionTo);
diff --git a/src/quick/items/qquickflickable_p.h b/src/quick/items/qquickflickable_p.h
index c8a1ba6984..c996d18b01 100644
--- a/src/quick/items/qquickflickable_p.h
+++ b/src/quick/items/qquickflickable_p.h
@@ -220,14 +220,14 @@ Q_SIGNALS:
void pixelAlignedChanged();
protected:
- virtual bool childMouseEventFilter(QQuickItem *, QEvent *);
- virtual void mousePressEvent(QMouseEvent *event);
- virtual void mouseMoveEvent(QMouseEvent *event);
- virtual void mouseReleaseEvent(QMouseEvent *event);
+ bool childMouseEventFilter(QQuickItem *, QEvent *) Q_DECL_OVERRIDE;
+ void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
+ void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
+ void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
#ifndef QT_NO_WHEELEVENT
- virtual void wheelEvent(QWheelEvent *event);
+ void wheelEvent(QWheelEvent *event) Q_DECL_OVERRIDE;
#endif
- virtual void timerEvent(QTimerEvent *event);
+ void timerEvent(QTimerEvent *event) Q_DECL_OVERRIDE;
QQuickFlickableVisibleArea *visibleArea();
@@ -244,11 +244,11 @@ protected:
virtual qreal maxYExtent() const;
qreal vWidth() const;
qreal vHeight() const;
- virtual void componentComplete();
+ void componentComplete() Q_DECL_OVERRIDE;
virtual void viewportMoved(Qt::Orientations orient);
- virtual void geometryChanged(const QRectF &newGeometry,
- const QRectF &oldGeometry);
- void mouseUngrabEvent();
+ void geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry) Q_DECL_OVERRIDE;
+ void mouseUngrabEvent() Q_DECL_OVERRIDE;
bool sendMouseEvent(QQuickItem *item, QMouseEvent *event);
bool xflick() const;
diff --git a/src/quick/items/qquickflickable_p_p.h b/src/quick/items/qquickflickable_p_p.h
index bd8c8de168..af4a4bccbf 100644
--- a/src/quick/items/qquickflickable_p_p.h
+++ b/src/quick/items/qquickflickable_p_p.h
@@ -80,7 +80,7 @@ public:
{
Velocity(QQuickFlickablePrivate *p)
: parent(p) {}
- virtual void setValue(qreal v) {
+ void setValue(qreal v) Q_DECL_OVERRIDE {
if (v != value()) {
QQuickTimeLineValue::setValue(v);
parent->updateVelocity();
@@ -185,7 +185,7 @@ public:
qreal overShootDistance(qreal size);
- void itemGeometryChanged(QQuickItem *, const QRectF &, const QRectF &);
+ void itemGeometryChanged(QQuickItem *, const QRectF &, const QRectF &) Q_DECL_OVERRIDE;
void draggingStarting();
void draggingEnding();
diff --git a/src/quick/items/qquickflipable.cpp b/src/quick/items/qquickflipable.cpp
index 1d439eef05..a68457319b 100644
--- a/src/quick/items/qquickflipable.cpp
+++ b/src/quick/items/qquickflipable.cpp
@@ -51,7 +51,7 @@ public:
transform = t;
update();
}
- virtual void applyTo(QMatrix4x4 *matrix) const {
+ void applyTo(QMatrix4x4 *matrix) const Q_DECL_OVERRIDE {
*matrix *= transform;
}
private:
@@ -64,7 +64,7 @@ class QQuickFlipablePrivate : public QQuickItemPrivate
public:
QQuickFlipablePrivate() : current(QQuickFlipable::Front), front(0), back(0), sideDirty(false) {}
- virtual void transformChanged();
+ void transformChanged() Q_DECL_OVERRIDE;
void updateSide();
void setBackTransform();
diff --git a/src/quick/items/qquickflipable_p.h b/src/quick/items/qquickflipable_p.h
index 0196e35315..9648b22ef6 100644
--- a/src/quick/items/qquickflipable_p.h
+++ b/src/quick/items/qquickflipable_p.h
@@ -72,7 +72,7 @@ Q_SIGNALS:
void sideChanged();
protected:
- virtual void updatePolish();
+ void updatePolish() Q_DECL_OVERRIDE;
private Q_SLOTS:
void retransformBack();
diff --git a/src/quick/items/qquickframebufferobject.h b/src/quick/items/qquickframebufferobject.h
index f6431dc38e..3c3ae77436 100644
--- a/src/quick/items/qquickframebufferobject.h
+++ b/src/quick/items/qquickframebufferobject.h
@@ -80,7 +80,7 @@ public:
void releaseResources() Q_DECL_OVERRIDE;
protected:
- void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry);
+ void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) Q_DECL_OVERRIDE;
protected:
QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *) Q_DECL_OVERRIDE;
diff --git a/src/quick/items/qquickgridview.cpp b/src/quick/items/qquickgridview.cpp
index 72edce4339..e3af926e22 100644
--- a/src/quick/items/qquickgridview.cpp
+++ b/src/quick/items/qquickgridview.cpp
@@ -115,7 +115,7 @@ public:
void setPosition(qreal col, qreal row, bool immediate = false) {
moveTo(pointForPosition(col, row), immediate);
}
- bool contains(qreal x, qreal y) const {
+ bool contains(qreal x, qreal y) const Q_DECL_OVERRIDE {
return (x >= itemX() && x < itemX() + view->cellWidth() &&
y >= itemY() && y < itemY() + view->cellHeight());
}
@@ -152,13 +152,13 @@ class QQuickGridViewPrivate : public QQuickItemViewPrivate
Q_DECLARE_PUBLIC(QQuickGridView)
public:
- virtual Qt::Orientation layoutOrientation() const;
- virtual bool isContentFlowReversed() const;
+ Qt::Orientation layoutOrientation() const Q_DECL_OVERRIDE;
+ bool isContentFlowReversed() const Q_DECL_OVERRIDE;
- virtual qreal positionAt(int index) const;
- virtual qreal endPositionAt(int index) const;
- virtual qreal originPosition() const;
- virtual qreal lastPosition() const;
+ qreal positionAt(int index) const Q_DECL_OVERRIDE;
+ qreal endPositionAt(int index) const Q_DECL_OVERRIDE;
+ qreal originPosition() const Q_DECL_OVERRIDE;
+ qreal lastPosition() const Q_DECL_OVERRIDE;
qreal rowSize() const;
qreal colSize() const;
@@ -172,41 +172,41 @@ public:
void resetColumns();
- virtual bool addVisibleItems(qreal fillFrom, qreal fillTo, qreal bufferFrom, qreal bufferTo, bool doBuffer);
- virtual bool removeNonVisibleItems(qreal bufferFrom, qreal bufferTo);
-
- virtual FxViewItem *newViewItem(int index, QQuickItem *item);
- virtual void initializeViewItem(FxViewItem *item);
- virtual void repositionItemAt(FxViewItem *item, int index, qreal sizeBuffer);
- virtual void repositionPackageItemAt(QQuickItem *item, int index);
- virtual void resetFirstItemPosition(qreal pos = 0.0);
- virtual void adjustFirstItem(qreal forwards, qreal backwards, int changeBeforeVisible);
-
- virtual void createHighlight();
- virtual void updateHighlight();
- virtual void resetHighlightPosition();
-
- virtual void setPosition(qreal pos);
- virtual void layoutVisibleItems(int fromModelIndex = 0);
- virtual bool applyInsertionChange(const QQmlChangeSet::Change &insert, ChangeResult *changeResult, QList<FxViewItem *> *addedItems, QList<MovedItem> *movingIntoView);
- virtual void translateAndTransitionItemsAfter(int afterModelIndex, const ChangeResult &insertionResult, const ChangeResult &removalResult);
- virtual bool needsRefillForAddedOrRemovedIndex(int index) const;
-
- virtual qreal headerSize() const;
- virtual qreal footerSize() const;
- virtual bool showHeaderForIndex(int index) const;
- virtual bool showFooterForIndex(int index) const;
- virtual void updateHeader();
- virtual void updateFooter();
-
- virtual void changedVisibleIndex(int newIndex);
- virtual void initializeCurrentItem();
-
- virtual void updateViewport();
- virtual void fixupPosition();
- virtual void fixup(AxisData &data, qreal minExtent, qreal maxExtent);
- virtual bool flick(QQuickItemViewPrivate::AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize,
- QQuickTimeLineCallback::Callback fixupCallback, qreal velocity);
+ bool addVisibleItems(qreal fillFrom, qreal fillTo, qreal bufferFrom, qreal bufferTo, bool doBuffer) Q_DECL_OVERRIDE;
+ bool removeNonVisibleItems(qreal bufferFrom, qreal bufferTo) Q_DECL_OVERRIDE;
+
+ FxViewItem *newViewItem(int index, QQuickItem *item) Q_DECL_OVERRIDE;
+ void initializeViewItem(FxViewItem *item) Q_DECL_OVERRIDE;
+ void repositionItemAt(FxViewItem *item, int index, qreal sizeBuffer) Q_DECL_OVERRIDE;
+ void repositionPackageItemAt(QQuickItem *item, int index) Q_DECL_OVERRIDE;
+ void resetFirstItemPosition(qreal pos = 0.0) Q_DECL_OVERRIDE;
+ void adjustFirstItem(qreal forwards, qreal backwards, int changeBeforeVisible) Q_DECL_OVERRIDE;
+
+ void createHighlight() Q_DECL_OVERRIDE;
+ void updateHighlight() Q_DECL_OVERRIDE;
+ void resetHighlightPosition() Q_DECL_OVERRIDE;
+
+ void setPosition(qreal pos) Q_DECL_OVERRIDE;
+ void layoutVisibleItems(int fromModelIndex = 0) Q_DECL_OVERRIDE;
+ bool applyInsertionChange(const QQmlChangeSet::Change &insert, ChangeResult *changeResult, QList<FxViewItem *> *addedItems, QList<MovedItem> *movingIntoView) Q_DECL_OVERRIDE;
+ void translateAndTransitionItemsAfter(int afterModelIndex, const ChangeResult &insertionResult, const ChangeResult &removalResult) Q_DECL_OVERRIDE;
+ bool needsRefillForAddedOrRemovedIndex(int index) const Q_DECL_OVERRIDE;
+
+ qreal headerSize() const Q_DECL_OVERRIDE;
+ qreal footerSize() const Q_DECL_OVERRIDE;
+ bool showHeaderForIndex(int index) const Q_DECL_OVERRIDE;
+ bool showFooterForIndex(int index) const Q_DECL_OVERRIDE;
+ void updateHeader() Q_DECL_OVERRIDE;
+ void updateFooter() Q_DECL_OVERRIDE;
+
+ void changedVisibleIndex(int newIndex) Q_DECL_OVERRIDE;
+ void initializeCurrentItem() Q_DECL_OVERRIDE;
+
+ void updateViewport() Q_DECL_OVERRIDE;
+ void fixupPosition() Q_DECL_OVERRIDE;
+ void fixup(AxisData &data, qreal minExtent, qreal maxExtent) Q_DECL_OVERRIDE;
+ bool flick(QQuickItemViewPrivate::AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize,
+ QQuickTimeLineCallback::Callback fixupCallback, qreal velocity) Q_DECL_OVERRIDE;
QQuickGridView::Flow flow;
qreal cellWidth;
diff --git a/src/quick/items/qquickgridview_p.h b/src/quick/items/qquickgridview_p.h
index 7468a49ac1..b835b0a070 100644
--- a/src/quick/items/qquickgridview_p.h
+++ b/src/quick/items/qquickgridview_p.h
@@ -65,8 +65,8 @@ public:
QQuickGridView(QQuickItem *parent=0);
~QQuickGridView();
- virtual void setHighlightFollowsCurrentItem(bool);
- virtual void setHighlightMoveDuration(int);
+ void setHighlightFollowsCurrentItem(bool) Q_DECL_OVERRIDE;
+ void setHighlightMoveDuration(int) Q_DECL_OVERRIDE;
Flow flow() const;
void setFlow(Flow);
@@ -97,10 +97,10 @@ Q_SIGNALS:
void snapModeChanged();
protected:
- virtual void viewportMoved(Qt::Orientations);
- virtual void keyPressEvent(QKeyEvent *);
- virtual void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry);
- virtual void initItem(int index, QObject *item);
+ void viewportMoved(Qt::Orientations) Q_DECL_OVERRIDE;
+ void keyPressEvent(QKeyEvent *) Q_DECL_OVERRIDE;
+ void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) Q_DECL_OVERRIDE;
+ void initItem(int index, QObject *item) Q_DECL_OVERRIDE;
};
class QQuickGridViewAttached : public QQuickItemViewAttached
diff --git a/src/quick/items/qquickimage_p.h b/src/quick/items/qquickimage_p.h
index b359ff779d..eef5c3901d 100644
--- a/src/quick/items/qquickimage_p.h
+++ b/src/quick/items/qquickimage_p.h
@@ -73,7 +73,7 @@ public:
qreal paintedWidth() const;
qreal paintedHeight() const;
- QRectF boundingRect() const;
+ QRectF boundingRect() const Q_DECL_OVERRIDE;
HAlignment horizontalAlignment() const;
void setHorizontalAlignment(HAlignment align);
@@ -81,8 +81,8 @@ public:
VAlignment verticalAlignment() const;
void setVerticalAlignment(VAlignment align);
- bool isTextureProvider() const { return true; }
- QSGTextureProvider *textureProvider() const;
+ bool isTextureProvider() const Q_DECL_OVERRIDE { return true; }
+ QSGTextureProvider *textureProvider() const Q_DECL_OVERRIDE;
bool mipmap() const;
void setMipmap(bool use);
@@ -99,12 +99,12 @@ private Q_SLOTS:
protected:
QQuickImage(QQuickImagePrivate &dd, QQuickItem *parent);
- void pixmapChange();
+ void pixmapChange() Q_DECL_OVERRIDE;
void updatePaintedGeometry();
void releaseResources() Q_DECL_OVERRIDE;
- virtual void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry);
- virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
+ void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) Q_DECL_OVERRIDE;
+ QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *) Q_DECL_OVERRIDE;
private:
Q_DISABLE_COPY(QQuickImage)
diff --git a/src/quick/items/qquickimagebase_p.h b/src/quick/items/qquickimagebase_p.h
index 2750db8873..c204bdd442 100644
--- a/src/quick/items/qquickimagebase_p.h
+++ b/src/quick/items/qquickimagebase_p.h
@@ -91,7 +91,7 @@ Q_SIGNALS:
protected:
virtual void load();
- virtual void componentComplete();
+ void componentComplete() Q_DECL_OVERRIDE;
virtual void pixmapChange();
void itemChange(ItemChange change, const ItemChangeData &value) Q_DECL_OVERRIDE;
QQuickImageBase(QQuickImageBasePrivate &dd, QQuickItem *parent);
diff --git a/src/quick/items/qquickimplicitsizeitem_p_p.h b/src/quick/items/qquickimplicitsizeitem_p_p.h
index cdf768cbd9..c34e3424b0 100644
--- a/src/quick/items/qquickimplicitsizeitem_p_p.h
+++ b/src/quick/items/qquickimplicitsizeitem_p_p.h
@@ -60,8 +60,8 @@ public:
{
}
- virtual void implicitWidthChanged();
- virtual void implicitHeightChanged();
+ void implicitWidthChanged() Q_DECL_OVERRIDE;
+ void implicitHeightChanged() Q_DECL_OVERRIDE;
};
QT_END_NAMESPACE
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp
index 2722f48ce9..38736e44b2 100644
--- a/src/quick/items/qquickitem.cpp
+++ b/src/quick/items/qquickitem.cpp
@@ -2724,8 +2724,11 @@ void QQuickItemPrivate::addChild(QQuickItem *child)
#ifndef QT_NO_CURSOR
QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(child);
- if (childPrivate->extra.isAllocated())
- incrementCursorCount(childPrivate->extra.value().numItemsWithCursor);
+
+ // if the added child has a cursor and we do not currently have any children
+ // with cursors, bubble the notification up
+ if (childPrivate->hasCursorInChild && !hasCursorInChild)
+ setHasCursorInChild(true);
#endif
markSortedChildrenDirty(child);
@@ -2747,8 +2750,10 @@ void QQuickItemPrivate::removeChild(QQuickItem *child)
#ifndef QT_NO_CURSOR
QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(child);
- if (childPrivate->extra.isAllocated())
- incrementCursorCount(-childPrivate->extra.value().numItemsWithCursor);
+
+ // turn it off, if nothing else is using it
+ if (childPrivate->hasCursorInChild && hasCursorInChild)
+ setHasCursorInChild(false);
#endif
markSortedChildrenDirty(child);
@@ -2843,10 +2848,8 @@ void QQuickItemPrivate::derefWindow()
extra->opacityNode = 0;
extra->clipNode = 0;
extra->rootNode = 0;
- extra->beforePaintNode = 0;
}
- groupNode = 0;
paintNode = 0;
for (int ii = 0; ii < childItems.count(); ++ii) {
@@ -2952,6 +2955,7 @@ QQuickItemPrivate::QQuickItemPrivate()
, isAccessible(false)
, culled(false)
, hasCursor(false)
+ , hasCursorInChild(false)
, activeFocusOnTab(false)
, implicitAntialiasing(false)
, antialiasingValid(false)
@@ -2971,7 +2975,6 @@ QQuickItemPrivate::QQuickItemPrivate()
, implicitHeight(0)
, baselineOffset(0)
, itemNodeInstance(0)
- , groupNode(0)
, paintNode(0)
{
}
@@ -4151,7 +4154,7 @@ void QQuickItem::mapFromItem(QQmlV4Function *args) const
return;
}
- QV4::Scoped<QV4::Object> rv(scope, v4->newObject());
+ QV4::ScopedObject rv(scope, v4->newObject());
args->setReturnValue(rv.asReturnedValue());
QV4::ScopedString s(scope);
@@ -4166,15 +4169,15 @@ void QQuickItem::mapFromItem(QQmlV4Function *args) const
QRectF r = mapRectFromItem(itemObj, QRectF(x, y, w, h));
- rv->put((s = v4->newString(QStringLiteral("x"))).getPointer(), (v = QV4::Primitive::fromDouble(r.x())));
- rv->put((s = v4->newString(QStringLiteral("y"))).getPointer(), (v = QV4::Primitive::fromDouble(r.y())));
- rv->put((s = v4->newString(QStringLiteral("width"))).getPointer(), (v = QV4::Primitive::fromDouble(r.width())));
- rv->put((s = v4->newString(QStringLiteral("height"))).getPointer(), (v = QV4::Primitive::fromDouble(r.height())));
+ rv->put((s = v4->newString(QStringLiteral("x"))), (v = QV4::Primitive::fromDouble(r.x())));
+ rv->put((s = v4->newString(QStringLiteral("y"))), (v = QV4::Primitive::fromDouble(r.y())));
+ rv->put((s = v4->newString(QStringLiteral("width"))), (v = QV4::Primitive::fromDouble(r.width())));
+ rv->put((s = v4->newString(QStringLiteral("height"))), (v = QV4::Primitive::fromDouble(r.height())));
} else {
QPointF p = mapFromItem(itemObj, QPointF(x, y));
- rv->put((s = v4->newString(QStringLiteral("x"))).getPointer(), (v = QV4::Primitive::fromDouble(p.x())));
- rv->put((s = v4->newString(QStringLiteral("y"))).getPointer(), (v = QV4::Primitive::fromDouble(p.y())));
+ rv->put((s = v4->newString(QStringLiteral("x"))), (v = QV4::Primitive::fromDouble(p.x())));
+ rv->put((s = v4->newString(QStringLiteral("y"))), (v = QV4::Primitive::fromDouble(p.y())));
}
}
}
@@ -4230,7 +4233,7 @@ void QQuickItem::mapToItem(QQmlV4Function *args) const
return;
}
- QV4::Scoped<QV4::Object> rv(scope, v4->newObject());
+ QV4::ScopedObject rv(scope, v4->newObject());
args->setReturnValue(rv.asReturnedValue());
QV4::ScopedValue v(scope);
@@ -4246,15 +4249,15 @@ void QQuickItem::mapToItem(QQmlV4Function *args) const
QRectF r = mapRectToItem(itemObj, QRectF(x, y, w, h));
- rv->put((s = v4->newString(QStringLiteral("x"))).getPointer(), (v = QV4::Primitive::fromDouble(r.x())));
- rv->put((s = v4->newString(QStringLiteral("y"))).getPointer(), (v = QV4::Primitive::fromDouble(r.y())));
- rv->put((s = v4->newString(QStringLiteral("width"))).getPointer(), (v = QV4::Primitive::fromDouble(r.width())));
- rv->put((s = v4->newString(QStringLiteral("height"))).getPointer(), (v = QV4::Primitive::fromDouble(r.height())));
+ rv->put((s = v4->newString(QStringLiteral("x"))), (v = QV4::Primitive::fromDouble(r.x())));
+ rv->put((s = v4->newString(QStringLiteral("y"))), (v = QV4::Primitive::fromDouble(r.y())));
+ rv->put((s = v4->newString(QStringLiteral("width"))), (v = QV4::Primitive::fromDouble(r.width())));
+ rv->put((s = v4->newString(QStringLiteral("height"))), (v = QV4::Primitive::fromDouble(r.height())));
} else {
QPointF p = mapToItem(itemObj, QPointF(x, y));
- rv->put((s = v4->newString(QStringLiteral("x"))).getPointer(), (v = QV4::Primitive::fromDouble(p.x())));
- rv->put((s = v4->newString(QStringLiteral("y"))).getPointer(), (v = QV4::Primitive::fromDouble(p.y())));
+ rv->put((s = v4->newString(QStringLiteral("x"))), (v = QV4::Primitive::fromDouble(p.x())));
+ rv->put((s = v4->newString(QStringLiteral("y"))), (v = QV4::Primitive::fromDouble(p.y())));
}
}
}
@@ -6736,15 +6739,27 @@ void QQuickItem::setAcceptHoverEvents(bool enabled)
d->hoverEnabled = enabled;
}
-void QQuickItemPrivate::incrementCursorCount(int delta)
+void QQuickItemPrivate::setHasCursorInChild(bool hasCursor)
{
#ifndef QT_NO_CURSOR
Q_Q(QQuickItem);
- extra.value().numItemsWithCursor += delta;
+
+ // if we're asked to turn it off (because of an unsetcursor call, or a node
+ // removal) then we should check our children and make sure it's really ok
+ // to turn it off.
+ if (!hasCursor && hasCursorInChild) {
+ foreach (QQuickItem *otherChild, childItems) {
+ QQuickItemPrivate *otherChildPrivate = QQuickItemPrivate::get(otherChild);
+ if (otherChildPrivate->hasCursorInChild)
+ return; // nope! sorry, something else wants it kept on.
+ }
+ }
+
+ hasCursorInChild = hasCursor;
QQuickItem *parent = q->parentItem();
if (parent) {
QQuickItemPrivate *parentPrivate = QQuickItemPrivate::get(parent);
- parentPrivate->incrementCursorCount(delta);
+ parentPrivate->setHasCursorInChild(hasCursor);
}
#endif
}
@@ -6807,7 +6822,7 @@ void QQuickItem::setCursor(const QCursor &cursor)
}
if (!d->hasCursor) {
- d->incrementCursorCount(+1);
+ d->setHasCursorInChild(true);
d->hasCursor = true;
if (d->window) {
QWindow *renderWindow = QQuickRenderControl::renderWindowFor(d->window);
@@ -6830,7 +6845,7 @@ void QQuickItem::unsetCursor()
Q_D(QQuickItem);
if (!d->hasCursor)
return;
- d->incrementCursorCount(-1);
+ d->setHasCursorInChild(false);
d->hasCursor = false;
if (d->extra.isAllocated())
d->extra->cursor = QCursor();
@@ -7819,11 +7834,8 @@ QQuickItemPrivate::ExtraData::ExtraData()
: z(0), scale(1), rotation(0), opacity(1),
contents(0), screenAttached(0), layoutDirectionAttached(0),
keyHandler(0), layer(0),
-#ifndef QT_NO_CURSOR
- numItemsWithCursor(0),
-#endif
effectRefCount(0), hideRefCount(0),
- opacityNode(0), clipNode(0), rootNode(0), beforePaintNode(0),
+ opacityNode(0), clipNode(0), rootNode(0),
acceptedMouseButtons(0), origin(QQuickItem::Center),
transparentForPositioner(false)
{
diff --git a/src/quick/items/qquickitem.h b/src/quick/items/qquickitem.h
index c17f6a6a7d..e93e8c1439 100644
--- a/src/quick/items/qquickitem.h
+++ b/src/quick/items/qquickitem.h
@@ -376,7 +376,7 @@ Q_SIGNALS:
void implicitHeightChanged();
protected:
- virtual bool event(QEvent *);
+ bool event(QEvent *) Q_DECL_OVERRIDE;
bool isComponentComplete() const;
virtual void itemChange(ItemChange, const ItemChangeData &);
diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h
index 7ef0f903b5..02d3b820a0 100644
--- a/src/quick/items/qquickitem_p.h
+++ b/src/quick/items/qquickitem_p.h
@@ -92,10 +92,10 @@ public:
void complete();
protected:
- void itemGeometryChanged(QQuickItem *item, const QRectF &newGeometry, const QRectF &oldGeometry);
- void itemDestroyed(QQuickItem *item);
- void itemChildAdded(QQuickItem *, QQuickItem *);
- void itemChildRemoved(QQuickItem *, QQuickItem *);
+ void itemGeometryChanged(QQuickItem *item, const QRectF &newGeometry, const QRectF &oldGeometry) Q_DECL_OVERRIDE;
+ void itemDestroyed(QQuickItem *item) Q_DECL_OVERRIDE;
+ void itemChildAdded(QQuickItem *, QQuickItem *) Q_DECL_OVERRIDE;
+ void itemChildRemoved(QQuickItem *, QQuickItem *) Q_DECL_OVERRIDE;
//void itemVisibilityChanged(QQuickItem *item)
private:
@@ -178,11 +178,11 @@ public:
QQuickShaderEffectSource *effectSource() const { return m_effectSource; }
- void itemGeometryChanged(QQuickItem *, const QRectF &, const QRectF &);
- void itemOpacityChanged(QQuickItem *);
- void itemParentChanged(QQuickItem *, QQuickItem *);
- void itemSiblingOrderChanged(QQuickItem *);
- void itemVisibilityChanged(QQuickItem *);
+ void itemGeometryChanged(QQuickItem *, const QRectF &, const QRectF &) Q_DECL_OVERRIDE;
+ void itemOpacityChanged(QQuickItem *) Q_DECL_OVERRIDE;
+ void itemParentChanged(QQuickItem *, QQuickItem *) Q_DECL_OVERRIDE;
+ void itemSiblingOrderChanged(QQuickItem *) Q_DECL_OVERRIDE;
+ void itemVisibilityChanged(QQuickItem *) Q_DECL_OVERRIDE;
void updateMatrix();
void updateGeometry();
@@ -342,7 +342,6 @@ public:
mutable QQuickItemLayer *layer;
#ifndef QT_NO_CURSOR
QCursor cursor;
- int numItemsWithCursor;
#endif
QPointF userTransformOriginPoint;
@@ -352,7 +351,8 @@ public:
QSGOpacityNode *opacityNode;
QQuickDefaultClipNode *clipNode;
QSGRootNode *rootNode;
- QSGNode *beforePaintNode;
+
+ QObjectList resourcesList;
// Although acceptedMouseButtons is inside ExtraData, we actually store
// the LeftButton flag in the extra.flag() bit. This is because it is
@@ -363,7 +363,7 @@ public:
QQuickItem::TransformOrigin origin:5;
uint transparentForPositioner : 1;
- QObjectList resourcesList;
+ // 26 bits padding
};
QLazilyAllocated<ExtraData> extra;
@@ -415,6 +415,7 @@ public:
bool culled:1;
bool hasCursor:1;
// Bit 32
+ bool hasCursorInChild:1;
bool activeFocusOnTab:1;
bool implicitAntialiasing:1;
bool antialiasingValid:1;
@@ -556,8 +557,7 @@ public:
- itemNode
- (opacityNode)
- (clipNode)
- - (effectNode)
- - groupNode
+ - (rootNode) (shader effect source's root node)
*/
QSGOpacityNode *opacityNode() const { return extra.isAllocated()?extra->opacityNode:0; }
@@ -565,7 +565,6 @@ public:
QSGRootNode *rootNode() const { return extra.isAllocated()?extra->rootNode:0; }
QSGTransformNode *itemNodeInstance;
- QSGNode *groupNode;
QSGNode *paintNode;
virtual QSGTransformNode *createTransformNode();
@@ -579,7 +578,7 @@ public:
virtual void mirrorChange() {}
- void incrementCursorCount(int delta);
+ void setHasCursorInChild(bool hasCursor);
// recursive helper to let a visual parent mark its visual children
void markObjects(QV4::ExecutionEngine *e);
@@ -681,8 +680,8 @@ Q_SIGNALS:
void priorityChanged();
private:
- virtual void keyPressed(QKeyEvent *event, bool post);
- virtual void keyReleased(QKeyEvent *event, bool post);
+ void keyPressed(QKeyEvent *event, bool post) Q_DECL_OVERRIDE;
+ void keyReleased(QKeyEvent *event, bool post) Q_DECL_OVERRIDE;
void setFocusNavigation(QQuickItem *currentItem, const char *dir,
Qt::FocusReason reason = Qt::OtherFocusReason);
};
@@ -765,7 +764,7 @@ public:
return QQmlListProperty<QQuickItem>(this, d->targets);
}
- virtual void componentComplete();
+ void componentComplete() Q_DECL_OVERRIDE;
static QQuickKeysAttached *qmlAttachedProperties(QObject *);
@@ -816,11 +815,11 @@ Q_SIGNALS:
void volumeDownPressed(QQuickKeyEvent *event);
private:
- virtual void keyPressed(QKeyEvent *event, bool post);
- virtual void keyReleased(QKeyEvent *event, bool post);
+ void keyPressed(QKeyEvent *event, bool post) Q_DECL_OVERRIDE;
+ void keyReleased(QKeyEvent *event, bool post) Q_DECL_OVERRIDE;
#ifndef QT_NO_IM
- virtual void inputMethodEvent(QInputMethodEvent *, bool post);
- virtual QVariant inputMethodQuery(Qt::InputMethodQuery query) const;
+ void inputMethodEvent(QInputMethodEvent *, bool post) Q_DECL_OVERRIDE;
+ QVariant inputMethodQuery(Qt::InputMethodQuery query) const Q_DECL_OVERRIDE;
#endif
const QByteArray keyToSignal(int key);
@@ -868,7 +867,7 @@ QSGTransformNode *QQuickItemPrivate::itemNode()
itemNodeInstance->setFlag(QSGNode::OwnedByParent, false);
#ifdef QSG_RUNTIME_DESCRIPTION
Q_Q(QQuickItem);
- qsgnode_set_description(itemNodeInstance, QString::fromLatin1("QQuickItem(%1)").arg(QString::fromLatin1(q->metaObject()->className())));
+ qsgnode_set_description(itemNodeInstance, QString::fromLatin1("QQuickItem(%1:%2)").arg(QString::fromLatin1(q->metaObject()->className())).arg(q->objectName()));
#endif
}
return itemNodeInstance;
@@ -876,21 +875,14 @@ QSGTransformNode *QQuickItemPrivate::itemNode()
QSGNode *QQuickItemPrivate::childContainerNode()
{
- if (!groupNode) {
- groupNode = new QSGNode();
- if (rootNode())
- rootNode()->appendChildNode(groupNode);
- else if (clipNode())
- clipNode()->appendChildNode(groupNode);
- else if (opacityNode())
- opacityNode()->appendChildNode(groupNode);
- else
- itemNode()->appendChildNode(groupNode);
-#ifdef QSG_RUNTIME_DESCRIPTION
- qsgnode_set_description(groupNode, QLatin1String("group"));
-#endif
- }
- return groupNode;
+ if (rootNode())
+ return rootNode();
+ else if (clipNode())
+ return clipNode();
+ else if (opacityNode())
+ return opacityNode();
+ else
+ return itemNode();
}
Q_DECLARE_OPERATORS_FOR_FLAGS(QQuickItemPrivate::ChangeTypes)
diff --git a/src/quick/items/qquickitemanimation.cpp b/src/quick/items/qquickitemanimation.cpp
index c7c40980dc..810b487e3a 100644
--- a/src/quick/items/qquickitemanimation.cpp
+++ b/src/quick/items/qquickitemanimation.cpp
@@ -210,7 +210,7 @@ QAbstractAnimationJob* QQuickParentAnimation::transition(QQuickStateActions &act
//### reverse should probably apply on a per-action basis
bool reverse;
QList<QQuickParentChange *> pc;
- virtual void doAction()
+ void doAction() Q_DECL_OVERRIDE
{
for (int ii = 0; ii < actions.count(); ++ii) {
const QQuickStateAction &action = actions.at(ii);
diff --git a/src/quick/items/qquickitemanimation_p.h b/src/quick/items/qquickitemanimation_p.h
index d16c9f8107..a1bc4b6bdf 100644
--- a/src/quick/items/qquickitemanimation_p.h
+++ b/src/quick/items/qquickitemanimation_p.h
@@ -69,10 +69,10 @@ Q_SIGNALS:
void viaChanged();
protected:
- virtual QAbstractAnimationJob* transition(QQuickStateActions &actions,
+ QAbstractAnimationJob* transition(QQuickStateActions &actions,
QQmlProperties &modified,
TransitionDirection direction,
- QObject *defaultTarget = 0);
+ QObject *defaultTarget = 0) Q_DECL_OVERRIDE;
};
class QQuickAnchorAnimationPrivate;
@@ -101,10 +101,10 @@ Q_SIGNALS:
void easingChanged(const QEasingCurve&);
protected:
- virtual QAbstractAnimationJob* transition(QQuickStateActions &actions,
+ QAbstractAnimationJob* transition(QQuickStateActions &actions,
QQmlProperties &modified,
TransitionDirection direction,
- QObject *defaultTarget = 0);
+ QObject *defaultTarget = 0) Q_DECL_OVERRIDE;
};
class QQuickItem;
@@ -166,10 +166,10 @@ public:
void setEndRotation(qreal);
protected:
- virtual QAbstractAnimationJob* transition(QQuickStateActions &actions,
+ QAbstractAnimationJob* transition(QQuickStateActions &actions,
QQmlProperties &modified,
TransitionDirection direction,
- QObject *defaultTarget = 0);
+ QObject *defaultTarget = 0) Q_DECL_OVERRIDE;
Q_SIGNALS:
void durationChanged(int);
void easingChanged(const QEasingCurve &);
diff --git a/src/quick/items/qquickitemview_p.h b/src/quick/items/qquickitemview_p.h
index 89c3bec465..3e7acdd26c 100644
--- a/src/quick/items/qquickitemview_p.h
+++ b/src/quick/items/qquickitemview_p.h
@@ -208,10 +208,10 @@ public:
Q_INVOKABLE void positionViewAtEnd();
Q_REVISION(1) Q_INVOKABLE void forceLayout();
- virtual void setContentX(qreal pos);
- virtual void setContentY(qreal pos);
- virtual qreal originX() const;
- virtual qreal originY() const;
+ void setContentX(qreal pos) Q_DECL_OVERRIDE;
+ void setContentY(qreal pos) Q_DECL_OVERRIDE;
+ qreal originX() const Q_DECL_OVERRIDE;
+ qreal originY() const Q_DECL_OVERRIDE;
Q_SIGNALS:
void modelChanged();
@@ -252,13 +252,13 @@ Q_SIGNALS:
void highlightMoveDurationChanged();
protected:
- virtual void updatePolish();
- virtual void componentComplete();
- virtual void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry);
- virtual qreal minYExtent() const;
- virtual qreal maxYExtent() const;
- virtual qreal minXExtent() const;
- virtual qreal maxXExtent() const;
+ void updatePolish() Q_DECL_OVERRIDE;
+ void componentComplete() Q_DECL_OVERRIDE;
+ void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) Q_DECL_OVERRIDE;
+ qreal minYExtent() const Q_DECL_OVERRIDE;
+ qreal maxYExtent() const Q_DECL_OVERRIDE;
+ qreal minXExtent() const Q_DECL_OVERRIDE;
+ qreal maxXExtent() const Q_DECL_OVERRIDE;
protected Q_SLOTS:
void destroyRemoved();
diff --git a/src/quick/items/qquickitemview_p_p.h b/src/quick/items/qquickitemview_p_p.h
index 76fc326367..b053b1ea6e 100644
--- a/src/quick/items/qquickitemview_p_p.h
+++ b/src/quick/items/qquickitemview_p_p.h
@@ -181,7 +181,7 @@ public:
virtual void animationFinished(QAbstractAnimationJob *);
void refill();
void refill(qreal from, qreal to);
- void mirrorChange();
+ void mirrorChange() Q_DECL_OVERRIDE;
FxViewItem *createItem(int modelIndex, bool asynchronous = false);
virtual bool releaseItem(FxViewItem *item);
@@ -211,7 +211,7 @@ public:
void prepareVisibleItemTransitions();
void prepareRemoveTransitions(QHash<QQmlChangeSet::MoveKey, FxViewItem *> *removedItems);
bool prepareNonVisibleItemTransition(FxViewItem *item, const QRectF &viewBounds);
- virtual void viewItemTransitionFinished(QQuickItemViewTransitionableItem *item);
+ void viewItemTransitionFinished(QQuickItemViewTransitionableItem *item) Q_DECL_OVERRIDE;
int findMoveKeyIndex(QQmlChangeSet::MoveKey key, const QVector<QQmlChangeSet::Change> &changes) const;
@@ -353,7 +353,7 @@ protected:
virtual void updateSectionCriteria() {}
virtual void updateSections() {}
- virtual void itemGeometryChanged(QQuickItem *item, const QRectF &newGeometry, const QRectF &oldGeometry);
+ void itemGeometryChanged(QQuickItem *item, const QRectF &newGeometry, const QRectF &oldGeometry) Q_DECL_OVERRIDE;
};
diff --git a/src/quick/items/qquickitemviewtransition.cpp b/src/quick/items/qquickitemviewtransition.cpp
index 41ee9bb1f2..9c14133cbd 100644
--- a/src/quick/items/qquickitemviewtransition.cpp
+++ b/src/quick/items/qquickitemviewtransition.cpp
@@ -57,7 +57,7 @@ public:
bool *m_wasDeleted;
protected:
- virtual void finished();
+ void finished() Q_DECL_OVERRIDE;
};
diff --git a/src/quick/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp
index d381fe2030..8afd5793fc 100644
--- a/src/quick/items/qquicklistview.cpp
+++ b/src/quick/items/qquicklistview.cpp
@@ -59,49 +59,49 @@ class QQuickListViewPrivate : public QQuickItemViewPrivate
public:
static QQuickListViewPrivate* get(QQuickListView *item) { return item->d_func(); }
- virtual Qt::Orientation layoutOrientation() const;
- virtual bool isContentFlowReversed() const;
+ Qt::Orientation layoutOrientation() const Q_DECL_OVERRIDE;
+ bool isContentFlowReversed() const Q_DECL_OVERRIDE;
bool isRightToLeft() const;
bool isBottomToTop() const;
- virtual qreal positionAt(int index) const;
- virtual qreal endPositionAt(int index) const;
- virtual qreal originPosition() const;
- virtual qreal lastPosition() const;
+ qreal positionAt(int index) const Q_DECL_OVERRIDE;
+ qreal endPositionAt(int index) const Q_DECL_OVERRIDE;
+ qreal originPosition() const Q_DECL_OVERRIDE;
+ qreal lastPosition() const Q_DECL_OVERRIDE;
FxViewItem *itemBefore(int modelIndex) const;
QString sectionAt(int modelIndex);
qreal snapPosAt(qreal pos);
FxViewItem *snapItemAt(qreal pos);
- virtual void init();
- virtual void clear();
+ void init() Q_DECL_OVERRIDE;
+ void clear() Q_DECL_OVERRIDE;
- virtual bool addVisibleItems(qreal fillFrom, qreal fillTo, qreal bufferFrom, qreal bufferTo, bool doBuffer);
- virtual bool removeNonVisibleItems(qreal bufferFrom, qreal bufferTo);
- virtual void visibleItemsChanged();
+ bool addVisibleItems(qreal fillFrom, qreal fillTo, qreal bufferFrom, qreal bufferTo, bool doBuffer) Q_DECL_OVERRIDE;
+ bool removeNonVisibleItems(qreal bufferFrom, qreal bufferTo) Q_DECL_OVERRIDE;
+ void visibleItemsChanged() Q_DECL_OVERRIDE;
- virtual FxViewItem *newViewItem(int index, QQuickItem *item);
- virtual void initializeViewItem(FxViewItem *item);
- virtual bool releaseItem(FxViewItem *item);
- virtual void repositionItemAt(FxViewItem *item, int index, qreal sizeBuffer);
- virtual void repositionPackageItemAt(QQuickItem *item, int index);
- virtual void resetFirstItemPosition(qreal pos = 0.0);
- virtual void adjustFirstItem(qreal forwards, qreal backwards, int);
- virtual void updateSizeChangesBeforeVisiblePos(FxViewItem *item, ChangeResult *removeResult);
+ FxViewItem *newViewItem(int index, QQuickItem *item) Q_DECL_OVERRIDE;
+ void initializeViewItem(FxViewItem *item) Q_DECL_OVERRIDE;
+ bool releaseItem(FxViewItem *item) Q_DECL_OVERRIDE;
+ void repositionItemAt(FxViewItem *item, int index, qreal sizeBuffer) Q_DECL_OVERRIDE;
+ void repositionPackageItemAt(QQuickItem *item, int index) Q_DECL_OVERRIDE;
+ void resetFirstItemPosition(qreal pos = 0.0) Q_DECL_OVERRIDE;
+ void adjustFirstItem(qreal forwards, qreal backwards, int) Q_DECL_OVERRIDE;
+ void updateSizeChangesBeforeVisiblePos(FxViewItem *item, ChangeResult *removeResult) Q_DECL_OVERRIDE;
- virtual void createHighlight();
- virtual void updateHighlight();
- virtual void resetHighlightPosition();
+ void createHighlight() Q_DECL_OVERRIDE;
+ void updateHighlight() Q_DECL_OVERRIDE;
+ void resetHighlightPosition() Q_DECL_OVERRIDE;
- virtual void setPosition(qreal pos);
- virtual void layoutVisibleItems(int fromModelIndex = 0);
+ void setPosition(qreal pos) Q_DECL_OVERRIDE;
+ void layoutVisibleItems(int fromModelIndex = 0) Q_DECL_OVERRIDE;
- virtual bool applyInsertionChange(const QQmlChangeSet::Change &insert, ChangeResult *changeResult, QList<FxViewItem *> *addedItems, QList<MovedItem> *movingIntoView);
- virtual void translateAndTransitionItemsAfter(int afterIndex, const ChangeResult &insertionResult, const ChangeResult &removalResult);
+ bool applyInsertionChange(const QQmlChangeSet::Change &insert, ChangeResult *changeResult, QList<FxViewItem *> *addedItems, QList<MovedItem> *movingIntoView) Q_DECL_OVERRIDE;
+ void translateAndTransitionItemsAfter(int afterIndex, const ChangeResult &insertionResult, const ChangeResult &removalResult) Q_DECL_OVERRIDE;
- virtual void updateSectionCriteria();
- virtual void updateSections();
+ void updateSectionCriteria() Q_DECL_OVERRIDE;
+ void updateSections() Q_DECL_OVERRIDE;
QQuickItem *getSectionItem(const QString &section);
void releaseSectionItem(QQuickItem *item);
void releaseSectionItems();
@@ -109,25 +109,25 @@ public:
void updateCurrentSection();
void updateStickySections();
- virtual qreal headerSize() const;
- virtual qreal footerSize() const;
- virtual bool showHeaderForIndex(int index) const;
- virtual bool showFooterForIndex(int index) const;
- virtual void updateHeader();
- virtual void updateFooter();
+ qreal headerSize() const Q_DECL_OVERRIDE;
+ qreal footerSize() const Q_DECL_OVERRIDE;
+ bool showHeaderForIndex(int index) const Q_DECL_OVERRIDE;
+ bool showFooterForIndex(int index) const Q_DECL_OVERRIDE;
+ void updateHeader() Q_DECL_OVERRIDE;
+ void updateFooter() Q_DECL_OVERRIDE;
bool hasStickyHeader() const;
bool hasStickyFooter() const;
- virtual void changedVisibleIndex(int newIndex);
- virtual void initializeCurrentItem();
+ void changedVisibleIndex(int newIndex) Q_DECL_OVERRIDE;
+ void initializeCurrentItem() Q_DECL_OVERRIDE;
void updateAverage();
- void itemGeometryChanged(QQuickItem *item, const QRectF &newGeometry, const QRectF &oldGeometry);
- virtual void fixupPosition();
- virtual void fixup(AxisData &data, qreal minExtent, qreal maxExtent);
- virtual bool flick(QQuickItemViewPrivate::AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize,
- QQuickTimeLineCallback::Callback fixupCallback, qreal velocity);
+ void itemGeometryChanged(QQuickItem *item, const QRectF &newGeometry, const QRectF &oldGeometry) Q_DECL_OVERRIDE;
+ void fixupPosition() Q_DECL_OVERRIDE;
+ void fixup(AxisData &data, qreal minExtent, qreal maxExtent) Q_DECL_OVERRIDE;
+ bool flick(QQuickItemViewPrivate::AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize,
+ QQuickTimeLineCallback::Callback fixupCallback, qreal velocity) Q_DECL_OVERRIDE;
QQuickListView::Orientation orient;
qreal visiblePos;
@@ -319,7 +319,7 @@ public:
else
item->setWidth(size);
}
- bool contains(qreal x, qreal y) const {
+ bool contains(qreal x, qreal y) const Q_DECL_OVERRIDE {
return (x >= itemX() && x < itemX() + item->width() &&
y >= itemY() && y < itemY() + item->height());
}
@@ -1603,10 +1603,10 @@ bool QQuickListViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExte
}
data.flickTarget = isContentFlowReversed() ? -data.flickTarget+size() : data.flickTarget;
if (overShoot) {
- if (data.flickTarget >= minExtent) {
+ if (data.flickTarget > minExtent) {
overshootDist = overShootDistance(vSize);
data.flickTarget += overshootDist;
- } else if (data.flickTarget <= maxExtent) {
+ } else if (data.flickTarget < maxExtent) {
overshootDist = overShootDistance(vSize);
data.flickTarget -= overshootDist;
}
@@ -1626,10 +1626,10 @@ bool QQuickListViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExte
accel = v2 / (2.0f * qAbs(dist));
} else if (overShoot) {
data.flickTarget = data.move.value() - dist;
- if (data.flickTarget >= minExtent) {
+ if (data.flickTarget > minExtent) {
overshootDist = overShootDistance(vSize);
data.flickTarget += overshootDist;
- } else if (data.flickTarget <= maxExtent) {
+ } else if (data.flickTarget < maxExtent) {
overshootDist = overShootDistance(vSize);
data.flickTarget -= overshootDist;
}
diff --git a/src/quick/items/qquicklistview_p.h b/src/quick/items/qquicklistview_p.h
index a02fba258e..2801879b0f 100644
--- a/src/quick/items/qquicklistview_p.h
+++ b/src/quick/items/qquicklistview_p.h
@@ -126,7 +126,7 @@ public:
QQuickViewSection *sectionCriteria();
QString currentSection() const;
- virtual void setHighlightFollowsCurrentItem(bool);
+ void setHighlightFollowsCurrentItem(bool) Q_DECL_OVERRIDE;
qreal highlightMoveVelocity() const;
void setHighlightMoveVelocity(qreal);
@@ -137,7 +137,7 @@ public:
int highlightResizeDuration() const;
void setHighlightResizeDuration(int);
- virtual void setHighlightMoveDuration(int);
+ void setHighlightMoveDuration(int) Q_DECL_OVERRIDE;
enum SnapMode { NoSnap, SnapToItem, SnapOneItem };
SnapMode snapMode() const;
@@ -169,10 +169,10 @@ Q_SIGNALS:
Q_REVISION(2) void footerPositioningChanged();
protected:
- virtual void viewportMoved(Qt::Orientations orient);
- virtual void keyPressEvent(QKeyEvent *);
- virtual void geometryChanged(const QRectF &newGeometry,const QRectF &oldGeometry);
- virtual void initItem(int index, QObject *item);
+ void viewportMoved(Qt::Orientations orient) Q_DECL_OVERRIDE;
+ void keyPressEvent(QKeyEvent *) Q_DECL_OVERRIDE;
+ void geometryChanged(const QRectF &newGeometry,const QRectF &oldGeometry) Q_DECL_OVERRIDE;
+ void initItem(int index, QObject *item) Q_DECL_OVERRIDE;
};
class QQuickListViewAttached : public QQuickItemViewAttached
diff --git a/src/quick/items/qquickloader.cpp b/src/quick/items/qquickloader.cpp
index 906126b433..4123f25b7e 100644
--- a/src/quick/items/qquickloader.cpp
+++ b/src/quick/items/qquickloader.cpp
@@ -466,7 +466,7 @@ void QQuickLoader::setSourceComponent(QQmlComponent *comp)
d->component = comp;
if (comp) {
if (QQmlData *ddata = QQmlData::get(comp))
- d->componentStrongReference = ddata->jsWrapper.value();
+ d->componentStrongReference = ddata->jsWrapper;
}
d->loadingFromSource = false;
@@ -574,8 +574,8 @@ void QQuickLoader::setSource(QQmlV4Function *args)
QUrl sourceUrl = d->resolveSourceUrl(args);
if (!ipv->isUndefined()) {
d->disposeInitialPropertyValues();
- d->initialPropertyValues = ipv.asReturnedValue();
- d->qmlGlobalForIpv = args->qmlGlobal();
+ d->initialPropertyValues.set(args->v4engine(), ipv);
+ d->qmlGlobalForIpv.set(args->v4engine(), args->qmlGlobal());
}
setSource(sourceUrl, false); // already cleared and set ipv above.
diff --git a/src/quick/items/qquickloader_p.h b/src/quick/items/qquickloader_p.h
index 3e0cba5865..640897d507 100644
--- a/src/quick/items/qquickloader_p.h
+++ b/src/quick/items/qquickloader_p.h
@@ -88,8 +88,8 @@ Q_SIGNALS:
void asynchronousChanged();
protected:
- void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry);
- void componentComplete();
+ void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) Q_DECL_OVERRIDE;
+ void componentComplete() Q_DECL_OVERRIDE;
private:
void setSource(const QUrl &sourceUrl, bool needsClear);
diff --git a/src/quick/items/qquickloader_p_p.h b/src/quick/items/qquickloader_p_p.h
index cae42a79ad..15e144855c 100644
--- a/src/quick/items/qquickloader_p_p.h
+++ b/src/quick/items/qquickloader_p_p.h
@@ -62,8 +62,8 @@ public:
QQuickLoaderIncubator(QQuickLoaderPrivate *l, IncubationMode mode) : QQmlIncubator(mode), loader(l) {}
protected:
- virtual void statusChanged(Status);
- virtual void setInitialState(QObject *);
+ void statusChanged(Status) Q_DECL_OVERRIDE;
+ void setInitialState(QObject *) Q_DECL_OVERRIDE;
private:
QQuickLoaderPrivate *loader;
@@ -78,9 +78,9 @@ public:
QQuickLoaderPrivate();
~QQuickLoaderPrivate();
- void itemGeometryChanged(QQuickItem *item, const QRectF &newGeometry, const QRectF &oldGeometry);
- void itemImplicitWidthChanged(QQuickItem *);
- void itemImplicitHeightChanged(QQuickItem *);
+ void itemGeometryChanged(QQuickItem *item, const QRectF &newGeometry, const QRectF &oldGeometry) Q_DECL_OVERRIDE;
+ void itemImplicitWidthChanged(QQuickItem *) Q_DECL_OVERRIDE;
+ void itemImplicitHeightChanged(QQuickItem *) Q_DECL_OVERRIDE;
void clear();
void initResize();
void load();
@@ -91,8 +91,8 @@ public:
QUrl resolveSourceUrl(QQmlV4Function *args);
QV4::ReturnedValue extractInitialPropertyValues(QQmlV4Function *args, QObject *loader, bool *error);
- virtual qreal getImplicitWidth() const;
- virtual qreal getImplicitHeight() const;
+ qreal getImplicitWidth() const Q_DECL_OVERRIDE;
+ qreal getImplicitHeight() const Q_DECL_OVERRIDE;
QUrl source;
QQuickItem *item;
diff --git a/src/quick/items/qquickmultipointtoucharea_p.h b/src/quick/items/qquickmultipointtoucharea_p.h
index 6d3e607d08..a1569548c9 100644
--- a/src/quick/items/qquickmultipointtoucharea_p.h
+++ b/src/quick/items/qquickmultipointtoucharea_p.h
@@ -228,13 +228,13 @@ Q_SIGNALS:
void mouseEnabledChanged();
protected:
- void touchEvent(QTouchEvent *);
- bool childMouseEventFilter(QQuickItem *i, QEvent *event);
- void mousePressEvent(QMouseEvent *event);
- void mouseReleaseEvent(QMouseEvent *event);
- void mouseMoveEvent(QMouseEvent *event);
- void mouseUngrabEvent();
- void touchUngrabEvent();
+ void touchEvent(QTouchEvent *) Q_DECL_OVERRIDE;
+ bool childMouseEventFilter(QQuickItem *i, QEvent *event) Q_DECL_OVERRIDE;
+ void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
+ void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
+ void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
+ void mouseUngrabEvent() Q_DECL_OVERRIDE;
+ void touchUngrabEvent() Q_DECL_OVERRIDE;
void addTouchPrototype(QQuickTouchPoint* prototype);
void addTouchPoint(const QTouchEvent::TouchPoint *p);
@@ -248,10 +248,10 @@ protected:
bool sendMouseEvent(QMouseEvent *event);
bool shouldFilter(QEvent *event);
void grabGesture();
- virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
+ QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *) Q_DECL_OVERRIDE;
#ifdef Q_OS_OSX
- void hoverEnterEvent(QHoverEvent *event);
- void hoverLeaveEvent(QHoverEvent *event);
+ void hoverEnterEvent(QHoverEvent *event) Q_DECL_OVERRIDE;
+ void hoverLeaveEvent(QHoverEvent *event) Q_DECL_OVERRIDE;
void setTouchEventsEnabled(bool enable);
#endif
diff --git a/src/quick/items/qquickpainteditem.h b/src/quick/items/qquickpainteditem.h
index b5e04694bf..fc14574a8d 100644
--- a/src/quick/items/qquickpainteditem.h
+++ b/src/quick/items/qquickpainteditem.h
@@ -107,7 +107,7 @@ Q_SIGNALS:
protected:
QQuickPaintedItem(QQuickPaintedItemPrivate &dd, QQuickItem *parent = 0);
- virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
+ QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *) Q_DECL_OVERRIDE;
void releaseResources() Q_DECL_OVERRIDE;
private Q_SLOTS:
diff --git a/src/quick/items/qquickpathview_p.h b/src/quick/items/qquickpathview_p.h
index 74ee4908b2..e57557204e 100644
--- a/src/quick/items/qquickpathview_p.h
+++ b/src/quick/items/qquickpathview_p.h
@@ -193,14 +193,14 @@ Q_SIGNALS:
void cacheItemCountChanged();
protected:
- virtual void updatePolish();
- void mousePressEvent(QMouseEvent *event);
- void mouseMoveEvent(QMouseEvent *event);
- void mouseReleaseEvent(QMouseEvent *);
+ void updatePolish() Q_DECL_OVERRIDE;
+ void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
+ void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
+ void mouseReleaseEvent(QMouseEvent *) Q_DECL_OVERRIDE;
bool sendMouseEvent(QMouseEvent *event);
- bool childMouseEventFilter(QQuickItem *, QEvent *);
- void mouseUngrabEvent();
- void componentComplete();
+ bool childMouseEventFilter(QQuickItem *, QEvent *) Q_DECL_OVERRIDE;
+ void mouseUngrabEvent() Q_DECL_OVERRIDE;
+ void componentComplete() Q_DECL_OVERRIDE;
private Q_SLOTS:
void refill();
diff --git a/src/quick/items/qquickpathview_p_p.h b/src/quick/items/qquickpathview_p_p.h
index cd52dd10bb..7c0e651b69 100644
--- a/src/quick/items/qquickpathview_p_p.h
+++ b/src/quick/items/qquickpathview_p_p.h
@@ -69,7 +69,7 @@ public:
void init();
- void itemGeometryChanged(QQuickItem *item, const QRectF &newGeometry, const QRectF &oldGeometry) {
+ void itemGeometryChanged(QQuickItem *item, const QRectF &newGeometry, const QRectF &oldGeometry) Q_DECL_OVERRIDE {
if ((newGeometry.size() != oldGeometry.size())
&& (!highlightItem || item != highlightItem)) {
if (QQuickPathViewAttached *att = attached(item))
diff --git a/src/quick/items/qquickpincharea_p.h b/src/quick/items/qquickpincharea_p.h
index b82db035e5..28db59fb55 100644
--- a/src/quick/items/qquickpincharea_p.h
+++ b/src/quick/items/qquickpincharea_p.h
@@ -268,15 +268,15 @@ Q_SIGNALS:
void pinchFinished(QQuickPinchEvent *pinch);
protected:
- virtual bool childMouseEventFilter(QQuickItem *i, QEvent *e);
- virtual void touchEvent(QTouchEvent *event);
+ bool childMouseEventFilter(QQuickItem *i, QEvent *e) Q_DECL_OVERRIDE;
+ void touchEvent(QTouchEvent *event) Q_DECL_OVERRIDE;
- virtual void geometryChanged(const QRectF &newGeometry,
- const QRectF &oldGeometry);
- virtual void itemChange(ItemChange change, const ItemChangeData& value);
+ void geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry) Q_DECL_OVERRIDE;
+ void itemChange(ItemChange change, const ItemChangeData& value) Q_DECL_OVERRIDE;
#ifdef Q_OS_OSX
- void hoverEnterEvent(QHoverEvent *event);
- void hoverLeaveEvent(QHoverEvent *event);
+ void hoverEnterEvent(QHoverEvent *event) Q_DECL_OVERRIDE;
+ void hoverLeaveEvent(QHoverEvent *event) Q_DECL_OVERRIDE;
void setTouchEventsEnabled(bool enable);
#endif
diff --git a/src/quick/items/qquickpositioners_p.h b/src/quick/items/qquickpositioners_p.h
index 7df4ee3b9a..164ea86c71 100644
--- a/src/quick/items/qquickpositioners_p.h
+++ b/src/quick/items/qquickpositioners_p.h
@@ -110,10 +110,10 @@ public:
protected:
QQuickBasePositioner(QQuickBasePositionerPrivate &dd, PositionerType at, QQuickItem *parent);
- virtual void componentComplete();
- virtual void itemChange(ItemChange, const ItemChangeData &);
+ void componentComplete() Q_DECL_OVERRIDE;
+ void itemChange(ItemChange, const ItemChangeData &) Q_DECL_OVERRIDE;
- virtual void updatePolish();
+ void updatePolish() Q_DECL_OVERRIDE;
Q_SIGNALS:
void spacingChanged();
@@ -173,8 +173,8 @@ public:
QQuickColumn(QQuickItem *parent=0);
protected:
- virtual void doPositioning(QSizeF *contentSize);
- virtual void reportConflictingAnchors();
+ void doPositioning(QSizeF *contentSize) Q_DECL_OVERRIDE;
+ void reportConflictingAnchors() Q_DECL_OVERRIDE;
private:
Q_DISABLE_COPY(QQuickColumn)
};
@@ -197,8 +197,8 @@ Q_SIGNALS:
void effectiveLayoutDirectionChanged();
protected:
- virtual void doPositioning(QSizeF *contentSize);
- virtual void reportConflictingAnchors();
+ void doPositioning(QSizeF *contentSize) Q_DECL_OVERRIDE;
+ void reportConflictingAnchors() Q_DECL_OVERRIDE;
private:
Q_DISABLE_COPY(QQuickRow)
Q_DECLARE_PRIVATE(QQuickRow)
@@ -274,8 +274,8 @@ Q_SIGNALS:
Q_REVISION(1) void verticalAlignmentChanged(VAlignment alignment);
protected:
- virtual void doPositioning(QSizeF *contentSize);
- virtual void reportConflictingAnchors();
+ void doPositioning(QSizeF *contentSize) Q_DECL_OVERRIDE;
+ void reportConflictingAnchors() Q_DECL_OVERRIDE;
private:
int m_rows;
@@ -316,8 +316,8 @@ Q_SIGNALS:
void effectiveLayoutDirectionChanged();
protected:
- virtual void doPositioning(QSizeF *contentSize);
- virtual void reportConflictingAnchors();
+ void doPositioning(QSizeF *contentSize) Q_DECL_OVERRIDE;
+ void reportConflictingAnchors() Q_DECL_OVERRIDE;
protected:
QQuickFlow(QQuickFlowPrivate &dd, QQuickItem *parent);
private:
diff --git a/src/quick/items/qquickpositioners_p_p.h b/src/quick/items/qquickpositioners_p_p.h
index e77997d4e9..cdcb09cf49 100644
--- a/src/quick/items/qquickpositioners_p_p.h
+++ b/src/quick/items/qquickpositioners_p_p.h
@@ -98,7 +98,7 @@ public:
Qt::LayoutDirection layoutDirection;
- void mirrorChange() {
+ void mirrorChange() Q_DECL_OVERRIDE {
effectiveLayoutDirectionChange();
}
bool isLeftToRight() const {
@@ -108,24 +108,24 @@ public:
return effectiveLayoutMirror ? layoutDirection == Qt::RightToLeft : layoutDirection == Qt::LeftToRight;
}
- virtual void itemSiblingOrderChanged(QQuickItem* other)
+ void itemSiblingOrderChanged(QQuickItem* other) Q_DECL_OVERRIDE
{
Q_UNUSED(other);
setPositioningDirty();
}
- void itemGeometryChanged(QQuickItem *, const QRectF &newGeometry, const QRectF &oldGeometry)
+ void itemGeometryChanged(QQuickItem *, const QRectF &newGeometry, const QRectF &oldGeometry) Q_DECL_OVERRIDE
{
if (newGeometry.size() != oldGeometry.size())
setPositioningDirty();
}
- virtual void itemVisibilityChanged(QQuickItem *)
+ void itemVisibilityChanged(QQuickItem *) Q_DECL_OVERRIDE
{
setPositioningDirty();
}
- void itemDestroyed(QQuickItem *item)
+ void itemDestroyed(QQuickItem *item) Q_DECL_OVERRIDE
{
Q_Q(QQuickBasePositioner);
int index = q->positionedItems.find(QQuickBasePositioner::PositionedItem(item));
diff --git a/src/quick/items/qquickrectangle_p.h b/src/quick/items/qquickrectangle_p.h
index 2e9eabd1d5..18922630f8 100644
--- a/src/quick/items/qquickrectangle_p.h
+++ b/src/quick/items/qquickrectangle_p.h
@@ -153,7 +153,7 @@ Q_SIGNALS:
void radiusChanged();
protected:
- virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
+ QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *) Q_DECL_OVERRIDE;
private Q_SLOTS:
void doUpdate();
diff --git a/src/quick/items/qquickrendercontrol.cpp b/src/quick/items/qquickrendercontrol.cpp
index a666bb59c9..656678a035 100644
--- a/src/quick/items/qquickrendercontrol.cpp
+++ b/src/quick/items/qquickrendercontrol.cpp
@@ -36,7 +36,7 @@
#include <QtCore/QCoreApplication>
#include <QtCore/QTime>
-#include <QtCore/private/qabstractanimation_p.h>
+#include <QtQuick/private/qquickanimatorcontroller_p.h>
#include <QtGui/QOpenGLContext>
#include <QtGui/private/qguiapplication_p.h>
@@ -170,6 +170,20 @@ void QQuickRenderControlPrivate::windowDestroyed()
}
/*!
+ Prepares rendering the Qt Quick scene outside the gui thread.
+
+ \a targetThread specifies the thread on which synchronization and
+ rendering will happen. There is no need to call this function in a
+ single threaded scenario.
+ */
+void QQuickRenderControl::prepareThread(QThread *targetThread)
+{
+ Q_D(QQuickRenderControl);
+ d->rc->moveToThread(targetThread);
+ QQuickWindowPrivate::get(d->window)->animationController->moveToThread(targetThread);
+}
+
+/*!
Initializes the scene graph resources. The context \a gl has to
be the current context.
diff --git a/src/quick/items/qquickrendercontrol.h b/src/quick/items/qquickrendercontrol.h
index e6903653c2..99d1b8ac2d 100644
--- a/src/quick/items/qquickrendercontrol.h
+++ b/src/quick/items/qquickrendercontrol.h
@@ -42,6 +42,7 @@ QT_BEGIN_NAMESPACE
class QQuickWindow;
class QOpenGLContext;
class QQuickRenderControlPrivate;
+class QThread;
class Q_QUICK_EXPORT QQuickRenderControl : public QObject
{
@@ -51,6 +52,7 @@ public:
QQuickRenderControl(QObject *parent = 0);
~QQuickRenderControl();
+ void prepareThread(QThread *targetThread);
void initialize(QOpenGLContext *gl);
void invalidate();
diff --git a/src/quick/items/qquickrepeater.cpp b/src/quick/items/qquickrepeater.cpp
index e2a3043857..975682192e 100644
--- a/src/quick/items/qquickrepeater.cpp
+++ b/src/quick/items/qquickrepeater.cpp
@@ -350,7 +350,9 @@ void QQuickRepeater::clear()
bool complete = isComponentComplete();
if (d->model) {
- for (int i = 0; i < d->deletables.count(); ++i) {
+ // We remove in reverse order deliberately; so that signals are emitted
+ // with sensible indices.
+ for (int i = d->deletables.count() - 1; i >= 0; --i) {
if (QQuickItem *item = d->deletables.at(i)) {
if (complete)
emit itemRemoved(i, item);
diff --git a/src/quick/items/qquickrepeater_p.h b/src/quick/items/qquickrepeater_p.h
index 159520a89d..d1ca686e78 100644
--- a/src/quick/items/qquickrepeater_p.h
+++ b/src/quick/items/qquickrepeater_p.h
@@ -77,8 +77,8 @@ private:
void regenerate();
protected:
- virtual void componentComplete();
- void itemChange(ItemChange change, const ItemChangeData &value);
+ void componentComplete() Q_DECL_OVERRIDE;
+ void itemChange(ItemChange change, const ItemChangeData &value) Q_DECL_OVERRIDE;
private Q_SLOTS:
void createdItem(int index, QObject *item);
diff --git a/src/quick/items/qquickscreen.cpp b/src/quick/items/qquickscreen.cpp
index 8ac5a1e292..2e104673af 100644
--- a/src/quick/items/qquickscreen.cpp
+++ b/src/quick/items/qquickscreen.cpp
@@ -37,6 +37,7 @@
#include "qquickitem_p.h"
#include "qquickwindow.h"
+#include <QGuiApplication>
#include <QScreen>
QT_BEGIN_NAMESPACE
@@ -218,6 +219,9 @@ QQuickScreenAttached::QQuickScreenAttached(QObject* attachee)
if (window)
windowChanged(window);
}
+
+ if (!m_screen)
+ screenChanged(QGuiApplication::primaryScreen());
}
QString QQuickScreenAttached::name() const
diff --git a/src/quick/items/qquickshadereffect.cpp b/src/quick/items/qquickshadereffect.cpp
index 0358495a3b..c64f6ab1c2 100644
--- a/src/quick/items/qquickshadereffect.cpp
+++ b/src/quick/items/qquickshadereffect.cpp
@@ -854,12 +854,17 @@ void QQuickShaderEffect::setCullMode(CullMode face)
/*!
\qmlproperty bool QtQuick::ShaderEffect::supportsAtlasTextures
- Set this property true to indicate that the ShaderEffect is able to
- use the default source texture without first removing it from an atlas.
- In this case the range of qt_MultiTexCoord0 will based on the position of
- the texture within the atlas, rather than (0,0) to (1,1).
-
- Setting this to true may enable some optimizations.
+ Set this property true to confirm that your shader code doesn't rely on
+ qt_MultiTexCoord0 ranging from (0,0) to (1,1) relative to the mesh.
+ In this case the range of qt_MultiTexCoord0 will rather be based on the position
+ of the texture within the atlas. This property currently has no effect if there
+ is less, or more, than one sampler uniform used as input to your shader.
+
+ This differs from providing qt_SubRect_<name> uniforms in that the latter allows
+ drawing one or more textures from the atlas in a single ShaderEffect item, while
+ supportsAtlasTextures allows multiple instances of a ShaderEffect component using
+ a different source image from the atlas to be batched in a single draw.
+ Both prevent a texture from being copied out of the atlas when referenced by a ShaderEffect.
The default value is false.
@@ -1029,24 +1034,23 @@ QSGNode *QQuickShaderEffect::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDa
m_dirtyUniforms = m_dirtyUniformValues = m_dirtyTextureProviders = false;
}
- int textureCount = material->textureProviders.size();
- bool preventBatching = m_customVertexShader || textureCount > 1 || (textureCount > 0 && !m_supportsAtlasTextures);
-
QRectF srcRect(0, 0, 1, 1);
- if (m_supportsAtlasTextures && textureCount != 0) {
- if (QSGTextureProvider *provider = material->textureProviders.at(0)) {
- if (provider->texture())
- srcRect = provider->texture()->normalizedTextureSubRect();
+ bool geometryUsesTextureSubRect = false;
+ if (m_supportsAtlasTextures && material->textureProviders.size() == 1) {
+ QSGTextureProvider *provider = material->textureProviders.at(0);
+ if (provider->texture()) {
+ srcRect = provider->texture()->normalizedTextureSubRect();
+ geometryUsesTextureSubRect = true;
}
}
- if (bool(material->flags() & QSGMaterial::RequiresFullMatrix) != preventBatching) {
- material->setFlag(QSGMaterial::RequiresFullMatrix, preventBatching);
+ if (bool(material->flags() & QSGMaterial::RequiresFullMatrix) != m_customVertexShader) {
+ material->setFlag(QSGMaterial::RequiresFullMatrix, m_customVertexShader);
node->markDirty(QSGNode::DirtyMaterial);
}
- if (material->supportsAtlasTextures != m_supportsAtlasTextures) {
- material->supportsAtlasTextures = m_supportsAtlasTextures;
+ if (material->geometryUsesTextureSubRect != geometryUsesTextureSubRect) {
+ material->geometryUsesTextureSubRect = geometryUsesTextureSubRect;
node->markDirty(QSGNode::DirtyMaterial);
}
diff --git a/src/quick/items/qquickshadereffect_p.h b/src/quick/items/qquickshadereffect_p.h
index 99e88a653d..8c5da9e5d5 100644
--- a/src/quick/items/qquickshadereffect_p.h
+++ b/src/quick/items/qquickshadereffect_p.h
@@ -136,7 +136,7 @@ public:
QString parseLog();
- virtual bool event(QEvent *);
+ bool event(QEvent *) Q_DECL_OVERRIDE;
Q_SIGNALS:
void fragmentShaderChanged();
@@ -149,10 +149,10 @@ Q_SIGNALS:
void supportsAtlasTexturesChanged();
protected:
- virtual void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry);
- virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
- virtual void componentComplete();
- virtual void itemChange(ItemChange change, const ItemChangeData &value);
+ void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) Q_DECL_OVERRIDE;
+ QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *) Q_DECL_OVERRIDE;
+ void componentComplete() Q_DECL_OVERRIDE;
+ void itemChange(ItemChange change, const ItemChangeData &value) Q_DECL_OVERRIDE;
private Q_SLOTS:
void updateGeometry();
diff --git a/src/quick/items/qquickshadereffectmesh.cpp b/src/quick/items/qquickshadereffectmesh.cpp
index 1eab3b4148..4100594711 100644
--- a/src/quick/items/qquickshadereffectmesh.cpp
+++ b/src/quick/items/qquickshadereffectmesh.cpp
@@ -59,7 +59,6 @@ QQuickGridMesh::QQuickGridMesh(QObject *parent)
: QQuickShaderEffectMesh(parent)
, m_resolution(1, 1)
{
- connect(this, SIGNAL(resolutionChanged()), this, SIGNAL(geometryChanged()));
}
QSGGeometry *QQuickGridMesh::updateGeometry(QSGGeometry *geometry, const QVector<QByteArray> &attributes, const QRectF &srcRect, const QRectF &dstRect)
@@ -204,6 +203,7 @@ void QQuickGridMesh::setResolution(const QSize &res)
}
m_resolution = res;
emit resolutionChanged();
+ emit geometryChanged();
}
QSize QQuickGridMesh::resolution() const
diff --git a/src/quick/items/qquickshadereffectmesh_p.h b/src/quick/items/qquickshadereffectmesh_p.h
index 5bcf633fa3..684f8461d8 100644
--- a/src/quick/items/qquickshadereffectmesh_p.h
+++ b/src/quick/items/qquickshadereffectmesh_p.h
@@ -69,8 +69,8 @@ class QQuickGridMesh : public QQuickShaderEffectMesh
Q_PROPERTY(QSize resolution READ resolution WRITE setResolution NOTIFY resolutionChanged)
public:
QQuickGridMesh(QObject *parent = 0);
- virtual QSGGeometry *updateGeometry(QSGGeometry *geometry, const QVector<QByteArray> &attributes, const QRectF &srcRect, const QRectF &rect);
- virtual QString log() const { return m_log; }
+ QSGGeometry *updateGeometry(QSGGeometry *geometry, const QVector<QByteArray> &attributes, const QRectF &srcRect, const QRectF &rect) Q_DECL_OVERRIDE;
+ QString log() const Q_DECL_OVERRIDE { return m_log; }
void setResolution(const QSize &res);
QSize resolution() const;
diff --git a/src/quick/items/qquickshadereffectnode.cpp b/src/quick/items/qquickshadereffectnode.cpp
index 43220a0e29..7877e1c1d4 100644
--- a/src/quick/items/qquickshadereffectnode.cpp
+++ b/src/quick/items/qquickshadereffectnode.cpp
@@ -41,20 +41,30 @@
QT_BEGIN_NAMESPACE
+static bool hasAtlasTexture(const QVector<QSGTextureProvider *> &textureProviders)
+{
+ for (int i = 0; i < textureProviders.size(); ++i) {
+ QSGTextureProvider *t = textureProviders.at(i);
+ if (t->texture() && t->texture()->isAtlasTexture())
+ return true;
+ }
+ return false;
+}
+
class QQuickCustomMaterialShader : public QSGMaterialShader
{
public:
QQuickCustomMaterialShader(const QQuickShaderEffectMaterialKey &key, const QVector<QByteArray> &attributes);
- virtual void deactivate();
- virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect);
- virtual char const *const *attributeNames() const;
+ void deactivate() Q_DECL_OVERRIDE;
+ void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) Q_DECL_OVERRIDE;
+ char const *const *attributeNames() const Q_DECL_OVERRIDE;
protected:
friend class QQuickShaderEffectNode;
- virtual void compile();
- virtual const char *vertexShader() const;
- virtual const char *fragmentShader() const;
+ void compile() Q_DECL_OVERRIDE;
+ const char *vertexShader() const Q_DECL_OVERRIDE;
+ const char *fragmentShader() const Q_DECL_OVERRIDE;
const QQuickShaderEffectMaterialKey m_key;
QVector<QByteArray> m_attributes;
@@ -137,7 +147,7 @@ void QQuickCustomMaterialShader::updateState(const RenderState &state, QSGMateri
if (loc >= 0) {
QRectF r = texture->normalizedTextureSubRect();
program()->setUniformValue(loc, r.x(), r.y(), r.width(), r.height());
- } else if (texture->isAtlasTexture() && (idx != 0 || !material->supportsAtlasTextures)) {
+ } else if (texture->isAtlasTexture() && !material->geometryUsesTextureSubRect) {
texture = texture->removedFromAtlas();
}
texture->bind();
@@ -342,7 +352,7 @@ QHash<QQuickShaderEffectMaterialKey, QSharedPointer<QSGMaterialType> > QQuickSha
QQuickShaderEffectMaterial::QQuickShaderEffectMaterial(QQuickShaderEffectNode *node)
: cullMode(NoCulling)
- , supportsAtlasTextures(false)
+ , geometryUsesTextureSubRect(false)
, m_node(node)
, m_emittedLogChanged(false)
{
@@ -380,14 +390,10 @@ bool QQuickShaderEffectMaterial::UniformData::operator == (const UniformData &ot
int QQuickShaderEffectMaterial::compare(const QSGMaterial *o) const
{
const QQuickShaderEffectMaterial *other = static_cast<const QQuickShaderEffectMaterial *>(o);
- if (!supportsAtlasTextures || !other->supportsAtlasTextures)
- return 1;
- if (bool(flags() & QSGMaterial::RequiresFullMatrix) || bool(other->flags() & QSGMaterial::RequiresFullMatrix))
+ if ((hasAtlasTexture(textureProviders) && !geometryUsesTextureSubRect) || (hasAtlasTexture(other->textureProviders) && !other->geometryUsesTextureSubRect))
return 1;
if (cullMode != other->cullMode)
return 1;
- if (m_source != other->m_source)
- return 1;
for (int shaderType = 0; shaderType < QQuickShaderEffectMaterialKey::ShaderTypeCount; ++shaderType) {
if (uniforms[shaderType] != other->uniforms[shaderType])
return 1;
diff --git a/src/quick/items/qquickshadereffectnode_p.h b/src/quick/items/qquickshadereffectnode_p.h
index fc7c643aea..f9f705630c 100644
--- a/src/quick/items/qquickshadereffectnode_p.h
+++ b/src/quick/items/qquickshadereffectnode_p.h
@@ -87,15 +87,15 @@ public:
};
explicit QQuickShaderEffectMaterial(QQuickShaderEffectNode *node = 0);
- virtual QSGMaterialType *type() const;
- virtual QSGMaterialShader *createShader() const;
- virtual int compare(const QSGMaterial *other) const;
+ QSGMaterialType *type() const Q_DECL_OVERRIDE;
+ QSGMaterialShader *createShader() const Q_DECL_OVERRIDE;
+ int compare(const QSGMaterial *other) const Q_DECL_OVERRIDE;
QVector<QByteArray> attributes;
QVector<UniformData> uniforms[QQuickShaderEffectMaterialKey::ShaderTypeCount];
QVector<QSGTextureProvider *> textureProviders;
CullMode cullMode;
- bool supportsAtlasTextures;
+ bool geometryUsesTextureSubRect;
void setProgramSource(const QQuickShaderEffectMaterialKey &source);
void updateTextures() const;
@@ -129,7 +129,7 @@ public:
QQuickShaderEffectNode();
virtual ~QQuickShaderEffectNode();
- virtual void preprocess();
+ void preprocess() Q_DECL_OVERRIDE;
Q_SIGNALS:
void logAndStatusChanged(const QString &, int status);
diff --git a/src/quick/items/qquickshadereffectsource_p.h b/src/quick/items/qquickshadereffectsource_p.h
index 69e65f927f..7add0b1033 100644
--- a/src/quick/items/qquickshadereffectsource_p.h
+++ b/src/quick/items/qquickshadereffectsource_p.h
@@ -112,8 +112,8 @@ public:
bool recursive() const;
void setRecursive(bool enabled);
- bool isTextureProvider() const { return true; }
- QSGTextureProvider *textureProvider() const;
+ bool isTextureProvider() const Q_DECL_OVERRIDE { return true; }
+ QSGTextureProvider *textureProvider() const Q_DECL_OVERRIDE;
Q_INVOKABLE void scheduleUpdate();
@@ -135,11 +135,11 @@ private Q_SLOTS:
void invalidateSceneGraph();
protected:
- virtual void releaseResources();
- virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
+ void releaseResources() Q_DECL_OVERRIDE;
+ QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *) Q_DECL_OVERRIDE;
- virtual void itemGeometryChanged(QQuickItem *item, const QRectF &newRect, const QRectF &oldRect);
- virtual void itemChange(ItemChange change, const ItemChangeData &value);
+ void itemGeometryChanged(QQuickItem *item, const QRectF &newRect, const QRectF &oldRect) Q_DECL_OVERRIDE;
+ void itemChange(ItemChange change, const ItemChangeData &value) Q_DECL_OVERRIDE;
private:
void ensureTexture();
diff --git a/src/quick/items/qquicksprite_p.h b/src/quick/items/qquicksprite_p.h
index 1bd625001d..a38a284201 100644
--- a/src/quick/items/qquicksprite_p.h
+++ b/src/quick/items/qquicksprite_p.h
@@ -138,7 +138,7 @@ public:
return m_frameDurationVariation;
}
- int variedDuration() const;
+ int variedDuration() const Q_DECL_OVERRIDE;
bool frameSync() const
{
diff --git a/src/quick/items/qquickspriteengine.cpp b/src/quick/items/qquickspriteengine.cpp
index c5e70c9a8b..12020e879b 100644
--- a/src/quick/items/qquickspriteengine.cpp
+++ b/src/quick/items/qquickspriteengine.cpp
@@ -201,10 +201,12 @@ int QQuickSpriteEngine::spriteFrames(int sprite)
extra = (m_sprites[state]->m_generatedCount - 1) - extra;
- if (extra == m_sprites[state]->m_generatedCount - 1)//last state
- return m_sprites[state]->frames() % m_sprites[state]->m_framesPerRow;
- else
- return m_sprites[state]->m_framesPerRow;
+ if (extra == m_sprites[state]->m_generatedCount - 1) {//last state
+ const int framesRemaining = m_sprites[state]->frames() % m_sprites[state]->m_framesPerRow;
+ if (framesRemaining > 0)
+ return framesRemaining;
+ }
+ return m_sprites[state]->m_framesPerRow;
}
int QQuickSpriteEngine::spriteDuration(int sprite)//Full duration, not per frame
@@ -219,10 +221,12 @@ int QQuickSpriteEngine::spriteDuration(int sprite)//Full duration, not per frame
if (m_sprites[state]->reverse())
extra = (m_sprites[state]->m_generatedCount - 1) - extra;
- if (extra == m_sprites[state]->m_generatedCount - 1)//last state
- return m_duration[sprite] % rowDuration;
- else
- return rowDuration;
+ if (extra == m_sprites[state]->m_generatedCount - 1) {//last state
+ const int durationRemaining = m_duration[sprite] % rowDuration;
+ if (durationRemaining > 0)
+ return durationRemaining;
+ }
+ return rowDuration;
}
int QQuickSpriteEngine::spriteY(int sprite)
@@ -512,7 +516,9 @@ void QQuickStochasticEngine::start(int index, int state)
else
m_startTimes[index] = 0;
m_goals[index] = -1;
+ m_addAdvance = false;
restart(index);
+ m_addAdvance = true;
}
void QQuickStochasticEngine::stop(int index)
diff --git a/src/quick/items/qquickspriteengine_p.h b/src/quick/items/qquickspriteengine_p.h
index 1705ab3ee3..227041f181 100644
--- a/src/quick/items/qquickspriteengine_p.h
+++ b/src/quick/items/qquickspriteengine_p.h
@@ -268,8 +268,8 @@ public:
int spriteCount();//Like state count
int maxFrames();
- virtual void restart(int index=0);
- virtual void advance(int index=0);
+ void restart(int index=0) Q_DECL_OVERRIDE;
+ void advance(int index=0) Q_DECL_OVERRIDE;
//Similar API to QQuickPixmap for async loading convenience
bool isNull() { return status() == QQuickPixmap::Null; }
diff --git a/src/quick/items/qquickspritesequence.cpp b/src/quick/items/qquickspritesequence.cpp
index a9a823c2ce..0bef823b3c 100644
--- a/src/quick/items/qquickspritesequence.cpp
+++ b/src/quick/items/qquickspritesequence.cpp
@@ -53,9 +53,9 @@ class QQuickSpriteSequenceMaterial : public QSGMaterial
public:
QQuickSpriteSequenceMaterial();
~QQuickSpriteSequenceMaterial();
- virtual QSGMaterialType *type() const { static QSGMaterialType type; return &type; }
- virtual QSGMaterialShader *createShader() const;
- virtual int compare(const QSGMaterial *other) const
+ QSGMaterialType *type() const Q_DECL_OVERRIDE{ static QSGMaterialType type; return &type; }
+ QSGMaterialShader *createShader() const Q_DECL_OVERRIDE;
+ int compare(const QSGMaterial *other) const Q_DECL_OVERRIDE
{
return this - static_cast<const QQuickSpriteSequenceMaterial *>(other);
}
@@ -99,7 +99,7 @@ public:
setShaderSourceFile(QOpenGLShader::Fragment, QStringLiteral(":/items/shaders/sprite.frag"));
}
- virtual void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *)
+ void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *) Q_DECL_OVERRIDE
{
QQuickSpriteSequenceMaterial *m = static_cast<QQuickSpriteSequenceMaterial *>(newEffect);
m->texture->bind();
@@ -112,14 +112,14 @@ public:
program()->setUniformValue(m_matrix_id, state.combinedMatrix());
}
- virtual void initialize() {
+ void initialize() Q_DECL_OVERRIDE {
m_matrix_id = program()->uniformLocation("qt_Matrix");
m_opacity_id = program()->uniformLocation("qt_Opacity");
m_animData_id = program()->uniformLocation("animData");
m_animPos_id = program()->uniformLocation("animPos");
}
- virtual char const *const *attributeNames() const {
+ char const *const *attributeNames() const Q_DECL_OVERRIDE {
static const char *attr[] = {
"vPos",
"vTex",
diff --git a/src/quick/items/qquickspritesequence_p.h b/src/quick/items/qquickspritesequence_p.h
index a32f5ead4f..3c22d8772c 100644
--- a/src/quick/items/qquickspritesequence_p.h
+++ b/src/quick/items/qquickspritesequence_p.h
@@ -114,7 +114,7 @@ private Q_SLOTS:
protected:
void reset();
- QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
+ QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *) Q_DECL_OVERRIDE;
private:
void prepareNextFrame();
QSGGeometryNode* buildNode();
diff --git a/src/quick/items/qquickstateoperations_p.h b/src/quick/items/qquickstateoperations_p.h
index 79facf2445..a9e4be1e20 100644
--- a/src/quick/items/qquickstateoperations_p.h
+++ b/src/quick/items/qquickstateoperations_p.h
@@ -93,17 +93,17 @@ public:
void setRotation(QQmlScriptString rotation);
bool rotationIsSet() const;
- virtual ActionList actions();
+ ActionList actions() Q_DECL_OVERRIDE;
- virtual void saveOriginals();
+ void saveOriginals() Q_DECL_OVERRIDE;
//virtual void copyOriginals(QQuickStateActionEvent*);
- virtual void execute(Reason reason = ActualChange);
- virtual bool isReversable();
- virtual void reverse(Reason reason = ActualChange);
- virtual EventType type() const;
- virtual bool override(QQuickStateActionEvent*other);
- virtual void rewind();
- virtual void saveCurrentValues();
+ void execute(Reason reason = ActualChange) Q_DECL_OVERRIDE;
+ bool isReversable() Q_DECL_OVERRIDE;
+ void reverse(Reason reason = ActualChange) Q_DECL_OVERRIDE;
+ EventType type() const Q_DECL_OVERRIDE;
+ bool override(QQuickStateActionEvent*other) Q_DECL_OVERRIDE;
+ void rewind() Q_DECL_OVERRIDE;
+ void saveCurrentValues() Q_DECL_OVERRIDE;
};
class QQuickAnchorChanges;
@@ -173,28 +173,28 @@ public:
QQuickAnchorChanges(QObject *parent=0);
~QQuickAnchorChanges();
- virtual ActionList actions();
+ ActionList actions() Q_DECL_OVERRIDE;
QQuickAnchorSet *anchors();
QQuickItem *object() const;
void setObject(QQuickItem *);
- virtual void execute(Reason reason = ActualChange);
- virtual bool isReversable();
- virtual void reverse(Reason reason = ActualChange);
- virtual EventType type() const;
- virtual bool override(QQuickStateActionEvent*other);
- virtual bool changesBindings();
- virtual void saveOriginals();
- virtual bool needsCopy() { return true; }
- virtual void copyOriginals(QQuickStateActionEvent*);
- virtual void clearBindings();
- virtual void rewind();
- virtual void saveCurrentValues();
+ void execute(Reason reason = ActualChange) Q_DECL_OVERRIDE;
+ bool isReversable() Q_DECL_OVERRIDE;
+ void reverse(Reason reason = ActualChange) Q_DECL_OVERRIDE;
+ EventType type() const Q_DECL_OVERRIDE;
+ bool override(QQuickStateActionEvent*other) Q_DECL_OVERRIDE;
+ bool changesBindings() Q_DECL_OVERRIDE;
+ void saveOriginals() Q_DECL_OVERRIDE;
+ bool needsCopy() Q_DECL_OVERRIDE { return true; }
+ void copyOriginals(QQuickStateActionEvent*) Q_DECL_OVERRIDE;
+ void clearBindings() Q_DECL_OVERRIDE;
+ void rewind() Q_DECL_OVERRIDE;
+ void saveCurrentValues() Q_DECL_OVERRIDE;
QList<QQuickStateAction> additionalActions();
- virtual void saveTargetValues();
+ void saveTargetValues() Q_DECL_OVERRIDE;
};
QT_END_NAMESPACE
diff --git a/src/quick/items/qquicktext_p.h b/src/quick/items/qquicktext_p.h
index c3fa9e6935..18f2a73470 100644
--- a/src/quick/items/qquicktext_p.h
+++ b/src/quick/items/qquicktext_p.h
@@ -186,15 +186,15 @@ public:
FontSizeMode fontSizeMode() const;
void setFontSizeMode(FontSizeMode mode);
- virtual void componentComplete();
+ void componentComplete() Q_DECL_OVERRIDE;
int resourcesLoading() const; // mainly for testing
qreal contentWidth() const;
qreal contentHeight() const;
- QRectF boundingRect() const;
- QRectF clipRect() const;
+ QRectF boundingRect() const Q_DECL_OVERRIDE;
+ QRectF clipRect() const Q_DECL_OVERRIDE;
Q_INVOKABLE void doLayout();
RenderType renderType() const;
@@ -233,18 +233,18 @@ Q_SIGNALS:
void renderTypeChanged();
protected:
- void mousePressEvent(QMouseEvent *event);
- void mouseReleaseEvent(QMouseEvent *event);
- virtual void itemChange(ItemChange change, const ItemChangeData &value);
- virtual void geometryChanged(const QRectF &newGeometry,
- const QRectF &oldGeometry);
- virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
-
- void updatePolish();
-
- void hoverEnterEvent(QHoverEvent *event);
- void hoverMoveEvent(QHoverEvent *event);
- void hoverLeaveEvent(QHoverEvent *event);
+ void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
+ void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
+ void itemChange(ItemChange change, const ItemChangeData &value) Q_DECL_OVERRIDE;
+ void geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry) Q_DECL_OVERRIDE;
+ QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *) Q_DECL_OVERRIDE;
+
+ void updatePolish() Q_DECL_OVERRIDE;
+
+ void hoverEnterEvent(QHoverEvent *event) Q_DECL_OVERRIDE;
+ void hoverMoveEvent(QHoverEvent *event) Q_DECL_OVERRIDE;
+ void hoverLeaveEvent(QHoverEvent *event) Q_DECL_OVERRIDE;
void invalidateFontCaches();
private Q_SLOTS:
diff --git a/src/quick/items/qquicktext_p_p.h b/src/quick/items/qquicktext_p_p.h
index 35cdb68104..0acd77aab8 100644
--- a/src/quick/items/qquicktext_p_p.h
+++ b/src/quick/items/qquicktext_p_p.h
@@ -72,7 +72,7 @@ public:
void updateLayout();
bool determineHorizontalAlignment();
bool setHAlign(QQuickText::HAlignment, bool forceAlign = false);
- void mirrorChange();
+ void mirrorChange() Q_DECL_OVERRIDE;
bool isLineLaidOutConnected();
void setLineGeometry(QTextLine &line, qreal lineWidth, qreal &height);
@@ -156,8 +156,8 @@ public:
static const QChar elideChar;
- virtual qreal getImplicitWidth() const;
- virtual qreal getImplicitHeight() const;
+ qreal getImplicitWidth() const Q_DECL_OVERRIDE;
+ qreal getImplicitHeight() const Q_DECL_OVERRIDE;
void ensureDoc();
diff --git a/src/quick/items/qquicktextcontrol_p.h b/src/quick/items/qquicktextcontrol_p.h
index d0af4a1cc9..2fe083f1d2 100644
--- a/src/quick/items/qquicktextcontrol_p.h
+++ b/src/quick/items/qquicktextcontrol_p.h
@@ -162,9 +162,9 @@ public:
bool cursorOn() const;
protected:
- virtual void timerEvent(QTimerEvent *e);
+ void timerEvent(QTimerEvent *e) Q_DECL_OVERRIDE;
- virtual bool event(QEvent *e);
+ bool event(QEvent *e) Q_DECL_OVERRIDE;
private:
Q_DISABLE_COPY(QQuickTextControl)
diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp
index 99e64b55f9..3446f65c19 100644
--- a/src/quick/items/qquicktextedit.cpp
+++ b/src/quick/items/qquicktextedit.cpp
@@ -1232,15 +1232,21 @@ void QQuickTextEdit::setTextMargin(qreal margin)
\endlist
*/
-#ifndef QT_NO_IM
Qt::InputMethodHints QQuickTextEdit::inputMethodHints() const
{
+#ifdef QT_NO_IM
+ return Qt::ImhNone;
+#else
Q_D(const QQuickTextEdit);
return d->inputMethodHints;
+#endif // QT_NO_IM
}
void QQuickTextEdit::setInputMethodHints(Qt::InputMethodHints hints)
{
+#ifdef QT_NO_IM
+ Q_UNUSED(hints);
+#else
Q_D(QQuickTextEdit);
if (hints == d->inputMethodHints)
@@ -1249,8 +1255,8 @@ void QQuickTextEdit::setInputMethodHints(Qt::InputMethodHints hints)
d->inputMethodHints = hints;
updateInputMethod(Qt::ImHints);
emit inputMethodHintsChanged();
-}
#endif // QT_NO_IM
+}
void QQuickTextEdit::geometryChanged(const QRectF &newGeometry,
const QRectF &oldGeometry)
@@ -1983,7 +1989,6 @@ bool QQuickTextEdit::canRedo() const
return d->document->isRedoAvailable();
}
-#ifndef QT_NO_IM
/*!
\qmlproperty bool QtQuick::TextEdit::inputMethodComposing
@@ -1998,10 +2003,13 @@ bool QQuickTextEdit::canRedo() const
*/
bool QQuickTextEdit::isInputMethodComposing() const
{
+#ifdef QT_NO_IM
+ return false;
+#else
Q_D(const QQuickTextEdit);
return d->control->hasImState();
-}
#endif // QT_NO_IM
+}
void QQuickTextEditPrivate::init()
{
diff --git a/src/quick/items/qquicktextedit_p.h b/src/quick/items/qquicktextedit_p.h
index da88fd4917..5320ecc2ca 100644
--- a/src/quick/items/qquicktextedit_p.h
+++ b/src/quick/items/qquicktextedit_p.h
@@ -81,18 +81,14 @@ class Q_QUICK_PRIVATE_EXPORT QQuickTextEdit : public QQuickImplicitSizeItem
Q_PROPERTY(bool activeFocusOnPress READ focusOnPress WRITE setFocusOnPress NOTIFY activeFocusOnPressChanged)
Q_PROPERTY(bool persistentSelection READ persistentSelection WRITE setPersistentSelection NOTIFY persistentSelectionChanged)
Q_PROPERTY(qreal textMargin READ textMargin WRITE setTextMargin NOTIFY textMarginChanged)
-#ifndef QT_NO_IM
Q_PROPERTY(Qt::InputMethodHints inputMethodHints READ inputMethodHints WRITE setInputMethodHints NOTIFY inputMethodHintsChanged)
-#endif
Q_PROPERTY(bool selectByKeyboard READ selectByKeyboard WRITE setSelectByKeyboard NOTIFY selectByKeyboardChanged REVISION 1)
Q_PROPERTY(bool selectByMouse READ selectByMouse WRITE setSelectByMouse NOTIFY selectByMouseChanged)
Q_PROPERTY(SelectionMode mouseSelectionMode READ mouseSelectionMode WRITE setMouseSelectionMode NOTIFY mouseSelectionModeChanged)
Q_PROPERTY(bool canPaste READ canPaste NOTIFY canPasteChanged)
Q_PROPERTY(bool canUndo READ canUndo NOTIFY canUndoChanged)
Q_PROPERTY(bool canRedo READ canRedo NOTIFY canRedoChanged)
-#ifndef QT_NO_IM
Q_PROPERTY(bool inputMethodComposing READ isInputMethodComposing NOTIFY inputMethodComposingChanged)
-#endif
Q_PROPERTY(QUrl baseUrl READ baseUrl WRITE setBaseUrl RESET resetBaseUrl NOTIFY baseUrlChanged)
Q_PROPERTY(RenderType renderType READ renderType WRITE setRenderType NOTIFY renderTypeChanged)
Q_PROPERTY(QQuickTextDocument *textDocument READ textDocument FINAL REVISION 1)
@@ -192,10 +188,8 @@ public:
qreal textMargin() const;
void setTextMargin(qreal margin);
-#ifndef QT_NO_IM
Qt::InputMethodHints inputMethodHints() const;
void setInputMethodHints(Qt::InputMethodHints hints);
-#endif
bool selectByKeyboard() const;
void setSelectByKeyboard(bool);
@@ -211,7 +205,7 @@ public:
bool canUndo() const;
bool canRedo() const;
- virtual void componentComplete();
+ void componentComplete() Q_DECL_OVERRIDE;
/* FROM EDIT */
void setReadOnly(bool);
@@ -220,7 +214,7 @@ public:
QRectF cursorRectangle() const;
#ifndef QT_NO_IM
- QVariant inputMethodQuery(Qt::InputMethodQuery property) const;
+ QVariant inputMethodQuery(Qt::InputMethodQuery property) const Q_DECL_OVERRIDE;
Q_REVISION(4) Q_INVOKABLE QVariant inputMethodQuery(Qt::InputMethodQuery query, QVariant argument) const;
#endif
@@ -236,12 +230,10 @@ public:
Q_INVOKABLE void moveCursorSelection(int pos);
Q_INVOKABLE void moveCursorSelection(int pos, SelectionMode mode);
- QRectF boundingRect() const;
- QRectF clipRect() const;
+ QRectF boundingRect() const Q_DECL_OVERRIDE;
+ QRectF clipRect() const Q_DECL_OVERRIDE;
-#ifndef QT_NO_IM
bool isInputMethodComposing() const;
-#endif
RenderType renderType() const;
void setRenderType(RenderType renderType);
@@ -286,14 +278,10 @@ Q_SIGNALS:
void canPasteChanged();
void canUndoChanged();
void canRedoChanged();
-#ifndef QT_NO_IM
void inputMethodComposingChanged();
-#endif
void effectiveHorizontalAlignmentChanged();
void baseUrlChanged();
-#ifndef QT_NO_IM
void inputMethodHintsChanged();
-#endif
void renderTypeChanged();
public Q_SLOTS:
@@ -333,28 +321,28 @@ private:
void invalidateFontCaches();
protected:
- virtual void geometryChanged(const QRectF &newGeometry,
- const QRectF &oldGeometry);
+ void geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry) Q_DECL_OVERRIDE;
- bool event(QEvent *);
- void keyPressEvent(QKeyEvent *);
- void keyReleaseEvent(QKeyEvent *);
- void focusInEvent(QFocusEvent *event);
- void focusOutEvent(QFocusEvent *event);
+ bool event(QEvent *) Q_DECL_OVERRIDE;
+ void keyPressEvent(QKeyEvent *) Q_DECL_OVERRIDE;
+ void keyReleaseEvent(QKeyEvent *) Q_DECL_OVERRIDE;
+ void focusInEvent(QFocusEvent *event) Q_DECL_OVERRIDE;
+ void focusOutEvent(QFocusEvent *event) Q_DECL_OVERRIDE;
- void hoverEnterEvent(QHoverEvent *event);
- void hoverMoveEvent(QHoverEvent *event);
- void hoverLeaveEvent(QHoverEvent *event);
+ void hoverEnterEvent(QHoverEvent *event) Q_DECL_OVERRIDE;
+ void hoverMoveEvent(QHoverEvent *event) Q_DECL_OVERRIDE;
+ void hoverLeaveEvent(QHoverEvent *event) Q_DECL_OVERRIDE;
// mouse filter?
- void mousePressEvent(QMouseEvent *event);
- void mouseReleaseEvent(QMouseEvent *event);
- void mouseDoubleClickEvent(QMouseEvent *event);
- void mouseMoveEvent(QMouseEvent *event);
+ void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
+ void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
+ void mouseDoubleClickEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
+ void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
#ifndef QT_NO_IM
- void inputMethodEvent(QInputMethodEvent *e);
+ void inputMethodEvent(QInputMethodEvent *e) Q_DECL_OVERRIDE;
#endif
- QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *updatePaintNodeData);
+ QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *updatePaintNodeData) Q_DECL_OVERRIDE;
void updatePolish();
friend class QQuickTextUtil;
diff --git a/src/quick/items/qquicktextedit_p_p.h b/src/quick/items/qquicktextedit_p_p.h
index ae00303dd1..5233413cd7 100644
--- a/src/quick/items/qquicktextedit_p_p.h
+++ b/src/quick/items/qquicktextedit_p_p.h
@@ -117,8 +117,8 @@ public:
void relayoutDocument();
bool determineHorizontalAlignment();
bool setHAlign(QQuickTextEdit::HAlignment, bool forceAlign = false);
- void mirrorChange();
- qreal getImplicitWidth() const;
+ void mirrorChange() Q_DECL_OVERRIDE;
+ qreal getImplicitWidth() const Q_DECL_OVERRIDE;
Qt::LayoutDirection textDirection(const QString &text) const;
bool isLinkHoveredConnected();
diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp
index a9c60273d2..288464e0b4 100644
--- a/src/quick/items/qquicktextinput.cpp
+++ b/src/quick/items/qquicktextinput.cpp
@@ -1027,6 +1027,8 @@ void QQuickDoubleValidator::resetLocaleName()
}
}
+#endif // QT_NO_VALIDATOR
+
/*!
\qmlproperty real QtQuick::DoubleValidator::top
@@ -1105,12 +1107,19 @@ void QQuickDoubleValidator::resetLocaleName()
QValidator* QQuickTextInput::validator() const
{
+#ifdef QT_NO_VALIDATOR
+ return 0;
+#else
Q_D(const QQuickTextInput);
return d->m_validator;
+#endif // QT_NO_VALIDATOR
}
void QQuickTextInput::setValidator(QValidator* v)
{
+#ifdef QT_NO_VALIDATOR
+ Q_UNUSED(v);
+#else
Q_D(QQuickTextInput);
if (d->m_validator == v)
return;
@@ -1133,14 +1142,15 @@ void QQuickTextInput::setValidator(QValidator* v)
d->checkIsValid();
emit validatorChanged();
+#endif // QT_NO_VALIDATOR
}
+#ifndef QT_NO_VALIDATOR
void QQuickTextInput::q_validatorChanged()
{
Q_D(QQuickTextInput);
d->checkIsValid();
}
-
#endif // QT_NO_VALIDATOR
void QQuickTextInputPrivate::checkIsValid()
@@ -1273,7 +1283,6 @@ void QQuickTextInput::setEchoMode(QQuickTextInput::EchoMode echo)
emit echoModeChanged(echoMode());
}
-#ifndef QT_NO_IM
/*!
\qmlproperty enumeration QtQuick::TextInput::inputMethodHints
@@ -1322,12 +1331,19 @@ void QQuickTextInput::setEchoMode(QQuickTextInput::EchoMode echo)
Qt::InputMethodHints QQuickTextInput::inputMethodHints() const
{
+#ifdef QT_NO_IM
+ return Qt::ImhNone;
+#else
Q_D(const QQuickTextInput);
return d->inputMethodHints;
+#endif // QT_NO_IM
}
void QQuickTextInput::setInputMethodHints(Qt::InputMethodHints hints)
{
+#ifdef QT_NO_IM
+ Q_UNUSED(hints);
+#else
Q_D(QQuickTextInput);
if (hints == d->inputMethodHints)
@@ -1336,8 +1352,8 @@ void QQuickTextInput::setInputMethodHints(Qt::InputMethodHints hints)
d->inputMethodHints = hints;
updateInputMethod(Qt::ImHints);
emit inputMethodHintsChanged();
-}
#endif // QT_NO_IM
+}
/*!
\qmlproperty Component QtQuick::TextInput::cursorDelegate
@@ -2612,7 +2628,6 @@ void QQuickTextInput::focusOutEvent(QFocusEvent *event)
QQuickImplicitSizeItem::focusOutEvent(event);
}
-#ifndef QT_NO_IM
/*!
\qmlproperty bool QtQuick::TextInput::inputMethodComposing
@@ -2627,10 +2642,13 @@ void QQuickTextInput::focusOutEvent(QFocusEvent *event)
*/
bool QQuickTextInput::isInputMethodComposing() const
{
+#ifdef QT_NO_IM
+ return false;
+#else
Q_D(const QQuickTextInput);
return d->hasImState;
-}
#endif
+}
void QQuickTextInputPrivate::init()
{
diff --git a/src/quick/items/qquicktextinput_p.h b/src/quick/items/qquicktextinput_p.h
index 34b0c81495..3cd5b7ad18 100644
--- a/src/quick/items/qquicktextinput_p.h
+++ b/src/quick/items/qquicktextinput_p.h
@@ -74,13 +74,9 @@ class Q_QUICK_PRIVATE_EXPORT QQuickTextInput : public QQuickImplicitSizeItem
Q_PROPERTY(QString selectedText READ selectedText NOTIFY selectedTextChanged)
Q_PROPERTY(int maximumLength READ maxLength WRITE setMaxLength NOTIFY maximumLengthChanged)
-#ifndef QT_NO_VALIDATOR
Q_PROPERTY(QValidator* validator READ validator WRITE setValidator NOTIFY validatorChanged)
-#endif
Q_PROPERTY(QString inputMask READ inputMask WRITE setInputMask NOTIFY inputMaskChanged)
-#ifndef QT_NO_IM
Q_PROPERTY(Qt::InputMethodHints inputMethodHints READ inputMethodHints WRITE setInputMethodHints NOTIFY inputMethodHintsChanged)
-#endif
Q_PROPERTY(bool acceptableInput READ hasAcceptableInput NOTIFY acceptableInputChanged)
Q_PROPERTY(EchoMode echoMode READ echoMode WRITE setEchoMode NOTIFY echoModeChanged)
@@ -95,9 +91,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickTextInput : public QQuickImplicitSizeItem
Q_PROPERTY(bool canPaste READ canPaste NOTIFY canPasteChanged)
Q_PROPERTY(bool canUndo READ canUndo NOTIFY canUndoChanged)
Q_PROPERTY(bool canRedo READ canRedo NOTIFY canRedoChanged)
-#ifndef QT_NO_IM
Q_PROPERTY(bool inputMethodComposing READ isInputMethodComposing NOTIFY inputMethodComposingChanged)
-#endif
Q_PROPERTY(qreal contentWidth READ contentWidth NOTIFY contentSizeChanged)
Q_PROPERTY(qreal contentHeight READ contentHeight NOTIFY contentSizeChanged)
Q_PROPERTY(RenderType renderType READ renderType WRITE setRenderType NOTIFY renderTypeChanged)
@@ -106,7 +100,7 @@ public:
QQuickTextInput(QQuickItem * parent=0);
~QQuickTextInput();
- void componentComplete();
+ void componentComplete() Q_DECL_OVERRIDE;
enum EchoMode {//To match QLineEdit::EchoMode
Normal,
@@ -205,10 +199,9 @@ public:
int maxLength() const;
void setMaxLength(int ml);
-#ifndef QT_NO_VALIDATOR
QValidator * validator() const;
void setValidator(QValidator* v);
-#endif
+
QString inputMask() const;
void setInputMask(const QString &im);
@@ -245,24 +238,22 @@ public:
bool hasAcceptableInput() const;
#ifndef QT_NO_IM
- QVariant inputMethodQuery(Qt::InputMethodQuery property) const;
+ QVariant inputMethodQuery(Qt::InputMethodQuery property) const Q_DECL_OVERRIDE;
Q_REVISION(3) Q_INVOKABLE QVariant inputMethodQuery(Qt::InputMethodQuery query, QVariant argument) const;
#endif
- QRectF boundingRect() const;
- QRectF clipRect() const;
+ QRectF boundingRect() const Q_DECL_OVERRIDE;
+ QRectF clipRect() const Q_DECL_OVERRIDE;
bool canPaste() const;
bool canUndo() const;
bool canRedo() const;
-#ifndef QT_NO_IM
bool isInputMethodComposing() const;
Qt::InputMethodHints inputMethodHints() const;
void setInputMethodHints(Qt::InputMethodHints hints);
-#endif
Q_INVOKABLE QString getText(int start, int end) const;
@@ -304,37 +295,33 @@ Q_SIGNALS:
void canPasteChanged();
void canUndoChanged();
void canRedoChanged();
-#ifndef QT_NO_IM
void inputMethodComposingChanged();
-#endif
void effectiveHorizontalAlignmentChanged();
void contentSizeChanged();
-#ifndef QT_NO_IM
void inputMethodHintsChanged();
-#endif
void renderTypeChanged();
private:
void invalidateFontCaches();
protected:
- virtual void geometryChanged(const QRectF &newGeometry,
- const QRectF &oldGeometry);
-
- void mousePressEvent(QMouseEvent *event);
- void mouseMoveEvent(QMouseEvent *event);
- void mouseReleaseEvent(QMouseEvent *event);
- void mouseDoubleClickEvent(QMouseEvent *event);
- void keyPressEvent(QKeyEvent* ev);
+ void geometryChanged(const QRectF &newGeometry,
+ const QRectF &oldGeometry) Q_DECL_OVERRIDE;
+
+ void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
+ void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
+ void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
+ void mouseDoubleClickEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
+ void keyPressEvent(QKeyEvent* ev) Q_DECL_OVERRIDE;
#ifndef QT_NO_IM
- void inputMethodEvent(QInputMethodEvent *);
+ void inputMethodEvent(QInputMethodEvent *) Q_DECL_OVERRIDE;
#endif
- void mouseUngrabEvent();
- bool event(QEvent *e);
- void focusOutEvent(QFocusEvent *event);
- void focusInEvent(QFocusEvent *event);
- void timerEvent(QTimerEvent *event);
- QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data);
+ void mouseUngrabEvent() Q_DECL_OVERRIDE;
+ bool event(QEvent *e) Q_DECL_OVERRIDE;
+ void focusOutEvent(QFocusEvent *event) Q_DECL_OVERRIDE;
+ void focusInEvent(QFocusEvent *event) Q_DECL_OVERRIDE;
+ void timerEvent(QTimerEvent *event) Q_DECL_OVERRIDE;
+ QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data) Q_DECL_OVERRIDE;
void updatePolish();
public Q_SLOTS:
diff --git a/src/quick/items/qquicktextinput_p_p.h b/src/quick/items/qquicktextinput_p_p.h
index 7d9f3ff9ce..9339bf9a30 100644
--- a/src/quick/items/qquicktextinput_p_p.h
+++ b/src/quick/items/qquicktextinput_p_p.h
@@ -145,7 +145,7 @@ public:
void updateVerticalScroll();
bool determineHorizontalAlignment();
bool setHAlign(QQuickTextInput::HAlignment, bool forceAlign = false);
- void mirrorChange();
+ void mirrorChange() Q_DECL_OVERRIDE;
bool sendMouseEventToInputContext(QMouseEvent *event);
#ifndef QT_NO_IM
Qt::InputMethodHints effectiveInputMethodHints() const;
@@ -418,7 +418,7 @@ public:
void updateLayout();
void updateBaselineOffset();
- qreal getImplicitWidth() const;
+ qreal getImplicitWidth() const Q_DECL_OVERRIDE;
private:
void removeSelectedText();
diff --git a/src/quick/items/qquicktextnodeengine.cpp b/src/quick/items/qquicktextnodeengine.cpp
index 67ff79d20f..707b32755b 100644
--- a/src/quick/items/qquicktextnodeengine.cpp
+++ b/src/quick/items/qquicktextnodeengine.cpp
@@ -980,7 +980,18 @@ void QQuickTextNodeEngine::addTextBlock(QTextDocument *textDocument, const QText
continue;
QTextCharFormat charFormat = fragment.charFormat();
- setPosition(blockPosition);
+ QFont font(charFormat.font());
+ QFontMetricsF fontMetrics(font);
+
+ int fontHeight = fontMetrics.descent() + fontMetrics.ascent();
+ int valign = charFormat.verticalAlignment();
+ if (valign == QTextCharFormat::AlignSuperScript)
+ setPosition(QPointF(blockPosition.x(), blockPosition.y() - fontHeight / 2));
+ else if (valign == QTextCharFormat::AlignSubScript)
+ setPosition(QPointF(blockPosition.x(), blockPosition.y() + fontHeight / 6));
+ else
+ setPosition(blockPosition);
+
if (text.contains(QChar::ObjectReplacementCharacter)) {
QTextFrame *frame = qobject_cast<QTextFrame *>(textDocument->objectForFormat(charFormat));
if (frame && frame->frameFormat().position() == QTextFrameFormat::InFlow) {
diff --git a/src/quick/items/qquicktranslate_p.h b/src/quick/items/qquicktranslate_p.h
index ca49349f74..f95e13ac35 100644
--- a/src/quick/items/qquicktranslate_p.h
+++ b/src/quick/items/qquicktranslate_p.h
@@ -58,7 +58,7 @@ public:
qreal y() const;
void setY(qreal);
- void applyTo(QMatrix4x4 *matrix) const;
+ void applyTo(QMatrix4x4 *matrix) const Q_DECL_OVERRIDE;
Q_SIGNALS:
void xChanged();
@@ -94,7 +94,7 @@ public:
qreal zScale() const;
void setZScale(qreal);
- void applyTo(QMatrix4x4 *matrix) const;
+ void applyTo(QMatrix4x4 *matrix) const Q_DECL_OVERRIDE;
Q_SIGNALS:
void originChanged();
@@ -129,7 +129,7 @@ public:
void setAxis(const QVector3D &axis);
void setAxis(Qt::Axis axis);
- void applyTo(QMatrix4x4 *matrix) const;
+ void applyTo(QMatrix4x4 *matrix) const Q_DECL_OVERRIDE;
Q_SIGNALS:
void originChanged();
@@ -153,7 +153,7 @@ public:
QMatrix4x4 matrix() const;
void setMatrix(const QMatrix4x4& matrix);
- void applyTo(QMatrix4x4 *matrix) const;
+ void applyTo(QMatrix4x4 *matrix) const Q_DECL_OVERRIDE;
Q_SIGNALS:
void matrixChanged();
diff --git a/src/quick/items/qquickview.cpp b/src/quick/items/qquickview.cpp
index b5b542a791..245fa488c4 100644
--- a/src/quick/items/qquickview.cpp
+++ b/src/quick/items/qquickview.cpp
@@ -48,17 +48,17 @@
QT_BEGIN_NAMESPACE
-DEFINE_OBJECT_VTABLE(QQuickRootItemMarker);
+DEFINE_OBJECT_VTABLE(QV4::QQuickRootItemMarker);
-QQuickRootItemMarker *QQuickRootItemMarker::create(QQmlEngine *engine, QQuickWindow *window)
+QV4::Heap::QQuickRootItemMarker *QV4::QQuickRootItemMarker::create(QQmlEngine *engine, QQuickWindow *window)
{
QV4::ExecutionEngine *e = QQmlEnginePrivate::getV4Engine(engine);
return e->memoryManager->alloc<QQuickRootItemMarker>(e, window);
}
-void QQuickRootItemMarker::markObjects(QV4::Managed *that, QV4::ExecutionEngine *e)
+void QV4::QQuickRootItemMarker::markObjects(QV4::Heap::Base *that, QV4::ExecutionEngine *e)
{
- QQuickItem *root = static_cast<QQuickRootItemMarker*>(that)->d()->window->contentItem();
+ QQuickItem *root = static_cast<QQuickRootItemMarker::Data *>(that)->window->contentItem();
if (root) {
QQuickItemPrivate *rootPrivate = QQuickItemPrivate::get(root);
rootPrivate->markObjects(e);
@@ -82,8 +82,8 @@ void QQuickViewPrivate::init(QQmlEngine* e)
{
QV4::ExecutionEngine *v4 = QQmlEnginePrivate::getV4Engine(engine.data());
QV4::Scope scope(v4);
- QV4::Scoped<QQuickRootItemMarker> v(scope, QQuickRootItemMarker::create(engine.data(), q));
- rootItemMarker = v;
+ QV4::Scoped<QV4::QQuickRootItemMarker> v(scope, QV4::QQuickRootItemMarker::create(engine.data(), q));
+ rootItemMarker.set(v4, v);
}
if (QQmlDebugService::isDebuggingEnabled())
diff --git a/src/quick/items/qquickview.h b/src/quick/items/qquickview.h
index d8017782aa..337d987243 100644
--- a/src/quick/items/qquickview.h
+++ b/src/quick/items/qquickview.h
@@ -90,14 +90,14 @@ private Q_SLOTS:
void continueExecute();
protected:
- virtual void resizeEvent(QResizeEvent *);
- virtual void timerEvent(QTimerEvent*);
-
- virtual void keyPressEvent(QKeyEvent *);
- virtual void keyReleaseEvent(QKeyEvent *);
- virtual void mousePressEvent(QMouseEvent *);
- virtual void mouseReleaseEvent(QMouseEvent *);
- virtual void mouseMoveEvent(QMouseEvent *);
+ void resizeEvent(QResizeEvent *) Q_DECL_OVERRIDE;
+ void timerEvent(QTimerEvent*) Q_DECL_OVERRIDE;
+
+ void keyPressEvent(QKeyEvent *) Q_DECL_OVERRIDE;
+ void keyReleaseEvent(QKeyEvent *) Q_DECL_OVERRIDE;
+ void mousePressEvent(QMouseEvent *) Q_DECL_OVERRIDE;
+ void mouseReleaseEvent(QMouseEvent *) Q_DECL_OVERRIDE;
+ void mouseMoveEvent(QMouseEvent *) Q_DECL_OVERRIDE;
private:
Q_DISABLE_COPY(QQuickView)
Q_DECLARE_PRIVATE(QQuickView)
diff --git a/src/quick/items/qquickview_p.h b/src/quick/items/qquickview_p.h
index 2d3323a59c..1017913469 100644
--- a/src/quick/items/qquickview_p.h
+++ b/src/quick/items/qquickview_p.h
@@ -71,7 +71,7 @@ public:
~QQuickViewPrivate();
void execute();
- void itemGeometryChanged(QQuickItem *item, const QRectF &newGeometry, const QRectF &oldGeometry);
+ void itemGeometryChanged(QQuickItem *item, const QRectF &newGeometry, const QRectF &oldGeometry) Q_DECL_OVERRIDE;
void initResize();
void updateSize();
void setRootObject(QObject *);
@@ -94,26 +94,37 @@ public:
QV4::PersistentValue rootItemMarker;
};
-struct QQuickRootItemMarker : public QV4::Object
-{
- struct Data : QV4::Object::Data {
- Data(QV4::ExecutionEngine *engine, QQuickWindow *window)
- : Object::Data(engine)
- , window(window)
- {
- setVTable(staticVTable());
- }
+namespace QV4 {
+namespace Heap {
- QQuickWindow *window;
- };
- V4_OBJECT(QV4::Object)
+struct QQuickRootItemMarker : Object {
+ inline QQuickRootItemMarker(QV4::ExecutionEngine *engine, QQuickWindow *window);
+
+ QQuickWindow *window;
+};
- static QQuickRootItemMarker *create(QQmlEngine *engine, QQuickWindow *window);
+}
+
+struct QQuickRootItemMarker : public Object
+{
+ V4_OBJECT2(QQuickRootItemMarker, Object)
- static void markObjects(Managed *that, QV4::ExecutionEngine *e);
+ static Heap::QQuickRootItemMarker *create(QQmlEngine *engine, QQuickWindow *window);
+
+ static void markObjects(QV4::Heap::Base *that, QV4::ExecutionEngine *e);
};
+inline
+Heap::QQuickRootItemMarker::QQuickRootItemMarker(QV4::ExecutionEngine *engine, QQuickWindow *window)
+ : Heap::Object(engine)
+ , window(window)
+{
+ setVTable(QV4::QQuickRootItemMarker::staticVTable());
+}
+
+}
+
QT_END_NAMESPACE
#endif // QQUICKVIEW_P_H
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index 359f68a114..2c8b24baf6 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -143,7 +143,7 @@ public slots:
void animationStopped() { incubate(); }
protected:
- virtual void incubatingObjectCountChanged(int count)
+ void incubatingObjectCountChanged(int count) Q_DECL_OVERRIDE
{
if (count && !m_renderLoop->interleaveIncubation())
incubateAgain();
@@ -364,19 +364,21 @@ void QQuickWindowPrivate::renderSceneGraph(const QSize &size)
animationController->advance();
emit q->beforeRendering();
runAndClearJobs(&beforeRenderingJobs);
- int fboId = 0;
- const qreal devicePixelRatio = q->effectiveDevicePixelRatio();
- renderer->setDeviceRect(QRect(QPoint(0, 0), size * devicePixelRatio));
- if (renderTargetId) {
- fboId = renderTargetId;
- renderer->setViewportRect(QRect(QPoint(0, 0), renderTargetSize));
- } else {
- renderer->setViewportRect(QRect(QPoint(0, 0), size * devicePixelRatio));
- }
- renderer->setProjectionMatrixToRect(QRect(QPoint(0, 0), size));
- renderer->setDevicePixelRatio(devicePixelRatio);
+ if (!customRenderStage || !customRenderStage->render()) {
+ int fboId = 0;
+ const qreal devicePixelRatio = q->effectiveDevicePixelRatio();
+ renderer->setDeviceRect(QRect(QPoint(0, 0), size * devicePixelRatio));
+ if (renderTargetId) {
+ fboId = renderTargetId;
+ renderer->setViewportRect(QRect(QPoint(0, 0), renderTargetSize));
+ } else {
+ renderer->setViewportRect(QRect(QPoint(0, 0), size * devicePixelRatio));
+ }
+ renderer->setProjectionMatrixToRect(QRect(QPoint(0, 0), size));
+ renderer->setDevicePixelRatio(devicePixelRatio);
- context->renderNextFrame(renderer, fboId);
+ context->renderNextFrame(renderer, fboId);
+ }
emit q->afterRendering();
runAndClearJobs(&afterRenderingJobs);
}
@@ -399,6 +401,7 @@ QQuickWindowPrivate::QQuickWindowPrivate()
, windowManager(0)
, renderControl(0)
, touchRecursionGuard(0)
+ , customRenderStage(0)
, clearColor(Qt::white)
, clearBeforeRendering(true)
, persistentGLContext(true)
@@ -418,6 +421,7 @@ QQuickWindowPrivate::QQuickWindowPrivate()
QQuickWindowPrivate::~QQuickWindowPrivate()
{
+ delete customRenderStage;
}
void QQuickWindowPrivate::init(QQuickWindow *c, QQuickRenderControl *control)
@@ -1385,6 +1389,11 @@ bool QQuickWindow::event(QEvent *e)
if (d->mouseGrabberItem)
d->mouseGrabberItem->ungrabMouse();
break;
+ case QEvent::UpdateRequest: {
+ if (d->windowManager)
+ d->windowManager->handleUpdateRequest(this);
+ break;
+ }
default:
break;
}
@@ -2023,11 +2032,14 @@ bool QQuickWindowPrivate::deliverMatchingPointsToItem(QQuickItem *item, QTouchEv
touchEvent.data()->setTarget(item);
bool touchEventAccepted = false;
+ qCDebug(DBG_TOUCH) << " - considering delivering " << touchEvent << " to " << item;
+
// First check whether the parent wants to be a filter,
// and if the parent accepts the event we are done.
if (sendFilteredTouchEvent(item->parentItem(), item, event, hasFiltered)) {
// If the touch was accepted (regardless by whom or in what form),
// update acceptedNewPoints
+ qCDebug(DBG_TOUCH) << " - can't. intercepted " << touchEvent.data() << " to " << item->parentItem() << " instead of " << item;
foreach (int id, matchingNewPoints)
acceptedNewPoints->insert(id);
return true;
@@ -2038,6 +2050,7 @@ bool QQuickWindowPrivate::deliverMatchingPointsToItem(QQuickItem *item, QTouchEv
itemForTouchPointId[id] = item;
// Deliver the touch event to the given item
+ qCDebug(DBG_TOUCH) << " - actually delivering " << touchEvent << " to " << item;
QCoreApplication::sendEvent(item, touchEvent.data());
touchEventAccepted = touchEvent->isAccepted();
@@ -2274,10 +2287,7 @@ QQuickItem *QQuickWindowPrivate::findCursorItem(QQuickItem *item, const QPointF
return 0;
}
- const int numCursorsInHierarchy = itemPrivate->extra.isAllocated() ? itemPrivate->extra.value().numItemsWithCursor : 0;
- const int numChildrenWithCursor = itemPrivate->hasCursor ? numCursorsInHierarchy-1 : numCursorsInHierarchy;
-
- if (numChildrenWithCursor > 0) {
+ if (itemPrivate->hasCursorInChild) {
QList<QQuickItem *> children = itemPrivate->paintOrderChildItems();
for (int ii = children.count() - 1; ii >= 0; --ii) {
QQuickItem *child = children.at(ii);
@@ -2310,6 +2320,7 @@ bool QQuickWindowPrivate::sendFilteredTouchEvent(QQuickItem *target, QQuickItem
QScopedPointer<QTouchEvent> targetEvent(touchEventForItemBounds(target, *event));
if (!targetEvent->touchPoints().isEmpty()) {
if (target->childMouseEventFilter(item, targetEvent.data())) {
+ qCDebug(DBG_TOUCH) << " - first chance intercepted on childMouseEventFilter by " << target;
QVector<int> touchIds;
for (int i = 0; i < targetEvent->touchPoints().size(); ++i)
touchIds.append(targetEvent->touchPoints().at(i).id());
@@ -2350,6 +2361,7 @@ bool QQuickWindowPrivate::sendFilteredTouchEvent(QQuickItem *target, QQuickItem
// targetEvent is already transformed wrt local position, velocity, etc.
QScopedPointer<QMouseEvent> mouseEvent(touchToMouseEvent(t, tp, event, item, false));
if (target->childMouseEventFilter(item, mouseEvent.data())) {
+ qCDebug(DBG_TOUCH) << " - second chance intercepted on childMouseEventFilter by " << target;
if (t != QEvent::MouseButtonRelease) {
itemForTouchPointId[tp.id()] = target;
touchMouseId = tp.id();
@@ -2562,7 +2574,9 @@ bool QQuickWindow::sendEvent(QQuickItem *item, QEvent *e)
case QEvent::TouchUpdate:
case QEvent::TouchEnd: {
QSet<QQuickItem*> hasFiltered;
- d->sendFilteredTouchEvent(item->parentItem(), item, static_cast<QTouchEvent *>(e), &hasFiltered);
+ QTouchEvent *ev = static_cast<QTouchEvent *>(e);
+ qCDebug(DBG_TOUCH) << " - sendEvent for " << ev << " to " << item->parentItem() << " and " << item;
+ d->sendFilteredTouchEvent(item->parentItem(), item, ev, &hasFiltered);
}
break;
default:
@@ -2592,7 +2606,6 @@ void QQuickWindowPrivate::cleanupNodesOnShutdown(QQuickItem *item)
p->extra->rootNode = 0;
}
- p->groupNode = 0;
p->paintNode = 0;
p->dirty(QQuickItemPrivate::Window);
@@ -2647,6 +2660,53 @@ void QQuickWindowPrivate::updateDirtyNodes()
}
}
+static inline QSGNode *qquickitem_before_paintNode(QQuickItemPrivate *d)
+{
+ const QList<QQuickItem *> childItems = d->paintOrderChildItems();
+ QQuickItem *before = 0;
+ for (int i=0; i<childItems.size(); ++i) {
+ QQuickItemPrivate *dd = QQuickItemPrivate::get(childItems.at(i));
+ // Perform the same check as the in buildOrderNodeList below.
+ if (dd->z() < 0 && (dd->explicitVisible || (dd->extra.isAllocated() && dd->extra->effectRefCount)))
+ before = childItems.at(i);
+ else
+ break;
+ }
+ return Q_UNLIKELY(before) ? QQuickItemPrivate::get(before)->itemNode() : 0;
+}
+
+static QVector<QSGNode *> buildOrderedNodeList(QQuickItemPrivate *itemPriv)
+{
+ QList<QQuickItem *> orderedChildren = itemPriv->paintOrderChildItems();
+ QVector<QSGNode *> desiredNodes;
+ desiredNodes.reserve(orderedChildren.size() + 1); // + 1 for the paintNode
+
+ int ii = 0;
+
+ for (; ii < orderedChildren.count() && orderedChildren.at(ii)->z() < 0; ++ii) {
+ QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(orderedChildren.at(ii));
+ if (!childPrivate->explicitVisible &&
+ (!childPrivate->extra.isAllocated() || !childPrivate->extra->effectRefCount))
+ continue;
+
+ desiredNodes.append(childPrivate->itemNode());
+ }
+
+ if (itemPriv->paintNode)
+ desiredNodes.append(itemPriv->paintNode);
+
+ for (; ii < orderedChildren.count(); ++ii) {
+ QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(orderedChildren.at(ii));
+ if (!childPrivate->explicitVisible &&
+ (!childPrivate->extra.isAllocated() || !childPrivate->extra->effectRefCount))
+ continue;
+
+ desiredNodes.append(childPrivate->itemNode());
+ }
+
+ return desiredNodes;
+}
+
void QQuickWindowPrivate::updateDirtyNode(QQuickItem *item)
{
QQuickItemPrivate *itemPriv = QQuickItemPrivate::get(item);
@@ -2686,101 +2746,139 @@ void QQuickWindowPrivate::updateDirtyNode(QQuickItem *item)
if (clipEffectivelyChanged) {
QSGNode *parent = itemPriv->opacityNode() ? (QSGNode *) itemPriv->opacityNode() :
- (QSGNode *)itemPriv->itemNode();
- QSGNode *child = itemPriv->rootNode() ? (QSGNode *)itemPriv->rootNode() :
- (QSGNode *)itemPriv->groupNode;
+ (QSGNode *) itemPriv->itemNode();
+ QSGNode *child = itemPriv->rootNode();
if (item->clip()) {
Q_ASSERT(itemPriv->clipNode() == 0);
- itemPriv->extra.value().clipNode = new QQuickDefaultClipNode(item->clipRect());
- itemPriv->clipNode()->update();
+ QQuickDefaultClipNode *clip = new QQuickDefaultClipNode(item->clipRect());
+ itemPriv->extra.value().clipNode = clip;
+ clip->update();
- if (child)
+ if (!child) {
+ parent->reparentChildNodesTo(clip);
+ parent->appendChildNode(clip);
+ } else {
parent->removeChildNode(child);
- parent->appendChildNode(itemPriv->clipNode());
- if (child)
- itemPriv->clipNode()->appendChildNode(child);
+ clip->appendChildNode(child);
+ parent->appendChildNode(clip);
+ }
} else {
- Q_ASSERT(itemPriv->clipNode() != 0);
- parent->removeChildNode(itemPriv->clipNode());
- if (child)
- itemPriv->clipNode()->removeChildNode(child);
+ QQuickDefaultClipNode *clip = itemPriv->clipNode();
+ Q_ASSERT(clip);
+ parent->removeChildNode(clip);
+ if (child) {
+ clip->removeChildNode(child);
+ parent->appendChildNode(child);
+ } else {
+ clip->reparentChildNodesTo(parent);
+ }
+
delete itemPriv->clipNode();
itemPriv->extra->clipNode = 0;
- if (child)
- parent->appendChildNode(child);
}
}
- if (dirty & QQuickItemPrivate::ChildrenUpdateMask)
- itemPriv->childContainerNode()->removeAllChildNodes();
-
if (effectRefEffectivelyChanged) {
+ if (dirty & QQuickItemPrivate::ChildrenUpdateMask)
+ itemPriv->childContainerNode()->removeAllChildNodes();
+
QSGNode *parent = itemPriv->clipNode();
if (!parent)
parent = itemPriv->opacityNode();
if (!parent)
parent = itemPriv->itemNode();
- QSGNode *child = itemPriv->groupNode;
if (itemPriv->extra.isAllocated() && itemPriv->extra->effectRefCount) {
Q_ASSERT(itemPriv->rootNode() == 0);
- itemPriv->extra->rootNode = new QSGRootNode;
-
- if (child)
- parent->removeChildNode(child);
- parent->appendChildNode(itemPriv->rootNode());
- if (child)
- itemPriv->rootNode()->appendChildNode(child);
+ QSGRootNode *root = new QSGRootNode();
+ itemPriv->extra->rootNode = root;
+ parent->reparentChildNodesTo(root);
+ parent->appendChildNode(root);
} else {
Q_ASSERT(itemPriv->rootNode() != 0);
- parent->removeChildNode(itemPriv->rootNode());
- if (child)
- itemPriv->rootNode()->removeChildNode(child);
+ QSGRootNode *root = itemPriv->rootNode();
+ parent->removeChildNode(root);
+ root->reparentChildNodesTo(parent);
delete itemPriv->rootNode();
itemPriv->extra->rootNode = 0;
- if (child)
- parent->appendChildNode(child);
}
}
if (dirty & QQuickItemPrivate::ChildrenUpdateMask) {
- QSGNode *groupNode = itemPriv->groupNode;
- if (groupNode)
- groupNode->removeAllChildNodes();
-
- QList<QQuickItem *> orderedChildren = itemPriv->paintOrderChildItems();
- int ii = 0;
+ QVector<QSGNode *> desiredNodes = buildOrderedNodeList(itemPriv);
+
+ // now start making current state match the promised land of
+ // desiredNodes. in the case of our current state matching desiredNodes
+ // (though why would we get ChildrenUpdateMask with no changes?) then we
+ // should make no changes at all.
+
+ // how many nodes did we process, when examining changes
+ int desiredNodesProcessed = 0;
+
+ // currentNode is how far, in our present tree, we have processed. we
+ // make use of this later on to trim the current child list if the
+ // desired list is shorter.
+ QSGNode *groupNode = itemPriv->childContainerNode();
+ QSGNode *currentNode = groupNode->firstChild();
+ int added = 0;
+ int removed = 0;
+ int replaced = 0;
+#if defined(CHILDRENUPDATE_DEBUG)
+ // This is slow! Do not do this in a normal/profiling build!
+ int initialCount = groupNode->childCount();
+#endif
- for (; ii < orderedChildren.count() && orderedChildren.at(ii)->z() < 0; ++ii) {
- QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(orderedChildren.at(ii));
- if (!childPrivate->explicitVisible &&
- (!childPrivate->extra.isAllocated() || !childPrivate->extra->effectRefCount))
- continue;
- if (childPrivate->itemNode()->parent())
- childPrivate->itemNode()->parent()->removeChildNode(childPrivate->itemNode());
+ while (currentNode && desiredNodesProcessed < desiredNodes.size()) {
+ QSGNode *desiredNode = desiredNodes.at(desiredNodesProcessed);
+
+ // uh oh... reality and our utopic paradise are diverging!
+ // we need to reconcile this...
+ if (currentNode != desiredNode) {
+ // for now, we're just removing the node from the children -
+ // and replacing it with the new node.
+ if (desiredNode->parent())
+ desiredNode->parent()->removeChildNode(desiredNode);
+ groupNode->insertChildNodeAfter(desiredNode, currentNode);
+ groupNode->removeChildNode(currentNode);
+ replaced++;
+
+ // since we just replaced currentNode, we also need to reset
+ // the pointer.
+ currentNode = desiredNode;
+ }
- itemPriv->childContainerNode()->appendChildNode(childPrivate->itemNode());
+ currentNode = currentNode->nextSibling();
+ desiredNodesProcessed++;
}
- QSGNode *beforePaintNode = itemPriv->groupNode ? itemPriv->groupNode->lastChild() : 0;
- if (beforePaintNode || itemPriv->extra.isAllocated())
- itemPriv->extra.value().beforePaintNode = beforePaintNode;
-
- if (itemPriv->paintNode)
- itemPriv->childContainerNode()->appendChildNode(itemPriv->paintNode);
-
- for (; ii < orderedChildren.count(); ++ii) {
- QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(orderedChildren.at(ii));
- if (!childPrivate->explicitVisible &&
- (!childPrivate->extra.isAllocated() || !childPrivate->extra->effectRefCount))
- continue;
- if (childPrivate->itemNode()->parent())
- childPrivate->itemNode()->parent()->removeChildNode(childPrivate->itemNode());
-
- itemPriv->childContainerNode()->appendChildNode(childPrivate->itemNode());
+ // if we didn't process as many nodes as in the new list, then we have
+ // more nodes at the end of desiredNodes to append to our list.
+ // this will be the case when adding new nodes, for instance.
+ if (desiredNodesProcessed < desiredNodes.size()) {
+ for (int i = desiredNodesProcessed; i < desiredNodes.size(); ++i) {
+ QSGNode *desiredNode = desiredNodes.at(i);
+ if (desiredNode->parent())
+ desiredNode->parent()->removeChildNode(desiredNode);
+ groupNode->appendChildNode(desiredNode);
+ added++;
+ }
+ } else if (currentNode) {
+ // on the other hand, if we processed less than our current node
+ // tree, then nodes have been _removed_ from the scene, and we need
+ // to take care of that here.
+ while (currentNode) {
+ QSGNode *node = currentNode->nextSibling();
+ groupNode->removeChildNode(currentNode);
+ currentNode = node;
+ removed++;
+ }
}
+
+#if defined(CHILDRENUPDATE_DEBUG)
+ qDebug() << "Done children update for " << itemPriv << "- before:" << initialCount << "after:" << groupNode->childCount() << "added:" << added << "removed:" << removed << "replaced:" << replaced;
+#endif
}
if ((dirty & QQuickItemPrivate::Size) && itemPriv->clipNode()) {
@@ -2795,20 +2893,22 @@ void QQuickWindowPrivate::updateDirtyNode(QQuickItem *item)
? itemPriv->opacity() : qreal(0);
if (opacity != 1 && !itemPriv->opacityNode()) {
- itemPriv->extra.value().opacityNode = new QSGOpacityNode;
+ QSGOpacityNode *node = new QSGOpacityNode;
+ itemPriv->extra.value().opacityNode = node;
QSGNode *parent = itemPriv->itemNode();
QSGNode *child = itemPriv->clipNode();
if (!child)
child = itemPriv->rootNode();
- if (!child)
- child = itemPriv->groupNode;
- if (child)
+ if (child) {
parent->removeChildNode(child);
- parent->appendChildNode(itemPriv->opacityNode());
- if (child)
- itemPriv->opacityNode()->appendChildNode(child);
+ node->appendChildNode(child);
+ parent->appendChildNode(node);
+ } else {
+ parent->reparentChildNodesTo(node);
+ parent->appendChildNode(node);
+ }
}
if (itemPriv->opacityNode())
itemPriv->opacityNode()->setOpacity(opacity);
@@ -2825,8 +2925,9 @@ void QQuickWindowPrivate::updateDirtyNode(QQuickItem *item)
itemPriv->paintNode->parent() == itemPriv->childContainerNode());
if (itemPriv->paintNode && itemPriv->paintNode->parent() == 0) {
- if (itemPriv->extra.isAllocated() && itemPriv->extra->beforePaintNode)
- itemPriv->childContainerNode()->insertChildNodeAfter(itemPriv->paintNode, itemPriv->extra->beforePaintNode);
+ QSGNode *before = qquickitem_before_paintNode(itemPriv);
+ if (before)
+ itemPriv->childContainerNode()->insertChildNodeAfter(itemPriv->paintNode, before);
else
itemPriv->childContainerNode()->prependChildNode(itemPriv->paintNode);
}
@@ -2838,37 +2939,22 @@ void QQuickWindowPrivate::updateDirtyNode(QQuickItem *item)
#ifndef QT_NO_DEBUG
// Check consistency.
- const QSGNode *nodeChain[] = {
- itemPriv->itemNodeInstance,
- itemPriv->opacityNode(),
- itemPriv->clipNode(),
- itemPriv->rootNode(),
- itemPriv->groupNode,
- itemPriv->paintNode,
- };
-
- int ip = 0;
- for (;;) {
- while (ip < 5 && nodeChain[ip] == 0)
- ++ip;
- if (ip == 5)
- break;
- int ic = ip + 1;
- while (ic < 5 && nodeChain[ic] == 0)
- ++ic;
- const QSGNode *parent = nodeChain[ip];
- const QSGNode *child = nodeChain[ic];
- if (child == 0) {
- Q_ASSERT(parent == itemPriv->groupNode || parent->childCount() == 0);
- } else {
- Q_ASSERT(parent == itemPriv->groupNode || parent->childCount() == 1);
- Q_ASSERT(child->parent() == parent);
- bool containsChild = false;
- for (QSGNode *n = parent->firstChild(); n; n = n->nextSibling())
- containsChild |= (n == child);
- Q_ASSERT(containsChild);
- }
- ip = ic;
+
+ QList<QSGNode *> nodes;
+ nodes << itemPriv->itemNodeInstance
+ << itemPriv->opacityNode()
+ << itemPriv->clipNode()
+ << itemPriv->rootNode()
+ << itemPriv->paintNode;
+ nodes.removeAll(0);
+
+ Q_ASSERT(nodes.first() == itemPriv->itemNodeInstance);
+ for (int i=1; i<nodes.size(); ++i) {
+ QSGNode *n = nodes.at(i);
+ // Failing this means we messed up reparenting
+ Q_ASSERT(n->parent() == nodes.at(i-1));
+ // Only the paintNode and the one who is childContainer may have more than one child.
+ Q_ASSERT(n == itemPriv->paintNode || n == itemPriv->childContainerNode() || n->childCount() == 1);
}
#endif
@@ -2937,6 +3023,15 @@ QOpenGLContext *QQuickWindow::openglContext() const
}
/*!
+ Returns true if the scene graph has been initialized; otherwise returns false.
+ */
+bool QQuickWindow::isSceneGraphInitialized() const
+{
+ Q_D(const QQuickWindow);
+ return d->context != 0 && d->context->isValid();
+}
+
+/*!
\fn void QQuickWindow::frameSwapped()
This signal is emitted when the frame buffers have been swapped.
@@ -3672,6 +3767,15 @@ void QQuickWindow::resetOpenGLState()
*/
/*!
+ \qmlattachedproperty int Window::width
+ \qmlattachedproperty int Window::height
+ \since 5.5
+
+ These attached properties hold the size of the item's window.
+ The Window attached property can be attached to any Item.
+*/
+
+/*!
\qmlproperty int Window::x
\qmlproperty int Window::y
\qmlproperty int Window::width
diff --git a/src/quick/items/qquickwindow.h b/src/quick/items/qquickwindow.h
index ddf9722313..349cdf7474 100644
--- a/src/quick/items/qquickwindow.h
+++ b/src/quick/items/qquickwindow.h
@@ -115,7 +115,7 @@ public:
QQmlIncubationController *incubationController() const;
#ifndef QT_NO_ACCESSIBILITY
- virtual QAccessibleInterface *accessibleRoot() const;
+ QAccessibleInterface *accessibleRoot() const Q_DECL_OVERRIDE;
#endif
// Scene graph specific functions
@@ -139,6 +139,7 @@ public:
bool isPersistentSceneGraph() const;
QOpenGLContext *openglContext() const;
+ bool isSceneGraphInitialized() const;
void scheduleRenderJob(QRunnable *job, RenderStage schedule);
@@ -169,25 +170,25 @@ public Q_SLOTS:
protected:
QQuickWindow(QQuickWindowPrivate &dd, QWindow *parent = 0);
- virtual void exposeEvent(QExposeEvent *);
- virtual void resizeEvent(QResizeEvent *);
+ void exposeEvent(QExposeEvent *) Q_DECL_OVERRIDE;
+ void resizeEvent(QResizeEvent *) Q_DECL_OVERRIDE;
- virtual void showEvent(QShowEvent *);
- virtual void hideEvent(QHideEvent *);
+ void showEvent(QShowEvent *) Q_DECL_OVERRIDE;
+ void hideEvent(QHideEvent *) Q_DECL_OVERRIDE;
// TODO Qt 6: reimplement QWindow::closeEvent to emit closing
- virtual void focusInEvent(QFocusEvent *);
- virtual void focusOutEvent(QFocusEvent *);
+ void focusInEvent(QFocusEvent *) Q_DECL_OVERRIDE;
+ void focusOutEvent(QFocusEvent *) Q_DECL_OVERRIDE;
- virtual bool event(QEvent *);
- virtual void keyPressEvent(QKeyEvent *);
- virtual void keyReleaseEvent(QKeyEvent *);
- virtual void mousePressEvent(QMouseEvent *);
- virtual void mouseReleaseEvent(QMouseEvent *);
- virtual void mouseDoubleClickEvent(QMouseEvent *);
- virtual void mouseMoveEvent(QMouseEvent *);
+ bool event(QEvent *) Q_DECL_OVERRIDE;
+ void keyPressEvent(QKeyEvent *) Q_DECL_OVERRIDE;
+ void keyReleaseEvent(QKeyEvent *) Q_DECL_OVERRIDE;
+ void mousePressEvent(QMouseEvent *) Q_DECL_OVERRIDE;
+ void mouseReleaseEvent(QMouseEvent *) Q_DECL_OVERRIDE;
+ void mouseDoubleClickEvent(QMouseEvent *) Q_DECL_OVERRIDE;
+ void mouseMoveEvent(QMouseEvent *) Q_DECL_OVERRIDE;
#ifndef QT_NO_WHEELEVENT
- virtual void wheelEvent(QWheelEvent *);
+ void wheelEvent(QWheelEvent *) Q_DECL_OVERRIDE;
#endif
private Q_SLOTS:
diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h
index 6cd41950cb..10be57059c 100644
--- a/src/quick/items/qquickwindow_p.h
+++ b/src/quick/items/qquickwindow_p.h
@@ -89,6 +89,14 @@ class QQuickWindowIncubationController;
class QOpenGLVertexArrayObjectHelper;
+class Q_QUICK_PRIVATE_EXPORT QQuickCustomRenderStage
+{
+public:
+ virtual ~QQuickCustomRenderStage() {}
+ virtual bool render() = 0;
+ virtual bool swap() = 0;
+};
+
class Q_QUICK_PRIVATE_EXPORT QQuickWindowPrivate : public QWindowPrivate
{
public:
@@ -209,6 +217,7 @@ public:
QQuickAnimatorController *animationController;
QTouchEvent *delayedTouch;
int touchRecursionGuard;
+ QQuickCustomRenderStage *customRenderStage;
QColor clearColor;
diff --git a/src/quick/items/qquickwindowattached.cpp b/src/quick/items/qquickwindowattached.cpp
index f74e903be3..70985bdd45 100644
--- a/src/quick/items/qquickwindowattached.cpp
+++ b/src/quick/items/qquickwindowattached.cpp
@@ -70,6 +70,16 @@ QQuickItem *QQuickWindowAttached::contentItem() const
return (m_window ? m_window->contentItem() : Q_NULLPTR);
}
+int QQuickWindowAttached::width() const
+{
+ return (m_window ? m_window->width() : 0);
+}
+
+int QQuickWindowAttached::height() const
+{
+ return (m_window ? m_window->height() : 0);
+}
+
void QQuickWindowAttached::windowChanged(QQuickWindow *window)
{
if (window != m_window) {
@@ -89,6 +99,10 @@ void QQuickWindowAttached::windowChanged(QQuickWindow *window)
if (!oldWindow || window->activeFocusItem() != oldWindow->activeFocusItem())
emit activeFocusItemChanged();
emit contentItemChanged();
+ if (!oldWindow || window->width() != oldWindow->width())
+ emit widthChanged();
+ if (!oldWindow || window->height() != oldWindow->height())
+ emit heightChanged();
// QQuickWindowQmlImpl::visibilityChanged also exists, and window might even
// be QQuickWindowQmlImpl, but that's not what we are connecting to.
@@ -102,6 +116,10 @@ void QQuickWindowAttached::windowChanged(QQuickWindow *window)
this, &QQuickWindowAttached::activeChanged);
connect(window, &QQuickWindow::activeFocusItemChanged,
this, &QQuickWindowAttached::activeFocusItemChanged);
+ connect(window, &QQuickWindow::widthChanged,
+ this, &QQuickWindowAttached::widthChanged);
+ connect(window, &QQuickWindow::heightChanged,
+ this, &QQuickWindowAttached::heightChanged);
}
}
diff --git a/src/quick/items/qquickwindowattached_p.h b/src/quick/items/qquickwindowattached_p.h
index 7c2b0bc873..df1499c692 100644
--- a/src/quick/items/qquickwindowattached_p.h
+++ b/src/quick/items/qquickwindowattached_p.h
@@ -50,6 +50,8 @@ class Q_AUTOTEST_EXPORT QQuickWindowAttached : public QObject
Q_PROPERTY(bool active READ isActive NOTIFY activeChanged)
Q_PROPERTY(QQuickItem* activeFocusItem READ activeFocusItem NOTIFY activeFocusItemChanged)
Q_PROPERTY(QQuickItem* contentItem READ contentItem NOTIFY contentItemChanged)
+ Q_PROPERTY(int width READ width NOTIFY widthChanged)
+ Q_PROPERTY(int height READ height NOTIFY heightChanged)
public:
QQuickWindowAttached(QObject* attachee);
@@ -58,6 +60,8 @@ public:
bool isActive() const;
QQuickItem* activeFocusItem() const;
QQuickItem* contentItem() const;
+ int width() const;
+ int height() const;
Q_SIGNALS:
@@ -65,6 +69,8 @@ Q_SIGNALS:
void activeChanged();
void activeFocusItemChanged();
void contentItemChanged();
+ void widthChanged();
+ void heightChanged();
protected Q_SLOTS:
void windowChanged(QQuickWindow*);
diff --git a/src/quick/items/qquickwindowmodule.cpp b/src/quick/items/qquickwindowmodule.cpp
index 371abd163b..065c50c8f6 100644
--- a/src/quick/items/qquickwindowmodule.cpp
+++ b/src/quick/items/qquickwindowmodule.cpp
@@ -89,7 +89,7 @@ Q_SIGNALS:
void visibilityChanged(QWindow::Visibility visibility);
protected:
- void classBegin() {
+ void classBegin() Q_DECL_OVERRIDE {
QQmlEngine* e = qmlEngine(this);
//Give QQuickView behavior when created from QML with QQmlApplicationEngine
if (QCoreApplication::instance()->property("__qml_using_qqmlapplicationengine") == QVariant(true)) {
@@ -100,12 +100,12 @@ protected:
{
QV4::ExecutionEngine *v4 = QQmlEnginePrivate::getV4Engine(e);
QV4::Scope scope(v4);
- QV4::ScopedObject v(scope, QQuickRootItemMarker::create(e, this));
+ QV4::ScopedObject v(scope, QV4::QQuickRootItemMarker::create(e, this));
rootItemMarker = v;
}
}
- void componentComplete() {
+ void componentComplete() Q_DECL_OVERRIDE {
m_complete = true;
if (transientParent() && !transientParent()->isVisible()) {
connect(transientParent(), &QQuickWindow::visibleChanged, this,
diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
index dbea0faa9a..fd9b2a4480 100644
--- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
+++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
@@ -128,8 +128,9 @@ ShaderManager::Shader *ShaderManager::prepareMaterial(QSGMaterial *material)
if (shader)
return shader;
- if (QSG_LOG_TIME_COMPILATION().isDebugEnabled() || QQuickProfiler::profilingSceneGraph())
+ if (QSG_LOG_TIME_COMPILATION().isDebugEnabled())
qsg_renderer_timer.start();
+ Q_QUICK_SG_PROFILE_START(QQuickProfiler::SceneGraphContextFrame);
QSGMaterialShader *s = material->createShader();
QOpenGLContext *ctx = QOpenGLContext::currentContext();
@@ -159,8 +160,7 @@ ShaderManager::Shader *ShaderManager::prepareMaterial(QSGMaterial *material)
qCDebug(QSG_LOG_TIME_COMPILATION, "shader compiled in %dms", (int) qsg_renderer_timer.elapsed());
- Q_QUICK_SG_PROFILE(QQuickProfiler::SceneGraphContextFrame, (
- qsg_renderer_timer.nsecsElapsed()));
+ Q_QUICK_SG_PROFILE_END(QQuickProfiler::SceneGraphContextFrame);
rewrittenShaders[type] = shader;
return shader;
@@ -173,8 +173,9 @@ ShaderManager::Shader *ShaderManager::prepareMaterialNoRewrite(QSGMaterial *mate
if (shader)
return shader;
- if (QSG_LOG_TIME_COMPILATION().isDebugEnabled() || QQuickProfiler::profilingSceneGraph())
+ if (QSG_LOG_TIME_COMPILATION().isDebugEnabled())
qsg_renderer_timer.start();
+ Q_QUICK_SG_PROFILE_START(QQuickProfiler::SceneGraphContextFrame);
QSGMaterialShader *s = static_cast<QSGMaterialShader *>(material->createShader());
context->compile(s, material);
@@ -190,8 +191,7 @@ ShaderManager::Shader *ShaderManager::prepareMaterialNoRewrite(QSGMaterial *mate
qCDebug(QSG_LOG_TIME_COMPILATION, "shader compiled in %dms (no rewrite)", (int) qsg_renderer_timer.elapsed());
- Q_QUICK_SG_PROFILE(QQuickProfiler::SceneGraphContextFrame, (
- qsg_renderer_timer.nsecsElapsed()));
+ Q_QUICK_SG_PROFILE_END(QQuickProfiler::SceneGraphContextFrame);
return shader;
}
@@ -760,6 +760,10 @@ Renderer::Renderer(QSGRenderContext *ctx)
, m_clipMatrixId(0)
, m_currentClip(0)
, m_currentClipType(NoClip)
+ , m_vertexUploadPool(256)
+#ifdef QSG_SEPARATE_INDEX_BUFFER
+ , m_indexUploadPool(64)
+#endif
, m_vao(0)
, m_visualizeMode(VisualizeNothing)
{
@@ -817,6 +821,11 @@ Renderer::Renderer(QSGRenderContext *ctx)
static void qsg_wipeBuffer(Buffer *buffer, QOpenGLFunctions *funcs)
{
funcs->glDeleteBuffers(1, &buffer->id);
+ // The free here is ok because we're in one of two situations.
+ // 1. We're using the upload pool in which case unmap will have set the
+ // data pointer to 0 and calling free on 0 is ok.
+ // 2. We're using dedicated buffers because of visualization or IBO workaround
+ // and the data something we malloced and must be freed.
free(buffer->data);
}
@@ -838,8 +847,8 @@ Renderer::~Renderer()
for (int i=0; i<m_batchPool.size(); ++i) qsg_wipeBatch(m_batchPool.at(i), this);
}
- // The shadowtree
- qDeleteAll(m_nodes.values());
+ foreach (Node *n, m_nodes.values())
+ m_nodeAllocator.release(n);
// Remaining elements...
for (int i=0; i<m_elementsToDelete.size(); ++i) {
@@ -847,7 +856,7 @@ Renderer::~Renderer()
if (e->isRenderNode)
delete static_cast<RenderNodeElement *>(e);
else
- delete e;
+ m_elementAllocator.release(e);
}
}
@@ -870,14 +879,26 @@ void Renderer::invalidateAndRecycleBatch(Batch *b)
*
* ref: http://www.opengl.org/wiki/Buffer_Object
*/
-void Renderer::map(Buffer *buffer, int byteSize)
+void Renderer::map(Buffer *buffer, int byteSize, bool isIndexBuf)
{
- if (buffer->size != byteSize) {
- if (buffer->data)
- free(buffer->data);
+ if (!m_context->hasBrokenIndexBufferObjects() && m_visualizeMode == VisualizeNothing) {
+ // Common case, use a shared memory pool for uploading vertex data to avoid
+ // excessive reevaluation
+ QDataBuffer<char> &pool =
+#ifdef QSG_SEPARATE_INDEX_BUFFER
+ isIndexBuf ? m_indexUploadPool : m_vertexUploadPool;
+#else
+ m_vertexUploadPool;
+ Q_UNUSED(isIndexBuf);
+#endif
+ if (byteSize > pool.size())
+ pool.resize(byteSize);
+ buffer->data = pool.data();
+ } else {
buffer->data = (char *) malloc(byteSize);
- buffer->size = byteSize;
}
+ buffer->size = byteSize;
+
}
void Renderer::unmap(Buffer *buffer, bool isIndexBuf)
@@ -887,6 +908,10 @@ void Renderer::unmap(Buffer *buffer, bool isIndexBuf)
GLenum target = isIndexBuf ? GL_ELEMENT_ARRAY_BUFFER : GL_ARRAY_BUFFER;
glBindBuffer(target, buffer->id);
glBufferData(target, buffer->size, buffer->data, m_bufferStrategy);
+
+ if (!m_context->hasBrokenIndexBufferObjects() && m_visualizeMode == VisualizeNothing) {
+ buffer->data = 0;
+ }
}
BatchRootInfo *Renderer::batchRootInfo(Node *node)
@@ -986,7 +1011,8 @@ void Renderer::nodeWasAdded(QSGNode *node, Node *shadowParent)
if (node->isSubtreeBlocked())
return;
- Node *snode = new Node(node);
+ Node *snode = m_nodeAllocator.allocate();
+ snode->sgNode = node;
m_nodes.insert(node, snode);
if (shadowParent) {
snode->parent = shadowParent;
@@ -994,7 +1020,8 @@ void Renderer::nodeWasAdded(QSGNode *node, Node *shadowParent)
}
if (node->type() == QSGNode::GeometryNodeType) {
- snode->data = new Element(static_cast<QSGGeometryNode *>(node));
+ snode->data = m_elementAllocator.allocate();
+ snode->element()->setNode(static_cast<QSGGeometryNode *>(node));
} else if (node->type() == QSGNode::ClipNodeType) {
snode->data = new ClipBatchRootInfo;
@@ -1057,7 +1084,7 @@ void Renderer::nodeWasRemoved(Node *node)
}
Q_ASSERT(m_nodes.contains(node->sgNode));
- delete m_nodes.take(node->sgNode);
+ m_nodeAllocator.release(m_nodes.take(node->sgNode));
}
void Renderer::turnNodeIntoBatchRoot(Node *node)
@@ -1240,8 +1267,8 @@ void Renderer::buildRenderLists(QSGNode *node)
if (node->isSubtreeBlocked())
return;
- Q_ASSERT(m_nodes.contains(node));
Node *shadowNode = m_nodes.value(node);
+ Q_ASSERT(shadowNode);
if (node->type() == QSGNode::GeometryNodeType) {
QSGGeometryNode *gn = static_cast<QSGGeometryNode *>(node);
@@ -1262,7 +1289,7 @@ void Renderer::buildRenderLists(QSGNode *node)
} else if (node->type() == QSGNode::ClipNodeType || shadowNode->isBatchRoot) {
Q_ASSERT(m_nodes.contains(node));
- BatchRootInfo *info = batchRootInfo(m_nodes.value(node));
+ BatchRootInfo *info = batchRootInfo(shadowNode);
if (node == m_partialRebuildRoot) {
m_nextRenderOrder = info->firstOrder;
QSGNODE_TRAVERSE(node)
@@ -1725,7 +1752,8 @@ void Renderer::uploadBatch(Batch *b)
QSGGeometryNode *gn = b->first->node;
QSGGeometry *g = gn->geometry();
QSGMaterial::Flags flags = gn->activeMaterial()->flags();
- bool canMerge = (g->drawingMode() == GL_TRIANGLES || g->drawingMode() == GL_TRIANGLE_STRIP)
+ bool canMerge = (g->drawingMode() == GL_TRIANGLES || g->drawingMode() == GL_TRIANGLE_STRIP ||
+ g->drawingMode() == GL_LINES || g->drawingMode() == GL_POINTS)
&& b->positionAttribute >= 0
&& g->indexType() == GL_UNSIGNED_SHORT
&& (flags & (QSGMaterial::CustomCompileStep | QSGMaterial_FullMatrix)) == 0
@@ -1747,11 +1775,12 @@ void Renderer::uploadBatch(Batch *b)
if (b->merged) {
if (iCount == 0)
iCount = eg->vertexCount();
- // merged Triangle strips need to contain degenerate triangles at the beginning and end.
- // One could save 2 ushorts here by ditching the padding for the front of the
+ // Merged triangle strips need to contain degenerate triangles at the beginning and end.
+ // One could save 2 uploaded ushorts here by ditching the padding for the front of the
// first and the end of the last, but for simplicity, we simply don't care.
+ // Those extra triangles will be skipped while drawing to preserve the strip's parity anyhow.
if (g->drawingMode() == GL_TRIANGLE_STRIP)
- iCount += sizeof(quint16);
+ iCount += 2;
} else {
unmergedIndexSize += iCount * eg->sizeOfIndex();
}
@@ -1787,7 +1816,7 @@ void Renderer::uploadBatch(Batch *b)
}
#ifdef QSG_SEPARATE_INDEX_BUFFER
- map(&b->ibo, ibufferSize);
+ map(&b->ibo, ibufferSize, true);
#else
bufferSize += ibufferSize;
#endif
@@ -1821,6 +1850,10 @@ void Renderer::uploadBatch(Batch *b)
verticesInSet += e->node->geometry()->vertexCount();
if (verticesInSet > 0xffff) {
b->drawSets.last().indexCount = indicesInSet;
+ if (g->drawingMode() == GL_TRIANGLE_STRIP) {
+ b->drawSets.last().indices += 1 * sizeof(quint16);
+ b->drawSets.last().indexCount -= 2;
+ }
#ifdef QSG_SEPARATE_INDEX_BUFFER
drawSetIndices = indexData - b->ibo.data;
#else
@@ -1837,6 +1870,12 @@ void Renderer::uploadBatch(Batch *b)
e = e->nextInBatch;
}
b->drawSets.last().indexCount = indicesInSet;
+ // We skip the very first and very last degenerate triangles since they aren't needed
+ // and the first one would reverse the vertex ordering of the merged strips.
+ if (g->drawingMode() == GL_TRIANGLE_STRIP) {
+ b->drawSets.last().indices += 1 * sizeof(quint16);
+ b->drawSets.last().indexCount -= 2;
+ }
} else {
char *vboData = b->vbo.data;
#ifdef QSG_SEPARATE_INDEX_BUFFER
@@ -2466,7 +2505,7 @@ void Renderer::deleteRemovedElements()
if (e->isRenderNode)
delete static_cast<RenderNodeElement *>(e);
else
- delete e;
+ m_elementAllocator.release(e);
}
m_elementsToDelete.reset();
}
@@ -2578,14 +2617,37 @@ void Renderer::render()
m_zRange = 1.0 / (m_nextRenderOrder);
}
+ int largestVBO = 0;
+#ifdef QSG_SEPARATE_INDEX_BUFFER
+ int largestIBO = 0;
+#endif
if (Q_UNLIKELY(debug_upload())) qDebug() << "Uploading Opaque Batches:";
- for (int i=0; i<m_opaqueBatches.size(); ++i)
- uploadBatch(m_opaqueBatches.at(i));
+ for (int i=0; i<m_opaqueBatches.size(); ++i) {
+ Batch *b = m_opaqueBatches.at(i);
+ largestVBO = qMax(b->vbo.size, largestVBO);
+#ifdef QSG_SEPARATE_INDEX_BUFFER
+ largestIBO = qMax(b->ibo.size, largestIBO);
+#endif
+ uploadBatch(b);
+ }
if (Q_UNLIKELY(debug_upload())) qDebug() << "Uploading Alpha Batches:";
- for (int i=0; i<m_alphaBatches.size(); ++i)
- uploadBatch(m_alphaBatches.at(i));
+ for (int i=0; i<m_alphaBatches.size(); ++i) {
+ Batch *b = m_alphaBatches.at(i);
+ uploadBatch(b);
+ largestVBO = qMax(b->vbo.size, largestVBO);
+#ifdef QSG_SEPARATE_INDEX_BUFFER
+ largestIBO = qMax(b->ibo.size, largestIBO);
+#endif
+ }
+
+ if (largestVBO * 2 < m_vertexUploadPool.size())
+ m_vertexUploadPool.resize(largestVBO * 2);
+#ifdef QSG_SEPARATE_INDEX_BUFFER
+ if (largestIBO * 2 < m_indexUploadPool.size())
+ m_indexUploadPool.resize(largestIBO * 2);
+#endif
renderBatches();
@@ -2709,7 +2771,8 @@ public:
int color;
int matrix;
int rotation;
- int tweak;
+ int pattern;
+ int projection;
};
void Renderer::visualizeDrawGeometry(const QSGGeometry *g)
@@ -2742,8 +2805,7 @@ void Renderer::visualizeBatch(Batch *b)
if (b->root)
matrix = matrix * qsg_matrixForRoot(b->root);
- QRect viewport = viewportRect();
- shader->setUniformValue(shader->tweak, viewport.width(), viewport.height(), b->merged ? 0 : 1, 0);
+ shader->setUniformValue(shader->pattern, float(b->merged ? 0 : 1));
QColor color = QColor::fromHsvF((rand() & 1023) / 1023.0, 1.0, 1.0);
float cr = color.redF();
@@ -2826,9 +2888,7 @@ void Renderer::visualizeChanges(Node *n)
float cg = color.greenF() * ca;
float cb = color.blueF() * ca;
shader->setUniformValue(shader->color, cr, cg, cb, ca);
-
- QRect viewport = viewportRect();
- shader->setUniformValue(shader->tweak, viewport.width(), viewport.height(), tinted ? 0.5 : 0, 0);
+ shader->setUniformValue(shader->pattern, float(tinted ? 0.5 : 0));
QSGGeometryNode *gn = static_cast<QSGGeometryNode *>(n->sgNode);
@@ -2880,10 +2940,8 @@ void Renderer::visualizeOverdraw_helper(Node *node)
void Renderer::visualizeOverdraw()
{
VisualizeShader *shader = static_cast<VisualizeShader *>(m_shaderManager->visualizeProgram);
- shader->setUniformValue(shader->color, 0.5, 0.5, 1, 1);
-
- QRect viewport = viewportRect();
- shader->setUniformValue(shader->tweak, viewport.width(), viewport.height(), 0, 1);
+ shader->setUniformValue(shader->color, 0.5f, 0.5f, 1.0f, 1.0f);
+ shader->setUniformValue(shader->projection, 1);
glBlendFunc(GL_ONE, GL_ONE);
@@ -2963,7 +3021,8 @@ void Renderer::visualize()
prog->link();
prog->bind();
prog->color = prog->uniformLocation("color");
- prog->tweak = prog->uniformLocation("tweak");
+ prog->pattern = prog->uniformLocation("pattern");
+ prog->projection = prog->uniformLocation("projection");
prog->matrix = prog->uniformLocation("matrix");
prog->rotation = prog->uniformLocation("rotation");
m_shaderManager->visualizeProgram = prog;
@@ -2973,7 +3032,6 @@ void Renderer::visualize()
VisualizeShader *shader = static_cast<VisualizeShader *>(m_shaderManager->visualizeProgram);
glDisable(GL_DEPTH_TEST);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glEnableVertexAttribArray(0);
@@ -2983,10 +3041,11 @@ void Renderer::visualize()
if (m_visualizeMode == VisualizeBatches)
bgOpacity = 1.0;
float v[] = { -1, 1, 1, 1, -1, -1, 1, -1 };
- shader->setUniformValue(shader->color, 0, 0, 0, bgOpacity);
+ shader->setUniformValue(shader->color, 0.0f, 0.0f, 0.0f, bgOpacity);
shader->setUniformValue(shader->matrix, QMatrix4x4());
shader->setUniformValue(shader->rotation, QMatrix4x4());
- shader->setUniformValue(shader->tweak, 0, 0, 0, 0);
+ shader->setUniformValue(shader->pattern, 0.0f);
+ shader->setUniformValue(shader->projection, false);
glVertexAttribPointer(0, 2, GL_FLOAT, false, 0, v);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
@@ -2995,9 +3054,8 @@ void Renderer::visualize()
for (int i=0; i<m_opaqueBatches.size(); ++i) visualizeBatch(m_opaqueBatches.at(i));
for (int i=0; i<m_alphaBatches.size(); ++i) visualizeBatch(m_alphaBatches.at(i));
} else if (m_visualizeMode == VisualizeClipping) {
- QRect viewport = viewportRect();
- shader->setUniformValue(shader->tweak, viewport.width(), viewport.height(), 0.5, 0);
- shader->setUniformValue(shader->color, GLfloat(0.2), 0, 0, GLfloat(0.2));
+ shader->setUniformValue(shader->pattern, 0.5f);
+ shader->setUniformValue(shader->color, 0.2f, 0.0f, 0.0f, 0.2f);
visualizeClipping(rootNode());
} else if (m_visualizeMode == VisualizeChanges) {
visualizeChanges(m_nodes.value(rootNode()));
diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
index 5447d9ea52..50bea04f23 100644
--- a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
+++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
@@ -31,8 +31,8 @@
**
****************************************************************************/
-#ifndef ULTRARENDERER_H
-#define ULTRARENDERER_H
+#ifndef QSGBATCHRENDERER_P_H
+#define QSGBATCHRENDERER_P_H
#include <private/qsgrenderer_p.h>
#include <private/qsgnodeupdater_p.h>
@@ -40,6 +40,8 @@
#include <private/qsgrendernode_p.h>
+#include <QtCore/QBitArray>
+
QT_BEGIN_NAMESPACE
class QOpenGLVertexArrayObject;
@@ -59,6 +61,115 @@ class Updater;
class Renderer;
class ShaderManager;
+template <typename Type, int PageSize> class AllocatorPage
+{
+public:
+ // The memory used by this allocator
+ char data[sizeof(Type) * PageSize];
+
+ // 'blocks' contains a list of free indices which can be allocated.
+ // The first available index is found in PageSize - available.
+ int blocks[PageSize];
+
+ // 'available' is the number of available instances this page has left to allocate.
+ int available;
+
+ // This is not strictly needed, but useful for sanity checking and anyway
+ // pretty small..
+ QBitArray allocated;
+
+ AllocatorPage()
+ : available(PageSize)
+ , allocated(PageSize)
+ {
+ for (int i=0; i<PageSize; ++i) blocks[i] = i;
+ }
+
+ Type *at(uint index) const
+ {
+ return (Type *) &data[index * sizeof(Type)];
+ }
+};
+
+template <typename Type, int PageSize> class Allocator
+{
+public:
+ Allocator()
+ {
+ pages.push_back(new AllocatorPage<Type, PageSize>());
+ }
+
+ ~Allocator()
+ {
+ qDeleteAll(pages);
+ }
+
+ Type *allocate()
+ {
+ AllocatorPage<Type, PageSize> *p = 0;
+ for (int i=0; i<pages.size(); ++i) {
+ if (pages.at(i)->available > 0) {
+ p = pages.at(i);
+ break;
+ }
+ }
+ if (!p) {
+ p = new AllocatorPage<Type, PageSize>();
+ pages.push_back(p);
+ }
+ uint pos = p->blocks[PageSize - p->available];
+ void *mem = p->at(pos);
+ p->available--;
+ p->allocated.setBit(pos);
+ Type *t = new (mem) Type();
+ return t;
+ }
+
+ void releaseExplicit(uint pageIndex, uint index)
+ {
+ AllocatorPage<Type, PageSize> *page = pages.at(pageIndex);
+ if (!page->allocated.testBit(index))
+ qFatal("Double delete in allocator: page=%d, index=%d", pageIndex , index);
+
+ // Call the destructor
+ page->at(index)->~Type();
+
+ page->allocated[index] = false;
+ page->available++;
+ page->blocks[PageSize - page->available] = index;
+
+ // Remove the pages if they are empty and they are the last ones. We need to keep the
+ // order of pages since we have references to their index, so we can only remove
+ // from the end.
+ while (page->available == PageSize && pages.size() > 1 && pages.back() == page) {
+ pages.pop_back();
+ delete page;
+ page = pages.back();
+ }
+ }
+
+ void release(Type *t)
+ {
+ int pageIndex = -1;
+ for (int i=0; i<pages.size(); ++i) {
+ AllocatorPage<Type, PageSize> *p = pages.at(i);
+ if ((Type *) (&p->data[0]) <= t && (Type *) (&p->data[PageSize * sizeof(Type)]) > t) {
+ pageIndex = i;
+ break;
+ }
+ }
+ Q_ASSERT(pageIndex >= 0);
+
+ AllocatorPage<Type, PageSize> *page = pages.at(pageIndex);
+ int index = (quint64(t) - quint64(&page->data[0])) / sizeof(Type);
+
+ releaseExplicit(pageIndex, index);
+ }
+
+ QVector<AllocatorPage<Type, PageSize> *> pages;
+};
+
+
inline bool hasMaterialWithBlending(QSGGeometryNode *n)
{
return (n->opaqueMaterial() ? n->opaqueMaterial()->flags() & QSGMaterial::Blending
@@ -144,13 +255,15 @@ inline QDebug operator << (QDebug d, const Rect &r) {
struct Buffer {
GLuint id;
int size;
+ // Data is only valid while preparing the upload. Exception is if we are using the
+ // broken IBO workaround or we are using a visualization mode.
char *data;
};
struct Element {
- Element(QSGGeometryNode *n)
- : node(n)
+ Element()
+ : node(0)
, batch(0)
, nextInBatch(0)
, root(0)
@@ -161,10 +274,15 @@ struct Element {
, removed(false)
, orphaned(false)
, isRenderNode(false)
- , isMaterialBlended(n ? hasMaterialWithBlending(n) : false)
+ , isMaterialBlended(false)
{
}
+ void setNode(QSGGeometryNode *n) {
+ node = n;
+ isMaterialBlended = hasMaterialWithBlending(n);
+ }
+
inline void ensureBoundsValid() {
if (!boundsComputed)
computeBounds();
@@ -192,8 +310,7 @@ struct Element {
struct RenderNodeElement : public Element {
RenderNodeElement(QSGRenderNode *rn)
- : Element(0)
- , renderNode(rn)
+ : renderNode(rn)
{
isRenderNode = true;
}
@@ -289,15 +406,14 @@ struct Batch
struct Node
{
- Node(QSGNode *node, Node *sparent = 0)
- : sgNode(node)
- , parent(sparent)
+ Node()
+ : sgNode(0)
+ , parent(0)
, data(0)
, dirtyState(0)
, isOpaque(false)
, isBatchRoot(false)
{
-
}
QSGNode *sgNode;
@@ -435,8 +551,7 @@ private:
friend class Updater;
-
- void map(Buffer *buffer, int size);
+ void map(Buffer *buffer, int size, bool isIndexBuf = false);
void unmap(Buffer *buffer, bool isIndexBuf = false);
void buildRenderListsFromScratch();
@@ -527,11 +642,18 @@ private:
const QSGClipNode *m_currentClip;
ClipType m_currentClipType;
+ QDataBuffer<char> m_vertexUploadPool;
+#ifdef QSG_SEPARATE_INDEX_BUFFER
+ QDataBuffer<char> m_indexUploadPool;
+#endif
// For minimal OpenGL core profile support
QOpenGLVertexArrayObject *m_vao;
QHash<Node *, uint> m_visualizeChanceSet;
VisualizeMode m_visualizeMode;
+
+ Allocator<Node, 256> m_nodeAllocator;
+ Allocator<Element, 64> m_elementAllocator;
};
Batch *Renderer::newBatch()
@@ -556,4 +678,4 @@ Batch *Renderer::newBatch()
QT_END_NAMESPACE
-#endif // ULTRARENDERER_H
+#endif // QSGBATCHRENDERER_P_H
diff --git a/src/quick/scenegraph/coreapi/qsgnode.cpp b/src/quick/scenegraph/coreapi/qsgnode.cpp
index 58b6462d23..7f78318884 100644
--- a/src/quick/scenegraph/coreapi/qsgnode.cpp
+++ b/src/quick/scenegraph/coreapi/qsgnode.cpp
@@ -504,7 +504,7 @@ void QSGNode::insertChildNodeAfter(QSGNode *node, QSGNode *after)
{
//Q_ASSERT_X(!m_children.contains(node), "QSGNode::insertChildNodeAfter", "QSGNode is already a child!");
Q_ASSERT_X(!node->m_parent, "QSGNode::insertChildNodeAfter", "QSGNode already has a parent");
- Q_ASSERT_X(after && after->m_parent == this, "QSGNode::insertChildNodeBefore", "The parent of \'before\' is wrong");
+ Q_ASSERT_X(after && after->m_parent == this, "QSGNode::insertChildNodeAfter", "The parent of \'after\' is wrong");
#ifndef QT_NO_DEBUG
if (node->type() == QSGNode::GeometryNodeType) {
@@ -575,6 +575,19 @@ void QSGNode::removeAllChildNodes()
}
}
+/*!
+ * \internal
+ *
+ * Reparents all nodes of this node to \a newParent.
+ */
+void QSGNode::reparentChildNodesTo(QSGNode *newParent)
+{
+ for (QSGNode *c = firstChild(); c; c = firstChild()) {
+ removeChildNode(c);
+ newParent->appendChildNode(c);
+ }
+}
+
int QSGNode::childCount() const
{
diff --git a/src/quick/scenegraph/coreapi/qsgnode.h b/src/quick/scenegraph/coreapi/qsgnode.h
index dfacd84288..059cbeebdf 100644
--- a/src/quick/scenegraph/coreapi/qsgnode.h
+++ b/src/quick/scenegraph/coreapi/qsgnode.h
@@ -132,6 +132,7 @@ public:
void appendChildNode(QSGNode *node);
void insertChildNodeBefore(QSGNode *node, QSGNode *before);
void insertChildNodeAfter(QSGNode *node, QSGNode *after);
+ void reparentChildNodesTo(QSGNode *newParent);
int childCount() const;
QSGNode *childAtIndex(int i) const;
diff --git a/src/quick/scenegraph/coreapi/qsgrenderer.cpp b/src/quick/scenegraph/coreapi/qsgrenderer.cpp
index dd089425f6..ce86408434 100644
--- a/src/quick/scenegraph/coreapi/qsgrenderer.cpp
+++ b/src/quick/scenegraph/coreapi/qsgrenderer.cpp
@@ -176,10 +176,11 @@ void QSGRenderer::renderScene(const QSGBindable &bindable)
m_is_rendering = true;
- bool profileFrames = QSG_LOG_TIME_RENDERER().isDebugEnabled() ||
- QQuickProfiler::profilingSceneGraph();
+ bool profileFrames = QSG_LOG_TIME_RENDERER().isDebugEnabled();
if (profileFrames)
frameTimer.start();
+ Q_QUICK_SG_PROFILE_START(QQuickProfiler::SceneGraphRendererFrame);
+
qint64 bindTime = 0;
qint64 renderTime = 0;
@@ -189,6 +190,7 @@ void QSGRenderer::renderScene(const QSGBindable &bindable)
bindable.bind();
if (profileFrames)
bindTime = frameTimer.nsecsElapsed();
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRendererFrame);
// Sanity check that attribute registers are disabled
if (qsg_sanity_check) {
@@ -206,6 +208,7 @@ void QSGRenderer::renderScene(const QSGBindable &bindable)
render();
if (profileFrames)
renderTime = frameTimer.nsecsElapsed();
+ Q_QUICK_SG_PROFILE_END(QQuickProfiler::SceneGraphRendererFrame);
m_is_rendering = false;
m_changed_emitted = false;
@@ -218,13 +221,6 @@ void QSGRenderer::renderScene(const QSGBindable &bindable)
int((updatePassTime - preprocessTime) / 1000000),
int((bindTime - updatePassTime) / 1000000),
int((renderTime - bindTime) / 1000000));
-
- Q_QUICK_SG_PROFILE(QQuickProfiler::SceneGraphRendererFrame, (
- preprocessTime,
- updatePassTime - preprocessTime,
- bindTime - updatePassTime,
- renderTime - bindTime));
-
}
/*!
@@ -273,15 +269,16 @@ void QSGRenderer::preprocess()
}
}
- bool profileFrames = QSG_LOG_TIME_RENDERER().isDebugEnabled()||
- QQuickProfiler::profilingSceneGraph();
+ bool profileFrames = QSG_LOG_TIME_RENDERER().isDebugEnabled();
if (profileFrames)
preprocessTime = frameTimer.nsecsElapsed();
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRendererFrame);
nodeUpdater()->updateStates(root);
if (profileFrames)
updatePassTime = frameTimer.nsecsElapsed();
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRendererFrame);
}
void QSGRenderer::addNodesToPreprocess(QSGNode *node)
diff --git a/src/quick/scenegraph/qsgadaptationlayer.cpp b/src/quick/scenegraph/qsgadaptationlayer.cpp
index 83704cf0ec..7ddfdeb2d4 100644
--- a/src/quick/scenegraph/qsgadaptationlayer.cpp
+++ b/src/quick/scenegraph/qsgadaptationlayer.cpp
@@ -153,10 +153,10 @@ void QSGDistanceFieldGlyphCache::update()
if (m_pendingGlyphs.isEmpty())
return;
- bool profileFrames = QSG_LOG_TIME_GLYPH().isDebugEnabled() ||
- QQuickProfiler::profilingSceneGraph();
+ bool profileFrames = QSG_LOG_TIME_GLYPH().isDebugEnabled();
if (profileFrames)
qsg_render_timer.start();
+ Q_QUICK_SG_PROFILE_START(QQuickProfiler::SceneGraphAdaptationLayerFrame);
QList<QDistanceField> distanceFields;
for (int i = 0; i < m_pendingGlyphs.size(); ++i) {
@@ -169,6 +169,7 @@ void QSGDistanceFieldGlyphCache::update()
int count = m_pendingGlyphs.size();
if (profileFrames)
renderTime = qsg_render_timer.nsecsElapsed();
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphAdaptationLayerFrame);
m_pendingGlyphs.reset();
@@ -188,10 +189,8 @@ void QSGDistanceFieldGlyphCache::update()
int(renderTime / 1000000),
int((now - (renderTime / 1000000))));
}
- Q_QUICK_SG_PROFILE(QQuickProfiler::SceneGraphAdaptationLayerFrame, (
- count,
- renderTime,
- qsg_render_timer.nsecsElapsed() - renderTime));
+ Q_QUICK_SG_PROFILE_END_WITH_PAYLOAD(QQuickProfiler::SceneGraphAdaptationLayerFrame,
+ (qint64)count);
}
void QSGDistanceFieldGlyphCache::setGlyphsPosition(const QList<GlyphPosition> &glyphs)
diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp
index 99695f058f..95388d82e0 100644
--- a/src/quick/scenegraph/qsgcontext.cpp
+++ b/src/quick/scenegraph/qsgcontext.cpp
@@ -379,6 +379,7 @@ void QSGContext::renderContextInitialized(QSGRenderContext *renderContext)
QByteArray all; foreach (const QByteArray &e, exts) all += ' ' + e;
qCDebug(QSG_LOG_INFO) << "GL_EXTENSIONS: " << all.constData();
qCDebug(QSG_LOG_INFO) << "Max Texture Size: " << renderContext->maxTextureSize();
+ qCDebug(QSG_LOG_INFO) << "Debug context: " << format.testOption(QSurfaceFormat::DebugContext);
}
d->mutex.unlock();
@@ -469,8 +470,11 @@ QSurfaceFormat QSGContext::defaultSurfaceFormat() const
QSurfaceFormat format = QSurfaceFormat::defaultFormat();
static bool useDepth = qEnvironmentVariableIsEmpty("QSG_NO_DEPTH_BUFFER");
static bool useStencil = qEnvironmentVariableIsEmpty("QSG_NO_STENCIL_BUFFER");
+ static bool enableDebug = qEnvironmentVariableIsSet("QSG_OPENGL_DEBUG");
format.setDepthBufferSize(useDepth ? 24 : 0);
format.setStencilBufferSize(useStencil ? 8 : 0);
+ if (enableDebug)
+ format.setOption(QSurfaceFormat::DebugContext);
if (QQuickWindow::hasDefaultAlphaBuffer())
format.setAlphaBufferSize(8);
format.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
diff --git a/src/quick/scenegraph/qsgcontext_p.h b/src/quick/scenegraph/qsgcontext_p.h
index 184b8248d5..91788d82d4 100644
--- a/src/quick/scenegraph/qsgcontext_p.h
+++ b/src/quick/scenegraph/qsgcontext_p.h
@@ -93,7 +93,7 @@ public:
QOpenGLContext *openglContext() const { return m_gl; }
QSGContext *sceneGraphContext() const { return m_sg; }
- bool isValid() const { return m_gl; }
+ virtual bool isValid() const { return m_gl; }
virtual void initialize(QOpenGLContext *context);
virtual void invalidate();
diff --git a/src/quick/scenegraph/qsgdefaultlayer.cpp b/src/quick/scenegraph/qsgdefaultlayer.cpp
index 450a9fbee0..2d114aebd5 100644
--- a/src/quick/scenegraph/qsgdefaultlayer.cpp
+++ b/src/quick/scenegraph/qsgdefaultlayer.cpp
@@ -57,7 +57,7 @@ namespace
public:
BindableFbo(QOpenGLFramebufferObject *fbo, QSGDepthStencilBuffer *depthStencil);
virtual ~BindableFbo();
- virtual void bind() const;
+ void bind() const Q_DECL_OVERRIDE;
private:
QOpenGLFramebufferObject *m_fbo;
QSGDepthStencilBuffer *m_depthStencil;
diff --git a/src/quick/scenegraph/qsgdefaultlayer_p.h b/src/quick/scenegraph/qsgdefaultlayer_p.h
index 44c74d7cfd..0615045d60 100644
--- a/src/quick/scenegraph/qsgdefaultlayer_p.h
+++ b/src/quick/scenegraph/qsgdefaultlayer_p.h
@@ -54,7 +54,7 @@ public:
QSGDefaultLayer(QSGRenderContext *context);
~QSGDefaultLayer();
- virtual bool updateTexture();
+ bool updateTexture() Q_DECL_OVERRIDE;
// The item's "paint node", not effect node.
QSGNode *item() const { return m_item; }
diff --git a/src/quick/scenegraph/qsgrenderloop.cpp b/src/quick/scenegraph/qsgrenderloop.cpp
index c66915d19d..985be8591f 100644
--- a/src/quick/scenegraph/qsgrenderloop.cpp
+++ b/src/quick/scenegraph/qsgrenderloop.cpp
@@ -169,7 +169,12 @@ QSGRenderLoop *QSGRenderLoop::instance()
RenderLoopType loopType = BasicRenderLoop;
#ifdef Q_OS_WIN
- loopType = WindowsRenderLoop;
+ // With desktop OpenGL (opengl32.dll), use threaded. Otherwise (ANGLE) use windows.
+ if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL
+ && QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ThreadedOpenGL))
+ loopType = ThreadedRenderLoop;
+ else
+ loopType = WindowsRenderLoop;
#else
if (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ThreadedOpenGL))
loopType = ThreadedRenderLoop;
@@ -347,17 +352,17 @@ void QSGGuiThreadRenderLoop::renderWindow(QQuickWindow *window)
}
QElapsedTimer renderTimer;
qint64 renderTime = 0, syncTime = 0, polishTime = 0;
- bool profileFrames = QSG_LOG_TIME_RENDERLOOP().isDebugEnabled() ||
- QQuickProfiler::profilingSceneGraph();
+ bool profileFrames = QSG_LOG_TIME_RENDERLOOP().isDebugEnabled();
if (profileFrames)
renderTimer.start();
+ Q_QUICK_SG_PROFILE_START(QQuickProfiler::SceneGraphPolishFrame);
cd->polishItems();
- if (profileFrames) {
+ if (profileFrames)
polishTime = renderTimer.nsecsElapsed();
- Q_QUICK_SG_PROFILE(QQuickProfiler::SceneGraphPolishFrame, (polishTime));
- }
+ Q_QUICK_SG_PROFILE_SWITCH(QQuickProfiler::SceneGraphPolishFrame,
+ QQuickProfiler::SceneGraphRenderLoopFrame);
emit window->afterAnimating();
@@ -365,11 +370,13 @@ void QSGGuiThreadRenderLoop::renderWindow(QQuickWindow *window)
if (profileFrames)
syncTime = renderTimer.nsecsElapsed();
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRenderLoopFrame);
cd->renderSceneGraph(window->size());
if (profileFrames)
renderTime = renderTimer.nsecsElapsed();
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRenderLoopFrame);
if (data.grabOnly) {
grabContent = qt_gl_read_framebuffer(window->size() * window->effectiveDevicePixelRatio(), false, false);
@@ -377,13 +384,15 @@ void QSGGuiThreadRenderLoop::renderWindow(QQuickWindow *window)
}
if (alsoSwap && window->isVisible()) {
- gl->swapBuffers(window);
+ if (!cd->customRenderStage || !cd->customRenderStage->swap())
+ gl->swapBuffers(window);
cd->fireFrameSwapped();
}
qint64 swapTime = 0;
if (profileFrames)
swapTime = renderTimer.nsecsElapsed();
+ Q_QUICK_SG_PROFILE_END(QQuickProfiler::SceneGraphRenderLoopFrame);
if (QSG_LOG_TIME_RENDERLOOP().isDebugEnabled()) {
static QTime lastFrameTime = QTime::currentTime();
@@ -398,11 +407,6 @@ void QSGGuiThreadRenderLoop::renderWindow(QQuickWindow *window)
lastFrameTime = QTime::currentTime();
}
- Q_QUICK_SG_PROFILE(QQuickProfiler::SceneGraphRenderLoopFrame, (
- syncTime - polishTime,
- renderTime - syncTime,
- swapTime - renderTime));
-
// Might have been set during syncSceneGraph()
if (data.updatePending)
maybeUpdate(window);
diff --git a/src/quick/scenegraph/qsgrenderloop_p.h b/src/quick/scenegraph/qsgrenderloop_p.h
index e9b58c60ba..8d3214db60 100644
--- a/src/quick/scenegraph/qsgrenderloop_p.h
+++ b/src/quick/scenegraph/qsgrenderloop_p.h
@@ -64,6 +64,7 @@ public:
virtual void update(QQuickWindow *window) = 0;
virtual void maybeUpdate(QQuickWindow *window) = 0;
+ virtual void handleUpdateRequest(QQuickWindow *) { }
virtual QAnimationDriver *animationDriver() const = 0;
diff --git a/src/quick/scenegraph/qsgthreadedrenderloop.cpp b/src/quick/scenegraph/qsgthreadedrenderloop.cpp
index 155b52b31a..43cb6ab05c 100644
--- a/src/quick/scenegraph/qsgthreadedrenderloop.cpp
+++ b/src/quick/scenegraph/qsgthreadedrenderloop.cpp
@@ -105,16 +105,6 @@ QT_BEGIN_NAMESPACE
#define QSG_RT_PAD " (RT)"
-static int get_env_int(const char *name, int defaultValue)
-{
- QByteArray content = qgetenv(name);
-
- bool ok = false;
- int value = content.toInt(&ok);
- return ok ? value : defaultValue;
-}
-
-
static inline int qsgrl_animation_interval() {
qreal refreshRate = QGuiApplication::primaryScreen()->refreshRate();
// To work around that some platforms wrongfully return 0 or something
@@ -155,7 +145,7 @@ const QEvent::Type WM_TryRelease = QEvent::Type(QEvent::User + 4);
// called.
const QEvent::Type WM_Grab = QEvent::Type(QEvent::User + 5);
-template <typename T> T *windowFor(const QList<T> list, QQuickWindow *window)
+template <typename T> T *windowFor(const QList<T> &list, QQuickWindow *window)
{
for (int i=0; i<list.size(); ++i) {
const T &t = list.at(i);
@@ -531,12 +521,12 @@ void QSGRenderThread::sync(bool inExpose)
void QSGRenderThread::syncAndRender()
{
- bool profileFrames = QSG_LOG_TIME_RENDERLOOP().isDebugEnabled() ||
- QQuickProfiler::profilingSceneGraph();
+ bool profileFrames = QSG_LOG_TIME_RENDERLOOP().isDebugEnabled();
if (profileFrames) {
sinceLastTime = threadTimer.nsecsElapsed();
threadTimer.start();
}
+ Q_QUICK_SG_PROFILE_START(QQuickProfiler::SceneGraphRenderLoopFrame);
QElapsedTimer waitTimer;
waitTimer.start();
@@ -544,20 +534,24 @@ void QSGRenderThread::syncAndRender()
qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "syncAndRender()";
syncResultedInChanges = false;
+ QQuickWindowPrivate *d = QQuickWindowPrivate::get(window);
- uint pending = pendingUpdate;
+ bool repaintRequested = (pendingUpdate & RepaintRequest) || d->customRenderStage;
+ bool syncRequested = pendingUpdate & SyncRequest;
+ bool exposeRequested = (pendingUpdate & ExposeRequest) == ExposeRequest;
pendingUpdate = 0;
- if (pending & SyncRequest) {
+ if (syncRequested) {
qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- updatePending, doing sync";
- sync(pending == ExposeRequest);
+ sync(exposeRequested);
}
#ifndef QSG_NO_RENDER_TIMING
if (profileFrames)
syncTime = threadTimer.nsecsElapsed();
#endif
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRenderLoopFrame);
- if (!syncResultedInChanges && ((pending & RepaintRequest) == 0)) {
+ if (!syncResultedInChanges && !repaintRequested) {
qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- no changes, render aborted";
int waitTime = vsyncDelta - (int) waitTimer.elapsed();
if (waitTime > 0)
@@ -567,7 +561,6 @@ void QSGRenderThread::syncAndRender()
qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- rendering started";
- QQuickWindowPrivate *d = QQuickWindowPrivate::get(window);
if (animatorDriver->isRunning()) {
d->animationController->lock();
@@ -582,9 +575,12 @@ void QSGRenderThread::syncAndRender()
d->renderSceneGraph(windowSize);
if (profileFrames)
renderTime = threadTimer.nsecsElapsed();
- gl->swapBuffers(window);
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRenderLoopFrame);
+ if (!d->customRenderStage || !d->customRenderStage->swap())
+ gl->swapBuffers(window);
d->fireFrameSwapped();
} else {
+ Q_QUICK_SG_PROFILE_SKIP(QQuickProfiler::SceneGraphRenderLoopFrame, 1);
qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- window not ready, skipping render";
}
@@ -595,7 +591,7 @@ void QSGRenderThread::syncAndRender()
// that to avoid blocking the GUI thread in the case where it
// has started rendering with a bad window, causing makeCurrent to
// fail or if the window has a bad size.
- if (pending == ExposeRequest) {
+ if (exposeRequested) {
qCDebug(QSG_LOG_RENDERLOOP) << QSG_RT_PAD << "- wake Gui after initial expose";
waitCondition.wakeOne();
mutex.unlock();
@@ -609,10 +605,7 @@ void QSGRenderThread::syncAndRender()
int(threadTimer.elapsed() - renderTime / 1000000));
- Q_QUICK_SG_PROFILE(QQuickProfiler::SceneGraphRenderLoopFrame, (
- syncTime,
- renderTime - syncTime,
- threadTimer.nsecsElapsed() - renderTime));
+ Q_QUICK_SG_PROFILE_END(QQuickProfiler::SceneGraphRenderLoopFrame);
}
@@ -695,8 +688,6 @@ QSGThreadedRenderLoop::QSGThreadedRenderLoop()
m_animation_driver = sg->createAnimationDriver(this);
- m_exhaust_delay = get_env_int("QML_EXHAUST_DELAY", 5);
-
connect(m_animation_driver, SIGNAL(started()), this, SLOT(animationStarted()));
connect(m_animation_driver, SIGNAL(stopped()), this, SLOT(animationStopped()));
@@ -710,10 +701,7 @@ QSGRenderContext *QSGThreadedRenderLoop::createRenderContext(QSGContext *sg) con
void QSGThreadedRenderLoop::maybePostPolishRequest(Window *w)
{
- if (w->timerId == 0) {
- qCDebug(QSG_LOG_RENDERLOOP) << "- posting update";
- w->timerId = startTimer(m_exhaust_delay, Qt::PreciseTimer);
- }
+ w->window->requestUpdate();
}
QAnimationDriver *QSGThreadedRenderLoop::animationDriver() const
@@ -863,7 +851,6 @@ void QSGThreadedRenderLoop::handleExposure(QQuickWindow *window)
win.window = window;
win.actualWindowFormat = window->format();
win.thread = new QSGRenderThread(this, QQuickWindowPrivate::get(window)->context);
- win.timerId = 0;
win.updateDuringSync = false;
win.forceRenderPass = true; // also covered by polishAndSync(inExpose=true), but doesn't hurt
m_windows << win;
@@ -953,6 +940,14 @@ void QSGThreadedRenderLoop::handleObscurity(Window *w)
}
+void QSGThreadedRenderLoop::handleUpdateRequest(QQuickWindow *window)
+{
+ qCDebug(QSG_LOG_RENDERLOOP) << "- polish and sync update request";
+ Window *w = windowFor(m_windows, window);
+ if (w)
+ polishAndSync(w);
+}
+
void QSGThreadedRenderLoop::maybeUpdate(QQuickWindow *window)
{
Window *w = windowFor(m_windows, window);
@@ -1080,8 +1075,6 @@ void QSGThreadedRenderLoop::polishAndSync(Window *w, bool inExpose)
QQuickWindow *window = w->window;
if (!w->thread || !w->thread->window) {
qCDebug(QSG_LOG_RENDERLOOP) << "- not exposed, abort";
- killTimer(w->timerId);
- w->timerId = 0;
return;
}
@@ -1091,8 +1084,6 @@ void QSGThreadedRenderLoop::polishAndSync(Window *w, bool inExpose)
w = windowFor(m_windows, window);
if (!w || !w->thread || !w->thread->window) {
qCDebug(QSG_LOG_RENDERLOOP) << "- removed after event flushing, abort";
- killTimer(w->timerId);
- w->timerId = 0;
return;
}
@@ -1101,16 +1092,17 @@ void QSGThreadedRenderLoop::polishAndSync(Window *w, bool inExpose)
qint64 polishTime = 0;
qint64 waitTime = 0;
qint64 syncTime = 0;
- bool profileFrames = QSG_LOG_TIME_RENDERLOOP().isDebugEnabled() ||
- QQuickProfiler::profilingSceneGraph();
+ bool profileFrames = QSG_LOG_TIME_RENDERLOOP().isDebugEnabled();
if (profileFrames)
timer.start();
+ Q_QUICK_SG_PROFILE_START(QQuickProfiler::SceneGraphPolishAndSync);
QQuickWindowPrivate *d = QQuickWindowPrivate::get(window);
d->polishItems();
if (profileFrames)
polishTime = timer.nsecsElapsed();
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphPolishAndSync);
w->updateDuringSync = false;
@@ -1125,6 +1117,7 @@ void QSGThreadedRenderLoop::polishAndSync(Window *w, bool inExpose)
qCDebug(QSG_LOG_RENDERLOOP) << "- wait for sync";
if (profileFrames)
waitTime = timer.nsecsElapsed();
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphPolishAndSync);
w->thread->waitCondition.wait(&w->thread->mutex);
m_lockedForSync = false;
w->thread->mutex.unlock();
@@ -1132,9 +1125,7 @@ void QSGThreadedRenderLoop::polishAndSync(Window *w, bool inExpose)
if (profileFrames)
syncTime = timer.nsecsElapsed();
-
- killTimer(w->timerId);
- w->timerId = 0;
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphPolishAndSync);
if (m_animation_timer == 0 && m_animation_driver->isRunning()) {
qCDebug(QSG_LOG_RENDERLOOP) << "- advancing animations";
@@ -1155,22 +1146,7 @@ void QSGThreadedRenderLoop::polishAndSync(Window *w, bool inExpose)
<< ", animations=" << (timer.nsecsElapsed() - syncTime) / 1000000
<< " - (on Gui thread) " << window;
- Q_QUICK_SG_PROFILE(QQuickProfiler::SceneGraphPolishAndSync, (
- polishTime,
- waitTime - polishTime,
- syncTime - waitTime,
- timer.nsecsElapsed() - syncTime));
-}
-
-QSGThreadedRenderLoop::Window *QSGThreadedRenderLoop::windowForTimer(int timerId) const
-{
- for (int i=0; i<m_windows.size(); ++i) {
- if (m_windows.at(i).timerId == timerId) {
- return const_cast<Window *>(&m_windows.at(i));
- break;
- }
- }
- return 0;
+ Q_QUICK_SG_PROFILE_END(QQuickProfiler::SceneGraphPolishAndSync);
}
bool QSGThreadedRenderLoop::event(QEvent *e)
@@ -1183,15 +1159,8 @@ bool QSGThreadedRenderLoop::event(QEvent *e)
qCDebug(QSG_LOG_RENDERLOOP) << "- ticking non-visual timer";
m_animation_driver->advance();
emit timeToIncubate();
- } else {
- qCDebug(QSG_LOG_RENDERLOOP) << "- polish and sync timer";
- Window *w = windowForTimer(te->timerId());
- if (w)
- polishAndSync(w);
- else
- killTimer(te->timerId());
+ return true;
}
- return true;
}
default:
diff --git a/src/quick/scenegraph/qsgthreadedrenderloop_p.h b/src/quick/scenegraph/qsgthreadedrenderloop_p.h
index 82f314a6af..b3db56e5f9 100644
--- a/src/quick/scenegraph/qsgthreadedrenderloop_p.h
+++ b/src/quick/scenegraph/qsgthreadedrenderloop_p.h
@@ -60,6 +60,8 @@ public:
void update(QQuickWindow *window);
void maybeUpdate(QQuickWindow *window);
+ void handleUpdateRequest(QQuickWindow *window);
+
QSGContext *sceneGraphContext() const;
QSGRenderContext *createRenderContext(QSGContext *) const;
@@ -80,7 +82,6 @@ private:
QQuickWindow *window;
QSGRenderThread *thread;
QSurfaceFormat actualWindowFormat;
- int timerId;
uint updateDuringSync : 1;
uint forceRenderPass : 1;
};
@@ -89,7 +90,6 @@ private:
void releaseResources(Window *window, bool inDestructor);
bool checkAndResetForceUpdate(QQuickWindow *window);
- Window *windowForTimer(int timerId) const;
bool anyoneShowing() const;
void initialize();
@@ -109,7 +109,6 @@ private:
QList<Window> m_windows;
int m_animation_timer;
- int m_exhaust_delay;
bool m_lockedForSync;
};
diff --git a/src/quick/scenegraph/qsgwindowsrenderloop.cpp b/src/quick/scenegraph/qsgwindowsrenderloop.cpp
index 17a9856a6d..9f74e259e3 100644
--- a/src/quick/scenegraph/qsgwindowsrenderloop.cpp
+++ b/src/quick/scenegraph/qsgwindowsrenderloop.cpp
@@ -54,10 +54,14 @@ extern Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_
#define RLDEBUG(x) qCDebug(QSG_LOG_RENDERLOOP) << x;
static QElapsedTimer qsg_render_timer;
-#define QSG_RENDER_TIMING_SAMPLE(sampleName) \
+#define QSG_LOG_TIME_SAMPLE(sampleName) \
qint64 sampleName = 0; \
- if (QSG_LOG_TIME_RENDERLOOP().isDebugEnabled() || QQuickProfiler::profilingSceneGraph()) \
- sampleName = qsg_render_timer.nsecsElapsed()
+ if (QSG_LOG_TIME_RENDERLOOP().isDebugEnabled()) \
+ sampleName = qsg_render_timer.nsecsElapsed(); \
+
+#define QSG_RENDER_TIMING_SAMPLE(frameType, sampleName) \
+ QSG_LOG_TIME_SAMPLE(sampleName) \
+ Q_QUICK_SG_PROFILE_RECORD(frameType);
QSGWindowsRenderLoop::QSGWindowsRenderLoop()
@@ -361,7 +365,8 @@ void QSGWindowsRenderLoop::render()
if (m_animationDriver->isRunning()) {
RLDEBUG("advancing animations");
- QSG_RENDER_TIMING_SAMPLE(time_start);
+ QSG_LOG_TIME_SAMPLE(time_start);
+ Q_QUICK_SG_PROFILE_START(QQuickProfiler::SceneGraphWindowsAnimations);
m_animationDriver->advance();
RLDEBUG("animations advanced");
@@ -369,8 +374,7 @@ void QSGWindowsRenderLoop::render()
"animations ticked in %dms",
int((qsg_render_timer.nsecsElapsed() - time_start)/1000000));
- Q_QUICK_SG_PROFILE(QQuickProfiler::SceneGraphWindowsAnimations, (
- qsg_render_timer.nsecsElapsed() - time_start));
+ Q_QUICK_SG_PROFILE_END(QQuickProfiler::SceneGraphWindowsAnimations);
// It is not given that animations triggered another maybeUpdate()
// and thus another render pass, so to keep things running,
@@ -405,27 +409,29 @@ void QSGWindowsRenderLoop::renderWindow(QQuickWindow *window)
if (!windowData(window))
return;
- QSG_RENDER_TIMING_SAMPLE(time_start);
+ QSG_LOG_TIME_SAMPLE(time_start);
+ Q_QUICK_SG_PROFILE_START(QQuickProfiler::SceneGraphPolishFrame);
RLDEBUG(" - polishing");
d->polishItems();
- QSG_RENDER_TIMING_SAMPLE(time_polished);
-
- Q_QUICK_SG_PROFILE(QQuickProfiler::SceneGraphPolishFrame, (time_polished - time_start));
+ QSG_LOG_TIME_SAMPLE(time_polished);
+ Q_QUICK_SG_PROFILE_SWITCH(QQuickProfiler::SceneGraphPolishFrame,
+ QQuickProfiler::SceneGraphRenderLoopFrame);
emit window->afterAnimating();
RLDEBUG(" - syncing");
d->syncSceneGraph();
- QSG_RENDER_TIMING_SAMPLE(time_synced);
+ QSG_RENDER_TIMING_SAMPLE(QQuickProfiler::SceneGraphRenderLoopFrame, time_synced);
RLDEBUG(" - rendering");
d->renderSceneGraph(window->size());
- QSG_RENDER_TIMING_SAMPLE(time_rendered);
+ QSG_RENDER_TIMING_SAMPLE(QQuickProfiler::SceneGraphRenderLoopFrame, time_rendered);
RLDEBUG(" - swapping");
- m_gl->swapBuffers(window);
- QSG_RENDER_TIMING_SAMPLE(time_swapped);
+ if (!d->customRenderStage || !d->customRenderStage->swap())
+ m_gl->swapBuffers(window);
+ QSG_RENDER_TIMING_SAMPLE(QQuickProfiler::SceneGraphRenderLoopFrame, time_swapped);
RLDEBUG(" - frameDone");
d->fireFrameSwapped();
@@ -438,10 +444,7 @@ void QSGWindowsRenderLoop::renderWindow(QQuickWindow *window)
<< ", swap=" << (time_swapped - time_rendered) / 1000000
<< " - " << window;
- Q_QUICK_SG_PROFILE(QQuickProfiler::SceneGraphRenderLoopFrame, (
- time_synced - time_polished,
- time_rendered - time_synced,
- time_swapped - time_rendered));
+ Q_QUICK_SG_PROFILE_REPORT(QQuickProfiler::SceneGraphRenderLoopFrame);
}
QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/shaders/visualization.frag b/src/quick/scenegraph/shaders/visualization.frag
index 15c81f2447..458d9dde14 100644
--- a/src/quick/scenegraph/shaders/visualization.frag
+++ b/src/quick/scenegraph/shaders/visualization.frag
@@ -1,11 +1,11 @@
uniform lowp vec4 color;
-uniform mediump vec4 tweak; // x,y -> width, height; z -> intensity of ;
+uniform lowp float pattern;
varying mediump vec2 pos;
void main(void)
{
lowp vec4 c = color;
- c.xyz += pow(max(sin(pos.x + pos.y), 0.0), 2.0) * tweak.z * 0.25;
+ c.xyz += pow(max(sin(pos.x + pos.y), 0.0), 2.0) * pattern * 0.25;
gl_FragColor = c;
}
diff --git a/src/quick/scenegraph/shaders/visualization.vert b/src/quick/scenegraph/shaders/visualization.vert
index 591eb12ed6..e110f51c99 100644
--- a/src/quick/scenegraph/shaders/visualization.vert
+++ b/src/quick/scenegraph/shaders/visualization.vert
@@ -2,8 +2,8 @@ attribute highp vec4 v;
uniform highp mat4 matrix;
uniform highp mat4 rotation;
-// w -> apply 3d rotation and projection
-uniform mediump vec4 tweak;
+// set to 1 if projection is enabled
+uniform bool projection;
varying mediump vec2 pos;
@@ -11,7 +11,7 @@ void main()
{
vec4 p = matrix * v;
- if (tweak.w > 0.0) {
+ if (projection) {
vec4 proj = rotation * p;
gl_Position = vec4(proj.x, proj.y, 0, proj.z);
} else {
diff --git a/src/quick/scenegraph/util/qsgatlastexture.cpp b/src/quick/scenegraph/util/qsgatlastexture.cpp
index 5edcb5d67a..cb82d721ca 100644
--- a/src/quick/scenegraph/util/qsgatlastexture.cpp
+++ b/src/quick/scenegraph/util/qsgatlastexture.cpp
@@ -377,10 +377,12 @@ void Atlas::bind(QSGTexture::Filtering filtering)
// Upload all pending images..
for (int i=0; i<m_pending_uploads.size(); ++i) {
- bool profileFrames = QSG_LOG_TIME_TEXTURE().isDebugEnabled() ||
- QQuickProfiler::profilingSceneGraph();
+ bool profileFrames = QSG_LOG_TIME_TEXTURE().isDebugEnabled();
if (profileFrames)
qsg_renderer_timer.start();
+ // Skip bind, convert, swizzle; they're irrelevant
+ Q_QUICK_SG_PROFILE_START(QQuickProfiler::SceneGraphTexturePrepare);
+ Q_QUICK_SG_PROFILE_SKIP(QQuickProfiler::SceneGraphTexturePrepare, 3);
if (m_externalFormat == GL_BGRA &&
!m_use_bgra_fallback) {
@@ -393,12 +395,10 @@ void Atlas::bind(QSGTexture::Filtering filtering)
<< "ms (" << m_pending_uploads.at(i)->image().width() << "x"
<< m_pending_uploads.at(i)->image().height() << ")";
- Q_QUICK_SG_PROFILE(QQuickProfiler::SceneGraphTexturePrepare, (
- 0, // bind (not relevant)
- 0, // convert (not relevant)
- 0, // swizzle (not relevant)
- qsg_renderer_timer.nsecsElapsed(), // (upload all of the above)
- 0)); // mipmap (not used ever...)
+ // Skip mipmap; unused
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphTexturePrepare);
+ Q_QUICK_SG_PROFILE_SKIP(QQuickProfiler::SceneGraphTexturePrepare, 1);
+ Q_QUICK_SG_PROFILE_REPORT(QQuickProfiler::SceneGraphTexturePrepare);
}
GLenum f = filtering == QSGTexture::Nearest ? GL_NEAREST : GL_LINEAR;
diff --git a/src/quick/scenegraph/util/qsgengine_p.h b/src/quick/scenegraph/util/qsgengine_p.h
index 1275ca161e..71906ea149 100644
--- a/src/quick/scenegraph/util/qsgengine_p.h
+++ b/src/quick/scenegraph/util/qsgengine_p.h
@@ -45,8 +45,8 @@ class QSGRenderContext;
class QSGEnginePrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QSGEngine)
-
public:
+ static QSGEnginePrivate *get(QSGEngine *engine) { return engine->d_func(); }
QSGEnginePrivate();
QScopedPointer<QSGContext> sgContext;
diff --git a/src/quick/scenegraph/util/qsgsimpletexturenode.cpp b/src/quick/scenegraph/util/qsgsimpletexturenode.cpp
index 1fbeba83bc..34e00e0b01 100644
--- a/src/quick/scenegraph/util/qsgsimpletexturenode.cpp
+++ b/src/quick/scenegraph/util/qsgsimpletexturenode.cpp
@@ -42,12 +42,13 @@ class QSGSimpleTextureNodePrivate : public QSGGeometryNodePrivate
public:
QSGSimpleTextureNodePrivate()
: QSGGeometryNodePrivate()
- , m_texCoordMode(QSGSimpleTextureNode::NoTransform)
+ , texCoordMode(QSGSimpleTextureNode::NoTransform)
, isAtlasTexture(false)
, ownsTexture(false)
{}
- QSGSimpleTextureNode::TextureCoordinatesTransformMode m_texCoordMode;
+ QRectF sourceRect;
+ QSGSimpleTextureNode::TextureCoordinatesTransformMode texCoordMode;
uint isAtlasTexture : 1;
uint ownsTexture : 1;
};
@@ -55,13 +56,16 @@ public:
static void qsgsimpletexturenode_update(QSGGeometry *g,
QSGTexture *texture,
const QRectF &rect,
+ QRectF sourceRect,
QSGSimpleTextureNode::TextureCoordinatesTransformMode texCoordMode)
{
if (!texture)
return;
- QSize ts = texture->textureSize();
- QRectF sourceRect(0, 0, ts.width(), ts.height());
+ if (!sourceRect.width() || !sourceRect.height()) {
+ QSize ts = texture->textureSize();
+ sourceRect = QRectF(0, 0, ts.width(), ts.height());
+ }
// Maybe transform the texture coordinates
if (texCoordMode.testFlag(QSGSimpleTextureNode::MirrorHorizontally)) {
@@ -151,7 +155,7 @@ void QSGSimpleTextureNode::setRect(const QRectF &r)
return;
m_rect = r;
Q_D(QSGSimpleTextureNode);
- qsgsimpletexturenode_update(&m_geometry, texture(), m_rect, d->m_texCoordMode);
+ qsgsimpletexturenode_update(&m_geometry, texture(), m_rect, d->sourceRect, d->texCoordMode);
markDirty(DirtyGeometry);
}
@@ -172,6 +176,41 @@ QRectF QSGSimpleTextureNode::rect() const
}
/*!
+ Sets the source rect of this texture node to \a r.
+
+ \since 5.5
+ */
+void QSGSimpleTextureNode::setSourceRect(const QRectF &r)
+{
+ Q_D(QSGSimpleTextureNode);
+ if (d->sourceRect == r)
+ return;
+ d->sourceRect = r;
+ qsgsimpletexturenode_update(&m_geometry, texture(), m_rect, d->sourceRect, d->texCoordMode);
+ markDirty(DirtyGeometry);
+}
+
+/*!
+ \fn void QSGSimpleTextureNode::setSourceRect(qreal x, qreal y, qreal w, qreal h)
+ \overload
+ \since 5.5
+
+ Sets the rectangle of this texture node to show its texture from (\a x, \a y) and
+ have width \a w and height \a h relatively to the QSGTexture::textureSize.
+ */
+
+/*!
+ Returns the source rect of this texture node.
+
+ \since 5.5
+ */
+QRectF QSGSimpleTextureNode::sourceRect() const
+{
+ Q_D(const QSGSimpleTextureNode);
+ return d->sourceRect;
+}
+
+/*!
Sets the texture of this texture node to \a texture.
Use setOwnsTexture() to set whether the node should take
@@ -187,7 +226,7 @@ void QSGSimpleTextureNode::setTexture(QSGTexture *texture)
m_material.setTexture(texture);
m_opaque_material.setTexture(texture);
Q_D(QSGSimpleTextureNode);
- qsgsimpletexturenode_update(&m_geometry, texture, m_rect, d->m_texCoordMode);
+ qsgsimpletexturenode_update(&m_geometry, texture, m_rect, d->sourceRect, d->texCoordMode);
DirtyState dirty = DirtyMaterial;
// It would be tempting to skip the extra bit here and instead use
@@ -236,10 +275,10 @@ QSGTexture *QSGSimpleTextureNode::texture() const
void QSGSimpleTextureNode::setTextureCoordinatesTransform(QSGSimpleTextureNode::TextureCoordinatesTransformMode mode)
{
Q_D(QSGSimpleTextureNode);
- if (d->m_texCoordMode == mode)
+ if (d->texCoordMode == mode)
return;
- d->m_texCoordMode = mode;
- qsgsimpletexturenode_update(&m_geometry, texture(), m_rect, d->m_texCoordMode);
+ d->texCoordMode = mode;
+ qsgsimpletexturenode_update(&m_geometry, texture(), m_rect, d->sourceRect, d->texCoordMode);
markDirty(DirtyMaterial);
}
@@ -251,7 +290,7 @@ void QSGSimpleTextureNode::setTextureCoordinatesTransform(QSGSimpleTextureNode::
QSGSimpleTextureNode::TextureCoordinatesTransformMode QSGSimpleTextureNode::textureCoordinatesTransform() const
{
Q_D(const QSGSimpleTextureNode);
- return d->m_texCoordMode;
+ return d->texCoordMode;
}
/*!
diff --git a/src/quick/scenegraph/util/qsgsimpletexturenode.h b/src/quick/scenegraph/util/qsgsimpletexturenode.h
index 56f5c5a0df..60fa445fe0 100644
--- a/src/quick/scenegraph/util/qsgsimpletexturenode.h
+++ b/src/quick/scenegraph/util/qsgsimpletexturenode.h
@@ -52,6 +52,10 @@ public:
inline void setRect(qreal x, qreal y, qreal w, qreal h) { setRect(QRectF(x, y, w, h)); }
QRectF rect() const;
+ void setSourceRect(const QRectF &r);
+ inline void setSourceRect(qreal x, qreal y, qreal w, qreal h) { setSourceRect(QRectF(x, y, w, h)); }
+ QRectF sourceRect() const;
+
void setTexture(QSGTexture *texture);
QSGTexture *texture() const;
diff --git a/src/quick/scenegraph/util/qsgtexture.cpp b/src/quick/scenegraph/util/qsgtexture.cpp
index fc5050014e..673323baa2 100644
--- a/src/quick/scenegraph/util/qsgtexture.cpp
+++ b/src/quick/scenegraph/util/qsgtexture.cpp
@@ -633,10 +633,12 @@ void QSGPlainTexture::bind()
m_dirty_texture = false;
- bool profileFrames = QSG_LOG_TIME_TEXTURE().isDebugEnabled() ||
- QQuickProfiler::profilingSceneGraph();
+ bool profileFrames = QSG_LOG_TIME_TEXTURE().isDebugEnabled();
if (profileFrames)
qsg_renderer_timer.start();
+ Q_QUICK_SG_PROFILE_START_SYNCHRONIZED(QQuickProfiler::SceneGraphTexturePrepare,
+ QQuickProfiler::SceneGraphTextureDeletion);
+
if (m_image.isNull()) {
if (m_texture_id && m_owns_texture) {
@@ -645,8 +647,7 @@ void QSGPlainTexture::bind()
(int) qsg_renderer_timer.elapsed(),
m_texture_size.width(),
m_texture_size.height());
- Q_QUICK_SG_PROFILE(QQuickProfiler::SceneGraphTextureDeletion, (
- qsg_renderer_timer.nsecsElapsed()));
+ Q_QUICK_SG_PROFILE_END(QQuickProfiler::SceneGraphTextureDeletion);
}
m_texture_id = 0;
m_texture_size = QSize();
@@ -662,6 +663,7 @@ void QSGPlainTexture::bind()
qint64 bindTime = 0;
if (profileFrames)
bindTime = qsg_renderer_timer.nsecsElapsed();
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphTexturePrepare);
// ### TODO: check for out-of-memory situations...
@@ -692,6 +694,7 @@ void QSGPlainTexture::bind()
qint64 convertTime = 0;
if (profileFrames)
convertTime = qsg_renderer_timer.nsecsElapsed();
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphTexturePrepare);
updateBindOptions(m_dirty_bind_options);
@@ -734,12 +737,14 @@ void QSGPlainTexture::bind()
qint64 swizzleTime = 0;
if (profileFrames)
swizzleTime = qsg_renderer_timer.nsecsElapsed();
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphTexturePrepare);
funcs->glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, m_texture_size.width(), m_texture_size.height(), 0, externalFormat, GL_UNSIGNED_BYTE, tmp.constBits());
qint64 uploadTime = 0;
if (profileFrames)
uploadTime = qsg_renderer_timer.nsecsElapsed();
+ Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphTexturePrepare);
if (mipmapFiltering() != QSGTexture::None) {
funcs->glGenerateMipmap(GL_TEXTURE_2D);
@@ -762,13 +767,7 @@ void QSGPlainTexture::bind()
int((mipmapTime - uploadTime)/1000000),
m_texture_size != m_image.size() ? " (scaled to GL_MAX_TEXTURE_SIZE)" : "");
}
-
- Q_QUICK_SG_PROFILE(QQuickProfiler::SceneGraphTexturePrepare, (
- bindTime,
- convertTime - bindTime,
- swizzleTime - convertTime,
- uploadTime - swizzleTime,
- qsg_renderer_timer.nsecsElapsed() - uploadTime));
+ Q_QUICK_SG_PROFILE_END(QQuickProfiler::SceneGraphTexturePrepare);
m_texture_rect = QRectF(0, 0, 1, 1);
diff --git a/src/quick/scenegraph/util/qsgvertexcolormaterial.cpp b/src/quick/scenegraph/util/qsgvertexcolormaterial.cpp
index 3a84bf6219..be24ebe76d 100644
--- a/src/quick/scenegraph/util/qsgvertexcolormaterial.cpp
+++ b/src/quick/scenegraph/util/qsgvertexcolormaterial.cpp
@@ -99,9 +99,12 @@ void QSGVertexColorMaterialShader::initialize()
The geometry to be rendered with vertex color must have the following layout. Attribute
position 0 must contain vertices. Attribute position 1 must contain colors, a tuple of
4 values with RGBA layout. Both floats in the range of 0 to 1 and unsigned bytes in
- the range 0 to 255 are valid for the color values. The
- QSGGeometry::defaultAttributes_ColoredPoint2D() constructs an attribute set
- compatible with this material.
+ the range 0 to 255 are valid for the color values.
+
+ \note The rendering pipeline expects pixels with premultiplied alpha.
+
+ QSGGeometry::defaultAttributes_ColoredPoint2D() can be used to construct an attribute
+ set that is compatible with this material.
The vertex color material respects both current opacity and current matrix when
updating it's rendering state.
diff --git a/src/quick/util/qquickanimatorjob.cpp b/src/quick/util/qquickanimatorjob.cpp
index f29ec49b9f..536413bba9 100644
--- a/src/quick/util/qquickanimatorjob.cpp
+++ b/src/quick/util/qquickanimatorjob.cpp
@@ -405,21 +405,33 @@ void QQuickOpacityAnimatorJob::initialize(QQuickAnimatorController *controller)
m_opacityNode = d->opacityNode();
if (!m_opacityNode) {
m_opacityNode = new QSGOpacityNode();
- d->extra.value().opacityNode = m_opacityNode;
-
- QSGNode *child = d->clipNode();
- if (!child)
- child = d->rootNode();
- if (!child)
- child = d->groupNode;
- if (child) {
+ /* The item node subtree is like this
+ *
+ * itemNode
+ * (opacityNode) optional
+ * (clipNode) optional
+ * (rootNode) optional
+ * children / paintNode
+ *
+ * If the opacity node doesn't exist, we need to insert it into
+ * the hierarchy between itemNode and clipNode or rootNode. If
+ * neither clip or root exists, we need to reparent all children
+ * from itemNode to opacityNode.
+ */
+ QSGNode *iNode = d->itemNode();
+ QSGNode *child = d->childContainerNode();
+ if (child != iNode) {
if (child->parent())
child->parent()->removeChildNode(child);
m_opacityNode->appendChildNode(child);
+ iNode->appendChildNode(m_opacityNode);
+ } else {
+ iNode->reparentChildNodesTo(m_opacityNode);
+ iNode->appendChildNode(m_opacityNode);
}
- d->itemNode()->appendChildNode(m_opacityNode);
+ d->extra.value().opacityNode = m_opacityNode;
}
}
diff --git a/src/quick/util/qquickglobal.cpp b/src/quick/util/qquickglobal.cpp
index 139bae4038..c75c87f8ef 100644
--- a/src/quick/util/qquickglobal.cpp
+++ b/src/quick/util/qquickglobal.cpp
@@ -261,13 +261,11 @@ public:
return QMatrix4x4();
}
- static QFont fontFromObject(QQmlV4Handle object, QV8Engine *e, bool *ok)
+ static QFont fontFromObject(QQmlV4Handle object, QV4::ExecutionEngine *v4, bool *ok)
{
- Q_UNUSED(e);
-
- if (ok) *ok = false;
+ if (ok)
+ *ok = false;
QFont retn;
- QV4::ExecutionEngine *v4 = QV8Engine::getV4(e);
QV4::Scope scope(v4);
QV4::ScopedObject obj(scope, object);
if (!obj) {
@@ -278,17 +276,17 @@ public:
QV4::ScopedString s(scope);
- QV4::ScopedValue vbold(scope, obj->get((s = v4->newString(QStringLiteral("bold"))).getPointer()));
- QV4::ScopedValue vcap(scope, obj->get((s = v4->newString(QStringLiteral("capitalization"))).getPointer()));
- QV4::ScopedValue vfam(scope, obj->get((s = v4->newString(QStringLiteral("family"))).getPointer()));
- QV4::ScopedValue vital(scope, obj->get((s = v4->newString(QStringLiteral("italic"))).getPointer()));
- QV4::ScopedValue vlspac(scope, obj->get((s = v4->newString(QStringLiteral("letterSpacing"))).getPointer()));
- QV4::ScopedValue vpixsz(scope, obj->get((s = v4->newString(QStringLiteral("pixelSize"))).getPointer()));
- QV4::ScopedValue vpntsz(scope, obj->get((s = v4->newString(QStringLiteral("pointSize"))).getPointer()));
- QV4::ScopedValue vstrk(scope, obj->get((s = v4->newString(QStringLiteral("strikeout"))).getPointer()));
- QV4::ScopedValue vundl(scope, obj->get((s = v4->newString(QStringLiteral("underline"))).getPointer()));
- QV4::ScopedValue vweight(scope, obj->get((s = v4->newString(QStringLiteral("weight"))).getPointer()));
- QV4::ScopedValue vwspac(scope, obj->get((s = v4->newString(QStringLiteral("wordSpacing"))).getPointer()));
+ QV4::ScopedValue vbold(scope, obj->get((s = v4->newString(QStringLiteral("bold")))));
+ QV4::ScopedValue vcap(scope, obj->get((s = v4->newString(QStringLiteral("capitalization")))));
+ QV4::ScopedValue vfam(scope, obj->get((s = v4->newString(QStringLiteral("family")))));
+ QV4::ScopedValue vital(scope, obj->get((s = v4->newString(QStringLiteral("italic")))));
+ QV4::ScopedValue vlspac(scope, obj->get((s = v4->newString(QStringLiteral("letterSpacing")))));
+ QV4::ScopedValue vpixsz(scope, obj->get((s = v4->newString(QStringLiteral("pixelSize")))));
+ QV4::ScopedValue vpntsz(scope, obj->get((s = v4->newString(QStringLiteral("pointSize")))));
+ QV4::ScopedValue vstrk(scope, obj->get((s = v4->newString(QStringLiteral("strikeout")))));
+ QV4::ScopedValue vundl(scope, obj->get((s = v4->newString(QStringLiteral("underline")))));
+ QV4::ScopedValue vweight(scope, obj->get((s = v4->newString(QStringLiteral("weight")))));
+ QV4::ScopedValue vwspac(scope, obj->get((s = v4->newString(QStringLiteral("wordSpacing")))));
// pull out the values, set ok to true if at least one valid field is given.
if (vbold->isBoolean()) {
@@ -339,10 +337,10 @@ public:
return retn;
}
- static QMatrix4x4 matrix4x4FromObject(QQmlV4Handle object, QV8Engine *e, bool *ok)
+ static QMatrix4x4 matrix4x4FromObject(QQmlV4Handle object, QV4::ExecutionEngine *v4, bool *ok)
{
- if (ok) *ok = false;
- QV4::ExecutionEngine *v4 = QV8Engine::getV4(e);
+ if (ok)
+ *ok = false;
QV4::Scope scope(v4);
QV4::ScopedArrayObject array(scope, object);
if (!array)
@@ -364,35 +362,28 @@ public:
return QMatrix4x4(matVals);
}
- template<typename T>
- bool typedCreate(QQmlValueType *&v)
- {
- v = new T;
- return true;
- }
-
- bool create(int type, QQmlValueType *&v)
+ const QMetaObject *getMetaObjectForMetaType(int type)
{
switch (type) {
case QMetaType::QColor:
- return typedCreate<QQuickColorValueType>(v);
+ return &QQuickColorValueType::staticMetaObject;
case QMetaType::QFont:
- return typedCreate<QQuickFontValueType>(v);
+ return &QQuickFontValueType::staticMetaObject;
case QMetaType::QVector2D:
- return typedCreate<QQuickVector2DValueType>(v);
+ return &QQuickVector2DValueType::staticMetaObject;
case QMetaType::QVector3D:
- return typedCreate<QQuickVector3DValueType>(v);
+ return &QQuickVector3DValueType::staticMetaObject;
case QMetaType::QVector4D:
- return typedCreate<QQuickVector4DValueType>(v);
+ return &QQuickVector4DValueType::staticMetaObject;
case QMetaType::QQuaternion:
- return typedCreate<QQuickQuaternionValueType>(v);
+ return &QQuickQuaternionValueType::staticMetaObject;
case QMetaType::QMatrix4x4:
- return typedCreate<QQuickMatrix4x4ValueType>(v);
+ return &QQuickMatrix4x4ValueType::staticMetaObject;
default:
break;
}
- return false;
+ return 0;
}
template<typename T>
@@ -711,9 +702,8 @@ public:
return false;
}
- bool variantFromJsObject(int type, QQmlV4Handle object, QV8Engine *e, QVariant *v)
+ bool variantFromJsObject(int type, QQmlV4Handle object, QV4::ExecutionEngine *v4, QVariant *v)
{
- QV4::ExecutionEngine *v4 = QV8Engine::getV4(e);
QV4::Scope scope(v4);
#ifndef QT_NO_DEBUG
QV4::ScopedObject obj(scope, object);
@@ -722,10 +712,10 @@ public:
bool ok = false;
switch (type) {
case QMetaType::QFont:
- *v = QVariant::fromValue(fontFromObject(object, e, &ok));
+ *v = QVariant::fromValue(fontFromObject(object, v4, &ok));
break;
case QMetaType::QMatrix4x4:
- *v = QVariant::fromValue(matrix4x4FromObject(object, e, &ok));
+ *v = QVariant::fromValue(matrix4x4FromObject(object, v4, &ok));
default: break;
}
diff --git a/src/quick/util/qquickpixmapcache.cpp b/src/quick/util/qquickpixmapcache.cpp
index 22ed9b7486..a2a8ef03c7 100644
--- a/src/quick/util/qquickpixmapcache.cpp
+++ b/src/quick/util/qquickpixmapcache.cpp
@@ -831,8 +831,10 @@ void QQuickPixmapStore::unreferencePixmap(QQuickPixmapData *data)
shrinkCache(-1); // Shrink the cache in case it has become larger than cache_limit
- if (m_timerId == -1 && m_unreferencedPixmaps && !m_destroying)
+ if (m_timerId == -1 && m_unreferencedPixmaps
+ && !m_destroying && !QCoreApplication::closingDown()) {
m_timerId = startTimer(CACHE_EXPIRE_TIME * 1000);
+ }
}
void QQuickPixmapStore::referencePixmap(QQuickPixmapData *data)
diff --git a/src/quick/util/qquickprofiler.cpp b/src/quick/util/qquickprofiler.cpp
index 3b34b7550b..c4441ed5dd 100644
--- a/src/quick/util/qquickprofiler.cpp
+++ b/src/quick/util/qquickprofiler.cpp
@@ -80,7 +80,7 @@ void QQuickProfilerData::toByteArrays(QList<QByteArray> &messages) const
// RendererFrame: preprocessTime, updateTime, bindingTime, renderTime
case QQuickProfiler::SceneGraphRendererFrame: ds << subtime_1 << subtime_2 << subtime_3 << subtime_4; break;
// AdaptationLayerFrame: glyphCount (which is an integer), glyphRenderTime, glyphStoreTime
- case QQuickProfiler::SceneGraphAdaptationLayerFrame: ds << subtime_1 << subtime_2 << subtime_3; break;
+ case QQuickProfiler::SceneGraphAdaptationLayerFrame: ds << subtime_3 << subtime_1 << subtime_2; break;
// ContextFrame: compiling material time
case QQuickProfiler::SceneGraphContextFrame: ds << subtime_1; break;
// RenderLoop: syncTime, renderTime, swapTime
diff --git a/src/quick/util/qquickprofiler_p.h b/src/quick/util/qquickprofiler_p.h
index 62e23cd393..ea37558741 100644
--- a/src/quick/util/qquickprofiler_p.h
+++ b/src/quick/util/qquickprofiler_p.h
@@ -51,6 +51,7 @@
#include <QUrl>
#include <QSize>
#include <QMutex>
+#include <QThreadStorage>
QT_BEGIN_NAMESPACE
@@ -63,9 +64,38 @@ QT_BEGIN_NAMESPACE
#define Q_QUICK_PROFILE(feature, Method)\
Q_QUICK_PROFILE_IF_ENABLED(feature, QQuickProfiler::Method)
-#define Q_QUICK_SG_PROFILE(Type, Params)\
+#define Q_QUICK_SG_PROFILE_START(Type)\
Q_QUICK_PROFILE_IF_ENABLED(QQuickProfiler::ProfileSceneGraph,\
- (QQuickProfiler::sceneGraphFrame<Type> Params))
+ (QQuickProfiler::startSceneGraphFrame<Type>()))
+
+#define Q_QUICK_SG_PROFILE_RECORD(Type)\
+ Q_QUICK_PROFILE_IF_ENABLED(QQuickProfiler::ProfileSceneGraph,\
+ (QQuickProfiler::recordSceneGraphTimestamp<Type>()))
+
+#define Q_QUICK_SG_PROFILE_SKIP(Type, Skip)\
+ Q_QUICK_PROFILE_IF_ENABLED(QQuickProfiler::ProfileSceneGraph,\
+ (QQuickProfiler::skipSceneGraphTimestamps<Type, Skip>()))
+
+#define Q_QUICK_SG_PROFILE_START_SYNCHRONIZED(Type1, Type2)\
+ Q_QUICK_PROFILE_IF_ENABLED(QQuickProfiler::ProfileSceneGraph,\
+ (QQuickProfiler::startSceneGraphFrame<Type1, Type2>()))
+
+#define Q_QUICK_SG_PROFILE_SWITCH(Type1, Type2) \
+ Q_QUICK_PROFILE_IF_ENABLED(QQuickProfiler::ProfileSceneGraph,\
+ (QQuickProfiler::reportSceneGraphFrame<Type1, true, Type2>()))
+
+#define Q_QUICK_SG_PROFILE_REPORT(Type)\
+ Q_QUICK_PROFILE_IF_ENABLED(QQuickProfiler::ProfileSceneGraph,\
+ (QQuickProfiler::reportSceneGraphFrame<Type, false>()))
+
+#define Q_QUICK_SG_PROFILE_END(Type)\
+ Q_QUICK_PROFILE_IF_ENABLED(QQuickProfiler::ProfileSceneGraph,\
+ (QQuickProfiler::reportSceneGraphFrame<Type, true>()))
+
+#define Q_QUICK_SG_PROFILE_END_WITH_PAYLOAD(Type, Payload)\
+ Q_QUICK_PROFILE_IF_ENABLED(QQuickProfiler::ProfileSceneGraph,\
+ (QQuickProfiler::reportSceneGraphFrame<Type, true>(Payload)))
+
#define Q_QUICK_INPUT_PROFILE(Method)\
Q_QUICK_PROFILE(QQuickProfiler::ProfileInputEvents, Method)
@@ -136,6 +166,39 @@ struct Q_AUTOTEST_EXPORT QQuickProfilerData
Q_DECLARE_TYPEINFO(QQuickProfilerData, Q_MOVABLE_TYPE);
+class QQuickProfilerSceneGraphData : public QQmlProfilerDefinitions {
+private:
+ static const uint s_numSceneGraphTimings = 5;
+
+ template<uint size>
+ struct TimingData {
+ qint64 values[size][s_numSceneGraphTimings + 1];
+ int offsets[size];
+ };
+
+ QThreadStorage<TimingData<NumRenderThreadFrameTypes> > renderThreadTimings;
+ TimingData<NumGUIThreadFrameTypes> guiThreadTimings;
+
+public:
+ template<SceneGraphFrameType type>
+ qint64 *timings()
+ {
+ if (type < NumRenderThreadFrameTypes)
+ return renderThreadTimings.localData().values[type];
+ else
+ return guiThreadTimings.values[type - NumRenderThreadFrameTypes];
+ }
+
+ template<SceneGraphFrameType type>
+ int &offset()
+ {
+ if (type < NumRenderThreadFrameTypes)
+ return renderThreadTimings.localData().offsets[type];
+ else
+ return guiThreadTimings.offsets[type - NumRenderThreadFrameTypes];
+ }
+};
+
class Q_QUICK_PRIVATE_EXPORT QQuickProfiler : public QQmlAbstractProfilerAdapter {
Q_OBJECT
public:
@@ -163,12 +226,62 @@ public:
}
}
+ template<SceneGraphFrameType FrameType1, SceneGraphFrameType FrameType2>
+ static void startSceneGraphFrame()
+ {
+ startSceneGraphFrame<FrameType1>();
+ s_instance->m_sceneGraphData.offset<FrameType2>() = 0;
+ s_instance->m_sceneGraphData.timings<FrameType2>()[0] =
+ s_instance->m_sceneGraphData.timings<FrameType1>()[0];
+ }
+
template<SceneGraphFrameType FrameType>
- static void sceneGraphFrame(qint64 value1, qint64 value2 = -1, qint64 value3 = -1,
- qint64 value4 = -1, qint64 value5 = -1)
+ static void startSceneGraphFrame()
+ {
+ s_instance->m_sceneGraphData.offset<FrameType>() = 0;
+ s_instance->m_sceneGraphData.timings<FrameType>()[0] = s_instance->timestamp();
+ }
+
+ template<SceneGraphFrameType FrameType>
+ static void recordSceneGraphTimestamp()
+ {
+ s_instance->m_sceneGraphData.timings<FrameType>()
+ [++s_instance->m_sceneGraphData.offset<FrameType>()] = s_instance->timestamp();
+ }
+
+ template<SceneGraphFrameType FrameType, uint Skip>
+ static void skipSceneGraphTimestamps()
+ {
+ qint64 *timings = s_instance->m_sceneGraphData.timings<FrameType>();
+ const qint64 last = timings[s_instance->m_sceneGraphData.offset<FrameType>()];
+ for (uint i = 0; i < Skip; ++i)
+ timings[++s_instance->m_sceneGraphData.offset<FrameType>()] = last;
+ }
+
+ template<SceneGraphFrameType FrameType, bool Record>
+ static void reportSceneGraphFrame(quint64 payload = -1)
+ {
+ qint64 *timings = s_instance->m_sceneGraphData.timings<FrameType>();
+ int &offset = s_instance->m_sceneGraphData.offset<FrameType>();
+ if (Record)
+ timings[++offset] = s_instance->timestamp();
+ s_instance->processMessage(QQuickProfilerData(
+ timings[offset], 1 << SceneGraphFrame, 1 << FrameType,
+ offset > 0 ? timings[1] - timings[0] : payload,
+ offset > 1 ? timings[2] - timings[1] : payload,
+ offset > 2 ? timings[3] - timings[2] : payload,
+ offset > 3 ? timings[4] - timings[3] : payload,
+ offset > 4 ? timings[5] - timings[4] : payload));
+ }
+
+ template<SceneGraphFrameType FrameType, bool Record, SceneGraphFrameType SwitchTo>
+ static void reportSceneGraphFrame(quint64 payload = -1)
{
- s_instance->processMessage(QQuickProfilerData(s_instance->timestamp(), 1 << SceneGraphFrame,
- 1 << FrameType, value1, value2, value3, value4, value5));
+ reportSceneGraphFrame<FrameType, Record>(payload);
+ s_instance->m_sceneGraphData.offset<SwitchTo>() = 0;
+ s_instance->m_sceneGraphData.timings<SwitchTo>()[0] =
+ s_instance->m_sceneGraphData.timings<FrameType>()
+ [s_instance->m_sceneGraphData.offset<FrameType>()];
}
template<PixmapEventType PixmapState>
@@ -215,6 +328,7 @@ protected:
QMutex m_dataMutex;
QElapsedTimer m_timer;
QVarLengthArray<QQuickProfilerData> m_data;
+ QQuickProfilerSceneGraphData m_sceneGraphData;
QQuickProfiler(QQmlProfilerService *service);
diff --git a/src/quick/util/qquickvaluetypes.cpp b/src/quick/util/qquickvaluetypes.cpp
index 862e5cee55..2e4fec0599 100644
--- a/src/quick/util/qquickvaluetypes.cpp
+++ b/src/quick/util/qquickvaluetypes.cpp
@@ -48,11 +48,6 @@ namespace QQuickValueTypes {
}
}
-QQuickColorValueType::QQuickColorValueType(QObject *parent)
- : QQmlValueTypeBase<QColor>(QMetaType::QColor, parent)
-{
-}
-
QString QQuickColorValueType::toString() const
{
// to maintain behaviour with QtQuick 1.0, we just output normal toString() value.
@@ -99,26 +94,11 @@ void QQuickColorValueType::setA(qreal a)
v.setAlphaF(a);
}
-
-QQuickVector2DValueType::QQuickVector2DValueType(QObject *parent)
- : QQmlValueTypeBase<QVector2D>(QMetaType::QVector2D, parent)
-{
-}
-
QString QQuickVector2DValueType::toString() const
{
return QString(QLatin1String("QVector2D(%1, %2)")).arg(v.x()).arg(v.y());
}
-bool QQuickVector2DValueType::isEqual(const QVariant &other) const
-{
- if (other.userType() != QMetaType::QVector2D)
- return false;
-
- QVector2D otherVector = other.value<QVector2D>();
- return (v == otherVector);
-}
-
qreal QQuickVector2DValueType::x() const
{
return v.x();
@@ -199,26 +179,11 @@ bool QQuickVector2DValueType::fuzzyEquals(const QVector2D &vec) const
return qFuzzyCompare(v, vec);
}
-
-QQuickVector3DValueType::QQuickVector3DValueType(QObject *parent)
- : QQmlValueTypeBase<QVector3D>(QMetaType::QVector3D, parent)
-{
-}
-
QString QQuickVector3DValueType::toString() const
{
return QString(QLatin1String("QVector3D(%1, %2, %3)")).arg(v.x()).arg(v.y()).arg(v.z());
}
-bool QQuickVector3DValueType::isEqual(const QVariant &other) const
-{
- if (other.userType() != QMetaType::QVector3D)
- return false;
-
- QVector3D otherVector = other.value<QVector3D>();
- return (v == otherVector);
-}
-
qreal QQuickVector3DValueType::x() const
{
return v.x();
@@ -321,26 +286,11 @@ bool QQuickVector3DValueType::fuzzyEquals(const QVector3D &vec) const
return qFuzzyCompare(v, vec);
}
-
-QQuickVector4DValueType::QQuickVector4DValueType(QObject *parent)
- : QQmlValueTypeBase<QVector4D>(QMetaType::QVector4D, parent)
-{
-}
-
QString QQuickVector4DValueType::toString() const
{
return QString(QLatin1String("QVector4D(%1, %2, %3, %4)")).arg(v.x()).arg(v.y()).arg(v.z()).arg(v.w());
}
-bool QQuickVector4DValueType::isEqual(const QVariant &other) const
-{
- if (other.userType() != QMetaType::QVector4D)
- return false;
-
- QVector4D otherVector = other.value<QVector4D>();
- return (v == otherVector);
-}
-
qreal QQuickVector4DValueType::x() const
{
return v.x();
@@ -450,11 +400,6 @@ bool QQuickVector4DValueType::fuzzyEquals(const QVector4D &vec) const
return qFuzzyCompare(v, vec);
}
-QQuickQuaternionValueType::QQuickQuaternionValueType(QObject *parent)
- : QQmlValueTypeBase<QQuaternion>(QMetaType::QQuaternion, parent)
-{
-}
-
QString QQuickQuaternionValueType::toString() const
{
return QString(QLatin1String("QQuaternion(%1, %2, %3, %4)")).arg(v.scalar()).arg(v.x()).arg(v.y()).arg(v.z());
@@ -500,12 +445,6 @@ void QQuickQuaternionValueType::setZ(qreal z)
v.setZ(z);
}
-
-QQuickMatrix4x4ValueType::QQuickMatrix4x4ValueType(QObject *parent)
- : QQmlValueTypeBase<QMatrix4x4>(QMetaType::QMatrix4x4, parent)
-{
-}
-
QMatrix4x4 QQuickMatrix4x4ValueType::times(const QMatrix4x4 &m) const
{
return v * m;
@@ -579,38 +518,6 @@ bool QQuickMatrix4x4ValueType::fuzzyEquals(const QMatrix4x4 &m) const
return qFuzzyCompare(v, m);
}
-QString QQuickMatrix4x4ValueType::toString() const
-{
- return QString(QLatin1String("QMatrix4x4(%1, %2, %3, %4, %5, %6, %7, %8, %9, %10, %11, %12, %13, %14, %15, %16)"))
- .arg(v(0, 0)).arg(v(0, 1)).arg(v(0, 2)).arg(v(0, 3))
- .arg(v(1, 0)).arg(v(1, 1)).arg(v(1, 2)).arg(v(1, 3))
- .arg(v(2, 0)).arg(v(2, 1)).arg(v(2, 2)).arg(v(2, 3))
- .arg(v(3, 0)).arg(v(3, 1)).arg(v(3, 2)).arg(v(3, 3));
-}
-
-bool QQuickMatrix4x4ValueType::isEqual(const QVariant &other) const
-{
- if (other.userType() != qMetaTypeId<QMatrix4x4>())
- return false;
-
- QMatrix4x4 otherMatrix = other.value<QMatrix4x4>();
- return (v == otherMatrix);
-
-}
-
-QQuickFontValueType::QQuickFontValueType(QObject *parent)
- : QQmlValueTypeBase<QFont>(QMetaType::QFont, parent),
- pixelSizeSet(false),
- pointSizeSet(false)
-{
-}
-
-void QQuickFontValueType::onLoad()
-{
- pixelSizeSet = false;
- pointSizeSet = false;
-}
-
QString QQuickFontValueType::toString() const
{
return QString(QLatin1String("QFont(%1)")).arg(v.toString());
@@ -689,34 +596,27 @@ void QQuickFontValueType::setStrikeout(bool b)
qreal QQuickFontValueType::pointSize() const
{
if (v.pointSizeF() == -1) {
- if (dpi.isNull)
- dpi = qt_defaultDpi();
- return v.pixelSize() * qreal(72.) / qreal(dpi);
+ return v.pixelSize() * qreal(72.) / qreal(qt_defaultDpi());
}
return v.pointSizeF();
}
void QQuickFontValueType::setPointSize(qreal size)
{
- if (pixelSizeSet) {
+ if ((v.resolve() & QFont::SizeResolved) && v.pixelSize() != -1) {
qWarning() << "Both point size and pixel size set. Using pixel size.";
return;
}
if (size >= 0.0) {
- pointSizeSet = true;
v.setPointSizeF(size);
- } else {
- pointSizeSet = false;
}
}
int QQuickFontValueType::pixelSize() const
{
if (v.pixelSize() == -1) {
- if (dpi.isNull)
- dpi = qt_defaultDpi();
- return (v.pointSizeF() * dpi) / qreal(72.);
+ return (v.pointSizeF() * qt_defaultDpi()) / qreal(72.);
}
return v.pixelSize();
}
@@ -724,12 +624,9 @@ int QQuickFontValueType::pixelSize() const
void QQuickFontValueType::setPixelSize(int size)
{
if (size >0) {
- if (pointSizeSet)
+ if ((v.resolve() & QFont::SizeResolved) && v.pointSizeF() != -1)
qWarning() << "Both point size and pixel size set. Using pixel size.";
v.setPixelSize(size);
- pixelSizeSet = true;
- } else {
- pixelSizeSet = false;
}
}
diff --git a/src/quick/util/qquickvaluetypes_p.h b/src/quick/util/qquickvaluetypes_p.h
index d6546fba36..7bd6d71dce 100644
--- a/src/quick/util/qquickvaluetypes_p.h
+++ b/src/quick/util/qquickvaluetypes_p.h
@@ -54,17 +54,16 @@ void registerValueTypes();
}
-class Q_AUTOTEST_EXPORT QQuickColorValueType : public QQmlValueTypeBase<QColor>
+class QQuickColorValueType
{
+ QColor v;
Q_PROPERTY(qreal r READ r WRITE setR FINAL)
Q_PROPERTY(qreal g READ g WRITE setG FINAL)
Q_PROPERTY(qreal b READ b WRITE setB FINAL)
Q_PROPERTY(qreal a READ a WRITE setA FINAL)
- Q_OBJECT
+ Q_GADGET
public:
- QQuickColorValueType(QObject *parent = 0);
-
- virtual QString toString() const;
+ Q_INVOKABLE QString toString() const;
qreal r() const;
qreal g() const;
@@ -76,16 +75,14 @@ public:
void setA(qreal);
};
-class Q_AUTOTEST_EXPORT QQuickVector2DValueType : public QQmlValueTypeBase<QVector2D>
+class QQuickVector2DValueType
{
+ QVector2D v;
Q_PROPERTY(qreal x READ x WRITE setX FINAL)
Q_PROPERTY(qreal y READ y WRITE setY FINAL)
- Q_OBJECT
+ Q_GADGET
public:
- QQuickVector2DValueType(QObject *parent = 0);
-
- virtual QString toString() const;
- virtual bool isEqual(const QVariant &other) const;
+ Q_INVOKABLE QString toString() const;
qreal x() const;
qreal y() const;
@@ -105,17 +102,15 @@ public:
Q_INVOKABLE bool fuzzyEquals(const QVector2D &vec) const;
};
-class Q_AUTOTEST_EXPORT QQuickVector3DValueType : public QQmlValueTypeBase<QVector3D>
+class QQuickVector3DValueType
{
+ QVector3D v;
Q_PROPERTY(qreal x READ x WRITE setX FINAL)
Q_PROPERTY(qreal y READ y WRITE setY FINAL)
Q_PROPERTY(qreal z READ z WRITE setZ FINAL)
- Q_OBJECT
+ Q_GADGET
public:
- QQuickVector3DValueType(QObject *parent = 0);
-
- virtual QString toString() const;
- virtual bool isEqual(const QVariant &other) const;
+ Q_INVOKABLE QString toString() const;
qreal x() const;
qreal y() const;
@@ -139,18 +134,16 @@ public:
Q_INVOKABLE bool fuzzyEquals(const QVector3D &vec) const;
};
-class Q_AUTOTEST_EXPORT QQuickVector4DValueType : public QQmlValueTypeBase<QVector4D>
+class QQuickVector4DValueType
{
+ QVector4D v;
Q_PROPERTY(qreal x READ x WRITE setX FINAL)
Q_PROPERTY(qreal y READ y WRITE setY FINAL)
Q_PROPERTY(qreal z READ z WRITE setZ FINAL)
Q_PROPERTY(qreal w READ w WRITE setW FINAL)
- Q_OBJECT
+ Q_GADGET
public:
- QQuickVector4DValueType(QObject *parent = 0);
-
- virtual QString toString() const;
- virtual bool isEqual(const QVariant &other) const;
+ Q_INVOKABLE QString toString() const;
qreal x() const;
qreal y() const;
@@ -175,17 +168,16 @@ public:
Q_INVOKABLE bool fuzzyEquals(const QVector4D &vec) const;
};
-class Q_AUTOTEST_EXPORT QQuickQuaternionValueType : public QQmlValueTypeBase<QQuaternion>
+class QQuickQuaternionValueType
{
+ QQuaternion v;
Q_PROPERTY(qreal scalar READ scalar WRITE setScalar)
Q_PROPERTY(qreal x READ x WRITE setX)
Q_PROPERTY(qreal y READ y WRITE setY)
Q_PROPERTY(qreal z READ z WRITE setZ)
- Q_OBJECT
+ Q_GADGET
public:
- QQuickQuaternionValueType(QObject *parent = 0);
-
- virtual QString toString() const;
+ Q_INVOKABLE QString toString() const;
qreal scalar() const;
qreal x() const;
@@ -197,8 +189,9 @@ public:
void setZ(qreal);
};
-class Q_AUTOTEST_EXPORT QQuickMatrix4x4ValueType : public QQmlValueTypeBase<QMatrix4x4>
+class QQuickMatrix4x4ValueType
{
+ QMatrix4x4 v;
Q_PROPERTY(qreal m11 READ m11 WRITE setM11 FINAL)
Q_PROPERTY(qreal m12 READ m12 WRITE setM12 FINAL)
Q_PROPERTY(qreal m13 READ m13 WRITE setM13 FINAL)
@@ -215,13 +208,8 @@ class Q_AUTOTEST_EXPORT QQuickMatrix4x4ValueType : public QQmlValueTypeBase<QMat
Q_PROPERTY(qreal m42 READ m42 WRITE setM42 FINAL)
Q_PROPERTY(qreal m43 READ m43 WRITE setM43 FINAL)
Q_PROPERTY(qreal m44 READ m44 WRITE setM44 FINAL)
- Q_OBJECT
+ Q_GADGET
public:
- QQuickMatrix4x4ValueType(QObject *parent = 0);
-
- virtual QString toString() const;
- virtual bool isEqual(const QVariant &other) const;
-
qreal m11() const { return v(0, 0); }
qreal m12() const { return v(0, 1); }
qreal m13() const { return v(0, 2); }
@@ -274,9 +262,10 @@ public:
Q_INVOKABLE bool fuzzyEquals(const QMatrix4x4 &m) const;
};
-class Q_AUTOTEST_EXPORT QQuickFontValueType : public QQmlValueTypeBase<QFont>
+class QQuickFontValueType
{
- Q_OBJECT
+ QFont v;
+ Q_GADGET
Q_ENUMS(FontWeight)
Q_ENUMS(Capitalization)
@@ -305,9 +294,7 @@ public:
SmallCaps = QFont::SmallCaps,
Capitalize = QFont::Capitalize };
- QQuickFontValueType(QObject *parent = 0);
-
- virtual QString toString() const;
+ Q_INVOKABLE QString toString() const;
QString family() const;
void setFamily(const QString &);
@@ -344,13 +331,6 @@ public:
qreal wordSpacing() const;
void setWordSpacing(qreal spacing);
-
- void onLoad();
-
-private:
- bool pixelSizeSet;
- bool pointSizeSet;
- mutable QQmlNullableValue<int> dpi;
};
QT_END_NAMESPACE
diff --git a/src/quickwidgets/qquickwidget.h b/src/quickwidgets/qquickwidget.h
index 530a523470..87f688c11a 100644
--- a/src/quickwidgets/qquickwidget.h
+++ b/src/quickwidgets/qquickwidget.h
@@ -99,6 +99,7 @@ Q_SIGNALS:
void sceneGraphError(QQuickWindow::SceneGraphError error, const QString &message);
private Q_SLOTS:
+ // ### Qt 6: make these truly private slots through Q_PRIVATE_SLOT
void continueExecute();
void createFramebufferObject();
void destroyFramebufferObject();