src/BytecodeEmitter.cpp
author David Anderson <dvander@alliedmods.net>
Sun Sep 02 13:06:09 2012 -0700 (2012-09-02)
changeset 177 56f7e5b0243c
parent 92 e3974e7360e9
permissions -rw-r--r--
Fix bug in bytecode resizing.
     1 /* vim: set ts=4 sw=4 tw=99 et:
     2  *
     3  * Copyright (C) 2012 David Anderson
     4  *
     5  * This file is part of JITCraft.
     6  *
     7  * JITCraft is free software: you can redistribute it and/or modify it under
     8  * the terms of the GNU General Public License as published by the Free
     9  * Software Foundation, either version 3 of the License, or (at your option)
    10  * any later version.
    11  * 
    12  * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
    13  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    14  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    15  *
    16  * You should have received a copy of the GNU General Public License along with
    17  * JITCraft. If not, see http://www.gnu.org/licenses/.
    18  */
    19 #include <stdlib.h>
    20 #include <string.h>
    21 #include "BytecodeEmitter.h"
    22 #include "Utility.h"
    23 #include "Types.h"
    24 #include "Zone.h"
    25 #include "Spaces-inl.h"
    26 #include "Heap-inl.h"
    27 
    28 using namespace ke;
    29 
    30 BytecodeEmitter::BytecodeEmitter(PoolAllocator &pool)
    31   : pool_(pool),
    32     buffer_(inline_buffer_),
    33     buffer_pos_(buffer_),
    34     buffer_end_(buffer_pos_ + ARRAY_LENGTH(inline_buffer_)),
    35     oom_(false),
    36     maxStackDepth_(0)
    37 {
    38     lastCodePosition_ = 0;
    39     firstLine_ = 1;
    40 }
    41 
    42 bool
    43 BytecodeEmitter::growBuffer(size_t nbytes)
    44 {
    45     if (oom_) {
    46         buffer_pos_ = buffer_;
    47         return false;
    48     }
    49 
    50     size_t newSize = size_t((buffer_end_ - buffer_) * 2);
    51     if (newSize >= MAX_LENGTH) {
    52         oom_ = true;
    53         buffer_pos_ = buffer_;
    54         ZONE()->reportOutOfMemory();
    55         return false;
    56     }
    57 
    58     bytecode *newBuffer;
    59     if (buffer_ == inline_buffer_)
    60         newBuffer = (bytecode *)malloc(newSize);
    61     else
    62         newBuffer = (bytecode *)realloc(buffer_, newSize);
    63 
    64     // If we can't allocate a buffer, reset the buffer to the start and set
    65     // a flag to indicate out-of-memory.
    66     if (!newBuffer) {
    67         oom_ = true;
    68         buffer_pos_ = buffer_;
    69         ZONE()->reportOutOfMemory();
    70         return false;
    71     }
    72 
    73     if (buffer_ == inline_buffer_)
    74         memcpy(newBuffer, inline_buffer_, (buffer_pos_ - inline_buffer_));
    75 
    76     buffer_pos_ = newBuffer + size_t(buffer_pos_ - buffer_);
    77     buffer_ = newBuffer;
    78     buffer_end_ = buffer_ + newSize;
    79     assert(buffer_pos_ + nbytes < buffer_end_);
    80 
    81     return true;
    82 }
    83 
    84 void
    85 BytecodeEmitter::recordOops()
    86 {
    87     OopRecord *record = new (pool_) OopRecord(oopMap_.length(), position());
    88 
    89     record->slots = (bool *)pool_.allocate(record->depth);
    90     if (!record->slots) {
    91         oom_ = true;
    92         return;
    93     }
    94 
    95     bool hadOops = false;
    96     for (size_t i = 0; i < oopMap_.length(); i++) {
    97         bool bit = oopMap_[i];
    98         record->slots[i] = bit;
    99         hadOops |= bit;
   100     }
   101 
   102     if (!hadOops)
   103         return;
   104 
   105     oom_ &= oopRecords_.append(record);
   106 }
   107 
   108 void
   109 BytecodeEmitter::note_position(const SourcePosition &pos)
   110 {
   111     assert(pos.line > 0);
   112     assert(unsigned(pos.line) >= firstLine_);
   113 
   114     unsigned lineDelta = unsigned(pos.line) - firstLine_;
   115     unsigned pcDelta = unsigned(position()) - lastCodePosition_;
   116 
   117     sourcemap_.writeUint32(pcDelta);
   118     sourcemap_.writeUint32(lineDelta);
   119     sourcemap_.writeUint32(pos.col);
   120 
   121     lastCodePosition_ = unsigned(position());
   122 }