Fixed #6716 (Performance: Alternative String Representation in Match Compiler)

This commit is contained in:
Frank Zingsheim 2015-06-07 16:18:40 +02:00 committed by Daniel Marjamäki
parent 0ca410a4d7
commit bac5aac92a
1 changed files with 32 additions and 31 deletions

View File

@ -32,7 +32,6 @@ class MatchCompiler:
def _reset(self): def _reset(self):
self._rawMatchFunctions = [] self._rawMatchFunctions = []
self._matchStrs = {}
self._matchFunctionCache = {} self._matchFunctionCache = {}
def _generateCacheSignature( def _generateCacheSignature(
@ -81,16 +80,6 @@ class MatchCompiler:
self._matchFunctionCache[signature] = id self._matchFunctionCache[signature] = id
def _insertMatchStr(self, look_for):
prefix = 'matchStr'
# Add entry if needed
if look_for not in self._matchStrs:
pos = len(self._matchStrs) + 1
self._matchStrs[look_for] = pos
return prefix + str(self._matchStrs[look_for])
def _compileCmd(self, tok): def _compileCmd(self, tok):
if tok == '%any%': if tok == '%any%':
return 'true' return 'true'
@ -107,9 +96,9 @@ class MatchCompiler:
elif tok == '%op%': elif tok == '%op%':
return 'tok->isOp()' return 'tok->isOp()'
elif tok == '%or%': elif tok == '%or%':
return '(tok->type() == Token::eBitOp && tok->str()==' + self._insertMatchStr('|') + ')/* | */' return '(tok->type() == Token::eBitOp && tok->str()==MatchCompiler::makeConstString("|") )'
elif tok == '%oror%': elif tok == '%oror%':
return '(tok->type() == Token::eLogicalOp && tok->str()==' + self._insertMatchStr('||') + ')/* || */' return '(tok->type() == Token::eLogicalOp && tok->str()==MatchCompiler::makeConstString("||"))'
elif tok == '%str%': elif tok == '%str%':
return '(tok->type()==Token::eString)' return '(tok->type()==Token::eString)'
elif tok == '%type%': elif tok == '%type%':
@ -126,7 +115,7 @@ class MatchCompiler:
print("unhandled:" + tok) print("unhandled:" + tok)
return ( return (
'(tok->str()==' + self._insertMatchStr(tok) + ')/* ' + tok + ' */' '(tok->str()==MatchCompiler::makeConstString("' + tok + '"))'
) )
def _compilePattern(self, pattern, nr, varid, def _compilePattern(self, pattern, nr, varid,
@ -164,8 +153,7 @@ class MatchCompiler:
# [abc] # [abc]
if (len(tok) > 2) and (tok[0] == '[') and (tok[-1] == ']'): if (len(tok) > 2) and (tok[0] == '[') and (tok[-1] == ']'):
ret += ' if (!tok || tok->str().size()!=1U || !strchr("' + tok[ ret += ' if (!tok || tok->str().size()!=1U || !strchr("' + tok[1:-1] + '", tok->str()[0]))\n'
1:-1] + '", tok->str()[0]))\n'
ret += ' ' + returnStatement ret += ' ' + returnStatement
# a|b|c # a|b|c
@ -200,8 +188,7 @@ class MatchCompiler:
# !!a # !!a
elif tok[0:2] == "!!": elif tok[0:2] == "!!":
ret += ' if (tok && tok->str() == ' + self._insertMatchStr( ret += ' if (tok && tok->str() == MatchCompiler::makeConstString("' + tok[2:] + '"))\n'
tok[2:]) + ')/* ' + tok[2:] + ' */\n'
ret += ' ' + returnStatement ret += ' ' + returnStatement
gotoNextToken = ' tok = tok ? tok->next() : NULL;\n' gotoNextToken = ' tok = tok ? tok->next() : NULL;\n'
@ -272,6 +259,23 @@ class MatchCompiler:
return None return None
def _isInString(self, line, pos1):
pos = 0
inString = False
while pos != pos1:
if inString:
if line[pos] == '\\':
pos += 1
elif line[pos] == '"':
inString = False
else:
if line[pos] == '\\':
pos += 1
elif line[pos] == '"':
inString = True
pos += 1
return inString
def _parseStringComparison(self, line, pos1): def _parseStringComparison(self, line, pos1):
startPos = 0 startPos = 0
endPos = 0 endPos = 0
@ -505,7 +509,7 @@ class MatchCompiler:
return ( return (
line[:start_pos] + functionName + str( line[:start_pos] + functionName + str(
findMatchNumber) + '(' + tok + more_args + ')' + line[start_pos + end_pos:] findMatchNumber) + '(' + tok + more_args + ') ' + line[start_pos + end_pos:]
) )
def _replaceTokenFindMatch(self, line): def _replaceTokenFindMatch(self, line):
@ -576,12 +580,13 @@ class MatchCompiler:
def _replaceCStrings(self, line): def _replaceCStrings(self, line):
while True: while True:
match = re.search('str\(\) *(==|!=) *"', line) match = re.search('(==|!=) *"', line)
if not match:
match = re.search('strAt\(.+?\) *(==|!=) *"', line)
if not match: if not match:
break break
if self._isInString(line, match.start()):
break
res = self._parseStringComparison(line, match.start()) res = self._parseStringComparison(line, match.start())
if res is None: if res is None:
break break
@ -589,8 +594,9 @@ class MatchCompiler:
startPos = res[0] startPos = res[0]
endPos = res[1] endPos = res[1]
text = line[startPos + 1:endPos - 1] text = line[startPos + 1:endPos - 1]
line = line[:startPos] + self._insertMatchStr(text) + line[endPos:] line = line[:startPos] + 'MatchCompiler::makeConstStringBegin' + text + 'MatchCompiler::makeConstStringEnd' + line[endPos:]
line = line.replace('MatchCompiler::makeConstStringBegin', 'MatchCompiler::makeConstString("')
line = line.replace('MatchCompiler::makeConstStringEnd', '")')
return line return line
def convertFile(self, srcname, destname): def convertFile(self, srcname, destname):
@ -602,6 +608,7 @@ class MatchCompiler:
header = '#include "token.h"\n' header = '#include "token.h"\n'
header += '#include "errorlogger.h"\n' header += '#include "errorlogger.h"\n'
header += '#include "matchcompiler.h"\n'
header += '#include <string>\n' header += '#include <string>\n'
header += '#include <cstring>\n' header += '#include <cstring>\n'
# header += '#include <iostream>\n' # header += '#include <iostream>\n'
@ -619,19 +626,13 @@ class MatchCompiler:
code += line code += line
# Compute string list
stringList = ''
for match in sorted(self._matchStrs, key=self._matchStrs.get):
stringList += 'static const std::string matchStr' + \
str(self._matchStrs[match]) + '("' + match + '");\n'
# Compute matchFunctions # Compute matchFunctions
strFunctions = '' strFunctions = ''
for function in self._rawMatchFunctions: for function in self._rawMatchFunctions:
strFunctions += function strFunctions += function
fout = open(destname, 'wt') fout = open(destname, 'wt')
fout.write(header + stringList + strFunctions + code) fout.write(header + strFunctions + code)
fout.close() fout.close()