Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 81827451392c
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 2651d86eb3a5
Choose a head ref
  • 12 commits
  • 2 files changed
  • 1 contributor

Commits on Jun 28, 2016

  1. [Truffle] Fix Array#fill_internal to not use tuple things and remove …

    …now unused #reallocate.
    eregon committed Jun 28, 2016
    Copy the full SHA
    cafbb6e View commit details
  2. Copy the full SHA
    bf261e1 View commit details
  3. Copy the full SHA
    6cdf430 View commit details
  4. Copy the full SHA
    1654476 View commit details
  5. Copy the full SHA
    a30bae2 View commit details
  6. Copy the full SHA
    fc156e9 View commit details
  7. [Truffle] Remove usage of tuple in Array#bsearch_index and reuse #bse…

    …arch_index for #bsearch.
    eregon committed Jun 28, 2016
    Copy the full SHA
    a236b3b View commit details
  8. Copy the full SHA
    9fb3dca View commit details
  9. Copy the full SHA
    4d95c74 View commit details
  10. Copy the full SHA
    a59cb9f View commit details
  11. Copy the full SHA
    641d217 View commit details
  12. Copy the full SHA
    2651d86 View commit details
Showing with 47 additions and 162 deletions.
  1. +4 −0 spec/ruby/core/array/slice_spec.rb
  2. +43 −162 truffle/src/main/ruby/core/array.rb
4 changes: 4 additions & 0 deletions spec/ruby/core/array/slice_spec.rb
Original file line number Diff line number Diff line change
@@ -42,6 +42,10 @@
a.slice!(0, 1).should == [1]
a.should == []
a[-1].should == nil

a = [1, 2, 3]
a.slice!(0,1).should == [1]
a.should == [2, 3]
end

it "returns nil if length is negative" do
205 changes: 43 additions & 162 deletions truffle/src/main/ruby/core/array.rb
Original file line number Diff line number Diff line change
@@ -32,10 +32,6 @@
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

# Rubinius uses the instance variable @total to store the size. We replace this
# in the translator with a call to size. We also replace the instance variable
# @tuple to be self, and @start to be 0.

class Array
include Enumerable

@@ -93,7 +89,7 @@ def <=>(other)
return 0 if equal? other
return nil if other.nil?

total = Rubinius::Mirror::Array.reflect(other).total
total = other.size

Thread.detect_recursion self, other do
i = 0
@@ -123,20 +119,12 @@ def ==(other)
return false unless size == other.size

Thread.detect_recursion self, other do
m = Rubinius::Mirror::Array.reflect other

md = self
od = m.tuple

i = 0
j = m.start

total = i + size
total = size

while i < total
return false unless md[i] == od[j]
return false unless self[i] == other[i]
i += 1
j += 1
end
end

@@ -156,28 +144,24 @@ def assoc(obj)
def bsearch(&block)
return to_enum :bsearch unless block_given?

idx = self.bsearch_index(&block)

return nil if idx.nil?

self.at(idx)
if idx = bsearch_index(&block)
self[idx]
else
nil
end
end

def bsearch_index
return to_enum :bsearch_index unless block_given?

m = Rubinius::Mirror::Array.reflect self

tuple = m.tuple

min = start = m.start
max = total = start + m.total
min = 0
max = total = size

last_true = nil
i = start + m.total / 2
i = size / 2

while max >= min and i >= start and i < total
x = yield tuple.at(i)
while max >= min and i >= 0 and i < total
x = yield at(i)

return i if x == 0

@@ -211,7 +195,7 @@ def combination(num)

unless block_given?
return to_enum(:combination, num) do
Rubinius::Mirror::Array.reflect(self).combination_size(num)
self.combination_size(num)
end
end

@@ -224,8 +208,8 @@ def combination(num)
elsif num == size
yield self.dup
elsif num >= 0 && num < size
stack = Rubinius::Tuple.pattern num + 1, 0
chosen = Rubinius::Tuple.new num
stack = Array.new(num + 1, 0)
chosen = Array.new(num)
lev = 0
done = false
stack[0] = -1
@@ -235,7 +219,7 @@ def combination(num)
lev += 1
chosen[lev] = self.at(stack[lev+1] = stack[lev] + 1)
end
yield chosen.to_a
yield chosen.dup
lev += 1
begin
done = lev == 0
@@ -397,27 +381,19 @@ def fill_internal(a=undefined, b=undefined, c=undefined)
right = size
end

total = right

if right > size
reallocate total
@total = right
if right.is_a?(Bignum)
raise RangeError, "bignum too big to convert into `long'"
end

# Must be after the potential call to reallocate, since
# reallocate might change @tuple
tuple = self

i = left

if block_given?
while i < total
tuple.put i, yield(i)
while i < right
self[i] = yield(i)
i += 1
end
else
while i < total
tuple.put i, obj
while i < right
self[i] = obj
i += 1
end
end
@@ -810,15 +786,11 @@ def reverse
def reverse_each
return to_enum(:reverse_each) { size } unless block_given?

stop = -1
i = stop + size
tuple = self

while i > stop
yield tuple.at(i)
i = size - 1
while i >= 0
yield at(i)
i -= 1
end

self
end

@@ -836,12 +808,9 @@ def rindex(obj=undefined)
i -= 1
end
else
stop = -1
i = stop + size
tuple = self

while i > stop
return i if tuple.at(i) == obj
i = size - 1
while i >= 0
return i if at(i) == obj
i -= 1
end
end
@@ -980,10 +949,11 @@ def sample(count=undefined, options=undefined)
end
end

result = Array.new self
tuple = Rubinius::Mirror::Array.reflect(result).tuple
result = Array.new(self)

count.times { |i| tuple.swap i, rng.rand(size) }
count.times { |i|
result.swap i, rng.rand(size)
}

return count == size ? result : result[0, count]
end
@@ -1154,24 +1124,6 @@ def zip_internal(*others)
out
end

# Reallocates the internal Tuple to accommodate at least given size
def reallocate(at_least)
return if at_least < size

new_total = size * 2

if new_total < at_least
new_total = at_least
end

new_tuple = Rubinius::Tuple.new new_total
new_tuple.copy_from self, 0, size, 0

@tuple = new_tuple
end

private :reallocate

# Helper to recurse through flattening since the method
# is not allowed to recurse itself. Detects recursive structures.
def recursively_flatten(array, out, max_levels = -1)
@@ -1185,14 +1137,13 @@ def recursively_flatten(array, out, max_levels = -1)

max_levels -= 1
recursion = Thread.detect_recursion(array) do
m = Rubinius::Mirror::Array.reflect array
array = Rubinius::Type.coerce_to(array, Array, :to_ary)

i = m.start
total = i + m.total
tuple = m.tuple
i = 0
size = array.size

while i < total
o = tuple.at i
while i < size
o = array.at i

if Rubinius::Type.object_kind_of? o, Array
modified = true
@@ -1222,7 +1173,7 @@ def recursively_flatten(array, out, max_levels = -1)

private :recursively_flatten

# Non-recursive sort using a temporary tuple for scratch storage.
# Non-recursive sort using a temporary array for scratch storage.
# This is a hybrid mergesort; it's hybrid because for short runs under
# 8 elements long we use insertion sort and then merge those sorted
# runs back together.
@@ -1430,10 +1381,6 @@ def new_reserved(count)
self.class.new(0 , nil)
end

# We must override the definition of `reverse!` because our Array isn't backed by a Tuple. Rubinius expects
# modifications to the Tuple to update the backing store and to do that, we treat the Array itself as its own Tuple.
# However, Rubinius::Tuple#reverse! has a different, conflicting signature from Array#reverse!. This override avoids
# all of those complications.
def reverse!
Truffle.check_frozen
return self unless size > 1
@@ -1449,9 +1396,6 @@ def reverse!
return self
end

# Rubinius expects to be able to resize the array and adjust pointers by modifying `@total` and `@start`, respectively.
# We might be able to handle such changes by special handling in the body translator, however simply resizing could
# delete elements from either side and we're not able to tell which without additional context.
def slice!(start, length=undefined)
Truffle.check_frozen

@@ -1523,40 +1467,18 @@ def slice!(start, length=undefined)
out
end

# Rubinius expects to modify the backing store via updates to `@tuple` and we don't support that. As such, we must
# provide our own modifying implementation here.
def delete_range(index, del_length)
# optimize for fast removal..
reg_start = index + del_length
reg_length = size - reg_start
if reg_start <= size
# If we're removing from the front, also reset @start to better
# use the Tuple
if index == 0
# Use a shift start optimization if we're only removing one
# element and the shift started isn't already huge.
if del_length == 1
# @start += 1 seems to work with this disabled?! FIXME
else
copy_from self, reg_start, reg_length, 0
end
else
copy_from self, reg_start, reg_length, index
end

# TODO we leave the old references in the Tuple, we should
# probably clear them out though.
del_length.times do
self.pop
end
# copy tail
copy_from self, reg_start, reg_length, index

self.pop(del_length)
end
end

private :delete_range

# Rubinius expects to modify the backing store via updates to `@tuple` and we don't support that. As such, we must
# provide our own modifying implementation here.
def uniq!(&block)
Truffle.check_frozen

@@ -1567,13 +1489,7 @@ def uniq!(&block)
end
return if im.size == size

m = Rubinius::Mirror::Array.reflect im.to_array
@tuple = m.tuple
raise 'start not zero' unless m.start.zero?
@total = m.total

copy_from(m.tuple, 0, m.total, 0)
delete_range(m.total, self.size - m.total)
Truffle::Array.steal_storage(self, im.to_array)
self
end

@@ -1621,38 +1537,3 @@ def sort!(&block)
end
public :sort!
end

module Rubinius
class Mirror
class Array

def self.reflect(object)
if Rubinius::Type.object_kind_of? object, ::Array
Array.new(object)
elsif ary = Rubinius::Type.try_convert(object, ::Array, :to_ary)
Array.new(ary)
else
message = "expected Array, given #{Rubinius::Type.object_class(object)}"
raise TypeError, message
end
end

def initialize(array)
@array = array
end

def total
@array.size
end

def tuple
@array
end

def start
0
end

end
end
end