| OLD | NEW |
| 1 # Copyright 2013 the V8 project authors. All rights reserved. | 1 # Copyright 2013 the V8 project authors. All rights reserved. |
| 2 # Redistribution and use in source and binary forms, with or without | 2 # Redistribution and use in source and binary forms, with or without |
| 3 # modification, are permitted provided that the following conditions are | 3 # modification, are permitted provided that the following conditions are |
| 4 # met: | 4 # met: |
| 5 # | 5 # |
| 6 # * Redistributions of source code must retain the above copyright | 6 # * Redistributions of source code must retain the above copyright |
| 7 # notice, this list of conditions and the following disclaimer. | 7 # notice, this list of conditions and the following disclaimer. |
| 8 # * Redistributions in binary form must reproduce the above | 8 # * Redistributions in binary form must reproduce the above |
| 9 # copyright notice, this list of conditions and the following | 9 # copyright notice, this list of conditions and the following |
| 10 # disclaimer in the documentation and/or other materials provided | 10 # disclaimer in the documentation and/or other materials provided |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 59 incoming_transitions = {} | 59 incoming_transitions = {} |
| 60 def build_incoming_transitions(state, visitor_state): | 60 def build_incoming_transitions(state, visitor_state): |
| 61 for key, transition_state in state.key_state_iter(): | 61 for key, transition_state in state.key_state_iter(): |
| 62 if not transition_state in incoming_transitions: | 62 if not transition_state in incoming_transitions: |
| 63 incoming_transitions[transition_state] = [] | 63 incoming_transitions[transition_state] = [] |
| 64 incoming_transitions[transition_state].append((key,state)) | 64 incoming_transitions[transition_state].append((key,state)) |
| 65 dfa.visit_all_states(build_incoming_transitions) | 65 dfa.visit_all_states(build_incoming_transitions) |
| 66 | 66 |
| 67 def is_replacement_candidate(state): | 67 def is_replacement_candidate(state): |
| 68 action = state.action() | 68 action = state.action() |
| 69 if not action or action.entry_action() or not action.match_action(): | 69 if not action or not action.match_action(): |
| 70 return False | 70 return False |
| 71 if (action.match_action()[0] == 'token' or | 71 if (action.match_action()[0] == 'token' or |
| 72 action.match_action()[0] == 'harmony_token'): | 72 action.match_action()[0] == 'harmony_token'): |
| 73 return True | 73 return True |
| 74 return False | 74 return False |
| 75 | 75 |
| 76 replacements = {} | 76 replacements = {} |
| 77 for state, incoming in incoming_transitions.items(): | 77 for state, incoming in incoming_transitions.items(): |
| 78 if len(incoming) < 10: | 78 if len(incoming) < 10: |
| 79 continue | 79 continue |
| (...skipping 29 matching lines...) Expand all Loading... |
| 109 name = lambda state : str(state.node_number()) | 109 name = lambda state : str(state.node_number()) |
| 110 counters = { | 110 counters = { |
| 111 'removals' : 0, | 111 'removals' : 0, |
| 112 'goto_start' : 0, | 112 'goto_start' : 0, |
| 113 'store_token_and_goto' : 0, | 113 'store_token_and_goto' : 0, |
| 114 'store_harmony_token_and_goto' : 0, | 114 'store_harmony_token_and_goto' : 0, |
| 115 } | 115 } |
| 116 store_states = set([]) | 116 store_states = set([]) |
| 117 # generate a store action to replace an existing action | 117 # generate a store action to replace an existing action |
| 118 def replacement_action(old_action, transition_state): | 118 def replacement_action(old_action, transition_state): |
| 119 assert not old_action.entry_action() | |
| 120 assert old_action.match_action() | 119 assert old_action.match_action() |
| 121 state_id = name(transition_state) | 120 state_id = name(transition_state) |
| 122 if old_action.match_action()[0] == 'token': | 121 if old_action.match_action()[0] == 'token': |
| 123 old_token = old_action.match_action()[1] | 122 old_token = old_action.match_action()[1] |
| 124 if (transition_state.action().match_action()[0] == 'token' and | 123 if (transition_state.action().match_action()[0] == 'token' and |
| 125 transition_state.action().match_action()[1] == old_token): | 124 transition_state.action().match_action()[1] == old_token): |
| 126 # no need to store token | 125 # no need to store token |
| 127 match_action = ('goto_start', (state_id,)) | 126 match_action = ('goto_start', (state_id,)) |
| 128 counters['goto_start'] += 1 | 127 counters['goto_start'] += 1 |
| 129 else: | 128 else: |
| 130 counters['store_token_and_goto'] += 1 | 129 counters['store_token_and_goto'] += 1 |
| 131 match_action = ('store_token_and_goto', (old_token, state_id)) | 130 match_action = ('store_token_and_goto', (old_token, state_id)) |
| 132 elif old_action.match_action()[0] == 'harmony_token': | 131 elif old_action.match_action()[0] == 'harmony_token': |
| 133 match_action = ('store_harmony_token_and_goto', | 132 match_action = ('store_harmony_token_and_goto', |
| 134 (old_action.match_action()[1][0], | 133 (old_action.match_action()[1][0], |
| 135 old_action.match_action()[1][1], | 134 old_action.match_action()[1][1], |
| 136 old_action.match_action()[1][2], | 135 old_action.match_action()[1][2], |
| 137 state_id)) | 136 state_id)) |
| 138 counters['store_harmony_token_and_goto'] += 1 | 137 counters['store_harmony_token_and_goto'] += 1 |
| 139 else: | 138 else: |
| 140 raise Exception(old_action.match_action()) | 139 raise Exception(old_action.match_action()) |
| 141 return Action(None, match_action, old_action.precedence()) | 140 return Action(old_action.entry_action(), match_action, |
| 141 old_action.precedence()) |
| 142 # map the old state to the new state, with fewer transitions and | 142 # map the old state to the new state, with fewer transitions and |
| 143 # goto actions | 143 # goto actions |
| 144 def replace_state(state, acc): | 144 def replace_state(state, acc): |
| 145 new_state = { | 145 new_state = { |
| 146 'transitions' : {}, | 146 'transitions' : {}, |
| 147 'terminal' : state in self.__dfa.terminal_set(), | 147 'terminal' : state in self.__dfa.terminal_set(), |
| 148 'action' : state.action(), | 148 'action' : state.action(), |
| 149 } | 149 } |
| 150 states[name(state)] = new_state | 150 states[name(state)] = new_state |
| 151 state_replacements = replacements[state] if state in replacements else {} | 151 state_replacements = replacements[state] if state in replacements else {} |
| 152 for transition_key, transition_state in state.transitions().items(): | 152 for transition_key, transition_state in state.transitions().items(): |
| 153 if not transition_key in state_replacements: | 153 if not transition_key in state_replacements: |
| 154 new_state['transitions'][transition_key] = name(transition_state) | 154 new_state['transitions'][transition_key] = name(transition_state) |
| 155 continue | 155 continue |
| 156 replacement = state_replacements[transition_key] | 156 replacement = state_replacements[transition_key] |
| 157 del state_replacements[transition_key] | 157 del state_replacements[transition_key] |
| 158 # just drop the transition | 158 # just drop the transition |
| 159 if replacement == None: | 159 if replacement == None: |
| 160 counters['removals'] += 1 | 160 counters['removals'] += 1 |
| 161 continue | 161 continue |
| 162 assert replacement == transition_state | 162 assert replacement == transition_state |
| 163 # do goto replacement | 163 # do goto replacement |
| 164 new_state['action'] = replacement_action(state.action(), replacement) | 164 new_state['action'] = replacement_action(state.action(), replacement) |
| 165 # will need to patch up transition_state | 165 # will need to patch up transition_state |
| 166 store_states.add(name(transition_state)) | 166 store_states.add(name(transition_state)) |
| 167 assert not state_replacements | 167 assert not state_replacements |
| 168 self.__dfa.visit_all_states(replace_state) | 168 self.__dfa.visit_all_states(replace_state) |
| 169 # now patch up all states with stores | 169 # now patch up all states with stores |
| 170 start_name = name(self.__dfa.start_state()) |
| 170 for state_id in store_states: | 171 for state_id in store_states: |
| 171 old_action = states[state_id]['action'] | 172 old_action = states[state_id]['action'] |
| 172 assert not old_action.entry_action() | 173 assert not old_action.entry_action() |
| 173 assert old_action.match_action()[0] == 'token', 'unimplemented' | 174 assert old_action.match_action()[0] == 'token', 'unimplemented' |
| 174 entry_action = ('store_token', old_action.match_action()[1]) | 175 entry_action = ('store_token', old_action.match_action()[1]) |
| 175 match_action = ('do_stored_token', state_id) | 176 match_action = ('do_stored_token', state_id) |
| 176 precedence = old_action.precedence() | 177 precedence = old_action.precedence() |
| 177 states[state_id]['action'] = Action( | 178 states[state_id]['action'] = Action( |
| 178 entry_action, match_action, precedence) | 179 entry_action, match_action, precedence) |
| 179 start_name = name(self.__dfa.start_state()) | 180 # The state might be only reachable via gotos; make sure it's connected in |
| 181 # the state graph by adding a bogus transition from the start state. This |
| 182 # transition doens't match any character. |
| 183 states[start_name]['transitions'][ |
| 184 TransitionKey.unique('no_match')] = state_id |
| 185 |
| 180 if self.__log: | 186 if self.__log: |
| 181 print 'goto_start inserted %s' % counters['goto_start'] | 187 print 'goto_start inserted %s' % counters['goto_start'] |
| 182 print 'store_token_and_goto inserted %s' % ( | 188 print 'store_token_and_goto inserted %s' % ( |
| 183 counters['store_token_and_goto']) | 189 counters['store_token_and_goto']) |
| 184 print 'store_harmony_token_and_goto %s' % ( | 190 print 'store_harmony_token_and_goto %s' % ( |
| 185 counters['store_harmony_token_and_goto']) | 191 counters['store_harmony_token_and_goto']) |
| 186 print 'transitions removed %s' % counters['removals'] | 192 print 'transitions removed %s' % counters['removals'] |
| 187 print 'do_stored_token actions added %s' % len(store_states) | 193 print 'do_stored_token actions added %s' % len(store_states) |
| 188 self.__dfa = Dfa(self.__dfa.encoding(), start_name, states) | 194 self.__dfa = Dfa(self.__dfa.encoding(), start_name, states) |
| 189 | 195 |
| 190 @staticmethod | 196 @staticmethod |
| 191 def optimize(dfa, log): | 197 def optimize(dfa, log): |
| 192 optimizer = DfaOptimizer(dfa, log) | 198 optimizer = DfaOptimizer(dfa, log) |
| 193 optimizer.replace_tokens_with_gotos() | 199 optimizer.replace_tokens_with_gotos() |
| 194 return optimizer.__dfa | 200 return optimizer.__dfa |
| OLD | NEW |