Change the V4 IR so it can be stored in a memory pool.
authorRoberto Raggi <roberto.raggi@nokia.com>
Tue, 19 Jul 2011 13:12:40 +0000 (15:12 +0200)
committerQt by Nokia <qt-info@nokia.com>
Tue, 30 Aug 2011 11:18:28 +0000 (13:18 +0200)
That is, remove members with a non-trivial destructor from IR::Stmt
and IR::Expr (that's because we don't destroy the objects
allocated in the pool).

Added the method MemoryPool::reset() so we can clear the pool
without disposing the allocated memory.

Change-Id: I126332be387c016578c086db8b3aa8098b2507f6
Reviewed-on: http://codereview.qt.nokia.com/3758
Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>

src/declarative/qml/parser/qdeclarativejsmemorypool_p.h
src/declarative/qml/v4/qdeclarativev4compiler.cpp
src/declarative/qml/v4/qdeclarativev4compiler_p_p.h
src/declarative/qml/v4/qdeclarativev4ir.cpp
src/declarative/qml/v4/qdeclarativev4ir_p.h
src/declarative/qml/v4/qdeclarativev4irbuilder.cpp

index e921ac6..043331d 100644 (file)
@@ -57,8 +57,9 @@
 
 #include <QtCore/qglobal.h>
 #include <QtCore/qshareddata.h>
+#include <QtCore/qdebug.h>
 
-#include <string.h>
+#include <cstring>
 
 QT_QML_BEGIN_NAMESPACE
 
@@ -66,63 +67,89 @@ namespace QDeclarativeJS {
 
 class QML_PARSER_EXPORT MemoryPool : public QSharedData
 {
+    MemoryPool(const MemoryPool &other);
+    void operator =(const MemoryPool &other);
+
 public:
-    enum { maxBlockCount = -1 };
-    enum { defaultBlockSize = 1 << 12 };
-
-    MemoryPool() {
-        m_blockIndex = maxBlockCount;
-        m_currentIndex = 0;
-        m_storage = 0;
-        m_currentBlock = 0;
-        m_currentBlockSize = 0;
+    MemoryPool()
+        : _blocks(0),
+          _allocatedBlocks(0),
+          _blockCount(-1),
+          _ptr(0),
+          _end(0)
+    { }
+
+    ~MemoryPool()
+    {
+        if (_blocks) {
+            for (int i = 0; i < _allocatedBlocks; ++i) {
+                if (char *b = _blocks[i])
+                    qFree(b);
+            }
+
+            qFree(_blocks);
+        }
     }
 
-    virtual ~MemoryPool() {
-        for (int index = 0; index < m_blockIndex + 1; ++index)
-            qFree(m_storage[index]);
+    inline void *allocate(size_t size)
+    {
+        size = (size + 7) & ~7;
+        if (_ptr && (_ptr + size < _end)) {
+            void *addr = _ptr;
+            _ptr += size;
+            return addr;
+        }
+        return allocate_helper(size);
+    }
 
-        qFree(m_storage);
+    void reset()
+    {
+        _blockCount = -1;
+        _ptr = _end = 0;
     }
 
-    char *allocate(int bytes) {
-        bytes += (8 - bytes) & 7; // ensure multiple of 8 bytes (maintain alignment)
-        if (m_currentBlock == 0 || m_currentBlockSize < m_currentIndex + bytes) {
-            ++m_blockIndex;
-            m_currentBlockSize = defaultBlockSize << m_blockIndex;
+private:
+    void *allocate_helper(size_t size)
+    {
+        Q_ASSERT(size < BLOCK_SIZE);
 
-            m_storage = reinterpret_cast<char**>(qRealloc(m_storage, sizeof(char*) * (1 + m_blockIndex)));
-            m_currentBlock = m_storage[m_blockIndex] = reinterpret_cast<char*>(qMalloc(m_currentBlockSize));
+        if (++_blockCount == _allocatedBlocks) {
+            if (! _allocatedBlocks)
+                _allocatedBlocks = DEFAULT_BLOCK_COUNT;
+            else
+                _allocatedBlocks *= 2;
 
-            m_currentIndex = (8 - quintptr(m_currentBlock)) & 7; // ensure first chunk is 64-bit aligned
-            Q_ASSERT(m_currentIndex + bytes <= m_currentBlockSize);
+            _blocks = (char **) qRealloc(_blocks, sizeof(char *) * _allocatedBlocks);
+
+            for (int index = _blockCount; index < _allocatedBlocks; ++index)
+                _blocks[index] = 0;
         }
 
-        char *p = reinterpret_cast<char *>
-            (m_currentBlock + m_currentIndex);
+        char *&block = _blocks[_blockCount];
 
-        m_currentIndex += bytes;
+        if (! block)
+            block = (char *) qMalloc(BLOCK_SIZE);
 
-        return p;
-    }
+        _ptr = block;
+        _end = _ptr + BLOCK_SIZE;
 
-    int bytesAllocated() const {
-        int bytes = 0;
-        for (int index = 0; index < m_blockIndex; ++index)
-            bytes += (defaultBlockSize << index);
-        bytes += m_currentIndex;
-        return bytes;
+        void *addr = _ptr;
+        _ptr += size;
+        return addr;
     }
 
 private:
-    int m_blockIndex;
-    int m_currentIndex;
-    char *m_currentBlock;
-    int m_currentBlockSize;
-    char **m_storage;
-
-private:
-    Q_DISABLE_COPY(MemoryPool)
+    char **_blocks;
+    int _allocatedBlocks;
+    int _blockCount;
+    char *_ptr;
+    char *_end;
+
+    enum
+    {
+        BLOCK_SIZE = 8 * 1024,
+        DEFAULT_BLOCK_COUNT = 8
+    };
 };
 
 class QML_PARSER_EXPORT Managed
index 371edda..332ce03 100644 (file)
@@ -91,11 +91,11 @@ void QDeclarativeV4CompilerPrivate::trace(int line, int column)
         if (IR::Stmt *terminator = block->terminator()) {
             if (IR::CJump *cj = terminator->asCJump()) {
                 if (cj->iffalse != next) {
-                    block->i(new IR::Jump(cj->iffalse));
+                    block->i(new (_function->module->pool) IR::Jump(cj->iffalse));
                 }
             } else if (IR::Jump *j = terminator->asJump()) {
                 if (j->target == next) {
-                    delete block->statements.back();
+                    delete block->statements.at(block->statements.size() - 1);
                     block->statements.resize(block->statements.size() - 1);
                 }
             }
@@ -174,9 +174,8 @@ void QDeclarativeV4CompilerPrivate::trace(int line, int column)
 
 void QDeclarativeV4CompilerPrivate::trace(QVector<IR::BasicBlock *> *blocks)
 {
-    QList<IR::BasicBlock *> todo = QList<IR::BasicBlock *>::fromVector(_function->basicBlocks);
-    while (! todo.isEmpty()) {
-        IR::BasicBlock *block = todo.takeFirst();
+    for (int i = 0; i < _function->basicBlocks.size(); ++i) {
+        IR::BasicBlock *block = _function->basicBlocks.at(i);
 
         while (! blocks->contains(block)) {
             blocks->append(block);
@@ -763,8 +762,9 @@ void QDeclarativeV4CompilerPrivate::visitBinop(IR::Binop *e)
 void QDeclarativeV4CompilerPrivate::visitCall(IR::Call *call)
 {
     if (IR::Name *name = call->base->asName()) {
-        if (call->args.size() == 1 && call->args.at(0)->type == IR::RealType) {
-            traceExpression(call->args.at(0), currentReg);
+        IR::Expr *arg = call->onlyArgument();
+        if (arg != 0 && arg->type == IR::RealType) {
+            traceExpression(arg, currentReg);
 
             Instr instr;
             instr.common.type = Instr::Noop;
@@ -989,6 +989,7 @@ void QDeclarativeV4CompilerPrivate::resetInstanceState()
     registeredStrings = committed.registeredStrings;
     bytecode.clear();
     patches.clear();
+    pool.reset(); // reset the memory pool without disposing the allocated memory
     currentReg = 0;
 }
 
@@ -1032,7 +1033,7 @@ bool QDeclarativeV4CompilerPrivate::compile(QDeclarativeJS::AST::Node *node)
         return false;
     }
 
-    IR::Module module;
+    IR::Module module(&pool);
     IR::Function *function = 0;
 
     QDeclarativeV4IRBuilder irBuilder(expression, engine);
@@ -1067,7 +1068,7 @@ bool QDeclarativeV4CompilerPrivate::compile(QDeclarativeJS::AST::Node *node)
 }
 
 // Returns a reg
-int QDeclarativeV4CompilerPrivate::registerLiteralString(quint8 reg, const QString &str)
+int QDeclarativeV4CompilerPrivate::registerLiteralString(quint8 reg, const QStringRef &str)
 {
     // ### string cleanup
 
index 1d9414d..e2c85f4 100644 (file)
@@ -111,7 +111,7 @@ public:
 
     QHash<int, QPair<int, int> > registerCleanups;
 
-    int registerLiteralString(quint8 reg, const QString &);
+    int registerLiteralString(quint8 reg, const QStringRef &);
     int registerString(const QString &);
     QHash<QString, QPair<int, int> > registeredStrings;
     QByteArray data;
@@ -137,6 +137,7 @@ public:
             : block(block), offset(index) {}
     };
     QVector<Patch> patches;
+    QDeclarativeJS::MemoryPool pool;
 
     // Committed binding data
     struct {
index c9c2c08..bc2cc62 100644 (file)
@@ -165,10 +165,11 @@ void String::dump(QTextStream &out)
     out << '"' << escape(value) << '"';
 }
 
-QString String::escape(const QString &s)
+QString String::escape(const QStringRef &s)
 {
     QString r;
-    foreach (const QChar &ch, s) {
+    for (int i = 0; i < s.length(); ++i) {
+        const QChar ch = s.at(i);
         if (ch == QLatin1Char('\n'))
             r += QLatin1String("\\n");
         else if (ch == QLatin1Char('\r'))
@@ -185,7 +186,7 @@ QString String::escape(const QString &s)
     return r;
 }
 
-Name::Name(Name *base, Type type, const QString &id, Symbol symbol, quint32 line, quint32 column)
+Name::Name(Name *base, Type type, QString &id, Symbol symbol, quint32 line, quint32 column)
 : Expr(type)
   , base(base)
   , id(id)
@@ -318,10 +319,10 @@ void Call::dump(QTextStream &out)
 {
     base->dump(out);
     out << '(';
-    for (int i = 0; i < args.size(); ++i) {
-        if (i)
+    for (ExprList *it = args; it; it = it->next) {
+        if (it != args)
             out << ", ";
-        args.at(i)->dump(out);
+        it->expr->dump(out);
     }
     out << ')';
 }
@@ -396,7 +397,6 @@ void Ret::dump(QTextStream &out, Mode)
 Function::~Function()
 {
     qDeleteAll(basicBlocks);
-    qDeleteAll(temps);
 }
 
 BasicBlock *Function::newBasicBlock()
@@ -419,7 +419,7 @@ void Function::dump(QTextStream &out)
 
 Temp *BasicBlock::TEMP(Type type, int index) 
 { 
-    return function->e(new Temp(type, index)); 
+    return function->e(new (function->module->pool) Temp(type, index));
 }
 
 Temp *BasicBlock::TEMP(Type type) 
@@ -434,12 +434,12 @@ Expr *BasicBlock::CONST(double value)
 
 Expr *BasicBlock::CONST(Type type, double value) 
 { 
-    return function->e(new Const(type, value)); 
+    return function->e(new (function->module->pool) Const(type, value));
 }
 
-Expr *BasicBlock::STRING(const QString &value) 
+Expr *BasicBlock::STRING(const QStringRef &value)
 { 
-    return function->e(new String(value)); 
+    return function->e(new (function->module->pool) String(value));
 }
 
 Name *BasicBlock::NAME(const QString &id, quint32 line, quint32 column)
@@ -449,7 +449,9 @@ Name *BasicBlock::NAME(const QString &id, quint32 line, quint32 column)
 
 Name *BasicBlock::NAME(Name *base, const QString &id, quint32 line, quint32 column)
 { 
-    return function->e(new Name(base, InvalidType, id, Name::Unbound, line, column));
+    return function->e(new (function->module->pool) Name(base, InvalidType,
+                                                          function->module->newIdentifier(id),
+                                                          Name::Unbound, line, column));
 }
 
 Name *BasicBlock::SYMBOL(Type type, const QString &id, const QMetaObject *meta, int index, Name::Storage storage,
@@ -463,7 +465,9 @@ Name *BasicBlock::SYMBOL(Type type, const QString &id, const QMetaObject *meta,
 Name *BasicBlock::SYMBOL(Name *base, Type type, const QString &id, const QMetaObject *meta, int index, Name::Storage storage,
                          quint32 line, quint32 column)
 {
-    Name *name = new Name(base, type, id, Name::Property, line, column);
+    Name *name = new (function->module->pool) Name(base, type,
+                                                    function->module->newIdentifier(id),
+                                                    Name::Property, line, column);
     name->meta = meta;
     name->index = index;
     name->storage = storage;
@@ -473,7 +477,9 @@ Name *BasicBlock::SYMBOL(Name *base, Type type, const QString &id, const QMetaOb
 Name *BasicBlock::SYMBOL(Name *base, Type type, const QString &id, const QMetaObject *meta, int index,
                          quint32 line, quint32 column)
 {
-    Name *name = new Name(base, type, id, Name::Property, line, column);
+    Name *name = new (function->module->pool) Name(base, type,
+                                                    function->module->newIdentifier(id),
+                                                    Name::Property, line, column);
     name->meta = meta;
     name->index = index;
     return function->e(name);
@@ -481,7 +487,9 @@ Name *BasicBlock::SYMBOL(Name *base, Type type, const QString &id, const QMetaOb
 
 Name *BasicBlock::ID_OBJECT(const QString &id, const QDeclarativeParser::Object *object, quint32 line, quint32 column)
 {
-    Name *name = new Name(/*base = */ 0, IR::ObjectType, id, Name::IdObject, line, column);
+    Name *name = new (function->module->pool) Name(/*base = */ 0, IR::ObjectType,
+                                                    function->module->newIdentifier(id),
+                                                    Name::IdObject, line, column);
     name->idObject = object;
     name->index = object->idIndex;
     name->storage = Name::IdStorage;
@@ -491,7 +499,9 @@ Name *BasicBlock::ID_OBJECT(const QString &id, const QDeclarativeParser::Object
 Name *BasicBlock::ATTACH_TYPE(const QString &id, const QDeclarativeType *attachType, Name::Storage storage,
                               quint32 line, quint32 column)
 { 
-    Name *name = new Name(/*base = */ 0, IR::AttachType, id, Name::AttachType, line, column);
+    Name *name = new (function->module->pool) Name(/*base = */ 0, IR::AttachType,
+                                                    function->module->newIdentifier(id),
+                                                    Name::AttachType, line, column);
     name->declarativeType = attachType;
     name->storage = storage;
     return function->e(name);
@@ -500,7 +510,7 @@ Name *BasicBlock::ATTACH_TYPE(const QString &id, const QDeclarativeType *attachT
 
 Expr *BasicBlock::UNOP(AluOp op, Expr *expr) 
 { 
-    return function->e(new Unop(op, expr)); 
+    return function->e(new (function->module->pool) Unop(op, expr));
 }
 
 Expr *BasicBlock::BINOP(AluOp op, Expr *left, Expr *right)
@@ -543,22 +553,22 @@ Expr *BasicBlock::BINOP(AluOp op, Expr *left, Expr *right)
         }
     }
 
-    return function->e(new Binop(op, left, right));
+    return function->e(new (function->module->pool) Binop(op, left, right));
 }
 
-Expr *BasicBlock::CALL(Expr *base, const QVector<Expr *> &args) 
+Expr *BasicBlock::CALL(Expr *base, ExprList *args)
 { 
-    return function->e(new Call(base, args));
+    return function->e(new (function->module->pool) Call(base, args));
 }
 
 Stmt *BasicBlock::EXP(Expr *expr) 
 { 
-    return i(new Exp(expr));
+    return i(new (function->module->pool) Exp(expr));
 }
 
 Stmt *BasicBlock::MOVE(Expr *target, Expr *source, bool isMoveForReturn) 
 { 
-    return i(new Move(target, source, isMoveForReturn));
+    return i(new (function->module->pool) Move(target, source, isMoveForReturn));
 }
 
 Stmt *BasicBlock::JUMP(BasicBlock *target) 
@@ -566,14 +576,14 @@ Stmt *BasicBlock::JUMP(BasicBlock *target)
     if (isTerminated())
         return 0;
     else
-        return i(new Jump(target));
+        return i(new (function->module->pool) Jump(target));
 }
 
 Stmt *BasicBlock::CJUMP(Expr *cond, BasicBlock *iftrue, BasicBlock *iffalse) 
 {
     if (isTerminated())
         return 0;
-    return i(new CJump(cond, iftrue, iffalse));
+    return i(new (function->module->pool) CJump(cond, iftrue, iffalse));
 }
 
 Stmt *BasicBlock::RET(Expr *expr, Type type, quint32 line, quint32 column)
@@ -581,7 +591,7 @@ Stmt *BasicBlock::RET(Expr *expr, Type type, quint32 line, quint32 column)
     if (isTerminated())
         return 0;
     else
-        return i(new Ret(expr, type, line, column));
+        return i(new (function->module->pool) Ret(expr, type, line, column));
 }
 
 void BasicBlock::dump(QTextStream &out)
@@ -594,6 +604,31 @@ void BasicBlock::dump(QTextStream &out)
     }
 }
 
+Module::Module(MemoryPool *pool)
+    : pool(pool)
+{
+}
+
+Module::~Module()
+{
+    qDeleteAll(functions);
+    qDeleteAll(strings);
+}
+
+QString &Module::newIdentifier(const QString &text)
+{
+    QString *s = new QString(text);
+    strings.append(s);
+    return *s;
+}
+
+Function *Module::newFunction(const QString &name)
+{
+    Function *f = new Function(this, name);
+    functions.append(f);
+    return f;
+}
+
 void Module::dump(QTextStream &out)
 {
     foreach (Function *fun, functions) {
index e8fde4f..a27b8d8 100644 (file)
@@ -60,7 +60,8 @@
 #include <private/qdeclarativeengine_p.h>
 #include <private/qdeclarativev4compiler_p.h>
 
-#include <QtCore/qvector.h>
+#include <qdeclarativejsmemorypool_p.h>
+#include <QtCore/qvarlengtharray.h>.h>
 
 // #define DEBUG_IR_STRUCTURE
 
@@ -175,7 +176,7 @@ struct StmtVisitor {
     virtual void visitRet(Ret *) {}
 };
 
-struct Expr {
+struct Expr: Managed {
     Type type;
 
     Expr(Type type): type(type) {}
@@ -191,6 +192,14 @@ struct Expr {
     virtual void dump(QTextStream &out) = 0;
 };
 
+struct ExprList: Managed {
+    Expr *expr;
+    ExprList *next;
+
+    ExprList(Expr *expr, ExprList *next = 0)
+        : expr(expr), next(next) {}
+};
+
 struct Const: Expr {
     double value;
     Const(Type type, double value): Expr(type), value(value) {}
@@ -202,14 +211,14 @@ struct Const: Expr {
 };
 
 struct String: Expr {
-    QString value;
-    String(const QString &value): Expr(StringType), value(value) {}
+    QStringRef value;
+    String(const QStringRef &value): Expr(StringType), value(value) {}
 
     virtual void accept(ExprVisitor *v) { v->visitString(this); }
     virtual String *asString() { return this; }
 
     virtual void dump(QTextStream &out);
-    static QString escape(const QString &s);
+    static QString escape(const QStringRef &s);
 };
 
 enum BuiltinSymbol {
@@ -240,7 +249,7 @@ struct Name: Expr {
     };
 
     Name *base;
-    QString id;
+    QString &id;
     Symbol symbol;
     union {
         void *ptr;
@@ -254,7 +263,7 @@ struct Name: Expr {
     quint32 line;
     quint32 column;
 
-    Name(Name *base, Type type, const QString &id, Symbol symbol, quint32 line, quint32 column);
+    Name(Name *base, Type type, QString &id, Symbol symbol, quint32 line, quint32 column);
 
     inline bool is(Symbol s) const { return s == symbol; }
     inline bool isNot(Symbol s) const { return s != symbol; }
@@ -309,11 +318,17 @@ private:
 
 struct Call: Expr {
     Expr *base;
-    QVector<Expr *> args;
+    ExprList *args;
 
-    Call(Expr *base, const QVector<Expr *> &args)
+    Call(Expr *base, ExprList *args)
         : Expr(typeForFunction(base)), base(base), args(args) {}
 
+    Expr *onlyArgument() const {
+        if (args && ! args->next)
+            return args->expr;
+        return 0;
+    }
+
     virtual void accept(ExprVisitor *v) { v->visitCall(this); }
     virtual Call *asCall() { return this; }
 
@@ -323,7 +338,7 @@ private:
     static Type typeForFunction(Expr *base);
 };
 
-struct Stmt {
+struct Stmt: Managed {
     enum Mode {
         HIR,
         MIR
@@ -409,11 +424,10 @@ struct Function {
     Module *module;
     QString name;
     int tempCount;
-    QVector<BasicBlock *> basicBlocks;
-    QVector<Expr *> temps;
+    QVarLengthArray<BasicBlock *, 8> basicBlocks;
 
     template <typename BB> inline BB i(BB i) { basicBlocks.append(i); return i; }
-    template <typename E> inline E e(E e) { temps.append(e); return e; }
+    template <typename E> inline E e(E e) { return e; }
 
     Function(Module *module, const QString &name): module(module), name(name), tempCount(0) {}
     ~Function();
@@ -426,11 +440,11 @@ struct Function {
 struct BasicBlock {
     Function *function;
     int index;
-    QVector<Stmt *> statements;
     int offset;
+    QVarLengthArray<Stmt *, 32> statements;
 
     BasicBlock(Function *function, int index): function(function), index(index), offset(-1) {}
-    ~BasicBlock() { qDeleteAll(statements); }
+    ~BasicBlock() {}
 
     template <typename Instr> inline Instr i(Instr i) { statements.append(i); return i; }
 
@@ -439,8 +453,8 @@ struct BasicBlock {
     }
 
     inline Stmt *terminator() const {
-        if (! statements.isEmpty() && statements.last()->asTerminator() != 0)
-            return statements.last();
+        if (! statements.isEmpty() && statements.at(statements.size() - 1)->asTerminator() != 0)
+            return statements.at(statements.size() - 1);
         return 0;
     }
 
@@ -455,7 +469,7 @@ struct BasicBlock {
 
     Expr *CONST(double value);
     Expr *CONST(Type type, double value);
-    Expr *STRING(const QString &value);
+    Expr *STRING(const QStringRef &value);
 
     Name *NAME(const QString &id, quint32 line, quint32 column);
     Name *NAME(Name *base, const QString &id, quint32 line, quint32 column);
@@ -467,7 +481,7 @@ struct BasicBlock {
 
     Expr *UNOP(AluOp op, Expr *expr);
     Expr *BINOP(AluOp op, Expr *left, Expr *right);
-    Expr *CALL(Expr *base, const QVector<Expr *> &args);
+    Expr *CALL(Expr *base, ExprList *args);
 
     Stmt *EXP(Expr *expr);
     Stmt *MOVE(Expr *target, Expr *source, bool = false);
@@ -480,14 +494,15 @@ struct BasicBlock {
 };
 
 struct Module {
-    QVector<Function *> functions;
-
-    Module() {}
-    ~Module() { qDeleteAll(functions); }
+    MemoryPool *pool;
+    QVarLengthArray<Function *, 4> functions;
+    QVarLengthArray<QString *, 8> strings;
 
-    template <typename BB> inline BB i(BB i) { functions.append(i); return i; }
+    Module(MemoryPool *pool);
+    ~Module();
 
-    Function *newFunction(const QString &name = QString()) { return i(new Function(this, name)); }
+    QString &newIdentifier(const QString &text);
+    Function *newFunction(const QString &name = QString());
 
     virtual void dump(QTextStream &out);
 };
index 1b8abba..fa67f57 100644 (file)
@@ -544,7 +544,7 @@ bool QDeclarativeV4IRBuilder::visit(AST::FalseLiteral *)
 bool QDeclarativeV4IRBuilder::visit(AST::StringLiteral *ast)
 {
     // ### TODO: cx format
-    _expr.code = _block->STRING(ast->value.toString());
+    _expr.code = _block->STRING(ast->value);
     return false;
 }
 
@@ -704,9 +704,12 @@ bool QDeclarativeV4IRBuilder::visit(AST::CallExpression *ast)
         const quint32 column = nameNodes.last()->firstSourceLocation().startColumn;
         IR::Expr *base = _block->NAME(id, line, column);
 
-        QVector<IR::Expr *> args;
-        for (AST::ArgumentList *it = ast->arguments; it; it = it->next)
-            args.append(expression(it->expression));
+        IR::ExprList *args = 0, **argsInserter = &args;
+        for (AST::ArgumentList *it = ast->arguments; it; it = it->next) {
+            IR::Expr *arg = expression(it->expression);
+            *argsInserter = new (_module->pool) IR::ExprList(arg);
+            argsInserter = &(*argsInserter)->next;
+        }
 
         IR::Temp *r = _block->TEMP(IR::InvalidType);
         IR::Expr *call = _block->CALL(base, args);