RJIT: Implement checkkeyword
This commit is contained in:
parent
67dd52d59c
commit
9f8e914943
@ -18,7 +18,7 @@ module RubyVM::RJIT
|
|||||||
asm.incr_counter(:rjit_insns_count)
|
asm.incr_counter(:rjit_insns_count)
|
||||||
asm.comment("Insn: #{insn.name}")
|
asm.comment("Insn: #{insn.name}")
|
||||||
|
|
||||||
# 77/102
|
# 78/102
|
||||||
case insn.name
|
case insn.name
|
||||||
when :nop then nop(jit, ctx, asm)
|
when :nop then nop(jit, ctx, asm)
|
||||||
when :getlocal then getlocal(jit, ctx, asm)
|
when :getlocal then getlocal(jit, ctx, asm)
|
||||||
@ -66,7 +66,7 @@ module RubyVM::RJIT
|
|||||||
when :defined then defined(jit, ctx, asm)
|
when :defined then defined(jit, ctx, asm)
|
||||||
when :definedivar then definedivar(jit, ctx, asm)
|
when :definedivar then definedivar(jit, ctx, asm)
|
||||||
# checkmatch
|
# checkmatch
|
||||||
# checkkeyword
|
when :checkkeyword then checkkeyword(jit, ctx, asm)
|
||||||
# checktype
|
# checktype
|
||||||
# defineclass
|
# defineclass
|
||||||
# definemethod
|
# definemethod
|
||||||
@ -1154,7 +1154,43 @@ module RubyVM::RJIT
|
|||||||
end
|
end
|
||||||
|
|
||||||
# checkmatch
|
# checkmatch
|
||||||
# checkkeyword
|
|
||||||
|
def checkkeyword(jit, ctx, asm)
|
||||||
|
# When a keyword is unspecified past index 32, a hash will be used
|
||||||
|
# instead. This can only happen in iseqs taking more than 32 keywords.
|
||||||
|
if jit.iseq.body.param.keyword.num >= 32
|
||||||
|
return CantCompile
|
||||||
|
end
|
||||||
|
|
||||||
|
# The EP offset to the undefined bits local
|
||||||
|
bits_offset = jit.operand(0)
|
||||||
|
|
||||||
|
# The index of the keyword we want to check
|
||||||
|
index = jit.operand(1, signed: true)
|
||||||
|
|
||||||
|
# Load environment pointer EP
|
||||||
|
ep_reg = :rax
|
||||||
|
jit_get_ep(asm, 0, reg: ep_reg)
|
||||||
|
|
||||||
|
# VALUE kw_bits = *(ep - bits)
|
||||||
|
bits_opnd = [ep_reg, C.VALUE.size * -bits_offset]
|
||||||
|
|
||||||
|
# unsigned int b = (unsigned int)FIX2ULONG(kw_bits);
|
||||||
|
# if ((b & (0x01 << idx))) {
|
||||||
|
#
|
||||||
|
# We can skip the FIX2ULONG conversion by shifting the bit we test
|
||||||
|
bit_test = 0x01 << (index + 1)
|
||||||
|
asm.test(bits_opnd, bit_test)
|
||||||
|
asm.mov(:rax, Qfalse)
|
||||||
|
asm.mov(:rcx, Qtrue)
|
||||||
|
asm.cmovz(:rax, :rcx)
|
||||||
|
|
||||||
|
stack_ret = ctx.stack_push
|
||||||
|
asm.mov(stack_ret, :rax)
|
||||||
|
|
||||||
|
KeepCompiling
|
||||||
|
end
|
||||||
|
|
||||||
# checktype
|
# checktype
|
||||||
# defineclass
|
# defineclass
|
||||||
# definemethod
|
# definemethod
|
||||||
|
16
rjit_c.rb
16
rjit_c.rb
@ -1001,6 +1001,18 @@ module RubyVM::RJIT # :nodoc: all
|
|||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def C.rb_iseq_param_keyword
|
||||||
|
@rb_iseq_param_keyword ||= CType::Struct.new(
|
||||||
|
"rb_iseq_param_keyword", Primitive.cexpr!("SIZEOF(struct rb_iseq_param_keyword)"),
|
||||||
|
num: [CType::Immediate.parse("int"), Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_param_keyword *)NULL)), num)")],
|
||||||
|
required_num: [CType::Immediate.parse("int"), Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_param_keyword *)NULL)), required_num)")],
|
||||||
|
bits_start: [CType::Immediate.parse("int"), Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_param_keyword *)NULL)), bits_start)")],
|
||||||
|
rest_start: [CType::Immediate.parse("int"), Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_param_keyword *)NULL)), rest_start)")],
|
||||||
|
table: [CType::Pointer.new { self.ID }, Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_param_keyword *)NULL)), table)")],
|
||||||
|
default_values: [CType::Pointer.new { self.VALUE }, Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_param_keyword *)NULL)), default_values)")],
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
def C.rb_iseq_struct
|
def C.rb_iseq_struct
|
||||||
@rb_iseq_struct ||= CType::Struct.new(
|
@rb_iseq_struct ||= CType::Struct.new(
|
||||||
"rb_iseq_struct", Primitive.cexpr!("SIZEOF(struct rb_iseq_struct)"),
|
"rb_iseq_struct", Primitive.cexpr!("SIZEOF(struct rb_iseq_struct)"),
|
||||||
@ -1354,10 +1366,6 @@ module RubyVM::RJIT # :nodoc: all
|
|||||||
CType::Stub.new(:rb_iseq_type)
|
CType::Stub.new(:rb_iseq_type)
|
||||||
end
|
end
|
||||||
|
|
||||||
def C.rb_iseq_param_keyword
|
|
||||||
CType::Stub.new(:rb_iseq_param_keyword)
|
|
||||||
end
|
|
||||||
|
|
||||||
def C.iseq_insn_info
|
def C.iseq_insn_info
|
||||||
CType::Stub.new(:iseq_insn_info)
|
CType::Stub.new(:iseq_insn_info)
|
||||||
end
|
end
|
||||||
|
@ -156,8 +156,8 @@ class BindingGenerator
|
|||||||
println
|
println
|
||||||
end
|
end
|
||||||
|
|
||||||
# TODO: Support nested declarations
|
# Build a hash table for type lookup by name
|
||||||
nodes_index = nodes.group_by(&:spelling).transform_values do |values|
|
nodes_index = flatten_nodes(nodes).group_by(&:spelling).transform_values do |values|
|
||||||
# Try to search a declaration with definitions
|
# Try to search a declaration with definitions
|
||||||
node_with_children = values.find { |v| !v.children.empty? }
|
node_with_children = values.find { |v| !v.children.empty? }
|
||||||
next node_with_children if node_with_children
|
next node_with_children if node_with_children
|
||||||
@ -169,7 +169,7 @@ class BindingGenerator
|
|||||||
# Define types
|
# Define types
|
||||||
@types.each do |type|
|
@types.each do |type|
|
||||||
unless definition = generate_node(nodes_index[type])
|
unless definition = generate_node(nodes_index[type])
|
||||||
raise "Failed to generate type: #{type}"
|
raise "Failed to find or generate type: #{type}"
|
||||||
end
|
end
|
||||||
println " def C.#{type}"
|
println " def C.#{type}"
|
||||||
println "@#{type} ||= #{definition}".gsub(/^/, " ").chomp
|
println "@#{type} ||= #{definition}".gsub(/^/, " ").chomp
|
||||||
@ -201,6 +201,18 @@ class BindingGenerator
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
# Make an array that includes all top-level and nested nodes
|
||||||
|
def flatten_nodes(nodes)
|
||||||
|
result = []
|
||||||
|
nodes.each do |node|
|
||||||
|
unless node.children.empty?
|
||||||
|
result.concat(flatten_nodes(node.children))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
result.concat(nodes) # prioritize top-level nodes
|
||||||
|
result
|
||||||
|
end
|
||||||
|
|
||||||
# Return code before BINDGEN_BEG and code after BINDGEN_END
|
# Return code before BINDGEN_BEG and code after BINDGEN_END
|
||||||
def split_ambles(src_path)
|
def split_ambles(src_path)
|
||||||
lines = File.read(src_path).lines
|
lines = File.read(src_path).lines
|
||||||
@ -573,6 +585,7 @@ generator = BindingGenerator.new(
|
|||||||
rb_shape_t
|
rb_shape_t
|
||||||
rb_thread_struct
|
rb_thread_struct
|
||||||
rb_jit_func_t
|
rb_jit_func_t
|
||||||
|
rb_iseq_param_keyword
|
||||||
rjit_options
|
rjit_options
|
||||||
],
|
],
|
||||||
# #ifdef-dependent immediate types, which need Primitive.cexpr! for type detection
|
# #ifdef-dependent immediate types, which need Primitive.cexpr! for type detection
|
||||||
|
Loading…
x
Reference in New Issue
Block a user