Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 0eb7937882bb
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 459fff97cdf7
Choose a head ref
  • 2 commits
  • 4 files changed
  • 1 contributor

Commits on Mar 18, 2015

  1. Copy the full SHA
    05b48fb View commit details
  2. Copy the full SHA
    459fff9 View commit details
6 changes: 3 additions & 3 deletions core/src/main/java/org/jruby/RubyString.java
Original file line number Diff line number Diff line change
@@ -5618,9 +5618,9 @@ public IRubyObject ascii_only_p(ThreadContext context) {
@JRubyMethod
public IRubyObject b(ThreadContext context) {
Encoding encoding = ASCIIEncoding.INSTANCE;
RubyString dup = (RubyString)dup();
dup.associateEncoding(encoding);
dup.clearCodeRange();
RubyString dup = strDup(context.runtime);
dup.modify19();
dup.setEncoding(encoding);
return dup;
}

11 changes: 9 additions & 2 deletions core/src/main/java/org/jruby/ir/runtime/IRRuntimeHelpers.java
Original file line number Diff line number Diff line change
@@ -1351,8 +1351,15 @@ public static VariableAccessor getVariableAccessorForWrite(IRubyObject object, S
}

@JIT
public static IRubyObject getVariableWithAccessor(IRubyObject self, VariableAccessor accessor, ThreadContext context) {
return Helpers.nullToNil((IRubyObject)accessor.get(self), context);
public static IRubyObject getVariableWithAccessor(IRubyObject self, VariableAccessor accessor, ThreadContext context, String name) {
IRubyObject result = (IRubyObject)accessor.get(self);
if (result == null) {
if (context.runtime.isVerbose()) {
context.runtime.getWarnings().warning(IRubyWarnings.ID.IVAR_NOT_INITIALIZED, "instance variable " + name + " not initialized");
}
result = context.nil;
}
return result;
}

@JIT
Original file line number Diff line number Diff line change
@@ -500,6 +500,6 @@ public void pushBlockBody(Handle handle, org.jruby.runtime.Signature signature,
private int variableCount = 0;
private Map<Integer, Type> variableTypes = new HashMap<Integer, Type>();
private Map<Integer, String> variableNames = new HashMap<Integer, String>();
private final Signature signature;
protected final Signature signature;
private final ClassData classData;
}
79 changes: 59 additions & 20 deletions core/src/main/java/org/jruby/ir/targets/IRBytecodeAdapter6.java
Original file line number Diff line number Diff line change
@@ -6,6 +6,8 @@

import com.headius.invokebinder.Signature;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.Map;

import org.jcodings.Encoding;
import org.jruby.Ruby;
@@ -58,7 +60,7 @@ public IRBytecodeAdapter6(SkinnyMethodAdapter adapter, Signature signature, Clas
}

public void pushFixnum(final long l) {
cacheValuePermanently(newFieldName("fixnum"), RubyFixnum.class, new Runnable() {
cacheValuePermanently("fixnum", RubyFixnum.class, keyFor("fixnum", l), new Runnable() {
@Override
public void run() {
loadRuntime();
@@ -69,7 +71,7 @@ public void run() {
}

public void pushFloat(final double d) {
cacheValuePermanently(newFieldName("float"), RubyFloat.class, new Runnable() {
cacheValuePermanently("float", RubyFloat.class, keyFor("float", Double.doubleToLongBits(d)), new Runnable() {
@Override
public void run() {
loadRuntime();
@@ -95,7 +97,7 @@ private String newFieldName(String baseName) {
* @param bl ByteList for the String to push
*/
public void pushFrozenString(final ByteList bl) {
cacheValuePermanently(newFieldName("frozenString"), RubyString.class, new Runnable() {
cacheValuePermanently("fstring", RubyString.class, keyFor("fstring", bl), new Runnable() {
@Override
public void run() {
loadRuntime();
@@ -107,7 +109,7 @@ public void run() {
}

public void pushByteList(final ByteList bl) {
cacheValuePermanently(newFieldName("byteList"), ByteList.class, new Runnable() {
cacheValuePermanently("byteList", ByteList.class, keyFor("bytelist", bl), new Runnable() {
@Override
public void run() {
loadRuntime();
@@ -118,22 +120,41 @@ public void run() {
});
}

public void cacheValuePermanently(String cacheField, Class type, Runnable construction) {
// FIXME: too much bytecode...make it a separate method?
Label done = new Label();
adapter.getClassVisitor().visitField(Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC, cacheField, ci(type), null, null).visitEnd();
adapter.getstatic(getClassData().clsName, cacheField, ci(type));
adapter.dup();
adapter.ifnonnull(done);
adapter.pop();
construction.run();
adapter.dup();
adapter.putstatic(getClassData().clsName, cacheField, ci(type));
adapter.label(done);
public void cacheValuePermanently(String what, Class type, Object key, Runnable construction) {
String cacheField = key == null ? null : cacheFieldNames.get(key);
if (cacheField == null) {
cacheField = newFieldName(what);
cacheFieldNames.put(key, cacheField);

SkinnyMethodAdapter tmp = adapter;
adapter = new SkinnyMethodAdapter(
adapter.getClassVisitor(),
Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC | Opcodes.ACC_SYNTHETIC,
cacheField,
sig(type, ThreadContext.class),
null,
null);
Label done = new Label();
adapter.getClassVisitor().visitField(Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC, cacheField, ci(type), null, null).visitEnd();
adapter.getstatic(getClassData().clsName, cacheField, ci(type));
adapter.dup();
adapter.ifnonnull(done);
adapter.pop();
construction.run();
adapter.dup();
adapter.putstatic(getClassData().clsName, cacheField, ci(type));
adapter.label(done);
adapter.areturn();
adapter.end();
adapter = tmp;
}

loadContext();
adapter.invokestatic(getClassData().clsName, cacheField, sig(type, ThreadContext.class));
}

public void pushRegexp(final ByteList source, final int options) {
cacheValuePermanently(newFieldName("regexp"), RubyRegexp.class, new Runnable() {
cacheValuePermanently("regexp", RubyRegexp.class, keyFor("regexp", source, options), new Runnable() {
@Override
public void run() {
loadContext();
@@ -144,6 +165,21 @@ public void run() {
});
}

private static String keyFor(Object... objs) {
StringBuilder sb = new StringBuilder();
for (Object obj : objs) {
if (obj instanceof ByteList) {
for (byte b : ((ByteList)obj).bytes()) sb.append(String.format("%2x", b));
sb.append('_');
sb.append(((ByteList)obj).getEncoding());
} else {
sb.append(obj.toString());
}
sb.append("_");
}
return sb.toString();
}

public void pushDRegexp(Runnable callback, RegexpOptions options, int arity) {
if (arity > MAX_ARGUMENTS) throw new NotCompilableException("dynamic regexp has more than " + MAX_ARGUMENTS + " elements");

@@ -197,7 +233,7 @@ public void pushDRegexp(Runnable callback, RegexpOptions options, int arity) {
}

public void pushSymbol(final String sym, final Encoding encoding) {
cacheValuePermanently(newFieldName("symbol"), RubySymbol.class, new Runnable() {
cacheValuePermanently("symbol", RubySymbol.class, keyFor("symbol", sym, encoding), new Runnable() {
@Override
public void run() {
loadRuntime();
@@ -217,7 +253,7 @@ public void loadRuntime() {
}

public void pushEncoding(final Encoding encoding) {
cacheValuePermanently(newFieldName("symbol"), RubySymbol.class, new Runnable() {
cacheValuePermanently("encoding", RubySymbol.class, keyFor("encoding", encoding), new Runnable() {
@Override
public void run() {
loadContext();
@@ -599,7 +635,8 @@ public void getField(String name) {
adapter.dup(); // self, self
cacheVariableAccessor(name, false); // self, accessor
loadContext(); // self, accessor, context
invokeIRHelper("getVariableWithAccessor", sig(IRubyObject.class, IRubyObject.class, VariableAccessor.class, ThreadContext.class));
adapter.ldc(name);
invokeIRHelper("getVariableWithAccessor", sig(IRubyObject.class, IRubyObject.class, VariableAccessor.class, ThreadContext.class, String.class));
}

/**
@@ -749,4 +786,6 @@ public void checkpoint() {
"callThreadPoll",
sig(void.class));
}

private final Map<Object, String> cacheFieldNames = new HashMap<>();
}