aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime/qv4scopedvalue_p.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/jsruntime/qv4scopedvalue_p.h')
-rw-r--r--src/qml/jsruntime/qv4scopedvalue_p.h208
1 files changed, 117 insertions, 91 deletions
diff --git a/src/qml/jsruntime/qv4scopedvalue_p.h b/src/qml/jsruntime/qv4scopedvalue_p.h
index 04a0c74133..e4aceef3ee 100644
--- a/src/qml/jsruntime/qv4scopedvalue_p.h
+++ b/src/qml/jsruntime/qv4scopedvalue_p.h
@@ -52,8 +52,8 @@
#include "qv4engine_p.h"
#include "qv4value_p.h"
-#include "qv4persistent_p.h"
#include "qv4property_p.h"
+#include "qv4propertykey_p.h"
#ifdef V4_USE_VALGRIND
#include <valgrind/memcheck.h>
@@ -71,56 +71,45 @@ struct ScopedValue;
#define CHECK_EXCEPTION() \
do { \
if (scope.hasException()) { \
- scope.result = QV4::Encode::undefined(); \
- return; \
+ return QV4::Encode::undefined(); \
} \
} while (false)
#define RETURN_UNDEFINED() \
- do { \
- scope.result = QV4::Encode::undefined(); \
- return; \
- } while (false)
+ return QV4::Encode::undefined()
#define RETURN_RESULT(r) \
- do { \
- scope.result = r; \
- return; \
- } while (false)
+ return QV4::Encode(r)
#define THROW_TYPE_ERROR() \
- do { \
- scope.result = scope.engine->throwTypeError(); \
- return; \
- } while (false)
+ return scope.engine->throwTypeError()
#define THROW_GENERIC_ERROR(str) \
- do { \
- scope.result = scope.engine->throwError(QString::fromUtf8(str)); \
- return; \
- } while (false)
+ return scope.engine->throwError(QString::fromUtf8(str))
struct Scope {
- inline Scope(ExecutionContext *ctx)
+ explicit Scope(ExecutionContext *ctx)
: engine(ctx->engine())
, mark(engine->jsStackTop)
- , result(*engine->jsAlloca(1))
{
- result = Encode::undefined();
}
explicit Scope(ExecutionEngine *e)
: engine(e)
, mark(engine->jsStackTop)
- , result(*engine->jsAlloca(1))
{
- result = Encode::undefined();
+ }
+
+ explicit Scope(const Managed *m)
+ : engine(m->engine())
+ , mark(engine->jsStackTop)
+ {
}
~Scope() {
#ifndef QT_NO_DEBUG
Q_ASSERT(engine->jsStackTop >= mark);
- Q_ASSERT(engine->currentContext < mark);
+// Q_ASSERT(engine->currentContext < mark);
memset(mark, 0, (engine->jsStackTop - mark)*sizeof(Value));
#endif
#ifdef V4_USE_VALGRIND
@@ -129,8 +118,45 @@ struct Scope {
engine->jsStackTop = mark;
}
- QML_NEARLY_ALWAYS_INLINE Value *alloc(int nValues) const {
- return engine->jsAlloca(nValues);
+ enum AllocMode {
+ Undefined,
+ Empty,
+ /* Be careful when using Uninitialized, the stack has to be fully initialized before calling into the memory manager again */
+ Uninitialized
+ };
+ template <AllocMode mode = Undefined>
+ QML_NEARLY_ALWAYS_INLINE Value *alloc(int nValues) const
+ {
+ Value *ptr = engine->jsAlloca(nValues);
+ switch (mode) {
+ case Undefined:
+ for (int i = 0; i < nValues; ++i)
+ ptr[i] = Value::undefinedValue();
+ break;
+ case Empty:
+ for (int i = 0; i < nValues; ++i)
+ ptr[i] = Value::emptyValue();
+ break;
+ case Uninitialized:
+ break;
+ }
+ return ptr;
+ }
+ template <AllocMode mode = Undefined>
+ QML_NEARLY_ALWAYS_INLINE Value *alloc() const
+ {
+ Value *ptr = engine->jsAlloca(1);
+ switch (mode) {
+ case Undefined:
+ *ptr = Value::undefinedValue();
+ break;
+ case Empty:
+ *ptr = Value::emptyValue();
+ break;
+ case Uninitialized:
+ break;
+ }
+ return ptr;
}
bool hasException() const {
@@ -139,7 +165,6 @@ struct Scope {
ExecutionEngine *engine;
Value *mark;
- Value &result;
private:
Q_DISABLE_COPY(Scope)
@@ -149,31 +174,31 @@ struct ScopedValue
{
ScopedValue(const Scope &scope)
{
- ptr = scope.engine->jsStackTop++;
+ ptr = scope.alloc<Scope::Uninitialized>();
ptr->setRawValue(0);
}
ScopedValue(const Scope &scope, const Value &v)
{
- ptr = scope.engine->jsStackTop++;
+ ptr = scope.alloc<Scope::Uninitialized>();
*ptr = v;
}
ScopedValue(const Scope &scope, Heap::Base *o)
{
- ptr = scope.engine->jsStackTop++;
+ ptr = scope.alloc<Scope::Uninitialized>();
ptr->setM(o);
}
ScopedValue(const Scope &scope, Managed *m)
{
- ptr = scope.engine->jsStackTop++;
+ ptr = scope.alloc<Scope::Uninitialized>();
ptr->setRawValue(m->asReturnedValue());
}
ScopedValue(const Scope &scope, const ReturnedValue &v)
{
- ptr = scope.engine->jsStackTop++;
+ ptr = scope.alloc<Scope::Uninitialized>();
ptr->setRawValue(v);
}
@@ -216,77 +241,121 @@ struct ScopedValue
Value *ptr;
};
+
+struct ScopedPropertyKey
+{
+ ScopedPropertyKey(const Scope &scope)
+ {
+ ptr = reinterpret_cast<PropertyKey *>(scope.alloc<Scope::Uninitialized>());
+ *ptr = PropertyKey::invalid();
+ }
+
+ ScopedPropertyKey(const Scope &scope, const PropertyKey &v)
+ {
+ ptr = reinterpret_cast<PropertyKey *>(scope.alloc<Scope::Uninitialized>());
+ *ptr = v;
+ }
+
+ ScopedPropertyKey &operator=(const PropertyKey &other) {
+ *ptr = other;
+ return *this;
+ }
+
+ PropertyKey *operator->() {
+ return ptr;
+ }
+ operator PropertyKey() const {
+ return *ptr;
+ }
+
+ bool operator==(const PropertyKey &other) const {
+ return *ptr == other;
+ }
+ bool operator==(const ScopedPropertyKey &other) const {
+ return *ptr == *other.ptr;
+ }
+ bool operator!=(const PropertyKey &other) const {
+ return *ptr != other;
+ }
+ bool operator!=(const ScopedPropertyKey &other) const {
+ return *ptr != *other.ptr;
+ }
+
+ PropertyKey *ptr;
+};
+
+
template<typename T>
struct Scoped
{
enum ConvertType { Convert };
QML_NEARLY_ALWAYS_INLINE void setPointer(const Managed *p) {
- ptr->setM(p ? p->m() : 0);
+ ptr->setM(p ? p->m() : nullptr);
}
QML_NEARLY_ALWAYS_INLINE Scoped(const Scope &scope)
{
- ptr = scope.engine->jsAlloca(1);
+ ptr = scope.alloc<Scope::Undefined>();
}
QML_NEARLY_ALWAYS_INLINE Scoped(const Scope &scope, const Value &v)
{
- ptr = scope.engine->jsAlloca(1);
+ ptr = scope.alloc<Scope::Uninitialized>();
setPointer(v.as<T>());
}
QML_NEARLY_ALWAYS_INLINE Scoped(const Scope &scope, Heap::Base *o)
{
Value v;
v = o;
- ptr = scope.engine->jsAlloca(1);
+ ptr = scope.alloc<Scope::Uninitialized>();
setPointer(v.as<T>());
}
QML_NEARLY_ALWAYS_INLINE Scoped(const Scope &scope, const ScopedValue &v)
{
- ptr = scope.engine->jsAlloca(1);
+ ptr = scope.alloc<Scope::Uninitialized>();
setPointer(v.ptr->as<T>());
}
QML_NEARLY_ALWAYS_INLINE Scoped(const Scope &scope, const Value &v, ConvertType)
{
- ptr = scope.engine->jsAlloca(1);
+ ptr = scope.alloc<Scope::Uninitialized>();
ptr->setRawValue(value_convert<T>(scope.engine, v));
}
QML_NEARLY_ALWAYS_INLINE Scoped(const Scope &scope, const Value *v)
{
- ptr = scope.engine->jsAlloca(1);
- setPointer(v ? v->as<T>() : 0);
+ ptr = scope.alloc<Scope::Uninitialized>();
+ setPointer(v ? v->as<T>() : nullptr);
}
QML_NEARLY_ALWAYS_INLINE Scoped(const Scope &scope, T *t)
{
- ptr = scope.engine->jsAlloca(1);
+ ptr = scope.alloc<Scope::Uninitialized>();
setPointer(t);
}
QML_NEARLY_ALWAYS_INLINE Scoped(const Scope &scope, const T *t)
{
- ptr = scope.engine->jsAlloca(1);
+ ptr = scope.alloc<Scope::Uninitialized>();
setPointer(t);
}
QML_NEARLY_ALWAYS_INLINE Scoped(const Scope &scope, typename T::Data *t)
{
- ptr = scope.engine->jsAlloca(1);
+ ptr = scope.alloc<Scope::Uninitialized>();
*ptr = t;
}
QML_NEARLY_ALWAYS_INLINE Scoped(const Scope &scope, const ReturnedValue &v)
{
- ptr = scope.engine->jsAlloca(1);
+ ptr = scope.alloc<Scope::Uninitialized>();
setPointer(QV4::Value::fromReturnedValue(v).as<T>());
}
QML_NEARLY_ALWAYS_INLINE Scoped(const Scope &scope, const ReturnedValue &v, ConvertType)
{
- ptr = scope.engine->jsAlloca(1);
+ ptr = scope.alloc<Scope::Uninitialized>();
ptr->setRawValue(value_convert<T>(scope.engine, QV4::Value::fromReturnedValue(v)));
}
@@ -303,7 +372,7 @@ struct Scoped
return *this;
}
Scoped<T> &operator=(Value *v) {
- setPointer(v ? v->as<T>() : 0);
+ setPointer(v ? v->as<T>() : nullptr);
return *this;
}
@@ -337,10 +406,7 @@ struct Scoped
return getPointer();
}
- bool operator!() const {
- return !ptr->m();
- }
- operator void *() const {
+ explicit operator bool() const {
return ptr->m();
}
@@ -363,27 +429,6 @@ struct Scoped
Value *ptr;
};
-struct ScopedCallData {
- ScopedCallData(const Scope &scope, int argc = 0)
- {
- int size = int(offsetof(QV4::CallData, args)/sizeof(QV4::Value)) + qMax(argc , int(QV4::Global::ReservedArgumentCount));
- ptr = reinterpret_cast<CallData *>(scope.alloc(size));
- ptr->tag = quint32(QV4::Value::ValueTypeInternal::Integer);
- ptr->argc = argc;
- }
-
- CallData *operator->() {
- return ptr;
- }
-
- operator CallData *() const {
- return ptr;
- }
-
- CallData *ptr;
-};
-
-
inline Value &Value::operator =(const ScopedValue &v)
{
_val = v.ptr->rawValue();
@@ -411,25 +456,6 @@ struct ScopedProperty
Property *property;
};
-struct ExecutionContextSaver
-{
- Scope scope; // this makes sure that a reference to context on the JS stack goes out of scope as soon as the context is not used anymore.
- ExecutionContext *savedContext;
-
- ExecutionContextSaver(const Scope &scope)
- : scope(scope.engine)
- {
- savedContext = scope.engine->currentContext;
- }
- ~ExecutionContextSaver()
- {
- Q_ASSERT(scope.engine->jsStackTop > scope.engine->currentContext);
- scope.engine->currentContext = savedContext;
- scope.engine->current = savedContext->d();
- }
-};
-
-
}
QT_END_NAMESPACE