Skip to content

Commit

Permalink
Change the V4 IR so it can be stored in a memory pool.
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Roberto Raggi authored and Qt by Nokia committed Aug 30, 2011
1 parent 5f54b6c commit ef9751e
Show file tree
Hide file tree
Showing 6 changed files with 188 additions and 106 deletions.
111 changes: 69 additions & 42 deletions src/declarative/qml/parser/qdeclarativejsmemorypool_p.h
Expand Up @@ -57,72 +57,99 @@

#include <QtCore/qglobal.h>
#include <QtCore/qshareddata.h>
#include <QtCore/qdebug.h>

#include <string.h>
#include <cstring>

QT_QML_BEGIN_NAMESPACE

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
Expand Down
19 changes: 10 additions & 9 deletions src/declarative/qml/v4/qdeclarativev4compiler.cpp
Expand Up @@ -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);
}
}
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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

Expand Down
3 changes: 2 additions & 1 deletion src/declarative/qml/v4/qdeclarativev4compiler_p_p.h
Expand Up @@ -111,7 +111,7 @@ class QDeclarativeV4CompilerPrivate: protected QDeclarativeJS::IR::ExprVisitor,

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;
Expand All @@ -137,6 +137,7 @@ class QDeclarativeV4CompilerPrivate: protected QDeclarativeJS::IR::ExprVisitor,
: block(block), offset(index) {}
};
QVector<Patch> patches;
QDeclarativeJS::MemoryPool pool;

// Committed binding data
struct {
Expand Down

0 comments on commit ef9751e

Please sign in to comment.