Skip to content

Commit e74c0f8

Browse files
chrisseatonLillian Zhang
authored andcommitted
Split detect_recursion for single objects and pairs of objects
1 parent ea86e59 commit e74c0f8

File tree

7 files changed

+40
-13
lines changed

7 files changed

+40
-13
lines changed

spec/truffle/thread/detect_recursion_spec.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,13 @@ def self.check_recursion_to_depth(obj, depth)
2525

2626
def self.check_double_recursion_equality_to_depth(obj1, obj2, depth)
2727
# checks that obj1 and obj2 are both recursive and equal structurally
28-
# (because detect_recursion on two objects is only used during object comparison,
28+
# (because detect_pair_recursion on two objects is only used during object comparison,
2929
# and aborts after inequality is discovered)
3030
return false unless obj1.class == obj2.class
3131
return false unless obj1.respond_to?(:each)
3232
return false unless obj1.size == obj2.size
3333

34-
Truffle::ThreadOperations.detect_recursion(obj1, obj2) do
34+
Truffle::ThreadOperations.detect_pair_recursion(obj1, obj2) do
3535
if depth > 1
3636
if obj1.class == Hash
3737
obj1.each do |key, val|

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ def <=>(other)
8989

9090
total = other.size
9191

92-
Truffle::ThreadOperations.detect_recursion self, other do
92+
Truffle::ThreadOperations.detect_pair_recursion self, other do
9393
i = 0
9494
count = Primitive.min(total, size)
9595

@@ -132,7 +132,7 @@ def ==(other)
132132

133133
return false unless size == other.size
134134

135-
Truffle::ThreadOperations.detect_recursion self, other do
135+
Truffle::ThreadOperations.detect_pair_recursion self, other do
136136
i = 0
137137
total = size
138138

@@ -325,7 +325,7 @@ def eql?(other)
325325
return false unless other.kind_of?(Array)
326326
return false if size != other.size
327327

328-
Truffle::ThreadOperations.detect_recursion self, other do
328+
Truffle::ThreadOperations.detect_pair_recursion self, other do
329329
i = 0
330330
each do |x|
331331
return false unless x.eql? other[i]

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ module Comparable
3030
def ==(other)
3131
return true if equal?(other)
3232

33-
return false if Truffle::ThreadOperations.detect_recursion(self, other) do
33+
return false if Truffle::ThreadOperations.detect_pair_recursion(self, other) do
3434
unless comp = (self <=> other)
3535
return false
3636
end

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ def eql_op(op, other)
137137

138138
return false unless other.size == size
139139

140-
Truffle::ThreadOperations.detect_recursion self, other do
140+
Truffle::ThreadOperations.detect_pair_recursion self, other do
141141
each_pair do |key, value|
142142
other_value = other._get_or_undefined(key)
143143

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1585,7 +1585,7 @@ def <=>(other)
15851585
return Primitive.string_cmp self, other
15861586
end
15871587

1588-
Truffle::ThreadOperations.detect_recursion self, other do
1588+
Truffle::ThreadOperations.detect_pair_recursion self, other do
15891589
if other.respond_to?(:<=>) && !other.respond_to?(:to_str)
15901590
return nil unless tmp = (other <=> self)
15911591
elsif other.respond_to?(:to_str)

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ def to_s
188188
def ==(other)
189189
return false if self.class != other.class
190190

191-
Truffle::ThreadOperations.detect_recursion self, other do
191+
Truffle::ThreadOperations.detect_pair_recursion self, other do
192192
return self.values == other.values
193193
end
194194

@@ -270,7 +270,7 @@ def eql?(other)
270270
return true if equal? other
271271
return false if self.class != other.class
272272

273-
Truffle::ThreadOperations.detect_recursion self, other do
273+
Truffle::ThreadOperations.detect_pair_recursion self, other do
274274
_attrs.each do |var|
275275
mine = Primitive.object_hidden_var_get(self, var)
276276
theirs = Primitive.object_hidden_var_get(other, var)

src/main/ruby/truffleruby/core/truffle/thread_operations.rb

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,37 @@
6363
module Truffle::ThreadOperations
6464

6565
# detect_recursion will return if there's a recursion
66-
# on obj (or the pair obj+paired_obj).
66+
# on obj.
6767
# If there is one, it returns true.
6868
# Otherwise, it will yield once and return false.
69-
def self.detect_recursion(obj, paired_obj=nil)
69+
def self.detect_recursion(obj)
70+
unless Primitive.object_can_contain_object obj
71+
yield
72+
return false
73+
end
74+
75+
id = obj.object_id
76+
objects = Primitive.thread_recursive_objects
77+
78+
if objects[id]
79+
true
80+
else
81+
objects[id] = true
82+
begin
83+
yield
84+
ensure
85+
objects.delete id
86+
end
87+
false
88+
end
89+
end
90+
Truffle::Graal.always_split method(:detect_recursion)
91+
92+
# detect_recursion will return if there's a recursion
93+
# on the pair obj+paired_obj.
94+
# If there is one, it returns true.
95+
# Otherwise, it will yield once and return false.
96+
def self.detect_pair_recursion(obj, paired_obj)
7097
unless Primitive.object_can_contain_object obj
7198
yield
7299
return false
@@ -118,7 +145,7 @@ def self.detect_recursion(obj, paired_obj=nil)
118145

119146
false
120147
end
121-
Truffle::Graal.always_split method(:detect_recursion)
148+
Truffle::Graal.always_split method(:detect_pair_recursion)
122149

123150
class InnerRecursionDetected < Exception; end # rubocop:disable Lint/InheritException
124151

0 commit comments

Comments
 (0)