dvander@0: /* dvander@0: * Copyright (C) 2012 David Anderson dvander@0: * dvander@0: * This file is part of JITCraft. dvander@0: * dvander@0: * JITCraft is free software: you can redistribute it and/or modify it under dvander@0: * the terms of the GNU General Public License as published by the Free dvander@0: * Software Foundation, either version 3 of the License, or (at your option) dvander@0: * any later version. dvander@0: * dvander@0: * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY dvander@0: * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS dvander@0: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. dvander@0: * dvander@0: * You should have received a copy of the GNU General Public License along with dvander@0: * JITCraft. If not, see http://www.gnu.org/licenses/. dvander@0: */ dvander@0: #include dvander@0: #include "BytecodeEmitter.h" dvander@0: #include "Utility.h" dvander@0: #include "Types.h" dvander@0: dvander@0: using namespace jc; dvander@0: dvander@0: BytecodeEmitter::BytecodeEmitter() dvander@0: : buffer_(inline_buffer_), dvander@0: buffer_pos_(buffer_), dvander@0: buffer_end_(buffer_pos_ + ARRAY_LENGTH(inline_buffer_)), dvander@0: oom_(false), dvander@0: stackDepth_(0), dvander@0: maxStackDepth_(0) dvander@0: { dvander@0: } dvander@0: dvander@0: bool dvander@0: BytecodeEmitter::growBuffer(size_t nbytes) dvander@0: { dvander@0: if (oom_) { dvander@0: buffer_pos_ = buffer_; dvander@0: return false; dvander@0: } dvander@0: dvander@0: size_t newSize = size_t((buffer_end_ - buffer_) * 2); dvander@0: if (newSize >= MAX_LENGTH) { dvander@0: oom_ = true; dvander@0: buffer_pos_ = buffer_; dvander@0: return false; dvander@0: } dvander@0: dvander@0: bytecode *newBuffer; dvander@0: if (buffer_ == inline_buffer_) dvander@0: newBuffer = (bytecode *)malloc(nbytes); dvander@0: else dvander@0: newBuffer = (bytecode *)realloc(buffer_, newSize); dvander@0: dvander@0: // If we can't allocate a buffer, reset the buffer to the start and set dvander@0: // a flag to indicate out-of-memory. dvander@0: if (!newBuffer) { dvander@0: oom_ = true; dvander@0: buffer_pos_ = buffer_; dvander@0: return false; dvander@0: } dvander@0: dvander@0: buffer_pos_ = newBuffer + size_t(buffer_pos_ - buffer_); dvander@0: buffer_ = newBuffer; dvander@0: buffer_end_ = buffer_ + newSize; dvander@0: return true; dvander@0: } dvander@0: dvander@0: void dvander@0: BytecodeEmitter::stackarray(Type *type) dvander@0: { dvander@7: assert(type->innermost()->primitive() == PrimitiveType_Int32 || dvander@7: type->innermost()->primitive() == PrimitiveType_Float); dvander@0: dvander@0: ensure((sizeof(Opcode) * 3) + sizeof(unsigned) * Type::MAX_UNSAFE_ARRAY_DEPTH); dvander@0: writeOp(OP_STACKARRAY); dvander@0: writeUint8(sizeof(unsigned)); dvander@0: writeUint8(type->levels()); dvander@0: dvander@0: for (; type->isArray(); type = type->contained()) dvander@0: writeUint32(type->elements()); dvander@0: }