diff options
author | Erik Verbruggen <erik.verbruggen@qt.io> | 2016-11-25 11:24:25 +0100 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2016-11-29 15:31:33 +0000 |
commit | 58d0fc4dcf99b867d1f0bd67327105983ec36e07 (patch) | |
tree | d4c1c1579873c96c78322a9234394761c2a7dc40 /src/qml/jsruntime | |
parent | e579076bb36e6594003b2ade7f3d062944ef6f47 (diff) |
V4: Help the C++ compiler to do more DSE by inlining more code
The JS stack allocation initializes the contents, but in most cases the
caller will immediately store a value in that stack slot. When the
allocation code is inlined, the compiler can use dead store elimination
to remove the unnecessary initialization code.
Change-Id: I0495417adc7c1c8764f845032611bd506a8b7df9
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src/qml/jsruntime')
-rw-r--r-- | src/qml/jsruntime/qv4engine_p.h | 3 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4global_p.h | 6 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4scopedvalue_p.h | 37 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4value_p.h | 46 |
4 files changed, 52 insertions, 40 deletions
diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h index 25d6fc1970..d20402b369 100644 --- a/src/qml/jsruntime/qv4engine_p.h +++ b/src/qml/jsruntime/qv4engine_p.h @@ -128,7 +128,8 @@ public: --jsStackTop; return jsStackTop->heapObject(); } - Value *jsAlloca(int nValues) { + + QML_NEARLY_ALWAYS_INLINE Value *jsAlloca(int nValues) { Value *ptr = jsStackTop; jsStackTop = ptr + nValues; for (int i = 0; i < nValues; ++i) diff --git a/src/qml/jsruntime/qv4global_p.h b/src/qml/jsruntime/qv4global_p.h index 184375a9b6..c37ad1668d 100644 --- a/src/qml/jsruntime/qv4global_p.h +++ b/src/qml/jsruntime/qv4global_p.h @@ -58,6 +58,12 @@ #include <QtCore/qglobal.h> #include <QString> +#ifdef QT_NO_DEBUG +#define QML_NEARLY_ALWAYS_INLINE Q_ALWAYS_INLINE +#else +#define QML_NEARLY_ALWAYS_INLINE inline +#endif + #ifdef V4_BOOTSTRAP #include <private/qtqmldevtoolsglobal_p.h> #else diff --git a/src/qml/jsruntime/qv4scopedvalue_p.h b/src/qml/jsruntime/qv4scopedvalue_p.h index 5022d7c3bc..164fbb2997 100644 --- a/src/qml/jsruntime/qv4scopedvalue_p.h +++ b/src/qml/jsruntime/qv4scopedvalue_p.h @@ -97,7 +97,7 @@ struct Scope { engine->jsStackTop = mark; } - Value *alloc(int nValues) const { + QML_NEARLY_ALWAYS_INLINE Value *alloc(int nValues) const { return engine->jsAlloca(nValues); } @@ -189,63 +189,70 @@ struct Scoped { enum ConvertType { Convert }; - inline void setPointer(const Managed *p) { + QML_NEARLY_ALWAYS_INLINE void setPointer(const Managed *p) { ptr->setM(p ? p->m() : 0); } - Scoped(const Scope &scope) + QML_NEARLY_ALWAYS_INLINE Scoped(const Scope &scope) { ptr = scope.engine->jsAlloca(1); } - Scoped(const Scope &scope, const Value &v) + QML_NEARLY_ALWAYS_INLINE Scoped(const Scope &scope, const Value &v) { ptr = scope.engine->jsAlloca(1); setPointer(v.as<T>()); } - Scoped(const Scope &scope, Heap::Base *o) + QML_NEARLY_ALWAYS_INLINE Scoped(const Scope &scope, Heap::Base *o) { Value v; v = o; ptr = scope.engine->jsAlloca(1); setPointer(v.as<T>()); } - Scoped(const Scope &scope, const ScopedValue &v) + QML_NEARLY_ALWAYS_INLINE Scoped(const Scope &scope, const ScopedValue &v) { ptr = scope.engine->jsAlloca(1); setPointer(v.ptr->as<T>()); } - Scoped(const Scope &scope, const Value &v, ConvertType) + QML_NEARLY_ALWAYS_INLINE Scoped(const Scope &scope, const Value &v, ConvertType) { ptr = scope.engine->jsAlloca(1); ptr->setRawValue(value_convert<T>(scope.engine, v)); } - Scoped(const Scope &scope, const Value *v) + QML_NEARLY_ALWAYS_INLINE Scoped(const Scope &scope, const Value *v) { ptr = scope.engine->jsAlloca(1); setPointer(v ? v->as<T>() : 0); } - Scoped(const Scope &scope, T *t) + QML_NEARLY_ALWAYS_INLINE Scoped(const Scope &scope, T *t) { ptr = scope.engine->jsAlloca(1); setPointer(t); } - Scoped(const Scope &scope, typename T::Data *t) + + QML_NEARLY_ALWAYS_INLINE Scoped(const Scope &scope, const T *t) + { + ptr = scope.engine->jsAlloca(1); + setPointer(t); + } + + QML_NEARLY_ALWAYS_INLINE Scoped(const Scope &scope, typename T::Data *t) { ptr = scope.engine->jsAlloca(1); *ptr = t; } - Scoped(const Scope &scope, const ReturnedValue &v) + QML_NEARLY_ALWAYS_INLINE Scoped(const Scope &scope, const ReturnedValue &v) { ptr = scope.engine->jsAlloca(1); setPointer(QV4::Value::fromReturnedValue(v).as<T>()); } - Scoped(const Scope &scope, const ReturnedValue &v, ConvertType) + QML_NEARLY_ALWAYS_INLINE Scoped(const Scope &scope, const ReturnedValue &v, ConvertType) { ptr = scope.engine->jsAlloca(1); ptr->setRawValue(value_convert<T>(scope.engine, QV4::Value::fromReturnedValue(v))); @@ -312,8 +319,8 @@ struct Scoped return ptr; } - ReturnedValue asReturnedValue() const { - return ptr->m() ? ptr->rawValue() : Encode::undefined(); + QML_NEARLY_ALWAYS_INLINE ReturnedValue asReturnedValue() const { + return ptr->rawValue(); } Value *ptr; @@ -358,8 +365,6 @@ struct ScopedProperty ScopedProperty(Scope &scope) { property = reinterpret_cast<Property*>(scope.alloc(sizeof(Property) / sizeof(Value))); - property->value = Encode::undefined(); - property->set = Encode::undefined(); } Property *operator->() { return property; } diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h index 6d5cff4ecc..29d8f196ee 100644 --- a/src/qml/jsruntime/qv4value_p.h +++ b/src/qml/jsruntime/qv4value_p.h @@ -160,9 +160,9 @@ private: quint64 _val; public: - Q_ALWAYS_INLINE quint64 &rawValueRef() { return _val; } - Q_ALWAYS_INLINE quint64 rawValue() const { return _val; } - Q_ALWAYS_INLINE void setRawValue(quint64 raw) { _val = raw; } + QML_NEARLY_ALWAYS_INLINE quint64 &rawValueRef() { return _val; } + QML_NEARLY_ALWAYS_INLINE quint64 rawValue() const { return _val; } + QML_NEARLY_ALWAYS_INLINE void setRawValue(quint64 raw) { _val = raw; } #if Q_BYTE_ORDER == Q_LITTLE_ENDIAN static inline int valueOffset() { return 0; } @@ -171,23 +171,23 @@ public: static inline int valueOffset() { return 4; } static inline int tagOffset() { return 0; } #endif - Q_ALWAYS_INLINE void setTagValue(quint32 tag, quint32 value) { _val = quint64(tag) << 32 | value; } - Q_ALWAYS_INLINE quint32 value() const { return _val & quint64(~quint32(0)); } - Q_ALWAYS_INLINE quint32 tag() const { return _val >> 32; } + QML_NEARLY_ALWAYS_INLINE void setTagValue(quint32 tag, quint32 value) { _val = quint64(tag) << 32 | value; } + QML_NEARLY_ALWAYS_INLINE quint32 value() const { return _val & quint64(~quint32(0)); } + QML_NEARLY_ALWAYS_INLINE quint32 tag() const { return _val >> 32; } #if defined(QV4_USE_64_BIT_VALUE_ENCODING) - Q_ALWAYS_INLINE Heap::Base *m() const + QML_NEARLY_ALWAYS_INLINE Heap::Base *m() const { Heap::Base *b; memcpy(&b, &_val, 8); return b; } - Q_ALWAYS_INLINE void setM(Heap::Base *b) + QML_NEARLY_ALWAYS_INLINE void setM(Heap::Base *b) { memcpy(&_val, &b, 8); } #else // !QV4_USE_64_BIT_VALUE_ENCODING - Q_ALWAYS_INLINE Heap::Base *m() const + QML_NEARLY_ALWAYS_INLINE Heap::Base *m() const { Q_STATIC_ASSERT(sizeof(Heap::Base*) == sizeof(quint32)); Heap::Base *b; @@ -195,7 +195,7 @@ public: memcpy(&b, &v, 4); return b; } - Q_ALWAYS_INLINE void setM(Heap::Base *b) + QML_NEARLY_ALWAYS_INLINE void setM(Heap::Base *b) { quint32 v; memcpy(&v, &b, 4); @@ -203,32 +203,32 @@ public: } #endif - Q_ALWAYS_INLINE int int_32() const + QML_NEARLY_ALWAYS_INLINE int int_32() const { return int(value()); } - Q_ALWAYS_INLINE void setInt_32(int i) + QML_NEARLY_ALWAYS_INLINE void setInt_32(int i) { setTagValue(Integer_Type_Internal, quint32(i)); } - Q_ALWAYS_INLINE uint uint_32() const { return value(); } + QML_NEARLY_ALWAYS_INLINE uint uint_32() const { return value(); } - Q_ALWAYS_INLINE void setEmpty() + QML_NEARLY_ALWAYS_INLINE void setEmpty() { setTagValue(Empty_Type_Internal, value()); } - Q_ALWAYS_INLINE void setEmpty(int i) + QML_NEARLY_ALWAYS_INLINE void setEmpty(int i) { setTagValue(Empty_Type_Internal, quint32(i)); } - Q_ALWAYS_INLINE void setEmpty(quint32 i) + QML_NEARLY_ALWAYS_INLINE void setEmpty(quint32 i) { setTagValue(Empty_Type_Internal, i); } - Q_ALWAYS_INLINE quint32 emptyValue() + QML_NEARLY_ALWAYS_INLINE quint32 emptyValue() { Q_ASSERT(isEmpty()); return quint32(value()); @@ -326,7 +326,7 @@ public: } inline bool isNaN() const { return (tag() & QV4::Value::NotDouble_Mask) == QV4::Value::NaN_Mask; } #endif - Q_ALWAYS_INLINE double doubleValue() const { + QML_NEARLY_ALWAYS_INLINE double doubleValue() const { Q_ASSERT(isDouble()); double d; quint64 v = _val; @@ -336,7 +336,7 @@ public: memcpy(&d, &v, 8); return d; } - Q_ALWAYS_INLINE void setDouble(double d) { + QML_NEARLY_ALWAYS_INLINE void setDouble(double d) { memcpy(&_val, &d, 8); #ifdef QV4_USE_64_BIT_VALUE_ENCODING _val ^= NaNEncodeMask; @@ -371,22 +371,22 @@ public: return int_32(); } - Q_ALWAYS_INLINE String *stringValue() const { + QML_NEARLY_ALWAYS_INLINE String *stringValue() const { if (!isString()) return nullptr; return m() ? reinterpret_cast<String*>(const_cast<Value *>(this)) : 0; } - Q_ALWAYS_INLINE Object *objectValue() const { + QML_NEARLY_ALWAYS_INLINE Object *objectValue() const { if (!isObject()) return nullptr; return m() ? reinterpret_cast<Object*>(const_cast<Value *>(this)) : 0; } - Q_ALWAYS_INLINE Managed *managed() const { + QML_NEARLY_ALWAYS_INLINE Managed *managed() const { if (!isManaged()) return nullptr; return m() ? reinterpret_cast<Managed*>(const_cast<Value *>(this)) : 0; } - Q_ALWAYS_INLINE Heap::Base *heapObject() const { + QML_NEARLY_ALWAYS_INLINE Heap::Base *heapObject() const { return isManaged() ? m() : nullptr; } |