Lots of micro-performance adjustments using conventional Python
techniques of reducing the number of lookups and avoiding method calls. More interestingly, the dispatch machinery has changed, especially TALInterpreter.iterpret(). Each instruction is now composed of a 2-tuple of the form (opcode, (arg1, arg2, ...)). This is important as it allows more efficient unpacking and construction of the argument list for the call to the handlers for individual bytecodes. The bytecode handlers are also located differently. Instead of using the opcode string to construct a method name, retrieve a bound method, and then calling it via apply(), a dictionary of handler functions is created as part of the class definition. Handlers are retrieved from this dictionary by opcode string (avoiding string concatenation and bound method creation in the inner dispatch loop). The handlers (now functions rather than methods) are then called using apply(), creating the arguments to the handler by tuple concatenation, which is faster than creating the bound method and then using the slower method-calling machinery. Temporary variables are avoided whenever possible. The test for "debug mode" in TALInterpreter.interpret() was moved out of the dispatch loop; it is used to select one of the two versions of the loop. Support has been added for two new bytecodes: rawtextColumn -- used when the TALGenerator can determine the resulting column number ahead of time (the text includes a newline) rawtextOffset -- used when the TALGenerator cannot determine the final column of the text (there is no newline). These new bytecodes allow the interpreter to avoid having to search for a newline for all rawtext instructions -- the compiler is able to determine which of these two cases is appropriate for each rawtext chunk -- the old 'rawtext' instruction is no longer generated. Re-phrased some conditions in if statements to allow more short-circuiting.
Showing
This diff is collapsed.
Please register or sign in to comment