aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2018-09-18 17:01:59 +0200
committerLars Knoll <lars.knoll@qt.io>2018-09-23 17:27:43 +0000
commita97d118bf55e1c44ded9bbcd143b0f0725db8268 (patch)
treee0f22b61ba294199758eaf25c7e4f3c71bae7470 /src
parent3440b8f9c5b198be4124ee1defd69d807bb972c6 (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.cpp7
-rw-r--r--src/qml/jsruntime/qv4enginebase_p.h1
-rw-r--r--src/qml/jsruntime/qv4functionobject.cpp24
-rw-r--r--src/qml/jsruntime/qv4functionobject_p.h45
-rw-r--r--src/qml/jsruntime/qv4generatorobject_p.h10
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp9
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) {