#include <private/qv4engine_p.h>
#include <private/qv4function_p.h>
#include <private/qv4lookup_p.h>
+#include <private/qv4regexpobject_p.h>
namespace QV4 {
free(data);
free(runtimeStrings);
delete [] runtimeLookups;
+ delete [] runtimeRegularExpressions;
}
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();
{
for (int i = 0; i < data->stringTableSize; ++i)
runtimeStrings[i]->mark();
+ for (int i = 0; i < data->regexpTableSize; ++i)
+ runtimeRegularExpressions[i].mark();
}
}
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";
uint offsetToFunctionTable;
uint lookupTableSize;
uint offsetToLookupTable;
+ uint regexpTableSize;
+ uint offsetToRegexpTable;
uint indexOfRootFunction;
quint32 sourceFileIndex;
}
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
QV4::String **runtimeStrings; // Array
QV4::Lookup *runtimeLookups;
+ QV4::Value *runtimeRegularExpressions;
QV4::Function *linkToEngine(QV4::ExecutionEngine *engine);
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);
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) {
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);
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;
}
namespace CompiledData {
struct Unit;
struct Lookup;
+struct RegExp;
}
namespace Compiler {
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);
int stringDataSize;
QHash<QQmlJS::V4IR::Function *, uint> functionOffsets;
QList<CompiledData::Lookup> lookups;
+ QVector<CompiledData::RegExp> regexps;
};
}
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)
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)
{
inline CallContext *asCallContext();
inline const CallContext *asCallContext() const;
+
+ const Function *runtimeFunction() const;
};
struct SimpleCallContext : public ExecutionContext
*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
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);