From b8613bcccb13f22ef9e5a0973fce325e0ceb3d49 Mon Sep 17 00:00:00 2001 From: Joe Shochet Date: Tue, 24 Aug 2004 08:51:51 +0000 Subject: [PATCH] optimizations to overloaded functions --- direct/src/ffi/FFIOverload.py | 72 ++++++++++++++++++++++++++--------- direct/src/ffi/FFISpecs.py | 30 +++++++-------- 2 files changed, 67 insertions(+), 35 deletions(-) diff --git a/direct/src/ffi/FFIOverload.py b/direct/src/ffi/FFIOverload.py index 1b5bcfb27b..1e97f89b9a 100644 --- a/direct/src/ffi/FFIOverload.py +++ b/direct/src/ffi/FFIOverload.py @@ -341,20 +341,49 @@ class FFIMethodArgumentTree: def traverse(self, file, nesting, level): oneTreeHasArgs = 0 typeNameList = [] + + # First see if this tree branches at all. If it does not there are + # drastic optimizations we can take because we can simply call the + # bottom-most function. We are not checking the types of all the + # arguments for the sake of type checking, we are simply trying to + # figure out which overloaded function to call. If there is only + # one overloaded function with this number of arguements at this + # level, it must be the one. No need to continue checking all the + # arguments. + branches = 0 + subTree = self + prevTree = subTree + levelCopy = level + + while subTree: + if (len(subTree.tree.keys()) == 0): + # Dead end branch + break + if (len(subTree.tree.keys()) > 1): + # Ok, we branch, it was worth a try though + branches = 1 + break + + prevTree = subTree + # Must only have one subtree, traverse it + subTree = subTree.tree.values()[0][0] + levelCopy += 1 + + # If there were no branches, this is easy + # Just output the function and return + # Note this operates on prevTree because subTree went one too far + if not branches: + methodSpec = prevTree.tree.values()[0][1] + indent(file, nesting+2, 'return ') + methodSpec.outputOverloadedCall(file, prevTree.classTypeDesc, levelCopy) + return + + # Ok, We must have a branch down here somewhere # Make a copy of the keys so we can sort them in place sortedKeys = self.tree.keys() # Sort the keys based on inheritance hierarchy, most specific classes first sortedKeys.sort(subclass) - # Import everybody we need - for i in range(len(sortedKeys)): - typeDesc = sortedKeys[i] - if ((typeDesc != 0) and - (not typeDesc.isNested) and - # Do not put our own module in the import list - (self.classTypeDesc != typeDesc) and - # If this is a class (not a primitive), put it on the list - (typeDesc.__class__ == FFITypes.ClassTypeDescriptor)): - indent(file, nesting+2, 'import ' + typeDesc.foreignTypeName + '\n') + for i in range(len(sortedKeys)): typeDesc = sortedKeys[i] # See if this takes no arguments @@ -364,6 +393,15 @@ class FFIMethodArgumentTree: indent(file, nesting+2, 'return ') methodSpec.outputOverloadedCall(file, self.classTypeDesc, 0) else: + # Import a file if we need to for this typeDesc + if ((typeDesc != 0) and + (not typeDesc.isNested) and + # Do not put our own module in the import list + (self.classTypeDesc != typeDesc) and + # If this is a class (not a primitive), put it on the list + (typeDesc.__class__ == FFITypes.ClassTypeDescriptor)): + indent(file, nesting+2, 'import ' + typeDesc.foreignTypeName + '\n') + # Specify that at least one of these trees had arguments # so we know to output an else clause oneTreeHasArgs = 1 @@ -384,23 +422,19 @@ class FFIMethodArgumentTree: + 'types.IntType' + '))') - if (i == 0): - indent(file, nesting+2, 'if ' + condition + ':\n') - else: - indent(file, nesting+2, 'elif ' + condition + ':\n') - # Get to the bottom of this chain - if (self.tree[typeDesc][0] != None): + indent(file, nesting+2, 'if ' + condition + ':\n') + + if (self.tree[typeDesc][0] is not None): self.tree[typeDesc][0].traverse(file, nesting+1, level+1) else: - # Output the function methodSpec = self.tree[typeDesc][1] indent(file, nesting+3, 'return ') numArgs = level+1 methodSpec.outputOverloadedCall(file, self.classTypeDesc, numArgs) + # Output an else clause if one of the trees had arguments if oneTreeHasArgs: - indent(file, nesting+2, 'else:\n') - indent(file, nesting+3, "raise TypeError, 'Invalid argument " + `level` + ", expected one of: ") + indent(file, nesting+2, "raise TypeError, 'Invalid argument " + `level` + ", expected one of: ") for name in typeNameList: indent(file, 0, ('<' + name + '> ')) indent(file, 0, "'\n") diff --git a/direct/src/ffi/FFISpecs.py b/direct/src/ffi/FFISpecs.py index 1409f2812c..ebb5e59750 100644 --- a/direct/src/ffi/FFISpecs.py +++ b/direct/src/ffi/FFISpecs.py @@ -101,9 +101,9 @@ class FunctionSpecification: """ Write the function call to call this overloaded method For example: - self.overloaded_setPos_ptrNodePath_float_float_float(_args[0], _args[1], _args[2]) + self.overloaded_setPos_ptrNodePath_float_float_float(*_args) If it is a class (static) method, call the class method - Class.overloaded_setPos_ptrNodePath_float_float_float(_args[0], _args[1], _args[2]) + Class.overloaded_setPos_ptrNodePath_float_float_float(*_args) Constructors are not treated as static. They are special because they are not really constructors, they are instance methods that fill @@ -117,22 +117,20 @@ class FunctionSpecification: """ if classTypeDesc: if (self.isStatic() and not self.isConstructor()): - indent(file, 0, classTypeDesc.foreignTypeName + '.' + self.getFinalName() + '(') + if numArgs: + indent(file, 0, classTypeDesc.foreignTypeName + '.' + self.getFinalName() + '(*_args)\n') + else: + indent(file, 0, classTypeDesc.foreignTypeName + '.' + self.getFinalName() + '()\n') else: - indent(file, 0, 'self.' + self.getFinalName() + '(') - - for i in range(numArgs): - file.write('_args[' + `i` + ']') - if (i != (numArgs - 1)): - file.write(', ') - file.write(')\n') + if numArgs: + indent(file, 0, 'self.' + self.getFinalName() + '(*_args)\n') + else: + indent(file, 0, 'self.' + self.getFinalName() + '()\n') else: - indent(file, 0, self.getFinalName() + '(') - for i in range(numArgs): - file.write('_args[' + `i` + ']') - if (i != (numArgs - 1)): - file.write(', ') - file.write(')\n') + if numArgs: + indent(file, 0, self.getFinalName() + '(*_args)\n') + else: + indent(file, 0, self.getFinalName() + '()\n') class GlobalFunctionSpecification(FunctionSpecification):