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

Commits on Mar 19, 2016

  1. Copy the full SHA
    b94ebd8 View commit details
  2. Copy the full SHA
    abea0ef View commit details
  3. Copy the full SHA
    c1ffff8 View commit details
  4. Copy the full SHA
    a8625f4 View commit details
  5. Copy the full SHA
    53666d5 View commit details
  6. Copy the full SHA
    f176640 View commit details
  7. Copy the full SHA
    8834533 View commit details
  8. do not filter out too much elements (all starting "org.jruby") of the…

    … Java stack trace
    
    'unknown' JRuby packages e.g. "org.jruby.test" should not be filtered
    ... if they are that hurts stack-traces from extensions such as jruby-rack, jruby-openssl
    kares committed Mar 19, 2016
    Copy the full SHA
    c5e3728 View commit details
  9. [test] Ruby backtrace side as well retaining trace element for an "or…

    …g.jruby" prefix pkg
    kares committed Mar 19, 2016
    Copy the full SHA
    256cfb1 View commit details
  10. avoid unnecessary sub-array creation on caller backtrace generation

    ... patch also avoids the ugly double caller logging with -Xlog.callers
    kares committed Mar 19, 2016
    Copy the full SHA
    6987768 View commit details
  11. don't need a local

    kares committed Mar 19, 2016
    Copy the full SHA
    53c7e48 View commit details
116 changes: 79 additions & 37 deletions core/src/main/java/org/jruby/RubyFile.java
Original file line number Diff line number Diff line change
@@ -892,7 +892,7 @@ public static IRubyObject ftype(ThreadContext context, IRubyObject recv, IRubyOb
*/
@JRubyMethod(rest = true, meta = true)
public static RubyString join(ThreadContext context, IRubyObject recv, IRubyObject[] args) {
return join(context, recv, RubyArray.newArrayNoCopyLight(context.runtime, args));
return doJoin(context, recv, args);
}

@JRubyMethod(name = "lstat", required = 1, meta = true)
@@ -1936,69 +1936,111 @@ private static void checkHome(ThreadContext context) {
Ruby runtime = context.runtime;
RubyHash env = runtime.getENV();
String home = (String) env.get(runtime.newString("HOME"));
if (home == null || home.equals("")) {
if (home == null || home.length() == 0) {
throw runtime.newArgumentError("couldn't find HOME environment -- expanding `~'");
}
}

private static String inspectJoin(ThreadContext context, IRubyObject recv, RubyArray parent, RubyArray array) {
Ruby runtime = context.runtime;
private static RubyString doJoin(ThreadContext context, IRubyObject recv, IRubyObject[] args) {
final Ruby runtime = context.runtime;
final String separator = runtime.getClass("File").getConstant("SEPARATOR").toString();

// If already inspecting, there is no need to register/unregister again.
if (runtime.isInspecting(parent)) return join(context, recv, array).toString();
final RubyArray argsAry = RubyArray.newArrayNoCopyLight(runtime, args);

try {
runtime.registerInspecting(parent);
return join(context, recv, array).toString();
} finally {
runtime.unregisterInspecting(parent);
}
final StringBuilder buffer = new StringBuilder(24);
boolean isTainted = joinImpl(buffer, separator, context, recv, argsAry);

RubyString fixedStr = new RubyString(runtime, runtime.getString(), buffer);
fixedStr.setTaint(isTainted);
return fixedStr;
}

private static RubyString join(ThreadContext context, IRubyObject recv, RubyArray ary) {
IRubyObject[] args = ary.toJavaArray();
private static boolean joinImpl(final StringBuilder buffer, final String separator,
ThreadContext context, IRubyObject recv, RubyArray args) {

boolean isTainted = false;
StringBuilder buffer = new StringBuilder();
Ruby runtime = context.runtime;
String separator = context.getRuntime().getClass("File").getConstant("SEPARATOR").toString();

for (int i = 0; i < args.length; i++) {
if (args[i].isTaint()) {
isTainted = true;
}
String element;
if (args[i] instanceof RubyString) {
element = args[i].convertToString().getUnicodeValue();
} else if (args[i] instanceof RubyArray) {
if (runtime.isInspecting(args[i])) {
throw runtime.newArgumentError("recursive array");
for (int i = 0; i < args.size(); i++) {
final IRubyObject arg = args.eltInternal(i);
if (arg.isTaint()) isTainted = true;

final CharSequence element;
if (arg instanceof RubyString) {
element = arg.convertToString().getUnicodeValue();
} else if (arg instanceof RubyArray) {
if (context.runtime.isInspecting(arg)) {
throw context.runtime.newArgumentError("recursive array");
} else {
element = inspectJoin(context, recv, ary, ((RubyArray)args[i]));
element = joinImplInspecting(separator, context, recv, args, ((RubyArray) arg));
}
} else {
RubyString path = StringSupport.checkEmbeddedNulls(runtime, get_path(context, args[i]));
RubyString path = StringSupport.checkEmbeddedNulls(context.runtime, get_path(context, arg));
element = path.getUnicodeValue();
}

chomp(buffer);
if (i > 0 && !element.startsWith(separator)) {
if (i > 0 && !startsWith(element, separator)) {
buffer.append(separator);
}
buffer.append(element);
}

RubyString fixedStr = RubyString.newString(runtime, buffer.toString());
fixedStr.setTaint(isTainted);
return fixedStr;
return isTainted;
}

private static void chomp(StringBuilder buffer) {
private static StringBuilder joinImplInspecting(final String separator,
ThreadContext context, IRubyObject recv, RubyArray parent, RubyArray array) {
final Ruby runtime = context.runtime;

final StringBuilder buffer = new StringBuilder(24);
// If already inspecting, there is no need to register/unregister again.
if (runtime.isInspecting(parent)) {
joinImpl(buffer, separator, context, recv, array);
return buffer;
}

try {
runtime.registerInspecting(parent);
joinImpl(buffer, separator, context, recv, array);
return buffer;
}
finally {
runtime.unregisterInspecting(parent);
}
}

private static void chomp(final StringBuilder buffer) {
int lastIndex = buffer.length() - 1;

while (lastIndex >= 0 && (buffer.lastIndexOf("/") == lastIndex || buffer.lastIndexOf("\\") == lastIndex)) {
buffer.setLength(lastIndex);
lastIndex--;
while ( lastIndex >= 0 ) {
char c = buffer.charAt(lastIndex);
if ( c == '/' || c == '\\' ) {
buffer.setLength(lastIndex--);
continue;
}
break;
}
}

// String.startsWith for a CharSequence
private static boolean startsWith(final CharSequence str, final String prefix) {
int p = prefix.length();
if ( p > str.length() ) return false;
int i = 0;
while ( --p >= 0 ) {
if (str.charAt(i) != prefix.charAt(i)) return false;
i++;
}
return true;
}

// without any char[] array copying, also StringBuilder only has lastIndexOf(String)
private static int lastIndexOf(final CharSequence str, final char c, int index) {
while ( index >= 0 ) {
if ( str.charAt(index) == c ) return index;
index--;
}
return -1;
}

private static IRubyObject truncateCommon(ThreadContext context, IRubyObject recv, IRubyObject arg1, IRubyObject arg2) {
16 changes: 11 additions & 5 deletions core/src/main/java/org/jruby/RubyThread.java
Original file line number Diff line number Diff line change
@@ -478,14 +478,20 @@ public IRubyObject path(ThreadContext context) {

@JRubyMethod
public IRubyObject to_s(ThreadContext context) {
return context.runtime.newString(element.mriStyleString());
return RubyString.newString(context.runtime, element.mriStyleString());
}

public static IRubyObject newLocationArray(Ruby runtime, RubyStackTraceElement[] elements) {
RubyArray ary = runtime.newArray(elements.length);
public static RubyArray newLocationArray(Ruby runtime, RubyStackTraceElement[] elements) {
return newLocationArray(runtime, elements, 0, elements.length);
}

public static RubyArray newLocationArray(Ruby runtime, RubyStackTraceElement[] elements,
final int offset, final int length) {
final RubyClass locationClass = runtime.getLocation();

for (RubyStackTraceElement element : elements) {
ary.append(new RubyThread.Location(runtime, runtime.getLocation(), element));
RubyArray ary = runtime.newArray(length);
for ( int i = offset; i < offset + length; i++ ) {
ary.append(new RubyThread.Location(runtime, locationClass, elements[i]));
}

return ary;
4 changes: 2 additions & 2 deletions core/src/main/java/org/jruby/exceptions/RaiseException.java
Original file line number Diff line number Diff line change
@@ -171,7 +171,7 @@ private static String buildMessage(Throwable exception) {

sb.append("Native Exception: '").append(exception.getClass()).append("'; ");
sb.append("Message: ").append(exception.getMessage()).append("; ");
sb.append("StackTrace: ").append(stackTrace.getBuffer().toString());
sb.append("StackTrace: ").append(stackTrace.getBuffer());

return sb.toString();
}
@@ -265,7 +265,7 @@ protected final void setException(RubyException newException, boolean nativeExce
public static StackTraceElement[] javaTraceFromRubyTrace(RubyStackTraceElement[] trace) {
StackTraceElement[] newTrace = new StackTraceElement[trace.length];
for (int i = 0; i < newTrace.length; i++) {
newTrace[i] = trace[i].getElement();
newTrace[i] = trace[i].asStackTraceElement();
}
return newTrace;
}
62 changes: 31 additions & 31 deletions core/src/main/java/org/jruby/internal/runtime/ThreadService.java
Original file line number Diff line number Diff line change
@@ -15,7 +15,7 @@
* Copyright (C) 2004 Charles O Nutter <headius@headius.com>
* Copyright (C) 2004 Stefan Matthias Aust <sma@3plus4.de>
* Copyright (C) 2006 Miguel Covarrubias <mlcovarrubias@gmail.com>
*
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
@@ -105,7 +105,7 @@
* <ul>
*/
public class ThreadService {
private Ruby runtime;
private final Ruby runtime;
/**
* A hard reference to the "main" context, so we always have one waiting for
* "main" thread execution.
@@ -119,7 +119,7 @@ public class ThreadService {
* through ThreadContext instances every time a Java thread enters and exits
* Ruby space.
*/
private ThreadLocal<SoftReference<ThreadContext>> localContext;
private final ThreadLocal<SoftReference<ThreadContext>> localContext;

/**
* The Java thread group into which we register all Ruby threads. This is
@@ -141,10 +141,10 @@ public class ThreadService {
* we don't need to be polling for cross-thread events.
*/
private volatile boolean polling = false;

private final ReentrantLock criticalLock = new ReentrantLock();

public ThreadService(Ruby runtime) {
public ThreadService(final Ruby runtime) {
this.runtime = runtime;
this.localContext = new ThreadLocal<SoftReference<ThreadContext>>();

@@ -176,9 +176,9 @@ public void initMainThread() {
* not be immediately available. This method should be used sparingly, and
* if it is possible to pass ThreadContext on the argument list, it is
* preferable.
*
*
* <b>Description of behavior</b>
*
*
* The threadlocal does not actually contain the ThreadContext directly;
* instead, it contains a SoftReference that holds the ThreadContext. This
* is to allow new threads to enter the system and execute Ruby code with
@@ -187,24 +187,24 @@ public void initMainThread() {
* WeakReference is collected too quickly, resulting in very expensive
* ThreadContext churn (and this originally lead to JRUBY-2261's leak of
* adopted RubyThread instances).
*
*
* @return The ThreadContext instance for the current thread, or a new one
* if none has previously been created or the old ThreadContext has been
* collected.
*/
public ThreadContext getCurrentContext() {
SoftReference sr = null;
public final ThreadContext getCurrentContext() {
SoftReference<ThreadContext> ref;
ThreadContext context = null;

while (context == null) {
// loop until a context is available, to clean up softrefs that might have been collected
if ((sr = (SoftReference)localContext.get()) == null) {
sr = adoptCurrentThread();
context = (ThreadContext)sr.get();
if ((ref = localContext.get()) == null) {
ref = adoptCurrentThread();
context = ref.get();
} else {
context = (ThreadContext)sr.get();
context = ref.get();
}

// context is null, wipe out the SoftReference (this could be done with a reference queue)
if (context == null) {
localContext.set(null);
@@ -217,16 +217,16 @@ public ThreadContext getCurrentContext() {
/*
* Used only for Fiber context management
*/
public void setCurrentContext(ThreadContext context) {
public final void setCurrentContext(ThreadContext context) {
localContext.set(new SoftReference<ThreadContext>(context));
}
private SoftReference adoptCurrentThread() {

private SoftReference<ThreadContext> adoptCurrentThread() {
Thread current = Thread.currentThread();

RubyThread.adopt(runtime.getThread(), current);
return (SoftReference) localContext.get();

return localContext.get();
}

public RubyThread getMainThread() {
@@ -241,17 +241,17 @@ public void setMainThread(Thread thread, RubyThread rubyThread) {
public boolean getPolling() {
return polling;
}

public synchronized RubyThread[] getActiveRubyThreads() {
// all threads in ruby thread group plus main thread

synchronized(rubyThreadMap) {
List<RubyThread> rtList = new ArrayList<RubyThread>(rubyThreadMap.size());

for (Map.Entry<Object, RubyThread> entry : rubyThreadMap.entrySet()) {
Object key = entry.getKey();
if (key == null) continue;

if (key instanceof Thread) {
Thread t = (Thread)key;

@@ -263,13 +263,13 @@ public synchronized RubyThread[] getActiveRubyThreads() {
// future is done or cancelled, skip it
if (f.isDone() || f.isCancelled()) continue;
}

rtList.add(entry.getValue());
}

RubyThread[] rubyThreads = new RubyThread[rtList.size()];
rtList.toArray(rubyThreads);

return rubyThreads;
}
}
@@ -284,7 +284,7 @@ public ThreadContext getThreadContextForThread(RubyThread thread) {

public synchronized ThreadContext registerNewThread(RubyThread thread) {
ThreadContext context = ThreadContext.newContext(runtime);
localContext.set(new SoftReference(context));
localContext.set(new SoftReference<ThreadContext>(context));
context.setThread(thread);
ThreadFiber.initRootFiber(context); // may be overwritten by fiber
return context;
@@ -299,14 +299,14 @@ public synchronized void dissociateThread(Object threadOrFuture) {
rubyThreadMap.remove(threadOrFuture);
if (rubyThreadMap.size() <= 1) polling = false;
}

public synchronized void unregisterThread(RubyThread thread) {
rubyThreadMap.remove(Thread.currentThread());
getCurrentContext().setThread(null);
localContext.set(null);
if (rubyThreadMap.size() >= 0) polling = false;
}

public void setCritical(boolean critical) {
if (critical && !criticalLock.isHeldByCurrentThread()) {
acquireCritical();
@@ -322,7 +322,7 @@ private void acquireCritical() {
private void releaseCritical() {
criticalLock.unlock();
}

public boolean getCritical() {
return criticalLock.isHeldByCurrentThread();
}
Loading