Skip to content

Commit

Permalink
Merge branch 'master' into test-hypernugget
Browse files Browse the repository at this point in the history
Conflicts:
	core/src/main/java/org/jruby/internal/runtime/methods/InterpretedIRBodyMethod.java
	core/src/main/java/org/jruby/internal/runtime/methods/InterpretedIRMetaClassBody.java
	core/src/main/java/org/jruby/ir/passes/LiveVariableAnalysis.java
  • Loading branch information
enebo committed Mar 8, 2015
2 parents 719d996 + c38ac67 commit 7393f31
Show file tree
Hide file tree
Showing 432 changed files with 2,914 additions and 2,346 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Expand Up @@ -24,6 +24,7 @@ env:
matrix:
- PHASE='-Ptest'
- PHASE='-Prake -Dtask=test:jruby'
- PHASE='-Prake -Dtask=test:jruby:jit'
- PHASE='-Prake -Dtask=test:mri'
- PHASE='-Prake -Dtask=test:mri:jit'
- PHASE='-Prake -Dtask=test:slow_suites'
Expand Down
Expand Up @@ -35,16 +35,44 @@ public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule claz
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, Block block) {
if (IRRuntimeHelpers.isDebug()) doDebug();

return callInternal(context, self, clazz, name, block);
}

protected IRubyObject callInternal(ThreadContext context, IRubyObject self, RubyModule clazz, String name, Block block) {
InterpreterContext ic = ensureInstrsReady();
if (ic.hasExplicitCallProtocol()) {
return ic.engine.interpret(context, self, ic, getImplementationClass().getMethodLocation(), name, block, null);
} else {
try {
pre(ic, context, self, name, block, getImplementationClass());
return ic.engine.interpret(context, self, ic, getImplementationClass().getMethodLocation(), name, block, null);
} finally {
post(ic, context);

if (!ic.hasExplicitCallProtocol()) this.pre(ic, context, self, name, block, getImplementationClass());

try {
switch (method.getScopeType()) {
case MODULE_BODY: return INTERPRET_MODULE(ic, context, self, clazz, method.getName(), block);
case CLASS_BODY: return INTERPRET_CLASS(ic, context, self, clazz, method.getName(), block);
case METACLASS_BODY: return INTERPRET_METACLASS(ic, context, self, clazz, "singleton class", block);
default: throw new RuntimeException("invalid body method type: " + method);
}
} finally {
if (!ic.hasExplicitCallProtocol()) this.post(ic, context);
}
}

private IRubyObject INTERPRET_METACLASS(InterpreterContext ic, ThreadContext context, IRubyObject self, RubyModule clazz, String name, Block block) {
return interpretWithBacktrace(ic, context, self, name, block);
}

private IRubyObject INTERPRET_MODULE(InterpreterContext ic, ThreadContext context, IRubyObject self, RubyModule clazz, String name, Block block) {
return interpretWithBacktrace(ic, context, self, name, block);
}

private IRubyObject INTERPRET_CLASS(InterpreterContext ic, ThreadContext context, IRubyObject self, RubyModule clazz, String name, Block block) {
return interpretWithBacktrace(ic, context, self, name, block);
}

private IRubyObject interpretWithBacktrace(InterpreterContext ic, ThreadContext context, IRubyObject self, String name, Block block) {
try {
ThreadContext.pushBacktrace(context, name, ic.getFileName(), context.getLine());
return ic.engine.interpret(context, self, ic, getImplementationClass().getMethodLocation(), name, block, null);
} finally {
ThreadContext.popBacktrace(context);
}
}

Expand Down
Expand Up @@ -14,6 +14,7 @@ public InterpretedIRMetaClassBody(IRScope metaClassBody, RubyModule implementati
super(metaClassBody, implementationClass);
}

@Override
protected void post(InterpreterContext ic, ThreadContext context) {
// update call stacks (pop: ..)
context.popFrame();
Expand All @@ -22,7 +23,8 @@ protected void post(InterpreterContext ic, ThreadContext context) {
}
}

protected void pre(InterpreterContext ic, ThreadContext context, IRubyObject self, String name, Block block) {
@Override
protected void pre(InterpreterContext ic, ThreadContext context, IRubyObject self, String name, Block block, RubyModule implClass) {
// update call stacks (push: frame, class, scope, etc.)
context.preMethodFrameOnly(getImplementationClass(), name, self, block);
if (ic.pushNewDynScope()) {
Expand All @@ -36,20 +38,8 @@ protected void pre(InterpreterContext ic, ThreadContext context, IRubyObject sel

@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, Block block) {
InterpreterContext ic = ensureInstrsReady();

if (IRRuntimeHelpers.isDebug()) doDebug();

if (ic.hasExplicitCallProtocol()) {
return ic.engine.interpret(context, self, ic, getImplementationClass().getMethodLocation(), name, block, null);
} else {
try {
pre(ic, context, self, name, block);

return ic.engine.interpret(context, self, ic, getImplementationClass().getMethodLocation(), name, block, null);
} finally {
post(ic, context);
}
}
return callInternal(context, self, clazz, name, block);
}
}
2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/ir/Compiler.java
Expand Up @@ -55,7 +55,7 @@ protected ScriptAndCode execute(final Ruby runtime, final IRScriptBody scope, Cl
bytecode = visitor.compileToBytecode(scope);
compiled = visitor.defineFromBytecode(scope, bytecode, classLoader);

Method compiledMethod = compiled.getMethod("__script__", ThreadContext.class,
Method compiledMethod = compiled.getMethod("RUBY$script", ThreadContext.class,
StaticScope.class, IRubyObject.class, IRubyObject[].class, Block.class, RubyModule.class, String.class);
_compiledHandle = MethodHandles.publicLookup().unreflect(compiledMethod);
} catch (NotCompilableException nce) {
Expand Down
Expand Up @@ -19,9 +19,6 @@
import java.util.List;

public class LiveVariableAnalysis extends CompilerPass {
// For LVA to run independently on closures (without parent scopes), it needs info about whether
// dyn scopes have been eliminated or not (see access to IRFlags.DYNSCOPE_ELIMINATED below).
// So, making that dependency explicit.
public static List<Class<? extends CompilerPass>> DEPENDENCIES = Arrays.<Class<? extends CompilerPass>>asList(OptimizeDynScopesPass.class);

@Override
Expand Down
30 changes: 10 additions & 20 deletions core/src/main/java/org/jruby/ir/targets/JVMVisitor.java
Expand Up @@ -220,26 +220,29 @@ public static final Signature signatureFor(IRScope method, boolean aritySplit) {
.appendArgs(new String[]{"context", "scope", "self", "args", "block", "superName", "type"}, ThreadContext.class, StaticScope.class, IRubyObject.class, IRubyObject[].class, Block.class, String.class, Block.Type.class);

public void emitScriptBody(IRScriptBody script) {
// Note: no index attached because there should be at most one script body per .class
String name = JavaNameMangler.encodeScopeForBacktrace(script);
String clsName = jvm.scriptToClass(script.getFileName());
jvm.pushscript(clsName, script.getFileName());

emitScope(script, "__script__", signatureFor(script, false), false);
emitScope(script, name, signatureFor(script, false), false);

jvm.cls().visitEnd();
jvm.popclass();
}

public void emitMethod(IRMethod method) {
String name = JavaNameMangler.mangleMethodName(method.getName() + "_" + methodIndex++);
String name = JavaNameMangler.encodeScopeForBacktrace(method) + "$" + methodIndex++;

emitWithSignatures(method, name);
}

public void emitMethodJIT(IRMethod method) {
String clsName = jvm.scriptToClass(method.getFileName());
String name = JavaNameMangler.encodeScopeForBacktrace(method) + "$" + methodIndex++;
jvm.pushscript(clsName, method.getFileName());

emitWithSignatures(method, "__script__");
emitWithSignatures(method, name);

jvm.cls().visitEnd();
jvm.popclass();
Expand All @@ -260,19 +263,13 @@ private void emitWithSignatures(IRMethod method, String name) {
}

public Handle emitModuleBodyJIT(IRModuleBody method) {
String baseName = method.getName() + "_" + methodIndex++;
String name;
String name = JavaNameMangler.encodeScopeForBacktrace(method) + "$" + methodIndex++;

if (baseName.indexOf("DUMMY_MC") != -1) {
name = "METACLASS_" + methodIndex++;
} else {
name = baseName + "_" + methodIndex++;
}
String clsName = jvm.scriptToClass(method.getFileName());
jvm.pushscript(clsName, method.getFileName());

Signature signature = signatureFor(method, false);
emitScope(method, "__script__", signature, false);
emitScope(method, name, signature, false);

Handle handle = new Handle(Opcodes.H_INVOKESTATIC, jvm.clsData().clsName, name, sig(signature.type().returnType(), signature.type().parameterArray()));

Expand All @@ -291,22 +288,15 @@ private void emitClosures(IRScope s) {

public Handle emitClosure(IRClosure closure) {
/* Compile the closure like a method */
String name = JavaNameMangler.mangleMethodName(closure.getName() + "__" + closure.getLexicalParent().getName() + "_" + methodIndex++);
String name = JavaNameMangler.encodeScopeForBacktrace(closure) + "$" + methodIndex++;

emitScope(closure, name, CLOSURE_SIGNATURE, false);

return new Handle(Opcodes.H_INVOKESTATIC, jvm.clsData().clsName, name, sig(CLOSURE_SIGNATURE.type().returnType(), CLOSURE_SIGNATURE.type().parameterArray()));
}

public Handle emitModuleBody(IRModuleBody method) {
String baseName = method.getName() + "_" + methodIndex++;
String name;

if (baseName.indexOf("DUMMY_MC") != -1) {
name = "METACLASS_" + methodIndex++;
} else {
name = baseName + "_" + methodIndex++;
}
String name = JavaNameMangler.encodeScopeForBacktrace(method) + "$" + methodIndex++;

Signature signature = signatureFor(method, false);
emitScope(method, name, signature, false);
Expand Down
78 changes: 23 additions & 55 deletions core/src/main/java/org/jruby/runtime/backtrace/BacktraceData.java
Expand Up @@ -71,63 +71,19 @@ private RubyStackTraceElement[] transformBacktrace(Map<String, Map<String, Strin
// Don't process .java files
if (!filename.endsWith(".java")) {

boolean compiled = false;
int index = -1;

// Check for compiled name markers
// FIXME: Formalize jitted method structure so this isn't quite as hacky
if (className.startsWith(JITCompiler.RUBY_JIT_PREFIX)) {

// JIT-compiled code
compiled = true;

// pull out and demangle the method name
String tmpClassName = className;
int start = JITCompiler.RUBY_JIT_PREFIX.length() + 1;
int hash = tmpClassName.indexOf(JITCompiler.CLASS_METHOD_DELIMITER, start);
int end = tmpClassName.lastIndexOf("_");
if( hash != -1 ) { // TODO in case the class file was loaded by jit codeCache. Is this right
className = tmpClassName.substring(start, hash);
}
methodName = tmpClassName.substring(hash + JITCompiler.CLASS_METHOD_DELIMITER.length(), end);

} else if ((index = methodName.indexOf("$RUBY$")) >= 0) {
String decodedName = JavaNameMangler.decodeMethodForBacktrace(methodName);

// AOT-compiled code
compiled = true;
if (decodedName != null) {
// construct Ruby trace element
RubyStackTraceElement rubyElement = new RubyStackTraceElement(className, decodedName, filename, line, false);

// pull out and demangle the method name
index += "$RUBY$".length();
if (methodName.indexOf("SYNTHETIC", index) == index) {
methodName = methodName.substring(index + "SYNTHETIC".length());
} else {
methodName = methodName.substring(index);
}

}

// demangle any JVM-prohibited names
methodName = JavaNameMangler.demangleMethodName(methodName);

// root body gets named (root)
if (methodName.equals("__file__")) methodName = "(root)";

// construct Ruby trace element
RubyStackTraceElement rubyElement = new RubyStackTraceElement(className, methodName, filename, line, false);

// add duplicate if masking native and previous frame was native (Kernel#caller)
if (maskNative && dupFrame) {
dupFrame = false;
trace.add(new RubyStackTraceElement(className, dupFrameName, filename, line, false));
}
trace.add(rubyElement);

if (compiled) {
// if it's a synthetic call, gobble up parent calls
// TODO: need to formalize this better
while (element.getMethodName().contains("$RUBY$SYNTHETIC") && ++i < javaTrace.length) {
element = javaTrace[i];
// add duplicate if masking native and previous frame was native (Kernel#caller)
if (maskNative && dupFrame) {
dupFrame = false;
trace.add(new RubyStackTraceElement(className, dupFrameName, filename, line, false));
}
trace.add(rubyElement);
continue;
}
}
}
Expand Down Expand Up @@ -169,8 +125,20 @@ private RubyStackTraceElement[] transformBacktrace(Map<String, Map<String, Strin
// pop interpreter frame
BacktraceElement rubyFrame = rubyTrace[rubyFrameIndex--];

FrameType frameType = FrameType.INTERPRETED_FRAMES.get(methodName);

// construct Ruby trace element
RubyStackTraceElement rubyElement = new RubyStackTraceElement("RUBY", rubyFrame.method, rubyFrame.filename, rubyFrame.line + 1, false);
String newName = rubyFrame.method;
switch (frameType) {
case METHOD: newName = rubyFrame.method; break;
case BLOCK: newName = "block in " + rubyFrame.method; break;
case CLASS: newName = "<class:" + rubyFrame.method + ">"; break;
case MODULE: newName = "<module:" + rubyFrame.method + ">"; break;
case METACLASS: newName = "singleton class"; break;
case ROOT: newName = "<top>"; break;
case EVAL: newName = "<eval>"; break;
}
RubyStackTraceElement rubyElement = new RubyStackTraceElement("RUBY", newName, rubyFrame.filename, rubyFrame.line + 1, false);

// dup if masking native and previous frame was native
if (maskNative && dupFrame) {
Expand Down
Expand Up @@ -5,23 +5,29 @@
import java.util.Map;
import java.util.Set;

import org.jruby.internal.runtime.methods.InterpretedIRBodyMethod;
import org.jruby.internal.runtime.methods.InterpretedIRMetaClassBody;
import org.jruby.internal.runtime.methods.InterpretedIRMethod;
import org.jruby.internal.runtime.methods.MixedModeIRMethod;
import org.jruby.ir.interpreter.Interpreter;
import org.jruby.runtime.InterpretedIRBlockBody;

public enum FrameType {
METHOD, BLOCK, EVAL, CLASS, ROOT;
METHOD, BLOCK, EVAL, CLASS, MODULE, METACLASS, ROOT;
public static final Set<String> INTERPRETED_CLASSES = new HashSet<String>();
public static final Map<String, FrameType> INTERPRETED_FRAMES = new HashMap<String, FrameType>();

static {
INTERPRETED_CLASSES.add(Interpreter.class.getName());
INTERPRETED_CLASSES.add(MixedModeIRMethod.class.getName());
INTERPRETED_CLASSES.add(InterpretedIRMethod.class.getName());
INTERPRETED_CLASSES.add(InterpretedIRBodyMethod.class.getName());

INTERPRETED_FRAMES.put("INTERPRET_METHOD", FrameType.METHOD);
INTERPRETED_FRAMES.put("INTERPRET_EVAL", FrameType.EVAL);
INTERPRETED_FRAMES.put("INTERPRET_CLASS", FrameType.CLASS);
INTERPRETED_FRAMES.put("INTERPRET_MODULE", FrameType.MODULE);
INTERPRETED_FRAMES.put("INTERPRET_METACLASS", FrameType.METACLASS);
INTERPRETED_FRAMES.put("INTERPRET_BLOCK", FrameType.BLOCK);
INTERPRETED_FRAMES.put("INTERPRET_ROOT", FrameType.ROOT);
}
Expand Down
8 changes: 8 additions & 0 deletions core/src/main/java/org/jruby/util/JarCache.java
Expand Up @@ -25,6 +25,14 @@
* The implementation pays attention to lastModified timestamp of the jar and will invalidate
* the cache entry if jar has been updated since the snapshot calculation.
* </p>
*
* ******************************************************************************************
* DANGER DANGER DANGER DANGER DANGER DANGER DANGER DANGER DANGER DANGER DANGER DANGER DANGER
* ******************************************************************************************
*
* The spec for this cache is disabled currently for #2655, because of last-modified time
* oddities on CloudBees. Please be cautious modifying this code and make sure you run the
* associated spec locally.
*/
class JarCache {
static class JarIndex {
Expand Down

0 comments on commit 7393f31

Please sign in to comment.