Added a mark-sweep garbage collector.
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/.
19 #include "Interpreter.h"
24 #include "Reference.h"
29 #define PUSH_I32(top, value) \
31 top.sp->i32 = value; \
35 #define PUSH_F(top, value) \
44 int value = top.sp[-1].i32;
52 float value = top.sp[-1].f;
58 PushNewRef(Zone *zone, Top &top, void *location, Heap::Tenure tenure)
60 Reference *ref = Reference::NewStack(zone, location, tenure);
69 CheckDimensionSize(int size, unsigned width)
75 // One word, because we hide stuff below and need to add that in.
76 if (unsigned(size) >= (INT_MAX / width) - sizeof(unsigned)) {
83 // Generate an array with completely static sizes.
85 GenerateArray(Zone *zone, Handle<ArrayMap> map)
87 assert(map->type()->elements() != -1);
89 Local<Array> array(zone, Array::New(zone, map, map->type()->elements(), Heap::Tenure_Stack));
93 if (map->type()->levels() == 1)
96 Local<ArrayMap> contained(zone, map->contained());
97 Local<Array> sub(zone);
98 for (unsigned i = 0; i < unsigned(map->type()->elements()); i++) {
99 sub = GenerateArray(zone, contained);
102 array->writeObject(zone, i, sub);
109 CopyArray(Zone *zone, Array *source, Array *dest)
111 assert(source->type()->levels() == 1);
112 assert(dest->type()->levels() == 1);
113 assert(source->type()->contained()->primitive() ==
114 dest->type()->contained()->primitive());
115 assert(source->nelements() >= dest->nelements());
116 assert(dest->elementSize() == source->elementSize());
118 memcpy(source->vec(), dest->vec(), dest->nelements() * dest->elementSize());
123 jc::Interpret(Zone *zone, Frame *entryFrame, LocalSlot *result)
125 Top &top = *zone->stack().top();
126 LocalSlot *locals = entryFrame->locals();
129 Opcode op = Opcode(*top.pc);
136 PUSH_I32(top, READ_INT32(top.pc));
140 PUSH_F(top, READ_FLOAT(top.pc));
149 zone->stack().popFrame();
150 locals = top.fp->locals();
152 top.pc += OpcodeInfo[*top.pc].length;
156 #define RELATIONAL_JUMP(op) \
158 int right = POP_I32(top); \
159 int left = POP_I32(top); \
160 if (left op right) { \
161 top.pc += READ_INT32(top.pc); \
192 int value = POP_I32(top);
194 top.pc += READ_INT32(top.pc);
202 int value = POP_I32(top);
204 top.pc += READ_INT32(top.pc);
211 top.pc += READ_INT32(top.pc);
216 int slot = READ_INT32(top.pc);
217 *top.sp++ = locals[slot];
223 int slot = READ_INT32(top.pc);
224 locals[slot] = top.sp[-1];
230 int right = POP_I32(top);
231 int left = POP_I32(top);
232 int result = left + right;
233 PUSH_I32(top, result);
239 int right = POP_I32(top);
240 int left = POP_I32(top);
241 int result = left - right;
242 PUSH_I32(top, result);
248 int right = POP_I32(top);
249 int left = POP_I32(top);
250 int result = left * right;
251 PUSH_I32(top, result);
257 int right = POP_I32(top);
258 int left = POP_I32(top);
261 int result = left / right;
262 PUSH_I32(top, result);
268 float right = POP_F(top);
269 float left = POP_F(top);
270 float result = left + right;
277 float right = POP_F(top);
278 float left = POP_F(top);
279 float result = left - right;
286 float right = POP_F(top);
287 float left = POP_F(top);
288 float result = left * right;
295 float right = POP_F(top);
296 float left = POP_F(top);
299 float result = left / right;
306 int right = POP_I32(top);
307 int left = POP_I32(top);
308 int result = left << right;
309 PUSH_I32(top, result);
315 int right = POP_I32(top);
316 int left = POP_I32(top);
317 int result = left >> right;
318 PUSH_I32(top, result);
324 int right = POP_I32(top);
325 int left = POP_I32(top);
326 int result = unsigned(left) >> unsigned(right);
327 PUSH_I32(top, result);
333 int right = POP_I32(top);
334 int left = POP_I32(top);
335 int result = left & right;
336 PUSH_I32(top, result);
342 int right = POP_I32(top);
343 int left = POP_I32(top);
344 int result = left | right;
345 PUSH_I32(top, result);
351 int right = POP_I32(top);
352 int left = POP_I32(top);
353 int result = left ^ right;
354 PUSH_I32(top, result);
368 zone->heap().reclaim();
369 unsigned index = READ_UINT32(top.pc);
370 Local<Function> newFun(zone, top.fp->code()->module()->getFunction(index));
371 if (!zone->stack().pushFrame(newFun)) {
376 locals = top.fp->locals();
382 unsigned slot = READ_UINT32(top.pc);
383 *top.sp++ = top.fp->arg(slot);
389 unsigned slot = READ_UINT32(top.pc);
390 top.fp->arg(slot) = *--top.sp;
396 Array *array = top.sp[-2].array;
397 int index = top.sp[-1].i32;
398 if (index < 0 || unsigned(index) >= array->nelements())
405 Array *array = top.sp[-2].array;
406 int index = top.sp[-1].i32;
407 top.sp[-2].i32 = array->readInt32(index);
414 Array *array = top.sp[-2].array;
415 int index = top.sp[-1].i32;
416 top.sp[-2].f = array->readFloat(index);
423 Array *array = top.sp[-2].array;
424 int index = top.sp[-1].i32;
425 top.sp[-2].i32 = array->readChar(index);
432 Array *array = top.sp[-3].array;
433 int index = top.sp[-2].i32;
434 array->writeInt32(index, top.sp[-1].i32);
435 top.sp[-3] = top.sp[-1];
442 Array *array = top.sp[-3].array;
443 int index = top.sp[-2].i32;
444 array->writeFloat(index, top.sp[-1].f);
445 top.sp[-3] = top.sp[-1];
452 Array *array = top.sp[-3].array;
453 int index = top.sp[-2].i32;
454 array->writeChar(index, top.sp[-1].i32);
455 top.sp[-3] = top.sp[-1];
462 Array *array = top.sp[-2].array;
463 int index = top.sp[-1].i32;
464 top.sp[-2].array = Array::cast(array->readObject(index));
471 int ival = POP_I32(top);
472 float fval = (float)ival;
477 case OP_NEWARRAY_LIFO:
479 Local<ArrayMap> map(zone, ArrayMap::cast(top.fp->code()->map(READ_UINT32(top.pc))));
480 Array *array = GenerateArray(zone, map);
492 unsigned slot = READ_UINT32(top.pc);
493 locals[slot].address = zone->heap().lifoPosition();
499 unsigned slot = READ_UINT32(top.pc);
500 zone->heap().unwindLifo(locals[slot].address);
506 unsigned slot = READ_UINT32(top.pc);
507 if (!PushNewRef(zone, top, &locals[slot], Heap::Tenure_Stack)) {
516 unsigned slot = READ_UINT32(top.pc);
517 if (!PushNewRef(zone, top, &top.fp->arg(slot), Heap::Tenure_Stack)) {
524 case OP_ARRAYREF_LIFO:
526 Local<Array> array(zone, top.sp[-2].array);
527 Local<Reference> ref(zone, Reference::NewArray(zone, array, top.sp[-1].i32, Heap::Tenure_Stack));
532 top.sp[-2].ref = ref;
537 case OP_SLOTREF_LIFO:
539 Reference *ref = Reference::NewStack(zone, top.sp[-1], Heap::Tenure_Stack);
544 top.sp[-1].ref = ref;
550 top.sp[-1].i32 = top.sp[-1].ref->getInt();
556 top.sp[-2].ref->setInt(top.sp[-1].i32);
557 top.sp[-2].i32 = top.sp[-1].i32;
564 top.sp[-1].f = top.sp[-1].ref->getFloat();
570 top.sp[-2].ref->setFloat(top.sp[-1].f);
571 top.sp[-2].f = top.sp[-1].f;
577 top.sp->obj = top.fp->code()->object(READ_UINT32(top.pc));
584 // Note for this assignment opcode, we return the left-hand side, not the
585 // right, since in this case the result of the expression could be different.
586 if (!CopyArray(zone, top.sp[-2].array, top.sp[-1].array)) {
597 top.sp[-1] = top.sp[-2];
604 top.sp[-2] = top.sp[-4];
605 top.sp[-1] = top.sp[-3];
611 LocalSlot slot = top.sp[-2];
612 top.sp[-2] = top.sp[-1];
619 LocalSlot slot = top.sp[-3];
620 top.sp[-3] = top.sp[-2];
621 top.sp[-2] = top.sp[-1];
629 top.sp[-1] = top.sp[-3];
636 top.sp[-1] = top.sp[-4];
646 top.pc += OpcodeInfo[op].length;