Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 80de9c9

Browse files
committed
Specialize using the linked list
1 parent 69d2dfa commit 80de9c9

File tree

2 files changed

+67
-77
lines changed

2 files changed

+67
-77
lines changed

lib/syntax_tree/yarv/compiler.rb

Lines changed: 2 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -608,33 +608,6 @@ def visit_call(node)
608608
)
609609
end
610610

611-
arg_parts = argument_parts(node.arguments)
612-
argc = arg_parts.length
613-
614-
# First we're going to check if we're calling a method on an array
615-
# literal without any arguments. In that case there are some
616-
# specializations we might be able to perform.
617-
if argc == 0 && (node.message.is_a?(Ident) || node.message.is_a?(Op))
618-
case node.receiver
619-
when ArrayLiteral
620-
parts = node.receiver.contents&.parts || []
621-
622-
if parts.none? { |part| part.is_a?(ArgStar) } &&
623-
RubyVisitor.compile(node.receiver).nil?
624-
case node.message.value
625-
when "max"
626-
visit(node.receiver.contents)
627-
iseq.opt_newarray_max(parts.length)
628-
return
629-
when "min"
630-
visit(node.receiver.contents)
631-
iseq.opt_newarray_min(parts.length)
632-
return
633-
end
634-
end
635-
end
636-
end
637-
638611
# Track whether or not this is a method call on a block proxy receiver.
639612
# If it is, we can potentially do tailcall optimizations on it.
640613
block_receiver = false
@@ -663,6 +636,8 @@ def visit_call(node)
663636
iseq.branchnil(after_call_label)
664637
end
665638

639+
arg_parts = argument_parts(node.arguments)
640+
argc = arg_parts.length
666641
flag = 0
667642

668643
arg_parts.each do |arg_part|

lib/syntax_tree/yarv/instruction_sequence.rb

Lines changed: 65 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -190,14 +190,16 @@ def inline_storage_for(name)
190190
end
191191

192192
def length
193-
insns.each.inject(0) do |sum, insn|
194-
case insn
195-
when Integer, Label, Symbol
196-
sum
197-
else
198-
sum + insn.length
193+
insns
194+
.each
195+
.inject(0) do |sum, insn|
196+
case insn
197+
when Integer, Label, Symbol
198+
sum
199+
else
200+
sum + insn.length
201+
end
199202
end
200-
end
201203
end
202204

203205
def eval
@@ -218,29 +220,32 @@ def to_a
218220
specialize_instructions! if options.specialized_instruction?
219221

220222
# Next, set it up so that all of the labels get their correct name.
221-
insns.each.inject(0) do |length, insn|
222-
case insn
223-
when Integer, Symbol
224-
length
225-
when Label
226-
insn.patch!(:"label_#{length}")
227-
length
228-
else
229-
length + insn.length
223+
insns
224+
.each
225+
.inject(0) do |length, insn|
226+
case insn
227+
when Integer, Symbol
228+
length
229+
when Label
230+
insn.patch!(:"label_#{length}")
231+
length
232+
else
233+
length + insn.length
234+
end
230235
end
231-
end
232236

233237
# Next, dump all of the instructions into a flat list.
234-
dumped = insns.each.map do |insn|
235-
case insn
236-
when Integer, Symbol
237-
insn
238-
when Label
239-
insn.name
240-
else
241-
insn.to_a(self)
238+
dumped =
239+
insns.each.map do |insn|
240+
case insn
241+
when Integer, Symbol
242+
insn
243+
when Label
244+
insn.name
245+
else
246+
insn.to_a(self)
247+
end
242248
end
243-
end
244249

245250
dumped_options = argument_options.dup
246251
dumped_options[:opt].map!(&:name) if dumped_options[:opt]
@@ -271,29 +276,55 @@ def to_a
271276
def specialize_instructions!
272277
insns.each_node do |node|
273278
case node.instruction
279+
when NewArray
280+
next unless node.next_node
281+
282+
next_node = node.next_node
283+
next unless next_node.instruction.is_a?(Send)
284+
next if next_node.instruction.block_iseq
285+
286+
calldata = next_node.instruction.calldata
287+
next unless calldata.flags == CallData::CALL_ARGS_SIMPLE
288+
next unless calldata.argc == 0
289+
290+
case calldata.method
291+
when :max
292+
node.instruction = OptNewArrayMax.new(node.instruction.number)
293+
node.next_node = next_node.next_node
294+
when :min
295+
node.instruction = OptNewArrayMin.new(node.instruction.number)
296+
node.next_node = next_node.next_node
297+
end
274298
when PutObject, PutString
275299
next unless node.next_node
276-
next if node.instruction.is_a?(PutObject) && !node.instruction.object.is_a?(String)
300+
if node.instruction.is_a?(PutObject) &&
301+
!node.instruction.object.is_a?(String)
302+
next
303+
end
277304

278305
next_node = node.next_node
279306
next unless next_node.instruction.is_a?(Send)
280307
next if next_node.instruction.block_iseq
281308

282309
calldata = next_node.instruction.calldata
283310
next unless calldata.flags == CallData::CALL_ARGS_SIMPLE
311+
next unless calldata.argc == 0
284312

285313
case calldata.method
286314
when :freeze
287-
node.instruction = OptStrFreeze.new(node.instruction.object, calldata)
315+
node.instruction =
316+
OptStrFreeze.new(node.instruction.object, calldata)
288317
node.next_node = next_node.next_node
289318
when :-@
290-
node.instruction = OptStrUMinus.new(node.instruction.object, calldata)
319+
node.instruction =
320+
OptStrUMinus.new(node.instruction.object, calldata)
291321
node.next_node = next_node.next_node
292322
end
293323
when Send
294324
calldata = node.instruction.calldata
295325

296-
if !node.instruction.block_iseq && !calldata.flag?(CallData::CALL_ARGS_BLOCKARG)
326+
if !node.instruction.block_iseq &&
327+
!calldata.flag?(CallData::CALL_ARGS_BLOCKARG)
297328
# Specialize the send instruction. If it doesn't have a block
298329
# attached, then we will replace it with an opt_send_without_block
299330
# and do further specializations based on the called method and
@@ -639,24 +670,6 @@ def opt_getinlinecache(label, cache)
639670
push(Legacy::OptGetInlineCache.new(label, cache))
640671
end
641672

642-
def opt_newarray_max(length)
643-
if options.specialized_instruction?
644-
push(OptNewArrayMax.new(length))
645-
else
646-
newarray(length)
647-
send(YARV.calldata(:max))
648-
end
649-
end
650-
651-
def opt_newarray_min(length)
652-
if options.specialized_instruction?
653-
push(OptNewArrayMin.new(length))
654-
else
655-
newarray(length)
656-
send(YARV.calldata(:min))
657-
end
658-
end
659-
660673
def opt_setinlinecache(cache)
661674
push(Legacy::OptSetInlineCache.new(cache))
662675
end
@@ -938,9 +951,11 @@ def self.from(source, options = Compiler::Options.new, parent_iseq = nil)
938951
when :opt_getinlinecache
939952
iseq.opt_getinlinecache(labels[opnds[0]], opnds[1])
940953
when :opt_newarray_max
941-
iseq.opt_newarray_max(opnds[0])
954+
iseq.newarray(opnds[0])
955+
iseq.send(YARV.calldata(:max))
942956
when :opt_newarray_min
943-
iseq.opt_newarray_min(opnds[0])
957+
iseq.newarray(opnds[0])
958+
iseq.send(YARV.calldata(:min))
944959
when :opt_neq
945960
iseq.push(
946961
OptNEq.new(CallData.from(opnds[0]), CallData.from(opnds[1]))

0 commit comments

Comments
 (0)