From 5f3ef18bf8c3e0e3ba1c80bcdeaece46cbb45c06 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Wed, 14 Aug 2013 10:17:37 +0200 Subject: [PATCH] Begin using the compiled data structures for runtime strings Change-Id: Idbf278a96624bf101df35de40577b38e593f22be Reviewed-by: Lars Knoll --- src/qml/compiler/qv4compileddata.cpp | 23 ++++++++++++++++++++ src/qml/compiler/qv4compileddata_p.h | 37 +++++++++++++++++++++++++++++++++ src/qml/compiler/qv4compiler.cpp | 2 +- src/qml/compiler/qv4compiler_p.h | 2 -- src/qml/compiler/qv4isel_masm.cpp | 9 +++++--- src/qml/compiler/qv4isel_moth.cpp | 2 +- src/qml/compiler/qv4isel_p.cpp | 27 +++++++++++++++++++----- src/qml/compiler/qv4isel_p.h | 10 +++++++-- src/qml/jsruntime/qv4function.cpp | 4 +++- src/qml/jsruntime/qv4function_p.h | 3 +++ src/qml/jsruntime/qv4functionobject.cpp | 5 +++-- src/qml/jsruntime/qv4runtime.cpp | 12 +++++++++++ src/qml/jsruntime/qv4runtime_p.h | 3 +++ src/qml/jsruntime/qv4script.cpp | 9 ++++---- 14 files changed, 126 insertions(+), 22 deletions(-) diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp index 4c142f4..ee198c3 100644 --- a/src/qml/compiler/qv4compileddata.cpp +++ b/src/qml/compiler/qv4compileddata.cpp @@ -41,6 +41,7 @@ #include "qv4compileddata_p.h" #include "qv4jsir_p.h" +#include namespace QV4 { @@ -51,6 +52,28 @@ int Function::calculateSize(QQmlJS::V4IR::Function *f) return calculateSize(f->formals.size(), f->locals.size(), f->nestedFunctions.size()); } +CompilationUnit::~CompilationUnit() +{ + free(data); + free(runtimeIdentifiers); +} + +QV4::Function *CompilationUnit::linkToEngine(ExecutionEngine *engine) +{ + assert(!runtimeIdentifiers); + assert(data); + runtimeIdentifiers = (QV4::String**)malloc(data->stringTableSize * sizeof(QV4::String*)); + for (int i = 0; i < data->stringTableSize; ++i) + runtimeIdentifiers[i] = engine->newIdentifier(data->stringAt(i)->qString()); + + return linkBackendToEngine(engine); +} + +// ### Move to masm +QV4::Function *MasmCompilationUnit::linkBackendToEngine(ExecutionEngine *engine) +{ + return rootFunction; +} } diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h index 47e4e48..67ddfb3 100644 --- a/src/qml/compiler/qv4compileddata_p.h +++ b/src/qml/compiler/qv4compileddata_p.h @@ -56,10 +56,13 @@ struct Function; namespace QV4 { +struct Function; struct ExecutionContext; namespace CompiledData { +struct String; + static const char magic_str[] = "qv4cdata"; struct Unit @@ -77,6 +80,13 @@ struct Unit uint offsetToStringTable; uint functionTableSize; uint offsetToFunctionTable; + uint indexOfRootFunction; + + const String *stringAt(int idx) const { + const uint *offsetTable = reinterpret_cast((reinterpret_cast(this)) + offsetToStringTable); + const uint offset = offsetTable[idx]; + return reinterpret_cast(reinterpret_cast(this) + offset); + } static int calculateSize(uint nStrings, uint nFunctions) { return (sizeof(Unit) + (nStrings + nFunctions) * sizeof(uint) + 7) & ~7; } }; @@ -110,6 +120,11 @@ struct String QArrayData str; // uint16 strdata[] + QString qString() const { + QStringDataPtr holder { const_cast(static_cast(&str)) }; + return QString(holder); + } + static int calculateSize(const QString &str) { return (sizeof(String) + (str.length() + 1) * sizeof(quint16) + 7) & ~0x7; } @@ -201,11 +216,29 @@ struct QmlUnit struct CompilationUnit { + CompilationUnit() + : refCount(0) + , data(0) + , runtimeIdentifiers(0) + {} virtual ~CompilationUnit(); + + void ref() { ++refCount; } + void deref() { if (!--refCount) delete this; } + + int refCount; Unit *data; + QV4::String **runtimeIdentifiers; // Array + + QV4::Function *linkToEngine(QV4::ExecutionEngine *engine); + + // ### runtime data // pointer to qml data for QML unit + +protected: + virtual QV4::Function *linkBackendToEngine(QV4::ExecutionEngine *engine) = 0; }; struct MasmCompilationUnit : public CompilationUnit @@ -214,8 +247,12 @@ struct MasmCompilationUnit : public CompilationUnit // free all jitted code } + virtual QV4::Function *linkBackendToEngine(QV4::ExecutionEngine *engine); + // Coderef + execution engine + // ### remove + QV4::Function *rootFunction; }; struct MothCompilationUnit : public CompilationUnit diff --git a/src/qml/compiler/qv4compiler.cpp b/src/qml/compiler/qv4compiler.cpp index b3aebbe..6bda115 100644 --- a/src/qml/compiler/qv4compiler.cpp +++ b/src/qml/compiler/qv4compiler.cpp @@ -48,7 +48,6 @@ QV4::Compiler::JSUnitGenerator::JSUnitGenerator(QV4::ExecutionEngine *engine, QQ : irModule(module) , stringDataSize(0) { - isel = engine->iselFactory->create(engine, irModule); } int QV4::Compiler::JSUnitGenerator::registerString(const QString &str) @@ -125,6 +124,7 @@ QV4::CompiledData::Unit *QV4::Compiler::JSUnitGenerator::generateUnit() writeFunction(f, irModule->rootFunction); ++functionTable; f += QV4::CompiledData::Function::calculateSize(irModule->rootFunction); + unit->indexOfRootFunction = 0; for (uint i = 0; i < irModule->functions.size(); ++i) { QQmlJS::V4IR::Function *function = irModule->functions.at(i); diff --git a/src/qml/compiler/qv4compiler_p.h b/src/qml/compiler/qv4compiler_p.h index c17e0dd..b111693 100644 --- a/src/qml/compiler/qv4compiler_p.h +++ b/src/qml/compiler/qv4compiler_p.h @@ -43,7 +43,6 @@ #include #include "qv4jsir_p.h" -#include QT_BEGIN_NAMESPACE @@ -59,7 +58,6 @@ struct JSUnitGenerator { JSUnitGenerator(QV4::ExecutionEngine *engine, QQmlJS::V4IR::Module *module); QQmlJS::V4IR::Module *irModule; - QQmlJS::EvalInstructionSelection *isel; int registerString(const QString &str); int getStringId(const QString &string) const; diff --git a/src/qml/compiler/qv4isel_masm.cpp b/src/qml/compiler/qv4isel_masm.cpp index 861ffbf..dc290c8 100644 --- a/src/qml/compiler/qv4isel_masm.cpp +++ b/src/qml/compiler/qv4isel_masm.cpp @@ -640,6 +640,9 @@ InstructionSelection::InstructionSelection(QV4::ExecutionEngine *engine, V4IR::M , _as(0) , _locals(0) { + QV4::CompiledData::MasmCompilationUnit *masmUnit = new QV4::CompiledData::MasmCompilationUnit; + compilationUnit = masmUnit; + masmUnit->rootFunction = _irToVM[module->rootFunction]; } InstructionSelection::~InstructionSelection() @@ -1003,8 +1006,8 @@ void InstructionSelection::loadConst(V4IR::Const *sourceConst, V4IR::Temp *targe void InstructionSelection::loadString(const QString &str, V4IR::Temp *targetTemp) { - Value v = Value::fromString(identifier(str)); - _as->storeValue(v, targetTemp); + int id = stringId(str); + generateFunctionCall(Assembler::Void, __qmljs_resolve_string_as_value, Assembler::ContextRegister, Assembler::PointerToValue(targetTemp), Assembler::TrustedImm32(id)); } void InstructionSelection::loadRegexp(V4IR::RegExp *sourceRegexp, V4IR::Temp *targetTemp) @@ -1035,7 +1038,7 @@ void InstructionSelection::setActivationProperty(V4IR::Temp *source, const QStri void InstructionSelection::initClosure(V4IR::Closure *closure, V4IR::Temp *target) { - QV4::Function *vmFunc = vmFunction(closure->value); + QV4::Function *vmFunc = _irToVM[closure->value]; assert(vmFunc); generateFunctionCall(Assembler::Void, __qmljs_init_closure, Assembler::ContextRegister, Assembler::PointerToValue(target), Assembler::TrustedImmPtr(vmFunc)); } diff --git a/src/qml/compiler/qv4isel_moth.cpp b/src/qml/compiler/qv4isel_moth.cpp index 8b86055..f7ff490 100644 --- a/src/qml/compiler/qv4isel_moth.cpp +++ b/src/qml/compiler/qv4isel_moth.cpp @@ -423,7 +423,7 @@ void InstructionSelection::setActivationProperty(V4IR::Temp *source, const QStri void InstructionSelection::initClosure(V4IR::Closure *closure, V4IR::Temp *target) { - QV4::Function *vmFunc = vmFunction(closure->value); + QV4::Function *vmFunc = _irToVM[closure->value]; assert(vmFunc); Instruction::LoadClosure load; load.value = vmFunc; diff --git a/src/qml/compiler/qv4isel_p.cpp b/src/qml/compiler/qv4isel_p.cpp index c864378..4436725 100644 --- a/src/qml/compiler/qv4isel_p.cpp +++ b/src/qml/compiler/qv4isel_p.cpp @@ -61,6 +61,8 @@ using namespace QQmlJS::V4IR; EvalInstructionSelection::EvalInstructionSelection(QV4::ExecutionEngine *engine, Module *module) : _engine(engine) , useFastLookups(true) + , jsUnitGenerator(engine, module) + , compilationUnit(0) { assert(engine); assert(module); @@ -105,11 +107,26 @@ QV4::Function *EvalInstructionSelection::createFunctionMapping(QV4::Function *ou return vmFunction; } -QV4::Function *EvalInstructionSelection::vmFunction(Function *f) { - QV4::Function *function = _irToVM[f]; - if (!function->code) - run(function, f); - return function; +QV4::CompiledData::CompilationUnit *EvalInstructionSelection::compile() +{ + Function *rootFunction = jsUnitGenerator.irModule->rootFunction; + if (!rootFunction) + return 0; + for (QHash::Iterator it = _irToVM.begin(), end = _irToVM.end(); + it != end; ++it) { + if (!(*it)->code) + run(it.value(), it.key()); + } + + compilationUnit->data = jsUnitGenerator.generateUnit(); + + for (QHash::Iterator it = _irToVM.begin(), end = _irToVM.end(); + it != end; ++it) { + compilationUnit->ref(); + (*it)->compilationUnit = compilationUnit; + } + + return compilationUnit; } void IRDecoder::visitMove(V4IR::Move *s) diff --git a/src/qml/compiler/qv4isel_p.h b/src/qml/compiler/qv4isel_p.h index 965caf2..d31d60d 100644 --- a/src/qml/compiler/qv4isel_p.h +++ b/src/qml/compiler/qv4isel_p.h @@ -44,6 +44,8 @@ #include "private/qv4global_p.h" #include "qv4jsir_p.h" +#include +#include #include #include @@ -63,7 +65,7 @@ public: EvalInstructionSelection(QV4::ExecutionEngine *engine, V4IR::Module *module); virtual ~EvalInstructionSelection() = 0; - QV4::Function *vmFunction(V4IR::Function *f); + QV4::CompiledData::CompilationUnit *compile(); void setUseFastLookups(bool b) { useFastLookups = b; } @@ -72,11 +74,15 @@ protected: QV4::ExecutionEngine *engine() const { return _engine; } virtual void run(QV4::Function *vmFunction, V4IR::Function *function) = 0; + int stringId(const QString &str) { return jsUnitGenerator.registerString(str); } + private: QV4::ExecutionEngine *_engine; - QHash _irToVM; protected: + QHash _irToVM; bool useFastLookups; + QV4::Compiler::JSUnitGenerator jsUnitGenerator; + QV4::CompiledData::CompilationUnit *compilationUnit; // subclass ctor needs to initialize. }; class Q_QML_EXPORT EvalISelFactory diff --git a/src/qml/jsruntime/qv4function.cpp b/src/qml/jsruntime/qv4function.cpp index 8c303a2..6e1645c 100644 --- a/src/qml/jsruntime/qv4function.cpp +++ b/src/qml/jsruntime/qv4function.cpp @@ -54,13 +54,15 @@ using namespace QV4; Function::~Function() { engine->functions.remove(engine->functions.indexOf(this)); - UnwindHelper::deregisterFunction(this); + UnwindHelper::deregisterFunction(this); // ### move to masm compilation unit Q_ASSERT(!refCount); delete[] codeData; delete[] lookups; foreach (Function *f, nestedFunctions) f->deref(); + if (compilationUnit) + compilationUnit->deref(); } void Function::mark() diff --git a/src/qml/jsruntime/qv4function_p.h b/src/qml/jsruntime/qv4function_p.h index 612bbb1..99b94ba 100644 --- a/src/qml/jsruntime/qv4function_p.h +++ b/src/qml/jsruntime/qv4function_p.h @@ -50,6 +50,7 @@ #include #include #include "qv4value_def_p.h" +#include QT_BEGIN_NAMESPACE @@ -90,6 +91,7 @@ struct Function { int refCount; String *name; + CompiledData::CompilationUnit *compilationUnit; Value (*code)(ExecutionContext *, const uchar *); const uchar *codeData; JSC::MacroAssemblerCodeRef codeRef; @@ -117,6 +119,7 @@ struct Function { Function(ExecutionEngine *engine, String *name) : refCount(0) , name(name) + , compilationUnit(0) , code(0) , codeData(0) , codeSize(0) diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index e441b1c..ae9fb76 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -211,10 +211,11 @@ Value FunctionCtor::construct(Managed *that, Value *args, int argc) QQmlJS::V4IR::Module module; QQmlJS::Codegen cg(v4->current, f->strictMode); - QQmlJS::V4IR::Function *irf = cg(QString(), function, fe, &module); + cg(QString(), function, fe, &module); QScopedPointer isel(v4->iselFactory->create(v4, &module)); - QV4::Function *vmf = isel->vmFunction(irf); + QV4::CompiledData::CompilationUnit *compilationUnit = isel->compile(); + QV4::Function *vmf = compilationUnit->linkToEngine(v4); return Value::fromObject(v4->newScriptFunction(v4->rootContext, vmf)); } diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index ed2c146..d061376 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -1245,6 +1245,18 @@ void __qmljs_decrement(Value *result, const Value &value) } } +String *__qmljs_resolve_string(ExecutionContext *ctx, int stringId) +{ + QV4::CallContext *callCtx = ctx->asCallContext(); + QV4::Function *fun = callCtx ? callCtx->function->function : ctx->engine->globalCode; + return fun->compilationUnit->runtimeIdentifiers[stringId]; +} + +void __qmljs_resolve_string_as_value(ExecutionContext *ctx, Value *result, int stringId) +{ + *result = Value::fromString(__qmljs_resolve_string(ctx, stringId)); +} + } // namespace QV4 QT_END_NAMESPACE diff --git a/src/qml/jsruntime/qv4runtime_p.h b/src/qml/jsruntime/qv4runtime_p.h index 836aedf..d1196a7 100644 --- a/src/qml/jsruntime/qv4runtime_p.h +++ b/src/qml/jsruntime/qv4runtime_p.h @@ -126,6 +126,9 @@ void __qmljs_builtin_define_array(QV4::ExecutionContext *ctx, QV4::Value *array, void __qmljs_builtin_define_getter_setter(QV4::ExecutionContext *ctx, const QV4::Value &object, QV4::String *name, const QV4::Value *getter, const QV4::Value *setter); void __qmljs_builtin_define_object_literal(QV4::ExecutionContext *ctx, QV4::Value *result, const QV4::Value *args, QV4::InternalClass *klass); +QV4::String *__qmljs_resolve_string(QV4::ExecutionContext *ctx, int stringId); +void __qmljs_resolve_string_as_value(QV4::ExecutionContext *ctx, QV4::Value *result, int stringId); + // constructors void __qmljs_init_closure(QV4::ExecutionContext *ctx, QV4::Value *result, QV4::Function *clos); QV4::Function *__qmljs_register_function(QV4::ExecutionContext *ctx, QV4::String *name, diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp index 8521501..cfe47c9 100644 --- a/src/qml/jsruntime/qv4script.cpp +++ b/src/qml/jsruntime/qv4script.cpp @@ -174,14 +174,13 @@ void Script::parse() inheritedLocals.append(*i ? (*i)->toQString() : QString()); Codegen cg(scope, strictMode); - V4IR::Function *globalIRCode = cg(sourceFile, sourceCode, program, &module, - parseAsBinding ? QQmlJS::Codegen::QmlBinding : QQmlJS::Codegen::EvalCode, inheritedLocals); + cg(sourceFile, sourceCode, program, &module, + parseAsBinding ? QQmlJS::Codegen::QmlBinding : QQmlJS::Codegen::EvalCode, inheritedLocals); QScopedPointer isel(v4->iselFactory->create(v4, &module)); if (inheritContext) isel->setUseFastLookups(false); - if (globalIRCode) { - vmFunction = isel->vmFunction(globalIRCode); - } + QV4::CompiledData::CompilationUnit *compilationUnit = isel->compile(); + vmFunction = compilationUnit->linkToEngine(v4); } if (!vmFunction) -- 2.7.4