|
@@ -3,10 +3,25 @@ class PrimitiveFinished(Exception):
|
|
|
def __init__(self, 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"
|
|
|
"""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."""
|
|
|
-
|
|
|
+
|
|
|
def integer_subtraction(a, b, **remainder):
|
|
|
a_value, b_value = yield [("RV", [a]), ("RV", [b])]
|
|
|
result, = yield [("CNV", [a_value - b_value])]
|