Split ArrayType from Type.
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 ensure(OP_GETLOCAL_LENGTH);
220 writeOp(OP_GETLOCAL);
221 writeUint32(var->slot());
222 if (var->type()->isTraceable())
227 BytecodeEmitter::setlocal(VariableSymbol *var)
229 ensure(OP_SETLOCAL_LENGTH);
230 writeOp(OP_SETLOCAL);
231 writeUint32(var->slot());
232 if (var->type()->isTraceable())
237 BytecodeEmitter::allocate(VariableSymbol *sym)
239 assert(sym->isVariable());
240 assert(sym->scope()->kind() == Scope::BLOCK);
242 switch (sym->scope()->kind()) {
245 // See overall comment on overflows.
246 assert(locals_.length() < UINT_MAX);
247 sym->allocate(VariableSymbol::Local, locals_.length());
248 if (!locals_.append(sym))
262 BytecodeEmitter::finish()
267 if (oom() || zone->hasPendingException())
270 Local<ByteArray> bytes(zone, ByteArray::New(zone, length(), Heap::Tenure_Old));
273 memcpy(bytes->raw(), buffer(), length());
275 Local<FixedArray> objects(zone, FixedArray::New(zone, objects_.length(), Heap::Tenure_Old));
279 for (size_t i = 0; i < objects_.length(); i++)
280 objects->set(zone, i, objects_[i]);
282 // If any stack slots hold gc pointers at potential failure points in the
283 // bytecode, record them now. We do this by building a list of tuples;
284 // each tuple contains the pc offset, and a bitset containing which stack
285 // slots must be scanned by the gc.
286 Local<ByteArray> safepoints(zone);
287 if (oopRecords_.length()) {
288 size_t bytesPerSafepoint = Code::BytesPerSafepoint(maxStackDepth());
289 size_t gcmapSize = bytesPerSafepoint * oopRecords_.length();
290 safepoints = ByteArray::New(zone, gcmapSize, Heap::Tenure_Old);
294 Address cursor = safepoints->raw();
295 for (size_t i = 0; i < oopRecords_.length(); i++) {
296 OopRecord *record = oopRecords_[i];
297 assert(record->depth <= maxStackDepth());
299 *reinterpret_cast<unsigned *>(cursor) = record->offset;
301 unsigned char *bits = reinterpret_cast<unsigned char *>(cursor + sizeof(unsigned));
302 for (unsigned i = 0; i < record->depth; i++)
303 bits[i / 8] |= (1 << (i % 8));
305 cursor += bytesPerSafepoint;
308 assert(cursor == safepoints->raw() + gcmapSize);
311 Local<ByteArray> sourcemap(zone);
312 if (sourcemap_.length()) {
313 sourcemap = ByteArray::New(zone, sourcemap_.length(), Heap::Tenure_Old);
317 memcpy(sourcemap->raw(), sourcemap_.buffer(), sourcemap_.length());
320 Local<FixedArray> strings(zone, FixedArray::New(zone, strings_.stringCount(), Heap::Tenure_Old));
323 for (size_t i = 0; i < strings_.stringCount(); i++)
324 strings->set(zone, i, strings_.stringAt(i));
326 Local<FixedArray> locals(zone, FixedArray::New(zone, locals_.length(), Heap::Tenure_Old));
329 for (size_t i = 0; i < locals_.length(); i++)
330 locals->set(zone, i, locals_[i]->type());
332 Local<Code> code(zone);
334 code = Code::New(zone,