Ported regular expressions over to be run-time generated data
authorSimon Hausmann <simon.hausmann@digia.com>
Thu, 15 Aug 2013 13:54:36 +0000 (15:54 +0200)
committerLars Knoll <lars.knoll@digia.com>
Fri, 16 Aug 2013 08:14:13 +0000 (10:14 +0200)
Change-Id: I04e693d4923c97c3d869a5beb17011f6aad85f03
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/jsruntime/qv4context.cpp
src/qml/jsruntime/qv4context_p.h
src/qml/jsruntime/qv4runtime.cpp
src/qml/jsruntime/qv4runtime_p.h

index 38461af..08c4d80 100644 (file)
@@ -44,6 +44,7 @@
 #include <private/qv4engine_p.h>
 #include <private/qv4function_p.h>
 #include <private/qv4lookup_p.h>
+#include <private/qv4regexpobject_p.h>
 
 namespace QV4 {
 
@@ -60,6 +61,7 @@ CompilationUnit::~CompilationUnit()
     free(data);
     free(runtimeStrings);
     delete [] runtimeLookups;
+    delete [] runtimeRegularExpressions;
 }
 
 QV4::Function *CompilationUnit::linkToEngine(ExecutionEngine *engine)
@@ -73,6 +75,20 @@ QV4::Function *CompilationUnit::linkToEngine(ExecutionEngine *engine)
     for (int i = 0; i < data->stringTableSize; ++i)
         runtimeStrings[i] = engine->newIdentifier(data->stringAt(i)->qString());
 
+    runtimeRegularExpressions = new QV4::Value[data->regexpTableSize];
+    for (int i = 0; i < data->regexpTableSize; ++i) {
+        const CompiledData::RegExp *re = data->regexpAt(i);
+        int flags = 0;
+        if (re->flags & CompiledData::RegExp::RegExp_Global)
+            flags |= QQmlJS::V4IR::RegExp::RegExp_Global;
+        if (re->flags & CompiledData::RegExp::RegExp_IgnoreCase)
+            flags |= QQmlJS::V4IR::RegExp::RegExp_IgnoreCase;
+        if (re->flags & CompiledData::RegExp::RegExp_Multiline)
+            flags |= QQmlJS::V4IR::RegExp::RegExp_Multiline;
+        QV4::RegExpObject *obj = engine->newRegExpObject(data->stringAt(re->stringIndex)->qString(), flags);
+        runtimeRegularExpressions[i] = QV4::Value::fromObject(obj);
+    }
+
     if (data->lookupTableSize) {
         runtimeLookups = new QV4::Lookup[data->lookupTableSize];
         const CompiledData::Lookup *compiledLookups = data->lookupTable();
@@ -101,6 +117,8 @@ void CompilationUnit::markObjects()
 {
     for (int i = 0; i < data->stringTableSize; ++i)
         runtimeStrings[i]->mark();
+    for (int i = 0; i < data->regexpTableSize; ++i)
+        runtimeRegularExpressions[i].mark();
 }
 
 }
index cd8a76b..e267f0f 100644 (file)
@@ -65,6 +65,20 @@ namespace CompiledData {
 struct String;
 struct Function;
 struct Lookup;
+struct RegExp;
+
+struct RegExp
+{
+    enum Flags {
+        RegExp_Global     = 0x01,
+        RegExp_IgnoreCase = 0x02,
+        RegExp_Multiline  = 0x04
+    };
+    quint32 flags;
+    quint32 stringIndex;
+
+    static int calculateSize() { return sizeof(RegExp); }
+};
 
 static const char magic_str[] = "qv4cdata";
 
@@ -85,6 +99,8 @@ struct Unit
     uint offsetToFunctionTable;
     uint lookupTableSize;
     uint offsetToLookupTable;
+    uint regexpTableSize;
+    uint offsetToRegexpTable;
     uint indexOfRootFunction;
     quint32 sourceFileIndex;
 
@@ -101,8 +117,11 @@ struct Unit
     }
 
     const Lookup *lookupTable() const { return reinterpret_cast<const Lookup*>(reinterpret_cast<const char *>(this) + offsetToLookupTable); }
+    const RegExp *regexpAt(int index) const {
+        return reinterpret_cast<const RegExp*>(reinterpret_cast<const char *>(this) + offsetToRegexpTable + index * sizeof(RegExp));
+    }
 
-    static int calculateSize(uint nStrings, uint nFunctions) { return (sizeof(Unit) + (nStrings + nFunctions) * sizeof(uint) + 7) & ~7; }
+    static int calculateSize(uint nStrings, uint nFunctions, uint nRegExps) { return (sizeof(Unit) + (nStrings + nFunctions ) * sizeof(uint) + nRegExps * RegExp::calculateSize() + 7) & ~7; }
 };
 
 struct Function
@@ -274,6 +293,7 @@ struct CompilationUnit
 
     QV4::String **runtimeStrings; // Array
     QV4::Lookup *runtimeLookups;
+    QV4::Value *runtimeRegularExpressions;
 
     QV4::Function *linkToEngine(QV4::ExecutionEngine *engine);
 
index 6707283..d67b7de 100644 (file)
@@ -94,6 +94,23 @@ uint QV4::Compiler::JSUnitGenerator::registerGlobalGetterLookup(const QString &n
     return lookups.size() - 1;
 }
 
+int QV4::Compiler::JSUnitGenerator::registerRegExp(QQmlJS::V4IR::RegExp *regexp)
+{
+    CompiledData::RegExp re;
+    re.stringIndex = registerString(*regexp->value);
+
+    re.flags = 0;
+    if (regexp->flags & QQmlJS::V4IR::RegExp::RegExp_Global)
+        re.flags |= CompiledData::RegExp::RegExp_Global;
+    if (regexp->flags & QQmlJS::V4IR::RegExp::RegExp_IgnoreCase)
+        re.flags |= CompiledData::RegExp::RegExp_IgnoreCase;
+    if (regexp->flags & QQmlJS::V4IR::RegExp::RegExp_Multiline)
+        re.flags |= CompiledData::RegExp::RegExp_Multiline;
+
+    regexps.append(re);
+    return regexps.size() - 1;
+}
+
 QV4::CompiledData::Unit *QV4::Compiler::JSUnitGenerator::generateUnit()
 {
     registerString(irModule->fileName);
@@ -105,7 +122,7 @@ QV4::CompiledData::Unit *QV4::Compiler::JSUnitGenerator::generateUnit()
             registerString(*f->locals.at(i));
     }
 
-    int unitSize = QV4::CompiledData::Unit::calculateSize(strings.size(), irModule->functions.size());
+    int unitSize = QV4::CompiledData::Unit::calculateSize(strings.size(), irModule->functions.size(), regexps.size());
 
     uint functionDataSize = 0;
     for (int i = 0; i < irModule->functions.size(); ++i) {
@@ -128,6 +145,8 @@ QV4::CompiledData::Unit *QV4::Compiler::JSUnitGenerator::generateUnit()
     unit->functionTableSize = irModule->functions.size();
     unit->offsetToFunctionTable = unit->offsetToStringTable + unit->stringTableSize * sizeof(uint);
     unit->lookupTableSize = lookups.count();
+    unit->regexpTableSize = regexps.size();
+    unit->offsetToRegexpTable = unit->offsetToFunctionTable + unit->functionTableSize * sizeof(uint);
     unit->offsetToLookupTable = unitSize + stringDataSize + functionDataSize;
     unit->sourceFileIndex = getStringId(irModule->fileName);
 
@@ -169,6 +188,9 @@ QV4::CompiledData::Unit *QV4::Compiler::JSUnitGenerator::generateUnit()
     foreach (const CompiledData::Lookup &l, lookups)
         *lookupsToWrite++ = l;
 
+    CompiledData::RegExp *regexpTable = (CompiledData::RegExp *)(data + unit->offsetToRegexpTable);
+    memcpy(regexpTable, regexps.constData(), regexps.size() * sizeof(*regexpTable));
+
     return unit;
 }
 
index e7385a0..753e462 100644 (file)
@@ -51,6 +51,7 @@ namespace QV4 {
 namespace CompiledData {
 struct Unit;
 struct Lookup;
+struct RegExp;
 }
 
 namespace Compiler {
@@ -67,6 +68,8 @@ struct JSUnitGenerator {
     uint registerSetterLookup(const QString &name);
     uint registerGlobalGetterLookup(const QString &name);
 
+    int registerRegExp(QQmlJS::V4IR::RegExp *regexp);
+
     QV4::CompiledData::Unit *generateUnit();
     void writeFunction(char *f, int index, QQmlJS::V4IR::Function *irFunction);
 
@@ -75,6 +78,7 @@ struct JSUnitGenerator {
     int stringDataSize;
     QHash<QQmlJS::V4IR::Function *, uint> functionOffsets;
     QList<CompiledData::Lookup> lookups;
+    QVector<CompiledData::RegExp> regexps;
 };
 
 }
index 3907cb1..d93a67a 100644 (file)
@@ -1056,10 +1056,8 @@ void InstructionSelection::loadString(const QString &str, V4IR::Temp *targetTemp
 
 void InstructionSelection::loadRegexp(V4IR::RegExp *sourceRegexp, V4IR::Temp *targetTemp)
 {
-    Value v = Value::fromObject(engine()->newRegExpObject(*sourceRegexp->value,
-                                                          sourceRegexp->flags));
-    _vmFunction->generatedValues.append(v);
-    _as->storeValue(v, targetTemp);
+    int id = jsUnitGenerator.registerRegExp(sourceRegexp);
+    generateFunctionCall(Assembler::Void, __qmljs_lookup_runtime_regexp, Assembler::ContextRegister, Assembler::PointerToValue(targetTemp), Assembler::TrustedImm32(id));
 }
 
 void InstructionSelection::getActivationProperty(const V4IR::Name *name, V4IR::Temp *temp)
index 57d559b..0effad9 100644 (file)
@@ -610,6 +610,16 @@ void ExecutionContext::throwURIError(Value msg)
     throwError(Value::fromObject(engine->newURIErrorObject(msg)));
 }
 
+const Function *ExecutionContext::runtimeFunction() const
+{
+    if (type >= Type_CallContext) {
+        const QV4::FunctionObject *f = asCallContext()->function;
+        Q_ASSERT(f);
+        return f ? f->function : 0;
+    }
+    Q_ASSERT(type == Type_GlobalContext);
+    return engine->globalCode;
+}
 
 void SimpleCallContext::initSimpleCallContext(ExecutionEngine *engine)
 {
index 3bae120..7c11113 100644 (file)
@@ -152,6 +152,8 @@ struct Q_QML_EXPORT ExecutionContext
 
     inline CallContext *asCallContext();
     inline const CallContext *asCallContext() const;
+
+    const Function *runtimeFunction() const;
 };
 
 struct SimpleCallContext : public ExecutionContext
index 8dcf65a..7d99a8e 100644 (file)
@@ -1226,6 +1226,13 @@ void __qmljs_value_from_string(Value *result, String *string)
     *result = Value::fromString(string);
 }
 
+void __qmljs_lookup_runtime_regexp(ExecutionContext *ctx, Value *result, int id)
+{
+    const QV4::Function *runtimeFunction = ctx->runtimeFunction();
+    Q_ASSERT(runtimeFunction);
+    *result = runtimeFunction->compilationUnit->runtimeRegularExpressions[id];
+}
+
 } // namespace QV4
 
 QT_END_NAMESPACE
index 31ee819..6f00d5b 100644 (file)
@@ -127,6 +127,7 @@ void __qmljs_builtin_define_getter_setter(QV4::ExecutionContext *ctx, const QV4:
 void __qmljs_builtin_define_object_literal(QV4::ExecutionContext *ctx, QV4::Value *result, const QV4::Value *args, QV4::InternalClass *klass);
 
 void __qmljs_value_from_string(QV4::Value *result, QV4::String *string);
+void __qmljs_lookup_runtime_regexp(QV4::ExecutionContext *ctx, QV4::Value *result, int id);
 
 // constructors
 void __qmljs_init_closure(QV4::ExecutionContext *ctx, QV4::Value *result, QV4::Function *clos);