1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtQml module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39#ifndef QV4LOOKUP_H
40#define QV4LOOKUP_H
41
42//
43// W A R N I N G
44// -------------
45//
46// This file is not part of the Qt API. It exists purely as an
47// implementation detail. This header file may change from version to
48// version without notice, or even be removed.
49//
50// We mean it.
51//
52
53#include "qv4global_p.h"
54#include "qv4runtime_p.h"
55#include "qv4engine_p.h"
56#include "qv4context_p.h"
57#include "qv4object_p.h"
58#include "qv4internalclass_p.h"
59#include "qv4qmlcontext_p.h"
60#include <private/qqmltypewrapper_p.h>
61#include <private/qqmlvaluetypewrapper_p.h>
62
63QT_BEGIN_NAMESPACE
64
65namespace QV4 {
66
67// Note: We cannot hide the copy ctor and assignment operator of this class because it needs to
68// be trivially copyable. But you should never ever copy it. There are refcounted members
69// in there.
70struct Q_QML_PRIVATE_EXPORT Lookup {
71 union {
72 ReturnedValue (*getter)(Lookup *l, ExecutionEngine *engine, const Value &object);
73 ReturnedValue (*globalGetter)(Lookup *l, ExecutionEngine *engine);
74 ReturnedValue (*qmlContextPropertyGetter)(Lookup *l, ExecutionEngine *engine, Value *thisObject);
75 bool (*setter)(Lookup *l, ExecutionEngine *engine, Value &object, const Value &v);
76 };
77 // NOTE: gc assumes the first two entries in the struct are pointers to heap objects or null
78 union {
79 struct {
80 Heap::Base *h1;
81 Heap::Base *h2;
82 quintptr unused;
83 quintptr unused2;
84 } markDef;
85 struct {
86 Heap::InternalClass *ic;
87 quintptr unused;
88 uint index;
89 uint offset;
90 } objectLookup;
91 struct {
92 quintptr protoId;
93 quintptr _unused;
94 const Value *data;
95 } protoLookup;
96 struct {
97 Heap::InternalClass *ic;
98 Heap::InternalClass *ic2;
99 uint offset;
100 uint offset2;
101 } objectLookupTwoClasses;
102 struct {
103 quintptr protoId;
104 quintptr protoId2;
105 const Value *data;
106 const Value *data2;
107 } protoLookupTwoClasses;
108 struct {
109 // Make sure the next two values are in sync with protoLookup
110 quintptr protoId;
111 Heap::Object *proto;
112 const Value *data;
113 quintptr type;
114 } primitiveLookup;
115 struct {
116 Heap::InternalClass *newClass;
117 quintptr protoId;
118 uint offset;
119 uint unused;
120 } insertionLookup;
121 struct {
122 quintptr _unused;
123 quintptr _unused2;
124 uint index;
125 uint unused;
126 } indexedLookup;
127 struct {
128 Heap::InternalClass *ic;
129 Heap::InternalClass *qmlTypeIc; // only used when lookup goes through QQmlTypeWrapper
130 QQmlPropertyCache *propertyCache;
131 QQmlPropertyData *propertyData;
132 } qobjectLookup;
133 struct {
134 Heap::InternalClass *ic;
135 quintptr unused;
136 QQmlPropertyCache *propertyCache;
137 QQmlPropertyData *propertyData;
138 } qgadgetLookup;
139 struct {
140 quintptr unused1;
141 quintptr unused2;
142 int scriptIndex;
143 } qmlContextScriptLookup;
144 struct {
145 Heap::Object *singleton;
146 quintptr unused;
147 } qmlContextSingletonLookup;
148 struct {
149 quintptr unused1;
150 quintptr unused2;
151 int objectId;
152 } qmlContextIdObjectLookup;
153 struct {
154 // Same as protoLookup, as used for global lookups
155 quintptr reserved1;
156 quintptr reserved2;
157 quintptr reserved3;
158 ReturnedValue (*getterTrampoline)(Lookup *l, ExecutionEngine *engine);
159 } qmlContextGlobalLookup;
160 struct {
161 Heap::Object *qmlTypeWrapper;
162 quintptr unused2;
163 } qmlTypeLookup;
164 struct {
165 Heap::InternalClass *ic;
166 quintptr unused;
167 ReturnedValue encodedEnumValue;
168 } qmlEnumValueLookup;
169 struct {
170 Heap::InternalClass *ic;
171 Heap::Object *qmlScopedEnumWrapper;
172 } qmlScopedEnumWrapperLookup;
173 };
174 uint nameIndex;
175
176 ReturnedValue resolveGetter(ExecutionEngine *engine, const Object *object);
177 ReturnedValue resolvePrimitiveGetter(ExecutionEngine *engine, const Value &object);
178 ReturnedValue resolveGlobalGetter(ExecutionEngine *engine);
179 void resolveProtoGetter(PropertyKey name, const Heap::Object *proto);
180
181 static ReturnedValue getterGeneric(Lookup *l, ExecutionEngine *engine, const Value &object);
182 static ReturnedValue getterTwoClasses(Lookup *l, ExecutionEngine *engine, const Value &object);
183 static ReturnedValue getterFallback(Lookup *l, ExecutionEngine *engine, const Value &object);
184
185 static ReturnedValue getter0MemberData(Lookup *l, ExecutionEngine *engine, const Value &object);
186 static ReturnedValue getter0Inline(Lookup *l, ExecutionEngine *engine, const Value &object);
187 static ReturnedValue getterProto(Lookup *l, ExecutionEngine *engine, const Value &object);
188 static ReturnedValue getter0Inlinegetter0Inline(Lookup *l, ExecutionEngine *engine, const Value &object);
189 static ReturnedValue getter0Inlinegetter0MemberData(Lookup *l, ExecutionEngine *engine, const Value &object);
190 static ReturnedValue getter0MemberDatagetter0MemberData(Lookup *l, ExecutionEngine *engine, const Value &object);
191 static ReturnedValue getterProtoTwoClasses(Lookup *l, ExecutionEngine *engine, const Value &object);
192 static ReturnedValue getterAccessor(Lookup *l, ExecutionEngine *engine, const Value &object);
193 static ReturnedValue getterProtoAccessor(Lookup *l, ExecutionEngine *engine, const Value &object);
194 static ReturnedValue getterProtoAccessorTwoClasses(Lookup *l, ExecutionEngine *engine, const Value &object);
195 static ReturnedValue getterIndexed(Lookup *l, ExecutionEngine *engine, const Value &object);
196 static ReturnedValue getterQObject(Lookup *l, ExecutionEngine *engine, const Value &object);
197
198 static ReturnedValue primitiveGetterProto(Lookup *l, ExecutionEngine *engine, const Value &object);
199 static ReturnedValue primitiveGetterAccessor(Lookup *l, ExecutionEngine *engine, const Value &object);
200 static ReturnedValue stringLengthGetter(Lookup *l, ExecutionEngine *engine, const Value &object);
201
202 static ReturnedValue globalGetterGeneric(Lookup *l, ExecutionEngine *engine);
203 static ReturnedValue globalGetterProto(Lookup *l, ExecutionEngine *engine);
204 static ReturnedValue globalGetterProtoAccessor(Lookup *l, ExecutionEngine *engine);
205
206 bool resolveSetter(ExecutionEngine *engine, Object *object, const Value &value);
207 static bool setterGeneric(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
208 Q_NEVER_INLINE static bool setterTwoClasses(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
209 static bool setterFallback(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
210 static bool setter0MemberData(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
211 static bool setter0Inline(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
212 static bool setter0setter0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
213 static bool setterInsert(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
214 static bool arrayLengthSetter(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
215
216 void markObjects(MarkStack *stack) {
217 if (markDef.h1 && !(reinterpret_cast<quintptr>(markDef.h1) & 1))
218 markDef.h1->mark(markStack: stack);
219 if (markDef.h2 && !(reinterpret_cast<quintptr>(markDef.h2) & 1))
220 markDef.h2->mark(markStack: stack);
221 }
222
223 void clear() {
224 memset(s: &markDef, c: 0, n: sizeof(markDef));
225 }
226
227 void releasePropertyCache()
228 {
229 if (getter == getterQObject
230 || getter == QQmlTypeWrapper::lookupSingletonProperty
231 || qmlContextPropertyGetter == QQmlContextWrapper::lookupScopeObjectProperty
232 || qmlContextPropertyGetter == QQmlContextWrapper::lookupContextObjectProperty) {
233 if (QQmlPropertyCache *pc = qobjectLookup.propertyCache)
234 pc->release();
235 } else if (getter == QQmlValueTypeWrapper::lookupGetter) {
236 if (QQmlPropertyCache *pc = qgadgetLookup.propertyCache)
237 pc->release();
238 }
239 }
240};
241
242Q_STATIC_ASSERT(std::is_standard_layout<Lookup>::value);
243// Ensure that these offsets are always at this point to keep generated code compatible
244// across 32-bit and 64-bit (matters when cross-compiling).
245Q_STATIC_ASSERT(offsetof(Lookup, getter) == 0);
246
247inline void setupQObjectLookup(
248 Lookup *lookup, const QQmlData *ddata, QQmlPropertyData *propertyData)
249{
250 lookup->releasePropertyCache();
251 Q_ASSERT(ddata->propertyCache != nullptr);
252 lookup->qobjectLookup.propertyCache = ddata->propertyCache;
253 lookup->qobjectLookup.propertyCache->addref();
254 lookup->qobjectLookup.propertyData = propertyData;
255}
256
257inline void setupQObjectLookup(
258 Lookup *lookup, const QQmlData *ddata, QQmlPropertyData *propertyData,
259 const Object *self)
260{
261 lookup->qobjectLookup.ic = self->internalClass();
262 setupQObjectLookup(lookup, ddata, propertyData);
263}
264
265
266inline void setupQObjectLookup(
267 Lookup *lookup, const QQmlData *ddata, QQmlPropertyData *propertyData,
268 const Object *self, const Object *qmlType)
269{
270 lookup->qobjectLookup.qmlTypeIc = qmlType->internalClass();
271 setupQObjectLookup(lookup, ddata, propertyData, self);
272}
273
274}
275
276QT_END_NAMESPACE
277
278#endif
279

source code of qtdeclarative/src/qml/jsruntime/qv4lookup_p.h