Browse Source

Add a comment that explains __primitive_return's rationale

jonathanvdc 8 years ago
parent
commit
0dcf3b4127
1 changed files with 16 additions and 1 deletions
  1. 16 1
      kernel/modelverse_kernel/primitives.py

+ 16 - 1
kernel/modelverse_kernel/primitives.py

@@ -3,10 +3,25 @@ class PrimitiveFinished(Exception):
     def __init__(self, value):
     def __init__(self, value):
         self.result = value
         self.result = value
 
 
+# Functions annotated with __primitive_return use the JIT's calling convention instead of
+# the kernel's: returns are handled by throwing a PrimitiveFinished exception; the caller's
+# returnvalue is not modified.
+#
+# ### Rationale for __primitive_return
+#
+# __primitive_return is a useful mechanism because it allows us to have an __interpret_function
+# implementation that has O(1) state read overhead. A previous implementation of
+# __interpret_function checked if the caller's frame had been popped whenever
+# ModelverseKernel.execute_yield threw a StopIteration exception. However, that incurs O(n) overhead
+# _per call,_ where n is the number of StopIteration exceptions that are thrown during the call.
+# O(n) is pretty bad, but this actually becomes O(n * m) when m calls to __interpret_function are
+# nested. And that's just not acceptable.
+# __primitive_return requires kernel support, but I think the complexity gains are well worth it;
+# I reckon JIT-to-interpreter switches aren't going to get a whole lot cheaper than this.
 PRIMITIVE_RETURN_KEY = "__primitive_return"
 PRIMITIVE_RETURN_KEY = "__primitive_return"
 """A dictionary key for functions which request that the kernel throw a PrimitiveFinished
 """A dictionary key for functions which request that the kernel throw a PrimitiveFinished
    exception with the return value instead of injecting the return value in the caller's frame."""
    exception with the return value instead of injecting the return value in the caller's frame."""
-    
+
 def integer_subtraction(a, b, **remainder):
 def integer_subtraction(a, b, **remainder):
     a_value, b_value =  yield [("RV", [a]), ("RV", [b])]
     a_value, b_value =  yield [("RV", [a]), ("RV", [b])]
     result, = yield [("CNV", [a_value - b_value])]
     result, = yield [("CNV", [a_value - b_value])]