starting to redo message_setup
apart from previous commits bug, it also needs to deal with dynamic/static correctly and while at it will do the getting from space
This commit is contained in:
parent
ec31bde33a
commit
f4ce6d6253
@ -4,34 +4,58 @@ module Mom
|
|||||||
# Ie: MessageSetup,ArgumentTransfer,SimpleCall
|
# Ie: MessageSetup,ArgumentTransfer,SimpleCall
|
||||||
#
|
#
|
||||||
# MessageSetup does Setup before a call can be made, acquiring and filling the message
|
# MessageSetup does Setup before a call can be made, acquiring and filling the message
|
||||||
# basically.
|
# basically.Only after MessageSetup is the next_message safe to use.
|
||||||
#
|
#
|
||||||
# With the current design the next message is already ready (hardwired as a linked list),
|
# The space keeps a linked list of Messages, from which we take and currenty also return.
|
||||||
# so nothing to be done there.
|
|
||||||
# (but this does not account for continuations or closures and so will have to be changed)
|
|
||||||
#
|
#
|
||||||
# But we do need to set the message name to the called method's name,
|
# Message setup set the name to the called method's name, and also set the arg and local
|
||||||
# and also set the arg and local types on the new message, currently for debugging
|
# types on the new message, currently for debugging but later for dynamic checking
|
||||||
# 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
|
||||||
#
|
#
|
||||||
class MessageSetup < Instruction
|
class MessageSetup < Instruction
|
||||||
attr_reader :method
|
attr_reader :method_source
|
||||||
|
|
||||||
def initialize(method)
|
def initialize(method_source)
|
||||||
@method = method
|
@method_source = method_source
|
||||||
end
|
end
|
||||||
|
|
||||||
# Move method name, frame and arguemnt types from the method to the neext_message
|
# Move method name, frame and arguemnt types from the method to the next_message
|
||||||
# Assumes the message is ready, see class description
|
# Get the message from Space and link it.
|
||||||
def to_risc(compiler)
|
def to_risc(compiler)
|
||||||
name_move = SlotLoad.new( [:message , :next_message,:name] , [method , :name],self)
|
method = compiler.use_reg( :TypedMethod )
|
||||||
|
risc = move_method_to(compiler , method)
|
||||||
|
message = compiler.use_reg( :Message )
|
||||||
|
risc << get_message_to(compiler , message)
|
||||||
|
|
||||||
|
# move name args frame
|
||||||
|
# this time using Risc instructions (create helpers?)
|
||||||
|
name_move = SlotLoad.new( [:message , :next_message,:name] , [method_source , :name],self)
|
||||||
moves = name_move.to_risc(compiler)
|
moves = name_move.to_risc(compiler)
|
||||||
args_move = SlotLoad.new( [:message , :next_message, :arguments,:type] , [method , :arguments, :type],self)
|
args_move = SlotLoad.new( [:message , :next_message, :arguments, :type] , [method_source , :arguments_type],self)
|
||||||
moves << args_move.to_risc(compiler)
|
moves << args_move.to_risc(compiler)
|
||||||
type_move = SlotLoad.new( [:message , :next_message, :frame,:type] , [method , :frame,:type],self)
|
type_move = SlotLoad.new( [:message , :next_message, :frame, :type] , [method_source , :frame_type],self)
|
||||||
moves << type_move.to_risc(compiler)
|
moves << type_move.to_risc(compiler)
|
||||||
|
return risc
|
||||||
|
end
|
||||||
|
private
|
||||||
|
# get the method from method_source into the given register
|
||||||
|
# return instruction that do this
|
||||||
|
def move_method_to(compiler, register)
|
||||||
|
Risc.load_constant("message setup move method" , @method_source ,register)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# get the next message from space and unlink it there
|
||||||
|
# also put it into next_message of current message
|
||||||
|
# use given message regster
|
||||||
|
# return instructions to do this
|
||||||
|
def get_message_to( compiler , message)
|
||||||
|
Risc.load_constant("message setup move method" , @method_source ,message)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@ -63,8 +63,8 @@ module Vool
|
|||||||
Mom::SlotDefinition.new(:message ,[ :return_value])
|
Mom::SlotDefinition.new(:message ,[ :return_value])
|
||||||
end
|
end
|
||||||
|
|
||||||
def message_setup(in_method)
|
def message_setup(in_method,called_method)
|
||||||
setup = Mom::MessageSetup.new(in_method)
|
setup = Mom::MessageSetup.new( called_method )
|
||||||
mom_receive = @receiver.slot_definition(in_method)
|
mom_receive = @receiver.slot_definition(in_method)
|
||||||
arg_target = [:message , :next_message , :arguments]
|
arg_target = [:message , :next_message , :arguments]
|
||||||
args = []
|
args = []
|
||||||
@ -78,7 +78,7 @@ module Vool
|
|||||||
type = @receiver.ct_type
|
type = @receiver.ct_type
|
||||||
called_method = type.resolve_method(@name)
|
called_method = type.resolve_method(@name)
|
||||||
raise "No method #{@name} for #{type}" unless called_method
|
raise "No method #{@name} for #{type}" unless called_method
|
||||||
message_setup(in_method) << Mom::SimpleCall.new( called_method)
|
message_setup(in_method,called_method) << Mom::SimpleCall.new(called_method)
|
||||||
end
|
end
|
||||||
|
|
||||||
# this breaks cleanly into two parts:
|
# this breaks cleanly into two parts:
|
||||||
@ -92,20 +92,17 @@ module Vool
|
|||||||
# if not, change and find method for the type (simple_call to resolve_method)
|
# if not, change and find method for the type (simple_call to resolve_method)
|
||||||
# conceptually easy in ruby, but we have to compile that "easy" ruby
|
# conceptually easy in ruby, but we have to compile that "easy" ruby
|
||||||
def cache_check(in_method)
|
def cache_check(in_method)
|
||||||
# if cached_type != current_type
|
|
||||||
# cached_type = current_type
|
|
||||||
# cached_method = current_type.resolve_method(method.name)
|
|
||||||
ok = Mom::Label.new("cache_ok_#{self.object_id}")
|
ok = Mom::Label.new("cache_ok_#{self.object_id}")
|
||||||
check = build_condition(ok)
|
check = build_condition(ok) # if cached_type != current_type
|
||||||
check << build_type_cache_update
|
check << build_type_cache_update # cached_type = current_type
|
||||||
check << build_method_cache_update(in_method)
|
check << build_method_cache_update(in_method)# cached_method = current_type.resolve_method(method.name)
|
||||||
check << ok
|
check << ok
|
||||||
end
|
end
|
||||||
|
|
||||||
# this may look like a simple_call, but the difference is that we don't know
|
# to call the method (that we know now to be in the cache), we move the method
|
||||||
# the method until run-time. Alas the setup is the same
|
# to reg1, do the setup (very similar to static) and call
|
||||||
def call_cached_method(in_method)
|
def call_cached_method(in_method)
|
||||||
message_setup(in_method) << dynamic_call
|
message_setup(in_method,dynamic_call.cache_entry) << dynamic_call
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
Loading…
Reference in New Issue
Block a user