Commit bc6144f6 authored by Yuki Shiino's avatar Yuki Shiino Committed by Commit Bot

bind-gen: Reduce the number of rendering iterations

Bug: 839389
Change-Id: I9d5d9238d48516d3d32e971510a3ca506a16c12c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1980605Reviewed-by: default avatarHitoshi Yoshida <peria@chromium.org>
Commit-Queue: Yuki Shiino <yukishiino@chromium.org>
Cr-Commit-Position: refs/heads/master@{#728411}
parent 7fd79607
...@@ -16,6 +16,30 @@ from .mako_renderer import MakoRenderer ...@@ -16,6 +16,30 @@ from .mako_renderer import MakoRenderer
from .mako_renderer import MakoTemplate from .mako_renderer import MakoTemplate
def render_code_node(code_node):
"""
Renders |code_node| and turns it into text letting |code_node| apply all
necessary changes (side effects). Returns the resulting text.
"""
assert isinstance(code_node, CodeNode)
assert code_node.outer is None
renderer = code_node.renderer
accumulator = code_node.accumulator
accumulated_size = accumulator.total_size()
while True:
prev_accumulated_size = accumulated_size
renderer.reset()
code_node.render()
accumulated_size = accumulator.total_size()
if (renderer.is_rendering_complete()
and accumulated_size == prev_accumulated_size):
break
return renderer.to_text()
class Likeliness(object): class Likeliness(object):
""" """
Represents how much likely a code node will be executed. Represents how much likely a code node will be executed.
...@@ -470,6 +494,8 @@ class ListNode(CodeNode): ...@@ -470,6 +494,8 @@ class ListNode(CodeNode):
self._head = head self._head = head
self._tail = tail self._tail = tail
self._will_skip_separator = False
if code_nodes is not None: if code_nodes is not None:
self.extend(code_nodes) self.extend(code_nodes)
...@@ -487,10 +513,10 @@ class ListNode(CodeNode): ...@@ -487,10 +513,10 @@ class ListNode(CodeNode):
try: try:
if self._element_nodes: if self._element_nodes:
renderer.render_text(self._head) renderer.render_text(self._head)
is_first = True self._will_skip_separator = True
for node in self._element_nodes: for node in self._element_nodes:
if is_first: if self._will_skip_separator:
is_first = False self._will_skip_separator = False
else: else:
renderer.render_text(self._separator) renderer.render_text(self._separator)
node.render() node.render()
...@@ -499,6 +525,9 @@ class ListNode(CodeNode): ...@@ -499,6 +525,9 @@ class ListNode(CodeNode):
finally: finally:
renderer.pop_caller() renderer.pop_caller()
def skip_separator(self):
self._will_skip_separator = True
def append(self, node): def append(self, node):
if node is None: if node is None:
return return
...@@ -575,7 +604,7 @@ class SequenceNode(ListNode): ...@@ -575,7 +604,7 @@ class SequenceNode(ListNode):
self.remove(node) self.remove(node)
self._to_be_removed = [] self._to_be_removed = []
return super(SequenceNode, self)._render( super(SequenceNode, self)._render(
renderer=renderer, last_render_state=last_render_state) renderer=renderer, last_render_state=last_render_state)
def schedule_to_remove(self, node): def schedule_to_remove(self, node):
...@@ -609,9 +638,12 @@ class SymbolScopeNode(SequenceNode): ...@@ -609,9 +638,12 @@ class SymbolScopeNode(SequenceNode):
if not self.is_code_symbol_defined(symbol_node): if not self.is_code_symbol_defined(symbol_node):
self._insert_symbol_definition(symbol_node, last_render_state) self._insert_symbol_definition(symbol_node, last_render_state)
return super(SymbolScopeNode, self)._render( super(SymbolScopeNode, self)._render(
renderer=renderer, last_render_state=last_render_state) renderer=renderer, last_render_state=last_render_state)
if self.current_render_state.undefined_code_symbols:
renderer.invalidate_rendering_result()
def _insert_symbol_definition(self, symbol_node, last_render_state): def _insert_symbol_definition(self, symbol_node, last_render_state):
DIRECT_USES = "u" DIRECT_USES = "u"
DIRECT_CHILD_SCOPES = "s" DIRECT_CHILD_SCOPES = "s"
...@@ -849,11 +881,12 @@ class SymbolDefinitionNode(SequenceNode): ...@@ -849,11 +881,12 @@ class SymbolDefinitionNode(SequenceNode):
if scope.is_code_symbol_defined(self._symbol_node): if scope.is_code_symbol_defined(self._symbol_node):
assert isinstance(self.outer, SequenceNode) assert isinstance(self.outer, SequenceNode)
self.outer.schedule_to_remove(self) self.outer.schedule_to_remove(self)
return "" self.outer.skip_separator()
return
scope.on_code_symbol_defined(self._symbol_node) scope.on_code_symbol_defined(self._symbol_node)
return super(SymbolDefinitionNode, self)._render( super(SymbolDefinitionNode, self)._render(
renderer=renderer, last_render_state=last_render_state) renderer=renderer, last_render_state=last_render_state)
@property @property
......
...@@ -7,11 +7,12 @@ import unittest ...@@ -7,11 +7,12 @@ import unittest
from .code_node import SymbolNode from .code_node import SymbolNode
from .code_node import SymbolScopeNode from .code_node import SymbolScopeNode
from .code_node import TextNode from .code_node import TextNode
from .code_node import render_code_node
from .code_node_cxx import CxxClassDefNode from .code_node_cxx import CxxClassDefNode
from .code_node_cxx import CxxFuncDefNode from .code_node_cxx import CxxFuncDefNode
from .code_node_cxx import CxxLikelyIfNode from .code_node_cxx import CxxLikelyIfNode
from .code_node_cxx import CxxUnlikelyIfNode from .code_node_cxx import CxxUnlikelyIfNode
from .codegen_utils import render_code_node from .codegen_accumulator import CodeGenAccumulator
from .mako_renderer import MakoRenderer from .mako_renderer import MakoRenderer
...@@ -23,6 +24,8 @@ class CodeNodeCxxTest(unittest.TestCase): ...@@ -23,6 +24,8 @@ class CodeNodeCxxTest(unittest.TestCase):
def assertRenderResult(self, node, expected): def assertRenderResult(self, node, expected):
if node.renderer is None: if node.renderer is None:
node.set_renderer(MakoRenderer()) node.set_renderer(MakoRenderer())
if node.accumulator is None:
node.set_accumulator(CodeGenAccumulator())
def simplify(text): def simplify(text):
return "\n".join( return "\n".join(
......
...@@ -9,7 +9,8 @@ from .code_node import LiteralNode ...@@ -9,7 +9,8 @@ from .code_node import LiteralNode
from .code_node import SymbolNode from .code_node import SymbolNode
from .code_node import SymbolScopeNode from .code_node import SymbolScopeNode
from .code_node import TextNode from .code_node import TextNode
from .codegen_utils import render_code_node from .code_node import render_code_node
from .codegen_accumulator import CodeGenAccumulator
from .mako_renderer import MakoRenderer from .mako_renderer import MakoRenderer
...@@ -21,6 +22,8 @@ class CodeNodeTest(unittest.TestCase): ...@@ -21,6 +22,8 @@ class CodeNodeTest(unittest.TestCase):
def assertRenderResult(self, node, expected): def assertRenderResult(self, node, expected):
if node.renderer is None: if node.renderer is None:
node.set_renderer(MakoRenderer()) node.set_renderer(MakoRenderer())
if node.accumulator is None:
node.set_accumulator(CodeGenAccumulator())
def simplify(text): def simplify(text):
return "\n".join( return "\n".join(
......
...@@ -17,6 +17,10 @@ class CodeGenAccumulator(object): ...@@ -17,6 +17,10 @@ class CodeGenAccumulator(object):
# Forward declarations of C++ struct # Forward declarations of C++ struct
self._struct_decls = set() self._struct_decls = set()
def total_size(self):
return (len(self.include_headers) + len(self.class_decls) + len(
self.struct_decls))
@property @property
def include_headers(self): def include_headers(self):
return self._include_headers return self._include_headers
......
...@@ -10,6 +10,7 @@ from .code_node import CodeNode ...@@ -10,6 +10,7 @@ from .code_node import CodeNode
from .code_node import EmptyNode from .code_node import EmptyNode
from .code_node import LiteralNode from .code_node import LiteralNode
from .code_node import SequenceNode from .code_node import SequenceNode
from .code_node import render_code_node
from .codegen_accumulator import CodeGenAccumulator from .codegen_accumulator import CodeGenAccumulator
from .path_manager import PathManager from .path_manager import PathManager
...@@ -146,22 +147,6 @@ def collect_include_headers(idl_definition): ...@@ -146,22 +147,6 @@ def collect_include_headers(idl_definition):
return header_paths return header_paths
def render_code_node(code_node):
"""
Renders |code_node| and turns it into text letting |code_node| apply all
necessary changes (side effects). Returns the resulting text.
"""
renderer = code_node.renderer
prev = None
current = ""
while current != prev:
renderer.reset()
prev = current
code_node.render()
current = renderer.to_text()
return current
def write_code_node_to_file(code_node, filepath): def write_code_node_to_file(code_node, filepath):
"""Renders |code_node| and then write the result to |filepath|.""" """Renders |code_node| and then write the result to |filepath|."""
assert isinstance(code_node, CodeNode) assert isinstance(code_node, CodeNode)
......
...@@ -2765,5 +2765,5 @@ def generate_interface(interface): ...@@ -2765,5 +2765,5 @@ def generate_interface(interface):
def generate_interfaces(web_idl_database): def generate_interfaces(web_idl_database):
interface = web_idl_database.find("Window") interface = web_idl_database.find("Navigator")
generate_interface(interface) generate_interface(interface)
...@@ -41,6 +41,7 @@ class MakoRenderer(object): ...@@ -41,6 +41,7 @@ class MakoRenderer(object):
def __init__(self): def __init__(self):
self._text_buffer = None self._text_buffer = None
self._is_invalidated = False
self._caller_stack = [] self._caller_stack = []
self._caller_stack_on_error = [] self._caller_stack_on_error = []
...@@ -50,6 +51,14 @@ class MakoRenderer(object): ...@@ -50,6 +51,14 @@ class MakoRenderer(object):
the first call to |render| or |render_text|. the first call to |render| or |render_text|.
""" """
self._text_buffer = mako.util.FastEncodingBuffer() self._text_buffer = mako.util.FastEncodingBuffer()
self._is_invalidated = False
def is_rendering_complete(self):
return not (self._is_invalidated or self._text_buffer is None
or self._caller_stack)
def invalidate_rendering_result(self):
self._is_invalidated = True
def to_text(self): def to_text(self):
"""Returns the rendering result.""" """Returns the rendering result."""
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment