Implement |const| keyword.
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_)),
97 lastCodePosition_ = 0;
101 BytecodeEmitter::~BytecodeEmitter()
103 for (size_t i = 0; i < oopRecords_.length(); i++)
104 delete oopRecords_[i];
108 BytecodeEmitter::accept(VirtualObjectVisitor *visitor)
110 for (size_t i = 0; i < objects_.length(); i++)
111 visitor->visit(&objects_[i]);
113 strings_.accept(visitor);
117 BytecodeEmitter::growBuffer(size_t nbytes)
120 buffer_pos_ = buffer_;
124 size_t newSize = size_t((buffer_end_ - buffer_) * 2);
125 if (newSize >= MAX_LENGTH) {
127 buffer_pos_ = buffer_;
128 ZONE()->reportOutOfMemory();
133 if (buffer_ == inline_buffer_)
134 newBuffer = (bytecode *)malloc(newSize);
136 newBuffer = (bytecode *)realloc(buffer_, newSize);
138 // If we can't allocate a buffer, reset the buffer to the start and set
139 // a flag to indicate out-of-memory.
142 buffer_pos_ = buffer_;
143 ZONE()->reportOutOfMemory();
147 if (buffer_ == inline_buffer_)
148 memcpy(newBuffer, inline_buffer_, (buffer_pos_ - inline_buffer_));
150 buffer_pos_ = newBuffer + size_t(buffer_pos_ - buffer_);
152 buffer_end_ = buffer_ + newSize;
153 assert(buffer_pos_ + nbytes < buffer_end_);
159 BytecodeEmitter::recordOops()
161 OopRecord *record = new OopRecord(oopMap_.length(), position());
163 if (!record->slots.ensure(record->depth)) {
168 bool hadOops = false;
169 for (size_t i = 0; i < oopMap_.length(); i++) {
170 bool bit = oopMap_[i];
171 record->slots.infallibleAppend(bit);
180 oom_ &= oopRecords_.append(record);
184 BytecodeEmitter::note_position(const SourcePosition &pos)
186 assert(pos.line > 0);
187 assert(unsigned(pos.line) >= firstLine_);
189 unsigned lineDelta = unsigned(pos.line) - firstLine_;
190 unsigned pcDelta = unsigned(position()) - lastCodePosition_;
192 sourcemap_.writeUint32(pcDelta);
193 sourcemap_.writeUint32(lineDelta);
194 sourcemap_.writeUint32(pos.col);
196 lastCodePosition_ = unsigned(position());
200 BytecodeEmitter::getglobal(Symbol *sym)
202 ensure(OP_GETGLOBAL_LENGTH);
203 writeOp(OP_GETGLOBAL);
204 writeUint32(addString(sym->name()));
205 if (sym->type()->isTraceable())
209 BytecodeEmitter::setglobal(Symbol *sym)
211 ensure(OP_SETGLOBAL_LENGTH);
212 writeOp(OP_SETGLOBAL);
213 writeUint32(addString(sym->name()));
214 if (sym->type()->isTraceable())
219 BytecodeEmitter::getlocal(VariableSymbol *var)
221 assert(var->storage() == VariableSymbol::Local);
222 ensure(OP_GETLOCAL_LENGTH);
223 writeOp(OP_GETLOCAL);
224 writeUint32(var->slot());
225 if (var->type()->isTraceable())
230 BytecodeEmitter::setlocal(VariableSymbol *var)
232 assert(var->storage() == VariableSymbol::Local);
233 ensure(OP_SETLOCAL_LENGTH);
234 writeOp(OP_SETLOCAL);
235 writeUint32(var->slot());
236 if (var->type()->isTraceable())
241 BytecodeEmitter::getarg(VariableSymbol *var)
243 assert(var->storage() == VariableSymbol::Arg);
244 ensure(OP_GETARG_LENGTH);
246 writeUint32(var->slot());
247 if (var->type()->isTraceable())
252 BytecodeEmitter::setarg(VariableSymbol *var)
254 assert(var->storage() == VariableSymbol::Arg);
255 ensure(OP_SETARG_LENGTH);
257 writeUint32(var->slot());
258 if (var->type()->isTraceable())
263 BytecodeEmitter::allocate(VariableSymbol *sym)
265 assert(sym->isVariable());
266 assert(sym->scope()->kind() == Scope::BLOCK);
268 switch (sym->scope()->kind()) {
271 // See overall comment on overflows.
272 assert(locals_.length() < UINT_MAX);
273 sym->allocate(VariableSymbol::Local, locals_.length());
274 if (!locals_.append(sym))
288 BytecodeEmitter::newref(VariableSymbol *var)
291 if (var->storage() == VariableSymbol::Local) {
292 ensure(OP_VARREF_LIFO_LENGTH);
293 writeOp(OP_VARREF_LIFO);
295 assert(var->storage() == VariableSymbol::Arg);
296 ensure(OP_ARGREF_LIFO_LENGTH);
297 writeOp(OP_ARGREF_LIFO);
299 writeUint32(var->slot());
304 BytecodeEmitter::finish()
309 if (oom() || zone->hasPendingException())
312 Local<ByteArray> bytes(zone, ByteArray::New(zone, length(), Heap::Tenure_Old));
315 memcpy(bytes->raw(), buffer(), length());
317 Local<FixedArray> objects(zone, FixedArray::New(zone, objects_.length(), Heap::Tenure_Old));
321 for (size_t i = 0; i < objects_.length(); i++)
322 objects->set(zone, i, objects_[i]);
324 // If any stack slots hold gc pointers at potential failure points in the
325 // bytecode, record them now. We do this by building a list of tuples;
326 // each tuple contains the pc offset, and a bitset containing which stack
327 // slots must be scanned by the gc.
328 Local<ByteArray> safepoints(zone);
329 if (oopRecords_.length()) {
330 size_t bytesPerSafepoint = Code::BytesPerSafepoint(maxStackDepth());
331 size_t gcmapSize = bytesPerSafepoint * oopRecords_.length();
332 safepoints = ByteArray::New(zone, gcmapSize, Heap::Tenure_Old);
336 Address cursor = safepoints->raw();
337 for (size_t i = 0; i < oopRecords_.length(); i++) {
338 OopRecord *record = oopRecords_[i];
339 assert(record->depth <= maxStackDepth());
341 *reinterpret_cast<unsigned *>(cursor) = record->offset;
343 unsigned char *bits = reinterpret_cast<unsigned char *>(cursor + sizeof(unsigned));
344 for (unsigned i = 0; i < record->depth; i++)
345 bits[i / 8] |= (1 << (i % 8));
347 cursor += bytesPerSafepoint;
350 assert(cursor == safepoints->raw() + gcmapSize);
353 Local<ByteArray> sourcemap(zone);
354 if (sourcemap_.length()) {
355 sourcemap = ByteArray::New(zone, sourcemap_.length(), Heap::Tenure_Old);
359 memcpy(sourcemap->raw(), sourcemap_.buffer(), sourcemap_.length());
362 Local<FixedArray> strings(zone, FixedArray::New(zone, strings_.stringCount(), Heap::Tenure_Old));
365 for (size_t i = 0; i < strings_.stringCount(); i++)
366 strings->set(zone, i, strings_.stringAt(i));
368 Local<FixedArray> locals(zone, FixedArray::New(zone, locals_.length(), Heap::Tenure_Old));
371 for (size_t i = 0; i < locals_.length(); i++)
372 locals->set(zone, i, locals_[i]->type());
374 Local<Code> code(zone);
376 code = Code::New(zone,