GoLightly: A Go Library For Building Virtual Machines

2,220 views

Published on

GoLightly is a flexible library for building virtual machines in Go. Instead of a single general purpose VM it encourages the use of many small, specialised VMs working in concert.

Published in: Technology
0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
2,220
On SlideShare
0
From Embeds
0
Number of Embeds
292
Actions
Shares
0
Downloads
43
Comments
0
Likes
3
Embeds 0
No embeds

No notes for slide




















  • GoLightly: A Go Library For Building Virtual Machines

    1. 1. GoLightly A Go library for building Virtual Machines Eleanor McHugh
    2. 2. Go
    3. 3. a new language statically-typed and compiled object-oriented but no classes garbage collected concurrency via communication (CSP) type polymorphism via interfaces
    4. 4. a new way of working the safety of a static type system the feel of a dynamic runtime the performance of a compiled language
    5. 5. Virtual Machines
    6. 6. from inspiration... computation serialisation communication
    7. 7. ...to perspiration simulation v. emulation instruction set design bytecodes memory abstraction operation dispatch
    8. 8. GoLightly
    9. 9. principles interface driven delegation architecture agnostic inspired by hardware techniques decoupled components scaling through specialisation
    10. 10. caveat references current dev branch fundamental changes from github still evolving next release due for Strange Loop
    11. 11. interfaces type Executable interface { type Comparable interface { Execute(p Processor) Identical(v Value) bool } Compare(v Value) int } type Processor interface { Reset() type Value interface { Step() fmt.Stringer Jump(a Address) Comparable Call(a Address) Nil() Value Return() IsNil() bool Load(program Program) } Run() Execute() type Program []Executable Sleep(n int64) Halt(n int) IsActive() bool }
    12. 12. instructions obey the Executable interface expressed as separate types no assumptions about semantics not tied to a bytecode representation
    13. 13. flow control type NoOp struct {} type Call Address func (n *NoOp) String() string { func (c Call) String() string { return "NOOP" return Sprint("CALL", Address(c)) } } func (n *NoOp) Execute(p Processor) {} func (c Call) Execute(p Processor) { p.Call(Address(c)) type Halt struct {} } func (h *Halt) String() string { return "HALT" type Return struct {} } func (r Return) String() string { func (h *Halt) Execute(p Processor) { return "RET" p.Halt(PROGRAM_TERMINATED) } } func (r Return) Execute(p Processor) { p.Return() type Jump Address } func (j Jump) String() string { return Sprint("JMP", Address(j)) } func (j Jump) Execute(p Processor) { p.Jump(Address(j)) }
    14. 14. bytecode type ByteCode []int case 5: / JMPZ n / case 10: / POP r / func (b *ByteCode) String() string { PC++ PC++ return "BYTECODE" if C == 0 { R[b[PC]] = DS.Pop() } PC++ case 11: / LOAD r, v / func (b *ByteCode) Execute(p Processor) { PC += b[PC] - 1 PC++ var PC, C, W int } else { W = b[PC] var R [2]int PC++ PC++ CS := new(vector.IntVector) } R[W] = b[PC] DS := new(vector.IntVector) case 6: / JMPNZ n / case 12: / ADD r1, r2 / for p.Active() { PC++ PC++ switch b[PC] { if C != 0 { W = b[PC] case 0: / NOOP / PC++ PC++ case 1: / NSLEEP n / PC += b[PC] - 1 R[b[PC]] += R[W] PC++ } else { default: p.Sleep(int64(b[PC])) PC++ p.Halt(ILLEGAL_INSTRUCTION) case 2: / SLEEP n / } } PC++ case 7: / CALL n / } p.Sleep(int64(b[PC]) << 32) PC++ } case 3: / HALT / CS.Push(PC) p.Halt(USER_HALT) PC = b[PC] return case 8: / RET / case 4: / JMP n / PC = CS.Pop PC++ case 9: / PUSH r / PC += b[PC] - 1 PC++ DS.Push(R[b[PC]])
    15. 15. processors typical Turing machines support flexible dispatch not tied to a given instruction set memory model agnostic ripe for specialisation
    16. 16. a scalar processor type SProc struct { func (s *SProc) Sleep(i int64) { func (s *SProc) Call(a Address){ Running bool syscall.Sleep(i) PC := s.PC PC int } s.PC = int(a) R IntBuffer for s.IsActive() { F FloatBuffer func (s *SProc) Halt(n int) { s.Execute() DS vector.IntVector s.Running = false s.Step() Program []Executable } } } s.PC = PC func (s *SProc) IsActive() bool{ } func (s *SProc) Run() { return s.Running && s.PC < s.Running = true len(s.Program) func (s *SProc) Return() { s.Call(0) } s.PC = len(s.Program) } } func (s *SProc) Reset() { func (s *SProc) Step() { s.R.ClearAll() s.PC++ s.PC = 0 } } func (s *SProc) Jump(a Address) { func (s *SProc) Load(program s.PC += int(a) Program) { } s.Reset() s.Program = program func (s *SProc) Execute() { } s.Program[s.PC].Execute(s) }
    17. 17. memory based on allocated Values aggregate as ValueStores require boxing/unboxing buffers for specific types buffers are also ValueStores
    18. 18. benefits encourages simple designs many different VMs per executable can run in separate goroutines easily duplicated and serialised split across processes or hosts
    19. 19. the future single dispatch for vector operations per vasive threading runtime code rewriting speculative loading JIT compilation
    20. 20. find out more http://github.com/feyeleanor/GoLightly http://golightly.wikidot.com t witter://#golightly

    ×