RJIT: Limit the number of versions per block
This commit is contained in:
parent
3bacc3877a
commit
d876c008ec
@ -34,6 +34,10 @@ module RubyVM::RJIT
|
|||||||
# Mark objects in this Array during GC
|
# Mark objects in this Array during GC
|
||||||
GC_REFS = []
|
GC_REFS = []
|
||||||
|
|
||||||
|
# Maximum number of versions per block
|
||||||
|
# 1 means always create generic versions
|
||||||
|
MAX_VERSIONS = 4
|
||||||
|
|
||||||
class Compiler
|
class Compiler
|
||||||
attr_accessor :write_pos
|
attr_accessor :write_pos
|
||||||
|
|
||||||
@ -277,6 +281,7 @@ module RubyVM::RJIT
|
|||||||
# @param asm [RubyVM::RJIT::Assembler]
|
# @param asm [RubyVM::RJIT::Assembler]
|
||||||
def compile_block(asm, jit:, pc:, ctx: Context.new)
|
def compile_block(asm, jit:, pc:, ctx: Context.new)
|
||||||
# Mark the block start address and prepare an exit code storage
|
# Mark the block start address and prepare an exit code storage
|
||||||
|
ctx = limit_block_versions(jit.iseq, pc, ctx)
|
||||||
block = Block.new(iseq: jit.iseq, pc:, ctx: ctx.dup)
|
block = Block.new(iseq: jit.iseq, pc:, ctx: ctx.dup)
|
||||||
jit.block = block
|
jit.block = block
|
||||||
asm.block(block)
|
asm.block(block)
|
||||||
@ -346,6 +351,32 @@ module RubyVM::RJIT
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Produce a generic context when the block version limit is hit for the block
|
||||||
|
def limit_block_versions(iseq, pc, ctx)
|
||||||
|
# Guard chains implement limits separately, do nothing
|
||||||
|
if ctx.chain_depth > 0
|
||||||
|
return ctx.dup
|
||||||
|
end
|
||||||
|
|
||||||
|
# If this block version we're about to add will hit the version limit
|
||||||
|
if list_blocks(iseq, pc).size + 1 >= MAX_VERSIONS
|
||||||
|
# Produce a generic context that stores no type information,
|
||||||
|
# but still respects the stack_size and sp_offset constraints.
|
||||||
|
# This new context will then match all future requests.
|
||||||
|
generic_ctx = Context.new
|
||||||
|
generic_ctx.stack_size = ctx.stack_size
|
||||||
|
generic_ctx.sp_offset = ctx.sp_offset
|
||||||
|
|
||||||
|
if ctx.diff(generic_ctx) == TypeDiff::Incompatible
|
||||||
|
raise 'should substitute a compatible context'
|
||||||
|
end
|
||||||
|
|
||||||
|
return generic_ctx
|
||||||
|
end
|
||||||
|
|
||||||
|
return ctx.dup
|
||||||
|
end
|
||||||
|
|
||||||
def list_blocks(iseq, pc)
|
def list_blocks(iseq, pc)
|
||||||
rjit_blocks(iseq)[pc]
|
rjit_blocks(iseq)[pc]
|
||||||
end
|
end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user