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

Commits on Dec 27, 2015

  1. Copy the full SHA
    50f6a5f View commit details
  2. Copy the full SHA
    247582e View commit details
  3. Faster impl (10x) of hash_le using Set.containsAll.

    For benchmark:
    
    ```ruby
    hash1 = {}
    1000.times.map{|i| hash1[i] = i**2}
    hash2 = hash1.dup
    loop {
      puts Benchmark.measure {
        1000.times { hash1 <= hash2 }
      }
    }
    ```
    
    Before:
    
    ```
      0.750000   0.040000   0.790000 (  0.352352)
      0.330000   0.020000   0.350000 (  0.271167)
      0.290000   0.010000   0.300000 (  0.254097)
      0.300000   0.020000   0.320000 (  0.285778)
      0.370000   0.010000   0.380000 (  0.261517)
    ```
    
    After:
    
    ```
      0.180000   0.010000   0.190000 (  0.049955)
      0.090000   0.000000   0.090000 (  0.026507)
      0.070000   0.000000   0.070000 (  0.024796)
      0.050000   0.000000   0.050000 (  0.024865)
      0.050000   0.010000   0.060000 (  0.024754)
    ```
    
    MRI 2.3:
    
    ```
      0.030000   0.000000   0.030000 (  0.028554)
      0.030000   0.000000   0.030000 (  0.028792)
      0.030000   0.000000   0.030000 (  0.029427)
      0.030000   0.000000   0.030000 (  0.027711)
      0.030000   0.000000   0.030000 (  0.028578)
    ```
    headius committed Dec 27, 2015
    Copy the full SHA
    cc23c68 View commit details
  4. Copy the full SHA
    4886125 View commit details
  5. Copy the full SHA
    27425c2 View commit details
  6. Copy the full SHA
    7e11bab View commit details
  7. Copy the full SHA
    d87e33e View commit details
  8. Copy the full SHA
    e5d2c30 View commit details
2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/RubyEnumerable.java
Original file line number Diff line number Diff line change
@@ -552,7 +552,7 @@ private static IRubyObject grep(ThreadContext context, IRubyObject self, final I
final RubyArray result = runtime.newArray();

if (block.isGiven()) {
callEach(runtime, context, self, block.getSignature(), new BlockCallback() {
callEach(runtime, context, self, Signature.ONE_REQUIRED, new BlockCallback() {
public IRubyObject call(ThreadContext ctx, IRubyObject[] largs, Block blk) {
IRubyObject larg = packEnumValues(ctx, largs);
if (pattern.callMethod(ctx, "===", larg).isTrue() == isPresent) {
8 changes: 1 addition & 7 deletions core/src/main/java/org/jruby/RubyHash.java
Original file line number Diff line number Diff line change
@@ -1213,13 +1213,7 @@ public IRubyObject op_aref(ThreadContext context, IRubyObject key) {
*
*/
private boolean hash_le(RubyHash other) {
RubyArray keys = keys();
for (Object key : keys) {
if (!other.get(key).equals( get(key) )) {
return false;
}
}
return true;
return other.directEntrySet().containsAll(directEntrySet());
}

@JRubyMethod(name = "<", required = 1)
24 changes: 16 additions & 8 deletions core/src/main/java/org/jruby/RubyIO.java
Original file line number Diff line number Diff line change
@@ -270,10 +270,17 @@ public OpenFile getOpenFile() {
}

public OpenFile getOpenFileChecked() {
checkInitialized();
openFile.checkClosed();
return openFile;
}

// MRI: rb_io_get_fptr
public OpenFile getOpenFileInitialized() {
checkInitialized();
return openFile;
}

private static ObjectAllocator IO_ALLOCATOR = new ObjectAllocator() {
@Override
public IRubyObject allocate(Ruby runtime, RubyClass klass) {
@@ -2040,7 +2047,9 @@ public IRubyObject close_write(ThreadContext context) {
RubyIO write_io;

write_io = GetWriteIO();
fptr = write_io.getOpenFileChecked();
fptr = write_io.getOpenFileInitialized();
if (!fptr.isOpen()) return context.nil;

boolean locked = fptr.lock();
try {
if (fptr.socketChannel() != null) {
@@ -2055,7 +2064,7 @@ public IRubyObject close_write(ThreadContext context) {
return context.nil;
}

if (fptr.isReadable()) {
if (fptr.isReadable() && !fptr.isDuplex()) {
throw runtime.newIOError("closing non-duplex IO for writing");
}
} finally {
@@ -2064,12 +2073,11 @@ public IRubyObject close_write(ThreadContext context) {


if (this != write_io) {
fptr = getOpenFileChecked();
fptr = getOpenFileInitialized();

locked = fptr.lock();
try {
fptr.tiedIOForWriting = null;
fptr.setMode(fptr.getMode() & ~OpenFile.DUPLEX);
} finally {
if (locked) fptr.unlock();
}
@@ -2085,7 +2093,8 @@ public IRubyObject close_read(ThreadContext context) {
OpenFile fptr;
RubyIO write_io;

fptr = getOpenFileChecked();
fptr = getOpenFileInitialized();
if (!fptr.isOpen()) return context.nil;

boolean locked = fptr.lock();
try {
@@ -2104,7 +2113,7 @@ public IRubyObject close_read(ThreadContext context) {
write_io = GetWriteIO();
if (this != write_io) {
OpenFile wfptr;
wfptr = write_io.getOpenFileChecked();
wfptr = write_io.getOpenFileInitialized();

boolean locked2 = wfptr.lock();
try {
@@ -2115,7 +2124,6 @@ public IRubyObject close_read(ThreadContext context) {
this.openFile = wfptr;
/* bind to write_io temporarily to get rid of memory/fd leak */
fptr.tiedIOForWriting = null;
fptr.setMode(fptr.getMode() & ~OpenFile.DUPLEX);
write_io.openFile = fptr;
fptr.cleanup(runtime, false);
/* should not finalize fptr because another thread may be reading it */
@@ -2125,7 +2133,7 @@ public IRubyObject close_read(ThreadContext context) {
}
}

if (fptr.isWritable()) {
if (fptr.isWritable() && !fptr.isDuplex()) {
throw runtime.newIOError("closing non-duplex IO for reading");
}
} finally {
4 changes: 2 additions & 2 deletions core/src/main/java/org/jruby/RubyNameError.java
Original file line number Diff line number Diff line change
@@ -219,8 +219,8 @@ public IRubyObject name() {

@JRubyMethod
public IRubyObject receiver(ThreadContext context) {
if (name instanceof RubyNameErrorMessage) {
return ((RubyNameErrorMessage)name).object;
if (message instanceof RubyNameErrorMessage) {
return ((RubyNameErrorMessage)message).object;
}

throw context.runtime.newArgumentError("no receiver is available");
5 changes: 2 additions & 3 deletions core/src/main/java/org/jruby/RubyObjectSpace.java
Original file line number Diff line number Diff line change
@@ -136,8 +136,7 @@ public static IRubyObject each_objectInternal(final ThreadContext context, IRuby
runtime.eachModule(new Function1<Object, IRubyObject>() {
public Object apply(IRubyObject arg1) {
if (rubyClass.isInstance(arg1)) {
if (arg1 instanceof IncludedModule ||
(arg1 instanceof RubyClass && ((RubyClass)arg1).isSingleton())) {
if (arg1 instanceof IncludedModule) {
// do nothing for included wrappers or singleton classes
} else {
count[0]++;
@@ -158,7 +157,7 @@ public Object apply(IRubyObject arg1) {
block.yield(context, attached);
if (attached instanceof RubyClass) {
for (RubyClass child : ((RubyClass)attached).subclasses(true)) {
if (child instanceof IncludedModule || child.isSingleton()) {
if (child instanceof IncludedModule) {
// do nothing for included wrappers or singleton classes
} else {
block.yield(context, child);
4 changes: 4 additions & 0 deletions core/src/main/java/org/jruby/util/io/OpenFile.java
Original file line number Diff line number Diff line change
@@ -706,6 +706,10 @@ public boolean isWritable() {
return (mode & WRITABLE) != 0;
}

public boolean isDuplex() {
return (mode & DUPLEX) != 0;
}

public boolean isReadBuffered() {
return READ_DATA_BUFFERED();
}
25 changes: 19 additions & 6 deletions spec/ruby/core/enumerable/grep_spec.rb
Original file line number Diff line number Diff line change
@@ -29,11 +29,24 @@ class EnumerableSpecGrep2; def ===(obj); /^ca/ =~ obj; end; end
ary.grep(/a(b)a/) { $1 }.should == ["b", "b"]
end

it "calls the block with an array when yielded with multiple arguments" do
yields = []
EnumerableSpecs::YieldsMixed.new.grep(Object){ |v| yields << v }
yields.should == [1, [2], [3, 4], [5, 6, 7], [8, 9], nil, []]

EnumerableSpecs::YieldsMixed.new.grep(Object).should == yields
describe "with a block" do
before :each do
@numerous = EnumerableSpecs::Numerous.new(*(0..9).to_a)
def (@odd_matcher = BasicObject.new).===(obj)
obj.odd?
end
end

it "returns an Array of matched elements that mapped by the block" do
@numerous.grep(@odd_matcher) { |n| n * 2 }.should == [2, 6, 10, 14, 18]
end

it "calls the block with gathered array when yielded with multiple arguments" do
EnumerableSpecs::YieldsMixed2.new.grep(Object){ |e| e }.should == EnumerableSpecs::YieldsMixed2.gathered_yields
end

it "raises an ArgumentError when not given a pattern" do
-> { @numerous.grep_v { |e| e } }.should raise_error(ArgumentError)
end
end
end
4 changes: 2 additions & 2 deletions spec/ruby/core/io/close_read_spec.rb
Original file line number Diff line number Diff line change
@@ -29,9 +29,9 @@

ruby_version_is '2.3' do
it "doesn't raise an IOError on subsequent invocations" do
@io.close_write
@io.close_read

lambda { @io.close_write }.should_not raise_error(IOError)
lambda { @io.close_read }.should_not raise_error(IOError)
end
end