move resolve_method code from word to mom

rather make resolve an instruction.
Since it was coded in risc anyway, we not only save the setup and call
But also makes the mom instruction flow clearer
The method really came from not wanting to code it in risc, but with
the Builder, that is now surprisingly painless
This commit is contained in:
Torsten Ruger 2018-04-08 18:55:17 +03:00
parent 8c322329fb
commit 33ffcf1d88
8 changed files with 84 additions and 28 deletions

View File

@ -32,6 +32,7 @@ require_relative "check"
require_relative "basic_values" require_relative "basic_values"
require_relative "simple_call" require_relative "simple_call"
require_relative "dynamic_call" require_relative "dynamic_call"
require_relative "resolve_method"
require_relative "truth_check" require_relative "truth_check"
require_relative "not_same_check" require_relative "not_same_check"
require_relative "jump" require_relative "jump"

View File

@ -27,17 +27,17 @@ module Mom
# Move method name, frame and arguemnt types from the method to the next_message # Move method name, frame and arguemnt types from the method to the next_message
# Get the message from Space and link it. # Get the message from Space and link it.
def to_risc(compiler) def to_risc(compiler)
build_with(compiler.builder) build_with(compiler.builder(false))
end end
# directly called by to_risc # directly called by to_risc
# but also used directly in __init # but also used directly in __init
def build_with(builder) def build_with(builder)
from = method_source from = method_source
risc = builder.build_and_return { typed_method << from } builder.build { typed_method << from }
risc << build_message_data(builder) build_message_data(builder)
builder.compiler.reset_regs builder.compiler.reset_regs
return risc return builder.built
end end
private private
@ -49,7 +49,7 @@ module Mom
# also put it into next_message of current message (and reverse) # also put it into next_message of current message (and reverse)
# set name and type data in the message, from the method loaded # set name and type data in the message, from the method loaded
def build_message_data( builder ) def build_message_data( builder )
builder.build_and_return do builder.build do
space << Parfait.object_space space << Parfait.object_space
next_message << space[:first_message] next_message << space[:first_message]
message[:next_message] << next_message message[:next_message] << next_message

View File

@ -0,0 +1,67 @@
module Mom
# Dynamic method resolution is at the heart of a dynamic language, and here
# is the Mom level instruction to do it.
#
# When the static type can not be determined a CacheEntry is used to store
# type and method of the resolved method. The CacheEntry is shared with
# DynamicCall instruction who is responsible for calling the method in the entry.
#
# This instruction resolves the method, in case the types don't match (and
# at least on first encouter)
#
# This used to be a method, but we don't really need the method setup etc
#
class ResolveMethod < Instruction
attr :cache_entry , :name
def initialize(name , cache_entry)
@name = name
@cache_entry = cache_entry
end
# resolve the method name of self, on the given object
# may seem wrong way around at first sight, but we know the type of string. And
# thus resolving this method happens at compile time, whereas any method on an
# unknown self (the object given) needs resolving and that is just what we are doing
# ( ie the snake bites it's tail)
# This method is just a placeholder until boot is over and the real method is
# parsed.
def to_risc( compiler )
name = @name
cache_entry = @cache_entry
return Risc.label("hi" , "there")
builder = compiler.builder(false)
builder.build do
word << name
type << cache_entry
type << type[:cached_type]
typed_method << type[:methods]
add while_start_label
space << Parfait.object_space
space << space[:nil_object]
space - typed_method
if_zero exit_label
name << typed_method[:name]
name - word
if_not_zero false_label
message[:return_value] << typed_method
add Mom::ReturnSequence.new.to_risc(compiler)
add false_label
typed_method << typed_method[:next_method]
branch while_start_label
add exit_label
end
Risc::Builtin::Object.emit_syscall( builder , :exit )
return builder.built
end
end
end

View File

@ -176,7 +176,7 @@ module Risc
end end
obj = space.get_class_by_name(:Word) obj = space.get_class_by_name(:Word)
[:putstring , :get_internal_byte , :set_internal_byte , :resolve_method].each do |f| [:putstring , :get_internal_byte , :set_internal_byte ].each do |f|
obj.instance_type.add_method Builtin::Word.send(f , nil) obj.instance_type.add_method Builtin::Word.send(f , nil)
end end

View File

@ -94,8 +94,8 @@ module Vool
def cache_check(in_method) def cache_check(in_method)
ok = Mom::Label.new("cache_ok_#{self.object_id}") ok = Mom::Label.new("cache_ok_#{self.object_id}")
check = build_condition(ok) # if cached_type != current_type check = build_condition(ok) # if cached_type != current_type
check << build_type_cache_update # cached_type = current_type check << Mom::SlotLoad.new([dynamic_call.cache_entry, :cached_type] , [:message , :receiver , :type])
check << build_method_cache_update(in_method)# cached_method = current_type.resolve_method(method.name) check << Mom::ResolveMethod.new( @name , dynamic_call.cache_entry )
check << ok check << ok
end end
@ -111,14 +111,5 @@ module Vool
current_type = Mom::SlotDefinition.new(:message , [:receiver , :type]) current_type = Mom::SlotDefinition.new(:message , [:receiver , :type])
Mom::NotSameCheck.new(cached_type , current_type, ok_label) Mom::NotSameCheck.new(cached_type , current_type, ok_label)
end end
def build_type_cache_update
Mom::SlotLoad.new([dynamic_call.cache_entry, :cached_type] , [:message , :receiver , :type])
end
def build_method_cache_update(in_method)
receiver = SymbolConstant.new(@name)
resolve = SendStatement.new(:resolve_method , receiver , [@receiver])
move_method = Mom::SlotLoad.new([dynamic_call.cache_entry, :cached_method] , [:message , :return_value])
resolve.to_mom(in_method) << move_method
end
end end
end end

View File

@ -24,7 +24,7 @@ class TestSpace < MiniTest::Test
end end
def test_methods_booted def test_methods_booted
word = @space.get_class_by_name(:Word).instance_type word = @space.get_class_by_name(:Word).instance_type
assert_equal 4 , word.method_names.get_length assert_equal 3 , word.method_names.get_length
assert word.get_method(:putstring) , "no putstring" assert word.get_method(:putstring) , "no putstring"
end end

View File

@ -29,13 +29,10 @@ module Risc
IsZero, SlotToReg, OperatorInstruction, IsNotZero, Label, IsZero, SlotToReg, OperatorInstruction, IsNotZero, Label,
SlotToReg, Branch, Label, LoadConstant, SlotToReg, SlotToReg, Branch, Label, LoadConstant, SlotToReg,
OperatorInstruction, IsZero, SlotToReg, OperatorInstruction, IsNotZero, OperatorInstruction, IsZero, SlotToReg, OperatorInstruction, IsNotZero,
Label, SlotToReg, Branch, Label, LoadConstant, RegToSlot, SlotToReg, SlotToReg, RegToSlot, SlotToReg,
SlotToReg, OperatorInstruction, IsZero, SlotToReg, OperatorInstruction, SlotToReg, FunctionReturn, SlotToReg, LoadConstant, RegToSlot,
IsNotZero, Label, SlotToReg, Branch, Label, Label, LoadConstant, LoadConstant, SlotToReg, RegToSlot,
LoadConstant, SlotToReg, OperatorInstruction, IsZero, SlotToReg, RegToSlot, SlotToReg, SlotToReg]
OperatorInstruction, IsNotZero, Label, SlotToReg, Branch,
Label, LoadConstant, SlotToReg, OperatorInstruction, IsZero,
Label, Transfer, Syscall, NilClass]
#assert_equal 1 , get_return #assert_equal 1 , get_return
end end

View File

@ -19,15 +19,15 @@ module Vool
assert_equal :type , load.right.slots[1] , load assert_equal :type , load.right.slots[1] , load
end end
def test_check_resolve_call def test_check_resolve_call
assert_equal SimpleCall , @ins.next(5).class , @ins assert_equal ResolveMethod , @ins.next(3).class , @ins
end end
def test_dynamic_call_last def test_dynamic_call_last
assert_equal DynamicCall , @ins.last.class , @ins assert_equal DynamicCall , @ins.last.class , @ins
end end
def test_array def test_array
check_array [SlotLoad, NotSameCheck, SlotLoad, MessageSetup, ArgumentTransfer, SimpleCall , check_array [SlotLoad, NotSameCheck, SlotLoad, ResolveMethod, Label, MessageSetup ,
SlotLoad, Label, MessageSetup, ArgumentTransfer, DynamicCall] , @ins ArgumentTransfer, DynamicCall] , @ins
end end
end end