compiler.embedding: use attribute count in fixpoint condition.

Before this commit, we had a hack where inferencing would run
one more time, in case we can still infer more attributes even
after all the type information is there. This doesn't work
if *that* round of inferencing brings even more code, e.g.
this is easy to trigger with context managers.
This commit is contained in:
whitequark 2017-02-28 21:28:05 +00:00
parent 252cda6e7f
commit 4107938fd8
1 changed files with 14 additions and 8 deletions

View File

@ -85,6 +85,14 @@ class EmbeddingMap:
n += 1 n += 1
new_instance_type.name = "{}.{}".format(new_instance_type.name, n) new_instance_type.name = "{}.{}".format(new_instance_type.name, n)
def attribute_count(self):
count = 0
for host_type in self.type_map:
instance_type, constructor_type = self.type_map[host_type]
count += len(instance_type.attributes)
count += len(constructor_type.attributes)
return count
# Functions # Functions
def store_function(self, function, ir_function_name): def store_function(self, function, ir_function_name):
self.function_map[function] = ir_function_name self.function_map[function] = ir_function_name
@ -725,22 +733,20 @@ class Stitcher:
inferencer = StitchingInferencer(engine=self.engine, inferencer = StitchingInferencer(engine=self.engine,
value_map=self.value_map, value_map=self.value_map,
quote=self._quote) quote=self._quote)
hasher = TypedtreeHasher() typedtree_hasher = TypedtreeHasher()
# Iterate inference to fixed point. # Iterate inference to fixed point.
old_typedtree_hash = None old_typedtree_hash = None
old_attr_count = None
while True: while True:
inferencer.visit(self.typedtree) inferencer.visit(self.typedtree)
typedtree_hash = hasher.visit(self.typedtree) typedtree_hash = typedtree_hasher.visit(self.typedtree)
attr_count = self.embedding_map.attribute_count()
if old_typedtree_hash == typedtree_hash: if old_typedtree_hash == typedtree_hash and old_attr_count == attr_count:
break break
old_typedtree_hash = typedtree_hash old_typedtree_hash = typedtree_hash
old_attr_count = attr_count
# When we have an excess of type information, sometimes we can infer every type
# in the AST without discovering every referenced attribute of host objects, so
# do one last pass unconditionally.
inferencer.visit(self.typedtree)
# After we've discovered every referenced attribute, check if any kernel_invariant # After we've discovered every referenced attribute, check if any kernel_invariant
# specifications refers to ones we didn't encounter. # specifications refers to ones we didn't encounter.