mirror of
https://github.com/golang/go
synced 2024-11-23 00:40:08 -07:00
dd7b583179
reuse Thread in function calls. R=austin DELTA=59 (8 added, 7 deleted, 44 changed) OCL=34266 CL=34266
90 lines
1.4 KiB
Go
90 lines
1.4 KiB
Go
// Copyright 2009 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package eval
|
|
|
|
import "os"
|
|
|
|
/*
|
|
* Virtual machine
|
|
*/
|
|
|
|
type Thread struct {
|
|
abort chan os.Error;
|
|
pc uint;
|
|
// The execution frame of this function. This remains the
|
|
// same throughout a function invocation.
|
|
f *Frame;
|
|
}
|
|
|
|
type code []func(*Thread)
|
|
|
|
func (i code) exec(t *Thread) {
|
|
opc := t.pc;
|
|
t.pc = 0;
|
|
l := uint(len(i));
|
|
for t.pc < l {
|
|
pc := t.pc;
|
|
t.pc++;
|
|
i[pc](t);
|
|
}
|
|
t.pc = opc;
|
|
}
|
|
|
|
/*
|
|
* Code buffer
|
|
*/
|
|
|
|
type codeBuf struct {
|
|
instrs code;
|
|
}
|
|
|
|
func newCodeBuf() *codeBuf {
|
|
return &codeBuf{make(code, 0, 16)};
|
|
}
|
|
|
|
func (b *codeBuf) push(instr func(*Thread)) {
|
|
n := len(b.instrs);
|
|
if n >= cap(b.instrs) {
|
|
a := make(code, n, n*2);
|
|
for i := range b.instrs {
|
|
a[i] = b.instrs[i];
|
|
}
|
|
b.instrs = a;
|
|
}
|
|
b.instrs = b.instrs[0:n+1];
|
|
b.instrs[n] = instr;
|
|
}
|
|
|
|
func (b *codeBuf) nextPC() uint {
|
|
return uint(len(b.instrs));
|
|
}
|
|
|
|
func (b *codeBuf) get() code {
|
|
// Freeze this buffer into an array of exactly the right size
|
|
a := make(code, len(b.instrs));
|
|
for i := range b.instrs {
|
|
a[i] = b.instrs[i];
|
|
}
|
|
return code(a);
|
|
}
|
|
|
|
/*
|
|
* User-defined functions
|
|
*/
|
|
|
|
type evalFunc struct {
|
|
outer *Frame;
|
|
frameSize int;
|
|
code code;
|
|
}
|
|
|
|
func (f *evalFunc) NewFrame() *Frame {
|
|
return f.outer.child(f.frameSize);
|
|
}
|
|
|
|
func (f *evalFunc) Call(t *Thread) {
|
|
f.code.exec(t);
|
|
}
|