runtime.py 3.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. import modelverse_kernel.primitives as primitive_functions
  2. class JitCompilationFailedException(Exception):
  3. """A type of exception that is raised when the jit fails to compile a function."""
  4. pass
  5. def call_function(function_id, named_arguments, **kwargs):
  6. """Makes the interpreter run the function with the given id with the specified
  7. argument dictionary."""
  8. user_root = kwargs['user_root']
  9. user_frame, = yield [("RD", [user_root, "frame"])]
  10. inst, = yield [("RD", [user_frame, "IP"])]
  11. body_id, = yield [("RD", [function_id, "body"])]
  12. kernel = kwargs['mvk']
  13. kernel.jit.mark_entry_point(body_id)
  14. # Try to jit the function here. We might be able to avoid building the stack
  15. # frame.
  16. try:
  17. # Try to compile.
  18. jit_gen = kernel.jit_compile(user_root, body_id)
  19. inp = None
  20. while 1:
  21. inp = yield jit_gen.send(inp)
  22. except primitive_functions.PrimitiveFinished as ex:
  23. compiled_func = ex.result
  24. # Add the keyword arguments to the argument dictionary.
  25. named_arguments.update(kwargs)
  26. # Run the function.
  27. gen = compiled_func(**named_arguments)
  28. inp = None
  29. while 1:
  30. inp = yield gen.send(inp)
  31. # Let primitive_functions.PrimitiveFinished bubble up.
  32. except JitCompilationFailedException:
  33. # That's quite alright. Just build a stack frame and hand the function to
  34. # the interpreter.
  35. pass
  36. # Create a new stack frame.
  37. frame_link, new_phase, new_frame, new_evalstack, new_symbols, \
  38. new_returnvalue, intrinsic_return = \
  39. yield [("RDE", [user_root, "frame"]),
  40. ("CNV", ["init"]),
  41. ("CN", []),
  42. ("CN", []),
  43. ("CN", []),
  44. ("CN", []),
  45. ("CN", [])
  46. ]
  47. _, _, _, _, _, _, _, _, _, _ = \
  48. yield [("CD", [user_root, "frame", new_frame]),
  49. ("CD", [new_frame, "evalstack", new_evalstack]),
  50. ("CD", [new_frame, "symbols", new_symbols]),
  51. ("CD", [new_frame, "returnvalue", new_returnvalue]),
  52. ("CD", [new_frame, "caller", inst]),
  53. ("CD", [new_frame, "phase", new_phase]),
  54. ("CD", [new_frame, "IP", body_id]),
  55. ("CD", [new_frame, "prev", user_frame]),
  56. ("CD", [
  57. new_frame,
  58. primitive_functions.PRIMITIVE_RETURN_KEY,
  59. intrinsic_return]),
  60. ("DE", [frame_link])
  61. ]
  62. # Put the parameters in the new stack frame's symbol table.
  63. try:
  64. gen = kernel.jit.jit_parameters(body_id)
  65. inp = None
  66. while 1:
  67. inp = yield gen.send(inp)
  68. except primitive_functions.PrimitiveFinished as ex:
  69. parameter_vars, parameter_names = ex.result
  70. parameter_dict = dict(zip(parameter_names, parameter_vars))
  71. for (key, value) in named_arguments.items():
  72. param_var = parameter_dict[key]
  73. variable, = yield [("CN", [])]
  74. yield [("CD", [variable, "value", value])]
  75. symbol_edge, = yield [("CE", [new_symbols, variable])]
  76. yield [("CE", [symbol_edge, param_var])]
  77. username = kwargs['username']
  78. while 1:
  79. try:
  80. gen = kernel.execute_rule(username)
  81. inp = None
  82. while 1:
  83. inp = yield gen.send(inp)
  84. except StopIteration:
  85. # An instruction has been completed. Forward it.
  86. yield None
  87. # Let primitive_functions.PrimitiveFinished bubble up.