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: 79e53b1a276d
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 970afeeb00ea
Choose a head ref
  • 5 commits
  • 8 files changed
  • 1 contributor

Commits on May 20, 2016

  1. Copy the full SHA
    434e54e View commit details
  2. Copy the full SHA
    d5067a2 View commit details
  3. Centralize get/put field logic in Instr.interpret.

    Also:
    
    * Add VariableAccessor caching to PutField.
    * Make accessor transient in GetField so it doesn't print.
    headius committed May 20, 2016
    Copy the full SHA
    7d8b03e View commit details
  4. Copy the full SHA
    6e91ecb View commit details
  5. Copy the full SHA
    970afee View commit details
Original file line number Diff line number Diff line change
@@ -76,7 +76,7 @@ public InterpreterContext ensureInstrsReady() {
if (Options.IR_PRINT.load()) {
ByteArrayOutputStream baos = IRDumper.printIR(method, false, true);

LOG.info("Printing simple IR for " + method.getName(), "\n" + new String(baos.toByteArray()));
LOG.info("Printing simple IR for " + method.getName() + ":\n" + new String(baos.toByteArray()));
}
}

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

import org.jruby.ir.IRFlags;
import org.jruby.ir.IRScope;
import org.jruby.ir.IRVisitor;
import org.jruby.ir.Operation;
import org.jruby.ir.persistence.IRReaderDecoder;
@@ -50,4 +52,11 @@ public String[] toStringNonOperandArgs() {
public void check(ThreadContext context, DynamicScope dynamicScope, Block.Type blockType) {
IRRuntimeHelpers.checkForLJE(context, dynamicScope, maybeLambda, blockType);
}

@Override
public boolean computeScopeFlags(IRScope scope) {
super.computeScopeFlags(scope);
scope.getFlags().add(IRFlags.REQUIRES_DYNSCOPE);
return true;
}
}
20 changes: 19 additions & 1 deletion core/src/main/java/org/jruby/ir/instructions/GetFieldInstr.java
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
package org.jruby.ir.instructions;

import org.jruby.RubyClass;
import org.jruby.common.IRubyWarnings;
import org.jruby.ir.IRVisitor;
import org.jruby.ir.Operation;
import org.jruby.ir.operands.Operand;
import org.jruby.ir.operands.Variable;
import org.jruby.ir.persistence.IRReaderDecoder;
import org.jruby.ir.transformations.inlining.CloneInfo;
import org.jruby.parser.StaticScope;
import org.jruby.runtime.DynamicScope;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.ivars.VariableAccessor;

public class GetFieldInstr extends GetInstr implements FixedArityInstr {
private VariableAccessor accessor = VariableAccessor.DUMMY_ACCESSOR;
private transient VariableAccessor accessor = VariableAccessor.DUMMY_ACCESSOR;

public GetFieldInstr(Variable dest, Operand obj, String fieldName) {
super(Operation.GET_FIELD, dest, obj, fieldName);
@@ -38,6 +42,20 @@ public VariableAccessor getAccessor(IRubyObject o) {
return localAccessor;
}

@Override
public Object interpret(ThreadContext context, StaticScope currScope, DynamicScope currDynScope, IRubyObject self, Object[] temp) {
IRubyObject object = (IRubyObject) getSource().retrieve(context, self, currScope, currDynScope, temp);
VariableAccessor a = getAccessor(object);
Object result = a == null ? null : (IRubyObject)a.get(object);
if (result == null) {
if (context.runtime.isVerbose()) {
context.runtime.getWarnings().warning(IRubyWarnings.ID.IVAR_NOT_INITIALIZED, "instance variable " + getRef() + " not initialized");
}
result = context.nil;
}
return result;
}

@Override
public void visit(IRVisitor visitor) {
visitor.GetFieldInstr(this);
23 changes: 17 additions & 6 deletions core/src/main/java/org/jruby/ir/instructions/PutFieldInstr.java
Original file line number Diff line number Diff line change
@@ -10,8 +10,11 @@
import org.jruby.runtime.DynamicScope;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.ivars.VariableAccessor;

public class PutFieldInstr extends PutInstr implements FixedArityInstr {
private transient VariableAccessor accessor = VariableAccessor.DUMMY_ACCESSOR;

public PutFieldInstr(Operand obj, String fieldName, Operand value) {
super(Operation.PUT_FIELD, obj, fieldName, value);
}
@@ -21,17 +24,25 @@ public Instr clone(CloneInfo ii) {
return new PutFieldInstr(getTarget().cloneForInlining(ii), ref, getValue().cloneForInlining(ii));
}

public VariableAccessor getAccessor(IRubyObject o) {
RubyClass cls = o.getMetaClass().getRealClass();
VariableAccessor localAccessor = accessor;

if (localAccessor.getClassId() != cls.hashCode()) {
localAccessor = cls.getVariableAccessorForWrite(getRef());
accessor = localAccessor;
}
return localAccessor;
}

@Override
public Object interpret(ThreadContext context, StaticScope currScope, DynamicScope currDynScope, IRubyObject self, Object[] temp) {
IRubyObject object = (IRubyObject) getTarget().retrieve(context, self, currScope, currDynScope, temp);

// We store instance variable offsets on the real class, since instance var tables are associated with the
// natural type of an object.
RubyClass clazz = object.getMetaClass().getRealClass();
VariableAccessor a = getAccessor(object);
Object value = getValue().retrieve(context, self, currScope, currDynScope, temp);
a.set(object, value);

// FIXME: Should add this as a field for instruction
clazz.getVariableAccessorForWrite(getRef()).set(object,
getValue().retrieve(context, self, currScope, currDynScope, temp));
return null;
}

18 changes: 0 additions & 18 deletions core/src/main/java/org/jruby/ir/interpreter/InterpreterEngine.java
Original file line number Diff line number Diff line change
@@ -4,14 +4,12 @@
import org.jruby.RubyFixnum;
import org.jruby.RubyFloat;
import org.jruby.RubyModule;
import org.jruby.common.IRubyWarnings;
import org.jruby.exceptions.Unrescuable;
import org.jruby.ir.Operation;
import org.jruby.ir.instructions.BreakInstr;
import org.jruby.ir.instructions.CheckArityInstr;
import org.jruby.ir.instructions.CheckForLJEInstr;
import org.jruby.ir.instructions.CopyInstr;
import org.jruby.ir.instructions.GetFieldInstr;
import org.jruby.ir.instructions.Instr;
import org.jruby.ir.instructions.JumpInstr;
import org.jruby.ir.instructions.LineNumberInstr;
@@ -65,7 +63,6 @@
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.Visibility;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.ivars.VariableAccessor;
import org.jruby.runtime.opto.ConstantCache;

/**
@@ -463,21 +460,6 @@ protected static void processOtherOp(ThreadContext context, Block block, Instr i
break;
}

case GET_FIELD: {
GetFieldInstr gfi = (GetFieldInstr)instr;
IRubyObject object = (IRubyObject)gfi.getSource().retrieve(context, self, currScope, currDynScope, temp);
VariableAccessor a = gfi.getAccessor(object);
result = a == null ? null : (IRubyObject)a.get(object);
if (result == null) {
if (context.runtime.isVerbose()) {
context.runtime.getWarnings().warning(IRubyWarnings.ID.IVAR_NOT_INITIALIZED, "instance variable " + gfi.getRef() + " not initialized");
}
result = context.nil;
}
setResult(temp, currDynScope, gfi.getResult(), result);
break;
}

case SEARCH_CONST: {
SearchConstInstr sci = (SearchConstInstr)instr;
ConstantCache cache = sci.getConstantCache();
Original file line number Diff line number Diff line change
@@ -2,17 +2,13 @@

import java.util.HashMap;
import java.util.Map;
import org.jruby.RubyClass;
import org.jruby.RubyModule;
import org.jruby.common.IRubyWarnings;
import org.jruby.ir.OpClass;
import org.jruby.ir.Operation;
import org.jruby.ir.instructions.CopyInstr;
import org.jruby.ir.instructions.GetFieldInstr;
import org.jruby.ir.instructions.Instr;
import org.jruby.ir.instructions.JumpInstr;
import org.jruby.ir.instructions.LineNumberInstr;
import org.jruby.ir.instructions.PutFieldInstr;
import org.jruby.ir.instructions.ReceivePreReqdArgInstr;
import org.jruby.ir.instructions.ResultInstr;
import org.jruby.ir.instructions.ReturnBase;
@@ -29,7 +25,6 @@
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.Visibility;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.ivars.VariableAccessor;
import org.jruby.runtime.opto.ConstantCache;

/**
@@ -211,33 +206,6 @@ public IRubyObject interpret(ThreadContext context, Block block, IRubyObject sel
rhc.callHelper(context, currScope, currDynScope, self, temp, blockType));
break;
}
case GET_FIELD: { // NO INTERP
GetFieldInstr gfi = (GetFieldInstr)instr;
IRubyObject object = (IRubyObject)gfi.getSource().retrieve(context, self, currScope, currDynScope, temp);
VariableAccessor a = gfi.getAccessor(object);
Object result = a == null ? null : (IRubyObject)a.get(object);
if (result == null) {
if (context.runtime.isVerbose()) {
context.runtime.getWarnings().warning(IRubyWarnings.ID.IVAR_NOT_INITIALIZED, "instance variable " + gfi.getRef() + " not initialized");
}
result = context.nil;
}
setResult(temp, currDynScope, gfi.getResult(), result);
break;
}
case PUT_FIELD: {
PutFieldInstr putField = (PutFieldInstr) instr;
IRubyObject object = (IRubyObject) putField.getTarget().retrieve(context, self, currScope, currDynScope, temp);

// We store instance variable offsets on the real class, since instance var tables are associated with the
// natural type of an object.
RubyClass clazz = object.getMetaClass().getRealClass();

// FIXME: Should add this as a field for instruction
clazz.getVariableAccessorForWrite(putField.getRef()).set(object,
putField.getValue().retrieve(context, self, currScope, currDynScope, temp));
break;
}

case BUILD_COMPOUND_STRING: case CONST_MISSING:
default:
@@ -413,33 +381,6 @@ public IRubyObject interpret(ThreadContext context, Block block, IRubyObject sel
rhc.callHelper(context, currScope, currDynScope, self, temp, blockType));
break;
}
case GET_FIELD: { // NO INTERP
GetFieldInstr gfi = (GetFieldInstr)instr;
IRubyObject object = (IRubyObject)gfi.getSource().retrieve(context, self, currScope, currDynScope, temp);
VariableAccessor a = gfi.getAccessor(object);
Object result = a == null ? null : (IRubyObject)a.get(object);
if (result == null) {
if (context.runtime.isVerbose()) {
context.runtime.getWarnings().warning(IRubyWarnings.ID.IVAR_NOT_INITIALIZED, "instance variable " + gfi.getRef() + " not initialized");
}
result = context.nil;
}
setResult(temp, currDynScope, gfi.getResult(), result);
break;
}
case PUT_FIELD: {
PutFieldInstr putField = (PutFieldInstr) instr;
IRubyObject object = (IRubyObject) putField.getTarget().retrieve(context, self, currScope, currDynScope, temp);

// We store instance variable offsets on the real class, since instance var tables are associated with the
// natural type of an object.
RubyClass clazz = object.getMetaClass().getRealClass();

// FIXME: Should add this as a field for instruction
clazz.getVariableAccessorForWrite(putField.getRef()).set(object,
putField.getValue().retrieve(context, self, currScope, currDynScope, temp));
break;
}

case BUILD_COMPOUND_STRING: case CONST_MISSING:
default:
@@ -616,33 +557,6 @@ public IRubyObject interpret(ThreadContext context, Block block, IRubyObject sel
rhc.callHelper(context, currScope, currDynScope, self, temp, blockType));
break;
}
case GET_FIELD: { // NO INTERP
GetFieldInstr gfi = (GetFieldInstr)instr;
IRubyObject object = (IRubyObject)gfi.getSource().retrieve(context, self, currScope, currDynScope, temp);
VariableAccessor a = gfi.getAccessor(object);
Object result = a == null ? null : (IRubyObject)a.get(object);
if (result == null) {
if (context.runtime.isVerbose()) {
context.runtime.getWarnings().warning(IRubyWarnings.ID.IVAR_NOT_INITIALIZED, "instance variable " + gfi.getRef() + " not initialized");
}
result = context.nil;
}
setResult(temp, currDynScope, gfi.getResult(), result);
break;
}
case PUT_FIELD: {
PutFieldInstr putField = (PutFieldInstr) instr;
IRubyObject object = (IRubyObject) putField.getTarget().retrieve(context, self, currScope, currDynScope, temp);

// We store instance variable offsets on the real class, since instance var tables are associated with the
// natural type of an object.
RubyClass clazz = object.getMetaClass().getRealClass();

// FIXME: Should add this as a field for instruction
clazz.getVariableAccessorForWrite(putField.getRef()).set(object,
putField.getValue().retrieve(context, self, currScope, currDynScope, temp));
break;
}

case BUILD_COMPOUND_STRING: case CONST_MISSING:
default:
@@ -820,33 +734,6 @@ public IRubyObject interpret(ThreadContext context, Block block, IRubyObject sel
rhc.callHelper(context, currScope, currDynScope, self, temp, blockType));
break;
}
case GET_FIELD: { // NO INTERP
GetFieldInstr gfi = (GetFieldInstr)instr;
IRubyObject object = (IRubyObject)gfi.getSource().retrieve(context, self, currScope, currDynScope, temp);
VariableAccessor a = gfi.getAccessor(object);
Object result = a == null ? null : (IRubyObject)a.get(object);
if (result == null) {
if (context.runtime.isVerbose()) {
context.runtime.getWarnings().warning(IRubyWarnings.ID.IVAR_NOT_INITIALIZED, "instance variable " + gfi.getRef() + " not initialized");
}
result = context.nil;
}
setResult(temp, currDynScope, gfi.getResult(), result);
break;
}
case PUT_FIELD: {
PutFieldInstr putField = (PutFieldInstr) instr;
IRubyObject object = (IRubyObject) putField.getTarget().retrieve(context, self, currScope, currDynScope, temp);

// We store instance variable offsets on the real class, since instance var tables are associated with the
// natural type of an object.
RubyClass clazz = object.getMetaClass().getRealClass();

// FIXME: Should add this as a field for instruction
clazz.getVariableAccessorForWrite(putField.getRef()).set(object,
putField.getValue().retrieve(context, self, currScope, currDynScope, temp));
break;
}

case BUILD_COMPOUND_STRING: case CONST_MISSING:
default:
@@ -1016,33 +903,6 @@ public IRubyObject interpret(ThreadContext context, Block block, IRubyObject sel
rhc.callHelper(context, currScope, currDynScope, self, temp, blockType));
break;
}
case GET_FIELD: { // NO INTERP
GetFieldInstr gfi = (GetFieldInstr)instr;
IRubyObject object = (IRubyObject)gfi.getSource().retrieve(context, self, currScope, currDynScope, temp);
VariableAccessor a = gfi.getAccessor(object);
Object result = a == null ? null : (IRubyObject)a.get(object);
if (result == null) {
if (context.runtime.isVerbose()) {
context.runtime.getWarnings().warning(IRubyWarnings.ID.IVAR_NOT_INITIALIZED, "instance variable " + gfi.getRef() + " not initialized");
}
result = context.nil;
}
setResult(temp, currDynScope, gfi.getResult(), result);
break;
}
case PUT_FIELD: {
PutFieldInstr putField = (PutFieldInstr) instr;
IRubyObject object = (IRubyObject) putField.getTarget().retrieve(context, self, currScope, currDynScope, temp);

// We store instance variable offsets on the real class, since instance var tables are associated with the
// natural type of an object.
RubyClass clazz = object.getMetaClass().getRealClass();

// FIXME: Should add this as a field for instruction
clazz.getVariableAccessorForWrite(putField.getRef()).set(object,
putField.getValue().retrieve(context, self, currScope, currDynScope, temp));
break;
}

case BUILD_COMPOUND_STRING: case CONST_MISSING:
default:
12 changes: 11 additions & 1 deletion core/src/main/java/org/jruby/runtime/ivars/VariableAccessor.java
Original file line number Diff line number Diff line change
@@ -134,7 +134,17 @@ public void set(Object object, Object value) {
public boolean verify(Object object) {
return ((RubyBasicObject)object).getMetaClass().getRealClass() == this.realClass;
}


/**
* Produce a string representation of this VariableAccessor.
*
* @return a string representation of this VariableAccessor
*/
@Override
public String toString() {
return "ivar:" + getName() + ":" + index;
}

/** a dummy accessor that will always return null */
public static final VariableAccessor DUMMY_ACCESSOR = new VariableAccessor(null, null, -1, -1);

1 change: 1 addition & 0 deletions rakelib/test.rake
Original file line number Diff line number Diff line change
@@ -115,6 +115,7 @@ namespace :test do
t.ruby_opts << '-Xaot.loadClasses=true' # disabled by default now
t.ruby_opts << '-I.'
t.ruby_opts << '-J-ea'
t.ruby_opts << '--headless'
classpath = %w[test test/target/test-classes core/target/test-classes].join(File::PATH_SEPARATOR)
t.ruby_opts << "-J-cp #{classpath}"
end