| 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 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 47 dfa = rule_processor.default_automata().dfa() | 47 dfa = rule_processor.default_automata().dfa() |
| 48 self.__dfa = dfa | 48 self.__dfa = dfa |
| 49 self.__default_action = rule_processor.default_action | 49 self.__default_action = rule_processor.default_action |
| 50 self.__debug_print = debug_print | 50 self.__debug_print = debug_print |
| 51 self.__start_node_number = self.__dfa.start_state().node_number() | 51 self.__start_node_number = self.__dfa.start_state().node_number() |
| 52 self.__log = log | 52 self.__log = log |
| 53 self.__inline = inline | 53 self.__inline = inline |
| 54 self.__switching = switching | 54 self.__switching = switching |
| 55 self.__jump_table = [] | 55 self.__jump_table = [] |
| 56 | 56 |
| 57 __jump_labels = ['state_entry', 'after_entry_code', 'before_match'] | 57 __jump_labels = ['state_entry', 'after_entry_code'] |
| 58 | 58 |
| 59 @staticmethod | 59 @staticmethod |
| 60 def __transform_state(encoding, state): | 60 def __transform_state(encoding, state): |
| 61 # action data | 61 # action data |
| 62 action = state.action() | 62 action = state.action() |
| 63 entry_action = None if not action else action.entry_action() | 63 entry_action = None if not action else action.entry_action() |
| 64 match_action = None if not action else action.match_action() | 64 match_action = None if not action else action.match_action() |
| 65 # generate ordered transitions | 65 # generate ordered transitions |
| 66 transitions = map(lambda (k, v) : (k, v.node_number()), | 66 transitions = map(lambda (k, v) : (k, v.node_number()), |
| 67 state.transitions().items()) | 67 state.transitions().items()) |
| 68 def cmp(left, right): | 68 def cmp(left, right): |
| 69 return TransitionKey.canonical_compare(left[0], right[0]) | 69 return TransitionKey.canonical_compare(left[0], right[0]) |
| 70 transitions = sorted(transitions, cmp) | 70 transitions = sorted(transitions, cmp) |
| 71 # map transition keys to disjoint ranges and collect stats | 71 # map transition keys to disjoint ranges and collect stats |
| 72 disjoint_keys = [] | 72 disjoint_keys = [] |
| 73 unique_transitions = {} | 73 unique_transitions = {} |
| 74 old_transitions = transitions | 74 old_transitions = transitions |
| 75 transitions = [] | 75 transitions = [] |
| 76 (class_keys, distinct_keys, ranges) = (0, 0, 0) | 76 (class_keys, distinct_keys, ranges) = (0, 0, 0) |
| 77 zero_transition = None |
| 77 for key, transition_id in old_transitions: | 78 for key, transition_id in old_transitions: |
| 78 keys = [] | 79 keys = [] |
| 79 for (t, r) in key.range_iter(encoding): | 80 for (t, r) in key.range_iter(encoding): |
| 80 if t == 'CLASS': | 81 if t == 'CLASS': |
| 81 class_keys += 1 | 82 class_keys += 1 |
| 82 keys.append((t, r)) | 83 keys.append((t, r)) |
| 83 elif t == 'PRIMARY_RANGE': | 84 elif t == 'PRIMARY_RANGE': |
| 84 distinct_keys += r[1] - r[0] + 1 | 85 distinct_keys += r[1] - r[0] + 1 |
| 85 ranges += 1 | 86 ranges += 1 |
| 87 # split 0 out of range, don't bother updating stats |
| 88 assert r[0] >= 0 |
| 89 if r[0] == 0: |
| 90 assert zero_transition == None |
| 91 zero_transition = transition_id |
| 92 if r[0] == r[1]: |
| 93 continue |
| 94 r = (r[0] + 1, r[1]) |
| 86 keys.append((t, r)) | 95 keys.append((t, r)) |
| 87 elif t == 'UNIQUE': | 96 elif t == 'UNIQUE': |
| 88 assert r == 'no_match' or r == 'eos' | 97 assert r == 'no_match' or r == 'eos' |
| 89 assert r not in unique_transitions | 98 assert r not in unique_transitions |
| 90 unique_transitions[r] = transition_id | 99 unique_transitions[r] = transition_id |
| 91 else: | 100 else: |
| 92 raise Exception() | 101 raise Exception() |
| 93 if keys: | 102 if keys: |
| 94 transitions.append((keys, transition_id)) | 103 transitions.append((keys, transition_id)) |
| 104 # delay zero transition until last |
| 105 if zero_transition != None: |
| 106 transitions.append(([('PRIMARY_RANGE', (0, 0))], transition_id)) |
| 95 return { | 107 return { |
| 96 'node_number' : None, | 108 'node_number' : None, |
| 97 'original_node_number' : state.node_number(), | 109 'original_node_number' : state.node_number(), |
| 98 'transitions' : transitions, | 110 'transitions' : transitions, |
| 99 # flags for code generator | 111 # flags for code generator |
| 100 'can_elide_read' : len(transitions) == 0, | 112 'can_elide_read' : len(transitions) == 0, |
| 101 'is_eos_handler' : False, | 113 'is_eos_handler' : False, |
| 102 'inline' : None, | 114 'inline' : False, |
| 103 'must_not_inline' : False, | 115 'must_not_inline' : False, |
| 104 # transitions for code generator | 116 # transitions for code generator |
| 105 'if_transitions' : [], | 117 'if_transitions' : [], |
| 106 'switch_transitions' : [], | 118 'switch_transitions' : [], |
| 107 'deferred_transitions' : [], | 119 'deferred_transitions' : [], |
| 108 'unique_transitions' : unique_transitions, | 120 'unique_transitions' : unique_transitions, |
| 109 # state actions | 121 # state actions |
| 110 'entry_action' : entry_action, | 122 'entry_action' : entry_action, |
| 111 'match_action' : match_action, | 123 'match_action' : match_action, |
| 112 # statistics for states | 124 # statistics for states |
| 113 'class_keys' : class_keys, | 125 'class_keys' : class_keys, |
| 114 'distinct_keys' : distinct_keys, | 126 'distinct_keys' : distinct_keys, |
| 115 'ranges' : ranges, | 127 'ranges' : ranges, |
| 116 # record of which entry points will be needed | 128 # record of which entry points will be needed |
| 117 'entry_points' : {k : False for k in CodeGenerator.__jump_labels} | 129 'entry_points' : {k : False for k in CodeGenerator.__jump_labels} |
| 118 } | 130 } |
| 119 | 131 |
| 120 def __register_jump(self, node_id, label): | 132 def __register_jump(self, node_id, label): |
| 121 if label != 'inline': | 133 if label != 'inline': |
| 122 assert label in CodeGenerator.__jump_labels | 134 assert label in CodeGenerator.__jump_labels |
| 123 state = self.__dfa_states[node_id]['entry_points'][label] = True | 135 state = self.__dfa_states[node_id]['entry_points'][label] = True |
| 124 self.__jump_table.append((node_id, label)) | 136 self.__jump_table.append((node_id, label)) |
| 125 return len(self.__jump_table) - 1 | 137 return len(self.__jump_table) - 1 |
| 126 | 138 |
| 127 def __set_inline(self, count, state): | 139 def __set_inline(self, count, state): |
| 128 assert state['inline'] == None | |
| 129 inline = False | 140 inline = False |
| 130 if state['must_not_inline']: | 141 if state['must_not_inline']: |
| 131 inline = False | 142 inline = False |
| 132 # inline terminal states | 143 # inline terminal states |
| 133 elif not state['transitions']: | 144 elif not state['transitions']: |
| 134 inline = True | 145 inline = True |
| 135 # inline next to terminal states with 1 or 2 transitions | 146 # inline next to terminal states with 1 or 2 transitions |
| 136 elif state['distinct_keys'] < 3 and state['class_keys'] == 0: | 147 elif state['distinct_keys'] < 3 and state['class_keys'] == 0: |
| 137 inline = True | 148 inline = True |
| 138 # ensure state terminates in 1 step | 149 # ensure state terminates in 1 step |
| (...skipping 14 matching lines...) Expand all Loading... |
| 153 switch_transitions = [] | 164 switch_transitions = [] |
| 154 deferred_transitions = [] | 165 deferred_transitions = [] |
| 155 for (ranges, node_id) in state['transitions']: | 166 for (ranges, node_id) in state['transitions']: |
| 156 i = [] | 167 i = [] |
| 157 s = [] | 168 s = [] |
| 158 d = [] | 169 d = [] |
| 159 for r in ranges: | 170 for r in ranges: |
| 160 # all class checks will be deferred to after all other checks | 171 # all class checks will be deferred to after all other checks |
| 161 if r[0] == 'CLASS': | 172 if r[0] == 'CLASS': |
| 162 d.append(r) | 173 d.append(r) |
| 163 elif no_switch: | 174 # zero must assigned to an if check because of eos check |
| 175 elif no_switch or (r[1][0] == 0): |
| 164 i.append(r) | 176 i.append(r) |
| 165 else: | 177 else: |
| 166 s.append(r[1]) | 178 s.append(r[1]) |
| 167 if i: | 179 if i: |
| 168 if_transitions.append((i, node_id)) | 180 if_transitions.append((i, node_id)) |
| 169 if s: | 181 if s: |
| 170 switch_transitions.append((s, node_id)) | 182 switch_transitions.append((s, node_id)) |
| 171 if d: | 183 if d: |
| 172 deferred_transitions.append((d, node_id)) | 184 deferred_transitions.append((d, node_id)) |
| 173 state['if_transitions'] = if_transitions | 185 state['if_transitions'] = if_transitions |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 347 else: | 359 else: |
| 348 assert not target_id in inline_mapping | 360 assert not target_id in inline_mapping |
| 349 return (key, self.__register_jump(target_id, jump_type)) | 361 return (key, self.__register_jump(target_id, jump_type)) |
| 350 for name in transition_names: | 362 for name in transition_names: |
| 351 state[name] = map(generate_jump, state[name]) | 363 state[name] = map(generate_jump, state[name]) |
| 352 if 'eos' in state['unique_transitions']: | 364 if 'eos' in state['unique_transitions']: |
| 353 # eos state is not inlined | 365 # eos state is not inlined |
| 354 eos_state_id = state['unique_transitions']['eos'] | 366 eos_state_id = state['unique_transitions']['eos'] |
| 355 jump = self.__register_jump(eos_state_id, 'state_entry') | 367 jump = self.__register_jump(eos_state_id, 'state_entry') |
| 356 state['unique_transitions']['eos'] = jump | 368 state['unique_transitions']['eos'] = jump |
| 357 elif state['transitions']: | |
| 358 jump = self.__register_jump(state_id, 'before_match') | |
| 359 state['jump_before_match'] = jump | |
| 360 # now rewrite all nodes created | 369 # now rewrite all nodes created |
| 361 nodes_created = len(inline_mapping) - len(inline_mapping_in) | 370 nodes_created = len(inline_mapping) - len(inline_mapping_in) |
| 362 assert len(self.__dfa_states) == ( | 371 assert len(self.__dfa_states) == ( |
| 363 end_offset + total_nodes_created + nodes_created) | 372 end_offset + total_nodes_created + nodes_created) |
| 364 if nodes_created == 0: | 373 if nodes_created == 0: |
| 365 continue | 374 continue |
| 366 created = self.__rewrite_transitions_to_jumps( | 375 created = self.__rewrite_transitions_to_jumps( |
| 367 end_offset + total_nodes_created, nodes_created, inline_mapping) | 376 end_offset + total_nodes_created, nodes_created, inline_mapping) |
| 368 total_nodes_created += nodes_created + created | 377 total_nodes_created += nodes_created + created |
| 369 return total_nodes_created | 378 return total_nodes_created |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 409 | 418 |
| 410 return template.render( | 419 return template.render( |
| 411 start_node_number = 0, | 420 start_node_number = 0, |
| 412 debug_print = self.__debug_print, | 421 debug_print = self.__debug_print, |
| 413 default_action = default_action, | 422 default_action = default_action, |
| 414 dfa_states = dfa_states, | 423 dfa_states = dfa_states, |
| 415 jump_table = self.__jump_table, | 424 jump_table = self.__jump_table, |
| 416 encoding = encoding.name(), | 425 encoding = encoding.name(), |
| 417 char_type = char_type, | 426 char_type = char_type, |
| 418 upper_bound = encoding.primary_range()[1]) | 427 upper_bound = encoding.primary_range()[1]) |
| OLD | NEW |