1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3#ifndef QMLJS_ENVIRONMENT_H
4#define QMLJS_ENVIRONMENT_H
5
6//
7// W A R N I N G
8// -------------
9//
10// This file is not part of the Qt API. It exists purely as an
11// implementation detail. This header file may change from version to
12// version without notice, or even be removed.
13//
14// We mean it.
15//
16
17#include "qv4global_p.h"
18#include "qv4managed_p.h"
19
20QT_BEGIN_NAMESPACE
21
22namespace QV4 {
23
24
25namespace Heap {
26
27#define ExecutionContextMembers(class, Member) \
28 Member(class, Pointer, ExecutionContext *, outer) \
29 Member(class, Pointer, Object *, activation)
30
31DECLARE_HEAP_OBJECT(ExecutionContext, Base) {
32 DECLARE_MARKOBJECTS(ExecutionContext)
33
34 enum ContextType {
35 Type_GlobalContext = 0x1,
36 Type_WithContext = 0x2,
37 Type_QmlContext = 0x3,
38 Type_BlockContext = 0x4,
39 Type_CallContext = 0x5
40 };
41
42 void init(ContextType t)
43 {
44 Base::init();
45
46 type = t;
47 }
48
49 const VTable *vtable() const {
50 return internalClass->vtable;
51 }
52
53 quint32 type : 8;
54 quint32 nArgs : 24;
55#if QT_POINTER_SIZE == 8
56 quint8 padding_[4];
57#endif
58};
59Q_STATIC_ASSERT(std::is_trivial_v<ExecutionContext>);
60Q_STATIC_ASSERT(sizeof(ExecutionContext) == sizeof(Base) + sizeof(ExecutionContextData) + QT_POINTER_SIZE);
61
62Q_STATIC_ASSERT(std::is_standard_layout<ExecutionContextData>::value);
63Q_STATIC_ASSERT(offsetof(ExecutionContextData, outer) == 0);
64Q_STATIC_ASSERT(offsetof(ExecutionContextData, activation) == offsetof(ExecutionContextData, outer) + QT_POINTER_SIZE);
65
66#define CallContextMembers(class, Member) \
67 Member(class, Pointer, FunctionObject *, function) \
68 Member(class, ValueArray, ValueArray, locals)
69
70DECLARE_HEAP_OBJECT(CallContext, ExecutionContext) {
71 DECLARE_MARKOBJECTS(CallContext)
72
73 void init()
74 {
75 ExecutionContext::init(t: Type_CallContext);
76 }
77
78 int argc() const {
79 return static_cast<int>(nArgs);
80 }
81 const Value *args() const {
82 return locals.data() + locals.size;
83 }
84 void setArg(uint index, Value v);
85
86 template <typename BlockOrFunction>
87 void setupLocalTemporalDeadZone(BlockOrFunction *bof) {
88 for (uint i = bof->nLocals - bof->sizeOfLocalTemporalDeadZone; i < bof->nLocals; ++i)
89 locals.values[i] = Value::emptyValue();
90 }
91};
92Q_STATIC_ASSERT(std::is_trivial_v<CallContext>);
93Q_STATIC_ASSERT(std::is_standard_layout<CallContextData>::value);
94Q_STATIC_ASSERT(offsetof(CallContextData, function) == 0);
95//### The following size check fails on Win8. With the ValueArray at the end of the
96// CallContextMembers, it doesn't look very useful.
97//#if defined(Q_PROCESSOR_ARM_32) && !defined(Q_OS_IOS)
98//Q_STATIC_ASSERT(sizeof(CallContext) == sizeof(ExecutionContext) + sizeof(CallContextData) + QT_POINTER_SIZE);
99//#else
100//Q_STATIC_ASSERT(sizeof(CallContext) == sizeof(ExecutionContext) + sizeof(CallContextData));
101//#endif
102
103
104}
105
106struct Q_QML_EXPORT ExecutionContext : public Managed
107{
108 enum {
109 IsExecutionContext = true
110 };
111
112 V4_MANAGED(ExecutionContext, Managed)
113 Q_MANAGED_TYPE(ExecutionContext)
114 V4_INTERNALCLASS(ExecutionContext)
115
116 static Heap::CallContext *newBlockContext(QV4::CppStackFrame *frame, int blockIndex);
117 static Heap::CallContext *cloneBlockContext(ExecutionEngine *engine,
118 Heap::CallContext *callContext);
119 static Heap::CallContext *newCallContext(JSTypesStackFrame *frame);
120 Heap::ExecutionContext *newWithContext(Heap::Object *with) const;
121 static Heap::ExecutionContext *newCatchContext(CppStackFrame *frame, int blockIndex, Heap::String *exceptionVarName);
122
123 void createMutableBinding(String *name, bool deletable);
124
125 enum Error {
126 NoError,
127 TypeError,
128 RangeError
129 };
130
131 Error setProperty(String *name, const Value &value);
132
133 ReturnedValue getProperty(String *name);
134 ReturnedValue getPropertyAndBase(String *name, Value *base);
135 bool deleteProperty(String *name);
136
137 inline CallContext *asCallContext();
138 inline const CallContext *asCallContext() const;
139
140protected:
141 // vtable method required for compilation
142 static bool virtualDeleteProperty(Managed *, PropertyKey) {
143 Q_UNREACHABLE();
144 }
145};
146
147struct Q_QML_EXPORT CallContext : public ExecutionContext
148{
149 V4_MANAGED(CallContext, ExecutionContext)
150 V4_INTERNALCLASS(CallContext)
151
152 int argc() const {
153 return d()->argc();
154 }
155 const Value *args() const {
156 return d()->args();
157 }
158};
159
160inline CallContext *ExecutionContext::asCallContext()
161{
162 return d()->type == Heap::ExecutionContext::Type_CallContext ? static_cast<CallContext *>(this) : nullptr;
163}
164
165inline const CallContext *ExecutionContext::asCallContext() const
166{
167 return d()->type == Heap::ExecutionContext::Type_CallContext ? static_cast<const CallContext *>(this) : nullptr;
168}
169
170} // namespace QV4
171
172QT_END_NAMESPACE
173
174#endif
175

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