#include "qv4compileddata_p.h"
#include "qv4jsir_p.h"
+#include <private/qv4engine_p.h>
namespace QV4 {
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;
+}
}
namespace QV4 {
+struct Function;
struct ExecutionContext;
namespace CompiledData {
+struct String;
+
static const char magic_str[] = "qv4cdata";
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; }
};
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;
}
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
// free all jitted code
}
+ virtual QV4::Function *linkBackendToEngine(QV4::ExecutionEngine *engine);
+
// Coderef + execution engine
+ // ### remove
+ QV4::Function *rootFunction;
};
struct MothCompilationUnit : public CompilationUnit
: irModule(module)
, stringDataSize(0)
{
- isel = engine->iselFactory->create(engine, irModule);
}
int QV4::Compiler::JSUnitGenerator::registerString(const QString &str)
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);
#include <QtCore/qstring.h>
#include "qv4jsir_p.h"
-#include <qv4isel_p.h>
QT_BEGIN_NAMESPACE
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;
, _as(0)
, _locals(0)
{
+ QV4::CompiledData::MasmCompilationUnit *masmUnit = new QV4::CompiledData::MasmCompilationUnit;
+ compilationUnit = masmUnit;
+ masmUnit->rootFunction = _irToVM[module->rootFunction];
}
InstructionSelection::~InstructionSelection()
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)
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));
}
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;
EvalInstructionSelection::EvalInstructionSelection(QV4::ExecutionEngine *engine, Module *module)
: _engine(engine)
, useFastLookups(true)
+ , jsUnitGenerator(engine, module)
+ , compilationUnit(0)
{
assert(engine);
assert(module);
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)
#include "private/qv4global_p.h"
#include "qv4jsir_p.h"
+#include <private/qv4compileddata_p.h>
+#include <private/qv4compiler_p.h>
#include <qglobal.h>
#include <QHash>
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; }
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
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()
#include <config.h>
#include <assembler/MacroAssemblerCodeRef.h>
#include "qv4value_def_p.h"
+#include <private/qv4compileddata_p.h>
QT_BEGIN_NAMESPACE
int refCount;
String *name;
+ CompiledData::CompilationUnit *compilationUnit;
Value (*code)(ExecutionContext *, const uchar *);
const uchar *codeData;
JSC::MacroAssemblerCodeRef codeRef;
Function(ExecutionEngine *engine, String *name)
: refCount(0)
, name(name)
+ , compilationUnit(0)
, code(0)
, codeData(0)
, codeSize(0)
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));
}
}
}
+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
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,
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)