_functionInfo.insert(function, new FunctionDebugInfo(function));
}
-void Debugger::addaddBasicBlockOffset(IR::Function *function, IR::BasicBlock *block, ptrdiff_t blockOffset)
+void Debugger::setSourceLocation(IR::Function *function, unsigned line, unsigned column)
{
- _functionInfo[function]->addBasicBlockOffset(block, blockOffset);
+ _functionInfo[function]->setSourceLocation(line, column);
}
-void Debugger::setSourceLocation(IR::Function *function, unsigned line, unsigned column)
+void Debugger::mapFunction(VM::Function *vmf, IR::Function *irf)
{
- _functionInfo[function]->setSourceLocation(line, column);
+ _vmToIr.insert(vmf, irf);
}
FunctionDebugInfo *Debugger::debugInfo(VM::FunctionObject *function) const
return 0;
if (VM::ScriptFunction *sf = function->asScriptFunction())
- return _functionInfo[sf->function];
+ return _functionInfo[irFunction(sf->function)];
else
return 0;
}
return -1;
}
+
+IR::Function *Debugger::irFunction(VM::Function *vmf) const
+{
+ return _vmToIr[vmf];
+}
struct FunctionDebugInfo { // TODO: use opaque d-pointers here
IR::Function *function;
- QHash<ptrdiff_t, IR::BasicBlock *> blockOffsets;
unsigned startLine, startColumn;
-
- FunctionDebugInfo(IR::Function *function): function(function), startLine(0), startColumn(0) {}
-
- void addBasicBlockOffset(IR::BasicBlock *block, ptrdiff_t offset) {
- blockOffsets.insert(offset, block);
- }
+ FunctionDebugInfo(IR::Function *function): function(function), startLine(0), startColumn(0) {}
void setSourceLocation(unsigned line, unsigned column)
{ startLine = line; startColumn = column; }
public: // compile-time interface
void addFunction(IR::Function *function);
- void addaddBasicBlockOffset(IR::Function *function, IR::BasicBlock *block, ptrdiff_t blockOffset);
void setSourceLocation(IR::Function *function, unsigned line, unsigned column);
+ void mapFunction(VM::Function *vmf, IR::Function *irf);
public: // run-time querying interface
FunctionDebugInfo *debugInfo(VM::FunctionObject *function) const;
private:
int callIndex(VM::ExecutionContext *context);
+ IR::Function *irFunction(VM::Function *vmf) const;
private: // TODO: use opaque d-pointers here
VM::ExecutionEngine *_engine;
QHash<IR::Function *, FunctionDebugInfo *> _functionInfo;
+ QHash<VM::Function *, IR::Function *> _vmToIr;
QVector<CallInfo> _callStack;
};
return EXIT_FAILURE;
}
- QScopedPointer<QQmlJS::IR::Function> f(QQmlJS::VM::EvalFunction::parseSource(ctx, fn, code, QQmlJS::Codegen::GlobalCode));
+ QQmlJS::VM::Function *f = QQmlJS::VM::EvalFunction::parseSource(ctx, fn, code, QQmlJS::Codegen::GlobalCode);
if (!f)
continue;
};
struct instr_loadClosure {
MOTH_INSTR_HEADER
- IR::Function *value;
+ VM::Function *value;
int targetTempIndex;
};
struct instr_loadName {
} // anonymous namespace
-InstructionSelection::InstructionSelection(VM::ExecutionEngine *engine)
- : _engine(engine)
+InstructionSelection::InstructionSelection(VM::ExecutionEngine *engine, IR::Module *module)
+ : EvalInstructionSelection(engine, module)
+ , _function(0)
+ , _block(0)
+ , _code(0)
+ , _ccode(0)
{
- // FIXME: make the size dynamic. This requires changing the patching.
- _code = new uchar[getpagesize() * 4000];
- _ccode = _code;
}
InstructionSelection::~InstructionSelection()
{
}
-void InstructionSelection::operator()(IR::Function *function)
+VM::Function *InstructionSelection::run(IR::Function *function)
{
qSwap(_function, function);
+ // FIXME: make the size dynamic. This requires changing the patching.
+ _code = new uchar[getpagesize() * 4000];
+ _ccode = _code;
CompressTemps().run(_function);
- _function->code = VME::exec;
- _function->codeData = _code;
-
int locals = frameSize();
assert(locals >= 0);
addInstruction(push);
foreach (_block, _function->basicBlocks) {
- ptrdiff_t blockOffset = _ccode - _code;
_addrs.insert(_block, _ccode - _code);
- if (_engine->debugger)
- _engine->debugger->addaddBasicBlockOffset(_function, _block, blockOffset);
foreach (IR::Stmt *s, _block->statements)
s->accept(this);
}
qSwap(_function, function);
+ _patches.clear();
+ _addrs.clear();
+
+ VM::Function *vmFunc = vmFunction(function);
+ vmFunc->code = VME::exec;
+ vmFunc->codeData = _code;
+
+ _block = 0;
+ _code = 0;
+ _ccode = 0;
+ return vmFunc;
}
void InstructionSelection::callActivationProperty(IR::Call *c, int targetTempIndex)
const int scratchIndex = scratchTempIndex();
Instruction::LoadName load;
- load.name = _engine->newString(*baseName->id);
+ load.name = engine()->newString(*baseName->id);
load.targetTempIndex = scratchIndex;
addInstruction(load);
if (IR::Member *m = c->args->expr->asMember()) {
Instruction::CallBuiltinDeleteMember call;
call.base = m->base->asTemp()->index;
- call.member = _engine->newString(*m->name);
+ call.member = engine()->newString(*m->name);
call.targetTempIndex = targetTempIndex;
addInstruction(call);
} else if (IR::Subscript *ss = c->args->expr->asSubscript()) {
addInstruction(call);
} else if (IR::Name *n = c->args->expr->asName()) {
Instruction::CallBuiltinDeleteName call;
- call.name = _engine->newString(*n->id);
+ call.name = engine()->newString(*n->id);
call.targetTempIndex = targetTempIndex;
addInstruction(call);
} else {
for (IR::ExprList *it = c->args->next; it; it = it->next) {
Instruction::CallBuiltinDeclareVar call;
call.isDeletable = isDeletable;
- call.varName = _engine->newString(*it->expr->asName()->id);
+ call.varName = engine()->newString(*it->expr->asName()->id);
}
} break;
// call the property on the loaded base
Instruction::CallProperty call;
call.baseTemp = m->base->asTemp()->index;
- call.name = _engine->newString(*m->name);
+ call.name = engine()->newString(*m->name);
prepareCallArgs(c->args, call.argc, call.args);
call.targetTempIndex = targetTempIndex;
addInstruction(call);
{
if (IR::Name *baseName = ctor->base->asName()) {
Instruction::CreateActivationProperty create;
- create.name = _engine->newString(*baseName->id);
+ create.name = engine()->newString(*baseName->id);
prepareCallArgs(ctor->args, create.argc, create.args);
create.targetTempIndex = targetTempIndex;
addInstruction(create);
Instruction::CreateProperty create;
create.base = base->index;
- create.name = _engine->newString(*member->name);
+ create.name = engine()->newString(*member->name);
prepareCallArgs(ctor->args, create.argc, create.args);
create.targetTempIndex = targetTempIndex;
addInstruction(create);
addInstruction(load);
} else {
Instruction::LoadName load;
- load.name = _engine->newString(*n->id);
+ load.name = engine()->newString(*n->id);
load.targetTempIndex = targetTempIndex;
addInstruction(load);
}
}
} else if (IR::String *str = s->source->asString()) {
Instruction::LoadValue load;
- load.value = VM::Value::fromString(_engine->newString(*str->value));
+ load.value = VM::Value::fromString(engine()->newString(*str->value));
load.targetTempIndex = targetTempIndex;
addInstruction(load);
} else if (IR::Closure *clos = s->source->asClosure()) {
+ VM::Function *vmFunc = vmFunction(clos->value);
+ assert(vmFunc);
Instruction::LoadClosure load;
- load.value = clos->value;
+ load.value = vmFunc;
load.targetTempIndex = targetTempIndex;
addInstruction(load);
} else if (IR::New *ctor = s->source->asNew()) {
if (IR::Temp *base = m->base->asTemp()) {
Instruction::LoadProperty load;
load.baseTemp = base->index;
- load.name = _engine->newString(*m->name);
+ load.name = engine()->newString(*m->name);
load.targetTempIndex = targetTempIndex;
addInstruction(load);
} else {
if (op) {
Instruction::InplaceNameOp ieo;
ieo.alu = op;
- ieo.targetName = _engine->newString(*n->id);
+ ieo.targetName = engine()->newString(*n->id);
ieo.sourceIsTemp = toValueOrTemp(s->source, ieo.source);
addInstruction(ieo);
return;
} else if (s->op == IR::OpInvalid) {
Instruction::StoreName store;
store.sourceIsTemp = toValueOrTemp(s->source, store.source);
- store.name = _engine->newString(*n->id);
+ store.name = engine()->newString(*n->id);
addInstruction(store);
return;
}
Instruction::InplaceMemberOp imo;
imo.alu = op;
imo.targetBase = m->base->asTemp()->index;
- imo.targetMember = _engine->newString(*m->name);
+ imo.targetMember = engine()->newString(*m->name);
imo.sourceIsTemp = toValueOrTemp(s->source, imo.source);
addInstruction(imo);
return;
} else if (s->op == IR::OpInvalid) {
Instruction::StoreProperty store;
store.baseTemp = m->base->asTemp()->index;
- store.name = _engine->newString(*m->name);
+ store.name = engine()->newString(*m->name);
store.sourceIsTemp = toValueOrTemp(s->source, store.source);
addInstruction(store);
return;
class InstructionSelection : public IR::StmtVisitor, public EvalInstructionSelection
{
public:
- InstructionSelection(VM::ExecutionEngine *engine);
+ InstructionSelection(VM::ExecutionEngine *engine, IR::Module *module);
~InstructionSelection();
- virtual void run(IR::Function *function)
- { this->operator()(function); }
- virtual void operator()(IR::Function *function);
+ virtual VM::Function *run(IR::Function *function);
protected:
virtual void visitExp(IR::Exp *);
inline ptrdiff_t addInstruction(const InstrData<Instr> &data);
ptrdiff_t addInstructionHelper(Instr::Type type, Instr &instr);
- VM::ExecutionEngine *_engine;
IR::Function *_function;
IR::BasicBlock *_block;
{
public:
virtual ~ISelFactory() {}
- virtual EvalInstructionSelection *create(VM::ExecutionEngine *engine)
- { return new InstructionSelection(engine); }
+ virtual EvalInstructionSelection *create(VM::ExecutionEngine *engine, IR::Module *module)
+ { return new InstructionSelection(engine, module); }
};
template<int InstrT>
delete globalObject.asObject();
delete rootContext;
delete stringPool;
+ qDeleteAll(functions);
}
ExecutionContext *ExecutionEngine::newContext()
return id;
}
+Function *ExecutionEngine::newFunction(const QString &name)
+{
+ VM::Function *f = new VM::Function(name);
+ functions.append(f);
+ return f;
+}
+
FunctionObject *ExecutionEngine::newNativeFunction(ExecutionContext *scope, String *name, Value (*code)(ExecutionContext *))
{
NativeFunction *f = new (memoryManager) NativeFunction(scope, name, code);
return f;
}
-FunctionObject *ExecutionEngine::newScriptFunction(ExecutionContext *scope, IR::Function *function)
+FunctionObject *ExecutionEngine::newScriptFunction(ExecutionContext *scope, VM::Function *function)
{
+ assert(function);
+
MemoryManager::GCBlocker gcBlocker(memoryManager);
ScriptFunction *f = new (memoryManager) ScriptFunction(scope, function);
struct Value;
class Array;
+struct Function;
struct Object;
struct BooleanObject;
struct NumberObject;
Value exception;
struct StringPool *stringPool;
+ QVector<Function *> functions;
ExecutionEngine(MemoryManager *memoryManager, EvalISelFactory *iselFactory);
~ExecutionEngine();
String *identifier(const QString &s);
+ VM::Function *newFunction(const QString &name);
+
FunctionObject *newNativeFunction(ExecutionContext *scope, String *name, Value (*code)(ExecutionContext *));
- FunctionObject *newScriptFunction(ExecutionContext *scope, IR::Function *function);
+ FunctionObject *newScriptFunction(ExecutionContext *scope, VM::Function *function);
Object *newObject();
FunctionObject *newObjectCtor(ExecutionContext *ctx);
value.getCollectables(objects);
}
+Function::~Function()
+{
+ delete[] codeData;
+}
+
bool FunctionObject::hasInstance(ExecutionContext *ctx, const Value &value)
{
if (! value.isObject()) {
return ctx->thisObject;
}
-ScriptFunction::ScriptFunction(ExecutionContext *scope, IR::Function *function)
+ScriptFunction::ScriptFunction(ExecutionContext *scope, VM::Function *function)
: FunctionObject(scope)
, function(function)
{
+ assert(function);
+ assert(function->code);
+
// global function
if (!scope)
return;
- if (function->name)
- name = scope->engine->identifier(*function->name);
+ if (!function->name.isEmpty())
+ name = scope->engine->identifier(function->name);
needsActivation = function->needsActivation();
strictMode = function->isStrict;
formalParameterCount = function->formals.size();
if (formalParameterCount) {
formalParameterList = new String*[formalParameterCount];
for (unsigned int i = 0; i < formalParameterCount; ++i) {
- formalParameterList[i] = scope->engine->identifier(*function->formals.at(i));
+ formalParameterList[i] = scope->engine->identifier(function->formals.at(i));
}
}
if (varCount) {
varList = new String*[varCount];
for (unsigned int i = 0; i < varCount; ++i) {
- varList[i] = scope->engine->identifier(*function->locals.at(i));
+ varList[i] = scope->engine->identifier(function->locals.at(i));
}
}
}
Value ScriptFunction::call(VM::ExecutionContext *ctx)
{
+ assert(function->code);
return function->code(ctx, function->codeData);
}
bool directCall = true;
const QString code = args[0].stringValue()->toQString();
- QScopedPointer<QQmlJS::IR::Function> f(parseSource(context, QStringLiteral("eval code"), code, QQmlJS::Codegen::EvalCode));
+ QQmlJS::VM::Function *f = parseSource(context, QStringLiteral("eval code"), code, QQmlJS::Codegen::EvalCode);
if (!f)
return Value::undefinedValue();
name = scope->engine->newString(QLatin1String("eval"));
}
-QQmlJS::IR::Function *EvalFunction::parseSource(QQmlJS::VM::ExecutionContext *ctx,
+QQmlJS::VM::Function *EvalFunction::parseSource(QQmlJS::VM::ExecutionContext *ctx,
const QString &fileName, const QString &source,
QQmlJS::Codegen::Mode mode)
{
VM::ExecutionEngine *vm = ctx->engine;
IR::Module module;
- IR::Function *globalCode = 0;
+ VM::Function *globalCode = 0;
{
QQmlJS::Engine ee, *engine = ⅇ
}
Codegen cg(ctx);
- globalCode = cg(fileName, program, &module, mode);
+ IR::Function *globalIRCode = cg(fileName, program, &module, mode);
+ QScopedPointer<EvalInstructionSelection> isel(ctx->engine->iselFactory->create(vm, &module));
+ if (globalIRCode) {
+ globalCode = isel->run(globalIRCode);
+ }
if (globalCode) {
// only generate other functions if global code generation succeeded.
foreach (IR::Function *function, module.functions) {
- EvalInstructionSelection *isel = ctx->engine->iselFactory->create(vm);
- isel->run(function);
- delete isel;
+ if (function == globalIRCode)
+ continue;
+ globalCode->nestedFunctions.append(isel->run(function));
}
}
}
namespace QQmlJS {
-namespace IR {
-struct Function;
-}
-
namespace VM {
struct Value;
+struct Function;
struct Object;
struct BooleanObject;
struct NumberObject;
virtual void getCollectables(QVector<Object *> &objects);
};
+struct Function {
+ QString name;
+
+ VM::Value (*code)(VM::ExecutionContext *, const uchar *);
+ const uchar *codeData;
+ JSC::MacroAssemblerCodeRef codeRef;
+
+ QList<QString> formals;
+ QList<QString> locals;
+ QVector<Function *> nestedFunctions;
+
+ bool hasDirectEval: 1;
+ bool isStrict: 1;
+
+ Function(const QString &name)
+ : name(name)
+ , code(0)
+ , codeData(0)
+ , hasDirectEval(false)
+ , isStrict(false)
+ {}
+ ~Function();
+
+ inline bool hasNestedFunctions() const { return !nestedFunctions.isEmpty(); }
+
+ inline bool needsActivation() const { return hasNestedFunctions() || hasDirectEval; }
+};
+
struct FunctionObject: Object {
ExecutionContext *scope;
String *name;
};
struct ScriptFunction: FunctionObject {
- IR::Function *function;
+ VM::Function *function;
- ScriptFunction(ExecutionContext *scope, IR::Function *function);
+ ScriptFunction(ExecutionContext *scope, VM::Function *function);
virtual ~ScriptFunction();
virtual Value call(ExecutionContext *ctx);
{
EvalFunction(ExecutionContext *scope);
- static QQmlJS::IR::Function *parseSource(QQmlJS::VM::ExecutionContext *ctx,
- const QString &fileName, const QString &source,
- QQmlJS::Codegen::Mode mode);
+ static QQmlJS::VM::Function *parseSource(QQmlJS::VM::ExecutionContext *ctx,
+ const QString &fileName,
+ const QString &source,
+ QQmlJS::Codegen::Mode mode);
virtual Value call(ExecutionContext *context, Value thisObject, Value *args, int argc);
};
extern "C" {
-Value __qmljs_init_closure(IR::Function *clos, ExecutionContext *ctx)
+Value __qmljs_init_closure(VM::Function *clos, ExecutionContext *ctx)
{
+ assert(clos);
return Value::fromObject(ctx->engine->newScriptFunction(ctx, clos));
}
#endif // TRACE1
namespace QQmlJS {
-
-namespace IR {
-struct Function;
-}
-
namespace VM {
enum TypeHint {
STRING_HINT
};
+struct Function;
struct Object;
struct String;
struct PropertyDescriptor;
void __qmljs_builtin_declare_var(ExecutionContext *ctx, bool deletable, String *name);
// constructors
-Value __qmljs_init_closure(IR::Function *clos, ExecutionContext *ctx);
+Value __qmljs_init_closure(VM::Function *clos, ExecutionContext *ctx);
Value __qmljs_init_native_function(String *name, Value (*code)(ExecutionContext *), ExecutionContext *ctx);
Bool __qmljs_is_function(Value value);
Codegen cg(ctx);
IR::Function *irf = cg(QString(), fe, &module);
- EvalInstructionSelection *isel = ctx->engine->iselFactory->create(ctx->engine);
- isel->run(irf);
- delete isel;
+ QScopedPointer<EvalInstructionSelection> isel(ctx->engine->iselFactory->create(ctx->engine, &module));
+ VM::Function *vmf = isel->run(irf);
- ctx->thisObject = Value::fromObject(ctx->engine->newScriptFunction(ctx->engine->rootContext, irf));
+ ctx->thisObject = Value::fromObject(ctx->engine->newScriptFunction(ctx->engine->rootContext, vmf));
return ctx->thisObject;
}
Module::~Module()
{
- foreach (Function *f, functions)
- f->releaseModuleManagedData();
+ foreach (Function *f, functions) {
+ delete f;
+ }
}
Function::~Function()
{
- delete[] codeData;
-}
-
-
-void Function::releaseModuleManagedData()
-{
// destroy the Stmt::Data blocks manually, because memory pool cleanup won't
// call the Stmt destructors.
foreach (IR::BasicBlock *b, basicBlocks)
QList<const QString *> formals;
QList<const QString *> locals;
- VM::Value (*code)(VM::ExecutionContext *, const uchar *);
- const uchar *codeData;
- JSC::MacroAssemblerCodeRef codeRef;
-
int insideWith;
bool hasDirectEval: 1;
, pool(&module->pool)
, tempCount(0)
, maxNumberOfArguments(0)
- , code(0)
- , codeData(0)
, insideWith(0)
, hasDirectEval(false)
, hasNestedFunctions(false)
{ this->name = newString(name); }
~Function();
- void releaseModuleManagedData();
enum BasicBlockInsertMode {
InsertBlock,
inline BasicBlock *insertBasicBlock(BasicBlock *block) { basicBlocks.append(block); return block; }
void dump(QTextStream &out, Stmt::Mode mode = Stmt::HIR);
-
- inline bool needsActivation() const { return hasNestedFunctions || hasDirectEval; }
};
struct BasicBlock {
}
#endif
-void Assembler::link()
+void Assembler::link(VM::Function *vmFunc)
{
QHashIterator<IR::BasicBlock *, QVector<Jump> > it(_patches);
while (it.hasNext()) {
#endif
QByteArray name = _function->name->toUtf8();
- _function->codeRef = linkBuffer.finalizeCodeWithDisassembly("%s", name.data());
+ vmFunc->codeRef = linkBuffer.finalizeCodeWithDisassembly("%s", name.data());
WTF::setDataFile(stderr);
#if OS(LINUX)
free(disasmOutput);
#endif
} else {
- _function->codeRef = linkBuffer.finalizeCodeWithoutDisassembly();
+ vmFunc->codeRef = linkBuffer.finalizeCodeWithoutDisassembly();
}
- _function->code = (Value (*)(VM::ExecutionContext *, const uchar *)) _function->codeRef.code().executableAddress();
+ vmFunc->code = (Value (*)(VM::ExecutionContext *, const uchar *)) vmFunc->codeRef.code().executableAddress();
}
-InstructionSelection::InstructionSelection(VM::ExecutionEngine *engine)
- : _engine(engine)
+InstructionSelection::InstructionSelection(VM::ExecutionEngine *engine, IR::Module *module)
+ : EvalInstructionSelection(engine, module)
, _block(0)
, _function(0)
, _asm(0)
delete _asm;
}
-void InstructionSelection::operator()(IR::Function *function)
+VM::Function *InstructionSelection::run(IR::Function *function)
{
qSwap(_function, function);
Assembler* oldAssembler = _asm;
#endif
_asm->ret();
- _asm->link();
+ VM::Function *vmFunc = vmFunction(_function);
+ _asm->link(vmFunc);
qSwap(_function, function);
delete _asm;
_asm = oldAssembler;
+
+ return vmFunc;
}
String *InstructionSelection::identifier(const QString &s)
{
- return _engine->identifier(s);
+ return engine()->identifier(s);
}
void InstructionSelection::callActivationProperty(IR::Call *call, IR::Temp *result)
return;
} else if (IR::String *str = s->source->asString()) {
Address dest = _asm->loadTempAddress(Assembler::ScratchRegister, t);
- Value v = Value::fromString(_engine->newString(*str->value));
+ Value v = Value::fromString(engine()->newString(*str->value));
_asm->storeValue(v, dest);
return;
} else if (IR::RegExp *re = s->source->asRegExp()) {
Address dest = _asm->loadTempAddress(Assembler::ScratchRegister, t);
- Value v = Value::fromObject(_engine->newRegExpObject(*re->value, re->flags));
+ Value v = Value::fromObject(engine()->newRegExpObject(*re->value, re->flags));
_asm->storeValue(v, dest);
return;
} else if (IR::Closure *clos = s->source->asClosure()) {
- generateFunctionCall(t, __qmljs_init_closure, Assembler::TrustedImmPtr(clos->value), Assembler::ContextRegister);
+ VM::Function *vmFunc = vmFunction(clos->value);
+ assert(vmFunc);
+ generateFunctionCall(t, __qmljs_init_closure, Assembler::TrustedImmPtr(vmFunc), Assembler::ContextRegister);
return;
} else if (IR::New *ctor = s->source->asNew()) {
if (ctor->base->asName()) {
return Jump();
}
- void link();
+ void link(VM::Function *vmFunc);
private:
IR::Function* _function;
class InstructionSelection: protected IR::StmtVisitor, public EvalInstructionSelection
{
public:
- InstructionSelection(VM::ExecutionEngine *engine);
+ InstructionSelection(VM::ExecutionEngine *engine, IR::Module *module);
~InstructionSelection();
- virtual void run(IR::Function *function)
- { this->operator()(function); }
- void operator()(IR::Function *function);
+ virtual VM::Function *run(IR::Function *function);
protected:
typedef Assembler::Address Address;
#define callRuntimeMethod(result, function, ...) \
callRuntimeMethodImp(result, isel_stringIfy(function), function, __VA_ARGS__)
-
- VM::ExecutionEngine *_engine;
IR::BasicBlock *_block;
IR::Function* _function;
Assembler* _asm;
{
public:
virtual ~ISelFactory() {}
- virtual EvalInstructionSelection *create(VM::ExecutionEngine *engine)
- { return new InstructionSelection(engine); }
+ virtual EvalInstructionSelection *create(VM::ExecutionEngine *engine, IR::Module *module)
+ { return new InstructionSelection(engine, module); }
};
} // end of namespace MASM
+#include "debugging.h"
+#include "qmljs_engine.h"
+#include "qv4ir_p.h"
#include "qv4isel_p.h"
+#include "qv4isel_util_p.h"
+
+#include <QString>
+
+#include <cassert>
using namespace QQmlJS;
+EvalInstructionSelection::EvalInstructionSelection(VM::ExecutionEngine *engine, IR::Module *module)
+ : _engine(engine)
+{
+ assert(engine);
+ assert(module);
+
+ foreach (IR::Function *f, module->functions)
+ _irToVM.insert(f, createFunctionMapping(engine, f));
+}
+
EvalInstructionSelection::~EvalInstructionSelection()
{}
EvalISelFactory::~EvalISelFactory()
{}
+
+VM::Function *EvalInstructionSelection::createFunctionMapping(VM::ExecutionEngine *engine, IR::Function *irFunction)
+{
+ VM::Function *vmFunction = engine->newFunction(irFunction->name ? *irFunction->name : QString());
+ vmFunction->hasDirectEval = irFunction->hasDirectEval;
+ vmFunction->isStrict = irFunction->isStrict;
+
+ foreach (const QString *formal, irFunction->formals)
+ if (formal)
+ vmFunction->formals.append(*formal);
+ foreach (const QString *local, irFunction->locals)
+ if (local)
+ vmFunction->locals.append(*local);
+
+ if (engine->debugger)
+ engine->debugger->mapFunction(vmFunction, irFunction);
+
+ return vmFunction;
+}
#define QV4ISEL_P_H
#include <qglobal.h>
+#include <QHash>
namespace QQmlJS {
namespace VM {
struct ExecutionEngine;
+struct Function;
} // namespace VM
class EvalInstructionSelection
{
public:
+ EvalInstructionSelection(VM::ExecutionEngine *engine, IR::Module *module);
virtual ~EvalInstructionSelection() = 0;
- virtual void run(IR::Function *function) = 0;
+ virtual VM::Function *run(IR::Function *function) = 0;
+
+protected:
+ VM::Function *createFunctionMapping(VM::ExecutionEngine *engine, IR::Function *irFunction);
+ VM::Function *vmFunction(IR::Function *f) const { return _irToVM[f]; }
+ VM::ExecutionEngine *engine() const { return _engine; }
+
+private:
+ VM::ExecutionEngine *_engine;
+ QHash<IR::Function *, VM::Function *> _irToVM;
};
class EvalISelFactory
{
public:
virtual ~EvalISelFactory() = 0;
- virtual EvalInstructionSelection *create(VM::ExecutionEngine *engine) = 0;
+ virtual EvalInstructionSelection *create(VM::ExecutionEngine *engine, IR::Module *module) = 0;
};
} // namespace QQmlJS