1.1 --- a/deducer.py Thu Oct 13 23:27:17 2016 +0200
1.2 +++ b/deducer.py Fri Oct 14 18:34:14 2016 +0200
1.3 @@ -399,13 +399,14 @@
1.4 locations.sort()
1.5
1.6 for location in locations:
1.7 - name, test, test_type, base, traversed, attrnames, context, \
1.8 + name, test, test_type, base, traversed, traversal_modes, attrnames, context, \
1.9 first_method, final_method, attr = self.access_plans[location]
1.10
1.11 print >>f_attrs, encode_access_location(location), \
1.12 name, test, test_type or "{}", \
1.13 base or "{}", \
1.14 ".".join(traversed) or "{}", \
1.15 + ".".join(traversal_modes) or "{}", \
1.16 ".".join(attrnames) or "{}", \
1.17 context, first_method, final_method, attr or "{}"
1.18
1.19 @@ -1854,13 +1855,18 @@
1.20 dynamic_base = ref.get_origin()
1.21
1.22 traversed = []
1.23 + traversal_modes = []
1.24 + provider_kind = first(provider_kinds)
1.25
1.26 # Traverse remaining attributes.
1.27
1.28 while len(attrs) == 1:
1.29 attr = first(attrs)
1.30 + accessor_kind = attr.get_kind()
1.31
1.32 traversed.append(attrname)
1.33 + traversal_modes.append(accessor_kind == provider_kind and "object" or "class")
1.34 +
1.35 del remaining[0]
1.36
1.37 if not remaining:
1.38 @@ -1871,11 +1877,13 @@
1.39 if attr.static():
1.40 base = attr.get_origin()
1.41 traversed = []
1.42 + traversal_modes = []
1.43
1.44 # Get the next attribute.
1.45
1.46 attrname = remaining[0]
1.47 attrs = self.importer.get_attributes(attr, attrname)
1.48 + provider_kind = self.importer.get_attribute_provider(attr, attrname)
1.49
1.50 # Where many attributes are suggested, no single attribute identity can
1.51 # be loaded.
1.52 @@ -1916,6 +1924,6 @@
1.53
1.54 context = len(traversed or remaining) == 1 and (base and "base" or "original-accessor") or "final-accessor"
1.55
1.56 - return name, test, test_type, base, traversed, remaining, context, first_method, final_method, origin
1.57 + return name, test, test_type, base, traversed, traversal_modes, remaining, context, first_method, final_method, origin
1.58
1.59 # vim: tabstop=4 expandtab shiftwidth=4
3.1 --- a/optimiser.py Thu Oct 13 23:27:17 2016 +0200
3.2 +++ b/optimiser.py Fri Oct 14 18:34:14 2016 +0200
3.3 @@ -82,7 +82,6 @@
3.4 self.position_parameters()
3.5 self.populate_tables()
3.6 self.populate_constants()
3.7 - self.refine_access_plans()
3.8 self.initialise_access_instructions()
3.9
3.10 def to_output(self):
3.11 @@ -113,6 +112,7 @@
3.12
3.13 location " " name " " test " " test type " " base
3.14 " " traversed attributes " " traversed attribute ambiguity
3.15 + " " traversal access modes
3.16 " " attributes to traverse " " attribute ambiguity
3.17 " " context " " access method " " static attribute
3.18
3.19 @@ -120,6 +120,9 @@
3.20
3.21 qualified name of scope "." local name ":" name version
3.22
3.23 + Traversal access modes are either "class" (obtain accessor class to
3.24 + access attribute) or "object" (obtain attribute directly from accessor).
3.25 +
3.26 ----
3.27
3.28 The structures are presented as a table in the following format:
3.29 @@ -195,28 +198,6 @@
3.30 finally:
3.31 f.close()
3.32
3.33 - f = open(join(self.output, "attribute_plans"), "w")
3.34 - try:
3.35 - access_plans = self.access_plans.items()
3.36 - access_plans.sort()
3.37 -
3.38 - for location, (name, test, test_type, base,
3.39 - traversed, traversed_ambiguity,
3.40 - attrnames, attrnames_ambiguity, context,
3.41 - first_method, final_method, attr) in access_plans:
3.42 -
3.43 - print >>f, encode_access_location(location), \
3.44 - name, test, test_type or "{}", \
3.45 - base or "{}", \
3.46 - ".".join(traversed) or "{}", \
3.47 - ".".join(map(str, traversed_ambiguity)) or "{}", \
3.48 - ".".join(map(str, attrnames_ambiguity)) or "{}", \
3.49 - ".".join(attrnames) or "{}", \
3.50 - context, first_method, final_method, attr or "{}"
3.51 -
3.52 - finally:
3.53 - f.close()
3.54 -
3.55 f = open(join(self.output, "instruction_plans"), "w")
3.56 try:
3.57 access_instructions = self.access_instructions.items()
3.58 @@ -355,25 +336,6 @@
3.59 l.extend([None] * (position - len(l) + 1))
3.60 l[position] = attrname
3.61
3.62 - def refine_access_plans(self):
3.63 -
3.64 - "Augment deduced access plans with attribute position information."
3.65 -
3.66 - for access_location, access_plan in self.deducer.access_plans.items():
3.67 -
3.68 - # Obtain the access details.
3.69 -
3.70 - name, test, test_type, base, traversed, attrnames, \
3.71 - context, first_method, final_method, origin = access_plan
3.72 -
3.73 - traversed_ambiguity = self.get_ambiguity_for_attributes(traversed)
3.74 - attrnames_ambiguity = self.get_ambiguity_for_attributes(attrnames)
3.75 -
3.76 - self.access_plans[access_location] = \
3.77 - name, test, test_type, base, traversed, traversed_ambiguity, \
3.78 - attrnames, attrnames_ambiguity, context, \
3.79 - first_method, final_method, origin
3.80 -
3.81 def initialise_access_instructions(self):
3.82
3.83 "Expand access plans into instruction sequences."
3.84 @@ -382,9 +344,8 @@
3.85
3.86 # Obtain the access details.
3.87
3.88 - name, test, test_type, base, traversed, traversed_ambiguity, \
3.89 - attrnames, attrnames_ambiguity, context, \
3.90 - first_method, final_method, origin = access_plan
3.91 + name, test, test_type, base, traversed, traversal_modes, \
3.92 + attrnames, context, first_method, final_method, origin = access_plan
3.93
3.94 instructions = []
3.95 emit = instructions.append
3.96 @@ -448,14 +409,14 @@
3.97 elif first_method == "check-object":
3.98 emit(("set_accessor", ("check_and_load_via_object", accessor, attrname)))
3.99 elif first_method == "check-object-class":
3.100 - emit(("set_accessor", ("get_class_check_and_load", accessor, attrname)))
3.101 + emit(("set_accessor", ("check_and_load_via_any", accessor, attrname)))
3.102
3.103 # Obtain an accessor.
3.104
3.105 remaining = len(traversed + attrnames)
3.106
3.107 if traversed:
3.108 - for attrname in traversed:
3.109 + for attrname, traversal_mode in zip(traversed, traversal_modes):
3.110
3.111 # Set the context, if appropriate.
3.112
3.113 @@ -465,12 +426,15 @@
3.114 # Perform the access only if not achieved directly.
3.115
3.116 if remaining > 1 or final_method == "access":
3.117 - emit(("set_accessor", ("load_unambiguous", "accessor", attrname)))
3.118 + if traversal_mode == "class":
3.119 + emit(("set_accessor", ("load_via_class", "accessor", attrname)))
3.120 + else:
3.121 + emit(("set_accessor", ("load_via_object", "accessor", attrname)))
3.122
3.123 remaining -= 1
3.124
3.125 if attrnames:
3.126 - for attrname, ambiguity in zip(attrnames, attrnames_ambiguity):
3.127 + for attrname in attrnames:
3.128
3.129 # Set the context, if appropriate.
3.130
3.131 @@ -480,10 +444,7 @@
3.132 # Perform the access only if not achieved directly.
3.133
3.134 if remaining > 1 or final_method == "access":
3.135 - if ambiguity == 1:
3.136 - emit(("set_accessor", ("load_unambiguous", "accessor", attrname)))
3.137 - else:
3.138 - emit(("set_accessor", ("load_ambiguous", "accessor", attrname)))
3.139 + emit(("set_accessor", ("check_and_load_via_any", "accessor", attrname)))
3.140
3.141 remaining -= 1
3.142