Skip to content

Commit

Permalink
Convert Backref operand to BuildBackrefInstr instruction
Browse files Browse the repository at this point in the history
* This is because Backref construction can throw exceptions and
  we currently assume that only instructions throw exceptions.

* This should fix the remaining test:mri:jit error with the
  explicit block call protocol enabled.

  The bug is not related to block call protocol changes, but was
  exposed by it.
subbuss committed Dec 19, 2015
1 parent a435287 commit ecf6cc9
Showing 8 changed files with 93 additions and 98 deletions.
3 changes: 1 addition & 2 deletions core/src/main/java/org/jruby/ir/IRBuilder.java
Original file line number Diff line number Diff line change
@@ -858,8 +858,7 @@ public Operand buildAttrAssignAssignment(Node node, Operand value) {
}

public Operand buildBackref(BackRefNode node) {
// SSS FIXME: Required? Verify with Tom/Charlie
return copyAndReturnValue(new Backref(node.getType()));
return addResultInstr(new BuildBackrefInstr(createTemporaryVariable(), node.getType()));
}

public Operand buildBegin(BeginNode beginNode) {
2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/ir/IRVisitor.java
Original file line number Diff line number Diff line change
@@ -41,6 +41,7 @@ private void error(Object object) {
public void BreakInstr(BreakInstr breakinstr) { error(breakinstr); }
public void BTrueInstr(BTrueInstr btrueinstr) { error(btrueinstr); }
public void BUndefInstr(BUndefInstr bundefinstr) { error(bundefinstr); }
public void BuildBackrefInstr(BuildBackrefInstr instr) { error(instr); }
public void BuildCompoundArrayInstr(BuildCompoundArrayInstr instr) { error(instr); }
public void BuildCompoundStringInstr(BuildCompoundStringInstr instr) { error(instr); }
public void BuildDynRegExpInstr(BuildDynRegExpInstr instr) { error(instr); }
@@ -156,7 +157,6 @@ private void error(Object object) {
// operands
public void Array(Array array) { error(array); }
public void AsString(AsString asstring) { error(asstring); }
public void Backref(Backref backref) { error(backref); }
public void Bignum(Bignum bignum) { error(bignum); }
public void Boolean(Boolean bool) { error(bool); }
public void UnboxedBoolean(UnboxedBoolean bool) { error(bool); }
3 changes: 2 additions & 1 deletion core/src/main/java/org/jruby/ir/Operation.java
Original file line number Diff line number Diff line change
@@ -140,14 +140,15 @@ public enum Operation {

/** JRuby-impl instructions **/
ARG_SCOPE_DEPTH(0),
BACKTICK_STRING(OpFlags.f_can_raise_exception),
BINDING_LOAD(OpFlags.f_is_load),
BINDING_STORE(OpFlags.f_is_store | OpFlags.f_has_side_effect),
BUILD_BACKREF(OpFlags.f_can_raise_exception),
BUILD_COMPOUND_ARRAY(OpFlags.f_can_raise_exception),
BUILD_COMPOUND_STRING(OpFlags.f_can_raise_exception),
BUILD_DREGEXP(OpFlags.f_can_raise_exception),
BUILD_RANGE(OpFlags.f_can_raise_exception),
BUILD_SPLAT(OpFlags.f_can_raise_exception),
BACKTICK_STRING(OpFlags.f_can_raise_exception),
CHECK_ARGS_ARRAY_ARITY(OpFlags.f_can_raise_exception),
CHECK_ARITY(OpFlags.f_is_book_keeping_op | OpFlags.f_can_raise_exception),
CHECK_FOR_LJE(OpFlags.f_has_side_effect | OpFlags.f_can_raise_exception),
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package org.jruby.ir.instructions;

import org.jruby.ir.IRVisitor;
import org.jruby.ir.Operation;
import org.jruby.ir.operands.Variable;
import org.jruby.RubyRegexp;
import org.jruby.ir.IRVisitor;
import org.jruby.ir.persistence.IRReaderDecoder;
import org.jruby.ir.persistence.IRWriterEncoder;
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;

// Represents a backref node in Ruby code
public class BuildBackrefInstr extends NoOperandResultBaseInstr {
final public char type;

public BuildBackrefInstr(Variable result, char t) {
super(Operation.BUILD_BACKREF, result);
type = t;
}

@Override
public void encode(IRWriterEncoder e) {
super.encode(e);
e.encode(type);
}

public static BuildBackrefInstr decode(IRReaderDecoder d) {
return new BuildBackrefInstr(d.decodeVariable(), d.decodeChar());
}

@Override
public Instr clone(CloneInfo ii) {
return new BuildBackrefInstr(ii.getRenamedVariable(result), type);
}

@Override
public String[] toStringNonOperandArgs() {
return new String[] {"$" + "'" + type + "'"};
}

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

switch (type) {
case '&' : return RubyRegexp.last_match(backref);
case '`' : return RubyRegexp.match_pre(backref);
case '\'': return RubyRegexp.match_post(backref);
case '+' : return RubyRegexp.match_last(backref);
default:
assert false: "backref with invalid type";
return null;
}
}

@Override
public void visit(IRVisitor visitor) {
visitor.BuildBackrefInstr(this);
}
}
66 changes: 0 additions & 66 deletions core/src/main/java/org/jruby/ir/operands/Backref.java

This file was deleted.

4 changes: 0 additions & 4 deletions core/src/main/java/org/jruby/ir/operands/OperandType.java
Original file line number Diff line number Diff line change
@@ -9,14 +9,10 @@ public enum OperandType {

ARRAY((byte) 'A'),
AS_STRING((byte) 'a'),
BACKREF((byte) '\\'),
BACKTICK_STRING((byte) '`'),
BIGNUM((byte) 'B'),
BOOLEAN((byte) 'b'),
LOCAL_VARIABLE((byte) 'l'), // Also applicable for ClosureLocalVariable
COMPLEX((byte) 'C'),
COMPOUND_ARRAY((byte) 'c'),
COMPOUND_STRING((byte) '"'),
CURRENT_SCOPE((byte) 's'),
DYNAMIC_SYMBOL((byte) 'd'),
FIXNUM((byte) 'f'),
Original file line number Diff line number Diff line change
@@ -200,6 +200,7 @@ public Instr decodeInstr() {
case BLOCK_GIVEN: return BlockGivenInstr.decode(this);
case BNE: return BNEInstr.decode(this);
case BREAK: return BreakInstr.decode(this);
case BUILD_BACKREF: return BuildBackrefInstr.decode(this);
case BUILD_COMPOUND_ARRAY: return BuildCompoundArrayInstr.decode(this);
case BUILD_COMPOUND_STRING: return BuildCompoundStringInstr.decode(this);
case BUILD_DREGEXP: return BuildDynRegExpInstr.decode(this);
@@ -429,7 +430,6 @@ public Operand decode(OperandType type) {
switch (type) {
case ARRAY: return Array.decode(this);
case AS_STRING: return AsString.decode(this);
case BACKREF: return Backref.decode(this);
case BIGNUM: return Bignum.decode(this);
case BOOLEAN: return org.jruby.ir.operands.Boolean.decode(this);
case CURRENT_SCOPE: return CurrentScope.decode(this);
47 changes: 24 additions & 23 deletions core/src/main/java/org/jruby/ir/targets/JVMVisitor.java
Original file line number Diff line number Diff line change
@@ -735,6 +735,30 @@ public void BUndefInstr(BUndefInstr bundefinstr) {
jvmAdapter().if_acmpeq(getJVMLabel(bundefinstr.getJumpTarget()));
}

@Override
public void BuildBackrefInstr(BuildBackrefInstr instr) {
jvmMethod().loadContext();
jvmAdapter().invokevirtual(p(ThreadContext.class), "getBackRef", sig(IRubyObject.class));

switch (instr.type) {
case '&':
jvmAdapter().invokestatic(p(RubyRegexp.class), "last_match", sig(IRubyObject.class, IRubyObject.class));
break;
case '`':
jvmAdapter().invokestatic(p(RubyRegexp.class), "match_pre", sig(IRubyObject.class, IRubyObject.class));
break;
case '\'':
jvmAdapter().invokestatic(p(RubyRegexp.class), "match_post", sig(IRubyObject.class, IRubyObject.class));
break;
case '+':
jvmAdapter().invokestatic(p(RubyRegexp.class), "match_last", sig(IRubyObject.class, IRubyObject.class));
break;
default:
assert false: "backref with invalid type";
}
jvmStoreLocal(instr.getResult());
}

@Override
public void BuildCompoundArrayInstr(BuildCompoundArrayInstr instr) {
jvmMethod().loadContext();
@@ -2063,29 +2087,6 @@ public void AsString(AsString asstring) {
jvmAdapter().invokeinterface(p(IRubyObject.class), "asString", sig(RubyString.class));
}

@Override
public void Backref(Backref backref) {
jvmMethod().loadContext();
jvmAdapter().invokevirtual(p(ThreadContext.class), "getBackRef", sig(IRubyObject.class));

switch (backref.type) {
case '&':
jvmAdapter().invokestatic(p(RubyRegexp.class), "last_match", sig(IRubyObject.class, IRubyObject.class));
break;
case '`':
jvmAdapter().invokestatic(p(RubyRegexp.class), "match_pre", sig(IRubyObject.class, IRubyObject.class));
break;
case '\'':
jvmAdapter().invokestatic(p(RubyRegexp.class), "match_post", sig(IRubyObject.class, IRubyObject.class));
break;
case '+':
jvmAdapter().invokestatic(p(RubyRegexp.class), "match_last", sig(IRubyObject.class, IRubyObject.class));
break;
default:
assert false: "backref with invalid type";
}
}

@Override
public void Bignum(Bignum bignum) {
jvmMethod().pushBignum(bignum.value);

0 comments on commit ecf6cc9

Please sign in to comment.