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 <erik.verbruggen@qt.io>
This commit is contained in:
Simon Hausmann 2016-07-14 20:39:58 +02:00 committed by Erik Verbruggen
parent 5b620ed689
commit c25c95ba22
7 changed files with 29 additions and 7 deletions

View File

@ -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<const Value*>(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)

View File

@ -691,8 +691,8 @@ struct Unit
const RegExp *regexpAt(int index) const {
return reinterpret_cast<const RegExp*>(reinterpret_cast<const char *>(this) + offsetToRegexpTable + index * sizeof(RegExp));
}
const QV4::Value *constants() const {
return reinterpret_cast<const QV4::Value*>(reinterpret_cast<const char *>(this) + offsetToConstantTable);
const LEUInt64 *constants() const {
return reinterpret_cast<const LEUInt64*>(reinterpret_cast<const char *>(this) + offsetToConstantTable);
}
const JSClassMember *jsClassAt(int idx, int *nMembers) const {
@ -853,6 +853,9 @@ struct Q_QML_PRIVATE_EXPORT CompilationUnit : public QQmlRefCount
QHash<int, IdentifierHash<int>> namedObjectsPerComponentCache;
IdentifierHash<int> 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

View File

@ -248,8 +248,14 @@ QV4::CompiledData::Unit *QV4::Compiler::JSUnitGenerator::generateUnit(GeneratorO
CompiledData::RegExp *regexpTable = reinterpret_cast<CompiledData::RegExp *>(dataPtr + unit->offsetToRegexpTable);
memcpy(regexpTable, regexps.constData(), regexps.size() * sizeof(*regexpTable));
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
ReturnedValue *constantTable = reinterpret_cast<ReturnedValue *>(dataPtr + unit->offsetToConstantTable);
memcpy(constantTable, constants.constData(), constants.size() * sizeof(ReturnedValue));
#else
CompiledData::LEUInt64 *constantTable = reinterpret_cast<CompiledData::LEUInt64 *>(dataPtr + unit->offsetToConstantTable);
for (int i = 0; i < constants.count(); ++i)
constantTable[i] = constants.at(i);
#endif
{
memcpy(dataPtr + jsClassDataOffset, jsClassData.constData(), jsClassData.size());

View File

@ -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;

View File

@ -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)

View File

@ -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);

View File

@ -402,7 +402,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code
QV4::Value **scopes = static_cast<QV4::Value **>(alloca(sizeof(QV4::Value *)*(2 + 2*scopeDepth)));
{
scopes[0] = const_cast<QV4::Value *>(context->d()->compilationUnit->data->constants());
scopes[0] = const_cast<QV4::Value *>(context->d()->compilationUnit->constants);
// stack gets setup in push instruction
scopes[1] = 0;
QV4::Heap::ExecutionContext *scope = context->d();