aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--moth/qv4isel_moth.cpp32
-rw-r--r--moth/qv4isel_moth_p.h2
-rw-r--r--qmljs_objects.cpp13
-rw-r--r--qv4codegen.cpp4
-rw-r--r--qv4ecmaobjects.cpp2
-rw-r--r--qv4ir.cpp8
-rw-r--r--qv4ir_p.h7
-rw-r--r--qv4isel_masm.cpp7
-rw-r--r--qv4isel_masm_p.h2
-rw-r--r--qv4isel_p.cpp18
-rw-r--r--qv4isel_p.h4
11 files changed, 60 insertions, 39 deletions
diff --git a/moth/qv4isel_moth.cpp b/moth/qv4isel_moth.cpp
index 5b00ccf552..14fd1cbbd3 100644
--- a/moth/qv4isel_moth.cpp
+++ b/moth/qv4isel_moth.cpp
@@ -194,12 +194,24 @@ InstructionSelection::~InstructionSelection()
{
}
-VM::Function *InstructionSelection::run(IR::Function *function)
+void InstructionSelection::run(VM::Function *vmFunction, IR::Function *function)
{
qSwap(_function, function);
+
+ IR::BasicBlock *block;
+
+ QHash<IR::BasicBlock *, QVector<ptrdiff_t> > patches;
+ QHash<IR::BasicBlock *, ptrdiff_t> addrs;
+
// FIXME: make the size dynamic. This requires changing the patching.
- _code = new uchar[getpagesize() * 4000];
- _ccode = _code;
+ uchar *code = new uchar[getpagesize() * 4000];
+ uchar *ccode = code;
+
+ qSwap(block, _block);
+ qSwap(patches, _patches);
+ qSwap(addrs, _addrs);
+ qSwap(code, _code);
+ qSwap(ccode, _ccode);
CompressTemps().run(_function);
@@ -235,14 +247,14 @@ VM::Function *InstructionSelection::run(IR::Function *function)
_patches.clear();
_addrs.clear();
- VM::Function *vmFunc = vmFunction(function);
- vmFunc->code = VME::exec;
- vmFunc->codeData = _code;
+ vmFunction->code = VME::exec;
+ vmFunction->codeData = _code;
- _block = 0;
- _code = 0;
- _ccode = 0;
- return vmFunc;
+ qSwap(block, _block);
+ qSwap(patches, _patches);
+ qSwap(addrs, _addrs);
+ qSwap(code, _code);
+ qSwap(ccode, _ccode);
}
void InstructionSelection::callActivationProperty(IR::Call *c, int targetTempIndex)
diff --git a/moth/qv4isel_moth_p.h b/moth/qv4isel_moth_p.h
index e7c85174c3..dece41323f 100644
--- a/moth/qv4isel_moth_p.h
+++ b/moth/qv4isel_moth_p.h
@@ -15,7 +15,7 @@ public:
InstructionSelection(VM::ExecutionEngine *engine, IR::Module *module);
~InstructionSelection();
- virtual VM::Function *run(IR::Function *function);
+ virtual void run(VM::Function *vmFunction, IR::Function *function);
protected:
virtual void visitExp(IR::Exp *);
diff --git a/qmljs_objects.cpp b/qmljs_objects.cpp
index 8ab6e50178..b282332c2e 100644
--- a/qmljs_objects.cpp
+++ b/qmljs_objects.cpp
@@ -671,17 +671,8 @@ QQmlJS::VM::Function *EvalFunction::parseSource(QQmlJS::VM::ExecutionContext *ct
Codegen cg(ctx);
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) {
- if (function == globalIRCode)
- continue;
- globalCode->nestedFunctions.append(isel->run(function));
- }
- }
+ if (globalIRCode)
+ globalCode = isel->vmFunction(globalIRCode);
}
if (! globalCode)
diff --git a/qv4codegen.cpp b/qv4codegen.cpp
index 7409a54bc6..1cbdc843a6 100644
--- a/qv4codegen.cpp
+++ b/qv4codegen.cpp
@@ -1650,14 +1650,14 @@ IR::Function *Codegen::defineFunction(const QString &name, AST::Node *ast,
TryCleanup *tryCleanup = 0;
enterEnvironment(ast);
- IR::Function *function = _module->newFunction(name);
+ IR::Function *function = _module->newFunction(name, _function);
+
if (_debugger)
_debugger->addFunction(function);
IR::BasicBlock *entryBlock = function->newBasicBlock();
IR::BasicBlock *exitBlock = function->newBasicBlock(IR::Function::DontInsertBlock);
IR::BasicBlock *throwBlock = function->newBasicBlock();
function->hasDirectEval = _env->hasDirectEval;
- function->hasNestedFunctions = _env->hasNestedFunctions;
function->maxNumberOfArguments = _env->maxNumberOfArguments;
function->isStrict = _env->isStrict;
diff --git a/qv4ecmaobjects.cpp b/qv4ecmaobjects.cpp
index 1a95c14603..6bf661cdce 100644
--- a/qv4ecmaobjects.cpp
+++ b/qv4ecmaobjects.cpp
@@ -2058,7 +2058,7 @@ Value FunctionCtor::construct(ExecutionContext *ctx)
IR::Function *irf = cg(QString(), fe, &module);
QScopedPointer<EvalInstructionSelection> isel(ctx->engine->iselFactory->create(ctx->engine, &module));
- VM::Function *vmf = isel->run(irf);
+ VM::Function *vmf = isel->vmFunction(irf);
ctx->thisObject = Value::fromObject(ctx->engine->newScriptFunction(ctx->engine->rootContext, vmf));
return ctx->thisObject;
diff --git a/qv4ir.cpp b/qv4ir.cpp
index 33b8b7721d..8d4c4f8b53 100644
--- a/qv4ir.cpp
+++ b/qv4ir.cpp
@@ -386,10 +386,16 @@ void Ret::dump(QTextStream &out, Mode)
out << ';';
}
-Function *Module::newFunction(const QString &name)
+Function *Module::newFunction(const QString &name, Function *outer)
{
Function *f = new Function(this, name);
functions.append(f);
+ if (!outer) {
+ assert(!rootFunction);
+ rootFunction = f;
+ } else {
+ outer->nestedFunctions.append(f);
+ }
return f;
}
diff --git a/qv4ir_p.h b/qv4ir_p.h
index b605e60b26..5f474f215c 100644
--- a/qv4ir_p.h
+++ b/qv4ir_p.h
@@ -587,9 +587,11 @@ struct Ret: Stmt {
struct Module {
MemoryPool pool;
QVector<Function *> functions;
+ Function *rootFunction;
- Function *newFunction(const QString &name);
+ Function *newFunction(const QString &name, Function *outer);
+ Module() : rootFunction(0) {}
~Module();
};
@@ -603,11 +605,11 @@ struct Function {
QSet<QString> strings;
QList<const QString *> formals;
QList<const QString *> locals;
+ QVector<Function *> nestedFunctions;
int insideWith;
bool hasDirectEval: 1;
- bool hasNestedFunctions: 1;
bool isStrict: 1;
template <typename _Tp> _Tp *New() { return new (pool->allocate(sizeof(_Tp))) _Tp(); }
@@ -619,7 +621,6 @@ struct Function {
, maxNumberOfArguments(0)
, insideWith(0)
, hasDirectEval(false)
- , hasNestedFunctions(false)
, isStrict(false)
{ this->name = newString(name); }
diff --git a/qv4isel_masm.cpp b/qv4isel_masm.cpp
index cabd1f7c5c..298d0b51f1 100644
--- a/qv4isel_masm.cpp
+++ b/qv4isel_masm.cpp
@@ -381,7 +381,7 @@ InstructionSelection::~InstructionSelection()
delete _asm;
}
-VM::Function *InstructionSelection::run(IR::Function *function)
+void InstructionSelection::run(VM::Function *vmFunction, IR::Function *function)
{
qSwap(_function, function);
Assembler* oldAssembler = _asm;
@@ -425,14 +425,11 @@ VM::Function *InstructionSelection::run(IR::Function *function)
#endif
_asm->ret();
- VM::Function *vmFunc = vmFunction(_function);
- _asm->link(vmFunc);
+ _asm->link(vmFunction);
qSwap(_function, function);
delete _asm;
_asm = oldAssembler;
-
- return vmFunc;
}
String *InstructionSelection::identifier(const QString &s)
diff --git a/qv4isel_masm_p.h b/qv4isel_masm_p.h
index ca32511ae4..481392c571 100644
--- a/qv4isel_masm_p.h
+++ b/qv4isel_masm_p.h
@@ -647,7 +647,7 @@ public:
InstructionSelection(VM::ExecutionEngine *engine, IR::Module *module);
~InstructionSelection();
- virtual VM::Function *run(IR::Function *function);
+ virtual void run(VM::Function *vmFunction, IR::Function *function);
protected:
typedef Assembler::Address Address;
diff --git a/qv4isel_p.cpp b/qv4isel_p.cpp
index 5a668fa246..b49d4d3adc 100644
--- a/qv4isel_p.cpp
+++ b/qv4isel_p.cpp
@@ -16,8 +16,10 @@ EvalInstructionSelection::EvalInstructionSelection(VM::ExecutionEngine *engine,
assert(engine);
assert(module);
- foreach (IR::Function *f, module->functions)
- _irToVM.insert(f, createFunctionMapping(engine, f));
+ createFunctionMapping(engine, module->rootFunction);
+ foreach (IR::Function *f, module->functions) {
+ assert(_irToVM.contains(f));
+ }
}
EvalInstructionSelection::~EvalInstructionSelection()
@@ -29,6 +31,8 @@ EvalISelFactory::~EvalISelFactory()
VM::Function *EvalInstructionSelection::createFunctionMapping(VM::ExecutionEngine *engine, IR::Function *irFunction)
{
VM::Function *vmFunction = engine->newFunction(irFunction->name ? *irFunction->name : QString());
+ _irToVM.insert(irFunction, vmFunction);
+
vmFunction->hasDirectEval = irFunction->hasDirectEval;
vmFunction->isStrict = irFunction->isStrict;
@@ -39,8 +43,18 @@ VM::Function *EvalInstructionSelection::createFunctionMapping(VM::ExecutionEngin
if (local)
vmFunction->locals.append(*local);
+ foreach (IR::Function *function, irFunction->nestedFunctions)
+ vmFunction->nestedFunctions.append(createFunctionMapping(engine, function));
+
if (engine->debugger)
engine->debugger->mapFunction(vmFunction, irFunction);
return vmFunction;
}
+
+VM::Function *EvalInstructionSelection::vmFunction(IR::Function *f) {
+ VM::Function *function = _irToVM[f];
+ if (!function->code)
+ run(function, f);
+ return function;
+}
diff --git a/qv4isel_p.h b/qv4isel_p.h
index 109ff795a5..221a564f32 100644
--- a/qv4isel_p.h
+++ b/qv4isel_p.h
@@ -51,12 +51,12 @@ public:
EvalInstructionSelection(VM::ExecutionEngine *engine, IR::Module *module);
virtual ~EvalInstructionSelection() = 0;
- virtual VM::Function *run(IR::Function *function) = 0;
+ VM::Function *vmFunction(IR::Function *f);
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; }
+ virtual void run(VM::Function *vmFunction, IR::Function *function) = 0;
private:
VM::ExecutionEngine *_engine;