summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJedrzej Nowacki <jedrzej.nowacki@nokia.com>2011-05-19 16:34:32 +0200
committerJedrzej Nowacki <jedrzej.nowacki@nokia.com>2011-05-25 10:56:26 +0200
commit8a84d56c572b163b6f4e50f3f66d6bb3cc057a03 (patch)
treec1c5ca7374cd137f8ce5ff9beecaf73dad333942
parent41668e40943f596dc3f64b2ec827ed40d9e25408 (diff)
Introduce optimized Handle class for QScriptContextPrivate usage.
New class depending on parameter behaves as v8::Local or as v8::Persistent. According to benchmarks, The QSCP::Handle class together with QSCP::Stack and QSCP::Heap classes gives us QObject bindings speedup from 2-12% (it reduce significantly v8::Persistent usage).
-rw-r--r--src/script/api/qscriptclass.cpp2
-rw-r--r--src/script/api/qscriptcontext_impl_p.h66
-rw-r--r--src/script/api/qscriptcontext_p.h142
-rw-r--r--src/script/api/qscriptcontextinfo.cpp2
4 files changed, 185 insertions, 27 deletions
diff --git a/src/script/api/qscriptclass.cpp b/src/script/api/qscriptclass.cpp
index ad6d8ac..0e5aac6 100644
--- a/src/script/api/qscriptclass.cpp
+++ b/src/script/api/qscriptclass.cpp
@@ -249,7 +249,7 @@ v8::Handle<v8::Value> QScriptClassObject::call(const v8::Arguments& args)
if (!userCallback->supportsExtension(QScriptClass::Callable))
return handleScope.Close(v8::ThrowException(v8::Exception::TypeError(v8::String::New("QScriptClass for object doesn't support Callable extension"))));
- v8::Handle<v8::Object> thisObject;
+ v8::Local<v8::Object> thisObject;
// v8 doesn't create a new Object to put in This() when the constructor call came from
// a callback registered with SetCallAsFunctionHandler().
diff --git a/src/script/api/qscriptcontext_impl_p.h b/src/script/api/qscriptcontext_impl_p.h
index 266f2d0..b2305e0 100644
--- a/src/script/api/qscriptcontext_impl_p.h
+++ b/src/script/api/qscriptcontext_impl_p.h
@@ -51,10 +51,10 @@ inline QScriptContextPrivate::QScriptContextPrivate(const AllocationType type, Q
inline QScriptContextPrivate::QScriptContextPrivate(const AllocationType type, QScriptEnginePrivate *engine, const v8::Arguments *args, v8::Handle<v8::Value> callee, v8::Handle<v8::Object> customThisObject)
: m_allocation(type), q_ptr(this), engine(engine), arguments(args), accessorInfo(0),
- context(v8::Persistent<v8::Context>::New(v8::Context::NewFunctionContext())),
- inheritedScope(v8::Persistent<v8::Context>::New(v8::Context::GetCallerContext())),
- parent(engine->setCurrentQSContext(this)), previous(0), m_thisObject(v8::Persistent<v8::Object>::New(customThisObject)),
- m_callee(v8::Persistent<v8::Value>::New(callee)), hasArgumentGetter(false)
+ context(type, v8::Context::NewFunctionContext()),
+ inheritedScope(type, v8::Context::GetCallerContext()),
+ parent(engine->setCurrentQSContext(this)), previous(0), m_thisObject(type, customThisObject),
+ m_callee(type, callee), hasArgumentGetter(false)
{
Q_ASSERT(engine);
Q_ASSERT(parent);
@@ -63,8 +63,8 @@ inline QScriptContextPrivate::QScriptContextPrivate(const AllocationType type, Q
inline QScriptContextPrivate::QScriptContextPrivate(const AllocationType type, QScriptEnginePrivate *engine, const v8::AccessorInfo *accessor)
: m_allocation(type), q_ptr(this), engine(engine), arguments(0), accessorInfo(accessor),
- context(v8::Persistent<v8::Context>::New(v8::Context::NewFunctionContext())),
- inheritedScope(v8::Persistent<v8::Context>::New(v8::Context::GetCallerContext())),
+ context(type, v8::Context::NewFunctionContext()),
+ inheritedScope(type, v8::Context::GetCallerContext()),
parent(engine->setCurrentQSContext(this)), previous(0), hasArgumentGetter(false)
{
Q_ASSERT(engine);
@@ -74,7 +74,8 @@ inline QScriptContextPrivate::QScriptContextPrivate(const AllocationType type, Q
inline QScriptContextPrivate::QScriptContextPrivate(const AllocationType type, QScriptEnginePrivate *engine, v8::Handle<v8::Context> context)
: m_allocation(type), q_ptr(this), engine(engine), arguments(0), accessorInfo(0),
- context(v8::Persistent<v8::Context>::New(context)), parent(engine->setCurrentQSContext(this)),
+ context(type, context),
+ parent(engine->setCurrentQSContext(this)),
previous(0), hasArgumentGetter(false)
{
Q_ASSERT(engine);
@@ -84,7 +85,39 @@ inline QScriptContextPrivate::QScriptContextPrivate(const AllocationType type, Q
inline QScriptContextPrivate::QScriptContextPrivate(const AllocationType type, QScriptContextPrivate *parent, v8::Handle<v8::StackFrame> frame)
: m_allocation(type), q_ptr(this), engine(parent->engine), arguments(0), accessorInfo(0),
- parent(parent), previous(0), frame(v8::Persistent<v8::StackFrame>::New(frame)), hasArgumentGetter(false)
+ parent(parent), previous(0), frame(type, frame), hasArgumentGetter(false)
+{
+ Q_ASSERT(engine);
+ Q_ASSERT(parent);
+}
+
+inline QScriptContextPrivate::QScriptContextPrivate(const AllocationType type, QScriptEnginePrivate *engine, const v8::Arguments *args, v8::Local<v8::Value> callee, v8::Local<v8::Object> customThisObject)
+ : m_allocation(type), q_ptr(this), engine(engine), arguments(args), accessorInfo(0),
+ context(type, v8::Context::NewFunctionContext()),
+ inheritedScope(type, v8::Context::GetCallerContext()),
+ parent(engine->setCurrentQSContext(this)), previous(0), m_thisObject(type, customThisObject),
+ m_callee(type, callee), hasArgumentGetter(false)
+{
+ Q_ASSERT(engine);
+ Q_ASSERT(parent);
+ context->Enter();
+}
+
+
+inline QScriptContextPrivate::QScriptContextPrivate(const AllocationType type, QScriptEnginePrivate *engine, v8::Local<v8::Context> context)
+ : m_allocation(type), q_ptr(this), engine(engine), arguments(0), accessorInfo(0),
+ context(type, context),
+ parent(engine->setCurrentQSContext(this)),
+ previous(0), hasArgumentGetter(false)
+{
+ Q_ASSERT(engine);
+ Q_ASSERT(parent);
+ context->Enter();
+}
+
+inline QScriptContextPrivate::QScriptContextPrivate(const AllocationType type, QScriptContextPrivate *parent, v8::Local<v8::StackFrame> frame)
+ : m_allocation(type), q_ptr(this), engine(parent->engine), arguments(0), accessorInfo(0),
+ parent(parent), previous(0), frame(type, frame), hasArgumentGetter(false)
{
Q_ASSERT(engine);
Q_ASSERT(parent);
@@ -166,7 +199,7 @@ inline v8::Handle<v8::Object> QScriptContextPrivate::thisObject() const
// setThisObject() doesn't work for native functions, but the constructor for native function
// can set m_thisObject, so we give it higher precedence.
if (!m_thisObject.IsEmpty()) {
- return m_thisObject;
+ return m_thisObject.v8Handle();
} else if (isNativeFunction()) {
return arguments->This();
} else if (isNativeAccessor()) {
@@ -197,8 +230,7 @@ inline void QScriptContextPrivate::setThisObject(QScriptValuePrivate *newThis)
return;
}
- m_thisObject.Dispose();
- m_thisObject = v8::Persistent<v8::Object>::New(*newThis);
+ m_thisObject = static_cast<v8::Handle<v8::Object> >(*newThis);
}
@@ -206,7 +238,7 @@ inline QScriptPassPointer<QScriptValuePrivate> QScriptContextPrivate::callee() c
{
if (isNativeFunction()) {
if (!m_callee.IsEmpty())
- return new QScriptValuePrivate(engine, m_callee);
+ return new QScriptValuePrivate(engine, m_callee.v8Handle());
return new QScriptValuePrivate(engine, arguments->Callee());
}
@@ -271,7 +303,7 @@ inline QScriptValueList QScriptContextPrivate::scopeChain() const
list.append(QScriptValuePrivate::get(activationObject()));
if (!inheritedScope.IsEmpty()) {
- v8::Handle<v8::Context> current = inheritedScope;
+ v8::Handle<v8::Context> current = inheritedScope.v8Handle();
do {
v8::Handle<v8::Object> object = current->GetExtensionObject();
list.append(QScriptValuePrivate::get(new QScriptValuePrivate(engine, object)));
@@ -290,8 +322,8 @@ inline QScriptValueList QScriptContextPrivate::scopeChain() const
inline void QScriptContextPrivate::pushScope(QScriptValuePrivate *object)
{
v8::Handle<v8::Object> objectHandle(v8::Object::Cast(*object->asV8Value(engine)));
- v8::Handle<v8::Context> scopeContext = v8::Context::NewScopeContext(objectHandle);
- scopes.append(v8::Persistent<v8::Context>::New(scopeContext));
+ Handle<v8::Context> scopeContext(m_allocation, v8::Context::NewScopeContext(objectHandle));
+ scopes.append(scopeContext);
scopeContext->Enter();
}
@@ -303,7 +335,7 @@ inline QScriptPassPointer<QScriptValuePrivate> QScriptContextPrivate::popScope()
Q_UNIMPLEMENTED();
return InvalidValue();
}
- v8::Persistent<v8::Context> scopeContext = scopes.takeLast();
+ Handle<v8::Context> scopeContext = scopes.takeLast();
v8::Handle<v8::Object> object = scopeContext->GetExtensionObject();
scopeContext->Exit();
scopeContext.Dispose();
@@ -384,7 +416,7 @@ inline QScriptContextPrivate::Stack::Stack(QScriptEnginePrivate *engine) // the
: QScriptContextPrivate(StackAllocation, engine)
{}
-inline QScriptContextPrivate::Stack::Stack(QScriptEnginePrivate *engine, const v8::Arguments *args, v8::Handle<v8::Value> callee, v8::Handle<v8::Object> customThisObject) // native function context (on the stack)
+inline QScriptContextPrivate::Stack::Stack(QScriptEnginePrivate *engine, const v8::Arguments *args, v8::Local<v8::Value> callee, v8::Local<v8::Object> customThisObject) // native function context (on the stack)
: QScriptContextPrivate(StackAllocation, engine, args, callee, customThisObject)
{}
diff --git a/src/script/api/qscriptcontext_p.h b/src/script/api/qscriptcontext_p.h
index daac674..d9bd218 100644
--- a/src/script/api/qscriptcontext_p.h
+++ b/src/script/api/qscriptcontext_p.h
@@ -59,9 +59,136 @@ protected:
inline QScriptContextPrivate(const AllocationType type, QScriptEnginePrivate *engine, v8::Handle<v8::Context> context); // from QScriptEngine::pushContext
inline QScriptContextPrivate(const AllocationType type, QScriptContextPrivate *parent, v8::Handle<v8::StackFrame> frame); // internal, for js frame (allocated in parentContext())
+ inline QScriptContextPrivate(const AllocationType type, QScriptEnginePrivate *engine, const v8::Arguments *args, v8::Local<v8::Value> callee = v8::Local<v8::Value>(), v8::Local<v8::Object> customThisObject = v8::Local<v8::Object>()); // native function context (on the stack)
+ inline QScriptContextPrivate(const AllocationType type, QScriptEnginePrivate *engine, v8::Local<v8::Context> context); // from QScriptEngine::pushContext
+ inline QScriptContextPrivate(const AllocationType type, QScriptContextPrivate *parent, v8::Local<v8::StackFrame> frame); // internal, for js frame (allocated in parentContext())
public:
class Stack;
class Heap;
+ template<class T>
+ class Handle : protected v8::Handle<T>
+ {
+ public:
+ typedef QScriptContextPrivate::AllocationType Type;
+
+ Handle()
+ : m_type(HeapAllocation) // lazy fall-back to Persistent
+ {}
+
+ Handle(Type type)
+ : m_type(type)
+ {}
+
+ Handle(Type type, v8::Handle<T> handle)
+ : m_type(type)
+ {
+ switch (m_type){
+ case Local: *asLocal() = v8::Local<T>::New(handle); break;
+ case Persistent: *asPersistent() = v8::Persistent<T>::New(handle); break;
+ }
+ }
+
+ Handle(Type type, v8::Local<T> handle)
+ : m_type(type)
+ {
+ switch (m_type){
+ case Local:
+ // We do not need to call Local::New because this local is already protected by
+ // a higher HandleScope that would survive longer than this QScriptContextPrivate
+ *asLocal() = handle;
+ break;
+ case Persistent: *asPersistent() = v8::Persistent<T>::New(handle); break;
+ }
+ }
+
+
+ Handle(const Handle<T>& handle)
+ : v8::Handle<T>(*handle)
+ , m_type(handle.m_type)
+ {
+ switch (m_type){
+ case Local:
+ // The other handle is already protected, its live time would the same or a bit longer
+ // so we do not need Local::New here.
+ break;
+ case Persistent: *asPersistent() = v8::Persistent<T>::New(handle); break;
+ }
+ }
+
+ void operator =(v8::Handle<T> handle)
+ {
+ switch (m_type){
+ case Local: *asLocal() = v8::Local<T>::New(handle); break;
+ case Persistent:
+ asPersistent()->Dispose();
+ *asPersistent() = v8::Persistent<T>::New(handle);
+ break;
+ }
+ }
+
+ void operator =(v8::Local<T> handle)
+ {
+ switch (m_type){
+ case Local:
+ // The other handle is already protected, its live time would the same or a bit longer
+ // so we do not need Local::New here.
+ *asLocal() = handle;
+ break;
+ case Persistent:
+ asPersistent()->Dispose();
+ *asPersistent() = v8::Persistent<T>::New(handle);
+ break;
+ }
+ }
+
+ void operator =(Handle<T> handle)
+ {
+ Q_ASSERT(handle.m_type == m_type);
+ switch (m_type) {
+ case Local:
+ // The other handle is already protected, its live time would the same or a bit longer
+ // so we do not need Local::New here.
+ *asLocal() = *handle.asLocal();
+ break;
+ case Persistent:
+ asPersistent()->Dispose();
+ *asPersistent() = v8::Persistent<T>::New(handle);
+ break;
+ }
+ }
+
+ void Dispose()
+ {
+ if (m_type == Persistent) {
+ asPersistent()->Dispose();
+ // FIXME: maybe it is not needed ?
+ asPersistent()->Clear();
+ }
+ }
+
+ inline T* operator->() const { return v8::Handle<T>::operator ->(); }
+ inline T* operator*() const { return v8::Handle<T>::operator *(); }
+ inline bool IsEmpty() const { return v8::Handle<T>::IsEmpty(); }
+ inline v8::Handle<T> v8Handle() const { return v8::Handle<T>(*this); }
+
+ private:
+ static const int Persistent = QScriptContextPrivate::HeapAllocation;
+ static const int Local = QScriptContextPrivate::StackAllocation;
+ const Type m_type;
+
+ inline v8::Persistent<T> *asPersistent()
+ {
+ Q_ASSERT(m_type == Persistent);
+ return reinterpret_cast<v8::Persistent<T> *>(this);
+ }
+
+ inline v8::Local<T> *asLocal()
+ {
+ Q_ASSERT(m_type == Local);
+ return reinterpret_cast<v8::Local<T> *>(this);
+ }
+ };
+
static QScriptContextPrivate *get(const QScriptContext *q) { Q_ASSERT(q->d_ptr); return q->d_ptr; }
static QScriptContext *get(QScriptContextPrivate *d) { return d->q_func(); }
@@ -96,15 +223,15 @@ public:
QScriptEnginePrivate *engine;
const v8::Arguments *arguments;
const v8::AccessorInfo *accessorInfo;
- v8::Persistent<v8::Context> context;
- QList<v8::Persistent<v8::Context> > scopes;
- v8::Persistent<v8::Context> inheritedScope;
+ Handle<v8::Context> context;
+ QList<Handle<v8::Context> > scopes;
+ Handle<v8::Context> inheritedScope;
QScriptContextPrivate *parent; //the parent native frame as seen by the engine
mutable QScriptContextPrivate *previous; //the previous js frame (lazily build)
- v8::Persistent<v8::StackFrame> frame; //only for js frames
+ Handle<v8::StackFrame> frame; //only for js frames
QScriptSharedDataPointer<QScriptValuePrivate> argsObject;
- v8::Persistent<v8::Object> m_thisObject;
- v8::Persistent<v8::Value> m_callee;
+ Handle<v8::Object> m_thisObject;
+ Handle<v8::Value> m_callee;
bool hasArgumentGetter;
static const int stackTraceLimit = 100;
@@ -123,7 +250,7 @@ class QScriptContextPrivate::Stack : public QScriptContextPrivate
{
public:
inline Stack(QScriptEnginePrivate *engine); // the global context (member of QScriptEnginePrivate)
- inline Stack(QScriptEnginePrivate *engine, const v8::Arguments *args, v8::Handle<v8::Value> callee = v8::Handle<v8::Value>(), v8::Handle<v8::Object> customThisObject = v8::Handle<v8::Object>()); // native function context (on the stack)
+ inline Stack(QScriptEnginePrivate *engine, const v8::Arguments *args, v8::Local<v8::Value> callee = v8::Local<v8::Value>(), v8::Local<v8::Object> customThisObject = v8::Local<v8::Object>()); // native function context (on the stack)
inline Stack(QScriptEnginePrivate *engine, const v8::AccessorInfo *accessor); // native acessors (on the stack)
// Only base class is used so destructor here is pointless
private:
@@ -145,7 +272,6 @@ public:
// Only base class is used so a destructor here is pointless
};
-
QT_END_NAMESPACE
#endif
diff --git a/src/script/api/qscriptcontextinfo.cpp b/src/script/api/qscriptcontextinfo.cpp
index ca96ecb..274fa81 100644
--- a/src/script/api/qscriptcontextinfo.cpp
+++ b/src/script/api/qscriptcontextinfo.cpp
@@ -128,7 +128,7 @@ QScriptContextInfoPrivate::QScriptContextInfoPrivate(const QScriptContext *conte
QScriptIsolate api(context_p->engine, QScriptIsolate::NotNullEngine);
v8::HandleScope handleScope;
if (context_p->isJSFrame()) {
- v8::Handle<v8::StackFrame> frame = context_p->frame;
+ v8::Handle<v8::StackFrame> frame = context_p->frame.v8Handle();
scriptId = frame->GetScriptId()->NumberValue();
columnNumber = frame->GetColumn();
lineNumber = frame->GetLineNumber();