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

Commits on Feb 4, 2015

  1. Copy the full SHA
    d92f842 View commit details
  2. Revert "[Truffle] Remove relationship between RubyThread and Java Thr…

    …ead."
    
    * This reverts commit 6c57d8e.
    * Turns out to be useful for Thread#run.
    eregon committed Feb 4, 2015
    Copy the full SHA
    8359731 View commit details
  3. Copy the full SHA
    186bb63 View commit details
  4. Copy the full SHA
    147cbea View commit details
  5. Copy the full SHA
    af8e1c9 View commit details
Showing with 364 additions and 53 deletions.
  1. +1 −0 core/src/main/ruby/jruby/truffle/core.rb
  2. +0 −6 core/src/main/ruby/jruby/truffle/core/rubinius/api/shims/undefined.rb
  3. +53 −0 core/src/main/ruby/jruby/truffle/core/rubinius/kernel/common/mutex.rb
  4. +0 −5 spec/truffle/tags/core/kernel/sleep_tags.txt
  5. +0 −3 spec/truffle/tags/core/mutex/lock_tags.txt
  6. +0 −2 spec/truffle/tags/core/mutex/locked_tags.txt
  7. +0 −8 spec/truffle/tags/core/mutex/sleep_tags.txt
  8. +0 −1 spec/truffle/tags/core/mutex/synchronize_tags.txt
  9. +0 −4 spec/truffle/tags/core/mutex/try_lock_tags.txt
  10. +0 −3 spec/truffle/tags/core/mutex/unlock_tags.txt
  11. +9 −3 tool/jt.rb
  12. +1 −0 truffle/src/main/java/org/jruby/truffle/TruffleBridgeImpl.java
  13. +8 −0 truffle/src/main/java/org/jruby/truffle/nodes/RubyNode.java
  14. +1 −0 truffle/src/main/java/org/jruby/truffle/nodes/RubyTypes.java
  15. +23 −13 truffle/src/main/java/org/jruby/truffle/nodes/core/KernelNodes.java
  16. +149 −0 truffle/src/main/java/org/jruby/truffle/nodes/core/MutexNodes.java
  17. +36 −0 truffle/src/main/java/org/jruby/truffle/nodes/core/ThreadNodes.java
  18. +17 −0 truffle/src/main/java/org/jruby/truffle/runtime/core/CoreLibrary.java
  19. +42 −0 truffle/src/main/java/org/jruby/truffle/runtime/core/RubyMutex.java
  20. +19 −2 truffle/src/main/java/org/jruby/truffle/runtime/core/RubyThread.java
  21. +1 −3 truffle/src/main/java/org/jruby/truffle/runtime/subsystems/ObjectSpaceManager.java
  22. +4 −0 truffle/src/main/java/org/jruby/truffle/runtime/subsystems/ThreadManager.java
1 change: 1 addition & 0 deletions core/src/main/ruby/jruby/truffle/core.rb
Original file line number Diff line number Diff line change
@@ -52,6 +52,7 @@
require_relative 'core/rubinius/kernel/common/string'
require_relative 'core/rubinius/kernel/common/struct'
require_relative 'core/rubinius/kernel/common/regexp'
require_relative 'core/rubinius/kernel/common/mutex'
require_relative 'core/rubinius/kernel/common/time'
require_relative 'core/rubinius/kernel/common/true'

Original file line number Diff line number Diff line change
@@ -6,12 +6,6 @@
# GNU General Public License version 2
# GNU Lesser General Public License version 2.1

module Rubinius

UNDEFINED = Object.new

end

module Kernel

# TODO(CS): this seems very vulnerable to name conflicts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Copyright (c) 2007-2014, Evan Phoenix and contributors
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# * Neither the name of Rubinius nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# 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' mutex.rb without implementation-specific methods.

class Mutex

def synchronize
lock
begin
yield
ensure
unlock
end
end

def sleep(duration=undefined)
if duration.kind_of?(Numeric) && duration < 0
raise ArgumentError, "time interval must be positive"
end

unlock
begin
Kernel.sleep(duration)
ensure
lock
end
end

end
5 changes: 0 additions & 5 deletions spec/truffle/tags/core/kernel/sleep_tags.txt
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
fails:Kernel#sleep is a private method
fails:Kernel#sleep pauses execution for approximately the duration requested
fails:Kernel#sleep returns the rounded number of seconds asleep
fails:Kernel#sleep raises an ArgumentError when passed a negative duration
fails:Kernel#sleep raises a TypeError when passed a non-numeric duration
fails:Kernel#sleep accepts a Rational
fails:Kernel#sleep pauses execution indefinitely if not given a duration
fails:Kernel.sleep needs to be reviewed for spec completeness
fails:Kernel#sleep raises a TypeError when passed nil
fails:Kernel#sleep raises a TypeError when passed a String
slow:Kernel#sleep accepts a Float
slow:Kernel#sleep accepts a Rational
3 changes: 0 additions & 3 deletions spec/truffle/tags/core/mutex/lock_tags.txt

This file was deleted.

2 changes: 0 additions & 2 deletions spec/truffle/tags/core/mutex/locked_tags.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
fails:Mutex#locked? returns true if locked
fails:Mutex#locked? returns false if unlocked
fails:Mutex#locked? returns the status of the lock
8 changes: 0 additions & 8 deletions spec/truffle/tags/core/mutex/sleep_tags.txt

This file was deleted.

1 change: 0 additions & 1 deletion spec/truffle/tags/core/mutex/synchronize_tags.txt

This file was deleted.

4 changes: 0 additions & 4 deletions spec/truffle/tags/core/mutex/try_lock_tags.txt

This file was deleted.

3 changes: 0 additions & 3 deletions spec/truffle/tags/core/mutex/unlock_tags.txt

This file was deleted.

12 changes: 9 additions & 3 deletions tool/jt.rb
Original file line number Diff line number Diff line change
@@ -36,9 +36,15 @@ module ShellUtils
private

def raw_sh(*args)
unless system(*args)
$stderr.puts "FAILED (#{$?}): #{args * ' '}"
exit $?.exitstatus
begin
result = system(*args)
rescue Interrupt
abort # Ignore Ctrl+C
else
unless result
$stderr.puts "FAILED (#{$?}): #{args * ' '}"
exit $?.exitstatus
end
end
end

Original file line number Diff line number Diff line change
@@ -84,6 +84,7 @@ public void init() {
CoreMethodNodeManager.addCoreMethodNodes(rubyObjectClass, MatchDataNodesFactory.getFactories());
CoreMethodNodeManager.addCoreMethodNodes(rubyObjectClass, MathNodesFactory.getFactories());
CoreMethodNodeManager.addCoreMethodNodes(rubyObjectClass, ModuleNodesFactory.getFactories());
CoreMethodNodeManager.addCoreMethodNodes(rubyObjectClass, MutexNodesFactory.getFactories());
CoreMethodNodeManager.addCoreMethodNodes(rubyObjectClass, NumericNodesFactory.getFactories());
CoreMethodNodeManager.addCoreMethodNodes(rubyObjectClass, ObjectSpaceNodesFactory.getFactories());
CoreMethodNodeManager.addCoreMethodNodes(rubyObjectClass, ProcessNodesFactory.getFactories());
8 changes: 8 additions & 0 deletions truffle/src/main/java/org/jruby/truffle/nodes/RubyNode.java
Original file line number Diff line number Diff line change
@@ -141,6 +141,10 @@ public RubyModule executeRubyModule(VirtualFrame frame) throws UnexpectedResultE
return RubyTypesGen.RUBYTYPES.expectRubyModule(execute(frame));
}

public RubyMutex executeRubyMutex(VirtualFrame frame) throws UnexpectedResultException {
return RubyTypesGen.RUBYTYPES.expectRubyMutex(execute(frame));
}

public RubyNilClass executeRubyNilClass(VirtualFrame frame) throws UnexpectedResultException {
return RubyTypesGen.RUBYTYPES.expectRubyNilClass(execute(frame));
}
@@ -471,4 +475,8 @@ public boolean isRubyNilObject(Object value) {
return value == getContext().getCoreLibrary().getNilObject();
}

public boolean isRubiniusUndefined(Object value) {
return value == getContext().getCoreLibrary().getRubiniusUndefined();
}

}
Original file line number Diff line number Diff line change
@@ -44,6 +44,7 @@
RubyHash.class, //
RubyMatchData.class, //
RubyModule.class, //
RubyMutex.class, //
RubyNilClass.class, //
RubyProc.class, //
RubyRange.class, //
36 changes: 23 additions & 13 deletions truffle/src/main/java/org/jruby/truffle/nodes/core/KernelNodes.java
Original file line number Diff line number Diff line change
@@ -1933,40 +1933,50 @@ public SleepNode(SleepNode prev) {
}

@Specialization
public double sleep(UndefinedPlaceholder duration) {
return doSleep(0);
public long sleep(UndefinedPlaceholder duration) {
// TODO: this should actually be "forever".
return doSleepMillis(Long.MAX_VALUE);
}

@Specialization(guards = "isRubiniusUndefined")
public long sleep(RubyBasicObject duration) {
return sleep(UndefinedPlaceholder.INSTANCE);
}

@Specialization
public double sleep(int duration) {
return doSleep(duration);
public long sleep(int duration) {
return doSleepMillis(duration * 1000);
}

@Specialization
public double sleep(long duration) {
return doSleep(duration);
public long sleep(long duration) {
return doSleepMillis(duration * 1000);
}

@Specialization
public double sleep(double duration) {
return doSleep(duration);
public long sleep(double duration) {
return doSleepMillis((long) (duration * 1000));
}

@TruffleBoundary
private double doSleep(final double duration) {
final long start = System.nanoTime();
private long doSleepMillis(final long durationInMillis) {
if (durationInMillis < 0) {
throw new RaiseException(getContext().getCoreLibrary().argumentError("time interval must be positive", this));
}

final long start = System.currentTimeMillis();

getContext().getThreadManager().runOnce(new BlockingActionWithoutGlobalLock<Boolean>() {
@Override
public Boolean block() throws InterruptedException {
Thread.sleep((long) (duration * 1000));
Thread.sleep(durationInMillis);
return SUCCESS;
}
});

final long end = System.nanoTime();
final long end = System.currentTimeMillis();

return (end - start) / 1e9;
return (end - start) / 1000;
}

}
149 changes: 149 additions & 0 deletions truffle/src/main/java/org/jruby/truffle/nodes/core/MutexNodes.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
/*
* Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved. This
* code is released under a tri EPL/GPL/LGPL license. You can use it,
* redistribute it and/or modify it under the terms of the:
*
* Eclipse Public License version 1.0
* GNU General Public License version 2
* GNU Lesser General Public License version 2.1
*/
package org.jruby.truffle.nodes.core;

import java.util.concurrent.locks.ReentrantLock;

import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.control.RaiseException;
import org.jruby.truffle.runtime.core.RubyMutex;
import org.jruby.truffle.runtime.subsystems.ThreadManager.BlockingActionWithoutGlobalLock;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.source.SourceSection;

@CoreClass(name = "Mutex")
public abstract class MutexNodes {

@CoreMethod(names = "lock")
public abstract static class LockNode extends UnaryCoreMethodNode {

public LockNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

public LockNode(LockNode prev) {
super(prev);
}

@Specialization
public RubyMutex lock(RubyMutex mutex) {
final ReentrantLock lock = mutex.getReentrantLock();

if (lock.isHeldByCurrentThread()) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().threadError("deadlock; recursive locking", this));
}

getContext().getThreadManager().runUntilResult(new BlockingActionWithoutGlobalLock<Boolean>() {
@Override
public Boolean block() throws InterruptedException {
lock.lockInterruptibly();
return SUCCESS;
}
});

return mutex;
}

}

@CoreMethod(names = "locked?")
public abstract static class IsLockedNode extends UnaryCoreMethodNode {

public IsLockedNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

public IsLockedNode(IsLockedNode prev) {
super(prev);
}

@Specialization
public boolean isLocked(RubyMutex mutex) {
final ReentrantLock lock = mutex.getReentrantLock();

return lock.isLocked();
}

}

@CoreMethod(names = "owned?")
public abstract static class IsOwnedNode extends UnaryCoreMethodNode {

public IsOwnedNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

public IsOwnedNode(IsOwnedNode prev) {
super(prev);
}

@Specialization
public boolean isOwned(RubyMutex mutex) {
final ReentrantLock lock = mutex.getReentrantLock();

return lock.isHeldByCurrentThread();
}

}

@CoreMethod(names = "try_lock")
public abstract static class TryLockNode extends UnaryCoreMethodNode {

public TryLockNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

public TryLockNode(TryLockNode prev) {
super(prev);
}

@Specialization
public boolean tryLock(RubyMutex mutex) {
final ReentrantLock lock = mutex.getReentrantLock();

if (lock.isHeldByCurrentThread()) {
return false;
}

return lock.tryLock();
}

}

@CoreMethod(names = "unlock")
public abstract static class UnlockNode extends UnaryCoreMethodNode {

public UnlockNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

public UnlockNode(UnlockNode prev) {
super(prev);
}

@Specialization
public RubyMutex unlock(RubyMutex mutex) {
final ReentrantLock lock = mutex.getReentrantLock();

try {
lock.unlock();
} catch (IllegalMonitorStateException e) {
throw new RaiseException(getContext().getCoreLibrary().threadError("Attempt to unlock a mutex which is not locked", this));
}

return mutex;
}

}

}
Loading