Skip to content

Commit

Permalink
Showing 82 changed files with 792 additions and 546 deletions.
11 changes: 1 addition & 10 deletions bin/ast
Original file line number Diff line number Diff line change
@@ -14,15 +14,6 @@ options = {
:dot_format => false
}

def get_ir_passes
ir_manager = org.jruby.ir.IRManager
ir_manager.DEFAULT_COMPILER_PASSES.split(',').map do |pass|
pass.to_sym
end
end

ir_passes = get_ir_passes

OptionParser.new do |opts|
opts.banner = "Usage: #{$0} [options]"

@@ -39,7 +30,7 @@ OptionParser.new do |opts|
options[:print_ir] = true
end

opts.on('-p', "--pass #{ir_passes}", ir_passes, 'Dump IR after running a pass') do |pass|
opts.on('-p', '--pass passes_list', 'Dump IR after running a pass') do |pass|
options[:print_pass] = pass
end

2 changes: 2 additions & 0 deletions core/src/main/java/org/jruby/RubyGlobal.java
Original file line number Diff line number Diff line change
@@ -245,6 +245,8 @@ public static void createGlobals(ThreadContext context, Ruby runtime) {
// ARGF, $< object
RubyArgsFile.initArgsFile(runtime);

globals.alias("$-0", "$/");

// Define aliases originally in the "English.rb" stdlib
globals.alias("$ERROR_INFO", "$!");
globals.alias("$ERROR_POSITION", "$@");
44 changes: 0 additions & 44 deletions core/src/main/java/org/jruby/RubyInstanceConfig.java
Original file line number Diff line number Diff line change
@@ -1912,48 +1912,4 @@ public boolean isCextEnabled() {
return false;
}

/**
* In Java integration, allow upper case name for a Java package;
* e.g., com.example.UpperCase.Class
*/
@Deprecated
public static final boolean UPPER_CASE_PACKAGE_NAME_ALLOWED = Options.JI_UPPER_CASE_PACKAGE_NAME_ALLOWED.load();

@Deprecated public static final boolean USE_INVOKEDYNAMIC = Options.COMPILE_INVOKEDYNAMIC.load();

// max times an indy call site can fail before it goes to simple IC
@Deprecated public static final int MAX_FAIL_COUNT = Options.INVOKEDYNAMIC_MAXFAIL.load();

// max polymorphism at a call site to build a chained method handle PIC
@Deprecated public static final int MAX_POLY_COUNT = Options.INVOKEDYNAMIC_MAXPOLY.load();

// logging of various indy aspects
@Deprecated public static final boolean LOG_INDY_BINDINGS = Options.INVOKEDYNAMIC_LOG_BINDING.load();
@Deprecated public static final boolean LOG_INDY_CONSTANTS = Options.INVOKEDYNAMIC_LOG_CONSTANTS.load();

// properties enabling or disabling certain uses of invokedynamic
@Deprecated public static final boolean INVOKEDYNAMIC_ALL = USE_INVOKEDYNAMIC && Options.INVOKEDYNAMIC_ALL.load();
@Deprecated public static final boolean INVOKEDYNAMIC_SAFE = USE_INVOKEDYNAMIC && Options.INVOKEDYNAMIC_SAFE.load();

@Deprecated private static final boolean invokedynamicOn = INVOKEDYNAMIC_ALL || INVOKEDYNAMIC_SAFE || USE_INVOKEDYNAMIC;

@Deprecated public static final boolean INVOKEDYNAMIC_INVOCATION = invokedynamicOn && Options.INVOKEDYNAMIC_INVOCATION.load();

@Deprecated private static final boolean invokedynamicInvocation = invokedynamicOn && INVOKEDYNAMIC_INVOCATION;

@Deprecated public static final boolean INVOKEDYNAMIC_INVOCATION_SWITCHPOINT = invokedynamicInvocation && Options.INVOKEDYNAMIC_INVOCATION_SWITCHPOINT.load();
@Deprecated public static final boolean INVOKEDYNAMIC_INDIRECT = invokedynamicInvocation && Options.INVOKEDYNAMIC_INVOCATION_INDIRECT.load();
@Deprecated public static final boolean INVOKEDYNAMIC_JAVA = invokedynamicInvocation && Options.INVOKEDYNAMIC_INVOCATION_JAVA.load();
@Deprecated public static final boolean INVOKEDYNAMIC_ATTR = invokedynamicInvocation && Options.INVOKEDYNAMIC_INVOCATION_ATTR.load();
@Deprecated public static final boolean INVOKEDYNAMIC_FFI = invokedynamicInvocation && Options.INVOKEDYNAMIC_INVOCATION_FFI.load();
@Deprecated public static final boolean INVOKEDYNAMIC_FASTOPS = invokedynamicInvocation && Options.INVOKEDYNAMIC_INVOCATION_FASTOPS.load();

@Deprecated public static final boolean INVOKEDYNAMIC_CACHE = invokedynamicOn && Options.INVOKEDYNAMIC_CACHE.load();

@Deprecated private static final boolean invokedynamicCache = invokedynamicOn && INVOKEDYNAMIC_CACHE;

@Deprecated public static final boolean INVOKEDYNAMIC_CONSTANTS = invokedynamicCache && Options.INVOKEDYNAMIC_CACHE_CONSTANTS.load();
@Deprecated public static final boolean INVOKEDYNAMIC_LITERALS = invokedynamicCache&& Options.INVOKEDYNAMIC_CACHE_LITERALS.load();
@Deprecated public static final boolean INVOKEDYNAMIC_IVARS = invokedynamicCache&& Options.INVOKEDYNAMIC_CACHE_IVARS.load();

}
Original file line number Diff line number Diff line change
@@ -48,9 +48,14 @@ public InterpretedIRMethod(IRScope method, Visibility visibility, RubyModule imp
this.method = method;
this.method.getStaticScope().determineModule();
this.arity = calculateArity();
if (!implementationClass.getRuntime().getInstanceConfig().getCompileMode().shouldJIT()) {

// disable JIT for anything that's not an IRMethod, or if JIT is turned off
// FIXME: kinda hacky, but I use IRMethod data in JITCompiler, and module/class/script bodies generally only run once
if (!(method instanceof IRMethod) ||
!implementationClass.getRuntime().getInstanceConfig().getCompileMode().shouldJIT()) {
this.box.callCount = -1;
}

isSynthetic = method instanceof IRModuleBody;
}

4 changes: 3 additions & 1 deletion core/src/main/java/org/jruby/ir/IRBuilder.java
Original file line number Diff line number Diff line change
@@ -2959,11 +2959,13 @@ public Operand buildPostExe(PostExeNode postExeNode, IRScope s) {
closureBuilder.addInstr(endClosure, new CopyInstr(endClosure.getCurrentModuleVariable(), new ScopeModule(0)));
closureBuilder.build(postExeNode.getBodyNode(), endClosure);

// Record to IRScope so JIT can pre-compile all potentially activated END blocks.
topLevel.recordEndBlock(endClosure);

// Add an instruction in 's' to record the end block in the 'topLevel' scope.
// SSS FIXME: IR support for end-blocks that access vars in non-toplevel-scopes
// might be broken currently. We could either fix it or consider dropping support
// for END blocks altogether or only support them in the toplevel. Not worth the pain.
s.recordEndBlock(endClosure);
addInstr(s, new RecordEndBlockInstr(topLevel, new WrappedIRClosure(s.getSelf(), endClosure)));
return manager.getNil();
}
25 changes: 9 additions & 16 deletions core/src/main/java/org/jruby/ir/IRScope.java
Original file line number Diff line number Diff line change
@@ -527,22 +527,15 @@ protected Instr[] prepareInstructions() {
}

private boolean isUnsafeScope() {
boolean unsafeScope = false;
if (flags.contains(HAS_END_BLOCKS) || this.isBeginEndBlock()) {
unsafeScope = true;
} else {
List beginBlocks = this.getBeginBlocks();
// Ex: BEGIN {a = 1}; p a
if (beginBlocks == null || beginBlocks.isEmpty()) {
// Ex: eval("BEGIN {a = 1}; p a")
// Here, the BEGIN is added to the outer script scope.
beginBlocks = this.getNearestTopLocalVariableScope().getBeginBlocks();
unsafeScope = beginBlocks != null && !beginBlocks.isEmpty();
} else {
unsafeScope = true;
}
}
return unsafeScope;
if (this.isBeginEndBlock()) return true; // this is a BEGIN block

List beginBlocks = getBeginBlocks();
if (beginBlocks != null && !beginBlocks.isEmpty()) return true; // this contains a BEGIN block

// Does topmost variable scope contain any BEGIN blocks (IRScriptBody or IREval)?
// Ex1: eval("BEGIN {a = 1}; p a") Ex2: BEGIN {a = 1}; p a
beginBlocks = getNearestTopLocalVariableScope().getBeginBlocks();
return beginBlocks != null && !beginBlocks.isEmpty();
}

public List<CompilerPass> getExecutedPasses() {
14 changes: 8 additions & 6 deletions core/src/main/java/org/jruby/ir/instructions/CallBase.java
Original file line number Diff line number Diff line change
@@ -131,6 +131,10 @@ public boolean hasClosure() {
return closure != null;
}

public boolean hasLiteralClosure() {
return closure instanceof WrappedIRClosure;
}

public boolean isAllConstants() {
for (Operand argument : arguments) {
if (!(argument instanceof ImmutableLiteral)) return false;
@@ -287,9 +291,8 @@ private boolean computeEvalFlag() {
private boolean computeRequiresCallersBindingFlag() {
if (canBeEval()) return true;

// Conservative -- assuming that the callee will save the closure
// and use it at a later point.
if (closure != null) return true;
// literal closures can be used to capture surrounding binding
if (hasLiteralClosure()) return true;

String mname = getMethodAddr().getName();
if (MethodIndex.SCOPE_AWARE_METHODS.contains(mname)) {
@@ -345,9 +348,8 @@ private boolean computeRequiresCallersBindingFlag() {
private boolean computeRequiresCallersFrameFlag() {
if (canBeEval()) return true;

// Conservative -- assuming that the callee will save the closure
// and use it at a later point.
if (closure != null) return true;
// literal closures can be used to capture surrounding binding
if (hasLiteralClosure()) return true;

if (procNew) return true;

Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.jruby.ir.instructions;

import org.jruby.ir.IRFlags;
import org.jruby.ir.IRScope;
import org.jruby.ir.IRVisitor;
import org.jruby.ir.Operation;
import org.jruby.ir.operands.MethAddr;
@@ -24,6 +26,13 @@ public UnresolvedSuperInstr(Variable result, Operand receiver, Operand[] args, O
this(Operation.UNRESOLVED_SUPER, result, receiver, args, closure);
}

@Override
public boolean computeScopeFlags(IRScope scope) {
scope.getFlags().add(IRFlags.REQUIRES_FRAME); // for current class and method name
scope.getFlags().add(IRFlags.REQUIRES_DYNSCOPE); // for current class and method name
return true;
}

@Override
public Instr clone(CloneInfo ii) {
return new UnresolvedSuperInstr(ii.getRenamedVariable(getResult()), getReceiver().cloneForInlining(ii), cloneCallArgs(ii), closure == null ? null : closure.cloneForInlining(ii));
Original file line number Diff line number Diff line change
@@ -632,7 +632,7 @@ private static IRubyObject interpret(ThreadContext context, IRubyObject self,
} catch (Throwable t) {
extractToMethodToAvoidC2Crash(context, instr, t);

if (debug) LOG.info("in : " + interpreterContext + ", caught Java throwable: " + t + "; excepting instr: " + instr);
if (debug) LOG.info("in : " + interpreterContext.getStaticScope().getIRScope() + ", caught Java throwable: " + t + "; excepting instr: " + instr);
ipc = instr.getRPC();
if (debug) LOG.info("ipc for rescuer: " + ipc);

Original file line number Diff line number Diff line change
@@ -57,21 +57,7 @@ public Object execute(IRScope scope, Object... data) {
scopeHasLocalVarStores = bindingHasEscaped;
}

boolean requireFrame = bindingHasEscaped || scope.usesEval();

for (IRFlags flag : scope.getFlags()) {
switch (flag) {
case BINDING_HAS_ESCAPED:
case CAN_CAPTURE_CALLERS_BINDING:
case REQUIRES_FRAME:
case REQUIRES_VISIBILITY:
case USES_BACKREF_OR_LASTLINE:
case USES_EVAL:
case USES_ZSUPER:
requireFrame = true;
}
}

boolean requireFrame = doesItRequireFrame(scope, bindingHasEscaped);
boolean requireBinding = !scope.getFlags().contains(IRFlags.DYNSCOPE_ELIMINATED);

if (requireBinding || requireFrame) {
@@ -148,6 +134,25 @@ public Object execute(IRScope scope, Object... data) {
return null;
}

private boolean doesItRequireFrame(IRScope scope, boolean bindingHasEscaped) {
boolean requireFrame = bindingHasEscaped || scope.usesEval();

for (IRFlags flag : scope.getFlags()) {
switch (flag) {
case BINDING_HAS_ESCAPED:
case CAN_CAPTURE_CALLERS_BINDING:
case REQUIRES_FRAME:
case REQUIRES_VISIBILITY:
case USES_BACKREF_OR_LASTLINE:
case USES_EVAL:
case USES_ZSUPER:
requireFrame = true;
}
}

return requireFrame;
}

@Override
public boolean invalidate(IRScope scope) {
// Cannot add call protocol instructions after we've added them once.
4 changes: 4 additions & 0 deletions core/src/main/java/org/jruby/ir/runtime/IRRuntimeHelpers.java
Original file line number Diff line number Diff line change
@@ -783,10 +783,12 @@ public static IRubyObject setCapturedVar(ThreadContext context, IRubyObject matc
return val;
}

@JIT // for JVM6
public static IRubyObject instanceSuperSplatArgs(ThreadContext context, IRubyObject self, String methodName, RubyModule definingModule, IRubyObject[] args, Block block, boolean[] splatMap) {
return instanceSuper(context, self, methodName, definingModule, splatArguments(args, splatMap), block);
}

@Interp
public static IRubyObject instanceSuper(ThreadContext context, IRubyObject self, String methodName, RubyModule definingModule, IRubyObject[] args, Block block) {
RubyClass superClass = definingModule.getSuperClass();
DynamicMethod method = superClass != null ? superClass.searchMethod(methodName) : UndefinedMethod.INSTANCE;
@@ -795,10 +797,12 @@ public static IRubyObject instanceSuper(ThreadContext context, IRubyObject self,
return rVal;
}

@JIT // for JVM6
public static IRubyObject classSuperSplatArgs(ThreadContext context, IRubyObject self, String methodName, RubyModule definingModule, IRubyObject[] args, Block block, boolean[] splatMap) {
return classSuper(context, self, methodName, definingModule, splatArguments(args, splatMap), block);
}

@Interp
public static IRubyObject classSuper(ThreadContext context, IRubyObject self, String methodName, RubyModule definingModule, IRubyObject[] args, Block block) {
RubyClass superClass = definingModule.getMetaClass().getSuperClass();
DynamicMethod method = superClass != null ? superClass.searchMethod(methodName) : UndefinedMethod.INSTANCE;
8 changes: 4 additions & 4 deletions core/src/main/java/org/jruby/ir/targets/Bootstrap.java
Original file line number Diff line number Diff line change
@@ -221,12 +221,12 @@ public static IRubyObject hash(ThreadContext context, IRubyObject[] pairs) {
return hash;
}

static MethodHandle buildGenericHandle(InvokeSite site, DynamicMethod method, RubyClass selfClass) {
static MethodHandle buildGenericHandle(InvokeSite site, DynamicMethod method, RubyClass dispatchClass) {
SmartBinder binder;

binder = SmartBinder.from(site.signature)
.drop("caller")
.insert(2, new String[]{"rubyClass", "name"}, new Class[]{RubyModule.class, String.class}, selfClass, site.name())
.permute("context", "self", "arg.*", "block")
.insert(2, new String[]{"rubyClass", "name"}, new Class[]{RubyModule.class, String.class}, dispatchClass, site.name())
.insert(0, "method", DynamicMethod.class, method);

if (site.arity > 3) {
@@ -255,7 +255,7 @@ static MethodHandle buildJittedHandle(InvokeSite site, DynamicMethod method, boo
// TODO: this will have to expand when we start specializing arities

binder = SmartBinder.from(site.signature)
.drop("caller");
.permute("context", "self", "arg.*", "block");

if (site.arity == -1) {
// already [], nothing to do
22 changes: 15 additions & 7 deletions core/src/main/java/org/jruby/ir/targets/ClassSuperInvokeSite.java
Original file line number Diff line number Diff line change
@@ -1,24 +1,32 @@
package org.jruby.ir.targets;

import org.jruby.RubyClass;
import org.jruby.internal.runtime.methods.DynamicMethod;
import org.jruby.internal.runtime.methods.UndefinedMethod;
import org.jruby.ir.runtime.IRRuntimeHelpers;
import org.jruby.runtime.Block;
import org.jruby.runtime.CallType;
import org.jruby.runtime.Helpers;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.callsite.CacheEntry;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodType;
import java.lang.invoke.SwitchPoint;

import static org.jruby.ir.runtime.IRRuntimeHelpers.splatArguments;

/**
* Created by headius on 10/23/14.
*/
public class ClassSuperInvokeSite extends SuperInvokeSite {
public ClassSuperInvokeSite(MethodType type, String name) {
super(type, name);
public class ClassSuperInvokeSite extends ResolvedSuperInvokeSite {
public ClassSuperInvokeSite(MethodType type, String name, String splatmapString) {
super(type, name, splatmapString);
}

public IRubyObject invoke(String methodName, boolean[] splatMap, ThreadContext context, IRubyObject caller, IRubyObject self, RubyClass definingModule, IRubyObject[] args, Block block) throws Throwable {
// TODO: get rid of caller
// TODO: caching
return IRRuntimeHelpers.classSuperSplatArgs(context, self, methodName, definingModule.getMetaClass(), args, block, splatMap);
@Override
protected RubyClass getSuperClass(RubyClass definingModule) {
return definingModule.getMetaClass().getMetaClass().getSuperClass();
}
}
Original file line number Diff line number Diff line change
@@ -1,24 +1,33 @@
package org.jruby.ir.targets;

import org.jruby.RubyClass;
import org.jruby.RubyModule;
import org.jruby.internal.runtime.methods.DynamicMethod;
import org.jruby.internal.runtime.methods.UndefinedMethod;
import org.jruby.ir.runtime.IRRuntimeHelpers;
import org.jruby.runtime.Block;
import org.jruby.runtime.CallType;
import org.jruby.runtime.Helpers;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.callsite.CacheEntry;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodType;
import java.lang.invoke.SwitchPoint;

import static org.jruby.ir.runtime.IRRuntimeHelpers.splatArguments;

/**
* Created by headius on 10/23/14.
*/
public class InstanceSuperInvokeSite extends SuperInvokeSite {
public InstanceSuperInvokeSite(MethodType type, String name) {
super(type, name);
public class InstanceSuperInvokeSite extends ResolvedSuperInvokeSite {
public InstanceSuperInvokeSite(MethodType type, String name, String splatmapString) {
super(type, name, splatmapString);
}

public IRubyObject invoke(String methodName, boolean[] splatMap, ThreadContext context, IRubyObject caller, IRubyObject self, RubyClass definingModule, IRubyObject[] args, Block block) throws Throwable {
// TODO: get rid of caller
// TODO: caching
return IRRuntimeHelpers.instanceSuperSplatArgs(context, self, methodName, definingModule, args, block, splatMap);
@Override
protected RubyClass getSuperClass(RubyClass definingModule) {
return definingModule.getSuperClass();
}
}
Loading

0 comments on commit 97f8152

Please sign in to comment.