mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Reduce allocations in transition_table (#39943)
* Reduce allocations in transition_table * Use predicate symbol? instead of is_a?
This commit is contained in:
parent
132ee010aa
commit
6e636e2336
1 changed files with 18 additions and 32 deletions
|
@ -13,45 +13,44 @@ module ActionDispatch
|
|||
def initialize(root)
|
||||
@root = root
|
||||
@ast = Nodes::Cat.new root, DUMMY
|
||||
@followpos = nil
|
||||
@followpos = build_followpos
|
||||
end
|
||||
|
||||
def transition_table
|
||||
dtrans = TransitionTable.new
|
||||
marked = {}
|
||||
state_id = Hash.new { |h, k| h[k] = h.length }
|
||||
dstates = [firstpos(root)]
|
||||
|
||||
start = firstpos(root)
|
||||
dstates = [start]
|
||||
until dstates.empty?
|
||||
s = dstates.shift
|
||||
next if marked[s]
|
||||
marked[s] = true # mark s
|
||||
|
||||
s.group_by { |state| symbol(state) }.each do |sym, ps|
|
||||
u = ps.flat_map { |l| followpos(l) }
|
||||
u = ps.flat_map { |l| @followpos[l] }
|
||||
next if u.empty?
|
||||
|
||||
if u.uniq == [DUMMY]
|
||||
from = state_id[s]
|
||||
|
||||
if u.all? { |pos| pos == DUMMY }
|
||||
to = state_id[Object.new]
|
||||
dtrans[from, to] = sym
|
||||
|
||||
dtrans.add_accepting(to)
|
||||
|
||||
ps.each { |state| dtrans.add_memo(to, state.memo) }
|
||||
else
|
||||
dtrans[state_id[s], state_id[u]] = sym
|
||||
to = state_id[u]
|
||||
dtrans[from, to] = sym
|
||||
|
||||
if u.include?(DUMMY)
|
||||
to = state_id[u]
|
||||
ps.each do |state|
|
||||
if @followpos[state].include?(DUMMY)
|
||||
dtrans.add_memo(to, state.memo)
|
||||
end
|
||||
end
|
||||
|
||||
accepting = ps.find_all { |l| followpos(l).include?(DUMMY) }
|
||||
|
||||
accepting.each { |accepting_state|
|
||||
dtrans.add_memo(to, accepting_state.memo)
|
||||
}
|
||||
|
||||
dtrans.add_accepting(state_id[u])
|
||||
dtrans.add_accepting(to)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -92,7 +91,7 @@ module ActionDispatch
|
|||
firstpos(node.left)
|
||||
end
|
||||
when Nodes::Or
|
||||
node.children.flat_map { |c| firstpos(c) }.uniq
|
||||
node.children.flat_map { |c| firstpos(c) }.tap(&:uniq!)
|
||||
when Nodes::Unary
|
||||
firstpos(node.left)
|
||||
when Nodes::Terminal
|
||||
|
@ -107,7 +106,7 @@ module ActionDispatch
|
|||
when Nodes::Star
|
||||
firstpos(node.left)
|
||||
when Nodes::Or
|
||||
node.children.flat_map { |c| lastpos(c) }.uniq
|
||||
node.children.flat_map { |c| lastpos(c) }.tap(&:uniq!)
|
||||
when Nodes::Cat
|
||||
if nullable?(node.right)
|
||||
lastpos(node.left) | lastpos(node.right)
|
||||
|
@ -123,15 +122,7 @@ module ActionDispatch
|
|||
end
|
||||
end
|
||||
|
||||
def followpos(node)
|
||||
followpos_table[node]
|
||||
end
|
||||
|
||||
private
|
||||
def followpos_table
|
||||
@followpos ||= build_followpos
|
||||
end
|
||||
|
||||
def build_followpos
|
||||
table = Hash.new { |h, k| h[k] = [] }
|
||||
@ast.each do |n|
|
||||
|
@ -150,12 +141,7 @@ module ActionDispatch
|
|||
end
|
||||
|
||||
def symbol(edge)
|
||||
case edge
|
||||
when Journey::Nodes::Symbol
|
||||
edge.regexp
|
||||
else
|
||||
edge.left
|
||||
end
|
||||
edge.symbol? ? edge.regexp : edge.left
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue