diff options
author | Lars Knoll <lars.knoll@qt.io> | 2018-09-18 17:01:59 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2018-09-23 17:27:43 +0000 |
commit | a97d118bf55e1c44ded9bbcd143b0f0725db8268 (patch) | |
tree | e0f22b61ba294199758eaf25c7e4f3c71bae7470 /src | |
parent | 3440b8f9c5b198be4124ee1defd69d807bb972c6 (diff) |
Better inheritance structure for functions
Give Arrow functions their own representation. This also prepares
for further optimizations especially for the instanceof operator.
Change-Id: I1f70c0271169a237e1acdeb7fe855be957ba2ea5
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/qml/jsruntime/qv4engine.cpp | 7 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4enginebase_p.h | 1 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4functionobject.cpp | 24 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4functionobject_p.h | 45 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4generatorobject_p.h | 10 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4runtime.cpp | 9 |
6 files changed, 63 insertions, 33 deletions
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 672196dd3f..bf8a91f6e1 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -347,10 +347,11 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine) ic = newInternalClass(FunctionObject::staticVTable(), functionPrototype()); classes[Class_FunctionObject] = ic->d(); ic = ic->addMember(id_name()->propertyKey(), Attr_ReadOnly, &index); - Q_ASSERT(index == Heap::ScriptFunction::Index_Name); - ic = ic->changeVTable(ScriptFunction::staticVTable()); + Q_ASSERT(index == Heap::ArrowFunction::Index_Name); ic = ic->addMember(id_length()->propertyKey(), Attr_ReadOnly_ButConfigurable, &index); - Q_ASSERT(index == Heap::ScriptFunction::Index_Length); + Q_ASSERT(index == Heap::ArrowFunction::Index_Length); + classes[Class_ArrowFunction] = ic->changeVTable(ArrowFunction::staticVTable()); + ic = ic->changeVTable(ScriptFunction::staticVTable()); classes[Class_ScriptFunction] = ic->d(); ic = ic->changeVTable(ConstructorFunction::staticVTable()); classes[Class_ConstructorFunction] = ic->d(); diff --git a/src/qml/jsruntime/qv4enginebase_p.h b/src/qml/jsruntime/qv4enginebase_p.h index 789ec5d970..b5cfea8863 100644 --- a/src/qml/jsruntime/qv4enginebase_p.h +++ b/src/qml/jsruntime/qv4enginebase_p.h @@ -99,6 +99,7 @@ struct Q_QML_EXPORT EngineBase { Class_Object, Class_ArrayObject, Class_FunctionObject, + Class_ArrowFunction, Class_GeneratorFunction, Class_GeneratorObject, Class_StringObject, diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index 8a674bc7fa..6fc2d45630 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -168,6 +168,8 @@ ReturnedValue FunctionObject::virtualCall(const FunctionObject *, const Value *, Heap::FunctionObject *FunctionObject::createScriptFunction(ExecutionContext *scope, Function *function) { + if (function->isArrowFunction()) + return scope->engine()->memoryManager->allocate<ArrowFunction>(scope, function); return scope->engine()->memoryManager->allocate<ScriptFunction>(scope, function); } @@ -213,6 +215,17 @@ bool FunctionObject::isBoundFunction() const return d()->vtable() == BoundFunction::staticVTable(); } +ReturnedValue FunctionObject::getHomeObject() const +{ + const MemberFunction *m = as<MemberFunction>(); + if (m) + return m->d()->homeObject->asReturnedValue(); + const ConstructorFunction *c = as<ConstructorFunction>(); + if (c) + return c->d()->homeObject->asReturnedValue(); + return Encode::undefined(); +} + QQmlSourceLocation FunctionObject::sourceLocation() const { return d()->function->sourceLocation(); @@ -489,7 +502,9 @@ ReturnedValue ScriptFunction::virtualCallAsConstructor(const FunctionObject *fo, return result; } -ReturnedValue ScriptFunction::virtualCall(const FunctionObject *fo, const Value *thisObject, const Value *argv, int argc) +DEFINE_OBJECT_VTABLE(ArrowFunction); + +ReturnedValue ArrowFunction::virtualCall(const FunctionObject *fo, const Value *thisObject, const Value *argv, int argc) { ExecutionEngine *engine = fo->engine(); CppStackFrame frame; @@ -508,7 +523,7 @@ ReturnedValue ScriptFunction::virtualCall(const FunctionObject *fo, const Value return result; } -void Heap::ScriptFunction::initNoConstructor(QV4::ExecutionContext *scope, Function *function, QV4::String *n) +void Heap::ArrowFunction::init(QV4::ExecutionContext *scope, Function *function, QV4::String *n) { FunctionObject::init(); this->scope.set(scope->engine(), scope->d()); @@ -529,9 +544,8 @@ void Heap::ScriptFunction::initNoConstructor(QV4::ExecutionContext *scope, Funct void Heap::ScriptFunction::init(QV4::ExecutionContext *scope, Function *function) { - initNoConstructor(scope, function, nullptr); - if (function->isArrowFunction()) - return; + ArrowFunction::init(scope, function); + Q_ASSERT(!function->isArrowFunction()); Scope s(scope); ScopedFunctionObject f(s, this); diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h index 908a9fcb1e..11ddd9a211 100644 --- a/src/qml/jsruntime/qv4functionobject_p.h +++ b/src/qml/jsruntime/qv4functionobject_p.h @@ -109,32 +109,42 @@ struct IndexedBuiltinFunction : FunctionObject { uint index; }; +struct ArrowFunction : FunctionObject { + enum { + Index_Name, + Index_Length + }; + void init(QV4::ExecutionContext *scope, Function *function, QV4::String *name = nullptr); +}; + #define ScriptFunctionMembers(class, Member) \ Member(class, Pointer, InternalClass *, cachedClassForConstructor) -DECLARE_HEAP_OBJECT(ScriptFunction, FunctionObject) { +DECLARE_HEAP_OBJECT(ScriptFunction, ArrowFunction) { DECLARE_MARKOBJECTS(ScriptFunction) enum { Index_Name, Index_Length }; - void initNoConstructor(QV4::ExecutionContext *scope, Function *function, QV4::String *name = nullptr); void init(QV4::ExecutionContext *scope, Function *function); }; #define MemberFunctionMembers(class, Member) \ Member(class, Pointer, Object *, homeObject) -DECLARE_HEAP_OBJECT(MemberFunction, ScriptFunction) { +DECLARE_HEAP_OBJECT(MemberFunction, ArrowFunction) { DECLARE_MARKOBJECTS(MemberFunction) void init(QV4::ExecutionContext *scope, Function *function, QV4::String *name = nullptr) { - ScriptFunction::initNoConstructor(scope, function, name); + ArrowFunction::init(scope, function, name); } }; -struct ConstructorFunction : MemberFunction -{ +#define ConstructorFunctionMembers(class, Member) \ + Member(class, Pointer, Object *, homeObject) + +DECLARE_HEAP_OBJECT(ConstructorFunction, ScriptFunction) { + DECLARE_MARKOBJECTS(ConstructorFunction) bool isDerivedConstructor; }; @@ -205,6 +215,8 @@ struct Q_QML_EXPORT FunctionObject: Object { return d()->isConstructor(); } + ReturnedValue getHomeObject() const; + ReturnedValue protoProperty() const { return get(engine()->id_prototype()); } @@ -256,25 +268,30 @@ void Heap::IndexedBuiltinFunction::init(QV4::ExecutionContext *scope, uint index this->index = index; } +struct ArrowFunction : FunctionObject { + V4_OBJECT2(ArrowFunction, FunctionObject) + V4_INTERNALCLASS(ArrowFunction) + enum { NInlineProperties = 3 }; + + static ReturnedValue virtualCall(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc); +}; -struct ScriptFunction : FunctionObject { - V4_OBJECT2(ScriptFunction, FunctionObject) +struct ScriptFunction : ArrowFunction { + V4_OBJECT2(ScriptFunction, ArrowFunction) V4_INTERNALCLASS(ScriptFunction) - enum { NInlineProperties = 3 }; static ReturnedValue virtualCallAsConstructor(const FunctionObject *, const Value *argv, int argc, const Value *); - static ReturnedValue virtualCall(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc); Heap::InternalClass *classForConstructor() const; }; -struct MemberFunction : ScriptFunction { - V4_OBJECT2(MemberFunction, ScriptFunction) +struct MemberFunction : ArrowFunction { + V4_OBJECT2(MemberFunction, ArrowFunction) V4_INTERNALCLASS(MemberFunction) }; -struct ConstructorFunction : MemberFunction { - V4_OBJECT2(ConstructorFunction, MemberFunction) +struct ConstructorFunction : ScriptFunction { + V4_OBJECT2(ConstructorFunction, ScriptFunction) V4_INTERNALCLASS(ConstructorFunction) static ReturnedValue virtualCallAsConstructor(const FunctionObject *, const Value *argv, int argc, const Value *); static ReturnedValue virtualCall(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc); diff --git a/src/qml/jsruntime/qv4generatorobject_p.h b/src/qml/jsruntime/qv4generatorobject_p.h index ad0929987d..366319723d 100644 --- a/src/qml/jsruntime/qv4generatorobject_p.h +++ b/src/qml/jsruntime/qv4generatorobject_p.h @@ -72,9 +72,9 @@ struct GeneratorFunctionCtor : FunctionObject { void init(QV4::ExecutionContext *scope); }; -struct GeneratorFunction : ScriptFunction { +struct GeneratorFunction : ArrowFunction { void init(QV4::ExecutionContext *scope, Function *function, QV4::String *name = nullptr) { - ScriptFunction::initNoConstructor(scope, function, name); + ArrowFunction::init(scope, function, name); } }; @@ -106,13 +106,12 @@ struct GeneratorFunctionCtor : FunctionCtor static ReturnedValue virtualCall(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc); }; -struct GeneratorFunction : ScriptFunction +struct GeneratorFunction : ArrowFunction { - V4_OBJECT2(GeneratorFunction, ScriptFunction) + V4_OBJECT2(GeneratorFunction, ArrowFunction) V4_INTERNALCLASS(GeneratorFunction) static Heap::FunctionObject *create(ExecutionContext *scope, Function *function); - static constexpr VTable::CallAsConstructor virtualCallAsConstructor = nullptr; static ReturnedValue virtualCall(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc); }; @@ -122,7 +121,6 @@ struct MemberGeneratorFunction : MemberFunction V4_INTERNALCLASS(MemberGeneratorFunction) static Heap::FunctionObject *create(ExecutionContext *scope, Function *function, Object *homeObject, String *name); - static constexpr VTable::CallAsConstructor virtualCallAsConstructor = nullptr; static ReturnedValue virtualCall(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc); }; diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index 8f529cea76..0a098ff7ef 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -987,8 +987,8 @@ static Object *getSuperBase(Scope &scope) } ScopedFunctionObject f(scope, scope.engine->currentStackFrame->jsFrame->function); - MemberFunction *m = f->as<MemberFunction>(); - if (!m) { + ScopedObject homeObject(scope, f->getHomeObject()); + if (!homeObject) { ScopedContext ctx(scope, static_cast<ExecutionContext *>(&scope.engine->currentStackFrame->jsFrame->context)); Q_ASSERT(ctx); while (ctx) { @@ -1000,13 +1000,12 @@ static Object *getSuperBase(Scope &scope) } ctx = ctx->d()->outer; } - m = f->as<MemberFunction>(); + homeObject = f->getHomeObject(); } - if (!m) { + if (!homeObject) { scope.engine->throwTypeError(); return nullptr; } - ScopedObject homeObject(scope, m->d()->homeObject); Q_ASSERT(homeObject); ScopedObject proto(scope, homeObject->getPrototypeOf()); if (!proto) { |