src/BytecodeEmitter.cpp
author David Anderson <dvander@alliedmods.net>
Sat Aug 04 19:33:06 2012 -0700 (2012-08-04)
changeset 147 9c544823d090
parent 92 e3974e7360e9
child 177 56f7e5b0243c
permissions -rw-r--r--
Structure declaration support.
     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 "BytecodeEmitter.h"
    21 #include "Utility.h"
    22 #include "Types.h"
    23 #include "Zone.h"
    24 #include "Spaces-inl.h"
    25 #include "Heap-inl.h"
    26 
    27 using namespace ke;
    28 
    29 BytecodeEmitter::BytecodeEmitter(PoolAllocator &pool)
    30   : pool_(pool),
    31     buffer_(inline_buffer_),
    32     buffer_pos_(buffer_),
    33     buffer_end_(buffer_pos_ + ARRAY_LENGTH(inline_buffer_)),
    34     oom_(false),
    35     maxStackDepth_(0)
    36 {
    37     lastCodePosition_ = 0;
    38     firstLine_ = 1;
    39 }
    40 
    41 bool
    42 BytecodeEmitter::growBuffer(size_t nbytes)
    43 {
    44     if (oom_) {
    45         buffer_pos_ = buffer_;
    46         return false;
    47     }
    48 
    49     size_t newSize = size_t((buffer_end_ - buffer_) * 2);
    50     if (newSize >= MAX_LENGTH) {
    51         oom_ = true;
    52         buffer_pos_ = buffer_;
    53         ZONE()->reportOutOfMemory();
    54         return false;
    55     }
    56 
    57     bytecode *newBuffer;
    58     if (buffer_ == inline_buffer_)
    59         newBuffer = (bytecode *)malloc(nbytes);
    60     else
    61         newBuffer = (bytecode *)realloc(buffer_, newSize);
    62 
    63     // If we can't allocate a buffer, reset the buffer to the start and set
    64     // a flag to indicate out-of-memory.
    65     if (!newBuffer) {
    66         oom_ = true;
    67         buffer_pos_ = buffer_;
    68         ZONE()->reportOutOfMemory();
    69         return false;
    70     }
    71 
    72     buffer_pos_ = newBuffer + size_t(buffer_pos_ - buffer_);
    73     buffer_ = newBuffer;
    74     buffer_end_ = buffer_ + newSize;
    75     return true;
    76 }
    77 
    78 void
    79 BytecodeEmitter::recordOops()
    80 {
    81     OopRecord *record = new (pool_) OopRecord(oopMap_.length(), position());
    82 
    83     record->slots = (bool *)pool_.allocate(record->depth);
    84     if (!record->slots) {
    85         oom_ = true;
    86         return;
    87     }
    88 
    89     bool hadOops = false;
    90     for (size_t i = 0; i < oopMap_.length(); i++) {
    91         bool bit = oopMap_[i];
    92         record->slots[i] = bit;
    93         hadOops |= bit;
    94     }
    95 
    96     if (!hadOops)
    97         return;
    98 
    99     oom_ &= oopRecords_.append(record);
   100 }
   101 
   102 void
   103 BytecodeEmitter::note_position(const SourcePosition &pos)
   104 {
   105     assert(pos.line > 0);
   106     assert(unsigned(pos.line) >= firstLine_);
   107 
   108     unsigned lineDelta = unsigned(pos.line) - firstLine_;
   109     unsigned pcDelta = unsigned(position()) - lastCodePosition_;
   110 
   111     sourcemap_.writeUint32(pcDelta);
   112     sourcemap_.writeUint32(lineDelta);
   113     sourcemap_.writeUint32(pos.col);
   114 
   115     lastCodePosition_ = unsigned(position());
   116 }