Begin using the compiled data structures for runtime strings
authorSimon Hausmann <simon.hausmann@digia.com>
Wed, 14 Aug 2013 08:17:37 +0000 (10:17 +0200)
committerSimon Hausmann <simon.hausmann@digia.com>
Thu, 15 Aug 2013 07:08:39 +0000 (09:08 +0200)
Change-Id: Idbf278a96624bf101df35de40577b38e593f22be
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
14 files changed:
src/qml/compiler/qv4compileddata.cpp
src/qml/compiler/qv4compileddata_p.h
src/qml/compiler/qv4compiler.cpp
src/qml/compiler/qv4compiler_p.h
src/qml/compiler/qv4isel_masm.cpp
src/qml/compiler/qv4isel_moth.cpp
src/qml/compiler/qv4isel_p.cpp
src/qml/compiler/qv4isel_p.h
src/qml/jsruntime/qv4function.cpp
src/qml/jsruntime/qv4function_p.h
src/qml/jsruntime/qv4functionobject.cpp
src/qml/jsruntime/qv4runtime.cpp
src/qml/jsruntime/qv4runtime_p.h
src/qml/jsruntime/qv4script.cpp

index 4c142f4..ee198c3 100644 (file)
@@ -41,6 +41,7 @@
 
 #include "qv4compileddata_p.h"
 #include "qv4jsir_p.h"
+#include <private/qv4engine_p.h>
 
 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;
+}
 
 }
 
index 47e4e48..67ddfb3 100644 (file)
@@ -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<const uint*>((reinterpret_cast<const char *>(this)) + offsetToStringTable);
+        const uint offset = offsetTable[idx];
+        return reinterpret_cast<const String*>(reinterpret_cast<const char *>(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<QStringData *>(static_cast<const QStringData*>(&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
index b3aebbe..6bda115 100644 (file)
@@ -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);
index c17e0dd..b111693 100644 (file)
@@ -43,7 +43,6 @@
 
 #include <QtCore/qstring.h>
 #include "qv4jsir_p.h"
-#include <qv4isel_p.h>
 
 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;
index 861ffbf..dc290c8 100644 (file)
@@ -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));
 }
index 8b86055..f7ff490 100644 (file)
@@ -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;
index c864378..4436725 100644 (file)
@@ -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<V4IR::Function*, QV4::Function*>::Iterator it = _irToVM.begin(), end = _irToVM.end();
+         it != end; ++it) {
+        if (!(*it)->code)
+            run(it.value(), it.key());
+    }
+
+    compilationUnit->data = jsUnitGenerator.generateUnit();
+
+    for (QHash<V4IR::Function *, QV4::Function *>::Iterator it = _irToVM.begin(), end = _irToVM.end();
+         it != end; ++it) {
+        compilationUnit->ref();
+        (*it)->compilationUnit = compilationUnit;
+    }
+
+    return compilationUnit;
 }
 
 void IRDecoder::visitMove(V4IR::Move *s)
index 965caf2..d31d60d 100644 (file)
@@ -44,6 +44,8 @@
 
 #include "private/qv4global_p.h"
 #include "qv4jsir_p.h"
+#include <private/qv4compileddata_p.h>
+#include <private/qv4compiler_p.h>
 
 #include <qglobal.h>
 #include <QHash>
@@ -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<V4IR::Function *, QV4::Function *> _irToVM;
 protected:
+    QHash<V4IR::Function *, QV4::Function *> _irToVM;
     bool useFastLookups;
+    QV4::Compiler::JSUnitGenerator jsUnitGenerator;
+    QV4::CompiledData::CompilationUnit *compilationUnit; // subclass ctor needs to initialize.
 };
 
 class Q_QML_EXPORT EvalISelFactory
index 8c303a2..6e1645c 100644 (file)
@@ -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()
index 612bbb1..99b94ba 100644 (file)
@@ -50,6 +50,7 @@
 #include <config.h>
 #include <assembler/MacroAssemblerCodeRef.h>
 #include "qv4value_def_p.h"
+#include <private/qv4compileddata_p.h>
 
 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)
index e441b1c..ae9fb76 100644 (file)
@@ -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<QQmlJS::EvalInstructionSelection> 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));
 }
index ed2c146..d061376 100644 (file)
@@ -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
index 836aedf..d1196a7 100644 (file)
@@ -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,
index 8521501..cfe47c9 100644 (file)
@@ -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<EvalInstructionSelection> 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)