Skip to content

Commit

Permalink
Showing 29 changed files with 408 additions and 377 deletions.
10 changes: 1 addition & 9 deletions core/pom.rb
Original file line number Diff line number Diff line change
@@ -13,9 +13,6 @@
'tzdata.version' => '2013d',
'tzdata.scope' => 'provided',

'unsafe.version' => '8.92.1',
'unsafe.jar' => '${settings.localRepository}/com/headius/unsafe-mock/${unsafe.version}/unsafe-mock-${unsafe.version}.jar',

'maven.build.timestamp.format' => 'yyyy-MM-dd',
'maven.test.skip' => 'true',
'build.date' => '${maven.build.timestamp}',
@@ -62,8 +59,7 @@

jar 'com.headius:invokebinder:1.7'
jar 'com.headius:options:1.4'
jar 'com.headius:coro-mock:1.0', :scope => 'provided'
jar 'com.headius:unsafe-mock', '${unsafe.version}', :scope => 'provided'
jar 'com.headius:unsafe-fences:1.0-SNAPSHOT'

This comment has been minimized.

Copy link
@eregon

eregon Dec 17, 2016

Member

SNAPSHOT dependency!

This comment has been minimized.

Copy link
@chrisseaton

chrisseaton Dec 18, 2016

Author Contributor

But we don't build this part any more!

(We do, but only for testing purposes, and won't in the next few days).


jar 'bsf:bsf:2.4.0', :scope => 'provided'
jar 'com.jcraft:jzlib:1.1.3'
@@ -192,17 +188,13 @@
'compilerArgs' => [ '-XDignore.symbol.file=true',
'-J-Duser.language=en',
'-J-Dfile.encoding=UTF-8',
'-J-Xbootclasspath/p:${unsafe.jar}',
'-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}',
'-Xbootclasspath/p:${unsafe.jar}',
'-J-Xmx${jruby.compile.memory}' ],
'includes' => [ 'org/jruby/gen/**/*.java' ] )
execute_goals( 'compile',
17 changes: 2 additions & 15 deletions core/pom.xml
Original file line number Diff line number Diff line change
@@ -22,7 +22,6 @@ DO NOT MODIFIY - GENERATED CODE
<spec.tags.dir>${spec.dir}/tags</spec.tags.dir>
<polyglot.dump.pom>pom.xml</polyglot.dump.pom>
<pkg.dir>${build.dir}/pkg</pkg.dir>
<unsafe.jar>${settings.localRepository}/com/headius/unsafe-mock/${unsafe.version}/unsafe-mock-${unsafe.version}.jar</unsafe.jar>
<spec.dir>spec</spec.dir>
<maven.build.timestamp.format>yyyy-MM-dd</maven.build.timestamp.format>
<jruby.test.memory.permgen>2G</jruby.test.memory.permgen>
@@ -41,7 +40,6 @@ DO NOT MODIFIY - GENERATED CODE
<jruby.launch.memory>1024M</jruby.launch.memory>
<jruby.compile.memory>2G</jruby.compile.memory>
<version.ruby.major>2.3</version.ruby.major>
<unsafe.version>8.92.1</unsafe.version>
<release.dir>release</release.dir>
<create.sources.jar>false</create.sources.jar>
<lib.dir>lib</lib.dir>
@@ -204,15 +202,8 @@ DO NOT MODIFIY - GENERATED CODE
</dependency>
<dependency>
<groupId>com.headius</groupId>
<artifactId>coro-mock</artifactId>
<version>1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.headius</groupId>
<artifactId>unsafe-mock</artifactId>
<version>${unsafe.version}</version>
<scope>provided</scope>
<artifactId>unsafe-fences</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>bsf</groupId>
@@ -496,8 +487,6 @@ DO NOT MODIFIY - GENERATED CODE
<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>-Xbootclasspath/p:${unsafe.jar}</compilerArg>
<compilerArg>-J-Xmx${jruby.compile.memory}</compilerArg>
</compilerArgs>
</configuration>
@@ -513,8 +502,6 @@ DO NOT MODIFIY - GENERATED CODE
<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>-Xbootclasspath/p:${unsafe.jar}</compilerArg>
<compilerArg>-J-Xmx${jruby.compile.memory}</compilerArg>
</compilerArgs>
<includes>
33 changes: 33 additions & 0 deletions core/src/main/java/org/jruby/ObjectFlags.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package org.jruby;

import org.jruby.ext.stringio.StringIO;

/**
* Flags used by RubyBasicObject descendants.
*/
public interface ObjectFlags {
FlagRegistry registry = new FlagRegistry();

// These flags must be registered from top of hierarchy down to maintain order.
// TODO: Replace these during the build with their calculated values.
int FALSE_F = registry.newFlag(RubyBasicObject.class);
int NIL_F = registry.newFlag(RubyBasicObject.class);
int FROZEN_F = registry.newFlag(RubyBasicObject.class);
int TAINTED_F = registry.newFlag(RubyBasicObject.class);

int CACHEPROXY_F = registry.newFlag(RubyModule.class);
int NEEDSIMPL_F = registry.newFlag(RubyModule.class);
int REFINED_MODULE_F = registry.newFlag(RubyModule.class);
int IS_OVERLAID_F = registry.newFlag(RubyModule.class);

int CR_7BIT_F = registry.newFlag(RubyString.class);
int CR_VALID_F = registry.newFlag(RubyString.class);

int STRIO_READABLE = registry.newFlag(StringIO.class);
int STRIO_WRITABLE = registry.newFlag(StringIO.class);

int MATCH_BUSY = registry.newFlag(RubyMatchData.class);

int COMPARE_BY_IDENTITY_F = registry.newFlag(RubyHash.class);
int PROCDEFAULT_HASH_F = registry.newFlag(RubyHash.class);
}
9 changes: 4 additions & 5 deletions core/src/main/java/org/jruby/RubyBasicObject.java
Original file line number Diff line number Diff line change
@@ -30,7 +30,6 @@
import org.jcodings.Encoding;
import org.jcodings.specific.UTF8Encoding;
import org.jruby.ir.interpreter.Interpreter;
import org.jruby.runtime.Constants;
import org.jruby.runtime.JavaSites;
import org.jruby.runtime.JavaSites.BasicObjectSites;
import org.jruby.runtime.ivars.VariableAccessor;
@@ -143,7 +142,7 @@ public class RubyBasicObject implements Cloneable, IRubyObject, Serializable, Co
public static final String ERR_INSECURE_SET_INST_VAR = "Insecure: can't modify instance variable";

public static final int ALL_F = -1;
public static final int FALSE_F = Constants.FALSE_F;
public static final int FALSE_F = ObjectFlags.FALSE_F;
/**
* This flag is a bit funny. It's used to denote that this value
* is nil. It's a bit counterintuitive for a Java programmer to
@@ -154,9 +153,9 @@ public class RubyBasicObject implements Cloneable, IRubyObject, Serializable, Co
* final. It turns out using a flag for this actually gives us
* better performance than having a polymorphic {@link #isNil()} method.
*/
public static final int NIL_F = Constants.NIL_F;
public static final int FROZEN_F = Constants.FROZEN_F;
public static final int TAINTED_F = Constants.TAINTED_F;
public static final int NIL_F = ObjectFlags.NIL_F;
public static final int FROZEN_F = ObjectFlags.FROZEN_F;
public static final int TAINTED_F = ObjectFlags.TAINTED_F;

/**
* A value that is used as a null sentinel in among other places
11 changes: 2 additions & 9 deletions core/src/main/java/org/jruby/RubyHash.java
Original file line number Diff line number Diff line change
@@ -44,20 +44,13 @@
import org.jruby.common.IRubyWarnings.ID;
import org.jruby.exceptions.RaiseException;
import org.jruby.javasupport.JavaUtil;
import org.jruby.parser.StaticScope;
import org.jruby.runtime.Arity;
import org.jruby.runtime.Binding;
import org.jruby.runtime.Block;
import org.jruby.runtime.BlockBody;
import org.jruby.runtime.ClassIndex;
import org.jruby.runtime.Constants;
import org.jruby.runtime.Frame;
import org.jruby.runtime.Helpers;
import org.jruby.runtime.JavaSites.HashSites;
import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.Signature;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.Visibility;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.marshal.MarshalStream;
import org.jruby.runtime.marshal.UnmarshalStream;
@@ -118,7 +111,7 @@
public class RubyHash extends RubyObject implements Map {
public static final int DEFAULT_INSPECT_STR_SIZE = 20;

public static final int COMPARE_BY_IDENTITY_F = Constants.COMPARE_BY_IDENTITY_F;
public static final int COMPARE_BY_IDENTITY_F = ObjectFlags.COMPARE_BY_IDENTITY_F;

public static RubyClass createHashClass(Ruby runtime) {
RubyClass hashc = runtime.defineClass("Hash", runtime.getObject(), HASH_ALLOCATOR);
@@ -231,7 +224,7 @@ public static final RubyHash newHash(Ruby runtime, Map valueMap, IRubyObject def
protected int size = 0;
private int threshold;

private static final int PROCDEFAULT_HASH_F = Constants.PROCDEFAULT_HASH_F;
private static final int PROCDEFAULT_HASH_F = ObjectFlags.PROCDEFAULT_HASH_F;

private IRubyObject ifNone;

3 changes: 1 addition & 2 deletions core/src/main/java/org/jruby/RubyMatchData.java
Original file line number Diff line number Diff line change
@@ -46,7 +46,6 @@
import org.jruby.anno.JRubyClass;
import org.jruby.runtime.Block;
import org.jruby.runtime.ClassIndex;
import org.jruby.runtime.Constants;
import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.Visibility;
@@ -276,7 +275,7 @@ private void updateCharOffset() {
charOffsetUpdated = true;
}

private static final int MATCH_BUSY = Constants.MATCH_BUSY;
private static final int MATCH_BUSY = ObjectFlags.MATCH_BUSY;

// rb_match_busy
public final void use() {
9 changes: 4 additions & 5 deletions core/src/main/java/org/jruby/RubyModule.java
Original file line number Diff line number Diff line change
@@ -93,7 +93,6 @@
import org.jruby.runtime.Block;
import org.jruby.runtime.CallSite;
import org.jruby.runtime.ClassIndex;
import org.jruby.runtime.Constants;
import org.jruby.runtime.Helpers;
import org.jruby.runtime.IRBlockBody;
import org.jruby.runtime.MethodFactory;
@@ -134,10 +133,10 @@ public class RubyModule extends RubyObject {
private static final Logger LOG = LoggerFactory.getLogger(RubyModule.class);
// static { LOG.setDebugEnable(true); } // enable DEBUG output

public static final int CACHEPROXY_F = Constants.CACHEPROXY_F;
public static final int NEEDSIMPL_F = Constants.NEEDSIMPL_F;
public static final int REFINED_MODULE_F = Constants.REFINED_MODULE_F;
public static final int IS_OVERLAID_F = Constants.IS_OVERLAID_F;
public static final int CACHEPROXY_F = ObjectFlags.CACHEPROXY_F;
public static final int NEEDSIMPL_F = ObjectFlags.NEEDSIMPL_F;
public static final int REFINED_MODULE_F = ObjectFlags.REFINED_MODULE_F;
public static final int IS_OVERLAID_F = ObjectFlags.IS_OVERLAID_F;

public static final ObjectAllocator MODULE_ALLOCATOR = new ObjectAllocator() {
@Override
7 changes: 3 additions & 4 deletions core/src/main/java/org/jruby/ext/stringio/StringIO.java
Original file line number Diff line number Diff line change
@@ -32,7 +32,7 @@

import org.jcodings.Encoding;
import org.jcodings.specific.ASCIIEncoding;
import org.jruby.FlagRegistry;
import org.jruby.ObjectFlags;
import org.jruby.Ruby;
import org.jruby.RubyArray;
import org.jruby.RubyClass;
@@ -49,7 +49,6 @@
import org.jruby.ast.util.ArgsUtil;
import org.jruby.java.addons.IOJavaAddons;
import org.jruby.runtime.Block;
import org.jruby.runtime.Constants;
import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
@@ -81,8 +80,8 @@ static class StringIOData {
}
StringIOData ptr;

private static final int STRIO_READABLE = Constants.STRIO_READABLE;
private static final int STRIO_WRITABLE = Constants.STRIO_WRITABLE;
private static final int STRIO_READABLE = ObjectFlags.STRIO_READABLE;
private static final int STRIO_WRITABLE = ObjectFlags.STRIO_WRITABLE;
private static final int STRIO_READWRITE = (STRIO_READABLE | STRIO_WRITABLE);

private static ObjectAllocator STRINGIO_ALLOCATOR = new ObjectAllocator() {

This file was deleted.

Original file line number Diff line number Diff line change
@@ -22,7 +22,6 @@ public class CompiledIRMethod extends AbstractIRMethod {
protected final MethodHandle specific;
protected final int specificArity;

private final boolean hasExplicitCallProtocol;
private final boolean hasKwargs;

public CompiledIRMethod(MethodHandle variable, IRScope method, Visibility visibility,
@@ -39,9 +38,10 @@ public CompiledIRMethod(MethodHandle variable, MethodHandle specific, int specif
// unboxing -- it was a simple path to hacking this in).
this.specificArity = hasKwargs ? -1 : specificArity;
this.method.getStaticScope().determineModule();
this.hasExplicitCallProtocol = method.hasExplicitCallProtocol();
this.hasKwargs = hasKwargs;

assert method.hasExplicitCallProtocol();

setHandle(variable);
}

@@ -69,202 +69,147 @@ public InterpreterContext ensureInstrsReady() {
return ic;
}

protected void post(ThreadContext context) {
// update call stacks (pop: ..)
context.postMethodFrameAndScope();
}

protected void pre(ThreadContext context, StaticScope staticScope, RubyModule implementationClass, IRubyObject self, String name, Block block) {
// update call stacks (push: frame, class, scope, etc.)
context.preMethodFrameAndScope(implementationClass, name, self, block, staticScope);
}

@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject[] args, Block block) {
if (!hasExplicitCallProtocol) return callNoProtocol(context, self, name, args, block);

if (hasKwargs) args = IRRuntimeHelpers.frobnicateKwargsArgument(context, args, getSignature().required());

return invokeExact(this.variable, context, staticScope, self, args, block, implementationClass, name);
try {
return (IRubyObject) this.variable.invokeExact(context, staticScope, self, args, block, implementationClass, name);
}
catch (Throwable t) {
Helpers.throwException(t);
return null; // not reached
}
}

@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, Block block) {
if (specificArity != 0) return call(context, self, clazz, name, IRubyObject.NULL_ARRAY, block);

if (!hasExplicitCallProtocol) return callNoProtocol(context, self, clazz, name, block);

return invokeExact(this.specific, context, staticScope, self, block, implementationClass, name);
try {
return (IRubyObject) this.specific.invokeExact(context, staticScope, self, block, implementationClass, name);
}
catch (Throwable t) {
Helpers.throwException(t);
return null; // not reached
}
}

@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject arg0, Block block) {
if (!hasExplicitCallProtocol) return callNoProtocol(context, self, clazz, name, arg0, block);

if (specificArity != 1) return call(context, self, clazz, name, new IRubyObject[]{arg0}, block);

return invokeExact(this.specific, context, staticScope, self, arg0, block, implementationClass, name);
try {
return (IRubyObject) this.specific.invokeExact(context, staticScope, self, arg0, block, implementationClass, name);
}
catch (Throwable t) {
Helpers.throwException(t);
return null; // not reached
}
}

@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject arg0, IRubyObject arg1, Block block) {
if (!hasExplicitCallProtocol) return callNoProtocol(context, self, clazz, name, arg0, arg1, block);

if (specificArity != 2) return call(context, self, clazz, name, new IRubyObject[] {arg0, arg1}, block);

return invokeExact(this.specific, context, staticScope, self, arg0, arg1, block, implementationClass, name);
}

@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2, Block block) {
if (!hasExplicitCallProtocol) return callNoProtocol(context, self, clazz, name, arg0, arg1, arg2, block);

if (specificArity != 3) return call(context, self, clazz, name, new IRubyObject[] {arg0, arg1, arg2 }, block);

return invokeExact(this.specific, context, staticScope, self, arg0, arg1, arg2, block, implementationClass, name);
}

private IRubyObject callNoProtocol(ThreadContext context, IRubyObject self, String name, IRubyObject[] args, Block block) {
StaticScope staticScope = this.staticScope;
RubyModule implementationClass = this.implementationClass;
pre(context, staticScope, implementationClass, self, name, block);

if (hasKwargs) args = IRRuntimeHelpers.frobnicateKwargsArgument(context, args, getSignature().required());

try {
return invokeExact(this.variable, context, staticScope, self, args, block, implementationClass, name);
}
finally { post(context); }
}

public final IRubyObject callNoProtocol(ThreadContext context, IRubyObject self, RubyModule clazz, String name, Block block) {
if (specificArity != 0) return call(context, self, clazz, name, IRubyObject.NULL_ARRAY, block);

StaticScope staticScope = this.staticScope;
RubyModule implementationClass = this.implementationClass;
pre(context, staticScope, implementationClass, self, name, block);

try {
return invokeExact(this.specific, context, staticScope, self, block, implementationClass, name);
return (IRubyObject) this.specific.invokeExact(context, staticScope, self, arg0, arg1, block, implementationClass, name);
}
finally { post(context); }
}

public final IRubyObject callNoProtocol(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject arg0, Block block) {
if (specificArity != 1) return call(context, self, clazz, name, Helpers.arrayOf(arg0), block);

StaticScope staticScope = this.staticScope;
RubyModule implementationClass = this.implementationClass;
pre(context, staticScope, implementationClass, self, name, block);

try {
return invokeExact(this.specific, context, staticScope, self, arg0, block, implementationClass, name);
catch (Throwable t) {
Helpers.throwException(t);
return null; // not reached
}
finally { post(context); }
}

public final IRubyObject callNoProtocol(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject arg0, IRubyObject arg1, Block block) {
if (specificArity != 2) return call(context, self, clazz, name, Helpers.arrayOf(arg0, arg1), block);

StaticScope staticScope = this.staticScope;
RubyModule implementationClass = this.implementationClass;
pre(context, staticScope, implementationClass, self, name, block);
@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2, Block block) {
if (specificArity != 3) return call(context, self, clazz, name, new IRubyObject[] {arg0, arg1, arg2 }, block);

try {
return invokeExact(this.specific, context, staticScope, self, arg0, arg1, block, implementationClass, name);
return (IRubyObject) this.specific.invokeExact(context, staticScope, self, arg0, arg1, arg2, block, implementationClass, name);
}
finally { post(context); }
}

public final IRubyObject callNoProtocol(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2, Block block) {
if (specificArity != 3) return call(context, self, clazz, name, Helpers.arrayOf(arg0, arg1, arg2), block);

StaticScope staticScope = this.staticScope;
RubyModule implementationClass = this.implementationClass;
pre(context, staticScope, implementationClass, self, name, block);

try {
return invokeExact(this.specific, context, staticScope, self, arg0, arg1, arg2, block, implementationClass, name);
catch (Throwable t) {
Helpers.throwException(t);
return null; // not reached
}
finally { post(context); }
}

public String getFile() {
return method.getFileName();
}

public int getLine() {
return method.getLineNumber();
}

@Override
public String toString() {
return getClass().getName() + '@' + Integer.toHexString(hashCode()) + ' ' + method + ' ' + getSignature();
}
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject[] args) {
if (hasKwargs) args = IRRuntimeHelpers.frobnicateKwargsArgument(context, args, getSignature().required());

private static IRubyObject invokeExact(MethodHandle method,
ThreadContext context, StaticScope staticScope, IRubyObject self,
IRubyObject[] args, Block block,
RubyModule implementationClass, String name) {
try {
return (IRubyObject) method.invokeExact(context, staticScope, self, args, block, implementationClass, name);
return (IRubyObject) this.variable.invokeExact(context, staticScope, self, args, Block.NULL_BLOCK, implementationClass, name);
}
catch (Throwable t) {
Helpers.throwException(t);
return null; // not reached
}
}

private static IRubyObject invokeExact(MethodHandle method,
ThreadContext context, StaticScope staticScope, IRubyObject self,
Block block,
RubyModule implementationClass, String name) {
@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name) {
if (specificArity != 0) return call(context, self, clazz, name, IRubyObject.NULL_ARRAY, Block.NULL_BLOCK);

try {
return (IRubyObject) method.invokeExact(context, staticScope, self, block, implementationClass, name);
return (IRubyObject) this.specific.invokeExact(context, staticScope, self, Block.NULL_BLOCK, implementationClass, name);
}
catch (Throwable t) {
Helpers.throwException(t);
return null; // not reached
}
}

private static IRubyObject invokeExact(MethodHandle method,
ThreadContext context, StaticScope staticScope, IRubyObject self,
IRubyObject arg0, Block block,
RubyModule implementationClass, String name) {
@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject arg0) {
if (specificArity != 1) return call(context, self, clazz, name, new IRubyObject[]{arg0}, Block.NULL_BLOCK);

try {
return (IRubyObject) method.invokeExact(context, staticScope, self, arg0, block, implementationClass, name);
return (IRubyObject) this.specific.invokeExact(context, staticScope, self, arg0, Block.NULL_BLOCK, implementationClass, name);
}
catch (Throwable t) {
Helpers.throwException(t);
return null; // not reached
}
}

private static IRubyObject invokeExact(MethodHandle method,
ThreadContext context, StaticScope staticScope, IRubyObject self,
IRubyObject arg0, IRubyObject arg1, Block block,
RubyModule implementationClass, String name) {
@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject arg0, IRubyObject arg1) {
if (specificArity != 2) return call(context, self, clazz, name, new IRubyObject[] {arg0, arg1}, Block.NULL_BLOCK);

try {
return (IRubyObject) method.invokeExact(context, staticScope, self, arg0, arg1, block, implementationClass, name);
return (IRubyObject) this.specific.invokeExact(context, staticScope, self, arg0, arg1, Block.NULL_BLOCK, implementationClass, name);
}
catch (Throwable t) {
Helpers.throwException(t);
return null; // not reached
}
}

private static IRubyObject invokeExact(MethodHandle method,
ThreadContext context, StaticScope staticScope, IRubyObject self,
IRubyObject arg0, IRubyObject arg1, IRubyObject arg2, Block block,
RubyModule implementationClass, String name) {
@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2) {
if (specificArity != 3) return call(context, self, clazz, name, new IRubyObject[] {arg0, arg1, arg2 }, Block.NULL_BLOCK);

try {
return (IRubyObject) method.invokeExact(context, staticScope, self, arg0, arg1, arg2, block, implementationClass, name);
return (IRubyObject) this.specific.invokeExact(context, staticScope, self, arg0, arg1, arg2, Block.NULL_BLOCK, implementationClass, name);
}
catch (Throwable t) {
Helpers.throwException(t);
return null; // not reached
}
}

public String getFile() {
return method.getFileName();
}

public int getLine() {
return method.getLineNumber();
}

@Override
public String toString() {
return getClass().getName() + '@' + Integer.toHexString(hashCode()) + ' ' + method + ' ' + getSignature();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package org.jruby.internal.runtime.methods;

import org.jruby.RubyModule;
import org.jruby.internal.runtime.AbstractIRMethod;
import org.jruby.ir.IRFlags;
import org.jruby.ir.IRMethod;
import org.jruby.ir.IRScope;
import org.jruby.ir.interpreter.InterpreterContext;
import org.jruby.parser.StaticScope;
import org.jruby.runtime.ArgumentDescriptor;
import org.jruby.runtime.Block;
import org.jruby.runtime.DynamicScope;
import org.jruby.runtime.Helpers;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.Visibility;
import org.jruby.runtime.builtin.IRubyObject;

import java.lang.invoke.MethodHandle;

public class CompiledIRNoProtocolMethod extends AbstractIRMethod {
private final boolean scope;
private final MethodHandle variable;

public CompiledIRNoProtocolMethod(MethodHandle handle, IRScope scope, RubyModule implementationClass) {
super(scope, Visibility.PUBLIC, implementationClass);

this.scope = !scope.getFlags().contains(IRFlags.DYNSCOPE_ELIMINATED);
this.variable = handle;
}

public ArgumentDescriptor[] getArgumentDescriptors() {
return ArgumentDescriptor.EMPTY_ARRAY;
}

@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, Block block) {
StaticScope staticScope1 = this.staticScope;
RubyModule implementationClass1 = this.implementationClass;
pre(context, staticScope1, implementationClass1, self, name, block);

try {
return (IRubyObject) this.variable.invokeExact(context, staticScope1, self, IRubyObject.NULL_ARRAY, block, implementationClass1, name);
} catch (Throwable t) {
Helpers.throwException(t);
return null; // not reached
} finally {
post(context);
}
}

@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject[] args, Block block) {
throw new RuntimeException("BUG: this path should never be called");
}

@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject arg0, Block block) {
throw new RuntimeException("BUG: this path should never be called");
}

@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject arg0, IRubyObject arg1, Block block) {
throw new RuntimeException("BUG: this path should never be called");
}

@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2, Block block) {
throw new RuntimeException("BUG: this path should never be called");
}

protected void post(ThreadContext context) {
// update call stacks (pop: ..)
context.popFrame();
if (scope) {
context.popScope();
}
}

protected void pre(ThreadContext context, StaticScope staticScope, RubyModule implementationClass, IRubyObject self, String name, Block block) {
// update call stacks (push: frame, class, scope, etc.)
context.preMethodFrameOnly(implementationClass, name, self, block);
if (scope) {
// Add a parent-link to current dynscope to support non-local returns cheaply
// This doesn't affect variable scoping since local variables will all have
// the right scope depth.
context.pushScope(DynamicScope.newDynamicScope(staticScope, context.getCurrentScope()));
}
context.setCurrentVisibility(getVisibility());
}

@Override
public InterpreterContext ensureInstrsReady() {
// FIXME: duplicated from MixedModeIRMethod
if (method instanceof IRMethod) {
return ((IRMethod) method).lazilyAcquireInterpreterContext();
}

InterpreterContext ic = method.getInterpreterContext();

return ic;
}

}
Original file line number Diff line number Diff line change
@@ -91,6 +91,14 @@ public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule claz
return INTERPRET_METHOD(context, ensureInstrsReady(), getImplementationClass(), self, name, args, block);
}

@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject[] args) {
if (IRRuntimeHelpers.isDebug()) doDebug();

if (callCount >= 0) promoteToFullBuild(context);
return INTERPRET_METHOD(context, ensureInstrsReady(), getImplementationClass(), self, name, args, Block.NULL_BLOCK);
}

private IRubyObject INTERPRET_METHOD(ThreadContext context, InterpreterContext ic, RubyModule implClass,
IRubyObject self, String name, IRubyObject[] args, Block block) {
try {
@@ -120,6 +128,15 @@ public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule claz
return INTERPRET_METHOD(context, ensureInstrsReady(), getImplementationClass(), self, name, block);
}

@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name) {
if (IRRuntimeHelpers.isDebug()) doDebug();

if (callCount >= 0) promoteToFullBuild(context);

return INTERPRET_METHOD(context, ensureInstrsReady(), getImplementationClass(), self, name, Block.NULL_BLOCK);
}

private IRubyObject INTERPRET_METHOD(ThreadContext context, InterpreterContext ic, RubyModule implClass,
IRubyObject self, String name, Block block) {
try {
@@ -148,6 +165,14 @@ public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule claz
return INTERPRET_METHOD(context, ensureInstrsReady(), getImplementationClass(), self, name, arg0, block);
}

@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject arg0) {
if (IRRuntimeHelpers.isDebug()) doDebug();

if (callCount >= 0) promoteToFullBuild(context);
return INTERPRET_METHOD(context, ensureInstrsReady(), getImplementationClass(), self, name, arg0, Block.NULL_BLOCK);
}

private IRubyObject INTERPRET_METHOD(ThreadContext context, InterpreterContext ic, RubyModule implClass,
IRubyObject self, String name, IRubyObject arg1, Block block) {
try {
@@ -176,6 +201,14 @@ public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule claz
return INTERPRET_METHOD(context, ensureInstrsReady(), getImplementationClass(), self, name, arg0, arg1, block);
}

@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject arg0, IRubyObject arg1) {
if (IRRuntimeHelpers.isDebug()) doDebug();

if (callCount >= 0) promoteToFullBuild(context);
return INTERPRET_METHOD(context, ensureInstrsReady(), getImplementationClass(), self, name, arg0, arg1, Block.NULL_BLOCK);
}

private IRubyObject INTERPRET_METHOD(ThreadContext context, InterpreterContext ic, RubyModule implClass,
IRubyObject self, String name, IRubyObject arg1, IRubyObject arg2, Block block) {
try {
@@ -204,6 +237,14 @@ public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule claz
return INTERPRET_METHOD(context, ensureInstrsReady(), getImplementationClass(), self, name, arg0, arg1, arg2, block);
}

@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2) {
if (IRRuntimeHelpers.isDebug()) doDebug();

if (callCount >= 0) promoteToFullBuild(context);
return INTERPRET_METHOD(context, ensureInstrsReady(), getImplementationClass(), self, name, arg0, arg1, arg2, Block.NULL_BLOCK);
}

private IRubyObject INTERPRET_METHOD(ThreadContext context, InterpreterContext ic, RubyModule implClass,
IRubyObject self, String name, IRubyObject arg1, IRubyObject arg2, IRubyObject arg3, Block block) {
try {
Original file line number Diff line number Diff line change
@@ -121,7 +121,7 @@ public DynamicMethod getAnnotatedMethod(final RubyModule implementationClass, fi
implementationClass,
desc1.anno.visibility(),
(min == max) ?
org.jruby.runtime.Signature.from(min, 0, 0, 0, 0, org.jruby.runtime.Signature.Rest.NONE, false).encode() :
org.jruby.runtime.Signature.from(min, 0, 0, 0, 0, org.jruby.runtime.Signature.Rest.NONE, -1).encode() :
org.jruby.runtime.Signature.OPTIONAL.encode(),
true,
notImplemented,
33 changes: 5 additions & 28 deletions core/src/main/java/org/jruby/ir/Compiler.java
Original file line number Diff line number Diff line change
@@ -63,12 +63,13 @@ protected ScriptAndCode execute(final Ruby runtime, final IRScriptBody scope, Cl
}

final MethodHandle compiledHandle = _compiledHandle;
final StaticScope staticScope = scope.getStaticScope();

Script script = new AbstractScript() {
@Override
public IRubyObject __file__(ThreadContext context, IRubyObject self, IRubyObject[] args, Block block) {
try {
return (IRubyObject) compiledHandle.invokeWithArguments(context, scope.getStaticScope(), self, IRubyObject.NULL_ARRAY, block, self.getMetaClass(), Interpreter.ROOT);
return (IRubyObject) compiledHandle.invokeWithArguments(context, staticScope, self, IRubyObject.NULL_ARRAY, block, self.getMetaClass(), Interpreter.ROOT);
} catch (Throwable t) {
Helpers.throwException(t);
return null; // not reached
@@ -78,45 +79,21 @@ public IRubyObject __file__(ThreadContext context, IRubyObject self, IRubyObject
@Override
public IRubyObject load(ThreadContext context, IRubyObject self, boolean wrap) {
// Compiler does not support BEGIN/END yet and should fail to compile above
{
// BeginEndInterpreterContext ic = (BeginEndInterpreterContext) irScope.prepareForInterpretation();

// We get the live object ball rolling here.
// This give a valid value for the top of this lexical tree.
// All new scopes can then retrieve and set based on lexical parent.
// StaticScope scope = ic.getStaticScope();
}
// Copied from Interpreter
StaticScope sscope = scope.getStaticScope();
RubyModule currModule = sscope.getModule();
if (currModule == null) {
// SSS FIXME: Looks like this has to do with Kernel#load
// and the wrap parameter. Figure it out and document it here.
currModule = context.getRuntime().getObject();
}
RubyModule currModule = staticScope.getModule();

sscope.setModule(currModule);
DynamicScope tlbScope = scope.getToplevelScope();
if (tlbScope == null) {
context.preMethodScopeOnly(sscope);
} else {
sscope = tlbScope.getStaticScope();
context.preScopedBody(tlbScope);
tlbScope.growIfNeeded();
}
staticScope.setModule(currModule);
context.setCurrentVisibility(Visibility.PRIVATE);

try {
// runBeginEndBlocks(ic.getBeginBlocks(), context, self, scope, null);
return (IRubyObject) compiledHandle.invokeWithArguments(context, sscope, self, IRubyObject.NULL_ARRAY, Block.NULL_BLOCK, currModule, Interpreter.ROOT);
return (IRubyObject) compiledHandle.invokeWithArguments(context, staticScope, self, IRubyObject.NULL_ARRAY, Block.NULL_BLOCK, currModule, Interpreter.ROOT);
} catch (IRBreakJump bj) {
throw IRException.BREAK_LocalJumpError.getException(context.runtime);
} catch (Throwable t) {
Helpers.throwException(t);
return null; // not reached
} finally {
// runEndBlocks(ic.getEndBlocks(), context, self, scope, null);
context.popScope();
}
}
};
5 changes: 2 additions & 3 deletions core/src/main/java/org/jruby/ir/IRBuilder.java
Original file line number Diff line number Diff line change
@@ -2144,7 +2144,6 @@ public void receiveRequiredArg(Node node, int argIndex, Signature signature) {

protected void receiveNonBlockArgs(final ArgsNode argsNode) {
Signature signature = scope.getStaticScope().getSignature();
KeywordRestArgNode keyRest = argsNode.getKeyRest();

// For closures, we don't need the check arity call
if (scope instanceof IRMethod) {
@@ -2155,12 +2154,12 @@ protected void receiveNonBlockArgs(final ArgsNode argsNode) {
// But later, perhaps can make this implicit in the method setup preamble?

addInstr(new CheckArityInstr(signature.required(), signature.opt(), signature.hasRest(), argsNode.hasKwargs(),
keyRest == null ? -1 : keyRest.getIndex()));
signature.keyRest()));
} else if (scope instanceof IRClosure && argsNode.hasKwargs()) {
// FIXME: This is added to check for kwargs correctness but bypass regular correctness.
// Any other arity checking currently happens within Java code somewhere (RubyProc.call?)
addInstr(new CheckArityInstr(signature.required(), signature.opt(), signature.hasRest(), argsNode.hasKwargs(),
keyRest == null ? -1 : keyRest.getIndex()));
signature.keyRest()));
}

// Other args begin at index 0
Original file line number Diff line number Diff line change
@@ -22,8 +22,10 @@ public String getLabel() {

private boolean explicitCallProtocolSupported(IRScope scope) {
return scope instanceof IRMethod
|| (scope instanceof IRClosure && !(scope instanceof IREvalScript))
|| (scope instanceof IRModuleBody && !(scope instanceof IRMetaClassBody));
|| (scope instanceof IRClosure && !(scope instanceof IREvalScript))
|| (scope instanceof IRModuleBody && !(scope instanceof IRMetaClassBody)
|| (scope instanceof IRScriptBody)
);
}

/*
2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/ir/persistence/IRWriter.java
Original file line number Diff line number Diff line change
@@ -88,7 +88,7 @@ private static void persistScopeHeader(IRWriterEncoder file, IRScope scope) {
if (scope instanceof IRClosure) {
IRClosure closure = (IRClosure) scope;

file.encode(closure.getSignature().encode());
file.encode(closure.getSignature());
}

persistStaticScope(file, scope.getStaticScope());
4 changes: 2 additions & 2 deletions core/src/main/java/org/jruby/ir/runtime/IRRuntimeHelpers.java
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@
import org.jruby.common.IRubyWarnings;
import org.jruby.exceptions.RaiseException;
import org.jruby.exceptions.Unrescuable;
import org.jruby.internal.runtime.methods.CompiledIRMetaClassBody;
import org.jruby.internal.runtime.methods.CompiledIRNoProtocolMethod;
import org.jruby.internal.runtime.methods.CompiledIRMethod;
import org.jruby.internal.runtime.methods.DynamicMethod;
import org.jruby.internal.runtime.methods.InterpretedIRBodyMethod;
@@ -1240,7 +1240,7 @@ public static DynamicMethod newInterpretedMetaClass(Ruby runtime, IRScope metaCl
public static DynamicMethod newCompiledMetaClass(ThreadContext context, MethodHandle handle, IRScope metaClassBody, IRubyObject obj) {
RubyClass singletonClass = newMetaClassFromIR(context.runtime, metaClassBody, obj);

return new CompiledIRMetaClassBody(handle, metaClassBody, singletonClass);
return new CompiledIRNoProtocolMethod(handle, metaClassBody, singletonClass);
}

private static RubyClass newMetaClassFromIR(Ruby runtime, IRScope metaClassBody, IRubyObject obj) {
83 changes: 63 additions & 20 deletions core/src/main/java/org/jruby/ir/targets/JVMVisitor.java
Original file line number Diff line number Diff line change
@@ -66,6 +66,7 @@ public class JVMVisitor extends IRVisitor {
private static final Signature METHOD_SIGNATURE_BASE = Signature
.returning(IRubyObject.class)
.appendArgs(new String[]{"context", "scope", "self", BLOCK_ARG_NAME, "class", "callName"}, ThreadContext.class, StaticScope.class, IRubyObject.class, Block.class, RubyModule.class, String.class);
private static final Signature METHOD_SIGNATURE_VARARGS = METHOD_SIGNATURE_BASE.insertArg(BLOCK_ARG_NAME, "args", IRubyObject[].class);

public static final Signature CLOSURE_SIGNATURE = Signature
.returning(IRubyObject.class)
@@ -238,6 +239,45 @@ protected void emitScope(IRScope scope, String name, Signature signature, boolea
jvm.popmethod();
}

protected void emitVarargsMethodWrapper(IRScope scope, String name, Signature variableSignature, Signature specificSignature) {

Map<BasicBlock, Label> exceptionTable = scope.buildJVMExceptionTable();

jvm.pushmethod(name, scope, variableSignature, false);

IRBytecodeAdapter m = jvmMethod();

// check arity
org.jruby.runtime.Signature scopeSig = scope.getStaticScope().getSignature();
checkArity(scopeSig.required(), scopeSig.opt(), scopeSig.hasRest(), scopeSig.hasKwargs(), scopeSig.keyRest());

// push leading args
m.loadContext();
m.loadStaticScope();
m.loadSelf();

// unwrap specific args
if (scopeSig.required() > 0) {
for (int i = 0; i < scopeSig.required(); i++) {
m.loadArgs();
jvmAdapter().pushInt(i);
jvmAdapter().aaload();
}
}

// push trailing args
m.loadBlock();
m.loadFrameClass();
m.loadFrameName();

// invoke specific-arity version and return
Method specificMethod = new Method(name, Type.getType(specificSignature.type().returnType()), IRRuntimeHelpers.typesFromSignature(specificSignature));
jvmAdapter().invokestatic(m.getClassData().clsName, name, specificMethod.getDescriptor());
jvmAdapter().areturn();

jvm.popmethod();
}

protected static final Signature signatureFor(IRScope method, boolean aritySplit) {
if (aritySplit) {
StaticScope argScope = method.getStaticScope();
@@ -306,14 +346,16 @@ protected void emitBlockJIT(IRClosure closure, JVMVisitorMethodContext context)
private void emitWithSignatures(IRMethod method, JVMVisitorMethodContext context, String name) {
context.setJittedName(name);

Signature signature = signatureFor(method, false);
emitScope(method, name, signature, false, true);
context.addNativeSignature(-1, signature.type());

Signature specificSig = signatureFor(method, true);
if (specificSig != null) {
if (specificSig == null) {
Signature signature = signatureFor(method, false);
emitScope(method, name, signature, false, true);
context.addNativeSignature(-1, signature.type());
} else {
emitScope(method, name, specificSig, true, false);
context.addNativeSignature(method.getStaticScope().getSignature().required(), specificSig.type());
emitVarargsMethodWrapper(method, name, METHOD_SIGNATURE_VARARGS, specificSig);
context.addNativeSignature(-1, METHOD_SIGNATURE_VARARGS.type());
}
}

@@ -1057,20 +1099,24 @@ public void CheckArityInstr(CheckArityInstr checkarityinstr) {
if (jvm.methodData().specificArity >= 0) {
// no arity check in specific arity path
} else {
jvmMethod().loadContext();
jvmMethod().loadStaticScope();
jvmMethod().loadArgs();
// TODO: pack these, e.g. in a constant pool String
jvmAdapter().ldc(checkarityinstr.required);
jvmAdapter().ldc(checkarityinstr.opt);
jvmAdapter().ldc(checkarityinstr.rest);
jvmAdapter().ldc(checkarityinstr.receivesKeywords);
jvmAdapter().ldc(checkarityinstr.restKey);
jvmMethod().loadBlockType();
jvmAdapter().invokestatic(p(IRRuntimeHelpers.class), "checkArity", sig(void.class, ThreadContext.class, StaticScope.class, Object[].class, int.class, int.class, boolean.class, boolean.class, int.class, Block.Type.class));
checkArity(checkarityinstr.required, checkarityinstr.opt, checkarityinstr.rest, checkarityinstr.receivesKeywords, checkarityinstr.restKey);
}
}

private void checkArity(int required, int opt, boolean rest, boolean receivesKeywords, int restKey) {
jvmMethod().loadContext();
jvmMethod().loadStaticScope();
jvmMethod().loadArgs();
// TODO: pack these, e.g. in a constant pool String
jvmAdapter().ldc(required);
jvmAdapter().ldc(opt);
jvmAdapter().ldc(rest);
jvmAdapter().ldc(receivesKeywords);
jvmAdapter().ldc(restKey);
jvmMethod().loadBlockType();
jvmAdapter().invokestatic(p(IRRuntimeHelpers.class), "checkArity", sig(void.class, ThreadContext.class, StaticScope.class, Object[].class, int.class, int.class, boolean.class, boolean.class, int.class, Block.Type.class));
}

@Override
public void CheckForLJEInstr(CheckForLJEInstr checkForljeinstr) {
jvmMethod().loadContext();
@@ -1151,13 +1197,10 @@ public void DefineClassMethodInstr(DefineClassMethodInstr defineclassmethodinstr
JVMVisitorMethodContext context = new JVMVisitorMethodContext();
emitMethod(method, context);

MethodType variable = context.getNativeSignature(-1); // always a variable arity handle
assert(variable != null);

String defSignature = pushHandlesForDef(
context.getJittedName(),
context.getNativeSignaturesExceptVariable(),
variable,
METHOD_SIGNATURE_VARARGS.type(),
sig(void.class, ThreadContext.class, java.lang.invoke.MethodHandle.class, IRScope.class, IRubyObject.class),
sig(void.class, ThreadContext.class, java.lang.invoke.MethodHandle.class, java.lang.invoke.MethodHandle.class, int.class, IRScope.class, IRubyObject.class));

11 changes: 11 additions & 0 deletions core/src/main/java/org/jruby/javasupport/DummyForJavaUtil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.jruby.javasupport;

/**
* This class exists only for access-checks to set {@linkplain JavaUtil#CAN_SET_ACCESSIBLE}
*/
public class DummyForJavaUtil {

private static final Object PRIVATE = new Object[0];
public static final Object PUBLIC = PRIVATE;

}
12 changes: 7 additions & 5 deletions core/src/main/java/org/jruby/javasupport/JavaUtil.java
Original file line number Diff line number Diff line change
@@ -36,10 +36,10 @@
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ReflectPermission;
import static java.lang.Character.isLetter;
import static java.lang.Character.isLowerCase;
import static java.lang.Character.isUpperCase;
@@ -48,7 +48,6 @@

import java.math.BigDecimal;
import java.math.BigInteger;
import java.security.AccessController;
import java.util.Collections;
import java.util.HashMap;
import java.util.IdentityHashMap;
@@ -99,9 +98,12 @@ public class JavaUtil {

if (RubyInstanceConfig.CAN_SET_ACCESSIBLE) {
try {
AccessController.checkPermission(new ReflectPermission("suppressAccessChecks"));
canSetAccessible = true;
} catch (Throwable t) {
// We want to check if we can access a commonly-existing private field through reflection. If so,
// we're probably able to access some other fields too later on.
Field f = DummyForJavaUtil.class.getDeclaredField("PRIVATE");
f.setAccessible(true);
canSetAccessible = f.get(null).equals(DummyForJavaUtil.PUBLIC);
} catch (Exception t) {
// added this so if things are weird in the future we can debug without
// spinning a new binary
if (Options.JI_LOGCANSETACCESSIBLE.load()) {
9 changes: 9 additions & 0 deletions core/src/main/java/org/jruby/parser/StaticScope.java
Original file line number Diff line number Diff line change
@@ -244,6 +244,9 @@ public int addVariableThisScope(String name) {

if (slot >= 0) return slot;

// Clear constructor since we are adding a name
constructor = null;

// This is perhaps innefficient timewise? Optimal spacewise
growVariableNames(name);

@@ -277,6 +280,9 @@ public int addVariable(String name) {

if (slot >= 0) return slot;

// Clear constructor since we are adding a name
constructor = null;

// This is perhaps innefficient timewise? Optimal spacewise
growVariableNames(name);

@@ -296,6 +302,9 @@ public void setVariables(String[] names) {
assert names != null : "names is not null";
assert namesAreInterned(names);

// Clear constructor since we are changing names
constructor = null;

variableNames = new String[names.length];
variableNamesLength = names.length;
System.arraycopy(names, 0, variableNames, 0, names.length);
57 changes: 29 additions & 28 deletions core/src/main/java/org/jruby/runtime/Signature.java
Original file line number Diff line number Diff line change
@@ -31,14 +31,14 @@ public static Rest fromOrdinal(int ordinal) {
}
}

public static final Signature NO_ARGUMENTS = new Signature(0, 0, 0, Rest.NONE, 0, 0, false);
public static final Signature ONE_ARGUMENT = new Signature(1, 0, 0, Rest.NONE, 0, 0, false);
public static final Signature TWO_ARGUMENTS = new Signature(2, 0, 0, Rest.NONE, 0, 0, false);
public static final Signature THREE_ARGUMENTS = new Signature(3, 0, 0, Rest.NONE, 0, 0, false);
public static final Signature OPTIONAL = new Signature(0, 0, 0, Rest.NORM, 0, 0, false);
public static final Signature ONE_REQUIRED = new Signature(1, 0, 0, Rest.NORM, 0, 0, false);
public static final Signature TWO_REQUIRED = new Signature(2, 0, 0, Rest.NORM, 0, 0, false);
public static final Signature THREE_REQUIRED = new Signature(3, 0, 0, Rest.NORM, 0, 0, false);
public static final Signature NO_ARGUMENTS = new Signature(0, 0, 0, Rest.NONE, 0, 0, -1);
public static final Signature ONE_ARGUMENT = new Signature(1, 0, 0, Rest.NONE, 0, 0, -1);
public static final Signature TWO_ARGUMENTS = new Signature(2, 0, 0, Rest.NONE, 0, 0, -1);
public static final Signature THREE_ARGUMENTS = new Signature(3, 0, 0, Rest.NONE, 0, 0, -1);
public static final Signature OPTIONAL = new Signature(0, 0, 0, Rest.NORM, 0, 0, -1);
public static final Signature ONE_REQUIRED = new Signature(1, 0, 0, Rest.NORM, 0, 0, -1);
public static final Signature TWO_REQUIRED = new Signature(2, 0, 0, Rest.NORM, 0, 0, -1);
public static final Signature THREE_REQUIRED = new Signature(3, 0, 0, Rest.NORM, 0, 0, -1);

private final short pre;
private final short opt;
@@ -47,16 +47,16 @@ public static Rest fromOrdinal(int ordinal) {
private final short kwargs;
private final short requiredKwargs;
private final Arity arity;
private final boolean restKwargs;
private final int keyRest;

public Signature(int pre, int opt, int post, Rest rest, int kwargs, int requiredKwargs, boolean restKwargs) {
public Signature(int pre, int opt, int post, Rest rest, int kwargs, int requiredKwargs, int keyRest) {
this.pre = (short) pre;
this.opt = (short) opt;
this.post = (short) post;
this.rest = rest;
this.kwargs = (short) kwargs;
this.requiredKwargs = (short) requiredKwargs;
this.restKwargs = restKwargs;
this.keyRest = keyRest;

// NOTE: Some logic to *assign* variables still uses Arity, which treats Rest.ANON (the
// |a,| form) as a rest arg for destructuring purposes. However ANON does *not*
@@ -74,15 +74,16 @@ public int getRequiredKeywordForArityCount() {
}

public boolean restKwargs() {
return restKwargs;
return keyRest != -1;
}

public int pre() { return pre; }
public int opt() { return opt; }
public Rest rest() { return rest; }
public int post() { return post; }
public boolean hasKwargs() { return kwargs > 0 || restKwargs; }
public boolean hasKwargs() { return kwargs > 0 || restKwargs(); }
public boolean hasRest() { return rest != Rest.NONE; }
public int keyRest() { return keyRest; }

/**
* Are there an exact (fixed) number of parameters to this signature?
@@ -128,8 +129,8 @@ public static Signature from(Arity arity) {
throw new UnsupportedOperationException("We do not know enough about the arity to convert it to a signature");
}

public static Signature from(int pre, int opt, int post, int kwargs, int requiredKwargs, Rest rest, boolean restKwargs) {
if (opt == 0 && post == 0 && kwargs == 0 && !restKwargs) {
public static Signature from(int pre, int opt, int post, int kwargs, int requiredKwargs, Rest rest, int keyRest) {
if (opt == 0 && post == 0 && kwargs == 0 && keyRest == -1) {
switch (pre) {
case 0:
switch (rest) {
@@ -165,15 +166,15 @@ public static Signature from(int pre, int opt, int post, int kwargs, int require
break;
}
}
return new Signature(pre, opt, post, rest, kwargs, requiredKwargs, restKwargs);
return new Signature(pre, opt, post, rest, kwargs, requiredKwargs, keyRest);
}

public static Signature from(ArgsNode args) {
ArgumentNode restArg = args.getRestArgNode();
Rest rest = restArg != null ? restFromArg(restArg) : Rest.NONE;

return Signature.from(args.getPreCount(), args.getOptionalArgsCount(), args.getPostCount(),
args.getKeywordCount(), args.getRequiredKeywordCount(),rest,args.hasKeyRest());
args.getKeywordCount(), args.getRequiredKeywordCount(),rest,args.hasKeyRest() ? args.getKeyRest().getIndex() : -1);
}

public static Signature from(IterNode iter) {
@@ -213,7 +214,7 @@ public static Signature from(ForNode iter) {
Node restArg = masgn.getRest();
rest = restFromArg(restArg);
}
return Signature.from(masgn.getPreCount(), 0, masgn.getPostCount(), 0, 0, rest, false);
return Signature.from(masgn.getPreCount(), 0, masgn.getPostCount(), 0, 0, rest, -1);
}
return Signature.ONE_ARGUMENT;
}
@@ -229,7 +230,7 @@ public static Signature from(PostExeNode iter) {
private static final int MAX_ENCODED_ARGS_EXPONENT = 8;
private static final int MAX_ENCODED_ARGS_MASK = 0xFF;
private static final int ENCODE_RESTKWARGS_SHIFT = 0;
private static final int ENCODE_REST_SHIFT = ENCODE_RESTKWARGS_SHIFT + 1;
private static final int ENCODE_REST_SHIFT = ENCODE_RESTKWARGS_SHIFT + MAX_ENCODED_ARGS_EXPONENT;
private static final int ENCODE_REQKWARGS_SHIFT = ENCODE_REST_SHIFT + MAX_ENCODED_ARGS_EXPONENT;
private static final int ENCODE_KWARGS_SHIFT = ENCODE_REQKWARGS_SHIFT + MAX_ENCODED_ARGS_EXPONENT;
private static final int ENCODE_POST_SHIFT = ENCODE_KWARGS_SHIFT + MAX_ENCODED_ARGS_EXPONENT;
@@ -244,24 +245,24 @@ public long encode() {
((long)kwargs << ENCODE_KWARGS_SHIFT) |
((long)requiredKwargs << ENCODE_REQKWARGS_SHIFT) |
(rest.ordinal() << ENCODE_REST_SHIFT) |
((restKwargs?1:0) << ENCODE_RESTKWARGS_SHIFT);
(keyRest & 0xFF) << ENCODE_RESTKWARGS_SHIFT;
}

public static Signature decode(long l) {
return Signature.from(
(int)(l >> ENCODE_PRE_SHIFT) & MAX_ENCODED_ARGS_MASK,
(int)(l >> ENCODE_OPT_SHIFT) & MAX_ENCODED_ARGS_MASK,
(int)(l >> ENCODE_POST_SHIFT) & MAX_ENCODED_ARGS_MASK,
(int)(l >> ENCODE_KWARGS_SHIFT) & MAX_ENCODED_ARGS_MASK,
(int)(l >> ENCODE_REQKWARGS_SHIFT) & MAX_ENCODED_ARGS_MASK,
Rest.fromOrdinal((int)((l >> ENCODE_REST_SHIFT) & MAX_ENCODED_ARGS_MASK)),
((int)(l >> ENCODE_RESTKWARGS_SHIFT) & 0x1)==1 ? true : false
(int)(l >>> ENCODE_PRE_SHIFT) & MAX_ENCODED_ARGS_MASK,
(int)(l >>> ENCODE_OPT_SHIFT) & MAX_ENCODED_ARGS_MASK,
(int)(l >>> ENCODE_POST_SHIFT) & MAX_ENCODED_ARGS_MASK,
(int)(l >>> ENCODE_KWARGS_SHIFT) & MAX_ENCODED_ARGS_MASK,
(int)(l >>> ENCODE_REQKWARGS_SHIFT) & MAX_ENCODED_ARGS_MASK,
Rest.fromOrdinal((int)((l >>> ENCODE_REST_SHIFT) & MAX_ENCODED_ARGS_MASK)),
(byte)(l >>> ENCODE_RESTKWARGS_SHIFT) & MAX_ENCODED_ARGS_MASK

);
}

public String toString() {
return "signature(pre=" + pre + ",opt=" + opt + ",post=" + post + ",rest=" + rest + ",kwargs=" + kwargs + ",kwreq=" + requiredKwargs + ",kwrest=" + restKwargs + ")";
return "signature(pre=" + pre + ",opt=" + opt + ",post=" + post + ",rest=" + rest + ",kwargs=" + kwargs + ",kwreq=" + requiredKwargs + ",kwrest=" + keyRest + ")";
}

public void checkArity(Ruby runtime, IRubyObject[] args) {
Original file line number Diff line number Diff line change
@@ -26,6 +26,7 @@
***** END LICENSE BLOCK *****/
package org.jruby.runtime.ivars;

import com.headius.unsafe.fences.UnsafeFences;
import org.jruby.RubyBasicObject;
import org.jruby.RubyClass;
import org.jruby.util.ArraySupport;
@@ -151,9 +152,9 @@ private static boolean createTableUnsafe(RubyBasicObject self, int currentStamp,
*/
private static boolean updateTableUnsafe(RubyBasicObject self, int currentStamp, Object[] currentTable, int index, Object value) {
// shared access to varTable field.
if(UnsafeHolder.SUPPORTS_FENCES) {
if(UnsafeFences.SUPPORTS_FENCES) {
currentTable[index] = value;
UnsafeHolder.fullFence();
UnsafeFences.fullFence();
} else {
// TODO: maybe optimize by read and checking current value before setting
UnsafeHolder.U.putObjectVolatile(currentTable, UnsafeHolder.ARRAY_OBJECT_BASE_OFFSET + UnsafeHolder.ARRAY_OBJECT_INDEX_SCALE * index, value);
8 changes: 3 additions & 5 deletions core/src/main/java/org/jruby/util/StringSupport.java
Original file line number Diff line number Diff line change
@@ -35,15 +35,13 @@
import org.jcodings.specific.UTF8Encoding;
import org.jcodings.util.IntHash;
import org.joni.Matcher;
import org.jruby.FlagRegistry;
import org.jruby.ObjectFlags;
import org.jruby.Ruby;
import org.jruby.RubyArray;
import org.jruby.RubyEncoding;
import org.jruby.RubyIO;
import org.jruby.RubyObject;
import org.jruby.RubyString;
import org.jruby.runtime.Block;
import org.jruby.runtime.Constants;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.util.collections.IntHashMap;
@@ -56,8 +54,8 @@
import java.util.List;

public final class StringSupport {
public static final int CR_7BIT_F = Constants.CR_7BIT_F;
public static final int CR_VALID_F = Constants.CR_VALID_F;
public static final int CR_7BIT_F = ObjectFlags.CR_7BIT_F;
public static final int CR_VALID_F = ObjectFlags.CR_VALID_F;
public static final int CR_UNKNOWN = 0;

// We hardcode these so they can be used in a switch below. The assert verifies they match FlagRegistry's value.
19 changes: 1 addition & 18 deletions core/src/main/java/org/jruby/util/unsafe/UnsafeHolder.java
Original file line number Diff line number Diff line change
@@ -37,8 +37,7 @@ private UnsafeHolder(){}
* Holds a reference to Unsafe if available, null otherwise.
*/
public static final sun.misc.Unsafe U = loadUnsafe();

public static final boolean SUPPORTS_FENCES = supportsFences();

public static final long ARRAY_OBJECT_BASE_OFFSET = arrayObjectBaseOffset();
public static final long ARRAY_OBJECT_INDEX_SCALE = arrayObjectIndexScale();

@@ -89,20 +88,4 @@ public static long fieldOffset(Class clazz, String name) {
return sun.misc.Unsafe.INVALID_FIELD_OFFSET;
}
}

//// The following methods are Java8 only. They will throw undefined method errors if invoked without checking for fence support

public static void fullFence() {
U.fullFence();
}

public static void loadFence() {
U.loadFence();
}

public static void storeFence() {
U.storeFence();
}


}
30 changes: 0 additions & 30 deletions core/src/main/resources/org/jruby/runtime/Constants.java
Original file line number Diff line number Diff line change
@@ -81,36 +81,6 @@ public final class Constants {
* The JIT threshold to the specified method invocation count.
*/
public static final int JIT_THRESHOLD = 50;

private static final FlagRegistry registry = new FlagRegistry();

// These flags must be registered from top of hierarchy down to maintain order.
// TODO: Replace these during the build with their calculated values.
public static final int FALSE_F = registry.newFlag(RubyBasicObject.class);
public static final int NIL_F = registry.newFlag(RubyBasicObject.class);
public static final int FROZEN_F = registry.newFlag(RubyBasicObject.class);
public static final int TAINTED_F = registry.newFlag(RubyBasicObject.class);

public static final int CACHEPROXY_F = registry.newFlag(RubyModule.class);
public static final int NEEDSIMPL_F = registry.newFlag(RubyModule.class);
public static final int REFINED_MODULE_F = registry.newFlag(RubyModule.class);
public static final int IS_OVERLAID_F = registry.newFlag(RubyModule.class);

public static final int CR_7BIT_F = registry.newFlag(RubyString.class);
public static final int CR_VALID_F = registry.newFlag(RubyString.class);

public static final int STRIO_READABLE = registry.newFlag(StringIO.class);
public static final int STRIO_WRITABLE = registry.newFlag(StringIO.class);

public static final int MATCH_BUSY = registry.newFlag(RubyMatchData.class);

public static final int COMPARE_BY_IDENTITY_F = registry.newFlag(RubyHash.class);
public static final int PROCDEFAULT_HASH_F = registry.newFlag(RubyHash.class);

private static final boolean DEBUG = false;
static {
if (DEBUG) registry.printFlags();
}

private static String jruby_revision = "@jruby.revision@";

4 changes: 2 additions & 2 deletions core/src/main/ruby/jruby/kernel/file.rb
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@
# Gracefully bail if FFI is not available
end

if defined?(::FFI)
if defined?(::FFI::Config)
module JRuby::Windows
module File
module Constants
@@ -231,4 +231,4 @@ def flock(operation)
end
end
end
end
end
4 changes: 1 addition & 3 deletions core/src/test/java/org/jruby/test/TestRubyBase.java
Original file line number Diff line number Diff line change
@@ -81,9 +81,7 @@ protected final String eval(String script, String fileName) throws Exception {
runtime.getGlobalVariables().set("$>", lStream);
runtime.getGlobalVariables().set("$stderr", lStream);

runtime.runNormally(
runtime.parseFile(new ByteArrayInputStream(script.getBytes()), fileName, runtime.getCurrentContext().getCurrentScope())
);
runtime.runFromMain(new ByteArrayInputStream(script.getBytes()), fileName);
StringBuffer sb = new StringBuffer(new String(result.toByteArray()));
for (int idx = sb.indexOf("\n"); idx != -1; idx = sb.indexOf("\n")) {
sb.deleteCharAt(idx);

0 comments on commit a14acdb

Please sign in to comment.