Skip to content

Commit

Permalink
Expanded Frame macros.
Browse files Browse the repository at this point in the history
  • Loading branch information
feyeleanor committed Nov 27, 2009
1 parent 41a77b6 commit d8aae1c
Show file tree
Hide file tree
Showing 20 changed files with 821 additions and 428 deletions.
46 changes: 23 additions & 23 deletions vm/array.go
Expand Up @@ -17,19 +17,19 @@ func newArray(vm *RubyVM) RubyObject {

// Uses variadic ... parameter which replaces the mechanism used by stdarg.h
func newArray2(vm *RubyVM, argc int, ...) RubyObject {
a := newArray(vm);
va_list argp;
int i;
va_start(argp, argc);
for (i = 0; i < argc; ++i) a.kv.Push(va_arg(argp, *RubyObject));
va_end(argp);
return a;
a := newArray(vm);
va_list argp;
int i;
va_start(argp, argc);
for (i = 0; i < argc; ++i) a.kv.Push(va_arg(argp, *RubyObject));
va_end(argp);
return a;
}

func newArray3(vm *RubyVM, argc int, items []RubyObject) RubyObject {
a := newArray(vm);
for i := 0; i < argc; ++i { a.kv.Push(items[i]) };
return a;
a := newArray(vm);
for i := 0; i < argc; ++i { a.kv.Push(items[i]) };
return a;
}

func (self *Array) push(vm *RubyVM, x *RubyObject) *RubyObject {
Expand All @@ -38,15 +38,15 @@ func (self *Array) push(vm *RubyVM, x *RubyObject) *RubyObject {
}

func (self *Array) at2index(vm *RubyVM, at *RubyObject) int {
int i = TR_FIX2INT(at);
if (i < 0) i = self.kv.Len() + i;
return i;
int i = TR_FIX2INT(at);
if (i < 0) i = self.kv.Len() + i;
return i;
}

func (self *Array) at(vm *RubyVM, at *RubyObject) *RubyObject {
i := self.at2index(vm, at);
if i < 0 || i >= self.kv.Len() { return TR_NIL; }
return self.kv.At(i);
i := self.at2index(vm, at);
if i < 0 || i >= self.kv.Len() { return TR_NIL; }
return self.kv.At(i);
}

func (self *Array) set(vm *RubyVM, at, x *RubyObject) *RubyObject {
Expand All @@ -62,14 +62,14 @@ func (self *Array) set(vm *RubyVM, at, x *RubyObject) *RubyObject {
}

func (self *Array) length(vm *RubyVM) RubyObject {
return TR_INT2FIX(self.kv.Len());
return TR_INT2FIX(self.kv.Len());
}

void TrArray_init(vm *RubyVM) {
c := vm.classes[TR_T_Array] = Object_const_set(vm, vm.self, tr_intern(Array), newClass(vm, tr_intern(Array), vm.classes[TR_T_Object]));
tr_def(c, "length", TrArray_length, 0);
tr_def(c, "size", TrArray_length, 0);
tr_def(c, "<<", TrArray_push, 1);
tr_def(c, "[]", TrArray_at, 1);
tr_def(c, "[]=", TrArray_set, 2);
c := vm.classes[TR_T_Array] = Object_const_set(vm, vm.self, tr_intern(Array), newClass(vm, tr_intern(Array), vm.classes[TR_T_Object]));
tr_def(c, "length", TrArray_length, 0);
tr_def(c, "size", TrArray_length, 0);
tr_def(c, "<<", TrArray_push, 1);
tr_def(c, "[]", TrArray_at, 1);
tr_def(c, "[]=", TrArray_set, 2);
}
113 changes: 93 additions & 20 deletions vm/block.go
Expand Up @@ -42,9 +42,7 @@ func newBlock(compiler *Compiler, parent *Block) *Block {
return block;
}

#define INSPECT_K(K) (K.(Symbol) ? TR_CSTRING(K).ptr : (sprintf(buf, "%d", TR_FIX2INT(K)), buf))

func (b *Block) dump2(vm *RubyVM, level int) RubyObject {
func (b *Block) dump(vm *RubyVM, level int) RubyObject {
char buf[10];

size_t i;
Expand All @@ -58,35 +56,110 @@ func (b *Block) dump2(vm *RubyVM, level int) RubyObject {
for (i = 0; i < b.defaults.Len; ++i) fmt.Printf("%d ", b.defaults.At(i));
fmt.Println();
}
for (i = 0; i < b.locals.Len(); ++i) { fmt.Println(".local %-8s ; %lu", INSPECT_K(b.locals.At(i)), i); }
for (i = 0; i < b.upvals.Len(); ++i) { fmt.Println(".upval %-8s ; %lu", INSPECT_K(b.upvals.At(i)), i); }
for (i = 0; i < b.k.Len(); ++i) { fmt.Println(".value %-8s ; %lu", INSPECT_K(b.k.At(i)), i); }
for (i = 0; i < b.strings.Len; ++i) { fmt.Println(".string %-8s ; %lu", b.strings.At(i), i); }
for (i = 0; i < b.locals.Len(); ++i) {
local := b.locals.At(i);
if local.(Symbol) {
local := local.ptr;
} else {
sprintf(buf, "%d", TR_FIX2INT(local));
local := buf;
}
fmt.Println(".local %-8s ; %lu", local, i);
}
for (i = 0; i < b.upvals.Len(); ++i) {
upval := b.upvals.At(i);
if upval.(Symbol) {
upval := upval.ptr;
} else {
sprintf(buf, "%d", TR_FIX2INT(upval));
upval := buf;
}
fmt.Println(".upval %-8s ; %lu", upval, i);
}
for (i = 0; i < b.k.Len(); ++i) {
k := b.k.At(i);
if k.(Symbol) {
k := k.ptr;
} else {
sprintf(buf, "%d", TR_FIX2INT(k));
k := buf;
}
fmt.Println(".value %-8s ; %lu",k, i);
}
for (i = 0; i < b.strings.Len; ++i) {
fmt.Println(".string %-8s ; %lu", b.strings.At(i), i);
}
for (i = 0; i < b.code.Len(); ++i) {
op := b.code.At(i);
fmt.printf("[%03lu] %-10s %3d %3d %3d", i, OPCODE_NAMES[op.OpCode], op.A, op.B, op.C);
switch (op.OpCode) {
case TR_OP_LOADK: fmt.Printf(" ; R[%d] = %s", op.A, INSPECT_K(b.k.At(op.Get_Bx())));
case TR_OP_STRING: fmt.Printf(" ; R[%d] = \"%s\"", op.A, b.strings.At(op.Get_Bx()));
case TR_OP_LOOKUP: fmt.Printf(" ; R[%d] = R[%d].method(:%s)", op.A + 1, op.A, INSPECT_K(b.k.At(op.Get_Bx())));
case TR_OP_CALL: fmt.Printf(" ; R[%d] = R[%d].R[%d](%d)", op.A, op.A, op.A + 1, op.B >> 1);
case TR_OP_SETUPVAL: fmt.Printf(" ; %s = R[%d]", INSPECT_K(b.upvals.At(op.B)), op.A);
case TR_OP_GETUPVAL: fmt.Printf(" ; R[%d] = %s", op.A, INSPECT_K(b.upvals.At(op.B)));
case TR_OP_JMP: fmt.Printf(" ; %d", op.Get_sBx());
case TR_OP_DEF: fmt.Printf(" ; %s => %p", INSPECT_K(b.k.At(op.Get_Bx())), b.blocks.At(op.A));
case TR_OP_LOADK:
k := b.k.At(op.Get_Bx());
if k.(Symbol) {
k := k.ptr;
} else {
sprintf(buf, "%d", TR_FIX2INT(k));
k := buf;
}
fmt.Printf(" ; R[%d] = %s", op.A, k);

case TR_OP_STRING:
fmt.Printf(" ; R[%d] = \"%s\"", op.A, b.strings.At(op.Get_Bx()));

case TR_OP_LOOKUP:
k := b.l.At(op.Get_Bx());
if k.(Symbol) {
k := k.ptr;
} else {
sprintf(buf, "%d", TR_FIX2INT(k));
k := buf;
}
fmt.Printf(" ; R[%d] = R[%d].method(:%s)", op.A + 1, op.A, k);

case TR_OP_CALL:
fmt.Printf(" ; R[%d] = R[%d].R[%d](%d)", op.A, op.A, op.A + 1, op.B >> 1);

case TR_OP_SETUPVAL:
upval := b.upvals.At(op.B);
if upval.(Symbol) {
upval := upval.ptr;
} else {
sprintf(buf, "%d", TR_FIX2INT(upval));
upval := buf;
}
fmt.Printf(" ; %s = R[%d]", upval, op.A);

case TR_OP_GETUPVAL:
upval := b.upvals.At(op.B);
if upval.(Symbol) {
upval := upval.ptr;
} else {
sprintf(buf, "%d", TR_FIX2INT(upval));
upval := buf;
}
fmt.Printf(" ; R[%d] = %s", op.A, upval);

case TR_OP_JMP:
fmt.Printf(" ; %d", op.Get_sBx());

case TR_OP_DEF:
k := b.k.At(op.Get_Bx());
if k.(Symbol) {
k := k.ptr;
} else {
sprintf(buf, "%d", TR_FIX2INT(k));
k := buf;
}
fmt.Printf(" ; %s => %p", k, b.blocks.At(op.A));
}
fmt.Println();
}
fmt.Println("; block end\n");

for (i = 0; i < b.blocks.Len(); ++i) { b.blocks.At(i).dump2(vm, level+1); }
for (i = 0; i < b.blocks.Len(); ++i) { b.blocks.At(i).dump(vm, level+1); }
return TR_NIL;
}

func (b *Block) dump(vm *RubyVM) {
b.dump2(vm, 0);
}

func (block *Block) push_value(k *RubyObject) int {
size_t i;
for i = 0; i < block.k.Len(); ++i {
Expand Down
108 changes: 49 additions & 59 deletions vm/call.go
@@ -1,5 +1,3 @@
/* Inlined functions frequently used in the method calling process. */

#include <alloca.h>

import (
Expand All @@ -18,67 +16,59 @@ type Frame struct {
previous *Frame;
}

func (self *Method) call(vm *RubyVM, receiver *RubyObject, argc int, args []RubyObject, splat int, closure *Closure) RubyObject {
if TR_IMMEDIATE(receiver) {
receiver_class := vm.classes[Object_type(vm, receiver)];
} else {
receiver_class := Object *(receiver).class;
}

#define TR_WITH_FRAME(SELF,CLASS,CLOS,BODY) ({ \
/* push a frame */ \
if (++vm.cf >= TR_MAX_FRAMES) { tr_raise(SystemStackError, "Stack overflow"); } \
Frame __f; \
Frame *__fp = &__f; \
__f.previous = vm.frame; \
if (vm.cf == 0) vm.top_frame = __fp; \
vm.frame = __fp; \
vm.throw_reason = vm.throw_value = 0; \
__f.method = NULL; \
__f.filename = __f.line = 0; \
__f.self = SELF; \
__f.class = CLASS; \
__f.closure = CLOS; \
/* execute BODY inside the frame */ \
BODY \
/* pop the frame */ \
vm.cf--; \
vm.frame = vm.frame.previous; \
})
// push a frame
vm.cf++;
if vm.cf >= TR_MAX_FRAMES { tr_raise(SystemStackError, "Stack overflow"); }

func (self *Method) call(vm *RubyVM, receiver *RubyObject, argc int, args []RubyObject, splat int, cl *Closure) RubyObject {
ret := TR_NIL;
Frame *f = nil;
frame := Frame{previous: vm.frame, method: nil, filename: nil, line: 0, self: receiver, class: receiver_class, closure: closure}
if vm.cf == 0 { vm.top_frame = frame; }
vm.frame = frame;
vm.throw_reason = vm.throw_value = 0;

TR_WITH_FRAME(receiver, TR_CLASS(receiver), cl, {
f := vm.frame;
m := f.method = self;
func = f.method.func;
// execute BODY inside the frame
method := frame.method = self;
function = frame.method.func;

// splat last arg is needed
if splat {
splated := args[argc - 1];
splatedn := splated.kv.Len();
new_args := make([]OBJ, argc)
memcpy(new_args, args, sizeof(OBJ) * (argc - 1));
memcpy(new_args + argc - 1, &splated.kv.At(0), sizeof(OBJ) * splatedn);
argc += splatedn-1;
args = new_args;
}
// splat last arg is needed
if splat {
splated := args[argc - 1];
splatedn := splated.kv.Len();
new_args := make([]OBJ, argc)
memcpy(new_args, args, sizeof(OBJ) * (argc - 1));
memcpy(new_args + argc - 1, &splated.kv.At(0), sizeof(OBJ) * splatedn);
argc += splatedn-1;
args = new_args;
}

if (m.arity == -1) {
ret := func(vm, receiver, argc, args);
} else {
if m.arity != argc { tr_raise(ArgumentError, "Expected %d arguments, got %d.", f.method.arity, argc); }
switch argc {
case 0: ret := func(vm, receiver);
case 1: ret := func(vm, receiver, args[0]);
case 2: ret := func(vm, receiver, args[0], args[1]);
case 3: ret := func(vm, receiver, args[0], args[1], args[2]);
case 4: ret := func(vm, receiver, args[0], args[1], args[2], args[3]);
case 5: ret := func(vm, receiver, args[0], args[1], args[2], args[3], args[4]);
case 6: ret := func(vm, receiver, args[0], args[1], args[2], args[3], args[4], args[5]);
case 7: ret := func(vm, receiver, args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
case 8: ret := func(vm, receiver, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);
case 9: ret := func(vm, receiver, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);
case 10: ret := func(vm, receiver, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);
default: tr_raise(ArgumentError, "Too much arguments: %d, max is %d for now.", argc, 10);
}
if (m.arity == -1) {
result := function(vm, receiver, argc, args);
} else {
if method.arity != argc { tr_raise(ArgumentError, "Expected %d arguments, got %d.", frame.method.arity, argc); }
switch argc {
case 0: result := function(vm, receiver);
case 1: result := function(vm, receiver, args[0]);
case 2: result := function(vm, receiver, args[0], args[1]);
case 3: result := function(vm, receiver, args[0], args[1], args[2]);
case 4: result := function(vm, receiver, args[0], args[1], args[2], args[3]);
case 5: result := function(vm, receiver, args[0], args[1], args[2], args[3], args[4]);
case 6: result := function(vm, receiver, args[0], args[1], args[2], args[3], args[4], args[5]);
case 7: result := function(vm, receiver, args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
case 8: result := function(vm, receiver, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);
case 9: result := function(vm, receiver, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);
case 10: result := function(vm, receiver, args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]);
default: tr_raise(ArgumentError, "Too much arguments: %d, max is %d for now.", argc, 10);
}
});
return ret;
}

// pop the frame
vm.cf--;
vm.frame = vm.frame.previous;
return result;
}

0 comments on commit d8aae1c

Please sign in to comment.