SlideShare a Scribd company logo
1 of 63
Download to read offline
GoLightly
                          Building VM-based language runtimes in Go


                                      Eleanor McHugh

                            http://golightly.games-with-brains.net


Friday, 15 October 2010                                               1
portrait of an artist...
                          physics major




                                                   http://feyele
                          embedded systems

                          dynamic languages

                          dns provisioning

                          network scaling               or.tel   an

                          questionable taste in music                 Elean or McHugh


Friday, 15 October 2010                                                                 2
today’s menu


                          an overview of golightly

                          a crash course in go programming

                          application virtualisation & soft machines




Friday, 15 October 2010                                                3
caveat lector
                          danger! we’re entering strange territory

                          our map is missing major landmarks

                          and will be riddled with inaccuracies

                          so please tread carefully

                          try not to disturb the local wildlife

                          and don’t be put off by the pages of code

Friday, 15 October 2010                                               4
golightly
                          agnostic heterogenous virtualisation networks




Friday, 15 October 2010                                                   5
go...
                              a systems language by google

                          productivity, performance, concurrency

                             lighter than Java, safer than C


Friday, 15 October 2010                                            6
...lightly
                               clean abstractions

                            geared to performance

                          non-viral open source license


Friday, 15 October 2010                                   7
inspiration
                                processor design

                           sensor and control networks

                          field-programmable gate arrays


Friday, 15 October 2010                                   8
perspiration
                               iterative empirical development

                          explore -> implement -> test -> benchmark

                                   evolve towards elegance


Friday, 15 October 2010                                               9
principles
                             decoupling improves scalability

                           coherence simplifies organisation

                          optimisations are application specific


Friday, 15 October 2010                                           10
agnostic
                           no blessed programming languages

                              flexible platform abstractions

                          write once, run everywhere it matters


Friday, 15 October 2010                                           11
heterogeneous
                             a system comprises many components

                          components may differ in purpose and design

                             but they cooperate to solve problems


Friday, 15 October 2010                                                 12
virtualisation
                             design discrete Turing machines

                          implement these machines in software

                            compile programs to run on them


Friday, 15 October 2010                                          13
networks
                            machines cooperate by sending messages

                          machine states can be serialised as messages

                  messages transcend process and host boundaries


Friday, 15 October 2010                                                  14
go
                          a crash course




Friday, 15 October 2010                    15
behind the hype
                          a statically-typed compiled language

                          class-free object-orientation

                          nominal type declaration

                          structural type inference

                          garbage collection

                          concurrency via communication (CSP)


Friday, 15 October 2010                                          16
an elegant tool


                          the safety of a static type system

                          the feel of a dynamic runtime

                          the performance of a compiled language

                          no dependence on runtime libraries




Friday, 15 October 2010                                            17
nominal types
                          primitive (boolean, numeric, pointer)

                          aggregate (array, slice, map, struct)

                          functional (closure, channel)

                          all types can underpin user-defined types

                          methods are declared on user-defined types

                          types can be embedded in struct types


Friday, 15 October 2010                                               18
package Integer                       package main
                                                       import “Integer”
                 type Int int
                                                       func main() {
                 func (i *Int) Add(x int) {              i := Integer.Buffer{0, 1, 2, 3, 4, 5}
                   *i += Int(x)                          b := i.Clone()
                 }                                       b.Swap(1, 2)
                                                         b.Move(3, 2)
                 type Buffer []Int                       b[0].Add(3)
                                                         println(“b[0:2] = {”, b[0], “,”, b[1], “}”)
                 func (b Buffer) Clone() Buffer {      }
                   s := make(Buffer, len(b))
                   copy(s, b)
                   return s
                 }

                 func (b Buffer) Swap(i, j int) {
                   b[i], b[j] = b[j], b[i]
                 }

                 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)   produces:
                 }                                           b[0:2] = { 6, 4 }




Friday, 15 October 2010                                                                                19
package Vector                              package main
                 import . “Integer”                          import “Integer”

                 type Vector struct {                        func main() {
                   Buffer                                      i := Vector{Buffer{0, 1, 2, 3, 4, 5}}
                 }                                             b := i.Clone()
                                                               b.Swap(1, 2)
                 func (v *Vector) Clone() Vector {             b.Move(3, 2)
                   return Vector{v.Buffer.Clone()}             s := b.Slice(0, 2)
                 }                                             s[0].Add(3)
                                                               b.Replace(s)
                 func (v *Vector) Slice(i, j int) Buffer {     println(“b[0:2] = {”, b.Buffer[0], “,”, b.Buffer[1], “}”)
                   return v.Buffer[i:j]                      }
                 }

                 func (v *Vector) Replace(o interface{}) {
                   switch o := o.(type) {
                   case Vector:
                      v=o
                   case Buffer:
                      v.Buffer = o
                   }
                 }




                                                             produces:
                                                                   b[0:2] = { 6, 4 }




Friday, 15 October 2010                                                                                                    20
structural types
                          interfaces define method sets

                          they can be embedded within each other

                          but do not implement methods

                          a type can implement many interfaces

                          type inference determines which if any

                          all types implement the blank interface


Friday, 15 October 2010                                             21
package main                                 type Calculator struct {
                                                                Adder
                 type Adder interface {                       }
                   Add(j int)
                   Subtract(j int)                            func main() {
                   Result() interface{}                         c := Calculator{}
                 }                                              c.Adder = IntAdder{0, 1, 2, 3, 4, 5}
                                                                c.Add(1)
                 type IntAdder []int                            c.Add(2)
                 func (i IntAdder) Add(j int) {                 c.Subtract(3)
                   i[0] += i[j]                                 println("c.Result() =", c.Result().(int))
                 }
                 func (i IntAdder) Subtract(j int) {              c.Adder = FloatAdder{0.0, 1.1, 2.2, 3.3, 4.4, 5.5}
                   i[0] -= i[j]                                   c.Add(1)
                 }                                                c.Add(2)
                 func (i IntAdder) Result() interface{} {         c.Subtract(3)
                   return i[0]                                    println("c.Result() =", c.Result())
                 }                                            }

                 type FloatAdder []float
                 func (f FloatAdder) Add(j int) {
                   f[0] += f[j]
                 }
                 func (f FloatAdder) Subtract(j int) {
                   f[0] -= f[j]
                 }                                            produces:
                 func (f FloatAdder) Result() interface{} {         c.Result() = 0
                   return f[0]
                                                                    c.Result() = (0x10f94,0x34800000)
                 }




Friday, 15 October 2010                                                                                                22
dynamic typing


                          type assertions

                          type switches

                          runtime reflection




Friday, 15 October 2010                         23
package generalise                                             func Duplicate(i interface{}) (clone interface{}) {
                 import "fmt"                                                     if clone = Allocate(i); clone != nil {
                 import . "reflect"                                                    switch clone := NewValue(clone).(type) {
                                                                                      case *SliceValue:
                 func Allocate(i interface{}, limit... int) (n interface{}) {            s := NewValue(i).(*SliceValue)
                   switch v := NewValue(i).(type) {                                      ArrayCopy(clone, s)
                   case *SliceValue:                                                  case *MapValue:
                      l := v.Cap()                                                       m := NewValue(i).(*MapValue)
                      if len(limit) > 0 { l = limit[0] }                                 for _, k := range m.Keys() {
                      t := v.Type().(*SliceType)                                            clone.SetElem(k, m.Elem(k))
                      n = MakeSlice(t, l, l).Interface()                                 }
                   case *MapValue:                                                    }
                      n = MakeMap(v.Type().(*MapType)).Interface()                }
                   }                                                              return
                   return                                                       }
                 }

                 func SwapSlices(i interface{}, d, s, n int) {
                   if v, ok := NewValue(i).(*SliceValue); ok {
                       source := v.Slice(s, s + n)
                       destination := v.Slice(d, d + n)
                       temp := NewValue(Allocate(i, n)).(*SliceValue)
                       ArrayCopy(temp, destination)
                       ArrayCopy(destination, source)
                       ArrayCopy(source, temp)
                   }
                 }




Friday, 15 October 2010                                                                                                               24
package main
                 import . “generalise”

                 func main() {
                   error_text := “panic caused by”
                   defer func() {
                       if x := recover(); x != nil {
                          fmt.Println(error_text, x)
                       }
                   }()

                     s1 := []int{0, 1, 2, 3, 4, 5}
                     fmt.Println("s1 =", s1)
                     s2 := Duplicate(s1)
                     fmt.Println("s2 =", s2, "Duplicate(s1)")
                     SwapSlices(s2, 0, 3, 3)
                     fmt.Println("s2 =", s2, "SwapSlices(s2, 0, 3, 3)")
                     s3 := Allocate(s1, 1)
                     fmt.Println("s3 =", s3, "Allocate(s1, 1)")
                                                                             produces:
                     m := map[int] int{1: 1, 2: 2, 3: 3, 0: 0, 4: 4, 5: 5}       s1 = [0 1 2 3 4 5]
                     fmt.Println("m =", m)
                                                                                 s2 = [0 1 2 3 4 5] Duplicate(s1)
                     n := Allocate(m)
                     fmt.Println("n =", n, "Allocate(m)")                        s2 = [3 4 5 0 1 2] SwapSlices(s2, 0, 3, 3)
                     SwapSlices(m, 0, 3, 3)                                      s3 = [0] Allocate(s1, 1)
                 }                                                               m = map[3:3 0:0 1:1 4:4 5:5 2:2]
                                                                                 n = map[]
                                                                                 panic caused by map[3:3 0:0 1:1 4:4 5:5 2:2]




Friday, 15 October 2010                                                                                                         25
goroutines

                          concurrent threads of control

                          launched by the go statement

                          which returns immediately

                          each may be a function call or method call

                          and can communicate via channels



Friday, 15 October 2010                                                26
channels

                          link concurrently executing functions

                          support sending and/or receiving

                          only accept items of a specified type

                          synchronous channels are unbuffered

                          asynchronous channels are buffered



Friday, 15 October 2010                                           27
package generalise                                          func (f Iteration) Each(c interface{}) {
                 import . "reflect"                                             switch c := NewValue(c).(type) {
                                                                               case *SliceValue:
                 type Results chan interface{}                                    count := c.Len()
                                                                                  SignalSource(func(done chan bool) {
                 type SignalSource func(status chan bool)                             for i := 0; i < count; i++ {
                 func (s SignalSource) Pipeline() {                                      f.apply(i, c.Elem(i).Interface(), done)
                   done := make(chan bool)                                            }
                   defer close(done)                                              }).Multiplex(count)
                   go s(done)                                                  case *MapValue:
                   <-done                                                         SignalSource(func(done chan bool) {
                 }                                                                    for _, k := range c.Keys() {
                                                                                         f.apply(k, c.Elem(k).Interface(), done)
                 func (s SignalSource) Multiplex(count int) {                         }
                   done := make(chan bool)                                        }).Multiplex(c.Len())
                   defer close(done)                                           }
                   go s(done)                                                }
                   for i := 0; i < count; i++ {
                      <- done                                                type Combination func(x, y interface{}) interface{}
                   }                                                         func (f Combination) Reduce(c, s interface{}) (r Results) {
                 }                                                             r = make(Results)
                                                                               go func() {
                 type Iteration func(k, x interface{})                             Iteration(func(k, x interface{}) {
                 func (i Iteration) apply(k, v interface{}, c chan bool) {             s = f(s, x)
                   go func() {                                                     }).Each(c)
                       i(k, v)                                                     r <- s
                       c <- true                                               }()
                   }()                                                         return
                 }                                                           }




Friday, 15 October 2010                                                                                                                    28
type Transformation func(x interface{}) interface{}        package main
                 func (t Transformation) GetValue(x interface{}) Value {    import “fmt”
                   return NewValue(t(x))                                    import . “generalise”
                 }
                                                                            var adder Combination = func(x, y interface{}) interface{} {
                 func (t Transformation) Map(c interface{}) interface{} {     return x.(int) + y.(int)
                   switch n := NewValue(Allocate(c)).(type) {               }
                   case *SliceValue:
                      SignalSource(func(done chan bool) {                   var multiplier Transformation = func(x interface{}) interface{} {
                          Iteration(func(k, x interface{}) {                  return x.(int) * 2
                              n.Elem(k.(int)).SetValue(t.GetValue(x))       }
                          }).Each(c)
                          done <- true                                      func main() {
                      }).Pipeline()                                           s := []int{0, 1, 2, 3, 4, 5}
                      return n.Interface()                                    fmt.Println("s =", s)
                   case *MapValue:                                            fmt.Println("sum s =", (<- adder.Reduce(s, 0)).(int))
                      SignalSource(func(done chan bool) {
                          Iteration(func(k, x interface{}) {                    c := multiplier.Map(s)
                              n.SetElem(NewValue(k), t.GetValue(x))             fmt.Println("c =", c)
                          }).Each(c)                                            fmt.Println("sum c =", (<- adder.Reduce(c, 0)).(int))
                          done <- true                                      }
                      }).Pipeline()
                      return n.Interface()
                   }                                                        produces:
                   return Duplicate(c)                                            s = [0 1 2 3 4 5]
                 }
                                                                                  sum s = 15
                                                                                  c = [0 2 4 6 8 10]
                                                                                  sum c = 30




Friday, 15 October 2010                                                                                                                         29
tooling
                          gotest is a testing framework

                          which also supports benchmarking

                          gofmt standardises code layout

                          godoc formats and serves documentation

                          goinstall is an automatic package installer

                          cgo integrates C code with go


Friday, 15 October 2010                                                 30
software machines
                            application virtualisation 101




Friday, 15 October 2010                                      31
system clock
                          synchronising components




Friday, 15 October 2010                              32
package clock                               package main
                 import "syscall"                            import . “clock”

                 type Clock struct {                         func main() {
                   Period int64                                c := Clock{1000, make(chan int64), make(chan bool), false}
                   Count chan int64                            c.Start()
                   Control chan bool
                   active bool                                   for i := 0; i < 3; i++ {
                 }                                                  println("pulse value", <-c.Count, "from clock")
                                                                 }
                 func (c *Clock) Start() {
                   if !c.active {                                println("disabling clock")
                       go func() {                               c.Control <- false
                           c.active = true                       syscall.Sleep(1000000)
                           for i := int64(0); ; i++ {            println("restarting clock")
                              select {                           c.Control <- true
                              case status := <- c.Control:       println("pulse value", <-c.Count, "from clock")
                                  c.active = status          }
                              default:
                                  if c.active {
                                      c.Count <- i           produces:
                                  }                                pulse value 0 from clock
                                  syscall.Sleep(c.Period)
                                                                   pulse value 1 from clock
                              }
                           }                                       pulse value 2 from clock
                       }()                                         disabling clock
                   }                                               restarting clock
                 }                                                 pulse value 106 from clock




Friday, 15 October 2010                                                                                                     33
instruction set
                          specifying operation sequences




Friday, 15 October 2010                                    34
package instructions                      func (i Instruction) Execute(op Operation) {
                 import "fmt"                                op(i.Operands())
                                                           }
                 type Operation func(o []int)
                                                           type Assembler struct {
                 type Executable interface {                 opcodes map[string] int
                   Opcode() int                              names map[int] string
                   Operands() []int                        }
                   Execute(op Operation)
                 }                                         func NewAssember(names... string) (a Assembler) {
                                                             a = Assembler{ make(map[string] int), make(map[int] string) }
                 const INVALID_OPCODE = -1                   a.Define(names...)
                                                             return
                 type Instruction []int                    }
                 func (i Instruction) Opcode() int {
                   if len(i) == 0 {                        func (a Assembler) Assemble(name string, params... int)
                       return INVALID_OPCODE                                                            (i Instruction) {
                   }                                         i = make(Instruction, len(params) + 1)
                   return i[0]                               if opcode, ok := a.opcodes[name]; ok {
                 }                                             i[0] = opcode
                                                             } else {
                 func (i Instruction) Operands() []int {       i[0] = INVALID_OPCODE
                   if len(i) < 2 {                           }
                       return []int{}                        copy(i[1:], params)
                   }                                         return
                   return i[1:]                            }
                 }




Friday, 15 October 2010                                                                                                      35
func (a Assembler) Define(names... string) {                 package main
                   for _, name := range names {                              import . “instructions”
                      a.opcodes[name] = len(a.names)
                      a.names[len(a.names)] = name                           func main() {
                   }                                                           a := NewAssembler("noop", "load", "store")
                 }                                                             p := Program{ a.Assemble("noop"),
                                                                                               a.Assemble("load", 1),
                 func (a Assembler) Disassemble(e Executable) (s string) {                     a.Assemble("store", 1, 2),
                   if name, ok := a.names[e.Opcode()]; ok {                                    a.Assemble("invalid", 3, 4, 5) }
                       s = name                                                p.Disassemble(a)
                       if params := e.Operands(); len(params) > 0 {            for _, v := range p {
                          s = fmt.Sprintf("%vt%v", s, params[0])                 if len(v.Operands()) == 2 {
                          for _, v := range params[1:] {                              v.Execute(func(o []int) {
                             s = fmt.Sprintf("%v, %v", s, v)                             o[0] += o[1]
                          }                                                           })
                       }                                                              println("op =", v.Opcode(), "result =", v.Operands()[0])
                   } else {                                                       }
                       s = "unknown"                                           }
                   }                                                         }
                   return
                 }
                                                                             produces:
                 type Program []Executable                                        noop
                 func (p Program) Disassemble(a Assembler) {
                                                                                  load!
                                                                                      !     1
                   for _, v := range p {
                      fmt.Println(a.Disassemble(v))                               store!    1, 2
                   }                                                              unknown
                 }                                                                op = 2 result = 3




Friday, 15 October 2010                                                                                                                          36
CISC
                            semantically rich instructions

                          complex memory addressing modes

                                compact binary code



Friday, 15 October 2010                                      37
RISC
                          separate IO and data processing

                          register-to-register instructions

                             load/store memory access



Friday, 15 October 2010                                       38
VLIW
                             multiple operations per instruction

                          compiler statically determines parallelism

                                   simplifies control logic



Friday, 15 October 2010                                                39
memory
                          storing data and instructions




Friday, 15 October 2010                                   40
subtleties
                            von Neumann

                              Harvard

                           indirection bits



Friday, 15 October 2010                       41
package memory                                         func Overwrite(i interface{}, b []byte) interface{} {
                 import "fmt"                                             switch i := NewValue(i).(type) {
                 import . "reflect"                                        case *SliceValue:
                 import "unsafe"                                             h := Header(unsafe.Pointer(&b))
                                                                             t := i.Type().(*SliceType)
                 var _BYTE_SLICE = Typeof([]byte(nil))                       Resize(&h, int(t.Elem().Size()), 1)
                 var _SLICE_TYPE = Typeof(SliceHeader{})                     return unsafe.Unreflect(t, unsafe.Pointer(&h))
                                                                          }
                 func Data(addr unsafe.Pointer) []byte {                  return nil
                   return unsafe.Unreflect(_BYTE_SLICE, addr).([]byte)   }
                 }

                 func Resize(h *SliceHeader, d, m int) {
                   h.Len /= d
                   h.Len *= m
                 }

                 func Serialise(i interface{}) []byte {
                   switch i := NewValue(i).(type) {
                   case *SliceValue:
                      h := Header(unsafe.Pointer(i.Addr()))
                      t := i.Type().(*SliceType)
                      Resize(&h, 1, int(t.Elem().Size()))
                      return Data(unsafe.Pointer(&h))
                   }
                   return nil
                 }




Friday, 15 October 2010                                                                                                         42
package main
                 import “fmt”
                 import . "memory"

                 type Memory []int

                 func main() {
                   m := make(Memory, 2)
                   fmt.Println("m (cells) =", len(m), "of", cap(m), ":", m)

                     b := Serialise(m)
                     fmt.Println("b (bytes) =", len(b), "of", cap(b), ":", b)

                     n := Overwrite(m, []byte{0, 0, 0, 1, 0, 0, 0, 1}).(Memory)
                     fmt.Println("n (cells) =", len(n), "of", cap(n), ":", n)

                     b = Serialise(n)
                     fmt.Println("b (bytes) =", len(b), "of", cap(b), ":", b)
                 }




                                                                                  produces:
                                                                                      m (cells) = 2 of 2 : [0 0]
                                                                                      b (bytes) = 8 of 2 : [0 0 0 0 0 0 0 0]
                                                                                      n (cells) = 2 of 8 : [16777216 16777216]
                                                                                      b (bytes) = 8 of 8 : [0 0 0 1 0 0 0 1]




Friday, 15 October 2010                                                                                                          43
processor core
                            tying it all together




Friday, 15 October 2010                             44
package processor                                 func (p *Core) Reset() {
                 import . “instructions”                             p.Running = false
                 import . “memory”                                   p.Flags = PROCESSOR_READY
                                                                   }
                 const    PROCESSOR_READY = 0
                 const    PROCESSOR_BUSY = 1                       func (c *Core) RunExclusive(p []Executable, f func()) {
                 const    CALL_STACK_UNDERFLOW = 2                   defer func() {
                 const    CALL_STACK_OVERFLOW = 4                        c.Running = false
                 const    ILLEGAL_OPERATION = 8                          if x := recover(); x != nil {
                 const    INVALID_ADDRESS = 16                               c.Flags &= x.(int)
                                                                         }
                 type Processor interface {                          }()
                 !    Run(p []Executable)                            if c.Running {
                 }                                                       panic(PROCESSOR_BUSY)
                                                                     }
                 type Core struct {                                  c.Running = true
                   Ticks! !    int                                   for c.PC = 0; c.Running; {
                   Running!    bool                                      c.LoadInstruction(p)
                   PC, Flags! int                                        f()
                   CS!    !    []int                                     c.Ticks++
                   M!     !    Memory                                }
                   OP!    !    Executable                          }
                 }
                                                                   func (c *Core) LoadInstruction(program []Executable) {
                 func NewCore(CSSize, MSize int) ProcessorCore {     if c.PC >= len(program) {
                   return Core{                                          panic(PROCESSOR_READY)
                      CS: make([]int, 0, Calls)},                    }
                      M: make(Memory, MSize),                        c.Executable = program[c.PC]
                   }                                                 c.PC++
                 }                                                 }




Friday, 15 October 2010                                                                                                      45
package processor

                 func (c *Core) Goto(addr int) {
                 !    c.PC = addr
                 }

                 func (c *Core) Call(addr int) {
                   if top := len(c.CS); top < cap(c.CS) - 1 {
                       c.CS = c.CS[:top + 1]
                       c.CS[top] = c.PC
                       c.PC = addr
                   } else {
                       panic(CALL_STACK_OVERFLOW)
                   }
                 }

                 func (c *Core) TailCall(addr int) {
                 !    c.CS[len(c.CS) - 1] = c.PC
                 !    c.PC = addr
                 }

                 func (c *Core) Return() {
                 !    if top := len(c.CS); top > 0 {
                 !    !     c.PC, c.CS = c.CS[top - 1], c.CS[:top]
                 !    } else {
                 !    !     panic(CALL_STACK_UNDERFLOW)
                 !    }
                 }




Friday, 15 October 2010                                              46
package main                                             func main() {
                 import . “processor”                                       c := NewCore(10, 8)
                 import . “instructions”                                    p := []Executable{
                                                                                Instruction{CALL, 2},
                 const (                                                        Instruction{GOTO, 5},
                   CALL = iota                                                  Instruction{MOVE, 2},
                   GOTO                                                         Instruction{RETURN},
                   MOVE                                                         Instruction{MOVE, -1},
                   RETURN                                                   }
                 )                                                          c.RunExclusive(p, dispatcher)
                                                                            fmt.Println("Instructions Executed:", c.Ticks)
                 var dispatcher = func() {                                  fmt.Println("PC =", c.PC)
                    switch c.Opcode() {                                     if c.Flags | PROCESSOR_READY == PROCESSOR_READY {
                    case CALL:                                                  fmt.Println("Core Ready")
                       c.Execute(func(o []int) { c.Call(o[0]) })            } else {
                    case GOTO:                                                  fmt.Println("Core Error:", c.Flags)
                       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:                                              produces:
                       panic(ILLEGAL_OPERATION)                               top = 0
                    }
                                                                              cap(c.CS) -1 = 9
                 }
                                                                              Instructions Executed: 2
                                                                              PC = 5
                                                                              Core Ready




Friday, 15 October 2010                                                                                                         47
accumulator machine
                                1-operand instructions

                      data from memory combined with accumulator

                              result stored in accumulator



Friday, 15 October 2010                                            48
package accmachine                                    func (a *AccMachine) Run(program []Executable) {
                 import . “processor”                                    a.RunExclusive(program, func() {
                 import . “memory”                                          switch a.Opcode() {
                                                                            case CONSTANT:
                 const (                                                       a.Execute(func(o []int) {
                   CONSTANT = iota                                                a.AC = o[0]
                   LOAD_VALUE                                                  })
                   STORE_VALUE                                              case LOAD_VALUE:
                   ADD                                                         a.Execute(func(o []int) {
                 )                                                                a.AC = a.M[o[0]]
                                                                               })
                 type AccMachine struct {                                   case STORE_VALUE:
                 !    Core                                                     a.Execute(func(o []int) {
                 !    AC! !   !    !    int                                       a.M[o[0]] = a.AC
                 }                                                             })
                                                                            case ADD:
                 func NewAccMachine(CSSize, MSize int) *AccMachine {           a.Execute(func(o []int) {
                 !    return &AccMachine{NewCore(CSSize, MSize), 0}               a.AC += a.M[o[0]]
                 }                                                             })
                                                                            default:
                                                                               panic(ILLEGAL_OPERATION)
                                                                            }
                                                                         })
                                                                       }




Friday, 15 October 2010                                                                                                   49
package main
                 import . “accmachine”
                 import . “instructions”

                 func main() {
                   a := NewAccMachine(10, 8)
                   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




Friday, 15 October 2010                                                                    50
stack machine
                           0-operand instructions

                          data popped from stack

                          results pushed on stack



Friday, 15 October 2010                             51
package smachine                                     type StackMachine struct {
                 import . “processor”                                   Core
                                                                        DS!    []int
                 func (s *StackMachine) Run(program []Executable) {   }
                   s.RunExclusive(program, func() {
                      switch s.Opcode() {                             func (s *StackMachine) Push(v int) {
                      case CONSTANT:                                    top := len(s.DS)
                          s.Execute(func(o []int) {                     s.DS, s.DS[top] = s.DS[:top + 1], v
                             s.Push(o[0])                             }
                          })
                      case PUSH_VALUE:                                func (s *StackMachine) Pop(addr int) {
                          s.Execute(func(o []int) {                     top := len(s.DS) - 1
                             s.Push(s.M[o[0]])                          s.M[addr], s.DS = s.DS[top], s.DS[:top]
                          })                                          }
                      case POP_VALUE:
                          s.Execute(func(o []int) {                   const (
                             s.Pop(s.M[o[0]])                           CONSTANT = iota
                          })                                            PUSH_VALUE
                      case ADD:                                         POP_VALUE
                          s.Execute(func(o []int) {                     ADD
                             l := len(s.DS)                           )
                             s.DS[l - 2] += s.DS[l - 1]
                             s.DS = s.DS[:l - 1]                      func NewStackM(CSSize, DSSize, MSize int) *StackMachine {
                          })                                            return &StackMachine{
                      default:                                             DS: make([]int, 0, DSSize),
                          panic(ILLEGAL_OPERATION)                         Core: NewCore(CSSize, MSize),
                      }                                                 }
                   })                                                 }
                 }




Friday, 15 October 2010                                                                                                           52
package main
                 import . “smachine”
                 import . “instructions”

                 func main() {
                   s := NewStackM(10, 10, 8)
                   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]




Friday, 15 October 2010                                                                             53
register machine
                                multi-operand instructions

                          data read from memory into registers

                          operator combines registers and stores



Friday, 15 October 2010                                            54
package rmachine                                        type RegisterMachine struct {
                 import . “processor”                                    !    Core
                                                                         !    R! !     Memory
                 func (r *RegisterMachine) Run(program []Executable) {   }
                 !    r.RunExclusive(program, func() {
                 !    !    switch r.Opcode() {                           const (
                 !    !    case CONSTANT:                                  CONSTANT = iota
                 !    !    !    r.Execute(func(o []int) {                  LOAD_VALUE
                 !    !    !    !    r.R[o[0]] = o[1]                      STORE_VALUE
                 !    !    !    })                                         ADD
                 !    !    case LOAD_VALUE:                              )
                 !    !    !    r.Execute(func(o []int) {
                 !    !    !    !    r.R[o[0]] = r.M[o[1]]               func NewRMachine(CSSize, RSize, MSize int) *RegisterMachine {
                 !    !    !    })                                         return &RegisterMachine{
                 !    !    case STORE_VALUE:                                  NewCore(CSSize, MSize),
                 !    !    !    r.Execute(func(o []int) {                     make([]int, RSize)
                 !    !    !    !    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)
                 !    !    }
                 !    })
                 }




Friday, 15 October 2010                                                                                                                  55
package main
                 import . “rmachine”
                 import . “instructions”

                 func main() {
                   r := NewRMachine(10, 10, 8)
                   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]




Friday, 15 October 2010                                                                          56
transport triggering
                                 register machine architecture

                             exposes internal buses and components

                          operations are side-effects of internal writes



Friday, 15 October 2010                                                    57
vector machine
                                   multi-operand instructions

                          data vectors read from memory into registers

                                  operations combine registers



Friday, 15 October 2010                                                  58
package vmachine                                            type VectorMachine struct {
                 import . “processor”                                        !    Core
                                                                             !    R! !    []Memory
                 func (v *VectorMachine) Run(program []Executable) {         }
                   v.RunExclusive(program, func() {
                       switch v.Opcode() {                                   func (v *VectorMachine) Load(r int, m Memory) {
                       case CONSTANT:                                        !    v.R[r] = make(Memory, len(m))
                          v.Execute(func(o []int) { v.Load(o[0], o[1:]) })   !    copy(v.R[r], m)
                       case LOAD_VALUE:                                      }
                          v.Execute(func(o []int) {
                               v.Load(o[0], v.M[o[1]:o[1] + o[2]])           func NewVMachine(CSSize, RSize, MSize int) *VectorMachine {
                          })                                                 !    return &VectorMachine{
                       case STORE_VALUE:                                             NewCore(CSSize, MSize),
                          v.Execute(func(o []int) {                                  make([]Memory, RSize)
                               copy(v.M[o[0]:], v.R[o[1]])                         }
                          })                                                 }
                       case ADD:
                          v.Execute(func(o []int) {                          const (
                               a, b := v.R[o[0]], v.R[o[1]]                    CONSTANT = iota
                               if len(a) < len(b) {                            LOAD_VALUE
                                   for i, x := range a { a[i] = x + b[i] }     STORE_VALUE
                               } else {                                        ADD
                                   for i, x := range b { a[i] += x }         )
                               }
                          })
                 !    !      default:
                 !    !      !      panic(ILLEGAL_OPERATION)
                 !    !      }
                 !    })
                 }




Friday, 15 October 2010                                                                                                                    59
package main
                 import . “vmachine”
                 import . “instructions”

                 func main() {
                   r := NewVMachine(10, 10, 8)
                   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] [] [] [] [] [] [] []]




Friday, 15 October 2010                                                                                                   60
superscalar
                          multiple execution units

                             processor caching

                          out-of-order execution



Friday, 15 October 2010                              61
close to the machine
                                  interrupts

                                transport buses

                               peripheral drivers



Friday, 15 October 2010                             62
finding out more

                          http://golightly.games-with-brains.net

                          http://github.com/feyeleanor/GoLightly

                          twitter://#golightly

                          wikipedia

                          google



Friday, 15 October 2010                                            63

More Related Content

Similar to GoLightly: Building VM-based language runtimes in Go

Akka scalaliftoff london_2010
Akka scalaliftoff london_2010Akka scalaliftoff london_2010
Akka scalaliftoff london_2010Skills Matter
 
Cas2010 herramientas-de-pruebas-unitarias-pex-y-moles
Cas2010 herramientas-de-pruebas-unitarias-pex-y-molesCas2010 herramientas-de-pruebas-unitarias-pex-y-moles
Cas2010 herramientas-de-pruebas-unitarias-pex-y-molesAgile Spain
 
Pythonic APIs - Anthony Baxter
Pythonic APIs - Anthony BaxterPythonic APIs - Anthony Baxter
Pythonic APIs - Anthony Baxterknappt
 
Muruca: Linked Data in Art History
Muruca: Linked Data in Art HistoryMuruca: Linked Data in Art History
Muruca: Linked Data in Art HistoryMichele Barbera
 
Model-based Research in Human-Computer Interaction (HCI): Keynote at Mensch u...
Model-based Research in Human-Computer Interaction (HCI): Keynote at Mensch u...Model-based Research in Human-Computer Interaction (HCI): Keynote at Mensch u...
Model-based Research in Human-Computer Interaction (HCI): Keynote at Mensch u...Ed Chi
 
iBizLog. Smalltalking the Web
iBizLog. Smalltalking the WebiBizLog. Smalltalking the Web
iBizLog. Smalltalking the WebESUG
 
OvertheAir 2010 html5 impact on application programming
OvertheAir 2010 html5 impact on application programmingOvertheAir 2010 html5 impact on application programming
OvertheAir 2010 html5 impact on application programmingTor Björn Minde
 
HTML5 impact on application programming
HTML5 impact on application programmingHTML5 impact on application programming
HTML5 impact on application programmingEricsson Labs
 
HTML5: Toolkits and Gaps
HTML5: Toolkits and GapsHTML5: Toolkits and Gaps
HTML5: Toolkits and Gapsdylanks
 
Puppet for Security Compliance - GOSCON 2010
Puppet for Security Compliance - GOSCON 2010Puppet for Security Compliance - GOSCON 2010
Puppet for Security Compliance - GOSCON 2010Puppet
 
UW Agile CP202 Class 3 Managing Software Debt
UW Agile CP202 Class 3 Managing Software DebtUW Agile CP202 Class 3 Managing Software Debt
UW Agile CP202 Class 3 Managing Software DebtChris Sterling
 
GateIn - Presented at Atlanta JUG on 1/19/2010
GateIn - Presented at Atlanta JUG on 1/19/2010GateIn - Presented at Atlanta JUG on 1/19/2010
GateIn - Presented at Atlanta JUG on 1/19/2010Wesley Hales
 
Hacking the Kinect with GAFFTA Day 4
Hacking the Kinect with GAFFTA Day 4Hacking the Kinect with GAFFTA Day 4
Hacking the Kinect with GAFFTA Day 4benDesigning
 
Creating OpenSocial Apps
Creating OpenSocial AppsCreating OpenSocial Apps
Creating OpenSocial AppsBastian Hofmann
 
Chatbots. Old Topic - New Era
Chatbots. Old Topic - New EraChatbots. Old Topic - New Era
Chatbots. Old Topic - New EraGregor Jarisch
 
DTrace talk at Oracle Open World
DTrace talk at Oracle Open WorldDTrace talk at Oracle Open World
DTrace talk at Oracle Open WorldAngelo Rajadurai
 
Connecting RIAs and hardware together
Connecting RIAs and hardware togetherConnecting RIAs and hardware together
Connecting RIAs and hardware togetherJustin Mclean
 
Open Source Tool Chains for Cloud Computing
Open Source Tool Chains for Cloud ComputingOpen Source Tool Chains for Cloud Computing
Open Source Tool Chains for Cloud ComputingMark Hinkle
 

Similar to GoLightly: Building VM-based language runtimes in Go (20)

Akka scalaliftoff london_2010
Akka scalaliftoff london_2010Akka scalaliftoff london_2010
Akka scalaliftoff london_2010
 
Cas2010 herramientas-de-pruebas-unitarias-pex-y-moles
Cas2010 herramientas-de-pruebas-unitarias-pex-y-molesCas2010 herramientas-de-pruebas-unitarias-pex-y-moles
Cas2010 herramientas-de-pruebas-unitarias-pex-y-moles
 
Pythonic APIs - Anthony Baxter
Pythonic APIs - Anthony BaxterPythonic APIs - Anthony Baxter
Pythonic APIs - Anthony Baxter
 
Muruca: Linked Data in Art History
Muruca: Linked Data in Art HistoryMuruca: Linked Data in Art History
Muruca: Linked Data in Art History
 
Model-based Research in Human-Computer Interaction (HCI): Keynote at Mensch u...
Model-based Research in Human-Computer Interaction (HCI): Keynote at Mensch u...Model-based Research in Human-Computer Interaction (HCI): Keynote at Mensch u...
Model-based Research in Human-Computer Interaction (HCI): Keynote at Mensch u...
 
Vagrant at LA Ruby
Vagrant at LA RubyVagrant at LA Ruby
Vagrant at LA Ruby
 
iBizLog. Smalltalking the Web
iBizLog. Smalltalking the WebiBizLog. Smalltalking the Web
iBizLog. Smalltalking the Web
 
OvertheAir 2010 html5 impact on application programming
OvertheAir 2010 html5 impact on application programmingOvertheAir 2010 html5 impact on application programming
OvertheAir 2010 html5 impact on application programming
 
HTML5 impact on application programming
HTML5 impact on application programmingHTML5 impact on application programming
HTML5 impact on application programming
 
HTML5: Toolkits and Gaps
HTML5: Toolkits and GapsHTML5: Toolkits and Gaps
HTML5: Toolkits and Gaps
 
Puppet for Security Compliance - GOSCON 2010
Puppet for Security Compliance - GOSCON 2010Puppet for Security Compliance - GOSCON 2010
Puppet for Security Compliance - GOSCON 2010
 
UW Agile CP202 Class 3 Managing Software Debt
UW Agile CP202 Class 3 Managing Software DebtUW Agile CP202 Class 3 Managing Software Debt
UW Agile CP202 Class 3 Managing Software Debt
 
GateIn - Presented at Atlanta JUG on 1/19/2010
GateIn - Presented at Atlanta JUG on 1/19/2010GateIn - Presented at Atlanta JUG on 1/19/2010
GateIn - Presented at Atlanta JUG on 1/19/2010
 
Hacking the Kinect with GAFFTA Day 4
Hacking the Kinect with GAFFTA Day 4Hacking the Kinect with GAFFTA Day 4
Hacking the Kinect with GAFFTA Day 4
 
Creating OpenSocial Apps
Creating OpenSocial AppsCreating OpenSocial Apps
Creating OpenSocial Apps
 
Chatbots. Old Topic - New Era
Chatbots. Old Topic - New EraChatbots. Old Topic - New Era
Chatbots. Old Topic - New Era
 
Linux on System z Disk I/O Performance
Linux on System z Disk I/O PerformanceLinux on System z Disk I/O Performance
Linux on System z Disk I/O Performance
 
DTrace talk at Oracle Open World
DTrace talk at Oracle Open WorldDTrace talk at Oracle Open World
DTrace talk at Oracle Open World
 
Connecting RIAs and hardware together
Connecting RIAs and hardware togetherConnecting RIAs and hardware together
Connecting RIAs and hardware together
 
Open Source Tool Chains for Cloud Computing
Open Source Tool Chains for Cloud ComputingOpen Source Tool Chains for Cloud Computing
Open Source Tool Chains for Cloud Computing
 

More from 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
 

More from 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
 

Recently uploaded

Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningLars Bell
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyAlfredo García Lavilla
 
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
 
Search Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfSearch Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfRankYa
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsRizwan Syed
 
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfPrecisely
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsMiki Katsuragi
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxhariprasad279825
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brandgvaughan
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):comworks
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...Fwdays
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024Stephanie Beckett
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsPixlogix Infotech
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 3652toLead Limited
 

Recently uploaded (20)

Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine Tuning
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easy
 
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
 
Search Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfSearch Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdf
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL Certs
 
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering Tips
 
Artificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptxArtificial intelligence in cctv survelliance.pptx
Artificial intelligence in cctv survelliance.pptx
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
WordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your BrandWordPress Websites for Engineers: Elevate Your Brand
WordPress Websites for Engineers: Elevate Your Brand
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and Cons
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365
 

GoLightly: Building VM-based language runtimes in Go

  • 1. GoLightly Building VM-based language runtimes in Go Eleanor McHugh http://golightly.games-with-brains.net Friday, 15 October 2010 1
  • 2. portrait of an artist... physics major http://feyele embedded systems dynamic languages dns provisioning network scaling or.tel an questionable taste in music Elean or McHugh Friday, 15 October 2010 2
  • 3. today’s menu an overview of golightly a crash course in go programming application virtualisation & soft machines Friday, 15 October 2010 3
  • 4. caveat lector danger! we’re entering strange territory our map is missing major landmarks and will be riddled with inaccuracies so please tread carefully try not to disturb the local wildlife and don’t be put off by the pages of code Friday, 15 October 2010 4
  • 5. golightly agnostic heterogenous virtualisation networks Friday, 15 October 2010 5
  • 6. go... a systems language by google productivity, performance, concurrency lighter than Java, safer than C Friday, 15 October 2010 6
  • 7. ...lightly clean abstractions geared to performance non-viral open source license Friday, 15 October 2010 7
  • 8. inspiration processor design sensor and control networks field-programmable gate arrays Friday, 15 October 2010 8
  • 9. perspiration iterative empirical development explore -> implement -> test -> benchmark evolve towards elegance Friday, 15 October 2010 9
  • 10. principles decoupling improves scalability coherence simplifies organisation optimisations are application specific Friday, 15 October 2010 10
  • 11. agnostic no blessed programming languages flexible platform abstractions write once, run everywhere it matters Friday, 15 October 2010 11
  • 12. heterogeneous a system comprises many components components may differ in purpose and design but they cooperate to solve problems Friday, 15 October 2010 12
  • 13. virtualisation design discrete Turing machines implement these machines in software compile programs to run on them Friday, 15 October 2010 13
  • 14. networks machines cooperate by sending messages machine states can be serialised as messages messages transcend process and host boundaries Friday, 15 October 2010 14
  • 15. go a crash course Friday, 15 October 2010 15
  • 16. behind the hype a statically-typed compiled language class-free object-orientation nominal type declaration structural type inference garbage collection concurrency via communication (CSP) Friday, 15 October 2010 16
  • 17. an elegant tool the safety of a static type system the feel of a dynamic runtime the performance of a compiled language no dependence on runtime libraries Friday, 15 October 2010 17
  • 18. nominal types primitive (boolean, numeric, pointer) aggregate (array, slice, map, struct) functional (closure, channel) all types can underpin user-defined types methods are declared on user-defined types types can be embedded in struct types Friday, 15 October 2010 18
  • 19. package Integer package main import “Integer” type Int int func main() { func (i *Int) Add(x int) { i := Integer.Buffer{0, 1, 2, 3, 4, 5} *i += Int(x) b := i.Clone() } b.Swap(1, 2) b.Move(3, 2) type Buffer []Int b[0].Add(3) println(“b[0:2] = {”, b[0], “,”, b[1], “}”) func (b Buffer) Clone() Buffer { } s := make(Buffer, len(b)) copy(s, b) return s } func (b Buffer) Swap(i, j int) { b[i], b[j] = b[j], b[i] } 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) produces: } b[0:2] = { 6, 4 } Friday, 15 October 2010 19
  • 20. package Vector package main import . “Integer” import “Integer” type Vector struct { func main() { Buffer i := Vector{Buffer{0, 1, 2, 3, 4, 5}} } b := i.Clone() b.Swap(1, 2) func (v *Vector) Clone() Vector { b.Move(3, 2) return Vector{v.Buffer.Clone()} s := b.Slice(0, 2) } s[0].Add(3) b.Replace(s) func (v *Vector) Slice(i, j int) Buffer { println(“b[0:2] = {”, b.Buffer[0], “,”, b.Buffer[1], “}”) return v.Buffer[i:j] } } func (v *Vector) Replace(o interface{}) { switch o := o.(type) { case Vector: v=o case Buffer: v.Buffer = o } } produces: b[0:2] = { 6, 4 } Friday, 15 October 2010 20
  • 21. structural types interfaces define method sets they can be embedded within each other but do not implement methods a type can implement many interfaces type inference determines which if any all types implement the blank interface Friday, 15 October 2010 21
  • 22. package main type Calculator struct { Adder type Adder interface { } Add(j int) Subtract(j int) func main() { Result() interface{} c := Calculator{} } c.Adder = IntAdder{0, 1, 2, 3, 4, 5} c.Add(1) type IntAdder []int c.Add(2) func (i IntAdder) Add(j int) { c.Subtract(3) i[0] += i[j] println("c.Result() =", c.Result().(int)) } func (i IntAdder) Subtract(j int) { c.Adder = FloatAdder{0.0, 1.1, 2.2, 3.3, 4.4, 5.5} i[0] -= i[j] c.Add(1) } c.Add(2) func (i IntAdder) Result() interface{} { c.Subtract(3) return i[0] println("c.Result() =", c.Result()) } } type FloatAdder []float func (f FloatAdder) Add(j int) { f[0] += f[j] } func (f FloatAdder) Subtract(j int) { f[0] -= f[j] } produces: func (f FloatAdder) Result() interface{} { c.Result() = 0 return f[0] c.Result() = (0x10f94,0x34800000) } Friday, 15 October 2010 22
  • 23. dynamic typing type assertions type switches runtime reflection Friday, 15 October 2010 23
  • 24. package generalise func Duplicate(i interface{}) (clone interface{}) { import "fmt" if clone = Allocate(i); clone != nil { import . "reflect" switch clone := NewValue(clone).(type) { case *SliceValue: func Allocate(i interface{}, limit... int) (n interface{}) { s := NewValue(i).(*SliceValue) switch v := NewValue(i).(type) { ArrayCopy(clone, s) case *SliceValue: case *MapValue: l := v.Cap() m := NewValue(i).(*MapValue) if len(limit) > 0 { l = limit[0] } for _, k := range m.Keys() { t := v.Type().(*SliceType) clone.SetElem(k, m.Elem(k)) n = MakeSlice(t, l, l).Interface() } case *MapValue: } n = MakeMap(v.Type().(*MapType)).Interface() } } return return } } func SwapSlices(i interface{}, d, s, n int) { if v, ok := NewValue(i).(*SliceValue); ok { source := v.Slice(s, s + n) destination := v.Slice(d, d + n) temp := NewValue(Allocate(i, n)).(*SliceValue) ArrayCopy(temp, destination) ArrayCopy(destination, source) ArrayCopy(source, temp) } } Friday, 15 October 2010 24
  • 25. package main import . “generalise” func main() { error_text := “panic caused by” defer func() { if x := recover(); x != nil { fmt.Println(error_text, x) } }() s1 := []int{0, 1, 2, 3, 4, 5} fmt.Println("s1 =", s1) s2 := Duplicate(s1) fmt.Println("s2 =", s2, "Duplicate(s1)") SwapSlices(s2, 0, 3, 3) fmt.Println("s2 =", s2, "SwapSlices(s2, 0, 3, 3)") s3 := Allocate(s1, 1) fmt.Println("s3 =", s3, "Allocate(s1, 1)") produces: m := map[int] int{1: 1, 2: 2, 3: 3, 0: 0, 4: 4, 5: 5} s1 = [0 1 2 3 4 5] fmt.Println("m =", m) s2 = [0 1 2 3 4 5] Duplicate(s1) n := Allocate(m) fmt.Println("n =", n, "Allocate(m)") s2 = [3 4 5 0 1 2] SwapSlices(s2, 0, 3, 3) SwapSlices(m, 0, 3, 3) s3 = [0] Allocate(s1, 1) } m = map[3:3 0:0 1:1 4:4 5:5 2:2] n = map[] panic caused by map[3:3 0:0 1:1 4:4 5:5 2:2] Friday, 15 October 2010 25
  • 26. goroutines concurrent threads of control launched by the go statement which returns immediately each may be a function call or method call and can communicate via channels Friday, 15 October 2010 26
  • 27. channels link concurrently executing functions support sending and/or receiving only accept items of a specified type synchronous channels are unbuffered asynchronous channels are buffered Friday, 15 October 2010 27
  • 28. package generalise func (f Iteration) Each(c interface{}) { import . "reflect" switch c := NewValue(c).(type) { case *SliceValue: type Results chan interface{} count := c.Len() SignalSource(func(done chan bool) { type SignalSource func(status chan bool) for i := 0; i < count; i++ { func (s SignalSource) Pipeline() { f.apply(i, c.Elem(i).Interface(), done) done := make(chan bool) } defer close(done) }).Multiplex(count) go s(done) case *MapValue: <-done SignalSource(func(done chan bool) { } for _, k := range c.Keys() { f.apply(k, c.Elem(k).Interface(), done) func (s SignalSource) Multiplex(count int) { } done := make(chan bool) }).Multiplex(c.Len()) defer close(done) } go s(done) } for i := 0; i < count; i++ { <- done type Combination func(x, y interface{}) interface{} } func (f Combination) Reduce(c, s interface{}) (r Results) { } r = make(Results) go func() { type Iteration func(k, x interface{}) Iteration(func(k, x interface{}) { func (i Iteration) apply(k, v interface{}, c chan bool) { s = f(s, x) go func() { }).Each(c) i(k, v) r <- s c <- true }() }() return } } Friday, 15 October 2010 28
  • 29. type Transformation func(x interface{}) interface{} package main func (t Transformation) GetValue(x interface{}) Value { import “fmt” return NewValue(t(x)) import . “generalise” } var adder Combination = func(x, y interface{}) interface{} { func (t Transformation) Map(c interface{}) interface{} { return x.(int) + y.(int) switch n := NewValue(Allocate(c)).(type) { } case *SliceValue: SignalSource(func(done chan bool) { var multiplier Transformation = func(x interface{}) interface{} { Iteration(func(k, x interface{}) { return x.(int) * 2 n.Elem(k.(int)).SetValue(t.GetValue(x)) } }).Each(c) done <- true func main() { }).Pipeline() s := []int{0, 1, 2, 3, 4, 5} return n.Interface() fmt.Println("s =", s) case *MapValue: fmt.Println("sum s =", (<- adder.Reduce(s, 0)).(int)) SignalSource(func(done chan bool) { Iteration(func(k, x interface{}) { c := multiplier.Map(s) n.SetElem(NewValue(k), t.GetValue(x)) fmt.Println("c =", c) }).Each(c) fmt.Println("sum c =", (<- adder.Reduce(c, 0)).(int)) done <- true } }).Pipeline() return n.Interface() } produces: return Duplicate(c) s = [0 1 2 3 4 5] } sum s = 15 c = [0 2 4 6 8 10] sum c = 30 Friday, 15 October 2010 29
  • 30. tooling gotest is a testing framework which also supports benchmarking gofmt standardises code layout godoc formats and serves documentation goinstall is an automatic package installer cgo integrates C code with go Friday, 15 October 2010 30
  • 31. software machines application virtualisation 101 Friday, 15 October 2010 31
  • 32. system clock synchronising components Friday, 15 October 2010 32
  • 33. package clock package main import "syscall" import . “clock” type Clock struct { func main() { Period int64 c := Clock{1000, make(chan int64), make(chan bool), false} Count chan int64 c.Start() Control chan bool active bool for i := 0; i < 3; i++ { } println("pulse value", <-c.Count, "from clock") } func (c *Clock) Start() { if !c.active { println("disabling clock") go func() { c.Control <- false c.active = true syscall.Sleep(1000000) for i := int64(0); ; i++ { println("restarting clock") select { c.Control <- true case status := <- c.Control: println("pulse value", <-c.Count, "from clock") c.active = status } default: if c.active { c.Count <- i produces: } pulse value 0 from clock syscall.Sleep(c.Period) pulse value 1 from clock } } pulse value 2 from clock }() disabling clock } restarting clock } pulse value 106 from clock Friday, 15 October 2010 33
  • 34. instruction set specifying operation sequences Friday, 15 October 2010 34
  • 35. package instructions func (i Instruction) Execute(op Operation) { import "fmt" op(i.Operands()) } type Operation func(o []int) type Assembler struct { type Executable interface { opcodes map[string] int Opcode() int names map[int] string Operands() []int } Execute(op Operation) } func NewAssember(names... string) (a Assembler) { a = Assembler{ make(map[string] int), make(map[int] string) } const INVALID_OPCODE = -1 a.Define(names...) return type Instruction []int } func (i Instruction) Opcode() int { if len(i) == 0 { func (a Assembler) Assemble(name string, params... int) return INVALID_OPCODE (i Instruction) { } i = make(Instruction, len(params) + 1) return i[0] if opcode, ok := a.opcodes[name]; ok { } i[0] = opcode } else { func (i Instruction) Operands() []int { i[0] = INVALID_OPCODE if len(i) < 2 { } return []int{} copy(i[1:], params) } return return i[1:] } } Friday, 15 October 2010 35
  • 36. func (a Assembler) Define(names... string) { package main for _, name := range names { import . “instructions” a.opcodes[name] = len(a.names) a.names[len(a.names)] = name func main() { } a := NewAssembler("noop", "load", "store") } p := Program{ a.Assemble("noop"), a.Assemble("load", 1), func (a Assembler) Disassemble(e Executable) (s string) { a.Assemble("store", 1, 2), if name, ok := a.names[e.Opcode()]; ok { a.Assemble("invalid", 3, 4, 5) } s = name p.Disassemble(a) if params := e.Operands(); len(params) > 0 { for _, v := range p { s = fmt.Sprintf("%vt%v", s, params[0]) if len(v.Operands()) == 2 { for _, v := range params[1:] { v.Execute(func(o []int) { s = fmt.Sprintf("%v, %v", s, v) o[0] += o[1] } }) } println("op =", v.Opcode(), "result =", v.Operands()[0]) } else { } s = "unknown" } } } return } produces: type Program []Executable noop func (p Program) Disassemble(a Assembler) { load! ! 1 for _, v := range p { fmt.Println(a.Disassemble(v)) store! 1, 2 } unknown } op = 2 result = 3 Friday, 15 October 2010 36
  • 37. CISC semantically rich instructions complex memory addressing modes compact binary code Friday, 15 October 2010 37
  • 38. RISC separate IO and data processing register-to-register instructions load/store memory access Friday, 15 October 2010 38
  • 39. VLIW multiple operations per instruction compiler statically determines parallelism simplifies control logic Friday, 15 October 2010 39
  • 40. memory storing data and instructions Friday, 15 October 2010 40
  • 41. subtleties von Neumann Harvard indirection bits Friday, 15 October 2010 41
  • 42. package memory func Overwrite(i interface{}, b []byte) interface{} { import "fmt" switch i := NewValue(i).(type) { import . "reflect" case *SliceValue: import "unsafe" h := Header(unsafe.Pointer(&b)) t := i.Type().(*SliceType) var _BYTE_SLICE = Typeof([]byte(nil)) Resize(&h, int(t.Elem().Size()), 1) var _SLICE_TYPE = Typeof(SliceHeader{}) return unsafe.Unreflect(t, unsafe.Pointer(&h)) } func Data(addr unsafe.Pointer) []byte { return nil return unsafe.Unreflect(_BYTE_SLICE, addr).([]byte) } } func Resize(h *SliceHeader, d, m int) { h.Len /= d h.Len *= m } func Serialise(i interface{}) []byte { switch i := NewValue(i).(type) { case *SliceValue: h := Header(unsafe.Pointer(i.Addr())) t := i.Type().(*SliceType) Resize(&h, 1, int(t.Elem().Size())) return Data(unsafe.Pointer(&h)) } return nil } Friday, 15 October 2010 42
  • 43. package main import “fmt” import . "memory" type Memory []int func main() { m := make(Memory, 2) fmt.Println("m (cells) =", len(m), "of", cap(m), ":", m) b := Serialise(m) fmt.Println("b (bytes) =", len(b), "of", cap(b), ":", b) n := Overwrite(m, []byte{0, 0, 0, 1, 0, 0, 0, 1}).(Memory) fmt.Println("n (cells) =", len(n), "of", cap(n), ":", n) b = Serialise(n) fmt.Println("b (bytes) =", len(b), "of", cap(b), ":", b) } produces: m (cells) = 2 of 2 : [0 0] b (bytes) = 8 of 2 : [0 0 0 0 0 0 0 0] n (cells) = 2 of 8 : [16777216 16777216] b (bytes) = 8 of 8 : [0 0 0 1 0 0 0 1] Friday, 15 October 2010 43
  • 44. processor core tying it all together Friday, 15 October 2010 44
  • 45. package processor func (p *Core) Reset() { import . “instructions” p.Running = false import . “memory” p.Flags = PROCESSOR_READY } const PROCESSOR_READY = 0 const PROCESSOR_BUSY = 1 func (c *Core) RunExclusive(p []Executable, f func()) { const CALL_STACK_UNDERFLOW = 2 defer func() { const CALL_STACK_OVERFLOW = 4 c.Running = false const ILLEGAL_OPERATION = 8 if x := recover(); x != nil { const INVALID_ADDRESS = 16 c.Flags &= x.(int) } type Processor interface { }() ! Run(p []Executable) if c.Running { } panic(PROCESSOR_BUSY) } type Core struct { c.Running = true Ticks! ! int for c.PC = 0; c.Running; { Running! bool c.LoadInstruction(p) PC, Flags! int f() CS! ! []int c.Ticks++ M! ! Memory } OP! ! Executable } } func (c *Core) LoadInstruction(program []Executable) { func NewCore(CSSize, MSize int) ProcessorCore { if c.PC >= len(program) { return Core{ panic(PROCESSOR_READY) CS: make([]int, 0, Calls)}, } M: make(Memory, MSize), c.Executable = program[c.PC] } c.PC++ } } Friday, 15 October 2010 45
  • 46. package processor func (c *Core) Goto(addr int) { ! c.PC = addr } func (c *Core) Call(addr int) { if top := len(c.CS); top < cap(c.CS) - 1 { c.CS = c.CS[:top + 1] c.CS[top] = c.PC c.PC = addr } else { panic(CALL_STACK_OVERFLOW) } } func (c *Core) TailCall(addr int) { ! c.CS[len(c.CS) - 1] = c.PC ! c.PC = addr } func (c *Core) Return() { ! if top := len(c.CS); top > 0 { ! ! c.PC, c.CS = c.CS[top - 1], c.CS[:top] ! } else { ! ! panic(CALL_STACK_UNDERFLOW) ! } } Friday, 15 October 2010 46
  • 47. package main func main() { import . “processor” c := NewCore(10, 8) import . “instructions” p := []Executable{ Instruction{CALL, 2}, const ( Instruction{GOTO, 5}, CALL = iota Instruction{MOVE, 2}, GOTO Instruction{RETURN}, MOVE Instruction{MOVE, -1}, RETURN } ) c.RunExclusive(p, dispatcher) fmt.Println("Instructions Executed:", c.Ticks) var dispatcher = func() { fmt.Println("PC =", c.PC) switch c.Opcode() { if c.Flags | PROCESSOR_READY == PROCESSOR_READY { case CALL: fmt.Println("Core Ready") c.Execute(func(o []int) { c.Call(o[0]) }) } else { case GOTO: fmt.Println("Core Error:", c.Flags) 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: produces: panic(ILLEGAL_OPERATION) top = 0 } cap(c.CS) -1 = 9 } Instructions Executed: 2 PC = 5 Core Ready Friday, 15 October 2010 47
  • 48. accumulator machine 1-operand instructions data from memory combined with accumulator result stored in accumulator Friday, 15 October 2010 48
  • 49. package accmachine func (a *AccMachine) Run(program []Executable) { import . “processor” a.RunExclusive(program, func() { import . “memory” switch a.Opcode() { case CONSTANT: const ( a.Execute(func(o []int) { CONSTANT = iota a.AC = o[0] LOAD_VALUE }) STORE_VALUE case LOAD_VALUE: ADD a.Execute(func(o []int) { ) a.AC = a.M[o[0]] }) type AccMachine struct { case STORE_VALUE: ! Core a.Execute(func(o []int) { ! AC! ! ! ! int a.M[o[0]] = a.AC } }) case ADD: func NewAccMachine(CSSize, MSize int) *AccMachine { a.Execute(func(o []int) { ! return &AccMachine{NewCore(CSSize, MSize), 0} a.AC += a.M[o[0]] } }) default: panic(ILLEGAL_OPERATION) } }) } Friday, 15 October 2010 49
  • 50. package main import . “accmachine” import . “instructions” func main() { a := NewAccMachine(10, 8) 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 Friday, 15 October 2010 50
  • 51. stack machine 0-operand instructions data popped from stack results pushed on stack Friday, 15 October 2010 51
  • 52. package smachine type StackMachine struct { import . “processor” Core DS! []int func (s *StackMachine) Run(program []Executable) { } s.RunExclusive(program, func() { switch s.Opcode() { func (s *StackMachine) Push(v int) { case CONSTANT: top := len(s.DS) s.Execute(func(o []int) { s.DS, s.DS[top] = s.DS[:top + 1], v s.Push(o[0]) } }) case PUSH_VALUE: func (s *StackMachine) Pop(addr int) { s.Execute(func(o []int) { top := len(s.DS) - 1 s.Push(s.M[o[0]]) s.M[addr], s.DS = s.DS[top], s.DS[:top] }) } case POP_VALUE: s.Execute(func(o []int) { const ( s.Pop(s.M[o[0]]) CONSTANT = iota }) PUSH_VALUE case ADD: POP_VALUE s.Execute(func(o []int) { ADD l := len(s.DS) ) s.DS[l - 2] += s.DS[l - 1] s.DS = s.DS[:l - 1] func NewStackM(CSSize, DSSize, MSize int) *StackMachine { }) return &StackMachine{ default: DS: make([]int, 0, DSSize), panic(ILLEGAL_OPERATION) Core: NewCore(CSSize, MSize), } } }) } } Friday, 15 October 2010 52
  • 53. package main import . “smachine” import . “instructions” func main() { s := NewStackM(10, 10, 8) 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] Friday, 15 October 2010 53
  • 54. register machine multi-operand instructions data read from memory into registers operator combines registers and stores Friday, 15 October 2010 54
  • 55. package rmachine type RegisterMachine struct { import . “processor” ! Core ! R! ! Memory func (r *RegisterMachine) Run(program []Executable) { } ! r.RunExclusive(program, func() { ! ! switch r.Opcode() { const ( ! ! case CONSTANT: CONSTANT = iota ! ! ! r.Execute(func(o []int) { LOAD_VALUE ! ! ! ! r.R[o[0]] = o[1] STORE_VALUE ! ! ! }) ADD ! ! case LOAD_VALUE: ) ! ! ! r.Execute(func(o []int) { ! ! ! ! r.R[o[0]] = r.M[o[1]] func NewRMachine(CSSize, RSize, MSize int) *RegisterMachine { ! ! ! }) return &RegisterMachine{ ! ! case STORE_VALUE: NewCore(CSSize, MSize), ! ! ! r.Execute(func(o []int) { make([]int, RSize) ! ! ! ! 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) ! ! } ! }) } Friday, 15 October 2010 55
  • 56. package main import . “rmachine” import . “instructions” func main() { r := NewRMachine(10, 10, 8) 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] Friday, 15 October 2010 56
  • 57. transport triggering register machine architecture exposes internal buses and components operations are side-effects of internal writes Friday, 15 October 2010 57
  • 58. vector machine multi-operand instructions data vectors read from memory into registers operations combine registers Friday, 15 October 2010 58
  • 59. package vmachine type VectorMachine struct { import . “processor” ! Core ! R! ! []Memory func (v *VectorMachine) Run(program []Executable) { } v.RunExclusive(program, func() { switch v.Opcode() { func (v *VectorMachine) Load(r int, m Memory) { case CONSTANT: ! v.R[r] = make(Memory, len(m)) v.Execute(func(o []int) { v.Load(o[0], o[1:]) }) ! copy(v.R[r], m) case LOAD_VALUE: } v.Execute(func(o []int) { v.Load(o[0], v.M[o[1]:o[1] + o[2]]) func NewVMachine(CSSize, RSize, MSize int) *VectorMachine { }) ! return &VectorMachine{ case STORE_VALUE: NewCore(CSSize, MSize), v.Execute(func(o []int) { make([]Memory, RSize) copy(v.M[o[0]:], v.R[o[1]]) } }) } case ADD: v.Execute(func(o []int) { const ( a, b := v.R[o[0]], v.R[o[1]] CONSTANT = iota if len(a) < len(b) { LOAD_VALUE for i, x := range a { a[i] = x + b[i] } STORE_VALUE } else { ADD for i, x := range b { a[i] += x } ) } }) ! ! default: ! ! ! panic(ILLEGAL_OPERATION) ! ! } ! }) } Friday, 15 October 2010 59
  • 60. package main import . “vmachine” import . “instructions” func main() { r := NewVMachine(10, 10, 8) 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] [] [] [] [] [] [] []] Friday, 15 October 2010 60
  • 61. superscalar multiple execution units processor caching out-of-order execution Friday, 15 October 2010 61
  • 62. close to the machine interrupts transport buses peripheral drivers Friday, 15 October 2010 62
  • 63. finding out more http://golightly.games-with-brains.net http://github.com/feyeleanor/GoLightly twitter://#golightly wikipedia google Friday, 15 October 2010 63

Editor's Notes