aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoberto Raggi <roberto.raggi@nokia.com>2012-05-16 19:00:31 +0200
committerRoberto Raggi <roberto.raggi@nokia.com>2012-05-16 19:00:31 +0200
commita34f11737ff29c383ab87b58258213a2ec92d74b (patch)
tree786471ebfdfdd9b23d7e32b36f531ce41fccc583
parentacb76025c450c5167f2c582de2c82c5078a5230a (diff)
Simplified the compiler.
-rw-r--r--main.cpp24
-rw-r--r--qv4codegen.cpp235
-rw-r--r--qv4codegen_p.h62
3 files changed, 168 insertions, 153 deletions
diff --git a/main.cpp b/main.cpp
index dec537a9de..9026a96f07 100644
--- a/main.cpp
+++ b/main.cpp
@@ -68,18 +68,14 @@ void evaluate(QQmlJS::VM::ExecutionEngine *vm, QQmlJS::Engine *engine, const QSt
Codegen cg;
IR::Module module;
- cg(program, &module);
+ IR::Function *globalCode = cg(program, &module);
const size_t codeSize = 10 * getpagesize();
uchar *code = (uchar *) malloc(codeSize);
x86_64::InstructionSelection isel(vm, &module, code);
- QHash<QString, IR::Function *> codeByName;
foreach (IR::Function *function, module.functions) {
isel(function);
- if (function->name && ! function->name->isEmpty()) {
- codeByName.insert(*function->name, function);
- }
}
if (! protect(code, codeSize))
@@ -91,13 +87,19 @@ void evaluate(QQmlJS::VM::ExecutionEngine *vm, QQmlJS::Engine *engine, const QSt
globalObject->put(vm->identifier(QLatin1String("print")),
VM::Value::fromObject(new builtins::Print(ctx)));
- foreach (IR::Function *function, module.functions) {
- if (function->name && ! function->name->isEmpty()) {
- globalObject->put(vm->identifier(*function->name),
- VM::Value::fromObject(ctx->engine->newScriptFunction(ctx, function)));
- }
+ ctx->varCount = globalCode->locals.size();
+ if (ctx->varCount) {
+ ctx->locals = new VM::Value[ctx->varCount];
+ ctx->vars = new VM::String*[ctx->varCount];
+ std::fill(ctx->locals, ctx->locals + ctx->varCount, VM::Value::undefinedValue());
+ for (size_t i = 0; i < ctx->varCount; ++i)
+ ctx->vars[i] = ctx->engine->identifier(*globalCode->locals.at(i));
}
- codeByName.value(QLatin1String("%entry"))->code(ctx);
+
+ globalCode->code(ctx);
+
+ delete[] ctx->locals;
+ delete[] ctx->vars;
}
}
diff --git a/qv4codegen.cpp b/qv4codegen.cpp
index ff50fb955d..a5f2b3d537 100644
--- a/qv4codegen.cpp
+++ b/qv4codegen.cpp
@@ -4,6 +4,7 @@
#include <QtCore/QSet>
#include <QtCore/QBuffer>
#include <QtCore/QBitArray>
+#include <QtCore/QStack>
#include <private/qqmljsast_p.h>
#include <iostream>
#include <cassert>
@@ -160,87 +161,110 @@ void liveness(IR::Function *function)
} // end of anonymous namespace
-struct Codegen::ScanFunctionBody: Visitor
+class Codegen::ScanFunctions: Visitor
{
- using Visitor::visit;
-
- // search for locals
- Codegen::Environment *env;
- QList<QStringRef> locals;
- int maxNumberOfArguments;
- bool hasDirectEval;
- bool hasNestedFunctions;
-
- ScanFunctionBody()
- : env(0)
- , maxNumberOfArguments(0)
- , hasDirectEval(false)
- , hasNestedFunctions(false)
+public:
+ ScanFunctions(Codegen *cg)
+ : _cg(cg)
+ , _env(0)
{
}
- void operator()(Node *node, Environment *e)
+ void operator()(Node *node)
{
- env = e;
- maxNumberOfArguments = 0;
- hasDirectEval = false;
- hasNestedFunctions = false;
- locals.clear();
+ _env = 0;
if (node)
node->accept(this);
}
protected:
+ using Visitor::visit;
+ using Visitor::endVisit;
+
+ inline void enterEnvironment(Node *node)
+ {
+ Environment *e = _cg->newEnvironment(node, _env);
+ _envStack.append(e);
+ _env = e;
+ }
+
+ inline void leaveEnvironment()
+ {
+ _envStack.pop();
+ _env = _envStack.isEmpty() ? 0 : _envStack.top();
+ }
+
+ virtual bool visit(Program *ast)
+ {
+ enterEnvironment(ast);
+ return true;
+ }
+
+ virtual void endVisit(Program *)
+ {
+ leaveEnvironment();
+ }
+
virtual bool visit(CallExpression *ast)
{
- if (! hasDirectEval) {
+ if (! _env->hasDirectEval) {
if (IdentifierExpression *id = cast<IdentifierExpression *>(ast->base)) {
if (id->name == QLatin1String("eval")) {
- hasDirectEval = true;
+ _env->hasDirectEval = true;
}
}
}
int argc = 0;
- for (AST::ArgumentList *it = ast->arguments; it; it = it->next)
+ for (ArgumentList *it = ast->arguments; it; it = it->next)
++argc;
- maxNumberOfArguments = qMax(maxNumberOfArguments, argc);
+ _env->maxNumberOfArguments = qMax(_env->maxNumberOfArguments, argc);
return true;
}
virtual bool visit(NewMemberExpression *ast)
{
int argc = 0;
- for (AST::ArgumentList *it = ast->arguments; it; it = it->next)
+ for (ArgumentList *it = ast->arguments; it; it = it->next)
++argc;
- maxNumberOfArguments = qMax(maxNumberOfArguments, argc);
+ _env->maxNumberOfArguments = qMax(_env->maxNumberOfArguments, argc);
return true;
}
virtual bool visit(VariableDeclaration *ast)
{
- env->enter(ast->name);
- if (! locals.contains(ast->name))
- locals.append(ast->name);
+ _env->enter(ast->name.toString());
return true;
}
virtual bool visit(FunctionExpression *ast)
{
- env->enter(ast->name);
- hasNestedFunctions = true;
- if (! locals.contains(ast->name))
- locals.append(ast->name);
- return false;
+ _env->hasNestedFunctions = true;
+ _env->enter(ast->name.toString());
+ enterEnvironment(ast);
+ return true;
+ }
+
+ virtual void endVisit(FunctionExpression *)
+ {
+ leaveEnvironment();
}
virtual bool visit(FunctionDeclaration *ast)
{
- env->enter(ast->name);
- hasNestedFunctions = true;
- if (! locals.contains(ast->name))
- locals.append(ast->name);
- return false;
+ _env->hasNestedFunctions = true;
+ _env->enter(ast->name.toString());
+ enterEnvironment(ast);
+ return true;
}
+
+ virtual void endVisit(FunctionDeclaration *)
+ {
+ leaveEnvironment();
+ }
+
+ Codegen *_cg;
+ Environment *_env;
+ QStack<Environment *> _envStack;
};
Codegen::Codegen()
@@ -253,38 +277,36 @@ Codegen::Codegen()
{
}
-void Codegen::operator()(AST::Program *node, IR::Module *module)
+IR::Function *Codegen::operator()(Program *node, IR::Module *module)
{
_module = module;
_env = 0;
- Scope scope(this, newEnvironment());
- ScanFunctionBody globalCodeInfo;
- globalCodeInfo(node, _env);
+ ScanFunctions scan(this);
+ scan(node);
- IR::Function *globalCode = _module->newFunction(QLatin1String("%entry"));
- globalCode->hasDirectEval = globalCodeInfo.hasDirectEval;
- globalCode->hasNestedFunctions = true; // ### FIXME: initialize it with globalCodeInfo.hasNestedFunctions;
- globalCode->maxNumberOfArguments = globalCodeInfo.maxNumberOfArguments;
- _function = globalCode;
- _block = _function->newBasicBlock();
- _exitBlock = _function->newBasicBlock();
- _returnAddress = _block->newTemp();
- move(_block->TEMP(_returnAddress), _block->CONST(IR::UndefinedType, 0));
- _exitBlock->RET(_exitBlock->TEMP(_returnAddress), IR::UndefinedType);
-
- program(node);
-
- if (! _block->isTerminated()) {
- _block->JUMP(_exitBlock);
- }
+ IR::Function *globalCode = defineFunction(QLatin1String("%entry"), node, 0, node->elements);
foreach (IR::Function *function, _module->functions) {
linearize(function);
}
- qDeleteAll(_allEnvironments);
- _allEnvironments.clear();
+ qDeleteAll(_envMap);
+ _envMap.clear();
+
+ return globalCode;
+}
+
+void Codegen::enterEnvironment(Node *node)
+{
+ _env = _envMap.value(node);
+ Q_ASSERT(_env);
+}
+
+void Codegen::leaveEnvironment()
+{
+ Q_ASSERT(_env);
+ _env = _env->parent;
}
IR::Expr *Codegen::member(IR::Expr *base, const QString *name)
@@ -504,8 +526,9 @@ void Codegen::functionBody(FunctionBody *ast)
void Codegen::program(Program *ast)
{
- if (ast)
+ if (ast) {
sourceElements(ast->elements);
+ }
}
void Codegen::propertyNameAndValueList(PropertyNameAndValueList *)
@@ -569,25 +592,11 @@ void Codegen::variableDeclaration(VariableDeclaration *ast)
{
if (ast->expression) {
Result expr = expression(ast->expression);
+ Q_ASSERT(expr.code);
- if (! expr.code)
- expr.code = _block->CONST(IR::UndefinedType, 0);
-
- if (! _function->needsActivation()) {
- int index = indexOfLocal(ast->name);
- if (index != -1) {
- move(_block->TEMP(index), *expr);
- return;
- }
- index = indexOfArgument(ast->name);
- if (index != -1) {
- move(_block->TEMP(-(index + 1)), *expr);
- return;
- }
- Q_UNREACHABLE();
- } else {
- move(_block->NAME(ast->name.toString(), ast->identifierToken.startLine, ast->identifierToken.startColumn), *expr);
- }
+ const int index = _env->findMember(ast->name.toString());
+ Q_ASSERT(index != -1);
+ move(_block->TEMP(index), *expr);
}
}
@@ -1005,14 +1014,21 @@ bool Codegen::visit(FieldMemberExpression *ast)
bool Codegen::visit(FunctionExpression *ast)
{
- defineFunction(ast, false);
+ IR::Function *function = defineFunction(ast->name.toString(), ast, ast->formals, ast->body ? ast->body->elements : 0, false);
+ if (_expr.accept(nx)) {
+ const int index = _env->findMember(ast->name.toString());
+ Q_ASSERT(index != -1);
+ move(_block->TEMP(index), _block->CLOSURE(function));
+ } else {
+ _expr.code = _block->CLOSURE(function);
+ }
return false;
}
bool Codegen::visit(IdentifierExpression *ast)
{
if (! _function->needsActivation()) {
- int index = indexOfLocal(ast->name);
+ int index = _env->findMember(ast->name.toString());
if (index != -1) {
_expr.code = _block->TEMP(index);
return false;
@@ -1216,7 +1232,14 @@ bool Codegen::visit(VoidExpression *ast)
bool Codegen::visit(FunctionDeclaration *ast)
{
- defineFunction(ast);
+ IR::Function *function = defineFunction(ast->name.toString(), ast, ast->formals, ast->body ? ast->body->elements : 0, true);
+ if (_expr.accept(nx)) {
+ const int index = _env->findMember(ast->name.toString());
+ Q_ASSERT(index != -1);
+ move(_block->TEMP(index), _block->CLOSURE(function));
+ } else {
+ _expr.code = _block->CLOSURE(function);
+ }
return false;
}
@@ -1373,47 +1396,42 @@ void Codegen::linearize(IR::Function *function)
#endif
}
-void Codegen::defineFunction(FunctionExpression *ast, bool /*isDeclaration*/)
+IR::Function *Codegen::defineFunction(const QString &name, AST::Node *ast,
+ AST::FormalParameterList *formals,
+ AST::SourceElements *body, bool /*isDeclaration*/)
{
- Scope scope(this, newEnvironment());
- ScanFunctionBody functionInfo;
- functionInfo(ast->body, _env);
-
- IR::Function *function = _module->newFunction(ast->name.toString());
+ enterEnvironment(ast);
+ IR::Function *function = _module->newFunction(name);
IR::BasicBlock *entryBlock = function->newBasicBlock();
IR::BasicBlock *exitBlock = function->newBasicBlock();
- function->hasDirectEval = functionInfo.hasDirectEval;
- function->hasNestedFunctions = functionInfo.hasNestedFunctions;
- function->maxNumberOfArguments = functionInfo.maxNumberOfArguments;
+ function->hasDirectEval = _env->hasDirectEval;
+ function->hasNestedFunctions = _env->hasNestedFunctions;
+ function->maxNumberOfArguments = _env->maxNumberOfArguments;
- //if (! function->needsActivation())
- {
- for (int i = 0; i < functionInfo.locals.size(); ++i) {
- unsigned t = entryBlock->newTemp();
- Q_ASSERT(t == unsigned(i));
- //entryBlock->MOVE(entryBlock->TEMP(t), entryBlock->CONST(IR::UndefinedType, 0));
- }
+ for (int i = 0; i < _env->vars.size(); ++i) {
+ unsigned t = entryBlock->newTemp();
+ Q_ASSERT(t == unsigned(i));
}
unsigned returnAddress = entryBlock->newTemp();
entryBlock->MOVE(entryBlock->TEMP(returnAddress), entryBlock->CONST(IR::UndefinedType, 0));
- exitBlock->RET(_block->TEMP(returnAddress), IR::InvalidType);
+ exitBlock->RET(exitBlock->TEMP(returnAddress), IR::InvalidType);
qSwap(_function, function);
qSwap(_block, entryBlock);
qSwap(_exitBlock, exitBlock);
qSwap(_returnAddress, returnAddress);
- for (FormalParameterList *it = ast->formals; it; it = it->next) {
+ for (FormalParameterList *it = formals; it; it = it->next) {
_function->RECEIVE(it->name.toString());
}
- foreach (const QStringRef &local, functionInfo.locals) {
- _function->LOCAL(local.toString());
+ foreach (const QString &local, _env->vars) {
+ _function->LOCAL(local);
}
- functionBody(ast->body);
+ sourceElements(body);
if (! _block->isTerminated())
_block->JUMP(_exitBlock);
@@ -1423,11 +1441,8 @@ void Codegen::defineFunction(FunctionExpression *ast, bool /*isDeclaration*/)
qSwap(_exitBlock, exitBlock);
qSwap(_returnAddress, returnAddress);
- if (_expr.accept(nx)) {
- // nothing to do
- } else {
- _expr.code = _block->CLOSURE(function);
- }
+ leaveEnvironment();
+ return function;
}
int Codegen::indexOfLocal(const QStringRef &string) const
diff --git a/qv4codegen_p.h b/qv4codegen_p.h
index c44341306a..f8780016dd 100644
--- a/qv4codegen_p.h
+++ b/qv4codegen_p.h
@@ -15,7 +15,7 @@ class Codegen: protected AST::Visitor
public:
Codegen();
- void operator()(AST::Program *ast, IR::Module *module);
+ IR::Function *operator()(AST::Program *ast, IR::Module *module);
protected:
enum Format { ex, cx, nx };
@@ -55,19 +55,24 @@ protected:
struct Environment {
Environment *parent;
- QHash<QStringRef, int> members;
- int count;
+ QHash<QString, int> members;
+ QVector<QString> vars;
+ int maxNumberOfArguments;
+ bool hasDirectEval;
+ bool hasNestedFunctions;
- Environment(Environment *parent = 0)
+ Environment(Environment *parent)
: parent(parent)
- , count(0) {}
+ , maxNumberOfArguments(0)
+ , hasDirectEval(false)
+ , hasNestedFunctions(false) {}
- int findMember(const QStringRef &name) const
+ int findMember(const QString &name) const
{
return members.value(name, -1);
}
- bool lookupMember(const QStringRef &name, Environment **scope, int *index, int *distance)
+ bool lookupMember(const QString &name, Environment **scope, int *index, int *distance)
{
Environment *it = this;
*distance = 0;
@@ -82,36 +87,25 @@ protected:
return false;
}
- void enter(const QStringRef &name)
+ void enter(const QString &name)
{
- int idx = members.value(name, -1);
- if (idx == -1)
- members.insert(name, count++);
+ if (! name.isEmpty()) {
+ int idx = members.value(name, -1);
+ if (idx == -1) {
+ members.insert(name, vars.count());
+ vars.append(name);
+ }
+ }
}
};
- Environment *newEnvironment()
- {
- Environment *scope = new Environment(_env);
- return scope;
- }
-
- Environment *changeEnvironment(Environment *env)
+ Environment *newEnvironment(AST::Node *node, Environment *parent)
{
- qSwap(_env, env);
+ Environment *env = new Environment(parent);
+ _envMap.insert(node, env);
return env;
}
- struct Scope {
- Codegen *cg;
- Environment *previous;
- inline Scope(Codegen *cg, Environment *env): cg(cg) { previous = cg->changeEnvironment(env); }
- inline ~Scope() { cg->changeEnvironment(previous); }
-
- private:
- Q_DISABLE_COPY(Scope)
- };
-
struct UiMember {
};
@@ -126,6 +120,9 @@ protected:
: breakBlock(breakBlock), continueBlock(continueBlock) {}
};
+ void enterEnvironment(AST::Node *node);
+ void leaveEnvironment();
+
IR::Expr *member(IR::Expr *base, const QString *name);
IR::Expr *subscript(IR::Expr *base, IR::Expr *index);
IR::Expr *argument(IR::Expr *expr);
@@ -134,7 +131,8 @@ protected:
void move(IR::Expr *target, IR::Expr *source, IR::AluOp op = IR::OpInvalid);
void linearize(IR::Function *function);
- void defineFunction(AST::FunctionExpression *ast, bool isDeclaration = false);
+ IR::Function *defineFunction(const QString &name, AST::Node *ast, AST::FormalParameterList *formals,
+ AST::SourceElements *body, bool isDeclaration = false);
int indexOfLocal(const QStringRef &string) const;
int indexOfArgument(const QStringRef &string) const;
@@ -284,10 +282,10 @@ private:
IR::BasicBlock *_block;
IR::BasicBlock *_exitBlock;
unsigned _returnAddress;
- QVector<Environment *> _allEnvironments;
Environment *_env;
+ QHash<AST::Node *, Environment *> _envMap;
- struct ScanFunctionBody;
+ class ScanFunctions;
};
} // end of namespace QQmlJS