2017-09-11 14:22:33 +03:00
|
|
|
module Mom
|
|
|
|
|
2018-03-21 12:20:55 +05:30
|
|
|
# As reminder: a statically resolved call (the simplest one) becomes three Mom Instructions.
|
|
|
|
# Ie: MessageSetup,ArgumentTransfer,SimpleCall
|
2017-09-11 14:22:33 +03:00
|
|
|
#
|
2018-03-21 12:20:55 +05:30
|
|
|
# MessageSetup does Setup before a call can be made, acquiring and filling the message
|
2018-11-14 12:41:13 +02:00
|
|
|
# basically. Only after MessageSetup is the next_message safe to use.
|
2017-09-11 14:22:33 +03:00
|
|
|
#
|
2018-11-14 12:41:13 +02:00
|
|
|
# The Factory (instane kept by Space) keeps a linked list of Messages,
|
|
|
|
# from which we take and currenty also return.
|
2018-03-21 12:20:55 +05:30
|
|
|
#
|
2018-04-05 12:24:49 +03:00
|
|
|
# Message setup set the name to the called method's name, and also set the arg and local
|
|
|
|
# types on the new message, currently for debugging but later for dynamic checking
|
|
|
|
#
|
|
|
|
# The only difference between the setup of a static call and a dynamic one is where
|
|
|
|
# the method comes from. A static, or simple call, passes the method, but a dynamic
|
|
|
|
# call passes the cache_entry that holds the resolved method.
|
|
|
|
#
|
|
|
|
# In either case, the method is loaded and name,frame and args set
|
2017-09-11 14:22:33 +03:00
|
|
|
#
|
|
|
|
class MessageSetup < Instruction
|
2018-04-05 12:24:49 +03:00
|
|
|
attr_reader :method_source
|
2017-09-11 14:22:33 +03:00
|
|
|
|
2018-04-05 12:24:49 +03:00
|
|
|
def initialize(method_source)
|
2019-08-13 00:13:29 +03:00
|
|
|
raise "no nil" unless method_source
|
2018-04-05 12:24:49 +03:00
|
|
|
@method_source = method_source
|
2017-09-11 14:22:33 +03:00
|
|
|
end
|
2018-03-13 16:16:06 +05:30
|
|
|
|
2018-04-05 12:24:49 +03:00
|
|
|
# Move method name, frame and arguemnt types from the method to the next_message
|
|
|
|
# Get the message from Space and link it.
|
2018-03-13 16:16:06 +05:30
|
|
|
def to_risc(compiler)
|
2018-08-19 13:18:25 +03:00
|
|
|
build_with(compiler.builder(self))
|
2018-04-07 00:14:02 +03:00
|
|
|
end
|
|
|
|
|
|
|
|
# directly called by to_risc
|
|
|
|
# but also used directly in __init
|
|
|
|
def build_with(builder)
|
2018-04-08 23:45:23 +03:00
|
|
|
case from = method_source
|
2018-07-07 09:11:09 +03:00
|
|
|
when Parfait::CallableMethod
|
2018-08-14 19:39:46 +03:00
|
|
|
builder.build { callable! << from }
|
2018-04-08 23:45:23 +03:00
|
|
|
when Parfait::CacheEntry
|
|
|
|
builder.build do
|
2018-08-14 19:39:46 +03:00
|
|
|
cache_entry! << from
|
|
|
|
callable! << cache_entry[:cached_method]
|
2018-04-08 23:45:23 +03:00
|
|
|
end
|
2018-07-24 11:35:49 +03:00
|
|
|
when Integer
|
|
|
|
builder.build do
|
2018-08-14 19:39:46 +03:00
|
|
|
arguments! << message[:arguments]
|
|
|
|
callable! << arguments[ from ]
|
2018-07-24 11:35:49 +03:00
|
|
|
end
|
2018-04-08 23:45:23 +03:00
|
|
|
else
|
2018-07-24 11:35:49 +03:00
|
|
|
raise "unknown source #{method_source.class}:#{method_source}"
|
2018-04-08 23:45:23 +03:00
|
|
|
end
|
2018-04-08 18:55:17 +03:00
|
|
|
build_message_data(builder)
|
|
|
|
return builder.built
|
2018-04-05 12:24:49 +03:00
|
|
|
end
|
2018-04-07 00:14:02 +03:00
|
|
|
|
2018-04-05 12:24:49 +03:00
|
|
|
private
|
2018-04-05 20:10:00 +03:00
|
|
|
def source
|
|
|
|
"method setup "
|
|
|
|
end
|
|
|
|
|
2018-04-05 12:24:49 +03:00
|
|
|
# get the next message from space and unlink it there
|
2018-04-06 22:54:54 +03:00
|
|
|
# also put it into next_message of current message (and reverse)
|
2018-08-12 14:47:05 +03:00
|
|
|
# set the method into the message
|
2018-04-06 22:40:58 +03:00
|
|
|
def build_message_data( builder )
|
2018-04-08 18:55:17 +03:00
|
|
|
builder.build do
|
2018-09-01 11:28:53 +03:00
|
|
|
factory? << Parfait.object_space.get_factory_for(:Message)
|
|
|
|
next_message? << factory[:next_object]
|
2018-04-06 22:40:58 +03:00
|
|
|
|
2018-08-12 14:47:05 +03:00
|
|
|
#FIXME in a multithreaded future this should be done using lock free compare and swap.
|
2018-08-14 19:39:46 +03:00
|
|
|
next_message_reg! << next_message[:next_message]
|
2018-09-01 11:28:53 +03:00
|
|
|
factory[:next_object] << next_message_reg
|
2018-04-06 22:40:58 +03:00
|
|
|
|
2018-11-21 11:12:39 +02:00
|
|
|
# FIXME: Also we relink used messages at the moment. This will have to stop
|
|
|
|
# when implementing continuations (or block passing/bindings)
|
|
|
|
# then we may run out and that means cheking and maybe getting more
|
2018-08-12 14:47:05 +03:00
|
|
|
message[:next_message] << next_message
|
|
|
|
next_message[:caller] << message
|
2018-07-27 10:46:22 +03:00
|
|
|
next_message[:method] << callable
|
2018-04-06 22:40:58 +03:00
|
|
|
|
2018-04-06 14:21:38 +03:00
|
|
|
end
|
2018-04-06 16:08:35 +03:00
|
|
|
end
|
2017-09-11 14:22:33 +03:00
|
|
|
end
|
|
|
|
end
|