dvander@47: /* vim: set ts=4 sw=4 tw=99 et: dvander@47: * 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@69: #include "Zone.h" danderson@92: #include "Spaces-inl.h" danderson@92: #include "Heap-inl.h" dvander@0: dvander@59: using namespace ke; dvander@0: dvander@47: BytecodeEmitter::BytecodeEmitter(PoolAllocator &pool) dvander@47: : pool_(pool), dvander@47: buffer_(inline_buffer_), dvander@0: buffer_pos_(buffer_), dvander@0: buffer_end_(buffer_pos_ + ARRAY_LENGTH(inline_buffer_)), dvander@0: oom_(false), dvander@47: maxStackDepth_(0) dvander@0: { dvander@70: lastCodePosition_ = 0; dvander@70: firstLine_ = 1; 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@69: ZONE()->reportOutOfMemory(); 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@69: ZONE()->reportOutOfMemory(); 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@47: void dvander@47: BytecodeEmitter::recordOops() dvander@47: { dvander@58: OopRecord *record = new (pool_) OopRecord(oopMap_.length(), position()); dvander@47: dvander@47: record->slots = (bool *)pool_.allocate(record->depth); dvander@47: if (!record->slots) { dvander@47: oom_ = true; dvander@47: return; dvander@47: } dvander@47: dvander@47: bool hadOops = false; dvander@58: for (size_t i = 0; i < oopMap_.length(); i++) { dvander@47: bool bit = oopMap_[i]; dvander@47: record->slots[i] = bit; dvander@47: hadOops |= bit; dvander@47: } dvander@47: dvander@47: if (!hadOops) dvander@47: return; dvander@47: dvander@58: oom_ &= oopRecords_.append(record); dvander@47: } dvander@47: dvander@70: void dvander@70: BytecodeEmitter::note_position(const SourcePosition &pos) dvander@70: { dvander@70: assert(pos.line > 0); dvander@70: assert(unsigned(pos.line) >= firstLine_); dvander@70: dvander@70: unsigned lineDelta = unsigned(pos.line) - firstLine_; dvander@70: unsigned pcDelta = unsigned(position()) - lastCodePosition_; dvander@70: dvander@70: sourcemap_.writeUint32(pcDelta); dvander@70: sourcemap_.writeUint32(lineDelta); dvander@70: sourcemap_.writeUint32(pos.col); dvander@70: dvander@70: lastCodePosition_ = unsigned(position()); dvander@70: }