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)) }