Skip to content

Commit 7393f31

Browse files
committed
Merge branch 'master' into test-hypernugget
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
2 parents 719d996 + c38ac67 commit 7393f31

File tree

432 files changed

+2914
-2346
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

432 files changed

+2914
-2346
lines changed

.travis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ env:
2424
matrix:
2525
- PHASE='-Ptest'
2626
- PHASE='-Prake -Dtask=test:jruby'
27+
- PHASE='-Prake -Dtask=test:jruby:jit'
2728
- PHASE='-Prake -Dtask=test:mri'
2829
- PHASE='-Prake -Dtask=test:mri:jit'
2930
- PHASE='-Prake -Dtask=test:slow_suites'

core/src/main/java/org/jruby/internal/runtime/methods/InterpretedIRBodyMethod.java

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,16 +35,44 @@ public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule claz
3535
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, Block block) {
3636
if (IRRuntimeHelpers.isDebug()) doDebug();
3737

38+
return callInternal(context, self, clazz, name, block);
39+
}
40+
41+
protected IRubyObject callInternal(ThreadContext context, IRubyObject self, RubyModule clazz, String name, Block block) {
3842
InterpreterContext ic = ensureInstrsReady();
39-
if (ic.hasExplicitCallProtocol()) {
40-
return ic.engine.interpret(context, self, ic, getImplementationClass().getMethodLocation(), name, block, null);
41-
} else {
42-
try {
43-
pre(ic, context, self, name, block, getImplementationClass());
44-
return ic.engine.interpret(context, self, ic, getImplementationClass().getMethodLocation(), name, block, null);
45-
} finally {
46-
post(ic, context);
43+
44+
if (!ic.hasExplicitCallProtocol()) this.pre(ic, context, self, name, block, getImplementationClass());
45+
46+
try {
47+
switch (method.getScopeType()) {
48+
case MODULE_BODY: return INTERPRET_MODULE(ic, context, self, clazz, method.getName(), block);
49+
case CLASS_BODY: return INTERPRET_CLASS(ic, context, self, clazz, method.getName(), block);
50+
case METACLASS_BODY: return INTERPRET_METACLASS(ic, context, self, clazz, "singleton class", block);
51+
default: throw new RuntimeException("invalid body method type: " + method);
4752
}
53+
} finally {
54+
if (!ic.hasExplicitCallProtocol()) this.post(ic, context);
55+
}
56+
}
57+
58+
private IRubyObject INTERPRET_METACLASS(InterpreterContext ic, ThreadContext context, IRubyObject self, RubyModule clazz, String name, Block block) {
59+
return interpretWithBacktrace(ic, context, self, name, block);
60+
}
61+
62+
private IRubyObject INTERPRET_MODULE(InterpreterContext ic, ThreadContext context, IRubyObject self, RubyModule clazz, String name, Block block) {
63+
return interpretWithBacktrace(ic, context, self, name, block);
64+
}
65+
66+
private IRubyObject INTERPRET_CLASS(InterpreterContext ic, ThreadContext context, IRubyObject self, RubyModule clazz, String name, Block block) {
67+
return interpretWithBacktrace(ic, context, self, name, block);
68+
}
69+
70+
private IRubyObject interpretWithBacktrace(InterpreterContext ic, ThreadContext context, IRubyObject self, String name, Block block) {
71+
try {
72+
ThreadContext.pushBacktrace(context, name, ic.getFileName(), context.getLine());
73+
return ic.engine.interpret(context, self, ic, getImplementationClass().getMethodLocation(), name, block, null);
74+
} finally {
75+
ThreadContext.popBacktrace(context);
4876
}
4977
}
5078

core/src/main/java/org/jruby/internal/runtime/methods/InterpretedIRMetaClassBody.java

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ public InterpretedIRMetaClassBody(IRScope metaClassBody, RubyModule implementati
1414
super(metaClassBody, implementationClass);
1515
}
1616

17+
@Override
1718
protected void post(InterpreterContext ic, ThreadContext context) {
1819
// update call stacks (pop: ..)
1920
context.popFrame();
@@ -22,7 +23,8 @@ protected void post(InterpreterContext ic, ThreadContext context) {
2223
}
2324
}
2425

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

3739
@Override
3840
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, Block block) {
39-
InterpreterContext ic = ensureInstrsReady();
40-
4141
if (IRRuntimeHelpers.isDebug()) doDebug();
4242

43-
if (ic.hasExplicitCallProtocol()) {
44-
return ic.engine.interpret(context, self, ic, getImplementationClass().getMethodLocation(), name, block, null);
45-
} else {
46-
try {
47-
pre(ic, context, self, name, block);
48-
49-
return ic.engine.interpret(context, self, ic, getImplementationClass().getMethodLocation(), name, block, null);
50-
} finally {
51-
post(ic, context);
52-
}
53-
}
43+
return callInternal(context, self, clazz, name, block);
5444
}
5545
}

core/src/main/java/org/jruby/ir/Compiler.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ protected ScriptAndCode execute(final Ruby runtime, final IRScriptBody scope, Cl
5555
bytecode = visitor.compileToBytecode(scope);
5656
compiled = visitor.defineFromBytecode(scope, bytecode, classLoader);
5757

58-
Method compiledMethod = compiled.getMethod("__script__", ThreadContext.class,
58+
Method compiledMethod = compiled.getMethod("RUBY$script", ThreadContext.class,
5959
StaticScope.class, IRubyObject.class, IRubyObject[].class, Block.class, RubyModule.class, String.class);
6060
_compiledHandle = MethodHandles.publicLookup().unreflect(compiledMethod);
6161
} catch (NotCompilableException nce) {

core/src/main/java/org/jruby/ir/passes/LiveVariableAnalysis.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,6 @@
1919
import java.util.List;
2020

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

2724
@Override

core/src/main/java/org/jruby/ir/targets/JVMVisitor.java

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -220,26 +220,29 @@ public static final Signature signatureFor(IRScope method, boolean aritySplit) {
220220
.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);
221221

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

226-
emitScope(script, "__script__", signatureFor(script, false), false);
228+
emitScope(script, name, signatureFor(script, false), false);
227229

228230
jvm.cls().visitEnd();
229231
jvm.popclass();
230232
}
231233

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

235237
emitWithSignatures(method, name);
236238
}
237239

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

242-
emitWithSignatures(method, "__script__");
245+
emitWithSignatures(method, name);
243246

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

262265
public Handle emitModuleBodyJIT(IRModuleBody method) {
263-
String baseName = method.getName() + "_" + methodIndex++;
264-
String name;
266+
String name = JavaNameMangler.encodeScopeForBacktrace(method) + "$" + methodIndex++;
265267

266-
if (baseName.indexOf("DUMMY_MC") != -1) {
267-
name = "METACLASS_" + methodIndex++;
268-
} else {
269-
name = baseName + "_" + methodIndex++;
270-
}
271268
String clsName = jvm.scriptToClass(method.getFileName());
272269
jvm.pushscript(clsName, method.getFileName());
273270

274271
Signature signature = signatureFor(method, false);
275-
emitScope(method, "__script__", signature, false);
272+
emitScope(method, name, signature, false);
276273

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

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

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

296293
emitScope(closure, name, CLOSURE_SIGNATURE, false);
297294

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

301298
public Handle emitModuleBody(IRModuleBody method) {
302-
String baseName = method.getName() + "_" + methodIndex++;
303-
String name;
304-
305-
if (baseName.indexOf("DUMMY_MC") != -1) {
306-
name = "METACLASS_" + methodIndex++;
307-
} else {
308-
name = baseName + "_" + methodIndex++;
309-
}
299+
String name = JavaNameMangler.encodeScopeForBacktrace(method) + "$" + methodIndex++;
310300

311301
Signature signature = signatureFor(method, false);
312302
emitScope(method, name, signature, false);

core/src/main/java/org/jruby/runtime/backtrace/BacktraceData.java

Lines changed: 23 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -71,63 +71,19 @@ private RubyStackTraceElement[] transformBacktrace(Map<String, Map<String, Strin
7171
// Don't process .java files
7272
if (!filename.endsWith(".java")) {
7373

74-
boolean compiled = false;
75-
int index = -1;
76-
77-
// Check for compiled name markers
78-
// FIXME: Formalize jitted method structure so this isn't quite as hacky
79-
if (className.startsWith(JITCompiler.RUBY_JIT_PREFIX)) {
80-
81-
// JIT-compiled code
82-
compiled = true;
83-
84-
// pull out and demangle the method name
85-
String tmpClassName = className;
86-
int start = JITCompiler.RUBY_JIT_PREFIX.length() + 1;
87-
int hash = tmpClassName.indexOf(JITCompiler.CLASS_METHOD_DELIMITER, start);
88-
int end = tmpClassName.lastIndexOf("_");
89-
if( hash != -1 ) { // TODO in case the class file was loaded by jit codeCache. Is this right
90-
className = tmpClassName.substring(start, hash);
91-
}
92-
methodName = tmpClassName.substring(hash + JITCompiler.CLASS_METHOD_DELIMITER.length(), end);
93-
94-
} else if ((index = methodName.indexOf("$RUBY$")) >= 0) {
74+
String decodedName = JavaNameMangler.decodeMethodForBacktrace(methodName);
9575

96-
// AOT-compiled code
97-
compiled = true;
76+
if (decodedName != null) {
77+
// construct Ruby trace element
78+
RubyStackTraceElement rubyElement = new RubyStackTraceElement(className, decodedName, filename, line, false);
9879

99-
// pull out and demangle the method name
100-
index += "$RUBY$".length();
101-
if (methodName.indexOf("SYNTHETIC", index) == index) {
102-
methodName = methodName.substring(index + "SYNTHETIC".length());
103-
} else {
104-
methodName = methodName.substring(index);
105-
}
106-
107-
}
108-
109-
// demangle any JVM-prohibited names
110-
methodName = JavaNameMangler.demangleMethodName(methodName);
111-
112-
// root body gets named (root)
113-
if (methodName.equals("__file__")) methodName = "(root)";
114-
115-
// construct Ruby trace element
116-
RubyStackTraceElement rubyElement = new RubyStackTraceElement(className, methodName, filename, line, false);
117-
118-
// add duplicate if masking native and previous frame was native (Kernel#caller)
119-
if (maskNative && dupFrame) {
120-
dupFrame = false;
121-
trace.add(new RubyStackTraceElement(className, dupFrameName, filename, line, false));
122-
}
123-
trace.add(rubyElement);
124-
125-
if (compiled) {
126-
// if it's a synthetic call, gobble up parent calls
127-
// TODO: need to formalize this better
128-
while (element.getMethodName().contains("$RUBY$SYNTHETIC") && ++i < javaTrace.length) {
129-
element = javaTrace[i];
80+
// add duplicate if masking native and previous frame was native (Kernel#caller)
81+
if (maskNative && dupFrame) {
82+
dupFrame = false;
83+
trace.add(new RubyStackTraceElement(className, dupFrameName, filename, line, false));
13084
}
85+
trace.add(rubyElement);
86+
continue;
13187
}
13288
}
13389
}
@@ -169,8 +125,20 @@ private RubyStackTraceElement[] transformBacktrace(Map<String, Map<String, Strin
169125
// pop interpreter frame
170126
BacktraceElement rubyFrame = rubyTrace[rubyFrameIndex--];
171127

128+
FrameType frameType = FrameType.INTERPRETED_FRAMES.get(methodName);
129+
172130
// construct Ruby trace element
173-
RubyStackTraceElement rubyElement = new RubyStackTraceElement("RUBY", rubyFrame.method, rubyFrame.filename, rubyFrame.line + 1, false);
131+
String newName = rubyFrame.method;
132+
switch (frameType) {
133+
case METHOD: newName = rubyFrame.method; break;
134+
case BLOCK: newName = "block in " + rubyFrame.method; break;
135+
case CLASS: newName = "<class:" + rubyFrame.method + ">"; break;
136+
case MODULE: newName = "<module:" + rubyFrame.method + ">"; break;
137+
case METACLASS: newName = "singleton class"; break;
138+
case ROOT: newName = "<top>"; break;
139+
case EVAL: newName = "<eval>"; break;
140+
}
141+
RubyStackTraceElement rubyElement = new RubyStackTraceElement("RUBY", newName, rubyFrame.filename, rubyFrame.line + 1, false);
174142

175143
// dup if masking native and previous frame was native
176144
if (maskNative && dupFrame) {

core/src/main/java/org/jruby/runtime/backtrace/FrameType.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,29 @@
55
import java.util.Map;
66
import java.util.Set;
77

8+
import org.jruby.internal.runtime.methods.InterpretedIRBodyMethod;
9+
import org.jruby.internal.runtime.methods.InterpretedIRMetaClassBody;
810
import org.jruby.internal.runtime.methods.InterpretedIRMethod;
911
import org.jruby.internal.runtime.methods.MixedModeIRMethod;
1012
import org.jruby.ir.interpreter.Interpreter;
13+
import org.jruby.runtime.InterpretedIRBlockBody;
1114

1215
public enum FrameType {
13-
METHOD, BLOCK, EVAL, CLASS, ROOT;
16+
METHOD, BLOCK, EVAL, CLASS, MODULE, METACLASS, ROOT;
1417
public static final Set<String> INTERPRETED_CLASSES = new HashSet<String>();
1518
public static final Map<String, FrameType> INTERPRETED_FRAMES = new HashMap<String, FrameType>();
1619

1720
static {
1821
INTERPRETED_CLASSES.add(Interpreter.class.getName());
1922
INTERPRETED_CLASSES.add(MixedModeIRMethod.class.getName());
2023
INTERPRETED_CLASSES.add(InterpretedIRMethod.class.getName());
24+
INTERPRETED_CLASSES.add(InterpretedIRBodyMethod.class.getName());
2125

2226
INTERPRETED_FRAMES.put("INTERPRET_METHOD", FrameType.METHOD);
2327
INTERPRETED_FRAMES.put("INTERPRET_EVAL", FrameType.EVAL);
2428
INTERPRETED_FRAMES.put("INTERPRET_CLASS", FrameType.CLASS);
29+
INTERPRETED_FRAMES.put("INTERPRET_MODULE", FrameType.MODULE);
30+
INTERPRETED_FRAMES.put("INTERPRET_METACLASS", FrameType.METACLASS);
2531
INTERPRETED_FRAMES.put("INTERPRET_BLOCK", FrameType.BLOCK);
2632
INTERPRETED_FRAMES.put("INTERPRET_ROOT", FrameType.ROOT);
2733
}

core/src/main/java/org/jruby/util/JarCache.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,14 @@
2525
* The implementation pays attention to lastModified timestamp of the jar and will invalidate
2626
* the cache entry if jar has been updated since the snapshot calculation.
2727
* </p>
28+
*
29+
* ******************************************************************************************
30+
* DANGER DANGER DANGER DANGER DANGER DANGER DANGER DANGER DANGER DANGER DANGER DANGER DANGER
31+
* ******************************************************************************************
32+
*
33+
* The spec for this cache is disabled currently for #2655, because of last-modified time
34+
* oddities on CloudBees. Please be cautious modifying this code and make sure you run the
35+
* associated spec locally.
2836
*/
2937
class JarCache {
3038
static class JarIndex {

0 commit comments

Comments
 (0)