Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@enebo
Created May 16, 2019 21:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save enebo/c58e6408b5e1fa965a0618029a5da43b to your computer and use it in GitHub Desktop.
Save enebo/c58e6408b5e1fa965a0618029a5da43b to your computer and use it in GitHub Desktop.
diff --git a/core/src/main/java/org/jruby/ir/IRBuilder.java b/core/src/main/java/org/jruby/ir/IRBuilder.java
index 9208a821d4..ae31f44d87 100644
--- a/core/src/main/java/org/jruby/ir/IRBuilder.java
+++ b/core/src/main/java/org/jruby/ir/IRBuilder.java
@@ -1392,11 +1392,10 @@ public class IRBuilder {
RubySymbol className = cpath.getName();
Operand container = getContainerFromCPath(cpath);
IRClassBody body = new IRClassBody(manager, scope, className, classNode.getLine(), classNode.getScope());
- Variable classVar = addResultInstr(new DefineClassInstr(createTemporaryVariable(), body, container, superClass));
+ Variable bodyResult = addResultInstr(new DefineClassInstr(createTemporaryVariable(), body, container, superClass));
- Variable processBodyResult = addResultInstr(new ProcessModuleBodyInstr(createTemporaryVariable(), classVar, NullBlock.INSTANCE));
newIRBuilder(manager, body).buildModuleOrClassBody(classNode.getBodyNode(), classNode.getLine(), classNode.getEndLine());
- return processBodyResult;
+ return bodyResult;
}
// class Foo; class << self; end; end
@@ -3188,11 +3187,10 @@ public class IRBuilder {
RubySymbol moduleName = cpath.getName();
Operand container = getContainerFromCPath(cpath);
IRModuleBody body = new IRModuleBody(manager, scope, moduleName, moduleNode.getLine(), moduleNode.getScope());
- Variable moduleVar = addResultInstr(new DefineModuleInstr(createTemporaryVariable(), body, container));
+ Variable bodyResult = addResultInstr(new DefineModuleInstr(createTemporaryVariable(), body, container));
- Variable processBodyResult = addResultInstr(new ProcessModuleBodyInstr(createTemporaryVariable(), moduleVar, NullBlock.INSTANCE));
newIRBuilder(manager, body).buildModuleOrClassBody(moduleNode.getBodyNode(), moduleNode.getLine(), moduleNode.getEndLine());
- return processBodyResult;
+ return bodyResult;
}
public Operand buildNext(final NextNode nextNode) {
diff --git a/core/src/main/java/org/jruby/ir/IRClassBody.java b/core/src/main/java/org/jruby/ir/IRClassBody.java
index fb4f0ddcc7..0a4f56ac55 100644
--- a/core/src/main/java/org/jruby/ir/IRClassBody.java
+++ b/core/src/main/java/org/jruby/ir/IRClassBody.java
@@ -2,7 +2,6 @@ package org.jruby.ir;
import org.jruby.RubySymbol;
import org.jruby.parser.StaticScope;
-import org.jruby.util.ByteList;
public class IRClassBody extends IRModuleBody {
public IRClassBody(IRManager manager, IRScope lexicalParent, RubySymbol name, int lineNumber, StaticScope scope) {
diff --git a/core/src/main/java/org/jruby/ir/IRModuleBody.java b/core/src/main/java/org/jruby/ir/IRModuleBody.java
index 4020864b1b..fb8257429c 100644
--- a/core/src/main/java/org/jruby/ir/IRModuleBody.java
+++ b/core/src/main/java/org/jruby/ir/IRModuleBody.java
@@ -26,4 +26,13 @@ public class IRModuleBody extends IRScope {
public boolean isModuleBody() {
return true;
}
+
+ @Override
+ public void cleanupAfterExecution() {
+ if (getClosures().isEmpty() && !(getLexicalParent() instanceof IRClosure)) {
+ interpreterContext = null;
+ fullInterpreterContext = null;
+ localVars = null;
+ }
+ }
}
diff --git a/core/src/main/java/org/jruby/ir/IRScope.java b/core/src/main/java/org/jruby/ir/IRScope.java
index 29b5427789..39c87a3069 100644
--- a/core/src/main/java/org/jruby/ir/IRScope.java
+++ b/core/src/main/java/org/jruby/ir/IRScope.java
@@ -1400,4 +1400,16 @@ public abstract class IRScope implements ParseResult {
}
}
}
+
+ /**
+ * We are done with execution of this scope and we can cleanup some amount of things
+ * in this scope which will no longer be used. Sub-classes will be the deciders of what
+ * is no longer needed. An example, to illustrate the complexity of cleanup: A class with
+ * no nested closures can remove any ICs created and can remove some other infomrational
+ * data structures like allocated variables unless closures do exist and then the ICs must
+ * stay for when closures JIT.
+ */
+ public void cleanupAfterExecution() {
+
+ }
}
diff --git a/core/src/main/java/org/jruby/ir/IRScriptBody.java b/core/src/main/java/org/jruby/ir/IRScriptBody.java
index 057ceee95c..9c6490d765 100644
--- a/core/src/main/java/org/jruby/ir/IRScriptBody.java
+++ b/core/src/main/java/org/jruby/ir/IRScriptBody.java
@@ -96,4 +96,13 @@ public class IRScriptBody extends IRScope {
public String getFile() {
return fileName.asJavaString();
}
+
+ @Override
+ public void cleanupAfterExecution() {
+ if (getClosures().isEmpty()) {
+ interpreterContext = null;
+ fullInterpreterContext = null;
+ localVars = null;
+ }
+ }
}
diff --git a/core/src/main/java/org/jruby/ir/instructions/DefineClassInstr.java b/core/src/main/java/org/jruby/ir/instructions/DefineClassInstr.java
index 0743adbd79..45d004fb99 100644
--- a/core/src/main/java/org/jruby/ir/instructions/DefineClassInstr.java
+++ b/core/src/main/java/org/jruby/ir/instructions/DefineClassInstr.java
@@ -1,8 +1,12 @@
package org.jruby.ir.instructions;
+import org.jruby.RubyClass;
+import org.jruby.RubyModule;
+import org.jruby.internal.runtime.methods.InterpretedIRBodyMethod;
import org.jruby.ir.IRClassBody;
import org.jruby.ir.IRVisitor;
import org.jruby.ir.Operation;
+import org.jruby.ir.interpreter.InterpreterContext;
import org.jruby.ir.operands.Operand;
import org.jruby.ir.operands.UndefinedValue;
import org.jruby.ir.operands.Variable;
@@ -11,23 +15,24 @@ import org.jruby.ir.persistence.IRWriterEncoder;
import org.jruby.ir.runtime.IRRuntimeHelpers;
import org.jruby.ir.transformations.inlining.CloneInfo;
import org.jruby.parser.StaticScope;
+import org.jruby.runtime.Block;
import org.jruby.runtime.DynamicScope;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
public class DefineClassInstr extends TwoOperandResultBaseInstr implements FixedArityInstr {
- private final IRClassBody newIRClassBody;
+ private final IRClassBody body;
- public DefineClassInstr(Variable result, IRClassBody newIRClassBody, Operand container, Operand superClass) {
+ public DefineClassInstr(Variable result, IRClassBody body, Operand container, Operand superClass) {
super(Operation.DEF_CLASS, result, container, superClass == null ? UndefinedValue.UNDEFINED : superClass);
assert result != null: "DefineClassInstr result is null";
- this.newIRClassBody = newIRClassBody;
+ this.body = body;
}
public IRClassBody getNewIRClassBody() {
- return newIRClassBody;
+ return body;
}
public Operand getContainer() {
@@ -40,13 +45,13 @@ public class DefineClassInstr extends TwoOperandResultBaseInstr implements Fixed
@Override
public Instr clone(CloneInfo ii) {
- return new DefineClassInstr(ii.getRenamedVariable(result), this.newIRClassBody,
+ return new DefineClassInstr(ii.getRenamedVariable(result), body,
getContainer().cloneForInlining(ii), getSuperClass().cloneForInlining(ii));
}
@Override
public String[] toStringNonOperandArgs() {
- return new String[] {"name: " + newIRClassBody.getId() };
+ return new String[] {"name: " + body.getId() };
}
@Override
@@ -66,7 +71,39 @@ public class DefineClassInstr extends TwoOperandResultBaseInstr implements Fixed
Object container = getContainer().retrieve(context, self, currScope, currDynScope, temp);
Object superClass = getSuperClass().retrieve(context, self, currScope, currDynScope, temp);
- return IRRuntimeHelpers.newInterpretedClassBody(context, newIRClassBody, container, superClass);
+ RubyModule clazz = IRRuntimeHelpers.newRubyClassFromIR(context.runtime, body, superClass, container);
+
+ //if (IRRuntimeHelpers.isDebug()) doDebug();
+
+ return INTERPRET_CLASS(context, clazz);
+ }
+
+ private IRubyObject INTERPRET_CLASS(ThreadContext context, RubyModule clazz) {
+ InterpreterContext ic = body.getInterpreterContext();
+ String id = body.getId();
+
+ boolean hasExplicitCallProtocol = ic.hasExplicitCallProtocol();
+
+ if (!hasExplicitCallProtocol) pre(ic, context, clazz, id, clazz);
+
+ try {
+ ThreadContext.pushBacktrace(context, id, ic.getFileName(), context.getLine());
+ return ic.getEngine().interpret(context, null, clazz, ic, clazz.getMethodLocation(), id, Block.NULL_BLOCK);
+ } finally {
+ body.cleanupAfterExecution();
+ if (!hasExplicitCallProtocol) post(ic, context);
+ ThreadContext.popBacktrace(context);
+ }
+ }
+
+ private void post(InterpreterContext ic, ThreadContext context) {
+ context.popFrame();
+ if (ic.popDynScope()) context.popScope();
+ }
+
+ private void pre(InterpreterContext ic, ThreadContext context, IRubyObject self, String name, RubyModule implClass) {
+ context.preMethodFrameOnly(implClass, name, self);
+ if (ic.pushNewDynScope()) context.pushScope(DynamicScope.newDynamicScope(ic.getStaticScope()));
}
@Override
diff --git a/core/src/main/java/org/jruby/ir/instructions/DefineModuleInstr.java b/core/src/main/java/org/jruby/ir/instructions/DefineModuleInstr.java
index d0aaa4be15..9af4f789d3 100644
--- a/core/src/main/java/org/jruby/ir/instructions/DefineModuleInstr.java
+++ b/core/src/main/java/org/jruby/ir/instructions/DefineModuleInstr.java
@@ -1,8 +1,10 @@
package org.jruby.ir.instructions;
+import org.jruby.RubyModule;
import org.jruby.ir.IRModuleBody;
import org.jruby.ir.IRVisitor;
import org.jruby.ir.Operation;
+import org.jruby.ir.interpreter.InterpreterContext;
import org.jruby.ir.operands.Operand;
import org.jruby.ir.operands.Variable;
import org.jruby.ir.persistence.IRReaderDecoder;
@@ -10,24 +12,25 @@ import org.jruby.ir.persistence.IRWriterEncoder;
import org.jruby.ir.runtime.IRRuntimeHelpers;
import org.jruby.ir.transformations.inlining.CloneInfo;
import org.jruby.parser.StaticScope;
+import org.jruby.runtime.Block;
import org.jruby.runtime.DynamicScope;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
public class DefineModuleInstr extends OneOperandResultBaseInstr implements FixedArityInstr {
- private final IRModuleBody newIRModuleBody;
+ private final IRModuleBody body;
- public DefineModuleInstr(Variable result, IRModuleBody newIRModuleBody, Operand container) {
+ public DefineModuleInstr(Variable result, IRModuleBody body, Operand container) {
super(Operation.DEF_MODULE, result, container);
assert result != null : "DefineModuleInstr result is null";
- this.newIRModuleBody = newIRModuleBody;
+ this.body = body;
}
public IRModuleBody getNewIRModuleBody() {
- return newIRModuleBody;
+ return body;
}
public Operand getContainer() {
@@ -36,12 +39,12 @@ public class DefineModuleInstr extends OneOperandResultBaseInstr implements Fixe
@Override
public String[] toStringNonOperandArgs() {
- return new String[] { "name: " + newIRModuleBody.getId() };
+ return new String[] { "name: " + body.getId() };
}
@Override
public Instr clone(CloneInfo ii) {
- return new DefineModuleInstr(ii.getRenamedVariable(result), this.newIRModuleBody, getContainer().cloneForInlining(ii));
+ return new DefineModuleInstr(ii.getRenamedVariable(result), body, getContainer().cloneForInlining(ii));
}
@Override
@@ -57,9 +60,41 @@ public class DefineModuleInstr extends OneOperandResultBaseInstr implements Fixe
@Override
public Object interpret(ThreadContext context, StaticScope currScope, DynamicScope currDynScope, IRubyObject self, Object[] temp) {
- Object rubyContainer = getContainer().retrieve(context, self, currScope, currDynScope, temp);
+ Object container = getContainer().retrieve(context, self, currScope, currDynScope, temp);
- return IRRuntimeHelpers.newInterpretedModuleBody(context, newIRModuleBody, rubyContainer);
+ RubyModule clazz = IRRuntimeHelpers.newRubyModuleFromIR(context, body, container);
+
+ //if (IRRuntimeHelpers.isDebug()) doDebug();
+
+ return INTERPRET_MODULE(context, clazz);
+ }
+
+ private IRubyObject INTERPRET_MODULE(ThreadContext context, RubyModule clazz) {
+ InterpreterContext ic = body.getInterpreterContext();
+ String id = body.getId();
+
+ boolean hasExplicitCallProtocol = ic.hasExplicitCallProtocol();
+
+ if (!hasExplicitCallProtocol) pre(ic, context, clazz, id, clazz);
+
+ try {
+ ThreadContext.pushBacktrace(context, id, ic.getFileName(), context.getLine());
+ return ic.getEngine().interpret(context, null, clazz, ic, clazz.getMethodLocation(), id, Block.NULL_BLOCK);
+ } finally {
+ body.cleanupAfterExecution();
+ if (!hasExplicitCallProtocol) post(ic, context);
+ ThreadContext.popBacktrace(context);
+ }
+ }
+
+ private void post(InterpreterContext ic, ThreadContext context) {
+ context.popFrame();
+ if (ic.popDynScope()) context.popScope();
+ }
+
+ private void pre(InterpreterContext ic, ThreadContext context, IRubyObject self, String name, RubyModule implClass) {
+ context.preMethodFrameOnly(implClass, name, self);
+ if (ic.pushNewDynScope()) context.pushScope(DynamicScope.newDynamicScope(ic.getStaticScope()));
}
@Override
diff --git a/core/src/main/java/org/jruby/ir/interpreter/Interpreter.java b/core/src/main/java/org/jruby/ir/interpreter/Interpreter.java
index 298c109324..20000844c0 100644
--- a/core/src/main/java/org/jruby/ir/interpreter/Interpreter.java
+++ b/core/src/main/java/org/jruby/ir/interpreter/Interpreter.java
@@ -27,7 +27,6 @@ import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.Visibility;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.scope.ManyVarsDynamicScope;
-import org.jruby.util.cli.Options;
import org.jruby.util.log.Logger;
import org.jruby.util.log.LoggerFactory;
@@ -95,6 +94,7 @@ public class Interpreter extends IRTranslator<IRubyObject, IRubyObject> {
} catch (IRBreakJump bj) {
throw IRException.BREAK_LocalJumpError.getException(context.runtime);
} finally {
+ irScope.cleanupAfterExecution();
dumpStats();
context.popScope();
}
diff --git a/core/src/main/java/org/jruby/ir/runtime/IRRuntimeHelpers.java b/core/src/main/java/org/jruby/ir/runtime/IRRuntimeHelpers.java
index f0fa5e1aca..0dec3eb6d9 100644
--- a/core/src/main/java/org/jruby/ir/runtime/IRRuntimeHelpers.java
+++ b/core/src/main/java/org/jruby/ir/runtime/IRRuntimeHelpers.java
@@ -39,6 +39,7 @@ import org.jruby.internal.runtime.methods.InterpretedIRMetaClassBody;
import org.jruby.internal.runtime.methods.InterpretedIRMethod;
import org.jruby.internal.runtime.methods.MixedModeIRMethod;
import org.jruby.internal.runtime.methods.UndefinedMethod;
+import org.jruby.ir.IRClassBody;
import org.jruby.ir.IRMetaClassBody;
import org.jruby.ir.IRScope;
import org.jruby.ir.IRScopeType;
@@ -1446,7 +1447,8 @@ public class IRRuntimeHelpers {
return new CompiledIRMethod(handle, irModule, Visibility.PUBLIC, newRubyModule);
}
- private static RubyModule newRubyModuleFromIR(ThreadContext context, IRScope irModule, Object rubyContainer) {
+ @Interp @JIT
+ public static RubyModule newRubyModuleFromIR(ThreadContext context, IRScope irModule, Object rubyContainer) {
if (!(rubyContainer instanceof RubyModule)) {
throw context.runtime.newTypeError("no outer class/module");
}
@@ -1473,6 +1475,7 @@ public class IRRuntimeHelpers {
return new CompiledIRMethod(handle, irClassBody, Visibility.PUBLIC, newRubyClass);
}
+ @Interp @JIT
public static RubyModule newRubyClassFromIR(Ruby runtime, IRScope irClassBody, Object superClass, Object container) {
if (!(container instanceof RubyModule)) {
throw runtime.newTypeError("no outer class/module");
@@ -1618,6 +1621,14 @@ public class IRRuntimeHelpers {
return method.call(context, implClass, implClass, "", block);
}
+ // FIXME: Temporary until CompiledIRMethod part of this is removed.
+ @JIT
+ public static IRubyObject invokeModuleBody(ThreadContext context, DynamicMethod method) {
+ RubyModule implClass = method.getImplementationClass();
+
+ return method.call(context, implClass, implClass, "", Block.NULL_BLOCK);
+ }
+
@JIT
public static RubyRegexp newDynamicRegexp(ThreadContext context, IRubyObject[] pieces, int embeddedOptions) {
RegexpOptions options = RegexpOptions.fromEmbeddedOptions(embeddedOptions);
diff --git a/core/src/main/java/org/jruby/ir/targets/JVMVisitor.java b/core/src/main/java/org/jruby/ir/targets/JVMVisitor.java
index e4e1afd652..7a501921e6 100644
--- a/core/src/main/java/org/jruby/ir/targets/JVMVisitor.java
+++ b/core/src/main/java/org/jruby/ir/targets/JVMVisitor.java
@@ -1201,6 +1201,8 @@ public class JVMVisitor extends IRVisitor {
jvmMethod().invokeIRHelper("newCompiledClassBody", sig(DynamicMethod.class, ThreadContext.class, java.lang.invoke.MethodHandle.class, IRScope.class, Object.class, Object.class));
jvmStoreLocal(defineclassinstr.getResult());
+
+ ProcessModuleBodyInstr(new ProcessModuleBodyInstr(newIRClassBody.createTemporaryVariable(), defineclassinstr.getResult(), NullBlock.INSTANCE));
}
@Override
@@ -1316,6 +1318,8 @@ public class JVMVisitor extends IRVisitor {
jvmMethod().invokeIRHelper("newCompiledModuleBody", sig(DynamicMethod.class, ThreadContext.class, java.lang.invoke.MethodHandle.class, IRScope.class, Object.class));
jvmStoreLocal(definemoduleinstr.getResult());
+
+ ProcessModuleBodyInstr(new ProcessModuleBodyInstr(newIRModuleBody.createTemporaryVariable(), definemoduleinstr.getResult(), NullBlock.INSTANCE));
}
@Override
diff --git a/core/src/main/java/org/jruby/runtime/backtrace/FrameType.java b/core/src/main/java/org/jruby/runtime/backtrace/FrameType.java
index 907a5cade8..f44f2917cf 100644
--- a/core/src/main/java/org/jruby/runtime/backtrace/FrameType.java
+++ b/core/src/main/java/org/jruby/runtime/backtrace/FrameType.java
@@ -5,6 +5,8 @@ import java.util.HashSet;
import org.jruby.internal.runtime.methods.InterpretedIRBodyMethod;
import org.jruby.internal.runtime.methods.InterpretedIRMethod;
import org.jruby.internal.runtime.methods.MixedModeIRMethod;
+import org.jruby.ir.instructions.DefineClassInstr;
+import org.jruby.ir.instructions.DefineModuleInstr;
import org.jruby.ir.interpreter.Interpreter;
public enum FrameType {
@@ -17,6 +19,9 @@ public enum FrameType {
INTERPRETED_CLASSES.add(MixedModeIRMethod.class.getName());
INTERPRETED_CLASSES.add(InterpretedIRMethod.class.getName());
INTERPRETED_CLASSES.add(InterpretedIRBodyMethod.class.getName());
+ INTERPRETED_CLASSES.add(InterpretedIRBodyMethod.class.getName());
+ INTERPRETED_CLASSES.add(DefineClassInstr.class.getName());
+ INTERPRETED_CLASSES.add(DefineModuleInstr.class.getName());
}
public static boolean isInterpreterFrame(final String className, final String methodName) {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment