Thanks to visit codestin.com
Credit goes to github.com

Skip to content

JIT size and perf improvements #7589

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Feb 6, 2023
6 changes: 5 additions & 1 deletion core/src/main/java/org/jruby/ir/IRBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import org.jruby.RubyRational;
import org.jruby.RubySymbol;
import org.jruby.ast.*;
import org.jruby.ast.types.ILiteralNode;
import org.jruby.ast.types.INameNode;
import org.jruby.common.IRubyWarnings;
import org.jruby.compiler.NotCompilableException;
Expand Down Expand Up @@ -628,8 +629,11 @@ public Operand buildMultipleAsgn19(MultipleAsgnNode multipleAsgnNode) {
Node valueNode = multipleAsgnNode.getValueNode();
Operand values = build(valueNode);
Variable ret = getValueInTemporaryVariable(values);
if (valueNode instanceof ArrayNode) {
if (valueNode instanceof ArrayNode || valueNode instanceof ZArrayNode) {
buildMultipleAsgn19Assignment(multipleAsgnNode, null, ret);
} else if (valueNode instanceof ILiteralNode) {
// treat a single literal value as a single-element array
buildMultipleAsgn19Assignment(multipleAsgnNode, null, new Array(new Operand[]{ret}));
} else {
Variable tmp = createTemporaryVariable();
addInstr(new ToAryInstr(tmp, ret));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ public Encoding getEncoding() {
return encoding;
}

public int getInitialSize() {
return estimatedSize * 3 / 2;
}

@Override
public Instr clone(CloneInfo ii) {
return new BuildCompoundStringInstr(ii.getRenamedVariable(result), cloneOperands(ii), encoding, estimatedSize, frozen, debug, file, line);
Expand All @@ -71,7 +75,7 @@ public static BuildCompoundStringInstr decode(IRReaderDecoder d) {
@Override
public Object interpret(ThreadContext context, StaticScope currScope, DynamicScope currDynScope, IRubyObject self, Object[] temp) {
// use estimatedSize * 1.5 to give some initial room for interpolation
RubyString str = RubyString.newStringLight(context.runtime, estimatedSize * 3 / 2, encoding);
RubyString str = RubyString.newStringLight(context.runtime, getInitialSize(), encoding);

for (Operand p : getOperands()) {
if (p instanceof StringLiteral) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import org.jruby.ir.IRVisitor;
import org.jruby.ir.Operation;
import org.jruby.ir.operands.Array;
import org.jruby.ir.operands.Nil;
import org.jruby.ir.operands.Operand;
import org.jruby.ir.operands.Variable;
import org.jruby.ir.persistence.IRReaderDecoder;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,11 @@ public IRubyObject interpret(ThreadContext context, Block block, IRubyObject sel
public IRubyObject interpret(ThreadContext context, Block block, IRubyObject self,
InterpreterContext interpreterContext, RubyModule implClass,
String name, IRubyObject arg1, IRubyObject arg2, IRubyObject arg3, Block blockArg) {
return interpret(context, block, self, interpreterContext, implClass, name, new IRubyObject[] {arg1, arg2, arg3}, blockArg);
try {
return interpret(context, block, self, interpreterContext, implClass, name, new IRubyObject[] {arg1, arg2, arg3}, blockArg);
} catch (ArrayStoreException ase) {
throw ase;
}
}

public IRubyObject interpret(ThreadContext context, Block block, IRubyObject self,
Expand Down
4 changes: 3 additions & 1 deletion core/src/main/java/org/jruby/ir/persistence/IRDumper.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,19 @@
import org.jruby.ir.operands.IRException;
import org.jruby.ir.operands.Label;
import org.jruby.ir.operands.LocalVariable;
import org.jruby.ir.operands.MutableString;
import org.jruby.ir.operands.Nil;
import org.jruby.ir.operands.NthRef;
import org.jruby.ir.operands.NullBlock;
import org.jruby.ir.operands.Operand;
import org.jruby.ir.operands.Range;
import org.jruby.ir.operands.Rational;
import org.jruby.ir.operands.Regexp;
import org.jruby.ir.operands.SValue;
import org.jruby.ir.operands.ScopeModule;
import org.jruby.ir.operands.Self;
import org.jruby.ir.operands.Splat;
import org.jruby.ir.operands.StandardError;
import org.jruby.ir.operands.MutableString;
import org.jruby.ir.operands.Symbol;
import org.jruby.ir.operands.SymbolProc;
import org.jruby.ir.operands.TemporaryBooleanVariable;
Expand Down Expand Up @@ -324,6 +325,7 @@ public void Nil(Nil nil) { }
public void NthRef(NthRef nthref) { print(nthref.getId()); }
public void NullBlock(NullBlock nullblock) { }
public void Rational(Rational rational) { print(rational.getNumerator() + "/" + rational.getDenominator()); }
public void Range(Range range) { print(range.getBegin() + (range.isExclusive() ? "..." : "..") + range.getEnd()); }
public void Regexp(Regexp regexp) { print(regexp.getSource()); }
public void ScopeModule(ScopeModule scopemodule) { print(scopemodule.getScopeModuleDepth()); }
public void Self(Self self) { print("%self"); }
Expand Down
51 changes: 36 additions & 15 deletions core/src/main/java/org/jruby/ir/runtime/IRRuntimeHelpers.java
Original file line number Diff line number Diff line change
Expand Up @@ -1984,6 +1984,42 @@ public static RubyArray splatArray(ThreadContext context, IRubyObject ary, boole
return (RubyArray) tmp;
}

/**
* Call to_ary to get Array or die typing. The optionally dup it if specified. Some conditional
* cases in compiler we know we are safe in not-duping. This method is the same impl as MRIs
* splatarray instr in the YARV instruction set.
*/
@JIT @Interp
public static RubyArray splatArray(ThreadContext context, IRubyObject ary) {
Ruby runtime = context.runtime;
IRubyObject tmp = TypeConverter.convertToTypeWithCheck(context, ary, runtime.getArray(), sites(context).to_a_checked);

if (tmp.isNil()) {
tmp = runtime.newArray(ary);
}

return (RubyArray) tmp;
}

/**
* Call to_ary to get Array or die typing. The optionally dup it if specified. Some conditional
* cases in compiler we know we are safe in not-duping. This method is the same impl as MRIs
* splatarray instr in the YARV instruction set.
*/
@JIT @Interp
public static RubyArray splatArrayDup(ThreadContext context, IRubyObject ary) {
Ruby runtime = context.runtime;
IRubyObject tmp = TypeConverter.convertToTypeWithCheck(context, ary, runtime.getArray(), sites(context).to_a_checked);

if (tmp.isNil()) {
tmp = runtime.newArray(ary);
} else {
tmp = ((RubyArray) tmp).aryDup();
}

return (RubyArray) tmp;
}

public static IRubyObject irToAry(ThreadContext context, IRubyObject value) {
return value instanceof RubyArray ? value : RubyArray.aryToAry(context, value);
}
Expand Down Expand Up @@ -2068,21 +2104,6 @@ public static VariableAccessor getVariableAccessorForWrite(IRubyObject object, S
return ((RubyBasicObject)object).getMetaClass().getRealClass().getVariableAccessorForWrite(name);
}

@JIT
public static IRubyObject getVariableWithAccessor(IRubyObject self, VariableAccessor accessor, ThreadContext context, String name) {
Ruby runtime = context.runtime;
IRubyObject result = (IRubyObject)accessor.get(self);
if (result == null) {
result = context.nil;
}
return result;
}

@JIT
public static void setVariableWithAccessor(IRubyObject self, IRubyObject value, VariableAccessor accessor) {
accessor.set(self, value);
}

@JIT
public static RubyFixnum getArgScopeDepth(ThreadContext context, StaticScope currScope) {
int i = 0;
Expand Down
6 changes: 6 additions & 0 deletions core/src/main/java/org/jruby/ir/targets/BranchCompiler.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,10 @@ public interface BranchCompiler {
public void bfalse(Label label);

public void btrue(Label label);

void checkArgsArity(Runnable args, int required, int opt, boolean rest);

void checkArity(int required, int opt, boolean rest, int restKey);

void checkAritySpecificArgs(int required, int opt, boolean rest, int restKey);
}
15 changes: 15 additions & 0 deletions core/src/main/java/org/jruby/ir/targets/IRBytecodeAdapter.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import org.jruby.ir.targets.indy.IndyGlobalVariableCompiler;
import org.jruby.ir.targets.indy.IndyInstanceVariableCompiler;
import org.jruby.ir.targets.indy.IndyInvocationCompiler;
import org.jruby.ir.targets.indy.IndyLocalVariableCompiler;
import org.jruby.ir.targets.indy.IndyValueCompiler;
import org.jruby.ir.targets.indy.IndyYieldCompiler;
import org.jruby.ir.targets.simple.NormalArgumentsCompiler;
Expand All @@ -31,6 +32,7 @@
import org.jruby.ir.targets.simple.NormalGlobalVariableCompiler;
import org.jruby.ir.targets.simple.NormalInstanceVariableCompiler;
import org.jruby.ir.targets.simple.NormalInvocationCompiler;
import org.jruby.ir.targets.simple.NormalLocalVariableCompiler;
import org.jruby.ir.targets.simple.NormalValueCompiler;
import org.jruby.ir.targets.simple.NormalYieldCompiler;
import org.jruby.parser.StaticScope;
Expand Down Expand Up @@ -72,6 +74,7 @@ public IRBytecodeAdapter(BytecodeMode bytecodeMode, SkinnyMethodAdapter adapter,
this.checkpointCompiler = new IndyCheckpointCompiler(this);
this.instanceVariableCompiler = new IndyInstanceVariableCompiler(this);
this.globalVariableCompiler = new IndyGlobalVariableCompiler(this);
this.localVariableCompiler = new IndyLocalVariableCompiler(this);
this.yieldCompiler = new IndyYieldCompiler(this);
this.blockCompiler = new IndyBlockCompiler(this);
this.argumentsCompiler = new IndyArgumentsCompiler(this);
Expand All @@ -85,6 +88,7 @@ public IRBytecodeAdapter(BytecodeMode bytecodeMode, SkinnyMethodAdapter adapter,
this.checkpointCompiler = new NormalCheckpointCompiler(this);
this.instanceVariableCompiler = new NormalInstanceVariableCompiler(this);
this.globalVariableCompiler = new IndyGlobalVariableCompiler(this);
this.localVariableCompiler = new NormalLocalVariableCompiler(this);
this.yieldCompiler = new IndyYieldCompiler(this);
this.blockCompiler = new IndyBlockCompiler(this);
this.argumentsCompiler = new NormalArgumentsCompiler(this);
Expand All @@ -98,6 +102,7 @@ public IRBytecodeAdapter(BytecodeMode bytecodeMode, SkinnyMethodAdapter adapter,
this.checkpointCompiler = new NormalCheckpointCompiler(this);
this.instanceVariableCompiler = new NormalInstanceVariableCompiler(this);
this.globalVariableCompiler = new NormalGlobalVariableCompiler(this);
this.localVariableCompiler = new NormalLocalVariableCompiler(this);
this.yieldCompiler = new NormalYieldCompiler(this);
this.blockCompiler = new NormalBlockCompiler(this);
this.argumentsCompiler = new NormalArgumentsCompiler(this);
Expand Down Expand Up @@ -180,6 +185,15 @@ public GlobalVariableCompiler getGlobalVariableCompiler() {
return globalVariableCompiler;
}

/**
* Instance variable compiler.
*
* @return the instance variable compiler
*/
public LocalVariableCompiler getLocalVariableCompiler() {
return localVariableCompiler;
}

/**
* Block yielding compiler.
*
Expand Down Expand Up @@ -453,6 +467,7 @@ public static BlockPassType fromIR(ClosureAcceptingInstr callInstr) {
protected final ConstantCompiler constantCompiler;
protected final InstanceVariableCompiler instanceVariableCompiler;
protected final GlobalVariableCompiler globalVariableCompiler;
protected final LocalVariableCompiler localVariableCompiler;
protected final YieldCompiler yieldCompiler;
protected final BlockCompiler blockCompiler;
protected final ArgumentsCompiler argumentsCompiler;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,23 @@ public interface InstanceVariableCompiler {
/**
* Store instance variable into self.
* <p>
* Stack required: self, value
* Stack required: none
* Stack result: empty
*
* @param target runnable to push target object, may be called twice
* @param value runnable to push value to assign, will only be called once
* @param name name of variable to store
*/
public abstract void putField(String name);
public abstract void putField(Runnable target, Runnable value, String name);

/**
* Load instance variable from self.
* <p>
* Stack required: self
* Stack required: none
* Stack result: value from self
*
* @param source runnable to push source object, may be called twice
* @param name name of variable to load
*/
public abstract void getField(String name);
public abstract void getField(Runnable source, String name);
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.jruby.ir.targets;

import org.jruby.ir.instructions.AsStringInstr;
import org.jruby.ir.instructions.CallBase;
import org.jruby.ir.instructions.EQQInstr;

Expand Down Expand Up @@ -105,4 +106,11 @@ public interface InvocationCompiler {
* Stack required: context, case value, when value
*/
void invokeEQQ(EQQInstr call);

/**
* Coerces the receiver to a String using to_s, unless it is already a String
*
* Stack required: context, caller, receiver
*/
void asString(AsStringInstr call, String scopeFieldName, String file);
}
Loading