Skip to content

Commit

Permalink
Showing 9 changed files with 281 additions and 226 deletions.
60 changes: 30 additions & 30 deletions core/pom.rb
Original file line number Diff line number Diff line change
@@ -163,36 +163,36 @@
'source' => [ '${base.java.version}', '1.7' ],
'target' => [ '${base.javac.version}', '1.7' ],
'useIncrementalCompilation' => 'false' ) do
execute_goals( 'compile',
:id => 'anno',
:phase => 'process-resources',
'includes' => [ 'org/jruby/anno/FrameField.java',
'org/jruby/anno/AnnotationBinder.java',
'org/jruby/anno/JRubyMethod.java',
'org/jruby/anno/FrameField.java',
'org/jruby/CompatVersion.java',
'org/jruby/runtime/Visibility.java',
'org/jruby/util/CodegenUtils.java',
'org/jruby/util/SafePropertyAccessor.java' ] )
execute_goals( 'compile',
:id => 'default-compile',
:phase => 'compile',
'annotationProcessors' => [ 'org.jruby.anno.AnnotationBinder' ],
'generatedSourcesDirectory' => 'target/generated-sources',
'compilerArgs' => [ '-XDignore.symbol.file=true',
'-J-Duser.language=en',
'-J-Dfile.encoding=UTF-8',
'-J-Xbootclasspath/p:${unsafe.jar}',
'-J-Xmx${jruby.compile.memory}' ] )
execute_goals( 'compile',
:id => 'populators',
:phase => 'process-classes',
'compilerArgs' => [ '-XDignore.symbol.file=true',
'-J-Duser.language=en',
'-J-Dfile.encoding=UTF-8',
'-J-Xbootclasspath/p:${unsafe.jar}',
'-J-Xmx${jruby.compile.memory}' ],
'includes' => [ 'org/jruby/gen/**/*.java' ] )
# execute_goals( 'compile',
# :id => 'anno',
# :phase => 'process-resources',
# 'includes' => [ 'org/jruby/anno/FrameField.java',
# 'org/jruby/anno/AnnotationBinder.java',
# 'org/jruby/anno/JRubyMethod.java',
# 'org/jruby/anno/FrameField.java',
# 'org/jruby/CompatVersion.java',
# 'org/jruby/runtime/Visibility.java',
# 'org/jruby/util/CodegenUtils.java',
# 'org/jruby/util/SafePropertyAccessor.java' ] )
# execute_goals( 'compile',
# :id => 'default-compile',
# :phase => 'compile',
# 'annotationProcessors' => [ 'org.jruby.anno.AnnotationBinder' ],
# 'generatedSourcesDirectory' => 'target/generated-sources',
# 'compilerArgs' => [ '-XDignore.symbol.file=true',
# '-J-Duser.language=en',
# '-J-Dfile.encoding=UTF-8',
# '-J-Xbootclasspath/p:${unsafe.jar}',
# '-J-Xmx${jruby.compile.memory}' ] )
# execute_goals( 'compile',
# :id => 'populators',
# :phase => 'process-classes',
# 'compilerArgs' => [ '-XDignore.symbol.file=true',
# '-J-Duser.language=en',
# '-J-Dfile.encoding=UTF-8',
# '-J-Xbootclasspath/p:${unsafe.jar}',
# '-J-Xmx${jruby.compile.memory}' ],
# 'includes' => [ 'org/jruby/gen/**/*.java' ] )
execute_goals( 'compile',
:id => 'eclipse-hack',
:phase => 'process-classes',
58 changes: 0 additions & 58 deletions core/pom.xml
Original file line number Diff line number Diff line change
@@ -397,64 +397,6 @@ DO NOT MODIFIY - GENERATED CODE
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<executions>
<execution>
<id>anno</id>
<phase>process-resources</phase>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<includes>
<include>org/jruby/anno/FrameField.java</include>
<include>org/jruby/anno/AnnotationBinder.java</include>
<include>org/jruby/anno/JRubyMethod.java</include>
<include>org/jruby/anno/FrameField.java</include>
<include>org/jruby/CompatVersion.java</include>
<include>org/jruby/runtime/Visibility.java</include>
<include>org/jruby/util/CodegenUtils.java</include>
<include>org/jruby/util/SafePropertyAccessor.java</include>
</includes>
</configuration>
</execution>
<execution>
<id>default-compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<annotationProcessors>
<annotationProcessor>org.jruby.anno.AnnotationBinder</annotationProcessor>
</annotationProcessors>
<generatedSourcesDirectory>target/generated-sources</generatedSourcesDirectory>
<compilerArgs>
<compilerArg>-XDignore.symbol.file=true</compilerArg>
<compilerArg>-J-Duser.language=en</compilerArg>
<compilerArg>-J-Dfile.encoding=UTF-8</compilerArg>
<compilerArg>-J-Xbootclasspath/p:${unsafe.jar}</compilerArg>
<compilerArg>-J-Xmx${jruby.compile.memory}</compilerArg>
</compilerArgs>
</configuration>
</execution>
<execution>
<id>populators</id>
<phase>process-classes</phase>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<compilerArgs>
<compilerArg>-XDignore.symbol.file=true</compilerArg>
<compilerArg>-J-Duser.language=en</compilerArg>
<compilerArg>-J-Dfile.encoding=UTF-8</compilerArg>
<compilerArg>-J-Xbootclasspath/p:${unsafe.jar}</compilerArg>
<compilerArg>-J-Xmx${jruby.compile.memory}</compilerArg>
</compilerArgs>
<includes>
<include>org/jruby/gen/**/*.java</include>
</includes>
</configuration>
</execution>
<execution>
<id>eclipse-hack</id>
<phase>process-classes</phase>
33 changes: 17 additions & 16 deletions core/src/main/java/org/jruby/RubyModule.java
Original file line number Diff line number Diff line change
@@ -965,23 +965,23 @@ public Map<String, List<JavaMethodDescriptor>> getStaticAnnotatedMethods() {
public void defineAnnotatedMethodsIndividually(Class clazz) {
TypePopulator populator;

if (RubyInstanceConfig.FULL_TRACE_ENABLED || RubyInstanceConfig.REFLECTED_HANDLES) {
// we want reflected invokers or need full traces, use default (slow) populator
if (DEBUG) LOG.info("trace mode, using default populator");
// if (RubyInstanceConfig.FULL_TRACE_ENABLED || RubyInstanceConfig.REFLECTED_HANDLES) {
// // we want reflected invokers or need full traces, use default (slow) populator
// if (DEBUG) LOG.info("trace mode, using default populator");
populator = TypePopulator.DEFAULT;
} else {
try {
String qualifiedName = "org.jruby.gen." + clazz.getCanonicalName().replace('.', '$');

if (DEBUG) LOG.info("looking for " + qualifiedName + AnnotationBinder.POPULATOR_SUFFIX);

Class populatorClass = Class.forName(qualifiedName + AnnotationBinder.POPULATOR_SUFFIX);
populator = (TypePopulator)populatorClass.newInstance();
} catch (Throwable t) {
if (DEBUG) LOG.info("Could not find it, using default populator");
populator = TypePopulator.DEFAULT;
}
}
// } else {
// try {
// String qualifiedName = "org.jruby.gen." + clazz.getCanonicalName().replace('.', '$');
//
// if (DEBUG) LOG.info("looking for " + qualifiedName + AnnotationBinder.POPULATOR_SUFFIX);
//
// Class populatorClass = Class.forName(qualifiedName + AnnotationBinder.POPULATOR_SUFFIX);
// populator = (TypePopulator)populatorClass.newInstance();
// } catch (Throwable t) {
// if (DEBUG) LOG.info("Could not find it, using default populator");
// populator = TypePopulator.DEFAULT;
// }
// }

populator.populate(this, clazz);
}
@@ -4154,6 +4154,7 @@ private static void define(RubyModule module, JavaMethodDescriptor desc, String
singletonClass = module.getSingletonClass();
// module/singleton methods are all defined public
DynamicMethod moduleMethod = dynamicMethod.dup();
moduleMethod.setImplementationClass(singletonClass);
moduleMethod.setVisibility(PUBLIC);

if (jrubyMethod.name().length == 0) {
12 changes: 0 additions & 12 deletions core/src/main/java/org/jruby/anno/TypePopulator.java
Original file line number Diff line number Diff line change
@@ -80,18 +80,6 @@ public void populate(RubyModule clsmod, Class clazz) {

RubyModule.MethodClumper clumper = new RubyModule.MethodClumper();
clumper.clump(clazz);

for (Map.Entry<String, List<JavaMethodDescriptor>> entry : clumper.getAllAnnotatedMethods().entrySet()) {
for (JavaMethodDescriptor desc : entry.getValue()) {
JRubyMethod anno = desc.anno;

// check for frame field reads or writes
if (anno.frame() || (anno.reads() != null && anno.reads().length >= 1) || (anno.writes() != null && anno.writes().length >= 1)) {
// add all names for this annotation
MethodIndex.addFrameAwareMethods(anno.name());
}
}
}

for (Map.Entry<String, List<JavaMethodDescriptor>> entry : clumper.getStaticAnnotatedMethods().entrySet()) {
clsmod.defineAnnotatedMethod(entry.getKey(), entry.getValue(), methodFactory);
Original file line number Diff line number Diff line change
@@ -28,9 +28,14 @@
package org.jruby.internal.runtime.methods;

import java.lang.invoke.MethodHandle;
import java.util.Arrays;
import java.util.concurrent.Callable;

import org.jruby.RubyModule;
import org.jruby.runtime.Arity;
import org.jruby.runtime.Block;
import org.jruby.runtime.Helpers;
import org.jruby.runtime.Signature;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.Visibility;
import org.jruby.runtime.builtin.IRubyObject;
@@ -48,29 +53,81 @@
* @author headius
*/
public class HandleMethod extends DynamicMethod implements MethodArgs2 {
private final MethodHandle[] targets;
private final MethodHandle target0;
private final MethodHandle target1;
private final MethodHandle target2;
private final MethodHandle target3;
private final MethodHandle target4;
private final Callable<MethodHandle[]> targetsGenerator;
private volatile MethodHandle[] targets;
private MethodHandle target0;
private MethodHandle target1;
private MethodHandle target2;
private MethodHandle target3;
private MethodHandle target4;
private final String parameterDesc;
private final Signature signature;
private final boolean builtin;
private final boolean notImplemented;

public HandleMethod(
RubyModule implementationClass,
Visibility visibility,
CallConfiguration callConfig,
Callable<MethodHandle[]> targetsGenerator,
Signature signature,
boolean builtin,
boolean notImplemented,
String parameterDesc) {

public HandleMethod(RubyModule implementationClass, Visibility visibility, CallConfiguration callConfig, MethodHandle[] targets, String parameterDesc) {
super(implementationClass, visibility, callConfig);
this.targets = targets;
this.target0 = targets[0];
this.target1 = targets[1];
this.target2 = targets[2];
this.target3 = targets[3];
this.target4 = targets[4];
this.targetsGenerator = targetsGenerator;
this.parameterDesc = parameterDesc;
this.signature = signature;
this.builtin = builtin;
this.notImplemented = notImplemented;
}

@Override
public Arity getArity() {
return signature.arity();
}

@Override
public boolean isBuiltin() {
return builtin;
}

@Override
public boolean isNotImplemented() {
return notImplemented;
}

@Override
public boolean isNative() {
return true;
}

private void ensureTargets() {
if (targets != null) return;
try {
MethodHandle[] targets = targetsGenerator.call();
this.target0 = targets[0];
this.target1 = targets[1];
this.target2 = targets[2];
this.target3 = targets[3];
this.target4 = targets[4];
this.targets = targets;
} catch (Exception e) {
e.printStackTrace();
// ignore
}
}

@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject[] args, Block block) {
ensureTargets();
try {
return (IRubyObject) target4.invokeWithArguments(context, self, args, block);
return (IRubyObject) target4.invokeExact(context, self, args, block);
} catch (NullPointerException npe) {
npe.printStackTrace();
System.out.println("handles: " + Arrays.toString(targets));
throw npe;
} catch (Throwable t) {
Helpers.throwException(t);
return null;
@@ -79,11 +136,12 @@ public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule claz

@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, Block block) {
ensureTargets();
if (target0 == null) {
return call(context, self, clazz, name, IRubyObject.NULL_ARRAY, block);
}
try {
return (IRubyObject) target0.invokeWithArguments(context, self, block);
return (IRubyObject) target0.invokeExact(context, self, block);
} catch (Throwable t) {
Helpers.throwException(t);
return null;
@@ -92,11 +150,12 @@ public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule claz

@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject arg0, Block block) {
ensureTargets();
if (target1 == null) {
return call(context, self, clazz, name, new IRubyObject[]{arg0}, block);
}
try {
return (IRubyObject) target1.invokeWithArguments(context, self, arg0, block);
return (IRubyObject) target1.invokeExact(context, self, arg0, block);
} catch (Throwable t) {
Helpers.throwException(t);
return null;
@@ -105,11 +164,12 @@ public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule claz

@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject arg0, IRubyObject arg1, Block block) {
ensureTargets();
if (target2 == null) {
return call(context, self, clazz, name, new IRubyObject[]{arg0, arg1}, block);
}
try {
return (IRubyObject) target2.invokeWithArguments(context, self, arg0, arg1, block);
return (IRubyObject) target2.invokeExact(context, self, arg0, arg1, block);
} catch (Throwable t) {
Helpers.throwException(t);
return null;
@@ -118,11 +178,12 @@ public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule claz

@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2, Block block) {
ensureTargets();
if (target3 == null) {
return call(context, self, clazz, name, new IRubyObject[]{arg0, arg1, arg2}, block);
}
try {
return (IRubyObject) target3.invokeWithArguments(context, self, arg0, arg1, arg2, block);
return (IRubyObject) target3.invokeExact(context, self, arg0, arg1, arg2, block);
} catch (Throwable t) {
Helpers.throwException(t);
return null;
@@ -131,7 +192,7 @@ public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule claz

@Override
public DynamicMethod dup() {
return new HandleMethod(implementationClass, visibility, callConfig, targets, parameterDesc);
return new HandleMethod(implementationClass, visibility, callConfig, targetsGenerator, signature, builtin, notImplemented, parameterDesc);
}

@Override

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -27,30 +27,33 @@
***** END LICENSE BLOCK *****/
package org.jruby.internal.runtime.methods;

import com.headius.invokebinder.Binder;
import com.headius.invokebinder.Signature;
import com.headius.invokebinder.SmartBinder;
import com.headius.invokebinder.SmartHandle;
import org.jruby.RubyInstanceConfig;
import org.jruby.parser.StaticScope;
import org.jruby.RubyModule;
import org.jruby.lexer.yacc.ISourcePosition;
import org.jruby.runtime.Arity;
import org.jruby.runtime.Block;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.Visibility;
import org.jruby.runtime.builtin.IRubyObject;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Array;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Callable;

import org.jruby.Ruby;
import org.jruby.anno.JavaMethodDescriptor;
import org.jruby.runtime.invokedynamic.InvocationLinker;
import org.jruby.util.log.Logger;
import org.jruby.util.log.LoggerFactory;

import static java.lang.invoke.MethodHandles.foldArguments;
import static java.lang.invoke.MethodHandles.insertArguments;
import static org.jruby.runtime.Helpers.arrayOf;

/**
* In order to avoid the overhead with reflection-based method handles, this
* MethodFactory uses ASM to generate tiny invoker classes. This allows for
@@ -77,7 +80,7 @@ public InvokeDynamicMethodFactory(ClassLoader classLoader) {
}

@Override
public DynamicMethod getAnnotatedMethod(RubyModule implementationClass, List<JavaMethodDescriptor> descs) {
public DynamicMethod getAnnotatedMethod(final RubyModule implementationClass, final List<JavaMethodDescriptor> descs) {
JavaMethodDescriptor desc1 = descs.get(0);

if (desc1.anno.frame()) {
@@ -91,29 +94,82 @@ public DynamicMethod getAnnotatedMethod(RubyModule implementationClass, List<Jav
LOG.warn("warning: binding non-public class {}; reflected handles won't work", desc1.declaringClassName);
}

int min = Integer.MAX_VALUE;
int max = 0;
boolean notImplemented = false;

for (JavaMethodDescriptor desc: descs) {
int specificArity = -1;
if (desc.optional == 0 && !desc.rest) {
if (desc.required == 0) {
if (desc.actualRequired <= 3) {
specificArity = desc.actualRequired;
}
} else if (desc.required >= 0 && desc.required <= 3) {
specificArity = desc.required;
}
}

if (specificArity != -1) {
if (specificArity < min) min = specificArity;
if (specificArity > max) max = specificArity;
} else {
if (desc.required < min) min = desc.required;
if (desc.rest) max = Integer.MAX_VALUE;
if (desc.required + desc.optional > max) max = desc.required + desc.optional;
}

notImplemented = notImplemented || desc.anno.notImplemented();
}

DescriptorInfo info = new DescriptorInfo(descs);
MethodHandle[] targets = buildAnnotatedMethodHandles(implementationClass.getRuntime(), descs, implementationClass);
Callable<MethodHandle[]> targetsGenerator = new Callable<MethodHandle[]>() {
@Override
public MethodHandle[] call() throws Exception {
return buildAnnotatedMethodHandles(implementationClass.getRuntime(), descs, implementationClass);
}
};

return new HandleMethod(implementationClass, desc1.anno.visibility(), CallConfiguration.getCallConfig(info.isFrame(), info.isScope()), targets, null);
return new HandleMethod(
implementationClass,
desc1.anno.visibility(),
CallConfiguration.getCallConfig(info.isFrame(), info.isScope()),
targetsGenerator,
(min == max) ?
org.jruby.runtime.Signature.from(min, 0, 0, 0, 0, org.jruby.runtime.Signature.Rest.NONE, false) :
org.jruby.runtime.Signature.OPTIONAL,
true,
notImplemented,
null);
}

private MethodHandle[] buildAnnotatedMethodHandles(Ruby runtime, List<JavaMethodDescriptor> descs, RubyModule implementationClass) {
MethodHandle[] targets = new MethodHandle[5];

int min = Integer.MAX_VALUE;
int max = 0;

for (JavaMethodDescriptor desc: descs) {
int specificArity = -1;
if (desc.optional == 0 && !desc.rest) {
if (desc.required == 0) {
if (desc.actualRequired <= 3) {
specificArity = desc.actualRequired;
} else {
specificArity = -1;
}
} else if (desc.required >= 0 && desc.required <= 3) {
specificArity = desc.required;
}
}

if (specificArity != -1) {
if (specificArity < min) min = specificArity;
if (specificArity > max) max = specificArity;
} else {
if (desc.required < min) min = desc.required;
if (desc.rest) max = Integer.MAX_VALUE;
if (desc.required + desc.optional > max) max = desc.required + desc.optional;
}

String javaMethodName = desc.name;
String rubyName;

@@ -124,8 +180,6 @@ private MethodHandle[] buildAnnotatedMethodHandles(Ruby runtime, List<JavaMethod
rubyName = javaMethodName;
}

// checkArity(desc.anno, method, specificArity);

SmartBinder targetBinder;
SmartHandle target;
Signature baseSignature;
@@ -215,21 +269,14 @@ private MethodHandle[] buildAnnotatedMethodHandles(Ruby runtime, List<JavaMethod
targets[4] = target.handle();
}
}

if (targets[4] == null) {
// provide a variable-arity path for specific-arity target
Signature VARIABLE_ARITY_SIGNATURE = Signature
.returning(IRubyObject.class)
.appendArg("context", ThreadContext.class)
.appendArg("self", IRubyObject.class)
.appendArg("args", IRubyObject[].class)
.appendArg("block", Block.class);

// convert all specific-arity handles into varargs handles
// provide a variable-arity path for all specific-arity targets, or error path

MethodHandle[] varargsTargets = new MethodHandle[4];
for (int i = 0; i < 4; i++) {
// TODO arity error
if (targets[i] == null) continue;
if (targets[i] == null) continue; // will never be retrieved; arity check will error first

if (i == 0) {
varargsTargets[i] = MethodHandles.dropArguments(targets[i], 2, IRubyObject[].class);
} else {
@@ -251,16 +298,26 @@ private MethodHandle[] buildAnnotatedMethodHandles(Ruby runtime, List<JavaMethod
.filterReturn(HANDLE_GETTER.bindTo(varargsTargets))
.cast(int.class, Object.class)
.invokeStaticQuiet(LOOKUP, Array.class, "getLength");

SmartHandle variableCall = SmartBinder
.from(VARIABLE_ARITY_SIGNATURE)
.fold("handle", handleLookup)
.invoker();

targets[4] = variableCall.handle();
}



targets[4] = SmartBinder
.from(VARIABLE_ARITY_SIGNATURE)
.foldVoid(SmartBinder
.from(VARIABLE_ARITY_SIGNATURE.changeReturn(int.class))
.permute("context", "args")
.append(arrayOf("min", "max"), arrayOf(int.class, int.class), min, max)
.invokeStaticQuiet(LOOKUP, Arity.class, "checkArgumentCount")
.handle())
.invoke(targets[4])
.handle();

// TODO: tracing

return targets;
@@ -324,4 +381,10 @@ public DynamicMethod getAnnotatedMethod(RubyModule implementationClass, JavaMeth
.permute("context", "self", "arg*", "block");
}
}

static final MethodHandle ARITY_ERROR_HANDLE = SmartBinder
.from(VARIABLE_ARITY_SIGNATURE.appendArgs(arrayOf("min", "max"), int.class, int.class))
.filterReturn(Binder.from(IRubyObject.class, int.class).drop(0).constant(null))
.permute(ARITY_CHECK_SIGNATURE)
.invokeStaticQuiet(LOOKUP, Arity.class, "checkArgumentCount").handle();
}
2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/runtime/MethodFactory.java
Original file line number Diff line number Diff line change
@@ -59,7 +59,7 @@ public abstract class MethodFactory {
*/
public static MethodFactory createFactory(ClassLoader classLoader) {
// otherwise, generate invokers at runtime
if (Options.COMPILE_INVOKEDYNAMIC.load() && Options.INVOKEDYNAMIC_HANDLES.load()) {
if (Options.INVOKEDYNAMIC_HANDLES.load()) {
return new InvokeDynamicMethodFactory(classLoader);
} else {
return new InvocationMethodFactory(classLoader);
2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/util/cli/Options.java
Original file line number Diff line number Diff line change
@@ -100,7 +100,7 @@ public class Options {
public static final Option<Boolean> INVOKEDYNAMIC_CACHE_IVARS = bool(INVOKEDYNAMIC, "invokedynamic.cache.ivars", true, "Use invokedynamic to get/set instance variables.");
public static final Option<Boolean> INVOKEDYNAMIC_CLASS_VALUES = bool(INVOKEDYNAMIC, "invokedynamic.class.values", false, "Use ClassValue to store class-specific data.");
public static final Option<Integer> INVOKEDYNAMIC_GLOBAL_MAXFAIL = integer(INVOKEDYNAMIC, "invokedynamic.global.maxfail", 100, "Maximum global cache failures after which to use slow path.");
public static final Option<Boolean> INVOKEDYNAMIC_HANDLES = bool(INVOKEDYNAMIC, "invokedynamic.handles", false, "Use MethodHandles rather than generated code to bind Ruby methods.");
public static final Option<Boolean> INVOKEDYNAMIC_HANDLES = bool(INVOKEDYNAMIC, "invokedynamic.handles", true, "Use MethodHandles rather than generated code to bind Ruby methods.");

public static final Option<Integer> JIT_THRESHOLD = integer(JIT, "jit.threshold", Constants.JIT_THRESHOLD, "Set the JIT threshold to the specified method invocation count.");
public static final Option<Integer> JIT_MAX = integer(JIT, "jit.max", Constants.JIT_MAX_METHODS_LIMIT, "Set the max count of active methods eligible for JIT-compilation.");

0 comments on commit 7b2bf65

Please sign in to comment.