elemheap: don't reuse elements if they are still referenced

This commit is contained in:
Michael Teichgräber 2014-07-31 01:38:40 +02:00
parent 5d66898cd7
commit 1c2705dcfe
4 changed files with 46 additions and 22 deletions

View File

@ -7,17 +7,19 @@ requested, a row is exhausted, and the next one will
be allocated. Previously allocated rows are tracked in
elemHeap.rows.
Pos() and setPos() methods allow to query and reset the
current position (row, and position within the row), which
allows reusing elements. It must be made sure, that previous
users of such storage don't access it anymore once setPos has
been called.
The Reset() method allows to reset the current position (row, and
position within the row), which allows reusing elements. Whether
elements can be reused, depends on the value of the hasGlobals
field.
*/
type elemHeap struct {
rows [][]element
heapPos
rowSize int
base heapPos
hasGlobals bool
}
type heapPos struct {
@ -38,12 +40,18 @@ func (h *elemHeap) init(size int) {
h.rowSize = size
h.rows = [][]element{make([]element, size)}
h.row = h.rows[h.iRow]
h.base = h.heapPos
}
func (h *elemHeap) Pos() heapPos {
return h.heapPos
}
func (h *elemHeap) setPos(i heapPos) {
h.heapPos = i
func (h *elemHeap) Reset() {
if !h.hasGlobals {
h.heapPos = h.base
} else {
/* Don't restore saved position in case elements added
* after the previous Reset call are needed in
* global context, like notes.
*/
h.hasGlobals = false
h.base = h.heapPos
}
}

View File

@ -31,7 +31,7 @@ const (
// rebuild it using
// make nuke
// make parser
needParserIfaceVersion = parserIfaceVersion_17
needParserIfaceVersion = parserIfaceVersion_18
)
// Markdown Extensions.
@ -81,7 +81,7 @@ func (p *Parser) Markdown(src io.Reader, f Formatter) {
if p.yy.extension.Notes {
p.parseRule(ruleNotes, s)
}
savedPos := p.yy.state.heap.Pos()
p.yy.state.heap.Reset()
for {
tree := p.parseRule(ruleDocblock, s)
@ -91,7 +91,8 @@ func (p *Parser) Markdown(src io.Reader, f Formatter) {
s = p.yy.ResetBuffer("")
tree = p.processRawBlocks(tree)
f.FormatBlock(tree)
p.yy.state.heap.setPos(savedPos)
p.yy.state.heap.Reset()
}
f.Finish()
}

View File

@ -28,7 +28,7 @@ import (
)
const (
parserIfaceVersion_17 = iota
parserIfaceVersion_18 = iota
)
// Semantic value of a parsing action.
@ -676,7 +676,9 @@ RefTitleParens = Spnl '(' < ( !(')' Sp Newline | Newline) . )* > ')'
References = a:StartList
( b:Reference { a = cons(b, a) } | SkipBlock )*
{ p.references = reverse(a) }
{ p.references = reverse(a)
p.state.heap.hasGlobals = true
}
commit
Ticks1 = "`" !'`'
@ -787,6 +789,7 @@ DoubleQuoted = DoubleQuoteStart
NoteReference = &{ p.extension.Notes }
ref:RawNoteReference
{
p.state.heap.hasGlobals = true
if match, ok := p.find_note(ref.contents.str); ok {
$$ = p.mkElem(NOTE)
$$.children = match.children
@ -814,7 +817,8 @@ InlineNote = &{ p.extension.Notes }
( !']' Inline { a = cons($$, a) } )+
']'
{ $$ = p.mkList(NOTE, a)
$$.contents.str = "" }
p.state.heap.hasGlobals = true
$$.contents.str = "" }
Notes = a:StartList
( b:Note { a = cons(b, a) } | SkipBlock )*
@ -825,7 +829,8 @@ RawNoteBlock = a:StartList
( !BlankLine OptionallyIndentedLine { a = cons($$, a) } )+
( < BlankLine* > { a = cons(p.mkString(yytext), a) } )
{ $$ = p.mkStringFromList(a, true)
$$.key = RAW
p.state.heap.hasGlobals = true
$$.key = RAW
}

View File

@ -27,7 +27,7 @@ import (
)
const (
parserIfaceVersion_17 = iota
parserIfaceVersion_18 = iota
)
// Semantic value of a parsing action.
@ -1043,6 +1043,8 @@ func (p *yyParser) Init() {
a := yyval[yyp-1]
b := yyval[yyp-2]
p.references = reverse(a)
p.state.heap.hasGlobals = true
yyval[yyp-1] = a
yyval[yyp-2] = b
},
@ -1121,6 +1123,7 @@ func (p *yyParser) Init() {
func(yytext string, _ int) {
ref := yyval[yyp-1]
p.state.heap.hasGlobals = true
if match, ok := p.find_note(ref.contents.str); ok {
yy = p.mkElem(NOTE)
yy.children = match.children
@ -1171,6 +1174,7 @@ func (p *yyParser) Init() {
func(yytext string, _ int) {
a := yyval[yyp-1]
yy = p.mkList(NOTE, a)
p.state.heap.hasGlobals = true
yy.contents.str = ""
yyval[yyp-1] = a
},
@ -1206,6 +1210,7 @@ func (p *yyParser) Init() {
func(yytext string, _ int) {
a := yyval[yyp-1]
yy = p.mkStringFromList(a, true)
p.state.heap.hasGlobals = true
yy.key = RAW
yyval[yyp-1] = a
@ -9668,7 +9673,9 @@ func (p *yyParser) Init() {
position = position0
return
},
/* 189 References <- (StartList ((Reference { a = cons(b, a) }) / SkipBlock)* { p.references = reverse(a) } commit) */
/* 189 References <- (StartList ((Reference { a = cons(b, a) }) / SkipBlock)* { p.references = reverse(a)
p.state.heap.hasGlobals = true
} commit) */
func() (match bool) {
position0, thunkPosition0 := position, thunkPosition
doarg(yyPush, 2)
@ -12058,6 +12065,7 @@ func (p *yyParser) Init() {
return
},
/* 237 NoteReference <- (&{p.extension.Notes} RawNoteReference {
p.state.heap.hasGlobals = true
if match, ok := p.find_note(ref.contents.str); ok {
yy = p.mkElem(NOTE)
yy.children = match.children
@ -12188,6 +12196,7 @@ func (p *yyParser) Init() {
return
},
/* 240 InlineNote <- (&{p.extension.Notes} '^[' StartList (!']' Inline { a = cons(yy, a) })+ ']' { yy = p.mkList(NOTE, a)
p.state.heap.hasGlobals = true
yy.contents.str = "" }) */
func() (match bool) {
position0, thunkPosition0 := position, thunkPosition
@ -12276,8 +12285,9 @@ func (p *yyParser) Init() {
return
},
/* 242 RawNoteBlock <- (StartList (!BlankLine OptionallyIndentedLine { a = cons(yy, a) })+ (< BlankLine* > { a = cons(p.mkString(yytext), a) }) { yy = p.mkStringFromList(a, true)
yy.key = RAW
}) */
p.state.heap.hasGlobals = true
yy.key = RAW
}) */
func() (match bool) {
position0, thunkPosition0 := position, thunkPosition
doarg(yyPush, 1)