Re-added parameter support.
1 /* vim: set ts=4 sw=4 tw=99 et:
3 * Copyright (C) 2012 David Anderson
5 * This file is part of JITCraft.
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)
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.
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/.
21 #include "../Utility.h"
24 #include "../Strings.h"
26 #include "BytecodeEmitter.h"
29 #include "../Spaces-inl.h"
30 #include "../Heap-inl.h"
34 StringTable::StringTable()
35 : set_(ZoneAllocatorPolicy()),
41 StringTable::initialize()
43 assert(!initialized_);
51 StringTable::add(Handle<String> name, unsigned *indexp)
53 if (!initialized_ && !initialize())
56 Set::Insert p = set_.findForAdd(*name);
62 if (strings_.length() > INT_MAX) {
63 ZONE()->reportAllocationOverflow();
67 Entry e(name, strings_.length());
68 if (!strings_.append(e))
80 StringTable::accept(VirtualObjectVisitor *visitor)
82 for (size_t i = 0; i < strings_.length(); i++)
83 visitor->visit(reinterpret_cast<Object **>(&strings_[i].string));
86 BytecodeEmitter::BytecodeEmitter(PoolAllocator &pool)
89 buffer_(inline_buffer_),
91 buffer_end_(buffer_pos_ + ARRAY_LENGTH(inline_buffer_)),
95 lastCodePosition_ = 0;
99 BytecodeEmitter::~BytecodeEmitter()
101 for (size_t i = 0; i < oopRecords_.length(); i++)
102 delete oopRecords_[i];
106 BytecodeEmitter::accept(VirtualObjectVisitor *visitor)
108 for (size_t i = 0; i < objects_.length(); i++)
109 visitor->visit(&objects_[i]);
111 strings_.accept(visitor);
115 BytecodeEmitter::growBuffer(size_t nbytes)
118 buffer_pos_ = buffer_;
122 size_t newSize = size_t((buffer_end_ - buffer_) * 2);
123 if (newSize >= MAX_LENGTH) {
125 buffer_pos_ = buffer_;
126 ZONE()->reportOutOfMemory();
131 if (buffer_ == inline_buffer_)
132 newBuffer = (bytecode *)malloc(newSize);
134 newBuffer = (bytecode *)realloc(buffer_, newSize);
136 // If we can't allocate a buffer, reset the buffer to the start and set
137 // a flag to indicate out-of-memory.
140 buffer_pos_ = buffer_;
141 ZONE()->reportOutOfMemory();
145 if (buffer_ == inline_buffer_)
146 memcpy(newBuffer, inline_buffer_, (buffer_pos_ - inline_buffer_));
148 buffer_pos_ = newBuffer + size_t(buffer_pos_ - buffer_);
150 buffer_end_ = buffer_ + newSize;
151 assert(buffer_pos_ + nbytes < buffer_end_);
157 BytecodeEmitter::recordOops()
159 OopRecord *record = new OopRecord(oopMap_.length(), position());
161 if (!record->slots.ensure(record->depth)) {
166 bool hadOops = false;
167 for (size_t i = 0; i < oopMap_.length(); i++) {
168 bool bit = oopMap_[i];
169 record->slots.infallibleAppend(bit);
178 oom_ &= oopRecords_.append(record);
182 BytecodeEmitter::note_position(const SourcePosition &pos)
184 assert(pos.line > 0);
185 assert(unsigned(pos.line) >= firstLine_);
187 unsigned lineDelta = unsigned(pos.line) - firstLine_;
188 unsigned pcDelta = unsigned(position()) - lastCodePosition_;
190 sourcemap_.writeUint32(pcDelta);
191 sourcemap_.writeUint32(lineDelta);
192 sourcemap_.writeUint32(pos.col);
194 lastCodePosition_ = unsigned(position());
198 BytecodeEmitter::getglobal(Symbol *sym)
200 ensure(OP_GETGLOBAL_LENGTH);
201 writeOp(OP_GETGLOBAL);
202 writeUint32(addString(sym->name()));
203 if (sym->type()->isTraceable())
207 BytecodeEmitter::setglobal(Symbol *sym)
209 ensure(OP_SETGLOBAL_LENGTH);
210 writeOp(OP_SETGLOBAL);
211 writeUint32(addString(sym->name()));
212 if (sym->type()->isTraceable())
217 BytecodeEmitter::getlocal(VariableSymbol *var)
219 assert(var->storage() == VariableSymbol::Local);
220 ensure(OP_GETLOCAL_LENGTH);
221 writeOp(OP_GETLOCAL);
222 writeUint32(var->slot());
223 if (var->type()->isTraceable())
228 BytecodeEmitter::setlocal(VariableSymbol *var)
230 assert(var->storage() == VariableSymbol::Local);
231 ensure(OP_SETLOCAL_LENGTH);
232 writeOp(OP_SETLOCAL);
233 writeUint32(var->slot());
234 if (var->type()->isTraceable())
239 BytecodeEmitter::getarg(VariableSymbol *var)
241 assert(var->storage() == VariableSymbol::Arg);
242 ensure(OP_GETARG_LENGTH);
244 writeUint32(var->slot());
245 if (var->type()->isTraceable())
250 BytecodeEmitter::setarg(VariableSymbol *var)
252 assert(var->storage() == VariableSymbol::Arg);
253 ensure(OP_SETARG_LENGTH);
255 writeUint32(var->slot());
256 if (var->type()->isTraceable())
261 BytecodeEmitter::allocate(VariableSymbol *sym)
263 assert(sym->isVariable());
264 assert(sym->scope()->kind() == Scope::BLOCK);
266 switch (sym->scope()->kind()) {
269 // See overall comment on overflows.
270 assert(locals_.length() < UINT_MAX);
271 sym->allocate(VariableSymbol::Local, locals_.length());
272 if (!locals_.append(sym))
286 BytecodeEmitter::finish()
291 if (oom() || zone->hasPendingException())
294 Local<ByteArray> bytes(zone, ByteArray::New(zone, length(), Heap::Tenure_Old));
297 memcpy(bytes->raw(), buffer(), length());
299 Local<FixedArray> objects(zone, FixedArray::New(zone, objects_.length(), Heap::Tenure_Old));
303 for (size_t i = 0; i < objects_.length(); i++)
304 objects->set(zone, i, objects_[i]);
306 // If any stack slots hold gc pointers at potential failure points in the
307 // bytecode, record them now. We do this by building a list of tuples;
308 // each tuple contains the pc offset, and a bitset containing which stack
309 // slots must be scanned by the gc.
310 Local<ByteArray> safepoints(zone);
311 if (oopRecords_.length()) {
312 size_t bytesPerSafepoint = Code::BytesPerSafepoint(maxStackDepth());
313 size_t gcmapSize = bytesPerSafepoint * oopRecords_.length();
314 safepoints = ByteArray::New(zone, gcmapSize, Heap::Tenure_Old);
318 Address cursor = safepoints->raw();
319 for (size_t i = 0; i < oopRecords_.length(); i++) {
320 OopRecord *record = oopRecords_[i];
321 assert(record->depth <= maxStackDepth());
323 *reinterpret_cast<unsigned *>(cursor) = record->offset;
325 unsigned char *bits = reinterpret_cast<unsigned char *>(cursor + sizeof(unsigned));
326 for (unsigned i = 0; i < record->depth; i++)
327 bits[i / 8] |= (1 << (i % 8));
329 cursor += bytesPerSafepoint;
332 assert(cursor == safepoints->raw() + gcmapSize);
335 Local<ByteArray> sourcemap(zone);
336 if (sourcemap_.length()) {
337 sourcemap = ByteArray::New(zone, sourcemap_.length(), Heap::Tenure_Old);
341 memcpy(sourcemap->raw(), sourcemap_.buffer(), sourcemap_.length());
344 Local<FixedArray> strings(zone, FixedArray::New(zone, strings_.stringCount(), Heap::Tenure_Old));
347 for (size_t i = 0; i < strings_.stringCount(); i++)
348 strings->set(zone, i, strings_.stringAt(i));
350 Local<FixedArray> locals(zone, FixedArray::New(zone, locals_.length(), Heap::Tenure_Old));
353 for (size_t i = 0; i < locals_.length(); i++)
354 locals->set(zone, i, locals_[i]->type());
356 Local<Code> code(zone);
358 code = Code::New(zone,