blob: 37bbd3347ad589b030ba1c31b874d45d9f82843e [file] [log] [blame]
package gls
// so, basically, we're going to encode integer tags in base-16 on the stack
const (
bitWidth = 4
stackBatchSize = 16
)
var (
pc_lookup = make(map[uintptr]int8, 17)
mark_lookup [16]func(uint, func())
)
func init() {
setEntries := func(f func(uint, func()), v int8) {
var ptr uintptr
f(0, func() {
ptr = findPtr()
})
pc_lookup[ptr] = v
if v >= 0 {
mark_lookup[v] = f
}
}
setEntries(github_com_jtolds_gls_markS, -0x1)
setEntries(github_com_jtolds_gls_mark0, 0x0)
setEntries(github_com_jtolds_gls_mark1, 0x1)
setEntries(github_com_jtolds_gls_mark2, 0x2)
setEntries(github_com_jtolds_gls_mark3, 0x3)
setEntries(github_com_jtolds_gls_mark4, 0x4)
setEntries(github_com_jtolds_gls_mark5, 0x5)
setEntries(github_com_jtolds_gls_mark6, 0x6)
setEntries(github_com_jtolds_gls_mark7, 0x7)
setEntries(github_com_jtolds_gls_mark8, 0x8)
setEntries(github_com_jtolds_gls_mark9, 0x9)
setEntries(github_com_jtolds_gls_markA, 0xa)
setEntries(github_com_jtolds_gls_markB, 0xb)
setEntries(github_com_jtolds_gls_markC, 0xc)
setEntries(github_com_jtolds_gls_markD, 0xd)
setEntries(github_com_jtolds_gls_markE, 0xe)
setEntries(github_com_jtolds_gls_markF, 0xf)
}
func addStackTag(tag uint, context_call func()) {
if context_call == nil {
return
}
github_com_jtolds_gls_markS(tag, context_call)
}
// these private methods are named this horrendous name so gopherjs support
// is easier. it shouldn't add any runtime cost in non-js builds.
//go:noinline
func github_com_jtolds_gls_markS(tag uint, cb func()) { _m(tag, cb) }
//go:noinline
func github_com_jtolds_gls_mark0(tag uint, cb func()) { _m(tag, cb) }
//go:noinline
func github_com_jtolds_gls_mark1(tag uint, cb func()) { _m(tag, cb) }
//go:noinline
func github_com_jtolds_gls_mark2(tag uint, cb func()) { _m(tag, cb) }
//go:noinline
func github_com_jtolds_gls_mark3(tag uint, cb func()) { _m(tag, cb) }
//go:noinline
func github_com_jtolds_gls_mark4(tag uint, cb func()) { _m(tag, cb) }
//go:noinline
func github_com_jtolds_gls_mark5(tag uint, cb func()) { _m(tag, cb) }
//go:noinline
func github_com_jtolds_gls_mark6(tag uint, cb func()) { _m(tag, cb) }
//go:noinline
func github_com_jtolds_gls_mark7(tag uint, cb func()) { _m(tag, cb) }
//go:noinline
func github_com_jtolds_gls_mark8(tag uint, cb func()) { _m(tag, cb) }
//go:noinline
func github_com_jtolds_gls_mark9(tag uint, cb func()) { _m(tag, cb) }
//go:noinline
func github_com_jtolds_gls_markA(tag uint, cb func()) { _m(tag, cb) }
//go:noinline
func github_com_jtolds_gls_markB(tag uint, cb func()) { _m(tag, cb) }
//go:noinline
func github_com_jtolds_gls_markC(tag uint, cb func()) { _m(tag, cb) }
//go:noinline
func github_com_jtolds_gls_markD(tag uint, cb func()) { _m(tag, cb) }
//go:noinline
func github_com_jtolds_gls_markE(tag uint, cb func()) { _m(tag, cb) }
//go:noinline
func github_com_jtolds_gls_markF(tag uint, cb func()) { _m(tag, cb) }
func _m(tag_remainder uint, cb func()) {
if tag_remainder == 0 {
cb()
} else {
mark_lookup[tag_remainder&0xf](tag_remainder>>bitWidth, cb)
}
}
func readStackTag() (tag uint, ok bool) {
var current_tag uint
offset := 0
for {
batch, next_offset := getStack(offset, stackBatchSize)
for _, pc := range batch {
val, ok := pc_lookup[pc]
if !ok {
continue
}
if val < 0 {
return current_tag, true
}
current_tag <<= bitWidth
current_tag += uint(val)
}
if next_offset == 0 {
break
}
offset = next_offset
}
return 0, false
}
func (m *ContextManager) preventInlining() {
// dunno if findPtr or getStack are likely to get inlined in a future release
// of go, but if they are inlined and their callers are inlined, that could
// hork some things. let's do our best to explain to the compiler that we
// really don't want those two functions inlined by saying they could change
// at any time. assumes preventInlining doesn't get compiled out.
// this whole thing is probably overkill.
findPtr = m.values[0][0].(func() uintptr)
getStack = m.values[0][1].(func(int, int) ([]uintptr, int))
}