src/compiler/BytecodeEmitter.cpp
changeset 263 ba85a47ee414
parent 262 c4b1341297e5
     1.1 --- a/src/compiler/BytecodeEmitter.cpp	Mon Jun 10 00:46:29 2013 +0100
     1.2 +++ b/src/compiler/BytecodeEmitter.cpp	Mon Jun 10 01:04:43 2013 +0100
     1.3 @@ -1,386 +1,386 @@
     1.4 -/* vim: set ts=4 sw=4 tw=99 et:
     1.5 - *
     1.6 - * Copyright (C) 2012 David Anderson
     1.7 - *
     1.8 - * This file is part of JITCraft.
     1.9 - *
    1.10 - * JITCraft is free software: you can redistribute it and/or modify it under
    1.11 - * the terms of the GNU General Public License as published by the Free
    1.12 - * Software Foundation, either version 3 of the License, or (at your option)
    1.13 - * any later version.
    1.14 - * 
    1.15 - * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
    1.16 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    1.17 - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    1.18 - *
    1.19 - * You should have received a copy of the GNU General Public License along with
    1.20 - * JITCraft. If not, see http://www.gnu.org/licenses/.
    1.21 - */
    1.22 -#include <stdlib.h>
    1.23 -#include <string.h>
    1.24 -#include "../Utility.h"
    1.25 -#include "../Types.h"
    1.26 -#include "../Zone.h"
    1.27 -#include "../Strings.h"
    1.28 -#include "../Zone.h"
    1.29 -#include "BytecodeEmitter.h"
    1.30 -#include "Symbols.h"
    1.31 -#include "Scopes.h"
    1.32 -#include "../Spaces-inl.h"
    1.33 -#include "../Heap-inl.h"
    1.34 -
    1.35 -using namespace ke;
    1.36 -
    1.37 -StringTable::StringTable()
    1.38 -  : set_(ZoneAllocatorPolicy()),
    1.39 -    initialized_(false)
    1.40 -{
    1.41 -}
    1.42 -
    1.43 -bool
    1.44 -StringTable::initialize()
    1.45 -{
    1.46 -    assert(!initialized_);
    1.47 -    initialized_ = true;
    1.48 -    if (!set_.init(16))
    1.49 -        return false;
    1.50 -    return true;
    1.51 -}
    1.52 -
    1.53 -bool
    1.54 -StringTable::add(Handle<String> name, unsigned *indexp)
    1.55 -{
    1.56 -    if (!initialized_ && !initialize())
    1.57 -        return false;
    1.58 -
    1.59 -    Set::Insert p = set_.findForAdd(*name);
    1.60 -    if (p.found()) {
    1.61 -        *indexp = p->index;
    1.62 -        return true;
    1.63 -    }
    1.64 -
    1.65 -    if (strings_.length() > INT_MAX) {
    1.66 -        ZONE()->reportAllocationOverflow();
    1.67 -        return false;
    1.68 -    }
    1.69 -
    1.70 -    Entry e(name, strings_.length());
    1.71 -    if (!strings_.append(e))
    1.72 -        return false;
    1.73 -
    1.74 -    if (!set_.add(p, e))
    1.75 -        return false;
    1.76 -
    1.77 -    *indexp = e.index;
    1.78 -
    1.79 -    return true;
    1.80 -}
    1.81 -
    1.82 -void
    1.83 -StringTable::accept(VirtualObjectVisitor *visitor)
    1.84 -{
    1.85 -    for (size_t i = 0; i < strings_.length(); i++)
    1.86 -        visitor->visit(reinterpret_cast<Object **>(&strings_[i].string));
    1.87 -}
    1.88 -
    1.89 -BytecodeEmitter::BytecodeEmitter()
    1.90 -  : AutoRooted(ZONE()),
    1.91 -    buffer_(inline_buffer_),
    1.92 -    buffer_pos_(buffer_),
    1.93 -    buffer_end_(buffer_pos_ + ARRAY_LENGTH(inline_buffer_)),
    1.94 -    oom_(false),
    1.95 -    maxStackDepth_(0),
    1.96 -    loopDepth_(0),
    1.97 -    maxLoopDepth_(0)
    1.98 -{
    1.99 -    lastCodePosition_ = 0;
   1.100 -    firstLine_ = 1;
   1.101 -}
   1.102 -
   1.103 -BytecodeEmitter::~BytecodeEmitter()
   1.104 -{
   1.105 -    for (size_t i = 0; i < oopRecords_.length(); i++)
   1.106 -        delete oopRecords_[i];
   1.107 -}
   1.108 -
   1.109 -void
   1.110 -BytecodeEmitter::accept(VirtualObjectVisitor *visitor)
   1.111 -{
   1.112 -    for (size_t i = 0; i < objects_.length(); i++)
   1.113 -        visitor->visit(&objects_[i]);
   1.114 -
   1.115 -    strings_.accept(visitor);
   1.116 -}
   1.117 -
   1.118 -bool
   1.119 -BytecodeEmitter::growBuffer(size_t nbytes)
   1.120 -{
   1.121 -    if (oom_) {
   1.122 -        buffer_pos_ = buffer_;
   1.123 -        return false;
   1.124 -    }
   1.125 -
   1.126 -    size_t newSize = size_t((buffer_end_ - buffer_) * 2);
   1.127 -    if (newSize >= MAX_LENGTH) {
   1.128 -        oom_ = true;
   1.129 -        buffer_pos_ = buffer_;
   1.130 -        ZONE()->reportOutOfMemory();
   1.131 -        return false;
   1.132 -    }
   1.133 -
   1.134 -    bytecode *newBuffer;
   1.135 -    if (buffer_ == inline_buffer_)
   1.136 -        newBuffer = (bytecode *)malloc(newSize);
   1.137 -    else
   1.138 -        newBuffer = (bytecode *)realloc(buffer_, newSize);
   1.139 -
   1.140 -    // If we can't allocate a buffer, reset the buffer to the start and set
   1.141 -    // a flag to indicate out-of-memory.
   1.142 -    if (!newBuffer) {
   1.143 -        oom_ = true;
   1.144 -        buffer_pos_ = buffer_;
   1.145 -        ZONE()->reportOutOfMemory();
   1.146 -        return false;
   1.147 -    }
   1.148 -
   1.149 -    if (buffer_ == inline_buffer_)
   1.150 -        memcpy(newBuffer, inline_buffer_, (buffer_pos_ - inline_buffer_));
   1.151 -
   1.152 -    buffer_pos_ = newBuffer + size_t(buffer_pos_ - buffer_);
   1.153 -    buffer_ = newBuffer;
   1.154 -    buffer_end_ = buffer_ + newSize;
   1.155 -    assert(buffer_pos_ + nbytes < buffer_end_);
   1.156 -
   1.157 -    return true;
   1.158 -}
   1.159 -
   1.160 -void
   1.161 -BytecodeEmitter::recordOops()
   1.162 -{
   1.163 -    OopRecord *record = new OopRecord(oopMap_.length(), position());
   1.164 -
   1.165 -    if (!record->slots.ensure(record->depth)) {
   1.166 -        oom_ = true;
   1.167 -        return;
   1.168 -    }
   1.169 -
   1.170 -    bool hadOops = false;
   1.171 -    for (size_t i = 0; i < oopMap_.length(); i++) {
   1.172 -        bool bit = oopMap_[i];
   1.173 -        record->slots.infallibleAppend(bit);
   1.174 -        hadOops |= bit;
   1.175 -    }
   1.176 -
   1.177 -    if (!hadOops) {
   1.178 -        delete record;
   1.179 -        return;
   1.180 -    }
   1.181 -
   1.182 -    oom_ &= oopRecords_.append(record);
   1.183 -}
   1.184 -
   1.185 -void
   1.186 -BytecodeEmitter::note_position(const SourcePosition &pos)
   1.187 -{
   1.188 -    assert(pos.line > 0);
   1.189 -    assert(unsigned(pos.line) >= firstLine_);
   1.190 -
   1.191 -    unsigned lineDelta = unsigned(pos.line) - firstLine_;
   1.192 -    unsigned pcDelta = unsigned(position()) - lastCodePosition_;
   1.193 -
   1.194 -    sourcemap_.writeUint32(pcDelta);
   1.195 -    sourcemap_.writeUint32(lineDelta);
   1.196 -    sourcemap_.writeUint32(pos.col);
   1.197 -
   1.198 -    lastCodePosition_ = unsigned(position());
   1.199 -}
   1.200 -
   1.201 -void
   1.202 -BytecodeEmitter::getglobal(Symbol *sym)
   1.203 -{
   1.204 -    ensure(OP_GETGLOBAL_LENGTH);
   1.205 -    writeOp(OP_GETGLOBAL);
   1.206 -    writeUint32(addString(sym->name()));
   1.207 -    if (sym->type()->isTraceable())
   1.208 -        markOop(1);
   1.209 -}
   1.210 -void
   1.211 -BytecodeEmitter::setglobal(Symbol *sym)
   1.212 -{
   1.213 -    ensure(OP_SETGLOBAL_LENGTH);
   1.214 -    writeOp(OP_SETGLOBAL);
   1.215 -    writeUint32(addString(sym->name()));
   1.216 -    if (sym->type()->isTraceable())
   1.217 -        markOop(1);
   1.218 -}
   1.219 -
   1.220 -void
   1.221 -BytecodeEmitter::getlocal(VariableSymbol *var)
   1.222 -{
   1.223 -    assert(var->storage() == VariableSymbol::Local);
   1.224 -    ensure(OP_GETLOCAL_LENGTH);
   1.225 -    writeOp(OP_GETLOCAL);
   1.226 -    writeUint32(var->slot());
   1.227 -    if (var->type()->isTraceable())
   1.228 -        markOop(1);
   1.229 -}
   1.230 -
   1.231 -void
   1.232 -BytecodeEmitter::setlocal(VariableSymbol *var)
   1.233 -{
   1.234 -    assert(var->storage() == VariableSymbol::Local);
   1.235 -    ensure(OP_SETLOCAL_LENGTH);
   1.236 -    writeOp(OP_SETLOCAL);
   1.237 -    writeUint32(var->slot());
   1.238 -    if (var->type()->isTraceable())
   1.239 -        markOop(1);
   1.240 -}
   1.241 -
   1.242 -void
   1.243 -BytecodeEmitter::getarg(VariableSymbol *var)
   1.244 -{
   1.245 -    assert(var->storage() == VariableSymbol::Arg);
   1.246 -    ensure(OP_GETARG_LENGTH);
   1.247 -    writeOp(OP_GETARG);
   1.248 -    writeUint32(var->slot());
   1.249 -    if (var->type()->isTraceable())
   1.250 -        markOop(1);
   1.251 -}
   1.252 -
   1.253 -void
   1.254 -BytecodeEmitter::setarg(VariableSymbol *var)
   1.255 -{
   1.256 -    assert(var->storage() == VariableSymbol::Arg);
   1.257 -    ensure(OP_SETARG_LENGTH);
   1.258 -    writeOp(OP_SETARG);
   1.259 -    writeUint32(var->slot());
   1.260 -    if (var->type()->isTraceable())
   1.261 -        markOop(1);
   1.262 -}
   1.263 -
   1.264 -bool
   1.265 -BytecodeEmitter::allocate(VariableSymbol *sym)
   1.266 -{
   1.267 -    assert(sym->isVariable());
   1.268 -    assert(sym->scope()->kind() == Scope::BLOCK);
   1.269 -
   1.270 -    switch (sym->scope()->kind()) {
   1.271 -      case Scope::BLOCK:
   1.272 -      {
   1.273 -        // See overall comment on overflows.
   1.274 -        assert(locals_.length() < UINT_MAX);
   1.275 -        sym->allocate(VariableSymbol::Local, locals_.length());
   1.276 -        if (!locals_.append(sym))
   1.277 -            return false;
   1.278 -        break;
   1.279 -      }
   1.280 -
   1.281 -      default:
   1.282 -        assert(false);
   1.283 -        return false;
   1.284 -    }
   1.285 -
   1.286 -    return true;
   1.287 -}
   1.288 -
   1.289 -void
   1.290 -BytecodeEmitter::newref(VariableSymbol *var)
   1.291 -{
   1.292 -    recordOops();
   1.293 -    if (var->storage() == VariableSymbol::Local) {
   1.294 -        ensure(OP_VARREF_LIFO_LENGTH);
   1.295 -        writeOp(OP_VARREF_LIFO);
   1.296 -    } else {
   1.297 -        assert(var->storage() == VariableSymbol::Arg);
   1.298 -        ensure(OP_ARGREF_LIFO_LENGTH);
   1.299 -        writeOp(OP_ARGREF_LIFO);
   1.300 -    }
   1.301 -    writeUint32(var->slot());
   1.302 -    markOop(1);
   1.303 -}
   1.304 -
   1.305 -Code *
   1.306 -BytecodeEmitter::finish()
   1.307 -{
   1.308 -    stop();
   1.309 -
   1.310 -    Zone *zone = ZONE();
   1.311 -    if (oom() || zone->hasPendingException())
   1.312 -        return NULL;
   1.313 -
   1.314 -    Local<ByteArray> bytes(zone, ByteArray::New(zone, length(), Heap::Tenure_Old));
   1.315 -    if (!bytes)
   1.316 -        return NULL;
   1.317 -    memcpy(bytes->raw(), buffer(), length());
   1.318 -
   1.319 -    Local<FixedArray> objects(zone, FixedArray::New(zone, objects_.length(), Heap::Tenure_Old));
   1.320 -    if (!objects)
   1.321 -        return NULL;
   1.322 -
   1.323 -    for (size_t i = 0; i < objects_.length(); i++)
   1.324 -        objects->set(zone, i, objects_[i]);
   1.325 -
   1.326 -    // If any stack slots hold gc pointers at potential failure points in the
   1.327 -    // bytecode, record them now. We do this by building a list of tuples;
   1.328 -    // each tuple contains the pc offset, and a bitset containing which stack
   1.329 -    // slots must be scanned by the gc.
   1.330 -    Local<ByteArray> safepoints(zone);
   1.331 -    if (oopRecords_.length()) {
   1.332 -        size_t bytesPerSafepoint = Code::BytesPerSafepoint(maxStackDepth());
   1.333 -        size_t gcmapSize = bytesPerSafepoint * oopRecords_.length();
   1.334 -        safepoints = ByteArray::New(zone, gcmapSize, Heap::Tenure_Old);
   1.335 -        if (!safepoints)
   1.336 -            return NULL;
   1.337 -
   1.338 -        Address cursor = safepoints->raw();
   1.339 -        for (size_t i = 0; i < oopRecords_.length(); i++) {
   1.340 -            OopRecord *record = oopRecords_[i];
   1.341 -            assert(record->depth <= maxStackDepth());
   1.342 -
   1.343 -            *reinterpret_cast<unsigned *>(cursor) = record->offset;
   1.344 -
   1.345 -            unsigned char *bits = reinterpret_cast<unsigned char *>(cursor + sizeof(unsigned));
   1.346 -            for (unsigned i = 0; i < record->depth; i++)
   1.347 -                bits[i / 8] |= (1 << (i % 8));
   1.348 -
   1.349 -            cursor += bytesPerSafepoint;
   1.350 -        }
   1.351 -
   1.352 -        assert(cursor == safepoints->raw() + gcmapSize);
   1.353 -    }
   1.354 -
   1.355 -    Local<ByteArray> sourcemap(zone);
   1.356 -    if (sourcemap_.length()) {
   1.357 -        sourcemap = ByteArray::New(zone, sourcemap_.length(), Heap::Tenure_Old);
   1.358 -        if (!sourcemap)
   1.359 -            return NULL;
   1.360 -
   1.361 -        memcpy(sourcemap->raw(), sourcemap_.buffer(), sourcemap_.length());
   1.362 -    }
   1.363 -
   1.364 -    Local<FixedArray> strings(zone, FixedArray::New(zone, strings_.stringCount(), Heap::Tenure_Old));
   1.365 -    if (!strings)
   1.366 -        return NULL;
   1.367 -    for (size_t i = 0; i < strings_.stringCount(); i++)
   1.368 -        strings->set(zone, i, strings_.stringAt(i));
   1.369 -
   1.370 -    Local<FixedArray> locals(zone, FixedArray::New(zone, locals_.length(), Heap::Tenure_Old));
   1.371 -    if (!locals)
   1.372 -        return NULL;
   1.373 -    for (size_t i = 0; i < locals_.length(); i++)
   1.374 -        locals->set(zone, i, locals_[i]->type());
   1.375 -
   1.376 -    Local<Code> code(zone);
   1.377 -
   1.378 -    code = Code::New(zone,
   1.379 -                     bytes,
   1.380 -                     locals,
   1.381 -                     objects,
   1.382 -                     strings,
   1.383 -                     maxStackDepth(),
   1.384 -                     maxLoopDepth_,
   1.385 -                     safepoints,
   1.386 -                     sourcemap);
   1.387 -
   1.388 -    return code;
   1.389 -}
   1.390 +/* vim: set ts=4 sw=4 tw=99 et:
   1.391 + *
   1.392 + * Copyright (C) 2012 David Anderson
   1.393 + *
   1.394 + * This file is part of JITCraft.
   1.395 + *
   1.396 + * JITCraft is free software: you can redistribute it and/or modify it under
   1.397 + * the terms of the GNU General Public License as published by the Free
   1.398 + * Software Foundation, either version 3 of the License, or (at your option)
   1.399 + * any later version.
   1.400 + * 
   1.401 + * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
   1.402 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   1.403 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
   1.404 + *
   1.405 + * You should have received a copy of the GNU General Public License along with
   1.406 + * JITCraft. If not, see http://www.gnu.org/licenses/.
   1.407 + */
   1.408 +#include <stdlib.h>
   1.409 +#include <string.h>
   1.410 +#include "../Utility.h"
   1.411 +#include "../Types.h"
   1.412 +#include "../Zone.h"
   1.413 +#include "../Strings.h"
   1.414 +#include "../Zone.h"
   1.415 +#include "BytecodeEmitter.h"
   1.416 +#include "Symbols.h"
   1.417 +#include "Scopes.h"
   1.418 +#include "../Spaces-inl.h"
   1.419 +#include "../Heap-inl.h"
   1.420 +
   1.421 +using namespace ke;
   1.422 +
   1.423 +StringTable::StringTable()
   1.424 +  : set_(ZoneAllocatorPolicy()),
   1.425 +    initialized_(false)
   1.426 +{
   1.427 +}
   1.428 +
   1.429 +bool
   1.430 +StringTable::initialize()
   1.431 +{
   1.432 +    assert(!initialized_);
   1.433 +    initialized_ = true;
   1.434 +    if (!set_.init(16))
   1.435 +        return false;
   1.436 +    return true;
   1.437 +}
   1.438 +
   1.439 +bool
   1.440 +StringTable::add(Handle<String> name, unsigned *indexp)
   1.441 +{
   1.442 +    if (!initialized_ && !initialize())
   1.443 +        return false;
   1.444 +
   1.445 +    Set::Insert p = set_.findForAdd(*name);
   1.446 +    if (p.found()) {
   1.447 +        *indexp = p->index;
   1.448 +        return true;
   1.449 +    }
   1.450 +
   1.451 +    if (strings_.length() > INT_MAX) {
   1.452 +        ZONE()->reportAllocationOverflow();
   1.453 +        return false;
   1.454 +    }
   1.455 +
   1.456 +    Entry e(name, strings_.length());
   1.457 +    if (!strings_.append(e))
   1.458 +        return false;
   1.459 +
   1.460 +    if (!set_.add(p, e))
   1.461 +        return false;
   1.462 +
   1.463 +    *indexp = e.index;
   1.464 +
   1.465 +    return true;
   1.466 +}
   1.467 +
   1.468 +void
   1.469 +StringTable::accept(VirtualObjectVisitor *visitor)
   1.470 +{
   1.471 +    for (size_t i = 0; i < strings_.length(); i++)
   1.472 +        visitor->visit(reinterpret_cast<Object **>(&strings_[i].string));
   1.473 +}
   1.474 +
   1.475 +BytecodeEmitter::BytecodeEmitter()
   1.476 +  : AutoRooted(ZONE()),
   1.477 +    buffer_(inline_buffer_),
   1.478 +    buffer_pos_(buffer_),
   1.479 +    buffer_end_(buffer_pos_ + ARRAY_LENGTH(inline_buffer_)),
   1.480 +    oom_(false),
   1.481 +    maxStackDepth_(0),
   1.482 +    loopDepth_(0),
   1.483 +    maxLoopDepth_(0)
   1.484 +{
   1.485 +    lastCodePosition_ = 0;
   1.486 +    firstLine_ = 1;
   1.487 +}
   1.488 +
   1.489 +BytecodeEmitter::~BytecodeEmitter()
   1.490 +{
   1.491 +    for (size_t i = 0; i < oopRecords_.length(); i++)
   1.492 +        delete oopRecords_[i];
   1.493 +}
   1.494 +
   1.495 +void
   1.496 +BytecodeEmitter::accept(VirtualObjectVisitor *visitor)
   1.497 +{
   1.498 +    for (size_t i = 0; i < objects_.length(); i++)
   1.499 +        visitor->visit(&objects_[i]);
   1.500 +
   1.501 +    strings_.accept(visitor);
   1.502 +}
   1.503 +
   1.504 +bool
   1.505 +BytecodeEmitter::growBuffer(size_t nbytes)
   1.506 +{
   1.507 +    if (oom_) {
   1.508 +        buffer_pos_ = buffer_;
   1.509 +        return false;
   1.510 +    }
   1.511 +
   1.512 +    size_t newSize = size_t((buffer_end_ - buffer_) * 2);
   1.513 +    if (newSize >= MAX_LENGTH) {
   1.514 +        oom_ = true;
   1.515 +        buffer_pos_ = buffer_;
   1.516 +        ZONE()->reportOutOfMemory();
   1.517 +        return false;
   1.518 +    }
   1.519 +
   1.520 +    bytecode *newBuffer;
   1.521 +    if (buffer_ == inline_buffer_)
   1.522 +        newBuffer = (bytecode *)malloc(newSize);
   1.523 +    else
   1.524 +        newBuffer = (bytecode *)realloc(buffer_, newSize);
   1.525 +
   1.526 +    // If we can't allocate a buffer, reset the buffer to the start and set
   1.527 +    // a flag to indicate out-of-memory.
   1.528 +    if (!newBuffer) {
   1.529 +        oom_ = true;
   1.530 +        buffer_pos_ = buffer_;
   1.531 +        ZONE()->reportOutOfMemory();
   1.532 +        return false;
   1.533 +    }
   1.534 +
   1.535 +    if (buffer_ == inline_buffer_)
   1.536 +        memcpy(newBuffer, inline_buffer_, (buffer_pos_ - inline_buffer_));
   1.537 +
   1.538 +    buffer_pos_ = newBuffer + size_t(buffer_pos_ - buffer_);
   1.539 +    buffer_ = newBuffer;
   1.540 +    buffer_end_ = buffer_ + newSize;
   1.541 +    assert(buffer_pos_ + nbytes < buffer_end_);
   1.542 +
   1.543 +    return true;
   1.544 +}
   1.545 +
   1.546 +void
   1.547 +BytecodeEmitter::recordOops()
   1.548 +{
   1.549 +    OopRecord *record = new OopRecord(oopMap_.length(), position());
   1.550 +
   1.551 +    if (!record->slots.ensure(record->depth)) {
   1.552 +        oom_ = true;
   1.553 +        return;
   1.554 +    }
   1.555 +
   1.556 +    bool hadOops = false;
   1.557 +    for (size_t i = 0; i < oopMap_.length(); i++) {
   1.558 +        bool bit = oopMap_[i];
   1.559 +        record->slots.infallibleAppend(bit);
   1.560 +        hadOops |= bit;
   1.561 +    }
   1.562 +
   1.563 +    if (!hadOops) {
   1.564 +        delete record;
   1.565 +        return;
   1.566 +    }
   1.567 +
   1.568 +    oom_ &= oopRecords_.append(record);
   1.569 +}
   1.570 +
   1.571 +void
   1.572 +BytecodeEmitter::note_position(const SourcePosition &pos)
   1.573 +{
   1.574 +    assert(pos.line > 0);
   1.575 +    assert(unsigned(pos.line) >= firstLine_);
   1.576 +
   1.577 +    unsigned lineDelta = unsigned(pos.line) - firstLine_;
   1.578 +    unsigned pcDelta = unsigned(position()) - lastCodePosition_;
   1.579 +
   1.580 +    sourcemap_.writeUint32(pcDelta);
   1.581 +    sourcemap_.writeUint32(lineDelta);
   1.582 +    sourcemap_.writeUint32(pos.col);
   1.583 +
   1.584 +    lastCodePosition_ = unsigned(position());
   1.585 +}
   1.586 +
   1.587 +void
   1.588 +BytecodeEmitter::getglobal(Symbol *sym)
   1.589 +{
   1.590 +    ensure(OP_GETGLOBAL_LENGTH);
   1.591 +    writeOp(OP_GETGLOBAL);
   1.592 +    writeUint32(addString(sym->name()));
   1.593 +    if (sym->type()->isTraceable())
   1.594 +        markOop(1);
   1.595 +}
   1.596 +void
   1.597 +BytecodeEmitter::setglobal(Symbol *sym)
   1.598 +{
   1.599 +    ensure(OP_SETGLOBAL_LENGTH);
   1.600 +    writeOp(OP_SETGLOBAL);
   1.601 +    writeUint32(addString(sym->name()));
   1.602 +    if (sym->type()->isTraceable())
   1.603 +        markOop(1);
   1.604 +}
   1.605 +
   1.606 +void
   1.607 +BytecodeEmitter::getlocal(VariableSymbol *var)
   1.608 +{
   1.609 +    assert(var->storage() == VariableSymbol::Local);
   1.610 +    ensure(OP_GETLOCAL_LENGTH);
   1.611 +    writeOp(OP_GETLOCAL);
   1.612 +    writeUint32(var->slot());
   1.613 +    if (var->type()->isTraceable())
   1.614 +        markOop(1);
   1.615 +}
   1.616 +
   1.617 +void
   1.618 +BytecodeEmitter::setlocal(VariableSymbol *var)
   1.619 +{
   1.620 +    assert(var->storage() == VariableSymbol::Local);
   1.621 +    ensure(OP_SETLOCAL_LENGTH);
   1.622 +    writeOp(OP_SETLOCAL);
   1.623 +    writeUint32(var->slot());
   1.624 +    if (var->type()->isTraceable())
   1.625 +        markOop(1);
   1.626 +}
   1.627 +
   1.628 +void
   1.629 +BytecodeEmitter::getarg(VariableSymbol *var)
   1.630 +{
   1.631 +    assert(var->storage() == VariableSymbol::Arg);
   1.632 +    ensure(OP_GETARG_LENGTH);
   1.633 +    writeOp(OP_GETARG);
   1.634 +    writeUint32(var->slot());
   1.635 +    if (var->type()->isTraceable())
   1.636 +        markOop(1);
   1.637 +}
   1.638 +
   1.639 +void
   1.640 +BytecodeEmitter::setarg(VariableSymbol *var)
   1.641 +{
   1.642 +    assert(var->storage() == VariableSymbol::Arg);
   1.643 +    ensure(OP_SETARG_LENGTH);
   1.644 +    writeOp(OP_SETARG);
   1.645 +    writeUint32(var->slot());
   1.646 +    if (var->type()->isTraceable())
   1.647 +        markOop(1);
   1.648 +}
   1.649 +
   1.650 +bool
   1.651 +BytecodeEmitter::allocate(VariableSymbol *sym)
   1.652 +{
   1.653 +    assert(sym->isVariable());
   1.654 +    assert(sym->scope()->kind() == Scope::BLOCK);
   1.655 +
   1.656 +    switch (sym->scope()->kind()) {
   1.657 +      case Scope::BLOCK:
   1.658 +      {
   1.659 +        // See overall comment on overflows.
   1.660 +        assert(locals_.length() < UINT_MAX);
   1.661 +        sym->allocate(VariableSymbol::Local, locals_.length());
   1.662 +        if (!locals_.append(sym))
   1.663 +            return false;
   1.664 +        break;
   1.665 +      }
   1.666 +
   1.667 +      default:
   1.668 +        assert(false);
   1.669 +        return false;
   1.670 +    }
   1.671 +
   1.672 +    return true;
   1.673 +}
   1.674 +
   1.675 +void
   1.676 +BytecodeEmitter::newref(VariableSymbol *var)
   1.677 +{
   1.678 +    recordOops();
   1.679 +    if (var->storage() == VariableSymbol::Local) {
   1.680 +        ensure(OP_VARREF_LIFO_LENGTH);
   1.681 +        writeOp(OP_VARREF_LIFO);
   1.682 +    } else {
   1.683 +        assert(var->storage() == VariableSymbol::Arg);
   1.684 +        ensure(OP_ARGREF_LIFO_LENGTH);
   1.685 +        writeOp(OP_ARGREF_LIFO);
   1.686 +    }
   1.687 +    writeUint32(var->slot());
   1.688 +    markOop(1);
   1.689 +}
   1.690 +
   1.691 +Code *
   1.692 +BytecodeEmitter::finish()
   1.693 +{
   1.694 +    stop();
   1.695 +
   1.696 +    Zone *zone = ZONE();
   1.697 +    if (oom() || zone->hasPendingException())
   1.698 +        return NULL;
   1.699 +
   1.700 +    Local<ByteArray> bytes(zone, ByteArray::New(zone, length(), Heap::Tenure_Old));
   1.701 +    if (!bytes)
   1.702 +        return NULL;
   1.703 +    memcpy(bytes->raw(), buffer(), length());
   1.704 +
   1.705 +    Local<FixedArray> objects(zone, FixedArray::New(zone, objects_.length(), Heap::Tenure_Old));
   1.706 +    if (!objects)
   1.707 +        return NULL;
   1.708 +
   1.709 +    for (size_t i = 0; i < objects_.length(); i++)
   1.710 +        objects->set(zone, i, objects_[i]);
   1.711 +
   1.712 +    // If any stack slots hold gc pointers at potential failure points in the
   1.713 +    // bytecode, record them now. We do this by building a list of tuples;
   1.714 +    // each tuple contains the pc offset, and a bitset containing which stack
   1.715 +    // slots must be scanned by the gc.
   1.716 +    Local<ByteArray> safepoints(zone);
   1.717 +    if (oopRecords_.length()) {
   1.718 +        size_t bytesPerSafepoint = Code::BytesPerSafepoint(maxStackDepth());
   1.719 +        size_t gcmapSize = bytesPerSafepoint * oopRecords_.length();
   1.720 +        safepoints = ByteArray::New(zone, gcmapSize, Heap::Tenure_Old);
   1.721 +        if (!safepoints)
   1.722 +            return NULL;
   1.723 +
   1.724 +        Address cursor = safepoints->raw();
   1.725 +        for (size_t i = 0; i < oopRecords_.length(); i++) {
   1.726 +            OopRecord *record = oopRecords_[i];
   1.727 +            assert(record->depth <= maxStackDepth());
   1.728 +
   1.729 +            *reinterpret_cast<unsigned *>(cursor) = record->offset;
   1.730 +
   1.731 +            unsigned char *bits = reinterpret_cast<unsigned char *>(cursor + sizeof(unsigned));
   1.732 +            for (unsigned i = 0; i < record->depth; i++)
   1.733 +                bits[i / 8] |= (1 << (i % 8));
   1.734 +
   1.735 +            cursor += bytesPerSafepoint;
   1.736 +        }
   1.737 +
   1.738 +        assert(cursor == safepoints->raw() + gcmapSize);
   1.739 +    }
   1.740 +
   1.741 +    Local<ByteArray> sourcemap(zone);
   1.742 +    if (sourcemap_.length()) {
   1.743 +        sourcemap = ByteArray::New(zone, sourcemap_.length(), Heap::Tenure_Old);
   1.744 +        if (!sourcemap)
   1.745 +            return NULL;
   1.746 +
   1.747 +        memcpy(sourcemap->raw(), sourcemap_.buffer(), sourcemap_.length());
   1.748 +    }
   1.749 +
   1.750 +    Local<FixedArray> strings(zone, FixedArray::New(zone, strings_.stringCount(), Heap::Tenure_Old));
   1.751 +    if (!strings)
   1.752 +        return NULL;
   1.753 +    for (size_t i = 0; i < strings_.stringCount(); i++)
   1.754 +        strings->set(zone, i, strings_.stringAt(i));
   1.755 +
   1.756 +    Local<FixedArray> locals(zone, FixedArray::New(zone, locals_.length(), Heap::Tenure_Old));
   1.757 +    if (!locals)
   1.758 +        return NULL;
   1.759 +    for (size_t i = 0; i < locals_.length(); i++)
   1.760 +        locals->set(zone, i, locals_[i]->type());
   1.761 +
   1.762 +    Local<Code> code(zone);
   1.763 +
   1.764 +    code = Code::New(zone,
   1.765 +                     bytes,
   1.766 +                     locals,
   1.767 +                     objects,
   1.768 +                     strings,
   1.769 +                     maxStackDepth(),
   1.770 +                     maxLoopDepth_,
   1.771 +                     safepoints,
   1.772 +                     sourcemap);
   1.773 +
   1.774 +    return code;
   1.775 +}