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 
60 QT_BEGIN_NAMESPACE
61 
62 namespace QV4 {
63 
64 struct Q_QML_PRIVATE_EXPORT Lookup {
65     union {
66         ReturnedValue (*getter)(Lookup *l, ExecutionEngine *engine, const Value &object);
67         ReturnedValue (*globalGetter)(Lookup *l, ExecutionEngine *engine);
68         ReturnedValue (*qmlContextPropertyGetter)(Lookup *l, ExecutionEngine *engine, Value *thisObject);
69         bool (*setter)(Lookup *l, ExecutionEngine *engine, Value &object, const Value &v);
70     };
71     // NOTE: gc assumes the first two entries in the struct are pointers to heap objects or null
72     union {
73         struct {
74             Heap::Base *h1;
75             Heap::Base *h2;
76             quintptr unused;
77             quintptr unused2;
78         } markDef;
79         struct {
80             Heap::InternalClass *ic;
81             quintptr unused;
82             uint index;
83             uint offset;
84         } objectLookup;
85         struct {
86             quintptr protoId;
87             quintptr _unused;
88             const Value *data;
89         } protoLookup;
90         struct {
91             Heap::InternalClass *ic;
92             Heap::InternalClass *ic2;
93             uint offset;
94             uint offset2;
95         } objectLookupTwoClasses;
96         struct {
97             quintptr protoId;
98             quintptr protoId2;
99             const Value *data;
100             const Value *data2;
101         } protoLookupTwoClasses;
102         struct {
103             // Make sure the next two values are in sync with protoLookup
104             quintptr protoId;
105             Heap::Object *proto;
106             const Value *data;
107             quintptr type;
108         } primitiveLookup;
109         struct {
110             Heap::InternalClass *newClass;
111             quintptr protoId;
112             uint offset;
113             uint unused;
114         } insertionLookup;
115         struct {
116             quintptr _unused;
117             quintptr _unused2;
118             uint index;
119             uint unused;
120         } indexedLookup;
121         struct {
122             Heap::InternalClass *ic;
123             Heap::InternalClass *qmlTypeIc; // only used when lookup goes through QQmlTypeWrapper
124             QQmlPropertyCache *propertyCache;
125             QQmlPropertyData *propertyData;
126         } qobjectLookup;
127         struct {
128             Heap::InternalClass *ic;
129             quintptr unused;
130             QQmlPropertyCache *propertyCache;
131             QQmlPropertyData *propertyData;
132         } qgadgetLookup;
133         struct {
134             quintptr unused1;
135             quintptr unused2;
136             int scriptIndex;
137         } qmlContextScriptLookup;
138         struct {
139             Heap::Object *singleton;
140             quintptr unused;
141         } qmlContextSingletonLookup;
142         struct {
143             quintptr unused1;
144             quintptr unused2;
145             int objectId;
146         } qmlContextIdObjectLookup;
147         struct {
148             // Same as protoLookup, as used for global lookups
149             quintptr reserved1;
150             quintptr reserved2;
151             quintptr reserved3;
152             ReturnedValue (*getterTrampoline)(Lookup *l, ExecutionEngine *engine);
153         } qmlContextGlobalLookup;
154         struct {
155             Heap::Object *qmlTypeWrapper;
156             quintptr unused2;
157         } qmlTypeLookup;
158         struct {
159             Heap::InternalClass *ic;
160             quintptr unused;
161             ReturnedValue encodedEnumValue;
162         } qmlEnumValueLookup;
163         struct {
164             Heap::InternalClass *ic;
165             Heap::Object *qmlScopedEnumWrapper;
166         } qmlScopedEnumWrapperLookup;
167     };
168     uint nameIndex;
169 
170     ReturnedValue resolveGetter(ExecutionEngine *engine, const Object *object);
171     ReturnedValue resolvePrimitiveGetter(ExecutionEngine *engine, const Value &object);
172     ReturnedValue resolveGlobalGetter(ExecutionEngine *engine);
173     void resolveProtoGetter(PropertyKey name, const Heap::Object *proto);
174 
175     static ReturnedValue getterGeneric(Lookup *l, ExecutionEngine *engine, const Value &object);
176     static ReturnedValue getterTwoClasses(Lookup *l, ExecutionEngine *engine, const Value &object);
177     static ReturnedValue getterFallback(Lookup *l, ExecutionEngine *engine, const Value &object);
178 
179     static ReturnedValue getter0MemberData(Lookup *l, ExecutionEngine *engine, const Value &object);
180     static ReturnedValue getter0Inline(Lookup *l, ExecutionEngine *engine, const Value &object);
181     static ReturnedValue getterProto(Lookup *l, ExecutionEngine *engine, const Value &object);
182     static ReturnedValue getter0Inlinegetter0Inline(Lookup *l, ExecutionEngine *engine, const Value &object);
183     static ReturnedValue getter0Inlinegetter0MemberData(Lookup *l, ExecutionEngine *engine, const Value &object);
184     static ReturnedValue getter0MemberDatagetter0MemberData(Lookup *l, ExecutionEngine *engine, const Value &object);
185     static ReturnedValue getterProtoTwoClasses(Lookup *l, ExecutionEngine *engine, const Value &object);
186     static ReturnedValue getterAccessor(Lookup *l, ExecutionEngine *engine, const Value &object);
187     static ReturnedValue getterProtoAccessor(Lookup *l, ExecutionEngine *engine, const Value &object);
188     static ReturnedValue getterProtoAccessorTwoClasses(Lookup *l, ExecutionEngine *engine, const Value &object);
189     static ReturnedValue getterIndexed(Lookup *l, ExecutionEngine *engine, const Value &object);
190 
191     static ReturnedValue primitiveGetterProto(Lookup *l, ExecutionEngine *engine, const Value &object);
192     static ReturnedValue primitiveGetterAccessor(Lookup *l, ExecutionEngine *engine, const Value &object);
193     static ReturnedValue stringLengthGetter(Lookup *l, ExecutionEngine *engine, const Value &object);
194 
195     static ReturnedValue globalGetterGeneric(Lookup *l, ExecutionEngine *engine);
196     static ReturnedValue globalGetterProto(Lookup *l, ExecutionEngine *engine);
197     static ReturnedValue globalGetterProtoAccessor(Lookup *l, ExecutionEngine *engine);
198 
199     bool resolveSetter(ExecutionEngine *engine, Object *object, const Value &value);
200     static bool setterGeneric(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
201     Q_NEVER_INLINE static bool setterTwoClasses(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
202     static bool setterFallback(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
203     static bool setter0MemberData(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
204     static bool setter0Inline(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
205     static bool setter0setter0(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
206     static bool setterInsert(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
207     static bool arrayLengthSetter(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value);
208 
markObjectsLookup209     void markObjects(MarkStack *stack) {
210         if (markDef.h1 && !(reinterpret_cast<quintptr>(markDef.h1) & 1))
211             markDef.h1->mark(stack);
212         if (markDef.h2 && !(reinterpret_cast<quintptr>(markDef.h2) & 1))
213             markDef.h2->mark(stack);
214     }
215 
clearLookup216     void clear() {
217         memset(&markDef, 0, sizeof(markDef));
218     }
219 };
220 
221 Q_STATIC_ASSERT(std::is_standard_layout<Lookup>::value);
222 // Ensure that these offsets are always at this point to keep generated code compatible
223 // across 32-bit and 64-bit (matters when cross-compiling).
224 Q_STATIC_ASSERT(offsetof(Lookup, getter) == 0);
225 
226 }
227 
228 QT_END_NAMESPACE
229 
230 #endif
231