diff options
Diffstat (limited to 'src/qml/jsruntime/qv4context_p.h')
-rw-r--r-- | src/qml/jsruntime/qv4context_p.h | 245 |
1 files changed, 83 insertions, 162 deletions
diff --git a/src/qml/jsruntime/qv4context_p.h b/src/qml/jsruntime/qv4context_p.h index a854c324d0..4efd0bc899 100644 --- a/src/qml/jsruntime/qv4context_p.h +++ b/src/qml/jsruntime/qv4context_p.h @@ -68,59 +68,66 @@ struct Function; struct Function; struct Identifier; struct CallContext; -struct SimpleCallContext; struct CatchContext; -struct WithContext; struct QmlContext; struct QQmlContextWrapper; -// Attention: Make sure that this structure is the same size on 32-bit and 64-bit -// architecture or you'll have to change the JIT code. 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 + enum Offsets { + Function = 0, + Context = 1, + Accumulator = 2, + This = 3, + Argc = 4 + }; + + Value function; + Value context; + Value accumulator; + Value thisObject; + Value _argc; + + int argc() const { + Q_ASSERT(_argc.isInteger()); + return _argc.int_32(); + } + + void setArgc(int argc) { + Q_ASSERT(argc >= 0); + _argc.setInt_32(argc); + } + inline ReturnedValue argument(int i) const { - return i < argc ? args[i].asReturnedValue() : Primitive::undefinedValue().asReturnedValue(); + return i < argc() ? args[i].asReturnedValue() : Primitive::undefinedValue().asReturnedValue(); } - Value thisObject; Value args[1]; + + static Q_DECL_CONSTEXPR int HeaderSize() { return offsetof(CallData, args) / sizeof(QV4::Value); } }; Q_STATIC_ASSERT(std::is_standard_layout<CallData>::value); -Q_STATIC_ASSERT(offsetof(CallData, thisObject) == 8); -Q_STATIC_ASSERT(offsetof(CallData, args) == 16); +Q_STATIC_ASSERT(offsetof(CallData, thisObject) == CallData::This*sizeof(Value)); +Q_STATIC_ASSERT(offsetof(CallData, args) == 5*sizeof(Value)); namespace Heap { struct QmlContext; #define ExecutionContextMembers(class, Member) \ - Member(class, NoMark, CallData *, callData) \ Member(class, Pointer, ExecutionContext *, outer) \ - Member(class, NoMark, Lookup *, lookups) \ - Member(class, NoMark, const QV4::Value *, constantTable) \ - Member(class, NoMark, CompiledData::CompilationUnitBase *, compilationUnit) \ - Member(class, NoMark, int, lineNumber) // as member of non-pointer size this has to come last to preserve the ability to - // translate offsetof of it between 64-bit and 32-bit. + Member(class, Pointer, Object *, activation) DECLARE_HEAP_OBJECT(ExecutionContext, Base) { - DECLARE_MARK_TABLE(ExecutionContext); + DECLARE_MARKOBJECTS(ExecutionContext); enum ContextType { Type_GlobalContext = 0x1, Type_CatchContext = 0x2, Type_WithContext = 0x3, Type_QmlContext = 0x4, - Type_SimpleCallContext = 0x5, - Type_CallContext = 0x6 + Type_CallContext = 0x5 }; void init(ContextType t) @@ -128,105 +135,63 @@ DECLARE_HEAP_OBJECT(ExecutionContext, Base) { Base::init(); type = t; - lineNumber = -1; } - quint8 type; - bool strictMode : 8; + quint32 type : 8; + quint32 nArgs : 24; #if QT_POINTER_SIZE == 8 - quint8 padding_[6]; -#else - quint8 padding_[2]; + quint8 padding_[4]; #endif }; V4_ASSERT_IS_TRIVIAL(ExecutionContext) Q_STATIC_ASSERT(sizeof(ExecutionContext) == sizeof(Base) + sizeof(ExecutionContextData) + QT_POINTER_SIZE); Q_STATIC_ASSERT(std::is_standard_layout<ExecutionContextData>::value); -Q_STATIC_ASSERT(offsetof(ExecutionContextData, callData) == 0); -Q_STATIC_ASSERT(offsetof(ExecutionContextData, outer) == offsetof(ExecutionContextData, callData) + QT_POINTER_SIZE); -Q_STATIC_ASSERT(offsetof(ExecutionContextData, lookups) == offsetof(ExecutionContextData, outer) + QT_POINTER_SIZE); -Q_STATIC_ASSERT(offsetof(ExecutionContextData, constantTable) == offsetof(ExecutionContextData, lookups) + QT_POINTER_SIZE); -Q_STATIC_ASSERT(offsetof(ExecutionContextData, compilationUnit) == offsetof(ExecutionContextData, constantTable) + QT_POINTER_SIZE); -Q_STATIC_ASSERT(offsetof(ExecutionContextData, lineNumber) == offsetof(ExecutionContextData, compilationUnit) + QT_POINTER_SIZE); - -#define SimpleCallContextMembers(class, Member) \ - Member(class, Pointer, Object *, activation) \ - Member(class, NoMark, QV4::Function *, v4Function) - -DECLARE_HEAP_OBJECT(SimpleCallContext, ExecutionContext) { - DECLARE_MARK_TABLE(SimpleCallContext); - - void init(ContextType t = Type_SimpleCallContext) - { - ExecutionContext::init(t); - } - - inline unsigned int formalParameterCount() const; +Q_STATIC_ASSERT(offsetof(ExecutionContextData, outer) == 0); +Q_STATIC_ASSERT(offsetof(ExecutionContextData, activation) == offsetof(ExecutionContextData, outer) + QT_POINTER_SIZE); -}; -V4_ASSERT_IS_TRIVIAL(SimpleCallContext) -Q_STATIC_ASSERT(std::is_standard_layout<SimpleCallContextData>::value); -Q_STATIC_ASSERT(offsetof(SimpleCallContextData, activation) == 0); -Q_STATIC_ASSERT(offsetof(SimpleCallContextData, v4Function) == offsetof(SimpleCallContextData, activation) + QT_POINTER_SIZE); -Q_STATIC_ASSERT(sizeof(SimpleCallContextData) == 2 * QT_POINTER_SIZE); -Q_STATIC_ASSERT(sizeof(SimpleCallContext) == sizeof(ExecutionContext) + sizeof(SimpleCallContextData)); - -#if QT_POINTER_SIZE == 8 #define CallContextMembers(class, Member) \ Member(class, Pointer, FunctionObject *, function) \ Member(class, ValueArray, ValueArray, locals) -#else -#define CallContextMembers(class, Member) \ - Member(class, Pointer, FunctionObject *, function) \ - Member(class, NoMark, void *, padding) \ - Member(class, ValueArray, ValueArray, locals) -#endif -DECLARE_HEAP_OBJECT(CallContext, SimpleCallContext) { - DECLARE_MARK_TABLE(CallContext); +DECLARE_HEAP_OBJECT(CallContext, ExecutionContext) { + DECLARE_MARKOBJECTS(CallContext); - using SimpleCallContext::formalParameterCount; -}; + void init() + { + ExecutionContext::init(Type_CallContext); + } + int argc() const { + return static_cast<int>(nArgs); + } + const Value *args() const { + return locals.data() + locals.size; + } + void setArg(uint index, Value v); +}; +V4_ASSERT_IS_TRIVIAL(CallContext) Q_STATIC_ASSERT(std::is_standard_layout<CallContextData>::value); Q_STATIC_ASSERT(offsetof(CallContextData, function) == 0); -// IMPORTANT: we cannot do offsetof(CallContextData, locals) in the JIT as the offset does not scale with -// the pointer size. On 32-bit ARM the offset of the ValueArray is aligned to 8 bytes, on 32-bit x86 for -// example it is not. Therefore we have a padding in place and always have a distance of 8 bytes. -Q_STATIC_ASSERT(offsetof(CallContextData, locals) == offsetof(CallContextData, function) + 8); - -#define GlobalContextMembers(class, Member) \ - Member(class, Pointer, Object *, global) - -DECLARE_HEAP_OBJECT(GlobalContext, ExecutionContext) { - DECLARE_MARK_TABLE(GlobalContext); - - void init(ExecutionEngine *engine); -}; -V4_ASSERT_IS_TRIVIAL(GlobalContext) +//### The following size check fails on Win8. With the ValueArray at the end of the +// CallContextMembers, it doesn't look very useful. +//#if defined(Q_PROCESSOR_ARM_32) && !defined(Q_OS_IOS) +//Q_STATIC_ASSERT(sizeof(CallContext) == sizeof(ExecutionContext) + sizeof(CallContextData) + QT_POINTER_SIZE); +//#else +//Q_STATIC_ASSERT(sizeof(CallContext) == sizeof(ExecutionContext) + sizeof(CallContextData)); +//#endif #define CatchContextMembers(class, Member) \ Member(class, Pointer, String *, exceptionVarName) \ Member(class, HeapValue, HeapValue, exceptionValue) DECLARE_HEAP_OBJECT(CatchContext, ExecutionContext) { - DECLARE_MARK_TABLE(CatchContext); + DECLARE_MARKOBJECTS(CatchContext); void init(ExecutionContext *outerContext, String *exceptionVarName, const Value &exceptionValue); }; V4_ASSERT_IS_TRIVIAL(CatchContext) -#define WithContextMembers(class, Member) \ - Member(class, Pointer, Object *, withObject) - -DECLARE_HEAP_OBJECT(WithContext, ExecutionContext) { - DECLARE_MARK_TABLE(WithContext); - - void init(ExecutionContext *outerContext, Object *with); -}; -V4_ASSERT_IS_TRIVIAL(WithContext) - } struct Q_QML_EXPORT ExecutionContext : public Managed @@ -239,68 +204,39 @@ struct Q_QML_EXPORT ExecutionContext : public Managed Q_MANAGED_TYPE(ExecutionContext) V4_INTERNALCLASS(ExecutionContext) - Heap::CallContext *newCallContext(Function *f, CallData *callData); - Heap::WithContext *newWithContext(Heap::Object *with); + static Heap::CallContext *newCallContext(QV4::CppStackFrame *frame); + Heap::ExecutionContext *newWithContext(Heap::Object *with); Heap::CatchContext *newCatchContext(Heap::String *exceptionVarName, ReturnedValue exceptionValue); void createMutableBinding(String *name, bool deletable); - void setProperty(String *name, const Value &value); + enum Error { + NoError, + TypeError, + RangeError + }; + + Error setProperty(String *name, const Value &value); + ReturnedValue getProperty(String *name); ReturnedValue getPropertyAndBase(String *name, Value *base); bool deleteProperty(String *name); - inline SimpleCallContext *asSimpleCallContext(); - inline const SimpleCallContext *asSimpleCallContext() const; - inline const CatchContext *asCatchContext() const; - inline const WithContext *asWithContext() const; + inline CallContext *asCallContext(); + inline const CallContext *asCallContext() const; +}; - Function *getFunction() const; +struct Q_QML_EXPORT CallContext : public ExecutionContext +{ + V4_MANAGED(CallContext, ExecutionContext) + V4_INTERNALCLASS(CallContext) - Value &thisObject() const { - return d()->callData->thisObject; - } int argc() const { - return d()->callData->argc; + return d()->argc(); } const Value *args() const { - return d()->callData->args; - } - ReturnedValue argument(int i) const { - return d()->callData->argument(i); + return d()->args(); } - - void call(Scope &scope, CallData *callData, QV4::Function *function, const QV4::FunctionObject *f = 0); - void simpleCall(Scope &scope, CallData *callData, QV4::Function *function); -}; - -struct Q_QML_EXPORT SimpleCallContext : public ExecutionContext -{ - V4_MANAGED(SimpleCallContext, ExecutionContext) - V4_INTERNALCLASS(SimpleCallContext) - - // formals are in reverse order - Identifier * const *formals() const; - unsigned int formalCount() const; - Identifier * const *variables() const; - unsigned int variableCount() const; - - inline ReturnedValue argument(int i) const; -}; - -inline ReturnedValue SimpleCallContext::argument(int i) const { - return i < argc() ? args()[i].asReturnedValue() : Primitive::undefinedValue().asReturnedValue(); -} - -struct Q_QML_EXPORT CallContext : public SimpleCallContext -{ - V4_MANAGED(CallContext, SimpleCallContext) -}; - -struct GlobalContext : public ExecutionContext -{ - V4_MANAGED(GlobalContext, ExecutionContext) - }; struct CatchContext : public ExecutionContext @@ -308,29 +244,14 @@ struct CatchContext : public ExecutionContext V4_MANAGED(CatchContext, ExecutionContext) }; -struct WithContext : public ExecutionContext -{ - V4_MANAGED(WithContext, ExecutionContext) -}; - -inline SimpleCallContext *ExecutionContext::asSimpleCallContext() -{ - return d()->type >= Heap::ExecutionContext::Type_SimpleCallContext ? static_cast<SimpleCallContext *>(this) : 0; -} - -inline const SimpleCallContext *ExecutionContext::asSimpleCallContext() const -{ - return d()->type >= Heap::ExecutionContext::Type_SimpleCallContext ? static_cast<const SimpleCallContext *>(this) : 0; -} - -inline const CatchContext *ExecutionContext::asCatchContext() const +inline CallContext *ExecutionContext::asCallContext() { - return d()->type == Heap::ExecutionContext::Type_CatchContext ? static_cast<const CatchContext *>(this) : 0; + return d()->type == Heap::ExecutionContext::Type_CallContext ? static_cast<CallContext *>(this) : 0; } -inline const WithContext *ExecutionContext::asWithContext() const +inline const CallContext *ExecutionContext::asCallContext() const { - return d()->type == Heap::ExecutionContext::Type_WithContext ? static_cast<const WithContext *>(this) : 0; + return d()->type == Heap::ExecutionContext::Type_CallContext ? static_cast<const CallContext *>(this) : 0; } } // namespace QV4 |