Skip to content

Commit 250e42d

Browse files
committed
[Go] Port locking algorithm from C++ to Go
1 parent d8e1644 commit 250e42d

File tree

8 files changed

+175
-171
lines changed

8 files changed

+175
-171
lines changed

runtime-testsuite/resources/org/antlr/v4/test/runtime/templates/Go.test.stg

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,9 +103,7 @@ PositionAdjustingLexerDef() ::= ""
103103
PositionAdjustingLexer() ::= <<
104104
func (p *PositionAdjustingLexer) NextToken() antlr.Token {
105105
if _, ok := p.Interpreter.(*PositionAdjustingLexerATNSimulator); !ok {
106-
lexerDeserializer := antlr.NewATNDeserializer(nil)
107-
lexerAtn := lexerDeserializer.DeserializeFromUInt16(serializedLexerAtn)
108-
p.Interpreter = NewPositionAdjustingLexerATNSimulator(p, lexerAtn, p.Interpreter.DecisionToDFA(), p.Interpreter.SharedContextCache())
106+
p.Interpreter = NewPositionAdjustingLexerATNSimulator(p, p.Interpreter.ATN(), p.Interpreter.DecisionToDFA(), p.Interpreter.SharedContextCache())
109107
p.Virt = p
110108
}
111109

runtime/Go/antlr/atn.go

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
package antlr
66

7+
import "sync"
8+
79
var ATNInvalidAltNumber int
810

911
type ATN struct {
@@ -37,6 +39,10 @@ type ATN struct {
3739
ruleToTokenType []int
3840

3941
states []ATNState
42+
43+
mu sync.Mutex
44+
stateMu sync.RWMutex
45+
edgeMu sync.RWMutex
4046
}
4147

4248
func NewATN(grammarType int, maxTokenType int) *ATN {
@@ -59,14 +65,15 @@ func (a *ATN) NextTokensInContext(s ATNState, ctx RuleContext) *IntervalSet {
5965
// in s and staying in same rule. Token.EPSILON is in set if we reach end of
6066
// rule.
6167
func (a *ATN) NextTokensNoContext(s ATNState) *IntervalSet {
62-
if s.GetNextTokenWithinRule() != nil {
63-
return s.GetNextTokenWithinRule()
68+
a.mu.Lock()
69+
defer a.mu.Unlock()
70+
iset := s.GetNextTokenWithinRule()
71+
if iset == nil {
72+
iset = a.NextTokensInContext(s, nil)
73+
iset.readOnly = true
74+
s.SetNextTokenWithinRule(iset)
6475
}
65-
66-
s.SetNextTokenWithinRule(a.NextTokensInContext(s, nil))
67-
s.GetNextTokenWithinRule().readOnly = true
68-
69-
return s.GetNextTokenWithinRule()
76+
return iset
7077
}
7178

7279
func (a *ATN) NextTokens(s ATNState, ctx RuleContext) *IntervalSet {

runtime/Go/antlr/atn_state.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,8 @@ func NewBasicBlockStartState() *BasicBlockStartState {
243243
return &BasicBlockStartState{BaseBlockStartState: b}
244244
}
245245

246+
var _ BlockStartState = &BasicBlockStartState{}
247+
246248
// BlockEndState is a terminal node of a simple (a|b|c) block.
247249
type BlockEndState struct {
248250
*BaseATNState
@@ -318,6 +320,8 @@ func NewPlusBlockStartState() *PlusBlockStartState {
318320
return &PlusBlockStartState{BaseBlockStartState: b}
319321
}
320322

323+
var _ BlockStartState = &PlusBlockStartState{}
324+
321325
// StarBlockStartState is the block that begins a closure loop.
322326
type StarBlockStartState struct {
323327
*BaseBlockStartState
@@ -331,6 +335,8 @@ func NewStarBlockStartState() *StarBlockStartState {
331335
return &StarBlockStartState{BaseBlockStartState: b}
332336
}
333337

338+
var _ BlockStartState = &StarBlockStartState{}
339+
334340
type StarLoopbackState struct {
335341
*BaseATNState
336342
}

runtime/Go/antlr/dfa.go

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,6 @@ package antlr
66

77
import (
88
"sort"
9-
"sync"
10-
"sync/atomic"
11-
"unsafe"
129
)
1310

1411
type DFA struct {
@@ -19,23 +16,28 @@ type DFA struct {
1916

2017
// states is all the DFA states. Use Map to get the old state back; Set can only
2118
// indicate whether it is there.
22-
states map[int]*DFAState
23-
statesMu sync.RWMutex
19+
states map[int]*DFAState
2420

2521
s0 *DFAState
2622

2723
// precedenceDfa is the backing field for isPrecedenceDfa and setPrecedenceDfa.
2824
// True if the DFA is for a precedence decision and false otherwise.
29-
precedenceDfa bool
30-
precedenceDfaMu sync.RWMutex
25+
precedenceDfa bool
3126
}
3227

3328
func NewDFA(atnStartState DecisionState, decision int) *DFA {
34-
return &DFA{
29+
dfa := &DFA{
3530
atnStartState: atnStartState,
3631
decision: decision,
3732
states: make(map[int]*DFAState),
3833
}
34+
if s, ok := atnStartState.(*StarLoopEntryState); ok && s.precedenceRuleDecision {
35+
dfa.precedenceDfa = true
36+
dfa.s0 = NewDFAState(-1, NewBaseATNConfigSet(false))
37+
dfa.s0.isAcceptState = false
38+
dfa.s0.requiresFullContext = false
39+
}
40+
return dfa
3941
}
4042

4143
// getPrecedenceStartState gets the start state for the current precedence and
@@ -80,8 +82,6 @@ func (d *DFA) setPrecedenceStartState(precedence int, startState *DFAState) {
8082
}
8183

8284
func (d *DFA) getPrecedenceDfa() bool {
83-
d.precedenceDfaMu.RLock()
84-
defer d.precedenceDfaMu.RUnlock()
8585
return d.precedenceDfa
8686
}
8787

@@ -105,42 +105,32 @@ func (d *DFA) setPrecedenceDfa(precedenceDfa bool) {
105105
d.setS0(nil)
106106
}
107107

108-
d.precedenceDfaMu.Lock()
109-
defer d.precedenceDfaMu.Unlock()
110108
d.precedenceDfa = precedenceDfa
111109
}
112110
}
113111

114112
func (d *DFA) getS0() *DFAState {
115-
return (*DFAState)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&d.s0))))
113+
return d.s0
116114
}
117115

118116
func (d *DFA) setS0(s *DFAState) {
119-
atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&d.s0)), unsafe.Pointer(s))
117+
d.s0 = s
120118
}
121119

122120
func (d *DFA) getState(hash int) (*DFAState, bool) {
123-
d.statesMu.RLock()
124-
defer d.statesMu.RUnlock()
125121
s, ok := d.states[hash]
126122
return s, ok
127123
}
128124

129125
func (d *DFA) setStates(states map[int]*DFAState) {
130-
d.statesMu.Lock()
131-
defer d.statesMu.Unlock()
132126
d.states = states
133127
}
134128

135129
func (d *DFA) setState(hash int, state *DFAState) {
136-
d.statesMu.Lock()
137-
defer d.statesMu.Unlock()
138130
d.states[hash] = state
139131
}
140132

141133
func (d *DFA) numStates() int {
142-
d.statesMu.RLock()
143-
defer d.statesMu.RUnlock()
144134
return len(d.states)
145135
}
146136

runtime/Go/antlr/dfa_state.go

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ package antlr
66

77
import (
88
"fmt"
9-
"sync"
109
)
1110

1211
// PredPrediction maps a predicate to a predicted alternative.
@@ -50,8 +49,7 @@ type DFAState struct {
5049

5150
// edges elements point to the target of the symbol. Shift up by 1 so (-1)
5251
// Token.EOF maps to the first element.
53-
edges []*DFAState
54-
edgesMu sync.RWMutex
52+
edges []*DFAState
5553

5654
isAcceptState bool
5755

@@ -109,32 +107,22 @@ func (d *DFAState) GetAltSet() Set {
109107
}
110108

111109
func (d *DFAState) getEdges() []*DFAState {
112-
d.edgesMu.RLock()
113-
defer d.edgesMu.RUnlock()
114110
return d.edges
115111
}
116112

117113
func (d *DFAState) numEdges() int {
118-
d.edgesMu.RLock()
119-
defer d.edgesMu.RUnlock()
120114
return len(d.edges)
121115
}
122116

123117
func (d *DFAState) getIthEdge(i int) *DFAState {
124-
d.edgesMu.RLock()
125-
defer d.edgesMu.RUnlock()
126118
return d.edges[i]
127119
}
128120

129121
func (d *DFAState) setEdges(newEdges []*DFAState) {
130-
d.edgesMu.Lock()
131-
defer d.edgesMu.Unlock()
132122
d.edges = newEdges
133123
}
134124

135125
func (d *DFAState) setIthEdge(i int, edge *DFAState) {
136-
d.edgesMu.Lock()
137-
defer d.edgesMu.Unlock()
138126
d.edges[i] = edge
139127
}
140128

runtime/Go/antlr/lexer_atn_simulator.go

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -91,11 +91,16 @@ func (l *LexerATNSimulator) Match(input CharStream, mode int) int {
9191

9292
dfa := l.decisionToDFA[mode]
9393

94-
if dfa.getS0() == nil {
94+
var s0 *DFAState
95+
l.atn.stateMu.RLock()
96+
s0 = dfa.getS0()
97+
l.atn.stateMu.RUnlock()
98+
99+
if s0 == nil {
95100
return l.MatchATN(input)
96101
}
97102

98-
return l.execATN(input, dfa.getS0())
103+
return l.execATN(input, s0)
99104
}
100105

101106
func (l *LexerATNSimulator) reset() {
@@ -117,11 +122,7 @@ func (l *LexerATNSimulator) MatchATN(input CharStream) int {
117122
suppressEdge := s0Closure.hasSemanticContext
118123
s0Closure.hasSemanticContext = false
119124

120-
next := l.addDFAState(s0Closure)
121-
122-
if !suppressEdge {
123-
l.decisionToDFA[l.mode].setS0(next)
124-
}
125+
next := l.addDFAState(s0Closure, suppressEdge)
125126

126127
predict := l.execATN(input, next)
127128

@@ -207,7 +208,9 @@ func (l *LexerATNSimulator) getExistingTargetState(s *DFAState, t int) *DFAState
207208
return nil
208209
}
209210

211+
l.atn.edgeMu.RLock()
210212
target := s.getIthEdge(t - LexerATNSimulatorMinDFAEdge)
213+
l.atn.edgeMu.RUnlock()
211214
if LexerATNSimulatorDebug && target != nil {
212215
fmt.Println("reuse state " + strconv.Itoa(s.stateNumber) + " edge to " + strconv.Itoa(target.stateNumber))
213216
}
@@ -537,7 +540,7 @@ func (l *LexerATNSimulator) addDFAEdge(from *DFAState, tk int, to *DFAState, cfg
537540
suppressEdge := cfgs.HasSemanticContext()
538541
cfgs.SetHasSemanticContext(false)
539542

540-
to = l.addDFAState(cfgs)
543+
to = l.addDFAState(cfgs, true)
541544

542545
if suppressEdge {
543546
return to
@@ -551,6 +554,8 @@ func (l *LexerATNSimulator) addDFAEdge(from *DFAState, tk int, to *DFAState, cfg
551554
if LexerATNSimulatorDebug {
552555
fmt.Println("EDGE " + from.String() + " -> " + to.String() + " upon " + strconv.Itoa(tk))
553556
}
557+
l.atn.edgeMu.Lock()
558+
defer l.atn.edgeMu.Unlock()
554559
if from.getEdges() == nil {
555560
// make room for tokens 1..n and -1 masquerading as index 0
556561
from.setEdges(make([]*DFAState, LexerATNSimulatorMaxDFAEdge-LexerATNSimulatorMinDFAEdge+1))
@@ -564,7 +569,7 @@ func (l *LexerATNSimulator) addDFAEdge(from *DFAState, tk int, to *DFAState, cfg
564569
// configurations already. This method also detects the first
565570
// configuration containing an ATN rule stop state. Later, when
566571
// traversing the DFA, we will know which rule to accept.
567-
func (l *LexerATNSimulator) addDFAState(configs ATNConfigSet) *DFAState {
572+
func (l *LexerATNSimulator) addDFAState(configs ATNConfigSet, suppressEdge bool) *DFAState {
568573

569574
proposed := NewDFAState(-1, configs)
570575
var firstConfigWithRuleStopState ATNConfig
@@ -585,16 +590,22 @@ func (l *LexerATNSimulator) addDFAState(configs ATNConfigSet) *DFAState {
585590
}
586591
hash := proposed.hash()
587592
dfa := l.decisionToDFA[l.mode]
593+
594+
l.atn.stateMu.Lock()
595+
defer l.atn.stateMu.Unlock()
588596
existing, ok := dfa.getState(hash)
589597
if ok {
590-
return existing
591-
}
592-
newState := proposed
593-
newState.stateNumber = dfa.numStates()
594-
configs.SetReadOnly(true)
595-
newState.configs = configs
596-
dfa.setState(hash, newState)
597-
return newState
598+
proposed = existing
599+
} else {
600+
proposed.stateNumber = dfa.numStates()
601+
configs.SetReadOnly(true)
602+
proposed.configs = configs
603+
dfa.setState(hash, proposed)
604+
}
605+
if !suppressEdge {
606+
dfa.setS0(proposed)
607+
}
608+
return proposed
598609
}
599610

600611
func (l *LexerATNSimulator) getDFA(mode int) *DFA {

0 commit comments

Comments
 (0)