SlideShare una empresa de Scribd logo
1 de 89
golightly
a customisable virtual machine written in Go
Eleanor McHugh
http://slides.games-with-brains.net/
Thursday, 30 May 13
portrait of an artist...
physics major
embedded controllers
software reliability
dynamic languages
network scaling
questionable taste in music
http://github.com/feyeleanor
Eleanor McHugh
Thursday, 30 May 13
go...
small, safety-conscious systems language
concurrency, closures & garbage collection
consistently fast compilation
Thursday, 30 May 13
...lightly
agnostic virtual machine networks
application performance matters
non-viral open source license
Thursday, 30 May 13
agnostic
no blessed programming languages
flexible platform abstractions
write once, run everywhere it matters
Thursday, 30 May 13
heterogeneous
a system comprises many components
components may differ in purpose and design
but they cooperate to solve problems
Thursday, 30 May 13
networks
machines cooperate by sending messages
machine states can be serialised as messages
messages transcend process and host boundaries
Thursday, 30 May 13
inspiration
hardware design
sensor and control networks
field-programmable gate arrays
Thursday, 30 May 13
virtual machine
emulate an existing system
simulate an imagined system
have dynamic control of system state
Thursday, 30 May 13
stack-based lambda calculus processor
threaded value cells in a von neumann memory
all operations are expressions are values
lisp
Thursday, 30 May 13
stack-based processor
threaded word definitions in a von neumann memory
words thread primitives, word pointers and data
forth
Thursday, 30 May 13
stack-based processor with instruction set
harvard memory separates code and data
class loaders convert bytecode to machine state
jvm
Thursday, 30 May 13
linux kernel hypervisor
intel X86 virtualisation with hardware execution
QEMU virtual machine runs in user space
kvm
Thursday, 30 May 13
hello world
Thursday, 30 May 13
package main
import "fmt"
const(
HELLO string = "hello"
WORLD string = "world"
)
func main() {
fmt.Println(HELLO, WORLD)
}
Thursday, 30 May 13
user-defined type
Thursday, 30 May 13
package Integer
type Int int
func (i *Int) Add(x int) {
*i += Int(x)
}
Thursday, 30 May 13
package Integer
type Buffer []Int
func (b Buffer) Eq(o Buffer) (r bool) {
if len(b) == len(o) {
for i := len(b) - 1; i > 0; i-- {
if b[i] != o[i] {
return
}
}
r = true
}
return
}
func (b Buffer) Swap(i, j int) {
b[i], b[j] = b[j], b[i]
}
func (b Buffer) Clone() Buffer {
s := make(Buffer, len(b))
copy(s, b)
return s
}
func (b Buffer) Move(i, n int) {
if n > len(b) - i {
n = len(b) - i
}
segment_to_move := b[:i].Clone()
copy(b, b[i:i + n])
copy(b[n:i + n], segment_to_move)
}
Thursday, 30 May 13
package main
import "Integer"
func main() {
i := Integer.Buffer{0, 1, 2, 3, 4, 5}
b := i.Clone()
b.Swap(1, 2)
b.Move(3, 2)
b[0].Add(3)
println("b[:2] = {", b[0], ",", b[1], "}")
}
produces:
b[0:2] = { 6, 4 }
Thursday, 30 May 13
package Integer
import "testing"
func TestSwap(t *testing.T) {
i := Buffer{0, 1, 2, 3, 4, 5}
b := i.Clone()
b.Swap(1, 2)
if !b[1:3].Eq(Buffer{2, 1}) {
t.Fatalf("b[:5] = %v", b)
}
}
func TestMove(t *testing.T) {
i := Buffer{0, 1, 2, 3, 4, 5}
b := i.Clone()
b.Move(3, 2)
if !b.Eq(Buffer{3, 4, 0, 1, 2, 5}) {
t.Fatalf("b[:5] = %v", b)
}
}
func TestAdd(t *testing.T) {
i := Buffer{0, 1, 2, 3, 4, 5}
b := i.Clone()
b[0].Add(3)
if b[0] != i[0] + 3 {
t.Fatalf("b[:5] = %v", b)
}
}
Thursday, 30 May 13
embedding
Thursday, 30 May 13
package Vector
import . "Integer"
type Vector struct {
Buffer
}
func (v *Vector) Clone() Vector {
return Vector{v.Buffer.Clone()}
}
func (v *Vector) Slice(i, j int) Buffer {
return v.Buffer[i:j]
}
Thursday, 30 May 13
package Integer
import "testing"
func TestVectorSwap(t *testing.T) {
i := Vector{Buffer{0, 1, 2, 3, 4, 5}}
v := i.Clone()
v.Swap(1, 2)
r := Vector{Buffer{0, 2, 1, 3, 4, 5}}
switch {
case !v.Match(&r):
fallthrough
case !v.Buffer.Match(r.Buffer):
t.Fatalf("b[:5] = %v", v)
}
}
Thursday, 30 May 13
package integer
import "testing"
func BenchmarkVectorClone6(b *testing.B) {
v := Vector{Buffer{0, 1, 2, 3, 4, 5}}
for i := 0; i < b.N; i++ {
_ = v.Clone()
}
}
func BenchmarkVectorSwap(b *testing.B) {
b.StopTimer()
v := Vector{Buffer{0, 1, 2, 3, 4, 5}}
b.StartTimer()
for i := 0; i < b.N; i++ {
v.Swap(1, 2)
}
}
Thursday, 30 May 13
$ go test -test.bench="Benchmark"
PASS
integer.BenchmarkVectorSwap 200000000 8 ns/op
integer.BenchmarkVectorClone6 10000000 300 ns/op
Thursday, 30 May 13
inference
Thursday, 30 May 13
package adder
type Adder interface {
Add(j int)
Subtract(j int)
Result() interface{}
}
type Calculator interface {
Adder
Reset()
}
type AddingMachine struct {
Memory interface{}
Adder
}
Thursday, 30 May 13
package adder
type IAdder []int
func (i IAdder) Add(j int) {
i[0] += i[j]
}
func (i IAdder) Subtract(j int) {
i[0] -= i[j]
}
func (i IAdder) Result() interface{} {
return i[0]
}
func (i IAdder) Reset() {
i[0] = *new(int)
}
Thursday, 30 May 13
package adder
import "testing"
func TestIAdder(t *testing.T) {
error := "Result %v != %v"
i := IAdder{0, 1, 2}
i.Add(1)
if i.Result().(int) != 1 { t.Fatalf(error, i.Result(), 1) }
i.Subtract(2)
if i.Result().(int) != -1 { t.Fatalf(error, i.Result()), -1 }
var r Calculator = IAdder{-1, 1, 2}
for n, v := range r.(IAdder) {
if i[n] != v { t.Fatalf("Adder %v should be %v", i, r) }
}
r.Reset()
if r.Result().(int) != *new(int) {
t.Fatalf(error, r.Result(), *new(int))
}
}
Thursday, 30 May 13
package adder
import "testing"
func TestIAdder(t *testing.T) {
error := "Result %v != %v"
i := IAdder{0, 1, 2}
i.Add(1)
if i.Result() != 1 { t.Fatalf(error, i.Result(), 1) }
i.Subtract(2)
if i.Result() != -1 { t.Fatalf(error, i.Result()), -1 }
var r Calculator = IAdder{-1, 1, 2}
for n, v := range r.(IAdder) {
if i[n] != v { t.Fatalf("Adder %v should be %v", i, r) }
}
r.Reset()
if r.Result() != *new(int) {
t.Fatalf(error, r.Result(), *new(int))
}
}
Thursday, 30 May 13
package adder
type FAdder []float32
func (f FAdder) Add(j int) {
f[0] += f[j]
}
func (f FAdder) Subtract(j int) {
f[0] -= f[j]
}
func (f FAdder) Result() interface{} {
return f[0]
}
func (f FAdder) Reset() {
f[0] = *new(float32)
}
Thursday, 30 May 13
package adder
import "testing"
func TestFAdder(t *testing.T) {
error := "Result %v != %v"
f := FAdder{0.0, 1.0, 2.0}
f.Add(1)
if f.Result() != 1.0 { t.Fatalf(error, f.Result(), 1.0) }
f.Subtract(2)
if i.Result() != -1.0 { t.Fatalf(error, i.Result()), -1.0 }
var r Calculator = FAdder{-1.0, 1.0, 2.0}
for n, v := range r.(FAdder) {
if f[n] != v { t.Fatalf("Adder %v should be %v", f, r) }
}
r.Reset()
if r.Result() != *new(float32) {
t.Fatalf(error, r.Result(), *new(float32))
}
}
Thursday, 30 May 13
package adder
import "testing"
func TestAddingMachine(t *testing.T) {
error := "Result %v != %v"
a := &AddingMachine{ Adder: FAdder{0.0, 1.0, 2.0} }
a.Add(1)
if f, ok := a.Result().(float32); !ok {
t.Fatal("Result should be a float32")
} else if f != 1.0 {
t.Fatalf(error, a.Result(), 1.0)
}
a.Subtract(2)
if a.Result().(float32) != -1.0 { t.Fatalf(error, a.Result(), -1.0) }
r := FAdder{-1.0, 1.0, 2.0}
for n, v := range a.Adder.(FAdder) {
if r[n] != v { t.Fatalf("Adder %v should be %v", a, r) }
}
}
Thursday, 30 May 13
concurrency
Thursday, 30 May 13
goroutines
concurrent execution stacks
initialised with a closure
scheduled automatically by the runtime
Thursday, 30 May 13
package main
import "fmt"
func main() {
var c chan int
c = make(chan int)
go func() {
for {
fmt.Print(<-c)
}
}()
for {
select {
case c <- 0:
case c <- 1:
}
}
} produces:
01100111010110...
Thursday, 30 May 13
package main
import "fmt"
func main() {
var c chan int
c = make(chan int, 16)
go func() {
for {
fmt.Print(<-c)
}
}()
go func() {
select {
case c <- 0:
case c <- 1:
}
}()
for {}
}
produces:
01100111010110...
Thursday, 30 May 13
package map_reduce
type SignalSource func(status chan bool)
func Wait(s SignalSource) {
done := make(chan bool)
defer close(done)
go s(done)
<-done
}
func WaitCount(count int, s SignalSource) {
done := make(chan bool)
defer close(done)
go s(done)
for i := 0; i < count; i++ {
<- done
}
}
Thursday, 30 May 13
package map_reduce
type Iteration func(k, x interface{})
func (i Iteration) apply(k, v interface{}, c chan bool) {
go func() {
i(k, v)
c <- true
}()
}
Thursday, 30 May 13
package map_reduce
func Each(c interface{}, f Iteration) {
switch c := c.(type) {
case []int: WaitCount(len(c), func(done chan bool) {
for i, v := range c {
f.apply(i, v, done)
}
})
case map[int] int: WaitCount(len(c), func(done chan bool) {
for k, v := range c {
f.apply(k, v, done)
}
})
}
}
Thursday, 30 May 13
package map_reduce
type Results chan interface{}
type Combination func(x, y interface{}) interface{}
func (f Combination) Reduce(c, s interface{}) (r Results) {
r = make(Results)
go func() {
Each(c, func(k, x interface{}) {
s = f(s, x)
})
r <- s
}()
return
}
Thursday, 30 May 13
package map_reduce
type Transformation func(x interface{}) interface{}
func (t Transformation) GetValue(x interface{}) interface{} {
return t(x)
}
Thursday, 30 May 13
func Map(c interface{}, t Transformation) (n interface{}) {
var i Iteration
switch c := c.(type) {
case []int: m := make([]int, len(c))
i = func(k, x interface{}) { m[k] = t.GetValue(x) }
n = m
case map[int] int: m := make(map[int] int)
i = func(k, x interface{}) { m[k] = t.GetValue(x) }
n = m
}
if i != nil {
Wait(func(done chan bool) {
Each(c, i)
done <- true
})
}
return
}
Thursday, 30 May 13
package main
import "fmt"
import . "map_reduce"
func main() {
m := "%v = %v, sum = %vn"
s := []int{0, 1, 2, 3, 4, 5}
sum := func(x, y interface{}) interface{} { return x.(int) + y.(int) }
d := Map(s, func(x interface{}) interface{} { return x.(int) * 2 })
x := <- Combination(sum).Reduce(s, 0)
fmt.Printf("s", s, x)
x = <- Combination(sum).Reduce(d, 0)
fmt.Printf("d", d, x)
}
produces:
s = [0 1 2 3 4 5], sum = 15
c = [0 2 4 6 8 10], sum = 30
Thursday, 30 May 13
software machines
Thursday, 30 May 13
synchronisation
Thursday, 30 May 13
package clock
import "syscall"
type Clock struct {
Period int64
Count chan int64
Control chan bool
active bool
}
Thursday, 30 May 13
package clock
import "syscall"
func (c *Clock) Start() {
if !c.active {
go func() {
c.active = true
for i := int64(0); ; i++ {
select {
case c.active = <- c.Control:
default:
if c.active {
c.Count <- i
}
syscall.Sleep(c.Period)
}
}
}()
}
}
Thursday, 30 May 13
package main
import . "clock"
func main() {
c := Clock{1000, make(chan int64), make(chan bool), false}
c.Start()
for i := 0; i < 3; i++ {
println("pulse value", <-c.Count, "from clock")
}
println("disabling clock")
c.Control <- false
syscall.Sleep(1000000)
println("restarting clock")
c.Control <- true
println("pulse value", <-c.Count, "from clock")
}
Thursday, 30 May 13
OSX 10.6.2 Intel Atom 270 @ 1.6GHz:
pulse value 0 from clock
pulse value 1 from clock
pulse value 2 from clock
disabling clock
restarting clock
pulse value 106 from clock
OSX 10.6.7 Intel Core 2 Duo @ 2.4GHz:
pulse value 0 from clock
pulse value 1 from clock
pulse value 2 from clock
disabling clock
restarting clock
pulse value 154 from clock
Thursday, 30 May 13
instruction set
Thursday, 30 May 13
operations
CISC
RISC
VLIW
Thursday, 30 May 13
package instructions
import "fmt"
type Operation func(o []int)
type Executable interface {
Opcode() int
Operands() []int
Execute(op Operation)
}
const INVALID_OPCODE = -1
type Program []Executable
func (p Program) Disassemble(a Assembler) {
for _, v := range p {
fmt.Println(a.Disassemble(v))
}
}
Thursday, 30 May 13
package instructions
type Instruction []int
func (i Instruction) Opcode() int {
if len(i) == 0 {
return INVALID_OPCODE
}
return i[0]
}
func (i Instruction) Operands() []int {
if len(i) < 2 {
return []int{}
}
return i[1:]
}
func (i Instruction) Execute(op Operation) {
op(i.Operands())
}
Thursday, 30 May 13
package instructions
type Assembler struct {
opcodes map[string] int
names map[int] string
}
func NewAssember(names... string) (a Assembler) {
a = Assembler{
opcodes: make(map[string] int),
names:make(map[int] string),
}
a.Define(names...)
return
}
func (a Assembler) Define(names... string) {
for _, name := range names {
a.opcodes[name] = len(a.names)
a.names[len(a.names)] = name
}
}
Thursday, 30 May 13
package instructions
func (a Assembler) Assemble(name string, params... int) (i Instruction) {
i = make(Instruction, len(params) + 1)
if opcode, ok := a.opcodes[name]; ok {
i[0] = opcode
} else {
i[0] = INVALID_OPCODE
}
copy(i[1:], params)
return
}
Thursday, 30 May 13
package instructions
import "fmt"
func (a Assembler) Disassemble(e Executable) (s string) {
if name, ok := a.names[e.Opcode()]; ok {
s = name
if params := e.Operands(); len(params) > 0 {
s = fmt.Sprintf("%vt%v", s, params[0])
for _, v := range params[1:] {
s = fmt.Sprintf("%v, %v", s, v)
}
}
} else {
s = "unknown"
}
return
}
Thursday, 30 May 13
package main
import . "instructions"
func main() {
a := NewAssembler("noop", "load", "store")
p := Program{ a.Assemble("noop"),
a.Assemble("load", 1),
a.Assemble("store", 1, 2),
a.Assemble("invalid", 3, 4, 5) }
p.Disassemble(a)
for _, v := range p {
if len(v.Operands()) == 2 {
v.Execute(func(o []int) {
o[0] += o[1]
})
println("op =", v.Opcode(), "result =", v.Operands()[0])
}
}
}
Thursday, 30 May 13
produces:
noop
load 1
store 1, 2
unknown
op = 2 result = 3
Thursday, 30 May 13
processor core
Thursday, 30 May 13
package processor
import . "instructions"
const PROCESSOR_READY = 0
const PROCESSOR_BUSY = 1
const CALL_STACK_UNDERFLOW = 2
const CALL_STACK_OVERFLOW = 4
const ILLEGAL_OPERATION = 8
const INVALID_ADDRESS = 16
type Processor interface {
Run(p []Executable)
}
type Core struct {
Running bool
PC, Flags, Ticks int
CS, M []int
OP Executable "Loaded OpCode"
I chan Executable "Interrupts"
}
Thursday, 30 May 13
package processor
import . "instructions"
func NewCore(CSS, MSS int, I chan Executable) *Core {
return &Core{
CS:make([]int, CSS)},
M: make([]int, MSS),
I: I,
}
}
func (c *Core) Reset() {
c.Running = false
c.Flags = PROCESSOR_READY
}
func (c *Core) Goto(addr int) {
c.PC = addr
}
Thursday, 30 May 13
package processor
func (c *Core) Call(addr int) {
top := len(c.CS)
if top >= cap(c.CS) - 1 { panic(CALL_STACK_OVERFLOW) }
c.CS = c.CS[:top + 1]
c.CS[top] = c.PC
c.PC = addr
}
func (c *Core) TailCall(addr int) {
c.CS[len(c.CS) - 1] = c.PC
c.PC = addr
}
func (c *Core) Return() {
top := len(c.CS)
if top == 0 { panic(CALL_STACK_UNDERFLOW) }
c.PC, c.CS = c.CS[top - 1], c.CS[:top]
}
Thursday, 30 May 13
package processor
import . "instructions"
func (c *Core) Run(p []Executable, dispatchers... func(c *Core)) {
defer func() {
c.Running = false
if x := recover(); x != nil { c.Flags &= x.(int) }
}()
switch {
case c.Running: panic(PROCESSOR_BUSY)
case len(dispatchers) == 0: panic(PROCESSOR_READY)
default:
c.Running = true
c.BusyLoop(dispatchers...)
}
}
func (c *Core) LoadInstruction(program []Executable) {
if c.PC >= len(program) { panic(PROCESSOR_READY) }
c.Executable = program[c.PC]
c.PC++
}
Thursday, 30 May 13
package processor
import . "instructions"
func (c *Core) BusyLoop(p []Executable, dispatchers... func(c *Core)) {
select {
case interrupt <- c.I:
op, pc := c.OP, c.PC
for c.PC = 0; c.Running; c.Ticks++ {
for _, f := range dispatchers { f(c) }
c.LoadInstruction(p)
}
c.OP, c.PC = op, pc
default:
for c.PC = 0; c.Running; c.Ticks++ {
c.LoadInstruction(p)
for _, f := range dispatchers { f(c) }
}
}
}
Thursday, 30 May 13
package processor
import . "instructions"
func (c *Core) RunExclusive(p []Executable, tracers... func(c *Core)) {
defer func() {
c.Running = false
if x := recover(); x != nil { c.Flags &= x.(int) }
}()
if c.Running { panic(PROCESSOR_BUSY) }
case len(dispatchers) == 0: panic(PROCESSOR_READY)
c.Running = true
for c.PC = 0; c.Running; c.Ticks++ {
c.LoadInstruction(p)
for _, f := range tracers { f(c) }
}
}
Thursday, 30 May 13
package main
import . "processor"
import . "instructions"
const( CALL = iota
GOTO
MOVE
RETURN
)
c := NewCore(10, 8, nil)
var dispatcher = func(c *Core) {
switch c.Opcode() {
case CALL: c.Execute(func(o []int) { c.Call(o[0]) })
case GOTO: c.Execute(func(o []int) { c.Goto(o[0]) })
case MOVE: c.Execute(func(o []int) { c.Goto(c.PC + o[0]) })
case RETURN: c.Execute(func(o []int) { c.Return() })
default: panic(ILLEGAL_OPERATION)
}
}
Thursday, 30 May 13
func main() {
p := []Executable{ Instruction{ CALL, 2 },
Instruction{ GOTO, 5 },
Instruction{ MOVE, 2 },
Instruction{ RETURN },
Instruction{ MOVE, -1 } }
c.RunExclusive(p, dispatcher)
fmt.Printf("Instructions Executed: %vnPC = %vn", c.Ticks, c.PC)
if c.Flags | PROCESSOR_READY == PROCESSOR_READY {
fmt.Println("Core Ready")
} else {
fmt.Println("Core Error:", c.Flags)
}
}
produces:
Instructions Executed: 2
PC = 5
Core Ready
Thursday, 30 May 13
accumulator machine
1-operand instructions
data from memory combined with accumulator
result stored in accumulator
Thursday, 30 May 13
package accmachine
import . "processor"
const (
CONSTANT = iota
LOAD_VALUE
STORE_VALUE
ADD
)
type AccMachine struct {
Core
AC int
}
func NewAccMachine(CSSize, MSize int, I chan Executable) *AccMachine {
return &AccMachine{ Core: NewCore(CSSize, MSize, I) }
}
Thursday, 30 May 13
package accmachine
import . "processor"
func (a *AccMachine) Run(program []Executable) {
a.RunExclusive(program, func() {
switch a.Opcode() {
case CONSTANT: a.Execute(func(o []int) { a.AC = o[0] })
case LOAD_VALUE: a.Execute(func(o []int) { a.AC = a.M[o[0]] })
case STORE_VALUE: a.Execute(func(o []int) { a.M[o[0]] = a.AC })
case ADD: a.Execute(func(o []int) { a.AC += a.M[o[0]] })
default: panic(ILLEGAL_OPERATION)
}
})
}
Thursday, 30 May 13
package main
import . "accmachine"
import . "instructions"
func main() {
a := NewAccMachine(10, 8, nil)
p := []Executable{ Instruction{CONSTANT, 27},
Instruction{STORE_VALUE, 0},
Instruction{CONSTANT, 13},
Instruction{STORE_VALUE, 1},
Instruction{CONSTANT, 10},
Instruction{ADD, 1},
Instruction{ADD, 0},
Instruction{STORE_VALUE, 2} }
a.Run(p)
fmt.Println("accumulated value =", a.AC)
}
produces:
accumulated value = 50
Thursday, 30 May 13
stack machine
0-operand instructions
data popped from stack
results pushed on stack
Thursday, 30 May 13
package smachine
import . "processor"
const (
CONSTANT = iota
PUSH_VALUE
POP_VALUE
ADD
)
type StackMachine struct {
Core
DS []int
}
func NewStackM(CSSize, DSSize, MSize int, I chan Executable) *StackMachine {
return &StackMachine{DS: make([]int, 0, DSSize),
Core: NewCore(CSSize, MSize, I) }
}
Thursday, 30 May 13
package smachine
import . "processor"
func (s *StackMachine) Push(v int) {
top := len(s.DS)
s.DS, s.DS[top] = s.DS[:top + 1], v
}
func (s *StackMachine) Pop(addr int) {
top := len(s.DS) - 1
s.M[addr], s.DS = s.DS[top], s.DS[:top]
}
Thursday, 30 May 13
package smachine
import . "processor"
func (s *StackMachine) Run(program []Executable) {
s.RunExclusive(program, func() {
switch s.Opcode() {
case CONSTANT: s.Execute(func(o []int) { s.Push(o[0]) })
case PUSH_VALUE: s.Execute(func(o []int) { s.Push(s.M[o[0]]) })
case POP_VALUE: s.Execute(func(o []int) { s.Pop(s.M[o[0]]) })
case ADD: s.Execute(func(o []int) {
l := len(s.DS)
s.DS[l - 2] += s.DS[l - 1]
s.DS = s.DS[:l - 1]
})
default: panic(ILLEGAL_OPERATION)
}
})
}
Thursday, 30 May 13
package main
import . "smachine"
import . "instructions"
func main() {
s := NewStackM(10, 10, 8, nil)
p := []Executable{ Instruction{CONSTANT, 27},
Instruction{CONSTANT, 13},
Instruction{CONSTANT, 10},
Instruction{ADD},
Instruction{ADD} }
s.Run(p)
fmt.Println("data stack =", s.DS)
}
produces:
registers = [50 13 10 0 0 0 0 0 0 0]
Thursday, 30 May 13
register machine
multi-operand instructions
data read from memory into registers
operator combines registers and stores
Thursday, 30 May 13
package rmachine
import . "processor"
const (
CONSTANT = iota
LOAD_VALUE
STORE_VALUE
ADD
)
type RMachine struct {
Core
R []int
}
func NewRMachine(CSSize, RSize, MSize int, I chan Executable) *RMachine {
return &RMachine{ Core: NewCore(CSSize, MSize, I),
R: make([]int, RSize) }
}
Thursday, 30 May 13
package rmachine
import . "processor"
func (r *RMachine) Run(program []Executable) {
r.RunExclusive(program, func() {
switch r.Opcode() {
case CONSTANT: r.Execute(func(o []int) { r.R[o[0]] = o[1] })
case LOAD_VALUE: r.Execute(func(o []int) { r.R[o[0]] = r.M[o[1]] })
case STORE_VALUE: r.Execute(func(o []int) { r.M[o[0]] = r.R[o[1]] })
case ADD: r.Execute(func(o []int) { r.R[o[0]] += r.R[o[1]] })
default: panic(ILLEGAL_OPERATION)
}
})
}
Thursday, 30 May 13
package main
import . "rmachine"
import . "instructions"
func main() {
r := NewRMachine(10, 10, 8, nil)
p := []Executable{ Instruction{CONSTANT, 0, 27},
Instruction{CONSTANT, 1, 13},
Instruction{CONSTANT, 2, 10},
Instruction{ADD, 0, 1},
Instruction{ADD, 0, 2} }
r.Run(p)
fmt.Println("registers =", r.R)
}
produces:
registers = [50 13 10 0 0 0 0 0 0 0]
Thursday, 30 May 13
vector machine
multi-operand instructions
data vectors read from memory into registers
operations combine registers
Thursday, 30 May 13
package vmachine
import . "processor"
const (
CONSTANT = iota
LOAD_VALUE
STORE_VALUE
ADD
)
type VMachine struct {
Core
R [][]int
}
func NewVMachine(CSSize, RSize, MSize int, I chan Executable) *VMachine {
return &VectorMachine{ Core: NewCore(CSSize, MSize),
make([][]int, RSize) }
}
Thursday, 30 May 13
package vmachine
import . "processor"
func (v *VMachine) Load(r int, m []int) {
v.R[r] = make([]int, len(m))
copy(v.R[r], m)
}
Thursday, 30 May 13
package vmachine
import . "processor"
func (v *VMachine) Run(program []Executable) {
v.RunExclusive(program, func() {
switch v.Opcode() {
case CONSTANT: v.Execute(func(o []int) { v.Load(o[0], o[1:]) })
case STORE_VALUE: v.Execute(func(o []int) { copy(v.M[o[0]:], v.R[o[1]]) })
case LOAD_VALUE: v.Execute(func(o []int) {
v.Load(o[0], v.M[o[1]:o[1] + o[2]])
})
case ADD: v.Execute(func(o []int) {
a, b := v.R[o[0]], v.R[o[1]]
count := len(a)
if len(b) < len(a) { count := len(b) }
for ; count > 0; count-- { a[i] += b[i] }
})
default: panic(ILLEGAL_OPERATION)
}
})
}
Thursday, 30 May 13
package main
import . "vmachine"
import . "instructions"
func main() {
r := NewVMachine(10, 10, 8, nil)
p := []Executable{ Instruction{CONSTANT, 0, 27},
Instruction{CONSTANT, 1, 13},
Instruction{CONSTANT, 2, 10},
Instruction{ADD, 0, 1},
Instruction{ADD, 0, 2} }
r.Run(p)
fmt.Println("registers =", r.R)
}
produces:
vectors = [[50 50 50] [13 10 27] [10 27 13] [] [] [] [] [] [] []]
Thursday, 30 May 13
related projects
gospeed
raw - slices - lists - chains - sexp
wendigo
Thursday, 30 May 13
related projects
gospeed
typelib
wendigo
Thursday, 30 May 13
finding out more
http://golang.org/
twitter://#golang
http://slides.games-with-brains.net/
http://github.com/feyeleanor/
wikipedia or google
Thursday, 30 May 13

Más contenido relacionado

La actualidad más candente

TensorFlow in Practice
TensorFlow in PracticeTensorFlow in Practice
TensorFlow in Practiceindico data
 
Gentlest Introduction to Tensorflow
Gentlest Introduction to TensorflowGentlest Introduction to Tensorflow
Gentlest Introduction to TensorflowKhor SoonHin
 
Python легко и просто. Красиво решаем повседневные задачи
Python легко и просто. Красиво решаем повседневные задачиPython легко и просто. Красиво решаем повседневные задачи
Python легко и просто. Красиво решаем повседневные задачиMaxim Kulsha
 
Explanation on Tensorflow example -Deep mnist for expert
Explanation on Tensorflow example -Deep mnist for expertExplanation on Tensorflow example -Deep mnist for expert
Explanation on Tensorflow example -Deep mnist for expert홍배 김
 
Gentlest Introduction to Tensorflow - Part 3
Gentlest Introduction to Tensorflow - Part 3Gentlest Introduction to Tensorflow - Part 3
Gentlest Introduction to Tensorflow - Part 3Khor SoonHin
 
Gentlest Introduction to Tensorflow - Part 2
Gentlest Introduction to Tensorflow - Part 2Gentlest Introduction to Tensorflow - Part 2
Gentlest Introduction to Tensorflow - Part 2Khor SoonHin
 
파이썬으로 해보는 이미지 처리
파이썬으로 해보는 이미지 처리파이썬으로 해보는 이미지 처리
파이썬으로 해보는 이미지 처리Kyunghoon Kim
 
Excel function
Excel functionExcel function
Excel functionSirajRock
 
imager package in R and examples..
imager package in R and examples..imager package in R and examples..
imager package in R and examples..Dr. Volkan OBAN
 
NTU ML TENSORFLOW
NTU ML TENSORFLOWNTU ML TENSORFLOW
NTU ML TENSORFLOWMark Chang
 
Drinking the free kool-aid
Drinking the free kool-aidDrinking the free kool-aid
Drinking the free kool-aidDavid Hoyt
 
The groovy puzzlers (as Presented at Gr8Conf US 2014)
The groovy puzzlers (as Presented at Gr8Conf US 2014)The groovy puzzlers (as Presented at Gr8Conf US 2014)
The groovy puzzlers (as Presented at Gr8Conf US 2014)GroovyPuzzlers
 
Programming in lua STRING AND ARRAY
Programming in lua STRING AND ARRAYProgramming in lua STRING AND ARRAY
Programming in lua STRING AND ARRAYvikram mahendra
 
The Ring programming language version 1.5.1 book - Part 61 of 180
The Ring programming language version 1.5.1 book - Part 61 of 180The Ring programming language version 1.5.1 book - Part 61 of 180
The Ring programming language version 1.5.1 book - Part 61 of 180Mahmoud Samir Fayed
 
Python Cheat Sheet
Python Cheat SheetPython Cheat Sheet
Python Cheat SheetGlowTouch
 

La actualidad más candente (20)

TensorFlow in Practice
TensorFlow in PracticeTensorFlow in Practice
TensorFlow in Practice
 
Gentlest Introduction to Tensorflow
Gentlest Introduction to TensorflowGentlest Introduction to Tensorflow
Gentlest Introduction to Tensorflow
 
Python легко и просто. Красиво решаем повседневные задачи
Python легко и просто. Красиво решаем повседневные задачиPython легко и просто. Красиво решаем повседневные задачи
Python легко и просто. Красиво решаем повседневные задачи
 
Explanation on Tensorflow example -Deep mnist for expert
Explanation on Tensorflow example -Deep mnist for expertExplanation on Tensorflow example -Deep mnist for expert
Explanation on Tensorflow example -Deep mnist for expert
 
Gentlest Introduction to Tensorflow - Part 3
Gentlest Introduction to Tensorflow - Part 3Gentlest Introduction to Tensorflow - Part 3
Gentlest Introduction to Tensorflow - Part 3
 
Gentlest Introduction to Tensorflow - Part 2
Gentlest Introduction to Tensorflow - Part 2Gentlest Introduction to Tensorflow - Part 2
Gentlest Introduction to Tensorflow - Part 2
 
파이썬으로 해보는 이미지 처리
파이썬으로 해보는 이미지 처리파이썬으로 해보는 이미지 처리
파이썬으로 해보는 이미지 처리
 
Excel function
Excel functionExcel function
Excel function
 
imager package in R and examples..
imager package in R and examples..imager package in R and examples..
imager package in R and examples..
 
NTU ML TENSORFLOW
NTU ML TENSORFLOWNTU ML TENSORFLOW
NTU ML TENSORFLOW
 
ProgrammingwithGOLang
ProgrammingwithGOLangProgrammingwithGOLang
ProgrammingwithGOLang
 
GANs
GANsGANs
GANs
 
Drinking the free kool-aid
Drinking the free kool-aidDrinking the free kool-aid
Drinking the free kool-aid
 
The groovy puzzlers (as Presented at Gr8Conf US 2014)
The groovy puzzlers (as Presented at Gr8Conf US 2014)The groovy puzzlers (as Presented at Gr8Conf US 2014)
The groovy puzzlers (as Presented at Gr8Conf US 2014)
 
Programming in lua STRING AND ARRAY
Programming in lua STRING AND ARRAYProgramming in lua STRING AND ARRAY
Programming in lua STRING AND ARRAY
 
662305 LAB13
662305 LAB13662305 LAB13
662305 LAB13
 
Basic Calculus in R.
Basic Calculus in R. Basic Calculus in R.
Basic Calculus in R.
 
The Ring programming language version 1.5.1 book - Part 61 of 180
The Ring programming language version 1.5.1 book - Part 61 of 180The Ring programming language version 1.5.1 book - Part 61 of 180
The Ring programming language version 1.5.1 book - Part 61 of 180
 
Python collections
Python collectionsPython collections
Python collections
 
Python Cheat Sheet
Python Cheat SheetPython Cheat Sheet
Python Cheat Sheet
 

Similar a GoLightly - a customisable virtual machine written in Go

Something about Golang
Something about GolangSomething about Golang
Something about GolangAnton Arhipov
 
Go: It's Not Just For Google
Go: It's Not Just For GoogleGo: It's Not Just For Google
Go: It's Not Just For GoogleEleanor McHugh
 
Python programming workshop session 3
Python programming workshop session 3Python programming workshop session 3
Python programming workshop session 3Abdul Haseeb
 
Python avanzado - parte 1
Python avanzado - parte 1Python avanzado - parte 1
Python avanzado - parte 1coto
 
Gentle Introduction to Functional Programming
Gentle Introduction to Functional ProgrammingGentle Introduction to Functional Programming
Gentle Introduction to Functional ProgrammingSaurabh Singh
 
Use Applicative where applicable!
Use Applicative where applicable!Use Applicative where applicable!
Use Applicative where applicable!Hermann Hueck
 
Kristhyan kurtlazartezubia evidencia1-metodosnumericos
Kristhyan kurtlazartezubia evidencia1-metodosnumericosKristhyan kurtlazartezubia evidencia1-metodosnumericos
Kristhyan kurtlazartezubia evidencia1-metodosnumericosKristhyanAndreeKurtL
 
Laziness, trampolines, monoids and other functional amenities: this is not yo...
Laziness, trampolines, monoids and other functional amenities: this is not yo...Laziness, trampolines, monoids and other functional amenities: this is not yo...
Laziness, trampolines, monoids and other functional amenities: this is not yo...Codemotion
 
Geeks Anonymes - Le langage Go
Geeks Anonymes - Le langage GoGeeks Anonymes - Le langage Go
Geeks Anonymes - Le langage GoGeeks Anonymes
 
Implementing Virtual Machines in Go & C
Implementing Virtual Machines in Go & CImplementing Virtual Machines in Go & C
Implementing Virtual Machines in Go & CEleanor McHugh
 
20181020 advanced higher-order function
20181020 advanced higher-order function20181020 advanced higher-order function
20181020 advanced higher-order functionChiwon Song
 
Arrow 101 - Kotlin funcional com Arrow
Arrow 101 - Kotlin funcional com ArrowArrow 101 - Kotlin funcional com Arrow
Arrow 101 - Kotlin funcional com ArrowLeandro Ferreira
 
Functional JS for everyone - 4Developers
Functional JS for everyone - 4DevelopersFunctional JS for everyone - 4Developers
Functional JS for everyone - 4DevelopersBartek Witczak
 
Redux saga: managing your side effects. Also: generators in es6
Redux saga: managing your side effects. Also: generators in es6Redux saga: managing your side effects. Also: generators in es6
Redux saga: managing your side effects. Also: generators in es6Ignacio Martín
 
TDC2016SP - Código funcional em Java: superando o hype
TDC2016SP - Código funcional em Java: superando o hypeTDC2016SP - Código funcional em Java: superando o hype
TDC2016SP - Código funcional em Java: superando o hypetdc-globalcode
 
Python cheatsheat.pdf
Python cheatsheat.pdfPython cheatsheat.pdf
Python cheatsheat.pdfHimoZZZ
 
Implementing Software Machines in Go and C
Implementing Software Machines in Go and CImplementing Software Machines in Go and C
Implementing Software Machines in Go and CEleanor McHugh
 

Similar a GoLightly - a customisable virtual machine written in Go (20)

Something about Golang
Something about GolangSomething about Golang
Something about Golang
 
Go: It's Not Just For Google
Go: It's Not Just For GoogleGo: It's Not Just For Google
Go: It's Not Just For Google
 
Python programming workshop session 3
Python programming workshop session 3Python programming workshop session 3
Python programming workshop session 3
 
Python avanzado - parte 1
Python avanzado - parte 1Python avanzado - parte 1
Python avanzado - parte 1
 
About Go
About GoAbout Go
About Go
 
Gentle Introduction to Functional Programming
Gentle Introduction to Functional ProgrammingGentle Introduction to Functional Programming
Gentle Introduction to Functional Programming
 
Use Applicative where applicable!
Use Applicative where applicable!Use Applicative where applicable!
Use Applicative where applicable!
 
Kristhyan kurtlazartezubia evidencia1-metodosnumericos
Kristhyan kurtlazartezubia evidencia1-metodosnumericosKristhyan kurtlazartezubia evidencia1-metodosnumericos
Kristhyan kurtlazartezubia evidencia1-metodosnumericos
 
Laziness, trampolines, monoids and other functional amenities: this is not yo...
Laziness, trampolines, monoids and other functional amenities: this is not yo...Laziness, trampolines, monoids and other functional amenities: this is not yo...
Laziness, trampolines, monoids and other functional amenities: this is not yo...
 
07012023.pptx
07012023.pptx07012023.pptx
07012023.pptx
 
Geeks Anonymes - Le langage Go
Geeks Anonymes - Le langage GoGeeks Anonymes - Le langage Go
Geeks Anonymes - Le langage Go
 
Implementing Virtual Machines in Go & C
Implementing Virtual Machines in Go & CImplementing Virtual Machines in Go & C
Implementing Virtual Machines in Go & C
 
Blocks+gcd入門
Blocks+gcd入門Blocks+gcd入門
Blocks+gcd入門
 
20181020 advanced higher-order function
20181020 advanced higher-order function20181020 advanced higher-order function
20181020 advanced higher-order function
 
Arrow 101 - Kotlin funcional com Arrow
Arrow 101 - Kotlin funcional com ArrowArrow 101 - Kotlin funcional com Arrow
Arrow 101 - Kotlin funcional com Arrow
 
Functional JS for everyone - 4Developers
Functional JS for everyone - 4DevelopersFunctional JS for everyone - 4Developers
Functional JS for everyone - 4Developers
 
Redux saga: managing your side effects. Also: generators in es6
Redux saga: managing your side effects. Also: generators in es6Redux saga: managing your side effects. Also: generators in es6
Redux saga: managing your side effects. Also: generators in es6
 
TDC2016SP - Código funcional em Java: superando o hype
TDC2016SP - Código funcional em Java: superando o hypeTDC2016SP - Código funcional em Java: superando o hype
TDC2016SP - Código funcional em Java: superando o hype
 
Python cheatsheat.pdf
Python cheatsheat.pdfPython cheatsheat.pdf
Python cheatsheat.pdf
 
Implementing Software Machines in Go and C
Implementing Software Machines in Go and CImplementing Software Machines in Go and C
Implementing Software Machines in Go and C
 

Más de Eleanor McHugh

[2023] Putting the R! in R&D.pdf
[2023] Putting the R! in R&D.pdf[2023] Putting the R! in R&D.pdf
[2023] Putting the R! in R&D.pdfEleanor McHugh
 
Generics, Reflection, and Efficient Collections
Generics, Reflection, and Efficient CollectionsGenerics, Reflection, and Efficient Collections
Generics, Reflection, and Efficient CollectionsEleanor McHugh
 
The Relevance of Liveness - Biometrics and Data Integrity
The Relevance of Liveness - Biometrics and Data IntegrityThe Relevance of Liveness - Biometrics and Data Integrity
The Relevance of Liveness - Biometrics and Data IntegrityEleanor McHugh
 
The Browser Environment - A Systems Programmer's Perspective [sinatra edition]
The Browser Environment - A Systems Programmer's Perspective [sinatra edition]The Browser Environment - A Systems Programmer's Perspective [sinatra edition]
The Browser Environment - A Systems Programmer's Perspective [sinatra edition]Eleanor McHugh
 
The Browser Environment - A Systems Programmer's Perspective
The Browser Environment - A Systems Programmer's PerspectiveThe Browser Environment - A Systems Programmer's Perspective
The Browser Environment - A Systems Programmer's PerspectiveEleanor McHugh
 
Go for the paranoid network programmer, 3rd edition
Go for the paranoid network programmer, 3rd editionGo for the paranoid network programmer, 3rd edition
Go for the paranoid network programmer, 3rd editionEleanor McHugh
 
An introduction to functional programming with Go [redux]
An introduction to functional programming with Go [redux]An introduction to functional programming with Go [redux]
An introduction to functional programming with Go [redux]Eleanor McHugh
 
An introduction to functional programming with go
An introduction to functional programming with goAn introduction to functional programming with go
An introduction to functional programming with goEleanor McHugh
 
Implementing virtual machines in go & c 2018 redux
Implementing virtual machines in go & c 2018 reduxImplementing virtual machines in go & c 2018 redux
Implementing virtual machines in go & c 2018 reduxEleanor McHugh
 
Identity & trust in Monitored Spaces
Identity & trust in Monitored SpacesIdentity & trust in Monitored Spaces
Identity & trust in Monitored SpacesEleanor McHugh
 
Don't Ask, Don't Tell - The Virtues of Privacy By Design
Don't Ask, Don't Tell - The Virtues of Privacy By DesignDon't Ask, Don't Tell - The Virtues of Privacy By Design
Don't Ask, Don't Tell - The Virtues of Privacy By DesignEleanor McHugh
 
Don't ask, don't tell the virtues of privacy by design
Don't ask, don't tell   the virtues of privacy by designDon't ask, don't tell   the virtues of privacy by design
Don't ask, don't tell the virtues of privacy by designEleanor McHugh
 
Anonymity, identity, trust
Anonymity, identity, trustAnonymity, identity, trust
Anonymity, identity, trustEleanor McHugh
 
Going Loopy - Adventures in Iteration with Google Go
Going Loopy - Adventures in Iteration with Google GoGoing Loopy - Adventures in Iteration with Google Go
Going Loopy - Adventures in Iteration with Google GoEleanor McHugh
 
Distributed Ledgers: Anonymity & Immutability at Scale
Distributed Ledgers: Anonymity & Immutability at ScaleDistributed Ledgers: Anonymity & Immutability at Scale
Distributed Ledgers: Anonymity & Immutability at ScaleEleanor McHugh
 
Go for the paranoid network programmer, 2nd edition
Go for the paranoid network programmer, 2nd editionGo for the paranoid network programmer, 2nd edition
Go for the paranoid network programmer, 2nd editionEleanor McHugh
 
Going Loopy: Adventures in Iteration with Go
Going Loopy: Adventures in Iteration with GoGoing Loopy: Adventures in Iteration with Go
Going Loopy: Adventures in Iteration with GoEleanor McHugh
 
Finding a useful outlet for my many Adventures in go
Finding a useful outlet for my many Adventures in goFinding a useful outlet for my many Adventures in go
Finding a useful outlet for my many Adventures in goEleanor McHugh
 
Anonymity, trust, accountability
Anonymity, trust, accountabilityAnonymity, trust, accountability
Anonymity, trust, accountabilityEleanor McHugh
 

Más de Eleanor McHugh (20)

[2023] Putting the R! in R&D.pdf
[2023] Putting the R! in R&D.pdf[2023] Putting the R! in R&D.pdf
[2023] Putting the R! in R&D.pdf
 
Generics, Reflection, and Efficient Collections
Generics, Reflection, and Efficient CollectionsGenerics, Reflection, and Efficient Collections
Generics, Reflection, and Efficient Collections
 
The Relevance of Liveness - Biometrics and Data Integrity
The Relevance of Liveness - Biometrics and Data IntegrityThe Relevance of Liveness - Biometrics and Data Integrity
The Relevance of Liveness - Biometrics and Data Integrity
 
The Browser Environment - A Systems Programmer's Perspective [sinatra edition]
The Browser Environment - A Systems Programmer's Perspective [sinatra edition]The Browser Environment - A Systems Programmer's Perspective [sinatra edition]
The Browser Environment - A Systems Programmer's Perspective [sinatra edition]
 
The Browser Environment - A Systems Programmer's Perspective
The Browser Environment - A Systems Programmer's PerspectiveThe Browser Environment - A Systems Programmer's Perspective
The Browser Environment - A Systems Programmer's Perspective
 
Go for the paranoid network programmer, 3rd edition
Go for the paranoid network programmer, 3rd editionGo for the paranoid network programmer, 3rd edition
Go for the paranoid network programmer, 3rd edition
 
An introduction to functional programming with Go [redux]
An introduction to functional programming with Go [redux]An introduction to functional programming with Go [redux]
An introduction to functional programming with Go [redux]
 
An introduction to functional programming with go
An introduction to functional programming with goAn introduction to functional programming with go
An introduction to functional programming with go
 
Implementing virtual machines in go & c 2018 redux
Implementing virtual machines in go & c 2018 reduxImplementing virtual machines in go & c 2018 redux
Implementing virtual machines in go & c 2018 redux
 
Identity & trust in Monitored Spaces
Identity & trust in Monitored SpacesIdentity & trust in Monitored Spaces
Identity & trust in Monitored Spaces
 
Don't Ask, Don't Tell - The Virtues of Privacy By Design
Don't Ask, Don't Tell - The Virtues of Privacy By DesignDon't Ask, Don't Tell - The Virtues of Privacy By Design
Don't Ask, Don't Tell - The Virtues of Privacy By Design
 
Don't ask, don't tell the virtues of privacy by design
Don't ask, don't tell   the virtues of privacy by designDon't ask, don't tell   the virtues of privacy by design
Don't ask, don't tell the virtues of privacy by design
 
Anonymity, identity, trust
Anonymity, identity, trustAnonymity, identity, trust
Anonymity, identity, trust
 
Going Loopy - Adventures in Iteration with Google Go
Going Loopy - Adventures in Iteration with Google GoGoing Loopy - Adventures in Iteration with Google Go
Going Loopy - Adventures in Iteration with Google Go
 
Distributed Ledgers: Anonymity & Immutability at Scale
Distributed Ledgers: Anonymity & Immutability at ScaleDistributed Ledgers: Anonymity & Immutability at Scale
Distributed Ledgers: Anonymity & Immutability at Scale
 
Hello Go
Hello GoHello Go
Hello Go
 
Go for the paranoid network programmer, 2nd edition
Go for the paranoid network programmer, 2nd editionGo for the paranoid network programmer, 2nd edition
Go for the paranoid network programmer, 2nd edition
 
Going Loopy: Adventures in Iteration with Go
Going Loopy: Adventures in Iteration with GoGoing Loopy: Adventures in Iteration with Go
Going Loopy: Adventures in Iteration with Go
 
Finding a useful outlet for my many Adventures in go
Finding a useful outlet for my many Adventures in goFinding a useful outlet for my many Adventures in go
Finding a useful outlet for my many Adventures in go
 
Anonymity, trust, accountability
Anonymity, trust, accountabilityAnonymity, trust, accountability
Anonymity, trust, accountability
 

Último

Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...panagenda
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality AssuranceInflectra
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesKari Kakkonen
 
2024 April Patch Tuesday
2024 April Patch Tuesday2024 April Patch Tuesday
2024 April Patch TuesdayIvanti
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPathCommunity
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI AgeCprime
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersRaghuram Pandurangan
 
Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rick Flair
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxLoriGlavin3
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity PlanDatabarracks
 
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesAssure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesThousandEyes
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxLoriGlavin3
 
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...Scott Andery
 
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentEmixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentPim van der Noll
 
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Mark Goldstein
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxLoriGlavin3
 
Manual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance AuditManual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance AuditSkynet Technologies
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfpanagenda
 

Último (20)

Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
Why device, WIFI, and ISP insights are crucial to supporting remote Microsoft...
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examples
 
2024 April Patch Tuesday
2024 April Patch Tuesday2024 April Patch Tuesday
2024 April Patch Tuesday
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to Hero
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI Age
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information Developers
 
Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity Plan
 
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesAssure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
 
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
Enhancing User Experience - Exploring the Latest Features of Tallyman Axis Lo...
 
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentEmixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
 
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
 
Manual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance AuditManual 508 Accessibility Compliance Audit
Manual 508 Accessibility Compliance Audit
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
 

GoLightly - a customisable virtual machine written in Go

  • 1. golightly a customisable virtual machine written in Go Eleanor McHugh http://slides.games-with-brains.net/ Thursday, 30 May 13
  • 2. portrait of an artist... physics major embedded controllers software reliability dynamic languages network scaling questionable taste in music http://github.com/feyeleanor Eleanor McHugh Thursday, 30 May 13
  • 3. go... small, safety-conscious systems language concurrency, closures & garbage collection consistently fast compilation Thursday, 30 May 13
  • 4. ...lightly agnostic virtual machine networks application performance matters non-viral open source license Thursday, 30 May 13
  • 5. agnostic no blessed programming languages flexible platform abstractions write once, run everywhere it matters Thursday, 30 May 13
  • 6. heterogeneous a system comprises many components components may differ in purpose and design but they cooperate to solve problems Thursday, 30 May 13
  • 7. networks machines cooperate by sending messages machine states can be serialised as messages messages transcend process and host boundaries Thursday, 30 May 13
  • 8. inspiration hardware design sensor and control networks field-programmable gate arrays Thursday, 30 May 13
  • 9. virtual machine emulate an existing system simulate an imagined system have dynamic control of system state Thursday, 30 May 13
  • 10. stack-based lambda calculus processor threaded value cells in a von neumann memory all operations are expressions are values lisp Thursday, 30 May 13
  • 11. stack-based processor threaded word definitions in a von neumann memory words thread primitives, word pointers and data forth Thursday, 30 May 13
  • 12. stack-based processor with instruction set harvard memory separates code and data class loaders convert bytecode to machine state jvm Thursday, 30 May 13
  • 13. linux kernel hypervisor intel X86 virtualisation with hardware execution QEMU virtual machine runs in user space kvm Thursday, 30 May 13
  • 15. package main import "fmt" const( HELLO string = "hello" WORLD string = "world" ) func main() { fmt.Println(HELLO, WORLD) } Thursday, 30 May 13
  • 17. package Integer type Int int func (i *Int) Add(x int) { *i += Int(x) } Thursday, 30 May 13
  • 18. package Integer type Buffer []Int func (b Buffer) Eq(o Buffer) (r bool) { if len(b) == len(o) { for i := len(b) - 1; i > 0; i-- { if b[i] != o[i] { return } } r = true } return } func (b Buffer) Swap(i, j int) { b[i], b[j] = b[j], b[i] } func (b Buffer) Clone() Buffer { s := make(Buffer, len(b)) copy(s, b) return s } func (b Buffer) Move(i, n int) { if n > len(b) - i { n = len(b) - i } segment_to_move := b[:i].Clone() copy(b, b[i:i + n]) copy(b[n:i + n], segment_to_move) } Thursday, 30 May 13
  • 19. package main import "Integer" func main() { i := Integer.Buffer{0, 1, 2, 3, 4, 5} b := i.Clone() b.Swap(1, 2) b.Move(3, 2) b[0].Add(3) println("b[:2] = {", b[0], ",", b[1], "}") } produces: b[0:2] = { 6, 4 } Thursday, 30 May 13
  • 20. package Integer import "testing" func TestSwap(t *testing.T) { i := Buffer{0, 1, 2, 3, 4, 5} b := i.Clone() b.Swap(1, 2) if !b[1:3].Eq(Buffer{2, 1}) { t.Fatalf("b[:5] = %v", b) } } func TestMove(t *testing.T) { i := Buffer{0, 1, 2, 3, 4, 5} b := i.Clone() b.Move(3, 2) if !b.Eq(Buffer{3, 4, 0, 1, 2, 5}) { t.Fatalf("b[:5] = %v", b) } } func TestAdd(t *testing.T) { i := Buffer{0, 1, 2, 3, 4, 5} b := i.Clone() b[0].Add(3) if b[0] != i[0] + 3 { t.Fatalf("b[:5] = %v", b) } } Thursday, 30 May 13
  • 22. package Vector import . "Integer" type Vector struct { Buffer } func (v *Vector) Clone() Vector { return Vector{v.Buffer.Clone()} } func (v *Vector) Slice(i, j int) Buffer { return v.Buffer[i:j] } Thursday, 30 May 13
  • 23. package Integer import "testing" func TestVectorSwap(t *testing.T) { i := Vector{Buffer{0, 1, 2, 3, 4, 5}} v := i.Clone() v.Swap(1, 2) r := Vector{Buffer{0, 2, 1, 3, 4, 5}} switch { case !v.Match(&r): fallthrough case !v.Buffer.Match(r.Buffer): t.Fatalf("b[:5] = %v", v) } } Thursday, 30 May 13
  • 24. package integer import "testing" func BenchmarkVectorClone6(b *testing.B) { v := Vector{Buffer{0, 1, 2, 3, 4, 5}} for i := 0; i < b.N; i++ { _ = v.Clone() } } func BenchmarkVectorSwap(b *testing.B) { b.StopTimer() v := Vector{Buffer{0, 1, 2, 3, 4, 5}} b.StartTimer() for i := 0; i < b.N; i++ { v.Swap(1, 2) } } Thursday, 30 May 13
  • 25. $ go test -test.bench="Benchmark" PASS integer.BenchmarkVectorSwap 200000000 8 ns/op integer.BenchmarkVectorClone6 10000000 300 ns/op Thursday, 30 May 13
  • 27. package adder type Adder interface { Add(j int) Subtract(j int) Result() interface{} } type Calculator interface { Adder Reset() } type AddingMachine struct { Memory interface{} Adder } Thursday, 30 May 13
  • 28. package adder type IAdder []int func (i IAdder) Add(j int) { i[0] += i[j] } func (i IAdder) Subtract(j int) { i[0] -= i[j] } func (i IAdder) Result() interface{} { return i[0] } func (i IAdder) Reset() { i[0] = *new(int) } Thursday, 30 May 13
  • 29. package adder import "testing" func TestIAdder(t *testing.T) { error := "Result %v != %v" i := IAdder{0, 1, 2} i.Add(1) if i.Result().(int) != 1 { t.Fatalf(error, i.Result(), 1) } i.Subtract(2) if i.Result().(int) != -1 { t.Fatalf(error, i.Result()), -1 } var r Calculator = IAdder{-1, 1, 2} for n, v := range r.(IAdder) { if i[n] != v { t.Fatalf("Adder %v should be %v", i, r) } } r.Reset() if r.Result().(int) != *new(int) { t.Fatalf(error, r.Result(), *new(int)) } } Thursday, 30 May 13
  • 30. package adder import "testing" func TestIAdder(t *testing.T) { error := "Result %v != %v" i := IAdder{0, 1, 2} i.Add(1) if i.Result() != 1 { t.Fatalf(error, i.Result(), 1) } i.Subtract(2) if i.Result() != -1 { t.Fatalf(error, i.Result()), -1 } var r Calculator = IAdder{-1, 1, 2} for n, v := range r.(IAdder) { if i[n] != v { t.Fatalf("Adder %v should be %v", i, r) } } r.Reset() if r.Result() != *new(int) { t.Fatalf(error, r.Result(), *new(int)) } } Thursday, 30 May 13
  • 31. package adder type FAdder []float32 func (f FAdder) Add(j int) { f[0] += f[j] } func (f FAdder) Subtract(j int) { f[0] -= f[j] } func (f FAdder) Result() interface{} { return f[0] } func (f FAdder) Reset() { f[0] = *new(float32) } Thursday, 30 May 13
  • 32. package adder import "testing" func TestFAdder(t *testing.T) { error := "Result %v != %v" f := FAdder{0.0, 1.0, 2.0} f.Add(1) if f.Result() != 1.0 { t.Fatalf(error, f.Result(), 1.0) } f.Subtract(2) if i.Result() != -1.0 { t.Fatalf(error, i.Result()), -1.0 } var r Calculator = FAdder{-1.0, 1.0, 2.0} for n, v := range r.(FAdder) { if f[n] != v { t.Fatalf("Adder %v should be %v", f, r) } } r.Reset() if r.Result() != *new(float32) { t.Fatalf(error, r.Result(), *new(float32)) } } Thursday, 30 May 13
  • 33. package adder import "testing" func TestAddingMachine(t *testing.T) { error := "Result %v != %v" a := &AddingMachine{ Adder: FAdder{0.0, 1.0, 2.0} } a.Add(1) if f, ok := a.Result().(float32); !ok { t.Fatal("Result should be a float32") } else if f != 1.0 { t.Fatalf(error, a.Result(), 1.0) } a.Subtract(2) if a.Result().(float32) != -1.0 { t.Fatalf(error, a.Result(), -1.0) } r := FAdder{-1.0, 1.0, 2.0} for n, v := range a.Adder.(FAdder) { if r[n] != v { t.Fatalf("Adder %v should be %v", a, r) } } } Thursday, 30 May 13
  • 35. goroutines concurrent execution stacks initialised with a closure scheduled automatically by the runtime Thursday, 30 May 13
  • 36. package main import "fmt" func main() { var c chan int c = make(chan int) go func() { for { fmt.Print(<-c) } }() for { select { case c <- 0: case c <- 1: } } } produces: 01100111010110... Thursday, 30 May 13
  • 37. package main import "fmt" func main() { var c chan int c = make(chan int, 16) go func() { for { fmt.Print(<-c) } }() go func() { select { case c <- 0: case c <- 1: } }() for {} } produces: 01100111010110... Thursday, 30 May 13
  • 38. package map_reduce type SignalSource func(status chan bool) func Wait(s SignalSource) { done := make(chan bool) defer close(done) go s(done) <-done } func WaitCount(count int, s SignalSource) { done := make(chan bool) defer close(done) go s(done) for i := 0; i < count; i++ { <- done } } Thursday, 30 May 13
  • 39. package map_reduce type Iteration func(k, x interface{}) func (i Iteration) apply(k, v interface{}, c chan bool) { go func() { i(k, v) c <- true }() } Thursday, 30 May 13
  • 40. package map_reduce func Each(c interface{}, f Iteration) { switch c := c.(type) { case []int: WaitCount(len(c), func(done chan bool) { for i, v := range c { f.apply(i, v, done) } }) case map[int] int: WaitCount(len(c), func(done chan bool) { for k, v := range c { f.apply(k, v, done) } }) } } Thursday, 30 May 13
  • 41. package map_reduce type Results chan interface{} type Combination func(x, y interface{}) interface{} func (f Combination) Reduce(c, s interface{}) (r Results) { r = make(Results) go func() { Each(c, func(k, x interface{}) { s = f(s, x) }) r <- s }() return } Thursday, 30 May 13
  • 42. package map_reduce type Transformation func(x interface{}) interface{} func (t Transformation) GetValue(x interface{}) interface{} { return t(x) } Thursday, 30 May 13
  • 43. func Map(c interface{}, t Transformation) (n interface{}) { var i Iteration switch c := c.(type) { case []int: m := make([]int, len(c)) i = func(k, x interface{}) { m[k] = t.GetValue(x) } n = m case map[int] int: m := make(map[int] int) i = func(k, x interface{}) { m[k] = t.GetValue(x) } n = m } if i != nil { Wait(func(done chan bool) { Each(c, i) done <- true }) } return } Thursday, 30 May 13
  • 44. package main import "fmt" import . "map_reduce" func main() { m := "%v = %v, sum = %vn" s := []int{0, 1, 2, 3, 4, 5} sum := func(x, y interface{}) interface{} { return x.(int) + y.(int) } d := Map(s, func(x interface{}) interface{} { return x.(int) * 2 }) x := <- Combination(sum).Reduce(s, 0) fmt.Printf("s", s, x) x = <- Combination(sum).Reduce(d, 0) fmt.Printf("d", d, x) } produces: s = [0 1 2 3 4 5], sum = 15 c = [0 2 4 6 8 10], sum = 30 Thursday, 30 May 13
  • 47. package clock import "syscall" type Clock struct { Period int64 Count chan int64 Control chan bool active bool } Thursday, 30 May 13
  • 48. package clock import "syscall" func (c *Clock) Start() { if !c.active { go func() { c.active = true for i := int64(0); ; i++ { select { case c.active = <- c.Control: default: if c.active { c.Count <- i } syscall.Sleep(c.Period) } } }() } } Thursday, 30 May 13
  • 49. package main import . "clock" func main() { c := Clock{1000, make(chan int64), make(chan bool), false} c.Start() for i := 0; i < 3; i++ { println("pulse value", <-c.Count, "from clock") } println("disabling clock") c.Control <- false syscall.Sleep(1000000) println("restarting clock") c.Control <- true println("pulse value", <-c.Count, "from clock") } Thursday, 30 May 13
  • 50. OSX 10.6.2 Intel Atom 270 @ 1.6GHz: pulse value 0 from clock pulse value 1 from clock pulse value 2 from clock disabling clock restarting clock pulse value 106 from clock OSX 10.6.7 Intel Core 2 Duo @ 2.4GHz: pulse value 0 from clock pulse value 1 from clock pulse value 2 from clock disabling clock restarting clock pulse value 154 from clock Thursday, 30 May 13
  • 53. package instructions import "fmt" type Operation func(o []int) type Executable interface { Opcode() int Operands() []int Execute(op Operation) } const INVALID_OPCODE = -1 type Program []Executable func (p Program) Disassemble(a Assembler) { for _, v := range p { fmt.Println(a.Disassemble(v)) } } Thursday, 30 May 13
  • 54. package instructions type Instruction []int func (i Instruction) Opcode() int { if len(i) == 0 { return INVALID_OPCODE } return i[0] } func (i Instruction) Operands() []int { if len(i) < 2 { return []int{} } return i[1:] } func (i Instruction) Execute(op Operation) { op(i.Operands()) } Thursday, 30 May 13
  • 55. package instructions type Assembler struct { opcodes map[string] int names map[int] string } func NewAssember(names... string) (a Assembler) { a = Assembler{ opcodes: make(map[string] int), names:make(map[int] string), } a.Define(names...) return } func (a Assembler) Define(names... string) { for _, name := range names { a.opcodes[name] = len(a.names) a.names[len(a.names)] = name } } Thursday, 30 May 13
  • 56. package instructions func (a Assembler) Assemble(name string, params... int) (i Instruction) { i = make(Instruction, len(params) + 1) if opcode, ok := a.opcodes[name]; ok { i[0] = opcode } else { i[0] = INVALID_OPCODE } copy(i[1:], params) return } Thursday, 30 May 13
  • 57. package instructions import "fmt" func (a Assembler) Disassemble(e Executable) (s string) { if name, ok := a.names[e.Opcode()]; ok { s = name if params := e.Operands(); len(params) > 0 { s = fmt.Sprintf("%vt%v", s, params[0]) for _, v := range params[1:] { s = fmt.Sprintf("%v, %v", s, v) } } } else { s = "unknown" } return } Thursday, 30 May 13
  • 58. package main import . "instructions" func main() { a := NewAssembler("noop", "load", "store") p := Program{ a.Assemble("noop"), a.Assemble("load", 1), a.Assemble("store", 1, 2), a.Assemble("invalid", 3, 4, 5) } p.Disassemble(a) for _, v := range p { if len(v.Operands()) == 2 { v.Execute(func(o []int) { o[0] += o[1] }) println("op =", v.Opcode(), "result =", v.Operands()[0]) } } } Thursday, 30 May 13
  • 59. produces: noop load 1 store 1, 2 unknown op = 2 result = 3 Thursday, 30 May 13
  • 61. package processor import . "instructions" const PROCESSOR_READY = 0 const PROCESSOR_BUSY = 1 const CALL_STACK_UNDERFLOW = 2 const CALL_STACK_OVERFLOW = 4 const ILLEGAL_OPERATION = 8 const INVALID_ADDRESS = 16 type Processor interface { Run(p []Executable) } type Core struct { Running bool PC, Flags, Ticks int CS, M []int OP Executable "Loaded OpCode" I chan Executable "Interrupts" } Thursday, 30 May 13
  • 62. package processor import . "instructions" func NewCore(CSS, MSS int, I chan Executable) *Core { return &Core{ CS:make([]int, CSS)}, M: make([]int, MSS), I: I, } } func (c *Core) Reset() { c.Running = false c.Flags = PROCESSOR_READY } func (c *Core) Goto(addr int) { c.PC = addr } Thursday, 30 May 13
  • 63. package processor func (c *Core) Call(addr int) { top := len(c.CS) if top >= cap(c.CS) - 1 { panic(CALL_STACK_OVERFLOW) } c.CS = c.CS[:top + 1] c.CS[top] = c.PC c.PC = addr } func (c *Core) TailCall(addr int) { c.CS[len(c.CS) - 1] = c.PC c.PC = addr } func (c *Core) Return() { top := len(c.CS) if top == 0 { panic(CALL_STACK_UNDERFLOW) } c.PC, c.CS = c.CS[top - 1], c.CS[:top] } Thursday, 30 May 13
  • 64. package processor import . "instructions" func (c *Core) Run(p []Executable, dispatchers... func(c *Core)) { defer func() { c.Running = false if x := recover(); x != nil { c.Flags &= x.(int) } }() switch { case c.Running: panic(PROCESSOR_BUSY) case len(dispatchers) == 0: panic(PROCESSOR_READY) default: c.Running = true c.BusyLoop(dispatchers...) } } func (c *Core) LoadInstruction(program []Executable) { if c.PC >= len(program) { panic(PROCESSOR_READY) } c.Executable = program[c.PC] c.PC++ } Thursday, 30 May 13
  • 65. package processor import . "instructions" func (c *Core) BusyLoop(p []Executable, dispatchers... func(c *Core)) { select { case interrupt <- c.I: op, pc := c.OP, c.PC for c.PC = 0; c.Running; c.Ticks++ { for _, f := range dispatchers { f(c) } c.LoadInstruction(p) } c.OP, c.PC = op, pc default: for c.PC = 0; c.Running; c.Ticks++ { c.LoadInstruction(p) for _, f := range dispatchers { f(c) } } } } Thursday, 30 May 13
  • 66. package processor import . "instructions" func (c *Core) RunExclusive(p []Executable, tracers... func(c *Core)) { defer func() { c.Running = false if x := recover(); x != nil { c.Flags &= x.(int) } }() if c.Running { panic(PROCESSOR_BUSY) } case len(dispatchers) == 0: panic(PROCESSOR_READY) c.Running = true for c.PC = 0; c.Running; c.Ticks++ { c.LoadInstruction(p) for _, f := range tracers { f(c) } } } Thursday, 30 May 13
  • 67. package main import . "processor" import . "instructions" const( CALL = iota GOTO MOVE RETURN ) c := NewCore(10, 8, nil) var dispatcher = func(c *Core) { switch c.Opcode() { case CALL: c.Execute(func(o []int) { c.Call(o[0]) }) case GOTO: c.Execute(func(o []int) { c.Goto(o[0]) }) case MOVE: c.Execute(func(o []int) { c.Goto(c.PC + o[0]) }) case RETURN: c.Execute(func(o []int) { c.Return() }) default: panic(ILLEGAL_OPERATION) } } Thursday, 30 May 13
  • 68. func main() { p := []Executable{ Instruction{ CALL, 2 }, Instruction{ GOTO, 5 }, Instruction{ MOVE, 2 }, Instruction{ RETURN }, Instruction{ MOVE, -1 } } c.RunExclusive(p, dispatcher) fmt.Printf("Instructions Executed: %vnPC = %vn", c.Ticks, c.PC) if c.Flags | PROCESSOR_READY == PROCESSOR_READY { fmt.Println("Core Ready") } else { fmt.Println("Core Error:", c.Flags) } } produces: Instructions Executed: 2 PC = 5 Core Ready Thursday, 30 May 13
  • 69. accumulator machine 1-operand instructions data from memory combined with accumulator result stored in accumulator Thursday, 30 May 13
  • 70. package accmachine import . "processor" const ( CONSTANT = iota LOAD_VALUE STORE_VALUE ADD ) type AccMachine struct { Core AC int } func NewAccMachine(CSSize, MSize int, I chan Executable) *AccMachine { return &AccMachine{ Core: NewCore(CSSize, MSize, I) } } Thursday, 30 May 13
  • 71. package accmachine import . "processor" func (a *AccMachine) Run(program []Executable) { a.RunExclusive(program, func() { switch a.Opcode() { case CONSTANT: a.Execute(func(o []int) { a.AC = o[0] }) case LOAD_VALUE: a.Execute(func(o []int) { a.AC = a.M[o[0]] }) case STORE_VALUE: a.Execute(func(o []int) { a.M[o[0]] = a.AC }) case ADD: a.Execute(func(o []int) { a.AC += a.M[o[0]] }) default: panic(ILLEGAL_OPERATION) } }) } Thursday, 30 May 13
  • 72. package main import . "accmachine" import . "instructions" func main() { a := NewAccMachine(10, 8, nil) p := []Executable{ Instruction{CONSTANT, 27}, Instruction{STORE_VALUE, 0}, Instruction{CONSTANT, 13}, Instruction{STORE_VALUE, 1}, Instruction{CONSTANT, 10}, Instruction{ADD, 1}, Instruction{ADD, 0}, Instruction{STORE_VALUE, 2} } a.Run(p) fmt.Println("accumulated value =", a.AC) } produces: accumulated value = 50 Thursday, 30 May 13
  • 73. stack machine 0-operand instructions data popped from stack results pushed on stack Thursday, 30 May 13
  • 74. package smachine import . "processor" const ( CONSTANT = iota PUSH_VALUE POP_VALUE ADD ) type StackMachine struct { Core DS []int } func NewStackM(CSSize, DSSize, MSize int, I chan Executable) *StackMachine { return &StackMachine{DS: make([]int, 0, DSSize), Core: NewCore(CSSize, MSize, I) } } Thursday, 30 May 13
  • 75. package smachine import . "processor" func (s *StackMachine) Push(v int) { top := len(s.DS) s.DS, s.DS[top] = s.DS[:top + 1], v } func (s *StackMachine) Pop(addr int) { top := len(s.DS) - 1 s.M[addr], s.DS = s.DS[top], s.DS[:top] } Thursday, 30 May 13
  • 76. package smachine import . "processor" func (s *StackMachine) Run(program []Executable) { s.RunExclusive(program, func() { switch s.Opcode() { case CONSTANT: s.Execute(func(o []int) { s.Push(o[0]) }) case PUSH_VALUE: s.Execute(func(o []int) { s.Push(s.M[o[0]]) }) case POP_VALUE: s.Execute(func(o []int) { s.Pop(s.M[o[0]]) }) case ADD: s.Execute(func(o []int) { l := len(s.DS) s.DS[l - 2] += s.DS[l - 1] s.DS = s.DS[:l - 1] }) default: panic(ILLEGAL_OPERATION) } }) } Thursday, 30 May 13
  • 77. package main import . "smachine" import . "instructions" func main() { s := NewStackM(10, 10, 8, nil) p := []Executable{ Instruction{CONSTANT, 27}, Instruction{CONSTANT, 13}, Instruction{CONSTANT, 10}, Instruction{ADD}, Instruction{ADD} } s.Run(p) fmt.Println("data stack =", s.DS) } produces: registers = [50 13 10 0 0 0 0 0 0 0] Thursday, 30 May 13
  • 78. register machine multi-operand instructions data read from memory into registers operator combines registers and stores Thursday, 30 May 13
  • 79. package rmachine import . "processor" const ( CONSTANT = iota LOAD_VALUE STORE_VALUE ADD ) type RMachine struct { Core R []int } func NewRMachine(CSSize, RSize, MSize int, I chan Executable) *RMachine { return &RMachine{ Core: NewCore(CSSize, MSize, I), R: make([]int, RSize) } } Thursday, 30 May 13
  • 80. package rmachine import . "processor" func (r *RMachine) Run(program []Executable) { r.RunExclusive(program, func() { switch r.Opcode() { case CONSTANT: r.Execute(func(o []int) { r.R[o[0]] = o[1] }) case LOAD_VALUE: r.Execute(func(o []int) { r.R[o[0]] = r.M[o[1]] }) case STORE_VALUE: r.Execute(func(o []int) { r.M[o[0]] = r.R[o[1]] }) case ADD: r.Execute(func(o []int) { r.R[o[0]] += r.R[o[1]] }) default: panic(ILLEGAL_OPERATION) } }) } Thursday, 30 May 13
  • 81. package main import . "rmachine" import . "instructions" func main() { r := NewRMachine(10, 10, 8, nil) p := []Executable{ Instruction{CONSTANT, 0, 27}, Instruction{CONSTANT, 1, 13}, Instruction{CONSTANT, 2, 10}, Instruction{ADD, 0, 1}, Instruction{ADD, 0, 2} } r.Run(p) fmt.Println("registers =", r.R) } produces: registers = [50 13 10 0 0 0 0 0 0 0] Thursday, 30 May 13
  • 82. vector machine multi-operand instructions data vectors read from memory into registers operations combine registers Thursday, 30 May 13
  • 83. package vmachine import . "processor" const ( CONSTANT = iota LOAD_VALUE STORE_VALUE ADD ) type VMachine struct { Core R [][]int } func NewVMachine(CSSize, RSize, MSize int, I chan Executable) *VMachine { return &VectorMachine{ Core: NewCore(CSSize, MSize), make([][]int, RSize) } } Thursday, 30 May 13
  • 84. package vmachine import . "processor" func (v *VMachine) Load(r int, m []int) { v.R[r] = make([]int, len(m)) copy(v.R[r], m) } Thursday, 30 May 13
  • 85. package vmachine import . "processor" func (v *VMachine) Run(program []Executable) { v.RunExclusive(program, func() { switch v.Opcode() { case CONSTANT: v.Execute(func(o []int) { v.Load(o[0], o[1:]) }) case STORE_VALUE: v.Execute(func(o []int) { copy(v.M[o[0]:], v.R[o[1]]) }) case LOAD_VALUE: v.Execute(func(o []int) { v.Load(o[0], v.M[o[1]:o[1] + o[2]]) }) case ADD: v.Execute(func(o []int) { a, b := v.R[o[0]], v.R[o[1]] count := len(a) if len(b) < len(a) { count := len(b) } for ; count > 0; count-- { a[i] += b[i] } }) default: panic(ILLEGAL_OPERATION) } }) } Thursday, 30 May 13
  • 86. package main import . "vmachine" import . "instructions" func main() { r := NewVMachine(10, 10, 8, nil) p := []Executable{ Instruction{CONSTANT, 0, 27}, Instruction{CONSTANT, 1, 13}, Instruction{CONSTANT, 2, 10}, Instruction{ADD, 0, 1}, Instruction{ADD, 0, 2} } r.Run(p) fmt.Println("registers =", r.R) } produces: vectors = [[50 50 50] [13 10 27] [10 27 13] [] [] [] [] [] [] []] Thursday, 30 May 13
  • 87. related projects gospeed raw - slices - lists - chains - sexp wendigo Thursday, 30 May 13