From c25c95ba22ef843d09b22f9524a04585dc26f2bd Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 14 Jul 2016 20:39:58 +0200 Subject: [PATCH] Fix endianness in constant handling When running on a big-endian system, we need to convert the constant values into big-endian once and then it's possible to access them directly. Change-Id: I655bad7b7734e3b95e79e5f688f0b4041d0c41c4 Reviewed-by: Erik Verbruggen --- src/qml/compiler/qv4compileddata.cpp | 13 +++++++++++++ src/qml/compiler/qv4compileddata_p.h | 7 +++++-- src/qml/compiler/qv4compiler.cpp | 6 ++++++ src/qml/jsruntime/qv4context.cpp | 2 +- src/qml/jsruntime/qv4functionobject.cpp | 4 ++-- src/qml/jsruntime/qv4script.cpp | 2 +- src/qml/jsruntime/qv4vme_moth.cpp | 2 +- 7 files changed, 29 insertions(+), 7 deletions(-) diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp index 121b5907db..b060d72448 100644 --- a/src/qml/compiler/qv4compileddata.cpp +++ b/src/qml/compiler/qv4compileddata.cpp @@ -161,6 +161,16 @@ QV4::Function *CompilationUnit::linkToEngine(ExecutionEngine *engine) } } +#if Q_BYTE_ORDER == Q_BIG_ENDIAN + Value *bigEndianConstants = new Value[data->constantTableSize]; + const LEUInt64 *littleEndianConstants = data->constants(); + for (uint i = 0; i < data->constantTableSize; ++i) + bigEndianConstants[i] = Value::fromReturnedValue(littleEndianConstants[i]); + constants = bigEndianConstants; +#else + constants = reinterpret_cast(data->constants()); +#endif + linkBackendToEngine(engine); if (data->indexOfRootFunction != -1) @@ -203,6 +213,9 @@ void CompilationUnit::unlink() runtimeClasses = 0; qDeleteAll(runtimeFunctions); runtimeFunctions.clear(); +#if Q_BYTE_ORDER == Q_BIG_ENDIAN + delete [] constants; +#endif } void CompilationUnit::markObjects(QV4::ExecutionEngine *e) diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h index 519708f089..1f253e02fd 100644 --- a/src/qml/compiler/qv4compileddata_p.h +++ b/src/qml/compiler/qv4compileddata_p.h @@ -691,8 +691,8 @@ struct Unit const RegExp *regexpAt(int index) const { return reinterpret_cast(reinterpret_cast(this) + offsetToRegexpTable + index * sizeof(RegExp)); } - const QV4::Value *constants() const { - return reinterpret_cast(reinterpret_cast(this) + offsetToConstantTable); + const LEUInt64 *constants() const { + return reinterpret_cast(reinterpret_cast(this) + offsetToConstantTable); } const JSClassMember *jsClassAt(int idx, int *nMembers) const { @@ -853,6 +853,9 @@ struct Q_QML_PRIVATE_EXPORT CompilationUnit : public QQmlRefCount QHash> namedObjectsPerComponentCache; IdentifierHash namedObjectsPerComponent(int componentObjectIndex); + // pointers either to data->constants() or little-endian memory copy. + const Value* constants; + void finalize(QQmlEnginePrivate *engine); int totalBindingsCount; // Number of bindings used in this type diff --git a/src/qml/compiler/qv4compiler.cpp b/src/qml/compiler/qv4compiler.cpp index 924f2e15e2..50ade2c6e5 100644 --- a/src/qml/compiler/qv4compiler.cpp +++ b/src/qml/compiler/qv4compiler.cpp @@ -248,8 +248,14 @@ QV4::CompiledData::Unit *QV4::Compiler::JSUnitGenerator::generateUnit(GeneratorO CompiledData::RegExp *regexpTable = reinterpret_cast(dataPtr + unit->offsetToRegexpTable); memcpy(regexpTable, regexps.constData(), regexps.size() * sizeof(*regexpTable)); +#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN ReturnedValue *constantTable = reinterpret_cast(dataPtr + unit->offsetToConstantTable); memcpy(constantTable, constants.constData(), constants.size() * sizeof(ReturnedValue)); +#else + CompiledData::LEUInt64 *constantTable = reinterpret_cast(dataPtr + unit->offsetToConstantTable); + for (int i = 0; i < constants.count(); ++i) + constantTable[i] = constants.at(i); +#endif { memcpy(dataPtr + jsClassDataOffset, jsClassData.constData(), jsClassData.size()); diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp index 60717c9491..1abaca3dd1 100644 --- a/src/qml/jsruntime/qv4context.cpp +++ b/src/qml/jsruntime/qv4context.cpp @@ -73,7 +73,7 @@ Heap::CallContext *ExecutionContext::newCallContext(const FunctionObject *functi c->compilationUnit = function->function()->compilationUnit; c->lookups = c->compilationUnit->runtimeLookups; - c->constantTable = c->compilationUnit->data->constants(); + c->constantTable = c->compilationUnit->constants; c->locals = (Value *)((quintptr(c + 1) + 7) & ~7); const CompiledData::Function *compiledFunction = function->function()->compiledFunction; diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index 805087e389..276a069a77 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -535,7 +535,7 @@ void SimpleScriptFunction::construct(const Managed *that, Scope &scope, CallData ctx.function = f->d(); ctx.compilationUnit = f->function()->compilationUnit; ctx.lookups = ctx.compilationUnit->runtimeLookups; - ctx.constantTable = ctx.compilationUnit->data->constants(); + ctx.constantTable = ctx.compilationUnit->constants; ctx.outer = f->scope(); ctx.locals = scope.alloc(f->varCount()); for (int i = callData->argc; i < (int)f->formalParameterCount(); ++i) @@ -573,7 +573,7 @@ void SimpleScriptFunction::call(const Managed *that, Scope &scope, CallData *cal ctx.function = f->d(); ctx.compilationUnit = f->function()->compilationUnit; ctx.lookups = ctx.compilationUnit->runtimeLookups; - ctx.constantTable = ctx.compilationUnit->data->constants(); + ctx.constantTable = ctx.compilationUnit->constants; ctx.outer = f->scope(); ctx.locals = scope.alloc(f->varCount()); for (int i = callData->argc; i < (int)f->formalParameterCount(); ++i) diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp index 46adaf7e79..e3475e5cd6 100644 --- a/src/qml/jsruntime/qv4script.cpp +++ b/src/qml/jsruntime/qv4script.cpp @@ -222,7 +222,7 @@ ReturnedValue Script::run() ContextStateSaver stateSaver(valueScope, scope); scope->d()->strictMode = vmFunction->isStrict(); scope->d()->lookups = vmFunction->compilationUnit->runtimeLookups; - scope->d()->constantTable = vmFunction->compilationUnit->data->constants(); + scope->d()->constantTable = vmFunction->compilationUnit->constants; scope->d()->compilationUnit = vmFunction->compilationUnit; return Q_V4_PROFILE(engine, vmFunction); diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp index b6dc7716ba..420abd1458 100644 --- a/src/qml/jsruntime/qv4vme_moth.cpp +++ b/src/qml/jsruntime/qv4vme_moth.cpp @@ -402,7 +402,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code QV4::Value **scopes = static_cast(alloca(sizeof(QV4::Value *)*(2 + 2*scopeDepth))); { - scopes[0] = const_cast(context->d()->compilationUnit->data->constants()); + scopes[0] = const_cast(context->d()->compilationUnit->constants); // stack gets setup in push instruction scopes[1] = 0; QV4::Heap::ExecutionContext *scope = context->d();