Move the instruction selection pass.
authorRoberto Raggi <roberto.raggi@nokia.com>
Mon, 7 May 2012 12:46:37 +0000 (14:46 +0200)
committerRoberto Raggi <roberto.raggi@nokia.com>
Mon, 7 May 2012 12:46:37 +0000 (14:46 +0200)
main.cpp
qv4codegen.cpp
qv4codegen_p.h
qv4ir_p.h
qv4isel.cpp
qv4isel_p.h

index f16eec2..e95a3aa 100644 (file)
--- a/main.cpp
+++ b/main.cpp
@@ -1,6 +1,7 @@
 
 #include "qmljs_objects.h"
 #include "qv4codegen_p.h"
+#include "qv4isel_p.h"
 
 #include <QtCore>
 #include <private/qqmljsengine_p.h>
@@ -8,8 +9,18 @@
 #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;
@@ -41,7 +52,26 @@ int main(int argc, char *argv[])
                 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);
             }
         }
     }
index 3407ed3..6f9181b 100644 (file)
@@ -1,5 +1,4 @@
 #include "qv4codegen_p.h"
-#include "qv4isel_p.h"
 
 #include <QtCore/QStringList>
 #include <QtCore/QSet>
@@ -288,10 +287,9 @@ Codegen::Codegen()
 {
 }
 
-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;
@@ -306,11 +304,8 @@ void Codegen::operator()(AST::Program *node)
         _block->JUMP(_exitBlock);
     }
 
-    x86_64::InstructionSelection isel(_module);
-
     foreach (IR::Function *function, _module->functions) {
         linearize(function);
-        isel.visitFunction(function);
     }
 }
 
index 6f3cb90..f1163c1 100644 (file)
@@ -15,7 +15,7 @@ class Codegen: protected AST::Visitor
 public:
     Codegen();
 
-    void operator()(AST::Program *ast);
+    void operator()(AST::Program *ast, IR::Module *module);
 
 protected:
     enum Format { ex, cx, nx };
index a606563..b13ebdc 100644 (file)
--- a/qv4ir_p.h
+++ b/qv4ir_p.h
@@ -68,6 +68,11 @@ class QQmlType;
 
 namespace QQmlJS {
 
+namespace VM {
+struct Context;
+struct Value;
+}
+
 namespace IR {
 
 struct BasicBlock;
@@ -585,11 +590,12 @@ struct Function {
     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();
 
index 7c6e216..a5a63da 100644 (file)
@@ -23,15 +23,6 @@ using namespace QQmlJS;
 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)
 {
@@ -85,12 +76,13 @@ 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)
 {
 }
 
@@ -98,17 +90,11 @@ InstructionSelection::~InstructionSelection()
 {
 }
 
-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;
@@ -146,16 +132,13 @@ void InstructionSelection::visitFunction(IR::Function *function)
     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);
 
@@ -164,12 +147,6 @@ void InstructionSelection::visitFunction(IR::Function *function)
         }
     }
 #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)
index 9c85c19..0672bc5 100644 (file)
@@ -12,10 +12,10 @@ namespace x86_64 {
 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);
@@ -34,6 +34,7 @@ private:
     IR::Module *_module;
     IR::Function *_function;
     IR::BasicBlock *_block;
+    uchar *_buffer;
     uchar *_code;
     uchar *_codePtr;
     QHash<IR::BasicBlock *, QVector<uchar *> > _patches;