Created
May 16, 2019 21:19
-
-
Save enebo/c58e6408b5e1fa965a0618029a5da43b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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