Skip to content

Commit

Permalink
Refactor to context based stack
Browse files Browse the repository at this point in the history
  • Loading branch information
elct9620 committed Nov 30, 2023
1 parent 265ca5c commit 9208fc4
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 21 deletions.
7 changes: 6 additions & 1 deletion context.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,13 @@ package mruby

import "github.com/elct9620/mruby-go/stack"

const StackInitSize = 128

type context struct {
callinfo *stack.Stack[*callinfo]
stackBase int
stackEnd int
stack []Value
callinfo *stack.Stack[*callinfo]
}

func (ctx *context) GetCallinfo() *callinfo {
Expand Down
36 changes: 19 additions & 17 deletions irep.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,73 +45,75 @@ func newIRep(r *Reader) (*iRep, error) {
}

func (ir *iRep) Execute(state *State) (Value, error) {
regs := make([]Value, ir.nRegs)
ci := state.context.GetCallinfo()
offset := ci.stackOffset
regs := state.context.stack

for {
opCode := ir.iSeq.ReadCode()

switch opCode {
case opMove:
regs[ir.iSeq.ReadB()] = regs[ir.iSeq.ReadB()]
regs[offset+int(ir.iSeq.ReadB())] = regs[offset+int(ir.iSeq.ReadB())]
case opLoadI:
a := ir.iSeq.ReadB()
b := ir.iSeq.ReadB()
regs[a] = int(b)
regs[offset+int(a)] = int(b)
case opLoadINeg:
a := ir.iSeq.ReadB()
b := ir.iSeq.ReadB()
regs[a] = -int(b)
regs[offset+int(a)] = -int(b)
case opLoadI__1, opLoadI_0, opLoadI_1, opLoadI_2, opLoadI_3, opLoadI_4, opLoadI_5, opLoadI_6, opLoadI_7:
a := ir.iSeq.ReadB()
regs[a] = int(opCode) - int(opLoadI_0)
regs[offset+int(a)] = int(opCode) - int(opLoadI_0)
case opLoadT, opLoadF:
a := ir.iSeq.ReadB()
regs[a] = opCode == opLoadT
regs[offset+int(a)] = opCode == opLoadT
case opLoadI16:
a := ir.iSeq.ReadB()
b := ir.iSeq.ReadS()
regs[a] = int(int16(binary.BigEndian.Uint16(b)))
regs[offset+int(a)] = int(int16(binary.BigEndian.Uint16(b)))
case opLoadI32:
a := ir.iSeq.ReadB()
b := ir.iSeq.ReadW()
regs[a] = int(int32(binary.BigEndian.Uint32(b)))
regs[offset+int(a)] = int(int32(binary.BigEndian.Uint32(b)))
case opLoadSym:
a := ir.iSeq.ReadB()
b := ir.iSeq.ReadB()
regs[a] = ir.syms[b]
regs[offset+int(a)] = ir.syms[b]
case opSelfSend:
a := ir.iSeq.ReadB()
b := ir.iSeq.ReadB()
c := ir.iSeq.ReadB()

regs[a] = regs[0]
regs[offset+int(a)] = regs[offset]

ci := state.PushCallinfo(ir.syms[b], c, nil)
ci := state.PushCallinfo(ir.syms[b], int(a), c, nil)
ci.stack = append(ci.stack, regs[int(a)+1:int(a)+ci.numArgs+1]...)

recv := regs[0]
recv := regs[offset]
ci.targetClass = state.ClassOf(recv)
method := state.FindMethod(recv, ci.methodId)

if method == nil {
regs[a] = nil
regs[offset+int(a)] = nil
state.PopCallinfo()
break
}

regs[a] = method.Function(state, recv)
regs[offset+int(a)] = method.Function(state, recv)
state.PopCallinfo()
case opString:
a := ir.iSeq.ReadB()
b := ir.iSeq.ReadB()

regs[a] = ir.poolValue[b]
regs[offset+int(a)] = ir.poolValue[b]
case opReturn:
a := ir.iSeq.ReadB()
return regs[a], nil
return regs[offset+int(a)], nil
case opStrCat:
a := ir.iSeq.ReadB()
regs[a] = fmt.Sprintf("%v%v", regs[a], regs[a+1])
regs[offset+int(a)] = fmt.Sprintf("%v%v", regs[offset+int(a)], regs[offset+int(a)+1])
default:
return nil, fmt.Errorf("opcode %d not implemented", opCode)
}
Expand Down
9 changes: 9 additions & 0 deletions load.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,15 @@ func (s *State) Load(r io.Reader) (Value, error) {
return nil, err
}

if s.context.stack == nil {
s.context.stack = make([]Value, StackInitSize)
s.context.stackBase = 0
s.context.stackEnd = StackInitSize - 1
}

s.context.stack[0] = s.topSelf
s.context.callinfo.Push(&callinfo{})

return proc.Execute(s)
}

Expand Down
7 changes: 6 additions & 1 deletion mruby.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ type Method struct {
type callinfo struct {
numArgs int
methodId Symbol
stackOffset int
stack []Value
targetClass *RClass
}
Expand Down Expand Up @@ -43,5 +44,9 @@ func (s *State) GetArgc() int {
}

func (s *State) GetArgv() []Value {
return s.context.GetCallinfo().stack[1:]
ci := s.context.GetCallinfo()
begin := ci.stackOffset + 1
end := begin + ci.numArgs

return s.context.stack[begin:end]
}
5 changes: 3 additions & 2 deletions vm.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package mruby

func (state *State) PushCallinfo(mid string, argc byte, targetClass *RClass) *callinfo {
func (state *State) PushCallinfo(mid string, pushStack int, argc byte, targetClass *RClass) *callinfo {
ctx := state.context
prevCi := ctx.GetCallinfo()

callinfo := &callinfo{
methodId: mid,
stackOffset: prevCi.stackOffset + pushStack,
numArgs: int(argc & 0xf),
stack: []Value{nil},
targetClass: targetClass,
}
ctx.callinfo.Push(callinfo)
Expand Down

0 comments on commit 9208fc4

Please sign in to comment.