diff options
author | Lars Knoll <lars.knoll@digia.com> | 2014-03-05 08:40:11 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2014-03-07 16:55:12 +0100 |
commit | b8ca4132433c2d1eef0a6cda8be8a1754786702b (patch) | |
tree | 4ace1513d0aaaa09b98bcc39f2a4fb2e08e0d59d /src/qml/jsruntime | |
parent | f836b9837dda09c09c2ee3307300998ca5dff5c4 (diff) |
Better way of retrieving the prototype property for FunctionObjects
Make sure FunctionObjects always have the prototype property at
index 0. This way we can speed up the instanceOf operator even more,
and at the same time save 16-28 bytes of memory per FunctionObject.
Change-Id: I8527bc8f9dc7b04a9db8395b5f05bab47ddc21ce
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'src/qml/jsruntime')
-rw-r--r-- | src/qml/jsruntime/qv4engine.cpp | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4engine_p.h | 1 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4functionobject.cpp | 75 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4functionobject_p.h | 18 |
4 files changed, 31 insertions, 65 deletions
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 6b2d1e657b..18075139d2 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -283,7 +283,7 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory) FunctionPrototype *functionPrototype = new (memoryManager) FunctionPrototype(InternalClass::create(this, FunctionPrototype::staticVTable(), objectPrototype)); functionClass = InternalClass::create(this, FunctionObject::staticVTable(), functionPrototype); uint index; - functionWithProtoClass = functionClass->addMember(id_prototype, Attr_NotEnumerable|Attr_NotConfigurable, &index); + functionClass = functionClass->addMember(id_prototype, Attr_NotEnumerable|Attr_NotConfigurable, &index); Q_ASSERT(index == FunctionObject::Index_Prototype); protoClass = objectClass->addMember(id_constructor, Attr_NotEnumerable, &index); Q_ASSERT(index == FunctionObject::Index_ProtoConstructor); diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h index cbe9815d4f..14358c1bb6 100644 --- a/src/qml/jsruntime/qv4engine_p.h +++ b/src/qml/jsruntime/qv4engine_p.h @@ -210,7 +210,6 @@ public: InternalClass *dateClass; InternalClass *functionClass; - InternalClass *functionWithProtoClass; InternalClass *protoClass; InternalClass *regExpClass; diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index f0966492a9..9a3aa331dc 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -75,21 +75,17 @@ using namespace QV4; DEFINE_OBJECT_VTABLE(FunctionObject); FunctionObject::FunctionObject(ExecutionContext *scope, const StringRef name, bool createProto) - : Object(createProto ? scope->engine->functionWithProtoClass : scope->engine->functionClass) + : Object(scope->engine->functionClass) , scope(scope) , function(0) - , protoCacheClass(0) - , protoCacheIndex(UINT_MAX) { init(name, createProto); } FunctionObject::FunctionObject(ExecutionContext *scope, const QString &name, bool createProto) - : Object(createProto ? scope->engine->functionWithProtoClass : scope->engine->functionClass) + : Object(scope->engine->functionClass) , scope(scope) , function(0) - , protoCacheClass(0) - , protoCacheIndex(UINT_MAX) { Scope s(scope); ScopedValue protectThis(s, this); @@ -101,8 +97,6 @@ FunctionObject::FunctionObject(ExecutionContext *scope, const ReturnedValue name : Object(scope->engine->functionClass) , scope(scope) , function(0) - , protoCacheClass(0) - , protoCacheIndex(UINT_MAX) { Scope s(scope); ScopedValue protectThis(s, this); @@ -117,6 +111,7 @@ FunctionObject::FunctionObject(InternalClass *ic) { needsActivation = false; strictMode = false; + memberData[Index_Prototype].value = Encode::undefined(); } FunctionObject::~FunctionObject() @@ -137,6 +132,9 @@ void FunctionObject::init(const StringRef n, bool createProto) Scoped<Object> proto(s, scope->engine->newObject(scope->engine->protoClass)); proto->memberData[Index_ProtoConstructor].value = this->asReturnedValue(); memberData[Index_Prototype].value = proto.asReturnedValue(); + } else { + // ### Empty or undefined? + memberData[Index_Prototype].value = Encode::undefined(); } ScopedValue v(s, n.asReturnedValue()); @@ -158,13 +156,8 @@ ReturnedValue FunctionObject::newInstance() ReturnedValue FunctionObject::construct(Managed *that, CallData *) { - ExecutionEngine *v4 = that->internalClass->engine; - Scope scope(v4); - Scoped<FunctionObject> f(scope, that, Scoped<FunctionObject>::Cast); - - InternalClass *ic = f->internalClassForConstructor(); - Scoped<Object> obj(scope, v4->newObject(ic)); - return obj.asReturnedValue(); + that->internalClass->engine->currentContext()->throwTypeError(); + return Encode::undefined(); } ReturnedValue FunctionObject::call(Managed *, CallData *) @@ -190,43 +183,6 @@ FunctionObject *FunctionObject::creatScriptFunction(ExecutionContext *scope, Fun return new (scope->engine->memoryManager) SimpleScriptFunction(scope, function, createProto); } -ReturnedValue FunctionObject::protoProperty() -{ - if (protoCacheClass != internalClass) { - protoCacheClass = internalClass; - protoCacheIndex = internalClass->find(internalClass->engine->id_prototype); - } - if (protoCacheIndex < UINT_MAX) { - if (internalClass->propertyData.at(protoCacheIndex).isData()) { - ReturnedValue v = memberData[protoCacheIndex].value.asReturnedValue(); - if (v != protoValue) { - classForConstructor = 0; - protoValue = v; - } - return v; - } - } - classForConstructor = 0; - return get(internalClass->engine->id_prototype); -} - -InternalClass *FunctionObject::internalClassForConstructor() -{ - // need to call this first to ensure we don't use a wrong class - ReturnedValue proto = protoProperty(); - if (classForConstructor) - return classForConstructor; - - Scope scope(internalClass->engine); - ScopedObject p(scope, proto); - if (p) - classForConstructor = InternalClass::create(scope.engine, Object::staticVTable(), p.getPointer()); - else - classForConstructor = scope.engine->objectClass; - - return classForConstructor; -} - DEFINE_OBJECT_VTABLE(FunctionCtor); FunctionCtor::FunctionCtor(ExecutionContext *scope) @@ -395,7 +351,7 @@ ReturnedValue FunctionPrototype::method_bind(CallContext *ctx) DEFINE_OBJECT_VTABLE(ScriptFunction); ScriptFunction::ScriptFunction(ExecutionContext *scope, Function *function) - : FunctionObject(scope, function->name(), true) + : SimpleScriptFunction(scope, function, true) { setVTable(staticVTable()); @@ -583,6 +539,19 @@ ReturnedValue SimpleScriptFunction::call(Managed *that, CallData *callData) return result.asReturnedValue(); } +InternalClass *SimpleScriptFunction::internalClassForConstructor() +{ + ReturnedValue proto = protoProperty(); + InternalClass *classForConstructor; + Scope scope(internalClass->engine); + ScopedObject p(scope, proto); + if (p) + classForConstructor = InternalClass::create(scope.engine, Object::staticVTable(), p.getPointer()); + else + classForConstructor = scope.engine->objectClass; + + return classForConstructor; +} diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h index 3f432c2f26..a08dc603ff 100644 --- a/src/qml/jsruntime/qv4functionobject_p.h +++ b/src/qml/jsruntime/qv4functionobject_p.h @@ -116,10 +116,6 @@ struct Q_QML_EXPORT FunctionObject: Object { unsigned int formalParameterCount() { return function ? function->compiledFunction->nFormals : 0; } unsigned int varCount() { return function ? function->compiledFunction->nLocals : 0; } Function *function; - InternalClass *protoCacheClass; - uint protoCacheIndex; - ReturnedValue protoValue; - InternalClass *classForConstructor; FunctionObject(ExecutionContext *scope, const StringRef name, bool createProto = false); FunctionObject(ExecutionContext *scope, const QString &name = QString(), bool createProto = false); @@ -141,8 +137,7 @@ struct Q_QML_EXPORT FunctionObject: Object { static FunctionObject *creatScriptFunction(ExecutionContext *scope, Function *function, bool createProto = true); - ReturnedValue protoProperty(); - InternalClass *internalClassForConstructor(); + ReturnedValue protoProperty() { return memberData[Index_Prototype].value.asReturnedValue(); } protected: FunctionObject(InternalClass *ic); @@ -213,22 +208,25 @@ struct IndexedBuiltinFunction: FunctionObject }; -struct ScriptFunction: FunctionObject { +struct SimpleScriptFunction: FunctionObject { V4_OBJECT - ScriptFunction(ExecutionContext *scope, Function *function); + SimpleScriptFunction(ExecutionContext *scope, Function *function, bool createProto); static ReturnedValue construct(Managed *, CallData *callData); static ReturnedValue call(Managed *that, CallData *callData); + + InternalClass *internalClassForConstructor(); }; -struct SimpleScriptFunction: FunctionObject { +struct ScriptFunction: SimpleScriptFunction { V4_OBJECT - SimpleScriptFunction(ExecutionContext *scope, Function *function, bool createProto); + ScriptFunction(ExecutionContext *scope, Function *function); static ReturnedValue construct(Managed *, CallData *callData); static ReturnedValue call(Managed *that, CallData *callData); }; + struct BoundFunction: FunctionObject { V4_OBJECT FunctionObject *target; |