1.1 --- a/encoders.py Fri Feb 17 18:49:57 2017 +0100
1.2 +++ b/encoders.py Fri Feb 17 18:52:18 2017 +0100
1.3 @@ -210,10 +210,18 @@
1.4 "__load_static_ignore", "__load_static_replace", "__load_static_test",
1.5 )
1.6
1.7 +context_values = (
1.8 + "<context>",
1.9 + )
1.10 +
1.11 +context_ops = (
1.12 + "<context>", "<set_context>",
1.13 + )
1.14 +
1.15 reference_acting_ops = attribute_ops + checked_ops + typename_ops
1.16 attribute_producing_ops = attribute_loading_ops + checked_loading_ops
1.17
1.18 -def encode_access_instruction(instruction, subs):
1.19 +def encode_access_instruction(instruction, subs, context_index):
1.20
1.21 """
1.22 Encode the 'instruction' - a sequence starting with an operation and
1.23 @@ -223,6 +231,9 @@
1.24 The 'subs' parameter defines a mapping of substitutions for special values
1.25 used in instructions.
1.26
1.27 + The 'context_index' parameter defines the position in local context storage
1.28 + for the referenced context or affected by a context operation.
1.29 +
1.30 Return both the encoded instruction and a collection of substituted names.
1.31 """
1.32
1.33 @@ -230,53 +241,60 @@
1.34 args = instruction[1:]
1.35 substituted = set()
1.36
1.37 - if not args:
1.38 - argstr = ""
1.39 + # Encode the arguments.
1.40
1.41 - else:
1.42 - # Encode the arguments.
1.43 -
1.44 - a = []
1.45 + a = []
1.46 + if args:
1.47 converting_op = op
1.48 for arg in args:
1.49 - s, _substituted = encode_access_instruction_arg(arg, subs, converting_op)
1.50 + s, _substituted = encode_access_instruction_arg(arg, subs, converting_op, context_index)
1.51 substituted.update(_substituted)
1.52 a.append(s)
1.53 converting_op = None
1.54
1.55 - # Modify certain arguments.
1.56 + # Modify certain arguments.
1.57
1.58 - # Convert attribute name arguments to position symbols.
1.59 + # Convert attribute name arguments to position symbols.
1.60
1.61 - if op in attribute_ops:
1.62 - arg = a[1]
1.63 - a[1] = encode_symbol("pos", arg)
1.64 + if op in attribute_ops:
1.65 + arg = a[1]
1.66 + a[1] = encode_symbol("pos", arg)
1.67 +
1.68 + # Convert attribute name arguments to position and code symbols.
1.69
1.70 - # Convert attribute name arguments to position and code symbols.
1.71 + elif op in checked_ops:
1.72 + arg = a[1]
1.73 + a[1] = encode_symbol("pos", arg)
1.74 + a.insert(2, encode_symbol("code", arg))
1.75
1.76 - elif op in checked_ops:
1.77 - arg = a[1]
1.78 - a[1] = encode_symbol("pos", arg)
1.79 - a.insert(2, encode_symbol("code", arg))
1.80 + # Convert type name arguments to position and code symbols.
1.81
1.82 - # Convert type name arguments to position and code symbols.
1.83 + elif op in typename_ops:
1.84 + arg = encode_type_attribute(args[1])
1.85 + a[1] = encode_symbol("pos", arg)
1.86 + a.insert(2, encode_symbol("code", arg))
1.87
1.88 - elif op in typename_ops:
1.89 - arg = encode_type_attribute(args[1])
1.90 - a[1] = encode_symbol("pos", arg)
1.91 - a.insert(2, encode_symbol("code", arg))
1.92 + # Obtain addresses of type arguments.
1.93 +
1.94 + elif op in type_ops:
1.95 + a[1] = "&%s" % a[1]
1.96
1.97 - # Obtain addresses of type arguments.
1.98 + # Obtain addresses of static objects.
1.99 +
1.100 + elif op in static_ops:
1.101 + a[-1] = "&%s" % a[-1]
1.102
1.103 - elif op in type_ops:
1.104 - a[1] = "&%s" % a[1]
1.105 + # Add context storage information to certain operations.
1.106
1.107 - # Obtain addresses of static objects.
1.108 + elif op in context_ops:
1.109 + a.insert(0, context_index)
1.110
1.111 - elif op in static_ops:
1.112 - a[-1] = "&%s" % a[-1]
1.113 + # Define any argument string.
1.114
1.115 + if a:
1.116 argstr = "(%s)" % ", ".join(map(str, a))
1.117 + else:
1.118 + argstr = ""
1.119
1.120 # Substitute the first element of the instruction, which may not be an
1.121 # operation at all.
1.122 @@ -300,16 +318,19 @@
1.123
1.124 return "%s%s" % (op, argstr), substituted
1.125
1.126 -def encode_access_instruction_arg(arg, subs, op):
1.127 +def encode_access_instruction_arg(arg, subs, op, context_index):
1.128
1.129 """
1.130 - Encode 'arg' using 'subs' to define substitutions, returning a tuple
1.131 - containing the encoded form of 'arg' along with a collection of any
1.132 - substituted values.
1.133 + Encode 'arg' using 'subs' to define substitutions, 'op' to indicate the
1.134 + operation to which the argument belongs, and 'context_index' to indicate any
1.135 + affected context storage.
1.136 +
1.137 + Return a tuple containing the encoded form of 'arg' along with a collection
1.138 + of any substituted values.
1.139 """
1.140
1.141 if isinstance(arg, tuple):
1.142 - encoded, substituted = encode_access_instruction(arg, subs)
1.143 + encoded, substituted = encode_access_instruction(arg, subs, context_index)
1.144
1.145 # Convert attribute results to references where required.
1.146
1.147 @@ -321,7 +342,13 @@
1.148 # Special values only need replacing, not encoding.
1.149
1.150 elif subs.has_key(arg):
1.151 - return subs.get(arg), set([arg])
1.152 +
1.153 + # Handle values modified by storage details.
1.154 +
1.155 + if arg in context_values:
1.156 + return "%s(%s)" % (subs.get(arg), context_index), set([arg])
1.157 + else:
1.158 + return subs.get(arg), set([arg])
1.159
1.160 # Convert static references to the appropriate type.
1.161
2.1 --- a/templates/ops.h Fri Feb 17 18:49:57 2017 +0100
2.2 +++ b/templates/ops.h Fri Feb 17 18:52:18 2017 +0100
2.3 @@ -73,7 +73,8 @@
2.4 __attr __test_context(__ref context, __attr attr);
2.5 __attr __update_context(__ref context, __attr attr);
2.6
2.7 -#define __set_context(__ATTR) (__tmp_context = (__ATTR).value)
2.8 +#define __get_context(__TARGET) (__tmp_contexts[__TARGET])
2.9 +#define __set_context(__TARGET, __ATTR) (__tmp_contexts[__TARGET] = (__ATTR).value)
2.10 #define __set_accessor(__ATTR) (__tmp_value = (__ATTR).value)
2.11 #define __set_target_accessor(__ATTR) (__tmp_target_value = (__ATTR).value)
2.12
3.1 --- a/translator.py Fri Feb 17 18:49:57 2017 +0100
3.2 +++ b/translator.py Fri Feb 17 18:52:18 2017 +0100
3.3 @@ -739,8 +739,8 @@
3.4 }
3.5
3.6 temp_subs = {
3.7 - "<context>" : "__tmp_context",
3.8 - "<set_context>" : "__tmp_context",
3.9 + "<context>" : "__tmp_contexts",
3.10 + "<set_context>" : "__tmp_contexts",
3.11 "<accessor>" : "__tmp_value",
3.12 "<target_accessor>" : "__tmp_target_value",
3.13 "<set_accessor>" : "__tmp_value",
3.14 @@ -748,6 +748,7 @@
3.15 }
3.16
3.17 op_subs = {
3.18 + "<context>" : "__get_context",
3.19 "<set_context>" : "__set_context",
3.20 "<set_accessor>" : "__set_accessor",
3.21 "<set_target_accessor>" : "__set_target_accessor",
3.22 @@ -759,11 +760,16 @@
3.23 output = []
3.24 substituted = set()
3.25
3.26 + # The context set or retrieved will be that used by any enclosing
3.27 + # invocation.
3.28 +
3.29 + context_index = self.function_target - 1
3.30 +
3.31 # Obtain encoded versions of each instruction, accumulating temporary
3.32 # variables.
3.33
3.34 for instruction in self.optimiser.access_instructions[location]:
3.35 - encoded, _substituted = encode_access_instruction(instruction, subs)
3.36 + encoded, _substituted = encode_access_instruction(instruction, subs, context_index)
3.37 output.append(encoded)
3.38 substituted.update(_substituted)
3.39
3.40 @@ -1253,7 +1259,8 @@
3.41
3.42 if context_required:
3.43 if have_access_context:
3.44 - args = ["(__attr) {.value=__tmp_context}"]
3.45 + self.record_temp("__tmp_contexts")
3.46 + args = ["(__attr) {.value=__tmp_contexts[%d]}" % self.function_target]
3.47 else:
3.48 self.record_temp("__tmp_targets")
3.49 args = ["__CONTEXT_AS_VALUE(__tmp_targets[%d])" % self.function_target]
3.50 @@ -1367,12 +1374,13 @@
3.51 # Methods accessed via unidentified accessors are obtained.
3.52
3.53 elif function:
3.54 + self.record_temp("__tmp_contexts")
3.55 self.record_temp("__tmp_targets")
3.56
3.57 if context_required:
3.58 if have_access_context:
3.59 - stages.append("__get_function(__tmp_context, __tmp_targets[%d])" % (
3.60 - self.function_target))
3.61 + stages.append("__get_function(__tmp_contexts[%d], __tmp_targets[%d])" % (
3.62 + self.function_target, self.function_target))
3.63 else:
3.64 stages.append("__get_function(__CONTEXT_AS_VALUE(__tmp_targets[%d]).value, __tmp_targets[%d])" % (
3.65 self.function_target, self.function_target))
3.66 @@ -1925,14 +1933,15 @@
3.67
3.68 # Provide space for the given number of targets.
3.69
3.70 + targets = self.importer.function_targets.get(name)
3.71 +
3.72 if self.uses_temp(name, "__tmp_targets"):
3.73 - targets = self.importer.function_targets.get(name)
3.74 self.writeline("__attr __tmp_targets[%d];" % targets)
3.75 + if self.uses_temp(name, "__tmp_contexts"):
3.76 + self.writeline("__ref __tmp_contexts[%d];" % targets)
3.77
3.78 # Add temporary variable usage details.
3.79
3.80 - if self.uses_temp(name, "__tmp_context"):
3.81 - self.writeline("__ref __tmp_context;")
3.82 if self.uses_temp(name, "__tmp_value"):
3.83 self.writeline("__ref __tmp_value;")
3.84 if self.uses_temp(name, "__tmp_target_value"):