Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge branch 'master' into truffle-head
  • Loading branch information
chrisseaton committed Oct 22, 2014
2 parents f346382 + ad74ecb commit 7e37a41
Show file tree
Hide file tree
Showing 72 changed files with 2,230 additions and 1,207 deletions.
58 changes: 47 additions & 11 deletions core/src/main/java/org/jruby/Ruby.java
Expand Up @@ -39,6 +39,9 @@
***** END LICENSE BLOCK *****/
package org.jruby;

import org.jruby.compiler.Constantizable;
import org.jruby.compiler.NotCompilableException;
import org.objectweb.asm.util.TraceClassVisitor;
import jnr.constants.Constant;
import jnr.constants.ConstantSet;
import jnr.constants.platform.Errno;
Expand All @@ -51,6 +54,7 @@
import org.jruby.ast.RootNode;
import org.jruby.ast.executable.RuntimeCache;
import org.jruby.ast.executable.Script;
import org.jruby.ast.executable.ScriptAndCode;
import org.jruby.common.IRubyWarnings.ID;
import org.jruby.common.RubyWarnings;
import org.jruby.compiler.JITCompiler;
Expand Down Expand Up @@ -136,6 +140,7 @@
import org.jruby.util.io.SelectorPool;
import org.jruby.util.log.Logger;
import org.jruby.util.log.LoggerFactory;
import org.objectweb.asm.ClassReader;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
Expand All @@ -144,6 +149,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.net.BindException;
import java.net.MalformedURLException;
Expand Down Expand Up @@ -190,7 +196,7 @@
* provides a number of utility methods for constructing global types and
* accessing global runtime structures.
*/
public final class Ruby {
public final class Ruby implements Constantizable {

/**
* The logger used to log relevant bits.
Expand All @@ -216,6 +222,8 @@ private Ruby(RubyInstanceConfig config) {
this.profiledMethods = null;
this.profilingServiceLookup = null;
}

constant = OptoFactory.newConstantWrapper(Ruby.class, this);

getJRubyClassLoader(); // force JRubyClassLoader to init if possible

Expand Down Expand Up @@ -712,14 +720,14 @@ public IRubyObject runNormally(Node scriptNode, boolean unused) {
* @return The result of executing the script
*/
public IRubyObject runNormally(Node scriptNode) {
Script script = null;
ScriptAndCode scriptAndCode = null;
boolean compile = getInstanceConfig().getCompileMode().shouldPrecompileCLI();
if (compile || config.isShowBytecode()) {
// IR JIT does not handle all scripts yet, so let those that fail run in interpreter instead
// FIXME: restore error once JIT should handle everything
try {
script = tryCompile(scriptNode, new JRubyClassLoader(getJRubyClassLoader()));
if (Options.JIT_LOGGING.load()) {
scriptAndCode = tryCompile(scriptNode, new JRubyClassLoader(getJRubyClassLoader()));
if (scriptAndCode != null && Options.JIT_LOGGING.load()) {
LOG.info("done compiling target script: " + scriptNode.getPosition().getFile());
}
} catch (Exception e) {
Expand All @@ -732,12 +740,15 @@ public IRubyObject runNormally(Node scriptNode) {
}
}

if (script != null) {
if (scriptAndCode != null) {
if (config.isShowBytecode()) {
TraceClassVisitor tracer = new TraceClassVisitor(new PrintWriter(System.err));
ClassReader reader = new ClassReader(scriptAndCode.bytecode());
reader.accept(tracer, 0);
return getNil();
}

return runScript(script);
return runScript(scriptAndCode.script());
} else {
// FIXME: temporarily allowing JIT to fail for $0 and fall back on interpreter
// failForcedCompile(scriptNode);
Expand All @@ -755,7 +766,7 @@ public IRubyObject runNormally(Node scriptNode) {
* @return an instance of the successfully-compiled Script, or null.
*/
public Script tryCompile(Node node) {
return tryCompile(node, new JRubyClassLoader(getJRubyClassLoader()));
return tryCompile(node, new JRubyClassLoader(getJRubyClassLoader())).script();
}

private void failForcedCompile(Node scriptNode) throws RaiseException {
Expand All @@ -771,8 +782,18 @@ private void handeCompileError(Node node, Throwable t) {
}
}

private Script tryCompile(Node node, JRubyClassLoader classLoader) {
return Compiler.getInstance().execute(this, node, classLoader);
private ScriptAndCode tryCompile(Node node, JRubyClassLoader classLoader) {
try {
return Compiler.getInstance().execute(this, node, classLoader);
} catch (NotCompilableException e) {
if (Options.JIT_LOGGING.load()) {
LOG.error("failed to compile target script " + node.getPosition().getFile() + ": " + e.getLocalizedMessage());
if (Options.JIT_LOGGING_VERBOSE.load()) {
LOG.error(e);
}
}
return null;
}
}

public IRubyObject runScript(Script script) {
Expand Down Expand Up @@ -2888,7 +2909,7 @@ public void compileAndLoadFile(String filename, InputStream in, boolean wrap) {
// script was not found in cache above, so proceed to compile
Node scriptNode = parseFile(readStream, filename, null);
if (script == null) {
script = tryCompile(scriptNode, new JRubyClassLoader(jrubyClassLoader));
script = tryCompile(scriptNode, new JRubyClassLoader(jrubyClassLoader)).script();
}

if (script == null) {
Expand Down Expand Up @@ -4622,6 +4643,14 @@ private void setNetworkStack() {
}
}

/**
* @see org.jruby.compiler.Constantizable
*/
@Override
public Object constant() {
return constant;
}

@Deprecated
public int getSafeLevel() {
return 0;
Expand Down Expand Up @@ -4703,7 +4732,8 @@ public FilenoUtil getFilenoUtil() {
private IRubyObject[] singleNilArray;
private RubyBoolean trueObject;
private RubyBoolean falseObject;
public final RubyFixnum[] fixnumCache = new RubyFixnum[2 * RubyFixnum.CACHE_OFFSET];
final RubyFixnum[] fixnumCache = new RubyFixnum[2 * RubyFixnum.CACHE_OFFSET];
final Object[] fixnumConstants = new Object[fixnumCache.length];

private boolean verbose, warningsEnabled, debug;
private IRubyObject verboseValue;
Expand Down Expand Up @@ -4973,4 +5003,10 @@ public void addToObjectSpace(boolean useObjectSpace, IRubyObject object) {
private final org.jruby.management.Runtime runtimeBean;

private final FilenoUtil filenoUtil = new FilenoUtil();

/**
* A representation of this runtime as a JIT-optimizable constant. Used for e.g. invokedynamic binding of runtime
* accesses.
*/
private final Object constant;
}
1 change: 1 addition & 0 deletions core/src/main/java/org/jruby/RubyBasicObject.java
Expand Up @@ -64,6 +64,7 @@
import org.jruby.runtime.builtin.Variable;
import org.jruby.runtime.component.VariableEntry;
import org.jruby.runtime.marshal.CoreObjectType;
import org.jruby.runtime.opto.OptoFactory;
import org.jruby.util.IdUtil;
import org.jruby.util.TypeConverter;
import org.jruby.util.io.EncodingUtils;
Expand Down
15 changes: 14 additions & 1 deletion core/src/main/java/org/jruby/RubyBoolean.java
Expand Up @@ -34,20 +34,23 @@

import org.jruby.anno.JRubyClass;
import org.jruby.anno.JRubyMethod;
import org.jruby.compiler.Constantizable;
import org.jruby.runtime.ClassIndex;
import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.marshal.MarshalStream;
import org.jruby.runtime.opto.OptoFactory;

/**
*
* @author jpetersen
*/
@JRubyClass(name={"TrueClass", "FalseClass"})
public class RubyBoolean extends RubyObject {
public class RubyBoolean extends RubyObject implements Constantizable {

private final int hashCode;
private final Object constant;

RubyBoolean(Ruby runtime, boolean value) {
super(runtime,
Expand All @@ -63,6 +66,8 @@ public class RubyBoolean extends RubyObject {
// save the object id based hash code;
this.hashCode = System.identityHashCode(this);
}

constant = OptoFactory.newConstantWrapper(IRubyObject.class, this);
}

@Override
Expand All @@ -85,6 +90,14 @@ public Class<?> getJavaClass() {
return boolean.class;
}

/**
* @see org.jruby.compiler.Constantizable
*/
@Override
public Object constant() {
return constant;
}

public static RubyClass createFalseClass(Ruby runtime) {
RubyClass falseClass = runtime.defineClass("FalseClass", runtime.getObject(), ObjectAllocator.NOT_ALLOCATABLE_ALLOCATOR);
runtime.setFalseClass(falseClass);
Expand Down
30 changes: 21 additions & 9 deletions core/src/main/java/org/jruby/RubyEncoding.java
Expand Up @@ -41,19 +41,21 @@
import org.jcodings.util.Hash.HashEntryIterator;
import org.jruby.anno.JRubyClass;
import org.jruby.anno.JRubyMethod;
import org.jruby.compiler.Constantizable;
import org.jruby.runtime.ClassIndex;
import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.encoding.EncodingCapable;
import org.jruby.runtime.encoding.EncodingService;
import org.jruby.runtime.opto.OptoFactory;
import org.jruby.util.ByteList;
import org.jruby.util.StringSupport;
import org.jruby.util.io.EncodingUtils;
import org.jruby.util.unsafe.UnsafeHolder;

@JRubyClass(name="Encoding")
public class RubyEncoding extends RubyObject {
public class RubyEncoding extends RubyObject implements Constantizable {
public static final Charset UTF8 = Charset.forName("UTF-8");
public static final Charset UTF16 = Charset.forName("UTF-16");
public static final Charset ISO = Charset.forName("ISO-8859-1");
Expand All @@ -76,29 +78,39 @@ public static RubyClass createEncodingClass(Ruby runtime) {
private Encoding encoding;
private final ByteList name;
private final boolean isDummy;
private final Object constant;

private RubyEncoding(Ruby runtime, byte[] name, int p, int end, boolean isDummy) {
super(runtime, runtime.getEncoding());
this.name = new ByteList(name, p, end);
this.isDummy = isDummy;
this(runtime, new ByteList(name, p, end), null, isDummy);
}

private RubyEncoding(Ruby runtime, byte[] name, boolean isDummy) {
this(runtime, name, 0, name.length, isDummy);
}

private RubyEncoding(Ruby runtime, Encoding encoding) {
super(runtime, runtime.getEncoding());
this.name = new ByteList(encoding.getName());
this.isDummy = false;
this.encoding = encoding;
this(runtime, new ByteList(encoding.getName()), encoding, false);
}

private RubyEncoding(Ruby runtime, byte[] name, Encoding encoding, boolean isDummy) {
this(runtime, new ByteList(name), encoding, isDummy);
}

private RubyEncoding(Ruby runtime, ByteList name, Encoding encoding, boolean isDummy) {
super(runtime, runtime.getEncoding());
this.name = new ByteList(name);
this.name = name;
this.isDummy = isDummy;
this.encoding = encoding;

this.constant = OptoFactory.newConstantWrapper(RubyEncoding.class, this);
}

/**
* @see org.jruby.compiler.Constantizable
*/
@Override
public Object constant() {
return constant;
}

public static RubyEncoding newEncoding(Ruby runtime, byte[] name, int p, int end, boolean isDummy) {
Expand Down
25 changes: 24 additions & 1 deletion core/src/main/java/org/jruby/RubyFixnum.java
Expand Up @@ -39,6 +39,7 @@
import org.jcodings.specific.USASCIIEncoding;
import org.jruby.anno.JRubyClass;
import org.jruby.anno.JRubyMethod;
import org.jruby.compiler.Constantizable;
import org.jruby.runtime.Arity;
import org.jruby.runtime.Block;
import org.jruby.runtime.BlockBody;
Expand All @@ -48,6 +49,7 @@
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.marshal.UnmarshalStream;
import org.jruby.runtime.opto.OptoFactory;
import org.jruby.util.ByteList;
import org.jruby.util.ConvertBytes;
import org.jruby.util.Numeric;
Expand All @@ -61,7 +63,7 @@
* Implementation of the Fixnum class.
*/
@JRubyClass(name="Fixnum", parent="Integer", include="Precision")
public class RubyFixnum extends RubyInteger {
public class RubyFixnum extends RubyInteger implements Constantizable {

public static RubyClass createFixnumClass(Ruby runtime) {
RubyClass fixnum = runtime.defineClass("Fixnum", runtime.getInteger(),
Expand Down Expand Up @@ -125,6 +127,27 @@ private RubyFixnum(RubyClass klazz, long value) {
public ClassIndex getNativeClassIndex() {
return ClassIndex.FIXNUM;
}

/**
* @see org.jruby.compiler.Constantizable
*/
@Override
public Object constant() {
Object constant = null;
long value = this.value;

if (value < CACHE_OFFSET && value >= -CACHE_OFFSET) {
Object[] fixnumConstants = getRuntime().fixnumConstants;
constant = fixnumConstants[(int) value + CACHE_OFFSET];

if (constant == null) {
constant = OptoFactory.newConstantWrapper(IRubyObject.class, this);
fixnumConstants[(int) value + CACHE_OFFSET] = constant;
}
}

return constant;
}

/**
* short circuit for Fixnum key comparison
Expand Down
15 changes: 14 additions & 1 deletion core/src/main/java/org/jruby/RubyNil.java
Expand Up @@ -34,19 +34,22 @@

import org.jruby.anno.JRubyMethod;
import org.jruby.anno.JRubyClass;
import org.jruby.compiler.Constantizable;
import org.jruby.runtime.ClassIndex;
import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.opto.OptoFactory;

/**
*
* @author jpetersen
*/
@JRubyClass(name="NilClass")
public class RubyNil extends RubyObject {
public class RubyNil extends RubyObject implements Constantizable {

private final int hashCode;
private final Object constant;

public RubyNil(Ruby runtime) {
super(runtime, runtime.getNilClass(), false);
Expand All @@ -59,6 +62,8 @@ public RubyNil(Ruby runtime) {
// save the object id based hash code;
this.hashCode = System.identityHashCode(this);
}

constant = OptoFactory.newConstantWrapper(IRubyObject.class, this);
}

public static final ObjectAllocator NIL_ALLOCATOR = new ObjectAllocator() {
Expand Down Expand Up @@ -103,6 +108,14 @@ public RubyClass getSingletonClass() {
public Class<?> getJavaClass() {
return void.class;
}

/**
* @see org.jruby.compiler.Constantizable
*/
@Override
public Object constant() {
return constant;
}

// Methods of the Nil Class (nil_*):

Expand Down

0 comments on commit 7e37a41

Please sign in to comment.