Skip to content

Commit ae12c2b

Browse files
author
Nicolas Laurent
committed
rewrite Array#recursively_flatten to not use Thread#detect_recursion and reduce splitting
1 parent d84da65 commit ae12c2b

File tree

1 file changed

+18
-16
lines changed

1 file changed

+18
-16
lines changed

src/main/ruby/truffleruby/core/array.rb

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1251,40 +1251,42 @@ def zip(*others)
12511251
end
12521252
end
12531253

1254-
# Helper to recurse through flattening since the method
1255-
# is not allowed to recurse itself. Detects recursive structures.
1254+
# Helper to "recurse" through flattening. Detects recursive structures.
1255+
# Does not actually recurse, but uses a worklist instead.
12561256
def recursively_flatten(array, out, max_levels = -1)
12571257
modified = false
1258+
visited = {}.compare_by_identity
1259+
worklist = [[array, 0]]
12581260

1259-
# Strict equality since < 0 means 'infinite'
1260-
if max_levels == 0
1261-
out.concat(array)
1262-
return false
1263-
end
1261+
until worklist.empty?
1262+
array, i = worklist.pop
12641263

1265-
max_levels -= 1
1266-
recursion = Truffle::ThreadOperations.detect_recursion(array) do
1267-
array = Truffle::Type.coerce_to(array, Array, :to_ary)
1264+
if i == 0
1265+
raise ArgumentError, 'tried to flatten recursive array' if visited.key?(array)
1266+
if max_levels == worklist.size
1267+
out.concat(array)
1268+
next
1269+
end
1270+
visited[array] = true
1271+
end
12681272

1269-
i = 0
12701273
size = array.size
1271-
12721274
while i < size
12731275
o = array.at i
1274-
12751276
tmp = Truffle::Type.rb_check_convert_type(o, Array, :to_ary)
12761277
if Primitive.nil? tmp
12771278
out << o
12781279
else
12791280
modified = true
1280-
recursively_flatten tmp, out, max_levels
1281+
worklist.push([array, i + 1], [tmp, 0])
1282+
break
12811283
end
1282-
12831284
i += 1
12841285
end
1286+
1287+
visited.delete array if i == size
12851288
end
12861289

1287-
raise ArgumentError, 'tried to flatten recursive array' if recursion
12881290
modified
12891291
end
12901292
private :recursively_flatten

0 commit comments

Comments
 (0)