#include "qmljs_objects.h"
#include "qv4codegen_p.h"
+#include "qv4isel_p.h"
#include <QtCore>
#include <private/qqmljsengine_p.h>
#include <private/qqmljsparser_p.h>
#include <private/qqmljsast_p.h>
+#include <sys/mman.h>
#include <iostream>
+static inline bool protect(const void *addr, size_t size)
+{
+ size_t pageSize = sysconf(_SC_PAGESIZE);
+ size_t iaddr = reinterpret_cast<size_t>(addr);
+ size_t roundAddr = iaddr & ~(pageSize - static_cast<size_t>(1));
+ int mode = PROT_READ | PROT_WRITE | PROT_EXEC;
+ return mprotect(reinterpret_cast<void*>(roundAddr), size + (iaddr - roundAddr), mode) == 0;
+}
+
int main(int argc, char *argv[])
{
using namespace QQmlJS;
Program *program = AST::cast<Program *>(parser.rootNode());
Codegen cg;
- cg(program);
+ IR::Module module;
+ cg(program, &module);
+
+ const size_t codeSize = 10 * getpagesize();
+ uchar *code = (uchar *) malloc(codeSize);
+
+ x86_64::InstructionSelection isel(&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))
+ Q_UNREACHABLE();
+
+ VM::Context *ctx = new VM::Context;
+ ctx->activation = VM::Value::object(ctx, new VM::ArgumentsObject);
+ codeByName.value(QLatin1String("%entry"))->code(ctx);
}
}
}
#include "qv4codegen_p.h"
-#include "qv4isel_p.h"
#include <QtCore/QStringList>
#include <QtCore/QSet>
{
}
-void Codegen::operator()(AST::Program *node)
+void Codegen::operator()(AST::Program *node, IR::Module *module)
{
- IR::Module module;
- _module = &module;
+ _module = module;
IR::Function *globalCode = _module->newFunction(QLatin1String("%entry"));
_function = globalCode;
_block->JUMP(_exitBlock);
}
- x86_64::InstructionSelection isel(_module);
-
foreach (IR::Function *function, _module->functions) {
linearize(function);
- isel.visitFunction(function);
}
}
public:
Codegen();
- void operator()(AST::Program *ast);
+ void operator()(AST::Program *ast, IR::Module *module);
protected:
enum Format { ex, cx, nx };
namespace QQmlJS {
+namespace VM {
+struct Context;
+struct Value;
+}
+
namespace IR {
struct BasicBlock;
QSet<QString> strings;
QList<const QString *> formals;
QList<const QString *> locals;
+ void (*code)(VM::Context *);
template <typename _Tp> _Tp *New() { return new (pool->allocate(sizeof(_Tp))) _Tp(); }
Function(Module *module, const QString &name)
- : module(module), pool(&module->pool), tempCount(0) { this->name = newString(name); }
+ : module(module), pool(&module->pool), tempCount(0), code(0) { this->name = newString(name); }
~Function();
using namespace QQmlJS::x86_64;
using namespace QQmlJS::VM;
-static inline bool protect(const void *addr, size_t size)
-{
- size_t pageSize = sysconf(_SC_PAGESIZE);
- size_t iaddr = reinterpret_cast<size_t>(addr);
- size_t roundAddr = iaddr & ~(pageSize - static_cast<size_t>(1));
- int mode = PROT_READ | PROT_WRITE | PROT_EXEC;
- return mprotect(reinterpret_cast<void*>(roundAddr), size + (iaddr - roundAddr), mode) == 0;
-}
-
static inline void
amd64_patch (unsigned char* code, gpointer target)
{
else
x86_patch (code, (unsigned char*)target);
}
-InstructionSelection::InstructionSelection(IR::Module *module)
+InstructionSelection::InstructionSelection(IR::Module *module, uchar *buffer)
: _module(module)
, _function(0)
, _block(0)
- , _code(0)
- , _codePtr(0)
+ , _buffer(buffer)
+ , _code(buffer)
+ , _codePtr(buffer)
{
}
{
}
-void InstructionSelection::visitFunction(IR::Function *function)
+void InstructionSelection::operator()(IR::Function *function)
{
- uchar *code = (uchar *) malloc(getpagesize());
- assert(! (size_t(code) & 15));
-
- protect(code, getpagesize());
-
- uchar *codePtr = code;
-
- qSwap(_code, code);
- qSwap(_codePtr, codePtr);
+ _code = (uchar *) ((size_t(_code) + 15) & ~15);
+ function->code = (void (*)(VM::Context *)) _code;
+ _codePtr = _code;
int locals = function->tempCount * sizeof(Value);
locals = (locals + 15) & ~15;
amd64_pop_reg(_codePtr, AMD64_RBP);
amd64_ret(_codePtr);
- qSwap(_codePtr, codePtr);
- qSwap(_code, code);
-
#ifndef NO_UDIS86
static bool showCode = !qgetenv("SHOW_CODE").isNull();
if (showCode) {
ud_t ud_obj;
ud_init(&ud_obj);
- ud_set_input_buffer(&ud_obj, code, codePtr - code);
+ ud_set_input_buffer(&ud_obj, _code, _codePtr - _code);
ud_set_mode(&ud_obj, 64);
ud_set_syntax(&ud_obj, UD_SYN_ATT);
}
}
#endif
-
- void (*f)(Context *) = (void (*)(Context *)) code;
-
- Context *ctx = new Context;
- ctx->activation = Value::object(ctx, new ArgumentsObject);
- f(ctx);
}
String *InstructionSelection::identifier(const QString &s)
class InstructionSelection: protected IR::StmtVisitor
{
public:
- InstructionSelection(IR::Module *module);
+ InstructionSelection(IR::Module *module, uchar *code);
~InstructionSelection();
- void visitFunction(IR::Function *function);
+ void operator()(IR::Function *function);
protected:
VM::String *identifier(const QString &s);
IR::Module *_module;
IR::Function *_function;
IR::BasicBlock *_block;
+ uchar *_buffer;
uchar *_code;
uchar *_codePtr;
QHash<IR::BasicBlock *, QVector<uchar *> > _patches;