Ported lookups to use the compiled data infrastructure
authorSimon Hausmann <simon.hausmann@digia.com>
Thu, 15 Aug 2013 10:48:05 +0000 (12:48 +0200)
committerLars Knoll <lars.knoll@digia.com>
Thu, 15 Aug 2013 13:28:37 +0000 (15:28 +0200)
Change-Id: Idf75cd51087ea825f22aabda59661be461fd3b86
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
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_masm_p.h
src/qml/compiler/qv4isel_p.h
src/qml/jsruntime/qv4context.cpp
src/qml/jsruntime/qv4function.cpp
src/qml/jsruntime/qv4function_p.h
src/qml/jsruntime/qv4script.cpp

index a1a355b..c4d7509 100644 (file)
@@ -43,6 +43,7 @@
 #include "qv4jsir_p.h"
 #include <private/qv4engine_p.h>
 #include <private/qv4function_p.h>
+#include <private/qv4lookup_p.h>
 
 namespace QV4 {
 
@@ -57,6 +58,7 @@ CompilationUnit::~CompilationUnit()
 {
     free(data);
     free(runtimeStrings);
+    delete [] runtimeLookups;
 }
 
 QV4::Function *CompilationUnit::linkToEngine(ExecutionEngine *engine)
@@ -67,6 +69,27 @@ QV4::Function *CompilationUnit::linkToEngine(ExecutionEngine *engine)
     for (int i = 0; i < data->stringTableSize; ++i)
         runtimeStrings[i] = engine->newIdentifier(data->stringAt(i)->qString());
 
+    if (data->lookupTableSize) {
+        runtimeLookups = new QV4::Lookup[data->lookupTableSize];
+        const CompiledData::Lookup *compiledLookups = data->lookupTable();
+        for (uint i = 0; i < data->lookupTableSize; ++i) {
+            QV4::Lookup *l = runtimeLookups + i;
+
+            if (compiledLookups[i].type_and_flags == CompiledData::Lookup::Type_Getter)
+                l->getter = QV4::Lookup::getterGeneric;
+            else if (compiledLookups[i].type_and_flags == CompiledData::Lookup::Type_Setter)
+                l->setter = QV4::Lookup::setterGeneric;
+            else if (compiledLookups[i].type_and_flags == CompiledData::Lookup::Type_GlobalGetter)
+                l->globalGetter = QV4::Lookup::globalGetterGeneric;
+
+            for (int i = 0; i < QV4::Lookup::Size; ++i)
+                l->classList[i] = 0;
+            l->level = -1;
+            l->index = UINT_MAX;
+            l->name = runtimeStrings[compiledLookups[i].nameIndex];
+        }
+    }
+
     return linkBackendToEngine(engine);
 }
 
index c9d5520..de5c82b 100644 (file)
@@ -64,6 +64,7 @@ namespace CompiledData {
 
 struct String;
 struct Function;
+struct Lookup;
 
 static const char magic_str[] = "qv4cdata";
 
@@ -82,6 +83,8 @@ struct Unit
     uint offsetToStringTable;
     uint functionTableSize;
     uint offsetToFunctionTable;
+    uint lookupTableSize;
+    uint offsetToLookupTable;
     uint indexOfRootFunction;
     quint32 sourceFileIndex;
 
@@ -97,6 +100,8 @@ struct Unit
         return reinterpret_cast<const Function*>(reinterpret_cast<const char *>(this) + offset);
     }
 
+    const Lookup *lookupTable() const { return reinterpret_cast<const Lookup*>(reinterpret_cast<const char *>(this) + offsetToLookupTable); }
+
     static int calculateSize(uint nStrings, uint nFunctions) { return (sizeof(Unit) + (nStrings + nFunctions) * sizeof(uint) + 7) & ~7; }
 };
 
@@ -150,6 +155,19 @@ struct String
     }
 };
 
+struct Lookup
+{
+    enum Type {
+        Type_Getter = 0x0,
+        Type_Setter = 0x1,
+        Type_GlobalGetter = 2
+    };
+
+    quint32 type_and_flags;
+    quint32 nameIndex;
+
+    static int calculateSize() { return sizeof(Lookup); }
+};
 
 // Qml data structures
 
@@ -240,6 +258,7 @@ struct CompilationUnit
         : refCount(0)
         , data(0)
         , runtimeStrings(0)
+        , runtimeLookups(0)
     {}
     virtual ~CompilationUnit();
 
@@ -252,6 +271,7 @@ struct CompilationUnit
     QString fileName() const { return data->stringAt(data->sourceFileIndex)->qString(); }
 
     QV4::String **runtimeStrings; // Array
+    QV4::Lookup *runtimeLookups;
 
     QV4::Function *linkToEngine(QV4::ExecutionEngine *engine);
 
index 07687cc..135c867 100644 (file)
@@ -67,6 +67,33 @@ int QV4::Compiler::JSUnitGenerator::getStringId(const QString &string) const
     return stringToId.value(string);
 }
 
+uint QV4::Compiler::JSUnitGenerator::registerGetterLookup(const QString &name)
+{
+    CompiledData::Lookup l;
+    l.type_and_flags = CompiledData::Lookup::Type_Getter;
+    l.nameIndex = registerString(name);
+    lookups << l;
+    return lookups.size() - 1;
+}
+
+uint QV4::Compiler::JSUnitGenerator::registerSetterLookup(const QString &name)
+{
+    CompiledData::Lookup l;
+    l.type_and_flags = CompiledData::Lookup::Type_Setter;
+    l.nameIndex = registerString(name);
+    lookups << l;
+    return lookups.size() - 1;
+}
+
+uint QV4::Compiler::JSUnitGenerator::registerGlobalGetterLookup(const QString &name)
+{
+    CompiledData::Lookup l;
+    l.type_and_flags = CompiledData::Lookup::Type_GlobalGetter;
+    l.nameIndex = registerString(name);
+    lookups << l;
+    return lookups.size() - 1;
+}
+
 QV4::CompiledData::Unit *QV4::Compiler::JSUnitGenerator::generateUnit()
 {
     registerString(irModule->fileName);
@@ -87,7 +114,9 @@ QV4::CompiledData::Unit *QV4::Compiler::JSUnitGenerator::generateUnit()
         functionDataSize += QV4::CompiledData::Function::calculateSize(f);
     }
 
-    char *data = (char *)malloc(unitSize + functionDataSize + stringDataSize);
+    const uint lookupDataSize = CompiledData::Lookup::calculateSize() * lookups.count();
+
+    char *data = (char *)malloc(unitSize + functionDataSize + stringDataSize + lookupDataSize);
     QV4::CompiledData::Unit *unit = (QV4::CompiledData::Unit*)data;
 
     memcpy(unit->magic, QV4::CompiledData::magic_str, sizeof(unit->magic));
@@ -98,6 +127,8 @@ QV4::CompiledData::Unit *QV4::Compiler::JSUnitGenerator::generateUnit()
     unit->offsetToStringTable = sizeof(QV4::CompiledData::Unit);
     unit->functionTableSize = irModule->functions.size();
     unit->offsetToFunctionTable = unit->offsetToStringTable + unit->stringTableSize * sizeof(uint);
+    unit->lookupTableSize = lookups.count();
+    unit->offsetToLookupTable = unitSize + stringDataSize + functionDataSize;
     unit->sourceFileIndex = getStringId(irModule->fileName);
 
     // write strings and string table
@@ -134,6 +165,10 @@ QV4::CompiledData::Unit *QV4::Compiler::JSUnitGenerator::generateUnit()
         f += QV4::CompiledData::Function::calculateSize(function);
     }
 
+    CompiledData::Lookup *lookupsToWrite = (CompiledData::Lookup*)(data + unit->offsetToLookupTable);
+    foreach (const CompiledData::Lookup &l, lookups)
+        *lookupsToWrite++ = l;
+
     return unit;
 }
 
index 661bcd1..e7385a0 100644 (file)
@@ -50,6 +50,7 @@ namespace QV4 {
 
 namespace CompiledData {
 struct Unit;
+struct Lookup;
 }
 
 namespace Compiler {
@@ -62,13 +63,18 @@ struct JSUnitGenerator {
     int registerString(const QString &str);
     int getStringId(const QString &string) const;
 
+    uint registerGetterLookup(const QString &name);
+    uint registerSetterLookup(const QString &name);
+    uint registerGlobalGetterLookup(const QString &name);
+
     QV4::CompiledData::Unit *generateUnit();
     void writeFunction(char *f, int index, QQmlJS::V4IR::Function *irFunction);
 
     QHash<QString, int> stringToId;
     QStringList strings;
-    QHash<QQmlJS::V4IR::Function *, uint> functionOffsets;
     int stringDataSize;
+    QHash<QQmlJS::V4IR::Function *, uint> functionOffsets;
+    QList<CompiledData::Lookup> lookups;
 };
 
 }
index cfc2247..8b3025b 100644 (file)
@@ -695,7 +695,6 @@ void InstructionSelection::run(QV4::Function *vmFunction, V4IR::Function *functi
     QSet<V4IR::BasicBlock*> reentryBlocks;
     qSwap(_function, function);
     qSwap(_vmFunction, vmFunction);
-    qSwap(_lookups, lookups);
     qSwap(_reentryBlocks, reentryBlocks);
     Assembler* oldAssembler = _as;
     _as = new Assembler(this, _function, _vmFunction, engine());
@@ -759,16 +758,10 @@ void InstructionSelection::run(QV4::Function *vmFunction, V4IR::Function *functi
     JSC::MacroAssemblerCodeRef codeRef =_as->link(_vmFunction);
     codeRefs[_function] = codeRef;
 
-    if (_lookups.size()) {
-        _vmFunction->lookups = new Lookup[_lookups.size()];
-        memcpy(_vmFunction->lookups, _lookups.constData(), _lookups.size()*sizeof(Lookup));
-    }
-
     UnwindHelper::registerFunction(_vmFunction);
 
     qSwap(_vmFunction, vmFunction);
     qSwap(_function, function);
-    qSwap(_lookups, lookups);
     qSwap(_reentryBlocks, reentryBlocks);
     qSwap(_locals, locals);
     delete _as;
@@ -793,8 +786,7 @@ void InstructionSelection::callBuiltinInvalid(V4IR::Name *func, V4IR::ExprList *
     int argc = prepareVariableArguments(args);
 
     if (useFastLookups && func->global) {
-        QV4::String *s = identifier(*func->id);
-        uint index = addGlobalLookup(s);
+        uint index = registerGlobalGetterLookup(*func->id);
         generateFunctionCall(Assembler::Void, __qmljs_call_global_lookup,
                              Assembler::ContextRegister, Assembler::PointerToValue(result),
                              Assembler::TrustedImm32(index),
@@ -1073,8 +1065,7 @@ void InstructionSelection::loadRegexp(V4IR::RegExp *sourceRegexp, V4IR::Temp *ta
 void InstructionSelection::getActivationProperty(const V4IR::Name *name, V4IR::Temp *temp)
 {
     if (useFastLookups && name->global) {
-        String *propertyName = identifier(*name->id);
-        uint index = addGlobalLookup(propertyName);
+        uint index = registerGlobalGetterLookup(*name->id);
         generateLookupCall(index, offsetof(QV4::Lookup, globalGetter), Assembler::ContextRegister, Assembler::PointerToValue(temp));
         return;
     }
@@ -1097,8 +1088,7 @@ void InstructionSelection::initClosure(V4IR::Closure *closure, V4IR::Temp *targe
 void InstructionSelection::getProperty(V4IR::Temp *base, const QString &name, V4IR::Temp *target)
 {
     if (useFastLookups) {
-        QV4::String *s = identifier(name);
-        uint index = addLookup(s);
+        uint index = registerGetterLookup(name);
         generateLookupCall(index, offsetof(QV4::Lookup, getter), Assembler::PointerToValue(target),
                            Assembler::Reference(base));
     } else {
@@ -1110,8 +1100,7 @@ void InstructionSelection::getProperty(V4IR::Temp *base, const QString &name, V4
 void InstructionSelection::setProperty(V4IR::Temp *source, V4IR::Temp *targetBase, const QString &targetName)
 {
     if (useFastLookups) {
-        QV4::String *s = identifier(targetName);
-        uint index = addSetterLookup(s);
+        uint index = registerSetterLookup(targetName);
         generateLookupCall(index, offsetof(QV4::Lookup, setter), Assembler::Reference(targetBase), Assembler::Reference(source));
     } else {
         generateFunctionCall(Assembler::Void, __qmljs_set_property, Assembler::ContextRegister,
@@ -1260,8 +1249,7 @@ void InstructionSelection::callProperty(V4IR::Temp *base, const QString &name,
     int argc = prepareVariableArguments(args);
 
     if (useFastLookups) {
-        QV4::String *s = identifier(name);
-        uint index = addLookup(s);
+        uint index = registerGetterLookup(name);
         generateFunctionCall(Assembler::Void, __qmljs_call_property_lookup,
                              Assembler::ContextRegister, Assembler::PointerToValue(result),
                              Assembler::Reference(base), Assembler::TrustedImm32(index),
@@ -1307,9 +1295,7 @@ void InstructionSelection::constructActivationProperty(V4IR::Name *func, V4IR::E
 
     if (useFastLookups && func->global) {
         int argc = prepareVariableArguments(args);
-        QV4::String *s = identifier(*func->id);
-
-        uint index = addGlobalLookup(s);
+        uint index = registerGlobalGetterLookup(*func->id);
         generateFunctionCall(Assembler::Void, __qmljs_construct_global_lookup,
                              Assembler::ContextRegister, Assembler::PointerToValue(result),
                              Assembler::TrustedImm32(index),
@@ -1472,45 +1458,3 @@ void InstructionSelection::callRuntimeMethodImp(V4IR::Temp *result, const char*
                                  Assembler::TrustedImm32(argc));
 }
 
-
-uint InstructionSelection::addLookup(QV4::String *name)
-{
-    uint index = (uint)_lookups.size();
-    QV4::Lookup l;
-    l.getter = Lookup::getterGeneric;
-    for (int i = 0; i < Lookup::Size; ++i)
-        l.classList[i] = 0;
-    l.level = -1;
-    l.index = UINT_MAX;
-    l.name = name;
-    _lookups.append(l);
-    return index;
-}
-
-uint InstructionSelection::addSetterLookup(QV4::String *name)
-{
-    uint index = (uint)_lookups.size();
-    QV4::Lookup l;
-    l.setter = Lookup::setterGeneric;
-    for (int i = 0; i < Lookup::Size; ++i)
-        l.classList[i] = 0;
-    l.level = -1;
-    l.index = UINT_MAX;
-    l.name = name;
-    _lookups.append(l);
-    return index;
-}
-
-uint InstructionSelection::addGlobalLookup(QV4::String *name)
-{
-    uint index = (uint)_lookups.size();
-    QV4::Lookup l;
-    l.globalGetter = Lookup::globalGetterGeneric;
-    for (int i = 0; i < Lookup::Size; ++i)
-        l.classList[i] = 0;
-    l.level = -1;
-    l.index = UINT_MAX;
-    l.name = name;
-    _lookups.append(l);
-    return index;
-}
index b67386d..517a50f 100644 (file)
@@ -923,10 +923,6 @@ private:
 #define callRuntimeMethod(result, function, ...) \
     callRuntimeMethodImp(result, isel_stringIfy(function), function, __VA_ARGS__)
 
-    uint addLookup(QV4::String *name);
-    uint addSetterLookup(QV4::String *name);
-    uint addGlobalLookup(QV4::String *name);
-
     template <typename Arg1, typename Arg2>
     void generateLookupCall(uint index, uint getterSetterOffset, Arg1 arg1, Arg2 arg2)
     {
@@ -950,7 +946,6 @@ private:
     V4IR::BasicBlock *_block;
     V4IR::Function* _function;
     QV4::Function* _vmFunction;
-    QVector<QV4::Lookup> _lookups;
     Assembler* _as;
     QSet<V4IR::BasicBlock*> _reentryBlocks;
     int _locals;
index 1e1d72d..24ad581 100644 (file)
@@ -70,6 +70,9 @@ public:
     void setUseFastLookups(bool b) { useFastLookups = b; }
 
     int stringId(const QString &str) { return jsUnitGenerator.registerString(str); }
+    uint registerGetterLookup(const QString &str) { return jsUnitGenerator.registerGetterLookup(str); }
+    uint registerSetterLookup(const QString &str) { return jsUnitGenerator.registerSetterLookup(str); }
+    uint registerGlobalGetterLookup(const QString &str) { return jsUnitGenerator.registerGlobalGetterLookup(str); }
 
 protected:
     QV4::Function *createFunctionMapping(QV4::Function *outer, V4IR::Function *irFunction);
index f6ba986..57d559b 100644 (file)
@@ -175,7 +175,7 @@ void CallContext::initCallContext(ExecutionContext *parentContext, FunctionObjec
     activation = 0;
 
     if (function->function) {
-        lookups = function->function->lookups;
+        lookups = function->function->compilationUnit->runtimeLookups;
         runtimeStrings = function->function->compilationUnit->runtimeStrings;
     }
 
@@ -223,7 +223,7 @@ void CallContext::initQmlContext(ExecutionContext *parentContext, Object *qml, F
 
     activation = qml;
 
-    lookups = function->function->lookups;
+    lookups = function->function->compilationUnit->runtimeLookups;
     runtimeStrings = function->function->compilationUnit->runtimeStrings;
 
     locals = (Value *)(this + 1);
index 58d2cdd..24ea1fb 100644 (file)
@@ -58,7 +58,6 @@ Function::~Function()
 
     Q_ASSERT(!refCount);
     delete[] codeData;
-    delete[] lookups;
     foreach (Function *f, nestedFunctions)
         f->deref();
     if (compilationUnit)
index 34e570f..eacd7d1 100644 (file)
@@ -102,8 +102,6 @@ struct Function {
     QVector<String *> identifiers;
     QVector<Function *> nestedFunctions;
 
-    Lookup *lookups;
-
     QVector<LineNumberMapping> lineNumberMappings;
 
     ExecutionEngine *engine;
@@ -116,7 +114,6 @@ struct Function {
         , code(0)
         , codeData(0)
         , codeSize(0)
-        , lookups(0)
         , engine(engine)
     {}
     ~Function();
index 59b52c3..70ab3d4 100644 (file)
@@ -205,7 +205,7 @@ Value Script::run()
         String **oldRuntimeStrings = scope->runtimeStrings;
 
         scope->strictMode = vmFunction->isStrict();
-        scope->lookups = vmFunction->lookups;
+        scope->lookups = vmFunction->compilationUnit->runtimeLookups;
         scope->runtimeStrings = vmFunction->compilationUnit->runtimeStrings;
 
         QV4::Value result;