Skip to content

Commit 588f52a

Browse files
committed
__copysplat added as an ugly (and hopefully temporary) hack.
Idea is to prevent unnecessary Array creation in the case of the frequent pattern of using the splat operator in arguments only to then forward the splatted arguments in a call to another method. To do it properly we need to check that it's not referenced elsewhere. Instead we use the special name __copysplat to trigger non-Ruby functionality until we have a proper verification step in place.
1 parent 850d71c commit 588f52a

File tree

6 files changed

+71
-43
lines changed

6 files changed

+71
-43
lines changed

compile_calls.rb

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -71,20 +71,28 @@ def copy_splat_loop(splatcnt, indir)
7171
# less efficient than it could be.
7272
#
7373
def compile_args_copysplat(scope, a, indir)
74-
@e.comment("SPLAT")
7574
@e.with_register do |splatcnt|
76-
param = compile_eval_arg(scope, a[1])
77-
@e.addl(4,param)
78-
@e.load_indirect(param, splatcnt)
79-
@e.addl(4,param)
80-
@e.load_indirect(param, :eax)
81-
@e.testl(:eax,:eax)
82-
l = @e.get_local
83-
84-
# If Array class ptr has not been allocated yet:
85-
@e.je(l)
86-
copy_splat_loop(splatcnt, indir)
87-
@e.local(l)
75+
if a[1] == :__copysplat
76+
@e.comment("SPLAT COPY")
77+
param = @e.save_to_reg(compile_eval_arg(scope, [:sub, :numargs, 2]))
78+
@e.movl(param, splatcnt)
79+
param = compile_eval_arg(scope, a[1])
80+
copy_splat_loop(splatcnt, indir)
81+
else
82+
@e.comment("SPLAT ARRAY")
83+
param = compile_eval_arg(scope, a[1])
84+
@e.addl(4,param)
85+
@e.load_indirect(param, splatcnt)
86+
@e.addl(4,param)
87+
@e.load_indirect(param, :eax)
88+
@e.testl(:eax,:eax)
89+
l = @e.get_local
90+
91+
# If Array class ptr has not been allocated yet:
92+
@e.je(l)
93+
copy_splat_loop(splatcnt, indir)
94+
@e.local(l)
95+
end
8896
end
8997

9098
end
@@ -129,11 +137,15 @@ def compile_args_splat(scope, ob, args)
129137
exprlist = []
130138
args.each_with_index do |a, i|
131139
if a.is_a?(Array) && a[0] == :splat
132-
# We do this, rather than Array#length, because the class may not
133-
# have been created yet. This *requires* Array's @len ivar to be
134-
# in the first ivar;
135-
# FIXME: should enforce this.
136-
exprlist << [:index, a[1], 1]
140+
if a[1] == :__copysplat
141+
exprlist << [:sub, :numargs, 2]
142+
else
143+
# We do this, rather than Array#length, because the class may not
144+
# have been created yet. This *requires* Array's @len ivar to be
145+
# in the first ivar;
146+
# FIXME: should enforce this.
147+
exprlist << [:index, a[1], 1]
148+
end
137149
else
138150
num_fixed += 1
139151
end

lib/core/array.rb

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ class Array
99
# FIXME: initialize should take two optional arguments,
1010
# but we don't yet handle initializers, so not supporting that
1111
# for now.
12-
def initialize *elements
12+
def initialize *__copysplat
1313
# FIXME: See notes in lib/core/core.rb regarding bootstrapping
1414
# of splat handling, which causes the annoyance below:
1515
#
@@ -21,9 +21,11 @@ def initialize *elements
2121
# We'd still be limited in what to do here, but not as strictly.
2222
#
2323
__initialize
24-
if elements.length > 0
25-
__grow(elements[0].__get_raw)
26-
end
24+
%s(if (gt numargs 2) (callm self __copy_init ((index __copysplat 0))))
25+
end
26+
27+
def __copy_init other
28+
__grow(other.__get_raw)
2729
end
2830

2931
def capacity

lib/core/array_base.rb

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,14 @@ def to_a
6969
(assign splat (callm Array __new))
7070
(assign pos 0)
7171
(assign max (sub na 2))
72-
(callm splat __grow (max))
73-
(while (lt pos max)
74-
(do
75-
(callm splat __set (pos (index r pos)))
76-
(assign pos (add pos 1))
77-
)
78-
)
79-
splat
72+
(if (gt max 0) (do
73+
(callm splat __grow (max))
74+
(while (lt pos max)
75+
(do
76+
(callm splat __set (pos (index r pos)))
77+
(assign pos (add pos 1))
78+
)
79+
)
80+
))
81+
splat
8082
))

lib/core/class.rb

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,9 +124,10 @@ def __new
124124
ob
125125
end
126126

127-
def new *rest
127+
# FIXME: Optimizing this will shave massively off __splat_to_Array calls.
128+
def new *__copysplat
128129
ob = allocate
129-
ob.initialize(*rest)
130+
ob.initialize(*__copysplat)
130131
ob
131132
end
132133

lib/core/proc.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ def arity
2323
@arity
2424
end
2525

26-
def call *arg
27-
%s(call @addr (@s 0 @env (splat arg)))
26+
def call *__copysplat
27+
%s(call @addr (@s 0 @env (splat __copysplat)))
2828

2929
# WARNING: Do not do extra stuff here. If this is a 'proc'/bare block
3030
# code after the %s(call ...) above will not get executed.

lib/core/string.rb

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11

2+
%s(defun __stralloc (len) (do (__alloc_leaf len)))
23
# See Symbol for a discussion of type tagging.
34
#
45
# FIXME: For (right) now String objects are sort-of immutable.
@@ -15,7 +16,8 @@ class String
1516
# will be prone to order of bootstrapping the core
1617
# classes.
1718
#
18-
def initialize *str
19+
20+
def initialize *__copysplat
1921
# @buffer contains the pointer to raw memory
2022
# used to contain the string.
2123
#
@@ -24,14 +26,22 @@ def initialize *str
2426
# be an FixNum instance instead of the actual
2527
# value 0.
2628

29+
%s(assign @buffer 0)
30+
@flags = 0
31+
@length = 0
32+
%s(assign @capacity 0)
2733
%s(if (lt numargs 3)
28-
(assign @buffer "")
29-
(do
30-
(assign first (callm str [] (__I0)))
31-
(assign len (callm first length))
32-
(callm self __copy_raw ((callm first __get_raw) len))
33-
)
34-
)
34+
(assign @buffer "")
35+
(callm self __copy_initialize ((splat __copysplat)))
36+
)
37+
end
38+
39+
def __copy_initialize *str
40+
%s(do
41+
(assign first (callm str [] ((__int 0))))
42+
(assign len (callm first length))
43+
(callm self __copy_raw ((callm first __get_raw) len))
44+
)
3545
end
3646

3747
def inspect
@@ -152,7 +162,8 @@ def eql? other
152162

153163
def __copy_raw(str,len)
154164
%s(assign len (add (callm len __get_raw) 1))
155-
%s(assign @buffer (__alloc_leaf len))
165+
%s(assign @capacity (add len 8))
166+
%s(assign @buffer (__stralloc @capacity))
156167
%s(memmove @buffer str len)
157168
%s(assign (bindex @buffer (sub len 1)) 0)
158169
nil

0 commit comments

Comments
 (0)