Added a Function object to sit in between Module and Code.
2 * Copyright (C) 2012 David Anderson
4 * This file is part of JITCraft.
6 * JITCraft is free software: you can redistribute it and/or modify it under
7 * the terms of the GNU General Public License as published by the Free
8 * Software Foundation, either version 3 of the License, or (at your option)
11 * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along with
16 * JITCraft. If not, see http://www.gnu.org/licenses/.
18 #include "Interpreter.h"
23 #include "Reference.h"
27 #define PUSH_I32(top, value) \
29 top.sp->i32 = value; \
33 #define PUSH_F(top, value) \
42 int value = top.sp[-1].i32;
50 float value = top.sp[-1].f;
56 PushNewRef(Zone *zone, Top &top, void *location, Heap::Tenure tenure)
58 Reference *ref = Reference::NewStack(zone, location, tenure);
67 CheckDimensionSize(int size, unsigned width)
73 // One word, because we hide stuff below and need to add that in.
74 if (unsigned(size) >= (INT_MAX / width) - sizeof(unsigned)) {
81 // Generate an array with completely static sizes.
83 GenerateArray(Zone *zone, ArrayMap *map)
85 assert(map->type()->elements() != -1);
88 Array *array = Array::New(zone, map, map->type()->elements(), Heap::Tenure_Stack);
92 if (map->type()->levels() == 1)
95 for (unsigned i = 0; i < unsigned(map->type()->elements()); i++) {
96 Array *sub = GenerateArray(zone, map->contained());
99 array->writeObject(zone, i, sub);
106 CopyArray(Zone *zone, Array *source, Array *dest)
108 assert(source->type()->levels() == 1);
109 assert(dest->type()->levels() == 1);
110 assert(source->type()->contained()->primitive() ==
111 dest->type()->contained()->primitive());
112 assert(source->nelements() >= dest->nelements());
113 assert(dest->elementSize() == source->elementSize());
115 memcpy(source->vec(), dest->vec(), dest->nelements() * dest->elementSize());
120 jc::Interpret(Frame *frame, LocalSlot *result)
122 Top &top = *ZONE()->stack().top();
123 LocalSlot *locals = frame->locals();
126 Opcode op = Opcode(*top.pc);
133 PUSH_I32(top, READ_INT32(top.pc));
137 PUSH_F(top, READ_FLOAT(top.pc));
146 frame = ZONE()->stack().popFrame(frame);
147 locals = frame->locals();
149 top.pc += OpcodeInfo[*top.pc].length;
153 #define RELATIONAL_JUMP(op) \
155 int right = POP_I32(top); \
156 int left = POP_I32(top); \
157 if (left op right) { \
158 top.pc += READ_INT32(top.pc); \
189 int value = POP_I32(top);
191 top.pc += READ_INT32(top.pc);
199 int value = POP_I32(top);
201 top.pc += READ_INT32(top.pc);
208 top.pc += READ_INT32(top.pc);
213 int slot = READ_INT32(top.pc);
214 *top.sp++ = locals[slot];
220 int slot = READ_INT32(top.pc);
221 locals[slot] = top.sp[-1];
227 int right = POP_I32(top);
228 int left = POP_I32(top);
229 int result = left + right;
230 PUSH_I32(top, result);
236 int right = POP_I32(top);
237 int left = POP_I32(top);
238 int result = left - right;
239 PUSH_I32(top, result);
245 int right = POP_I32(top);
246 int left = POP_I32(top);
247 int result = left * right;
248 PUSH_I32(top, result);
254 int right = POP_I32(top);
255 int left = POP_I32(top);
258 int result = left / right;
259 PUSH_I32(top, result);
265 float right = POP_F(top);
266 float left = POP_F(top);
267 float result = left + right;
274 float right = POP_F(top);
275 float left = POP_F(top);
276 float result = left - right;
283 float right = POP_F(top);
284 float left = POP_F(top);
285 float result = left * right;
292 float right = POP_F(top);
293 float left = POP_F(top);
296 float result = left / right;
303 int right = POP_I32(top);
304 int left = POP_I32(top);
305 int result = left << right;
306 PUSH_I32(top, result);
312 int right = POP_I32(top);
313 int left = POP_I32(top);
314 int result = left >> right;
315 PUSH_I32(top, result);
321 int right = POP_I32(top);
322 int left = POP_I32(top);
323 int result = unsigned(left) >> unsigned(right);
324 PUSH_I32(top, result);
330 int right = POP_I32(top);
331 int left = POP_I32(top);
332 int result = left & right;
333 PUSH_I32(top, result);
339 int right = POP_I32(top);
340 int left = POP_I32(top);
341 int result = left | right;
342 PUSH_I32(top, result);
348 int right = POP_I32(top);
349 int left = POP_I32(top);
350 int result = left ^ right;
351 PUSH_I32(top, result);
365 unsigned argc = READ_UINT32(top.pc);
366 unsigned index = READ_UINT32(top.pc + 4);
367 Function *newFun = frame->code()->module()->getFunction(index);
368 frame = ZONE()->stack().pushFrame(frame, newFun);
370 assert(newFun->nargs() == argc);
372 locals = frame->locals();
378 unsigned slot = READ_UINT32(top.pc);
379 *top.sp++ = frame->arg(slot);
385 unsigned slot = READ_UINT32(top.pc);
386 frame->arg(slot) = *--top.sp;
392 Array *array = top.sp[-2].array;
393 int index = top.sp[-1].i32;
394 if (index < 0 || unsigned(index) >= array->nelements())
401 Array *array = top.sp[-2].array;
402 int index = top.sp[-1].i32;
403 top.sp[-2].i32 = array->readInt32(index);
410 Array *array = top.sp[-2].array;
411 int index = top.sp[-1].i32;
412 top.sp[-2].f = array->readFloat(index);
419 Array *array = top.sp[-2].array;
420 int index = top.sp[-1].i32;
421 top.sp[-2].i32 = array->readChar(index);
428 Array *array = top.sp[-3].array;
429 int index = top.sp[-2].i32;
430 array->writeInt32(index, top.sp[-1].i32);
431 top.sp[-3] = top.sp[-1];
438 Array *array = top.sp[-3].array;
439 int index = top.sp[-2].i32;
440 array->writeFloat(index, top.sp[-1].f);
441 top.sp[-3] = top.sp[-1];
448 Array *array = top.sp[-3].array;
449 int index = top.sp[-2].i32;
450 array->writeChar(index, top.sp[-1].i32);
451 top.sp[-3] = top.sp[-1];
458 Array *array = top.sp[-2].array;
459 int index = top.sp[-1].i32;
460 top.sp[-2].array = Array::cast(array->readObject(index));
467 int ival = POP_I32(top);
468 float fval = (float)ival;
473 case OP_NEWARRAY_LIFO:
476 ArrayMap *map = ArrayMap::cast(frame->code()->map(READ_UINT32(top.pc)));
477 Array *array = GenerateArray(ZONE(), map);
489 unsigned slot = READ_UINT32(top.pc);
490 locals[slot].address = ZONE()->heap().lifoPosition();
496 unsigned slot = READ_UINT32(top.pc);
497 ZONE()->heap().unwindLifo(locals[slot].address);
503 unsigned slot = READ_UINT32(top.pc);
504 if (!PushNewRef(ZONE(), top, &locals[slot], Heap::Tenure_Stack)) {
513 unsigned slot = READ_UINT32(top.pc);
514 if (!PushNewRef(ZONE(), top, &frame->arg(slot), Heap::Tenure_Stack)) {
521 case OP_ARRAYREF_LIFO:
523 Reference *ref = Reference::NewArray(ZONE(), top.sp[-2].array, top.sp[-1].i32, Heap::Tenure_Stack);
528 top.sp[-2].ref = ref;
533 case OP_SLOTREF_LIFO:
535 Reference *ref = Reference::NewStack(ZONE(), top.sp[-1], Heap::Tenure_Stack);
540 top.sp[-1].ref = ref;
546 top.sp[-1].i32 = top.sp[-1].ref->getInt();
552 top.sp[-2].ref->setInt(top.sp[-1].i32);
553 top.sp[-2].i32 = top.sp[-1].i32;
560 top.sp[-1].f = top.sp[-1].ref->getFloat();
566 top.sp[-2].ref->setFloat(top.sp[-1].f);
567 top.sp[-2].f = top.sp[-1].f;
573 top.sp->obj = frame->code()->object(READ_UINT32(top.pc));
580 // Note for this assignment opcode, we return the left-hand side, not the
581 // right, since in this case the result of the expression could be different.
582 if (!CopyArray(ZONE(), top.sp[-2].array, top.sp[-1].array)) {
593 top.sp[-1] = top.sp[-2];
600 top.sp[-2] = top.sp[-4];
601 top.sp[-1] = top.sp[-3];
607 LocalSlot slot = top.sp[-2];
608 top.sp[-2] = top.sp[-1];
615 LocalSlot slot = top.sp[-3];
616 top.sp[-3] = top.sp[-2];
617 top.sp[-2] = top.sp[-1];
625 top.sp[-1] = top.sp[-3];
632 top.sp[-1] = top.sp[-4];
642 top.pc += OpcodeInfo[op].length;