Skip to content

Commit 057bd36

Browse files
jimidleparrt
authored andcommitted
feat: Catches up minor performance improvements and adds a build tag to build without mutex use
when the user knows there will be no multiple access from go routines Signed-off-by: Jim.Idle <[email protected]>
1 parent 41b9360 commit 057bd36

File tree

10 files changed

+69
-24
lines changed

10 files changed

+69
-24
lines changed

runtime/Go/antlr/go.sum

Lines changed: 0 additions & 2 deletions
This file was deleted.

runtime/Go/antlr/v4/atn.go

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

55
package antlr
66

7-
import "sync"
8-
97
// ATNInvalidAltNumber is used to represent an ALT number that has yet to be calculated or
108
// which is invalid for a particular struct such as [*antlr.BaseRuleContext]
119
var ATNInvalidAltNumber int
@@ -56,9 +54,9 @@ type ATN struct {
5654
//
5755
states []ATNState
5856

59-
mu sync.Mutex
60-
stateMu sync.RWMutex
61-
edgeMu sync.RWMutex
57+
mu Mutex
58+
stateMu RWMutex
59+
edgeMu RWMutex
6260
}
6361

6462
// NewATN returns a new ATN struct representing the given grammarType and is used

runtime/Go/antlr/v4/atn_config.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,6 @@ func NewATNConfig1(c *ATNConfig, state ATNState, context *PredictionContext) *AT
7373
// NewATNConfig creates a new ATNConfig instance given an existing config, a state, a context and a semantic context, other 'constructors'
7474
// are just wrappers around this one.
7575
func NewATNConfig(c *ATNConfig, state ATNState, context *PredictionContext, semanticContext SemanticContext) *ATNConfig {
76-
if semanticContext == nil {
77-
panic("semanticContext cannot be nil") // TODO: Remove this - probably put here for some bug that is now fixed
78-
}
7976
b := &ATNConfig{}
8077
b.InitATNConfig(c, state, c.GetAlt(), context, semanticContext)
8178
b.cType = parserConfig

runtime/Go/antlr/v4/jcollect.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import (
88
"container/list"
99
"runtime/debug"
1010
"sort"
11-
"sync"
1211
)
1312

1413
// Collectable is an interface that a struct should implement if it is to be
@@ -587,12 +586,12 @@ type VisitRecord struct {
587586

588587
type VisitList struct {
589588
cache *list.List
590-
lock sync.RWMutex
589+
lock RWMutex
591590
}
592591

593592
var visitListPool = VisitList{
594593
cache: list.New(),
595-
lock: sync.RWMutex{},
594+
lock: RWMutex{},
596595
}
597596

598597
// NewVisitRecord returns a new VisitRecord instance from the pool if available.

runtime/Go/antlr/v4/ll1_analyzer.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ func (la *LL1Analyzer) getDecisionLookahead(s ATNState) []*IntervalSet {
4040
for alt := 0; alt < count; alt++ {
4141

4242
look[alt] = NewIntervalSet()
43+
// TODO: This is one of the reasons that ATNConfigs are allocated and freed all the time - fix this tomorrow jim!
4344
lookBusy := NewJStore[*ATNConfig, Comparator[*ATNConfig]](aConfEqInst, ClosureBusyCollection, "LL1Analyzer.getDecisionLookahead for lookBusy")
4445
la.look1(s.GetTransitions()[alt].getTarget(), nil, BasePredictionContextEMPTY, look[alt], lookBusy, NewBitSet(), false, false)
4546

runtime/Go/antlr/v4/mutex.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
1-
// +build !nomutex
1+
//go:build !antlr.nomutex
2+
// +build !antlr.nomutex
23

34
package antlr
45

56
import "sync"
67

8+
// Mutex is a simple mutex implementation which just delegates to sync.Mutex, it
9+
// is used to provide a mutex implementation for the antlr package, which users
10+
// can turn off with the build tag -tags antlr.nomutex
711
type Mutex struct {
812
mu sync.Mutex
913
}
@@ -16,7 +20,6 @@ func (m *Mutex) Unlock() {
1620
m.mu.Unlock()
1721
}
1822

19-
2023
type RWMutex struct {
2124
mu sync.RWMutex
2225
}
@@ -35,4 +38,4 @@ func (m *RWMutex) RLock() {
3538

3639
func (m *RWMutex) RUnlock() {
3740
m.mu.RUnlock()
38-
}
41+
}

runtime/Go/antlr/v4/mutex_nomutex.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// +build nomutex
1+
// +build antlr.nomutex
22

33
package antlr
44

runtime/Go/antlr/v4/prediction_context.go

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ package antlr
66

77
import (
88
"fmt"
9-
"golang.org/x/exp/slices"
109
"strconv"
1110
)
1211

@@ -144,10 +143,8 @@ func (p *PredictionContext) ArrayEquals(o Collectable[*PredictionContext]) bool
144143

145144
// Must compare the actual array elements and not just the array address
146145
//
147-
return slices.Equal(p.returnStates, other.returnStates) &&
148-
slices.EqualFunc(p.parents, other.parents, func(x, y *PredictionContext) bool {
149-
return x.Equals(y)
150-
})
146+
return intSlicesEqual(p.returnStates, other.returnStates) &&
147+
pcSliceEqual(p.parents, other.parents)
151148
}
152149

153150
func (p *PredictionContext) SingletonEquals(other Collectable[*PredictionContext]) bool {

runtime/Go/antlr/v4/statistics.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import (
99
"path/filepath"
1010
"sort"
1111
"strconv"
12-
"sync"
1312
)
1413

1514
// This file allows the user to collect statistics about the runtime of the ANTLR runtime. It is not enabled by default
@@ -30,7 +29,7 @@ type goRunStats struct {
3029
// within this package.
3130
//
3231
jStats []*JStatRec
33-
jStatsLock sync.RWMutex
32+
jStatsLock `RWMutex
3433
topN int
3534
topNByMax []*JStatRec
3635
topNByUsed []*JStatRec

runtime/Go/antlr/v4/utils.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,3 +326,56 @@ func isDirectory(dir string) (bool, error) {
326326
}
327327
return fileInfo.IsDir(), err
328328
}
329+
330+
// intSlicesEqual returns true if the two slices of ints are equal, and is a little
331+
// faster than slices.Equal.
332+
func intSlicesEqual(s1, s2 []int) bool {
333+
if s1 == nil && s2 == nil {
334+
return true
335+
}
336+
if s1 == nil || s2 == nil {
337+
return false
338+
}
339+
if len(s1) == 0 && len(s2) == 0 {
340+
return true
341+
}
342+
343+
if len(s1) == 0 || len(s2) == 0 || len(s1) != len(s2) {
344+
return false
345+
}
346+
// If the slices are using the same memory, then they are the same slice
347+
if &s1[0] == &s2[0] {
348+
return true
349+
}
350+
for i, v := range s1 {
351+
if v != s2[i] {
352+
return false
353+
}
354+
}
355+
return true
356+
}
357+
358+
func pcSliceEqual(s1, s2 []*PredictionContext) bool {
359+
if s1 == nil && s2 == nil {
360+
return true
361+
}
362+
if s1 == nil || s2 == nil {
363+
return false
364+
}
365+
if len(s1) == 0 && len(s2) == 0 {
366+
return true
367+
}
368+
if len(s1) == 0 || len(s2) == 0 || len(s1) != len(s2) {
369+
return false
370+
}
371+
// If the slices are using the same memory, then they are the same slice
372+
if &s1[0] == &s2[0] {
373+
return true
374+
}
375+
for i, v := range s1 {
376+
if !v.Equals(s2[i]) {
377+
return false
378+
}
379+
}
380+
return true
381+
}

0 commit comments

Comments
 (0)