Skip to content

Commit

Permalink
更加智能的编译缓存
Browse files Browse the repository at this point in the history
  • Loading branch information
lollipopkit committed Oct 24, 2022
1 parent 091d845 commit bc852a2
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 30 deletions.
2 changes: 1 addition & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"request": "launch",
"mode": "debug",
"program": ".",
"args": ["-f", "test/test.lk"]
"args": ["test/test.lk"]
}
]
}
23 changes: 17 additions & 6 deletions binchunk/binary_chunk.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,18 @@ import (
"strings"

"git.lolli.tech/lollipopkit/lk/consts"
"git.lolli.tech/lollipopkit/lk/utils"
jsoniter "github.com/json-iterator/go"
)

const (
MismatchVersionPrefix = "mismatch LK VM version: "
)

var (
json = jsoniter.ConfigCompatibleWithStandardLibrary
json = jsoniter.ConfigCompatibleWithStandardLibrary
ErrInvalidVersionFormat = errors.New("invalid version format")
ErrMismatchedHash = errors.New("mismatched hash")
)

const (
Expand All @@ -25,7 +31,7 @@ const (
type binaryChunk struct {
Version string `json:"v"`
Sign string `json:"si"`
Hash string `json:"h"`
Md5 string `json:"m"`
Proto *Prototype `json:"p"`
}

Expand Down Expand Up @@ -57,15 +63,19 @@ type LocVar struct {
EndPC uint32 `json:"epc"`
}

func Verify(data []byte) (*Prototype, error) {
func Verify(data, sourceData []byte) (*Prototype, error) {
var bin binaryChunk
err := json.Unmarshal(data, &bin)
if err != nil {
return nil, err
}
if bin.Sign != consts.SIGNATURE {
return nil, errors.New("invalid signature: "+bin.Sign)
return nil, errors.New("invalid signature: " + bin.Sign)
}
if len(sourceData) != 0 && bin.Md5 != utils.Md5(sourceData) {
return nil, ErrMismatchedHash
}

return bin.Proto, passVersion(bin.Version)
}

Expand All @@ -78,14 +88,15 @@ func passVersion(v string) error {
if strings.Compare(v, consts.VERSION) >= 0 {
return nil
}
return errors.New("LK VM version "+consts.VERSION+" is required, but "+v+" is provided")
return errors.New(MismatchVersionPrefix + consts.VERSION + " is required, but " + v + " is provided")
}

func (proto *Prototype) Dump() ([]byte, error) {
func (proto *Prototype) Dump(md5 string) ([]byte, error) {
bin := &binaryChunk{
Version: consts.VERSION,
Sign: consts.SIGNATURE,
Proto: proto,
Md5: md5,
}
return json.Marshal(bin)
}
86 changes: 64 additions & 22 deletions run.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"git.lolli.tech/lollipopkit/lk/compiler"
"git.lolli.tech/lollipopkit/lk/state"
"git.lolli.tech/lollipopkit/lk/term"
"git.lolli.tech/lollipopkit/lk/utils"
)

func compile(source string) []byte {
Expand All @@ -22,44 +23,85 @@ func compile(source string) []byte {
}

bin := compiler.Compile(string(data), source)
f, err := os.Create(source + "c")
if err != nil {
term.Error("[compile] can't create file: " + err.Error())
}

compiledData, err := bin.Dump()
compiledData, err := bin.Dump(utils.Md5(data))
if err != nil {
term.Error("[compile] dump file failed: " + err.Error())
}
f.Write(compiledData)
err = ioutil.WriteFile(source+"c", compiledData, 0744)
if err != nil {
term.Error("[compile] write file failed: " + err.Error())
}
return compiledData
}

func run(file string) {
if !exist(file) {
term.Error("[run] file not found: " + file)
func runVM(data []byte, source string) {
ls := state.New()
ls.OpenLibs()
ls.Load(data, source, "bt")
ls.Call(0, -1)
}

func runlk(source string) {
lkc := source + "c"
if exist(lkc) {
runlkc(lkc)
} else {
data := compile(source)
runVM(data, source)
}
}

func runlkc(source string) {
if !exist(source) {
term.Error("[run] file not found: " + source)
}

data, err := ioutil.ReadFile(file)
data, err := ioutil.ReadFile(source)
if err != nil {
term.Error("[run] can't read file: " + err.Error())
}

var compiledData []byte
lkPath := source[:len(source)-1]
lkData := make([]byte, 0)
lkExist := exist(lkPath)
if lkExist {
lkData, err = ioutil.ReadFile(lkPath)
if err != nil {
term.Error("[run] can't read file: " + err.Error())
}
}

_, err = binchunk.Verify(data)
if err == nil {
compiledData = data
} else if strings.HasSuffix(file, ".lk") {
compiledData = compile(file)
} else {
term.Error("[run] can't compile: " + err.Error())
_, err = binchunk.Verify(data, lkData)
if err != nil {
if err == binchunk.ErrMismatchedHash {
if lkExist {
term.Info("[run] source changed, recompiling " + lkPath)
data = compile(lkPath)
} else {
term.Warn("[run] source not found: " + lkPath)
}
} else if strings.HasPrefix(err.Error(), binchunk.MismatchVersionPrefix) {
if lkExist {
term.Info("[run] mismatch version, recompiling " + lkPath)
data = compile(lkPath)
} else {
term.Error("[run] mismatch version and source not found: " + lkPath)
}
} else {
term.Error("[run] chunk verify failed: " + err.Error())
}
}

ls := state.New()
ls.OpenLibs()
ls.Load(compiledData, file, "bt")
ls.Call(0, -1)
runVM(data, source)
}

func run(file string) {
if strings.HasSuffix(file, ".lk") {
runlk(file)
} else if strings.HasSuffix(file, ".lkc") {
runlkc(file)
}
}

func exist(path string) bool {
Expand Down
2 changes: 1 addition & 1 deletion state/api_call.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
// http://www.lua.org/manual/5.3/manual.html#lua_load
func (self *luaState) Load(chunk []byte, chunkName, mode string) int {
var proto *binchunk.Prototype
prot, err := binchunk.Verify(chunk)
prot, err := binchunk.Verify(chunk, []byte{})
logger.I("[state.Load] Using compiled chunk: %v", err)
if err == nil {
proto = prot
Expand Down

0 comments on commit bc852a2

Please sign in to comment.