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: ef4c54c267c5
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 829740f22fb3
Choose a head ref
  • 3 commits
  • 3 files changed
  • 1 contributor

Commits on May 11, 2015

  1. Copy the full SHA
    590d33c View commit details
  2. [Truffle] Fixed version of delta/struct.rb from Rubinius 8c898e705e54…

    …5cc055e6afff6d0ef3620688fe2f
    chrisseaton committed May 11, 2015
    Copy the full SHA
    e394104 View commit details
  3. [Truffle] Fixed version of Array#sample from Rubinius fce598288cc7cdf…

    …f9de6542bd0723027cfa70eac
    chrisseaton committed May 11, 2015
    Copy the full SHA
    829740f View commit details
Showing with 158 additions and 20 deletions.
  1. +1 −1 core/src/main/java/org/jruby/Ruby.java
  2. +68 −17 truffle/src/main/ruby/core/rubinius/common/array.rb
  3. +89 −2 truffle/src/main/ruby/core/rubinius/delta/struct.rb
2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/Ruby.java
Original file line number Diff line number Diff line change
@@ -927,7 +927,7 @@ private TruffleContextInterface loadTruffleContext() {
try {
clazz = getJRubyClassLoader().loadClass("org.jruby.truffle.runtime.RubyContext");
} catch (Exception e) {
throw new RuntimeException("Truffle backend available", e);
throw new RuntimeException("Truffle backend not available", e);
}

final TruffleContextInterface truffleBridge;
85 changes: 68 additions & 17 deletions truffle/src/main/ruby/core/rubinius/common/array.rb
Original file line number Diff line number Diff line change
@@ -928,29 +928,80 @@ def sample(count=undefined, options=undefined)
end

rng = options[:random] if options
rng = Kernel unless rng and rng.respond_to? :rand

unless count
random = Rubinius::Type.coerce_to_collection_index rng.rand(size)
raise RangeError, "random value must be >= 0" if random < 0
raise RangeError, "random value must be less than Array size" unless random < size

return at random
if rng and rng.respond_to? :rand
rng = SampleRandom.new rng
else
rng = Kernel
end

return at rng.rand(size) unless count

count = size if count > size
result = Array.new self
tuple = Rubinius::Mirror::Array.reflect(result).tuple

count.times do |i|
random = Rubinius::Type.coerce_to_collection_index rng.rand(size)
raise RangeError, "random value must be >= 0" if random < 0
raise RangeError, "random value must be less than Array size" unless random < size
case count
when 0
return []
when 1
return [at(rng.rand(size))]
when 2
i = rng.rand(size)
j = rng.rand(size)
if i == j
j = i == 0 ? i + 1 : i - 1
end
return [at(i), at(j)]
else
if size / count > 3
abandon = false
spin = 0

result = Array.new count
i = 1

result[0] = rng.rand(size)
while i < count
k = rng.rand(size)
j = 0

while j < i
while k == result[j]
spin += 1
if spin > 100
abandon = true
break
end
k = rng.rand(size)
end
break if abandon

j += 1
end

break if abandon

tuple.swap i, random
end
result[i] = k

return count == size ? result : result[0, count]
i += 1
end

unless abandon
i = 0
while i < count
result[i] = at result[i]
i += 1
end

return result
end
end

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

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

return count == size ? result : result[0, count]
end
end

def select!(&block)
91 changes: 89 additions & 2 deletions truffle/src/main/ruby/core/rubinius/delta/struct.rb
Original file line number Diff line number Diff line change
@@ -24,8 +24,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.

# Only part of Rubinius' struct.rb

class Struct
Struct.new 'Tms', :utime, :stime, :cutime, :cstime, :tutime, :tstime

@@ -40,4 +38,93 @@ def initialize(utime=nil, stime=nil, cutime=nil, cstime=nil,
@tstime = tstime
end
end

def self._specialize(attrs)
# Because people are crazy, they subclass Struct directly, ie.
# class Craptastic < Struct
#
# NOT
#
# class Fine < Struct.new(:x, :y)
#
# When they do this craptastic act, they'll sometimes define their
# own #initialize and super into Struct#initialize.
#
# When they do this and then do Craptastic.new(:x, :y), this code
# will accidentally shadow their #initialize. So for now, only run
# the specialize if we're trying new Struct's directly from Struct itself,
# not a craptastic Struct subclass.

return unless superclass.equal? Struct

# To allow for optimization, we generate code with normal ivar
# references for all attributes whose names can be written as
# tIVAR tokens. For example, of the following struct attributes
#
# Struct.new(:a, :@b, :c?, :'d-e')
#
# only the first, :a, can be written as a valid tIVAR token:
#
# * :a can be written as @a
# * :@b becomes @@b and would be interpreted as a tCVAR
# * :c? becomes @c? and be interpreted as the beginning of
# a ternary expression
# * :'d-e' becomes @d-e and would be interpreted as a method
# invocation
#
# Attribute names that cannot be written as tIVAR tokens will
# fall back to using #instance_variable_(get|set).

args, assigns, hashes, vars = [], [], [], []

attrs.each_with_index do |name, i|
name = "@#{name}"

if name =~ /^@[a-z_]\w*$/i
assigns << "#{name} = a#{i}"
vars << name
else
assigns << "instance_variable_set(:#{name.inspect}, a#{i})"
vars << "instance_variable_get(:#{name.inspect})"
end

args << "a#{i} = nil"
hashes << "#{vars[-1]}.hash"
end

code = <<-CODE
def initialize(#{args.join(", ")})
#{assigns.join(';')}
self
end
def hash
hash = #{hashes.size}
return hash if Thread.detect_outermost_recursion(self) do
hash = hash ^ #{hashes.join(' ^ ')}
end
hash
end
def to_a
[#{vars.join(', ')}]
end
def length
#{vars.size}
end
CODE

begin
mod = Module.new do
module_eval code
end
include mod
rescue SyntaxError
# SyntaxError means that something is wrong with the
# specialization code. Just eat the error and don't specialize.
end
end
end