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: 54c031b98437
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 3b26bc71ad85
Choose a head ref

Commits on May 20, 2016

  1. Disable the AddLocalVarLoadStore pass to fix #3891.

    This was a good experiment, but we're not properly ensuring the
    heap variables are being loaded live when needed, causing examples
    like that in #3891 to fail to propagate changes across threads.
    By implementing LocalVariable load/store logic in JIT and turning
    off the "Add" pass, we basically revert heap vars to always being
    read/written immediately, as in JRuby 1.7.25.
    
    It may be possible to improve the pass so that it localizes the
    loads and stores better and ensures we don't miss updates we
    should see, but this commit will test whether the "nuclear option"
    passes all our suites.
    headius committed May 20, 2016
    Copy the full SHA
    cf2df89 View commit details
  2. Fixes to get LocalVariable compiling in all contexts.

    Many places just used jvmStoreLocal to store the variable, which
    assumed (because we only ran with call protocol in place) that
    all such stores would be to Java locals. I refactored this method
    to support LocalVariable as well as a different form that avoids
    stack-juggling to insert the value into the scope. This appears to
    get almost all code compiling that compiled before.
    headius committed May 20, 2016
    Copy the full SHA
    1c183c0 View commit details
  3. Copy the full SHA
    88a8896 View commit details
  4. Move OptDelegationPass after OptDynScope so we have temp locals.

    We can't store Block in heap scope, so we need this pass to come
    later.
    headius committed May 20, 2016
    Copy the full SHA
    6f37585 View commit details
  5. Copy the full SHA
    d4d6ac3 View commit details
  6. Unify super and call splatting logic in interpreter and JIT.

    This improves things in a few ways:
    
    * JIT and interpreter are calling through most of the same APIs.
    * Fewer transient objects for calls with splats.
    * Less duplication of code.
    
    There are other ways we could split the super dispatch paths
    apart to reduce overhead and allocation. This patch puts us on
    that path.
    headius committed May 20, 2016
    Copy the full SHA
    32512d5 View commit details

Commits on May 22, 2016

  1. Copy the full SHA
    47a9386 View commit details
  2. Copy the full SHA
    8847b78 View commit details

Commits on May 26, 2016

  1. Copy the full SHA
    aa425d6 View commit details
  2. wait_readable in MRI appears to always block, so we should too.

    This may have been an oversight; 0 means don't wait on the select
    at all, but I may have been confused thinking it meant wait
    forever. Doing waitReadable but not waiting for it to be readable
    seems obviously wrong.
    headius committed May 26, 2016
    Copy the full SHA
    f4d66bd View commit details
  3. Merge pull request #3898 from headius/disable_add_loadstore

    Disable the AddLocalVarLoadStore pass to fix #3891.
    headius committed May 26, 2016
    Copy the full SHA
    1c5c931 View commit details
  4. Merge pull request #3909 from headius/zsuper_sans_binding

    ZSuper does not require caller's binding/scope.
    headius committed May 26, 2016
    Copy the full SHA
    6d1062e View commit details
  5. Merge pull request #3912 from MSNexploder/string_tests

    fix four additional MRI string tests
    headius committed May 26, 2016
    Copy the full SHA
    4d9c129 View commit details
  6. Merge pull request #3911 from headius/zsuper_splatmap

    Unify super and call splatting logic in interpreter and JIT.
    headius committed May 26, 2016
    Copy the full SHA
    276a7d2 View commit details
  7. Merge pull request #3929 from headius/waitreadable_blocking

    waitReadable should block
    headius committed May 26, 2016
    Copy the full SHA
    a65ad3a View commit details
  8. Copy the full SHA
    8b73005 View commit details
  9. Use special Maven local repository dir to isolate in parallel running…

    … mx builds
    Jaroslav Tulach committed May 26, 2016
    Copy the full SHA
    26a4fca View commit details
  10. Copy the full SHA
    6dbf62c View commit details
  11. Copy the full SHA
    23b13fc View commit details
  12. Copy the full SHA
    ae90ed6 View commit details
  13. Copy the full SHA
    5115b11 View commit details
  14. Copy the full SHA
    01a69f0 View commit details
  15. Using maven_version_arg and maven_repo_arg instead of repeating the s…

    …trings
    Jaroslav Tulach committed May 26, 2016
    Copy the full SHA
    cbc6e91 View commit details
  16. Removing commented out code

    Jaroslav Tulach committed May 26, 2016
    Copy the full SHA
    e02a08f View commit details
  17. Merge pull request #3931 from jtulach/MavenRepo

    [Truffle] Use private maven repo instead of $HOME/.m2
    eregon committed May 26, 2016
    Copy the full SHA
    64ba959 View commit details
  18. [Truffle] reset buffer before reopening

    otherwise reopend io will inherit unclean buffer
    pitr-ch committed May 26, 2016
    Copy the full SHA
    9b255cf View commit details
  19. Copy the full SHA
    e73f65e View commit details
  20. Copy the full SHA
    86aebed View commit details
  21. Copy the full SHA
    bbb5009 View commit details
  22. Copy the full SHA
    05effd1 View commit details
  23. Copy the full SHA
    a48d113 View commit details
  24. Copy the full SHA
    75e7a35 View commit details
  25. Copy the full SHA
    5d8f696 View commit details
  26. Copy the full SHA
    bb6a444 View commit details
  27. Copy the full SHA
    6a75d7a View commit details
  28. Copy the full SHA
    78d2436 View commit details
  29. Copy the full SHA
    ab63a40 View commit details
  30. Copy the full SHA
    251f680 View commit details
  31. Copy the full SHA
    d472e99 View commit details
  32. Copy the full SHA
    72fdffe View commit details
  33. Copy the full SHA
    3b26bc7 View commit details
Showing with 396 additions and 233 deletions.
  1. +1 −1 VERSION
  2. +1 −1 core/pom.xml
  3. +2 −1 core/src/main/java/org/jruby/RubyIO.java
  4. +9 −8 core/src/main/java/org/jruby/RubyString.java
  5. +1 −1 core/src/main/java/org/jruby/ir/IRManager.java
  6. +1 −2 core/src/main/java/org/jruby/ir/IRScope.java
  7. +12 −20 core/src/main/java/org/jruby/ir/instructions/CallBase.java
  8. +1 −3 core/src/main/java/org/jruby/ir/instructions/ZSuperInstr.java
  9. +6 −0 core/src/main/java/org/jruby/ir/passes/OptimizeDelegationPass.java
  10. +23 −10 core/src/main/java/org/jruby/ir/runtime/IRRuntimeHelpers.java
  11. +30 −19 core/src/main/java/org/jruby/ir/targets/IRBytecodeAdapter6.java
  12. +119 −21 core/src/main/java/org/jruby/ir/targets/JVMVisitor.java
  13. +49 −0 core/src/main/java/org/jruby/runtime/DynamicScope.java
  14. +1 −1 core/src/main/java/org/jruby/util/io/OpenFile.java
  15. +2 −2 lib/pom.xml
  16. +7 −5 mx.jruby/mx_jruby.py
  17. +1 −1 pom.xml
  18. +0 −5 spec/truffle/tags/core/io/eof_tags.txt
  19. +0 −1 spec/truffle/tags/core/io/seek_tags.txt
  20. +0 −3 test/mri/excludes/TestString.rb
  21. +2 −1 tool/jt.rb
  22. +1 −1 truffle/pom.xml
  23. +1 −1 truffle/src/main/java/org/jruby/truffle/Layouts.java
  24. +1 −1 truffle/src/main/java/org/jruby/truffle/builtins/PrimitiveManager.java
  25. +2 −1 truffle/src/main/java/org/jruby/truffle/core/CoreLibrary.java
  26. +0 −1 truffle/src/main/java/org/jruby/truffle/core/MainNodes.java
  27. +0 −1 truffle/src/main/java/org/jruby/truffle/core/MathNodes.java
  28. +0 −1 truffle/src/main/java/org/jruby/truffle/core/ProcessNodes.java
  29. +2 −0 truffle/src/main/java/org/jruby/truffle/core/VMPrimitiveNodes.java
  30. +2 −0 truffle/src/main/java/org/jruby/truffle/core/array/ArrayNodes.java
  31. +0 −1 truffle/src/main/java/org/jruby/truffle/core/basicobject/BasicObjectNodes.java
  32. +0 −1 truffle/src/main/java/org/jruby/truffle/core/cast/IntegerCastNode.java
  33. +0 −1 truffle/src/main/java/org/jruby/truffle/core/encoding/EncodingConverterNodes.java
  34. +1 −1 truffle/src/main/java/org/jruby/truffle/core/fiber/FiberNodes.java
  35. +0 −1 truffle/src/main/java/org/jruby/truffle/core/format/convert/ToStringNode.java
  36. +0 −1 truffle/src/main/java/org/jruby/truffle/core/format/read/bytes/ReadBinaryStringNode.java
  37. +0 −1 truffle/src/main/java/org/jruby/truffle/core/format/read/bytes/ReadUTF8CharacterNode.java
  38. +0 −1 truffle/src/main/java/org/jruby/truffle/core/hash/LookupEntryNode.java
  39. +2 −4 truffle/src/main/java/org/jruby/truffle/core/kernel/KernelNodes.java
  40. +1 −0 truffle/src/main/java/org/jruby/truffle/core/kernel/TruffleKernelNodes.java
  41. +0 −1 truffle/src/main/java/org/jruby/truffle/core/klass/ClassNodes.java
  42. +0 −1 truffle/src/main/java/org/jruby/truffle/core/method/UnboundMethodNodes.java
  43. +1 −0 truffle/src/main/java/org/jruby/truffle/core/module/ModuleFields.java
  44. +1 −0 truffle/src/main/java/org/jruby/truffle/core/module/ModuleNodes.java
  45. +0 −1 truffle/src/main/java/org/jruby/truffle/core/numeric/FixnumNodes.java
  46. +0 −1 truffle/src/main/java/org/jruby/truffle/core/objectspace/ObjectSpaceNodes.java
  47. +1 −1 truffle/src/main/java/org/jruby/truffle/core/queue/QueueNodes.java
  48. +1 −1 truffle/src/main/java/org/jruby/truffle/core/queue/SizedQueueNodes.java
  49. +1 −0 truffle/src/main/java/org/jruby/truffle/core/regexp/MatchDataNodes.java
  50. +0 −1 truffle/src/main/java/org/jruby/truffle/core/rope/RopeTable.java
  51. +0 −1 truffle/src/main/java/org/jruby/truffle/core/rubinius/ByteArrayNodes.java
  52. +0 −1 truffle/src/main/java/org/jruby/truffle/core/rubinius/IOBufferPrimitiveNodes.java
  53. +4 −3 truffle/src/main/java/org/jruby/truffle/core/rubinius/IOPrimitiveNodes.java
  54. +0 −1 truffle/src/main/java/org/jruby/truffle/core/rubinius/RegexpPrimitiveNodes.java
  55. +2 −0 truffle/src/main/java/org/jruby/truffle/core/string/StringNodes.java
  56. +0 −1 truffle/src/main/java/org/jruby/truffle/core/symbol/SymbolNodes.java
  57. +1 −0 truffle/src/main/java/org/jruby/truffle/core/symbol/SymbolTable.java
  58. +3 −1 truffle/src/main/java/org/jruby/truffle/extra/TrufflePosixNodes.java
  59. +0 −4 truffle/src/main/java/org/jruby/truffle/gem/bcrypt/BCrypt.java
  60. +28 −12 truffle/src/main/java/org/jruby/truffle/language/CallStackManager.java
  61. +0 −1 truffle/src/main/java/org/jruby/truffle/language/arguments/SingleBlockArgNode.java
  62. +5 −0 truffle/src/main/java/org/jruby/truffle/language/backtrace/Activation.java
  63. +1 −1 truffle/src/main/java/org/jruby/truffle/language/backtrace/BacktraceFormatter.java
  64. +0 −1 truffle/src/main/java/org/jruby/truffle/language/constants/LookupConstantNode.java
  65. +0 −1 truffle/src/main/java/org/jruby/truffle/language/dispatch/RubyCallNode.java
  66. +5 −6 truffle/src/main/java/org/jruby/truffle/language/exceptions/DisablingBacktracesNode.java
  67. +1 −1 truffle/src/main/java/org/jruby/truffle/language/loader/FeatureLoader.java
  68. +1 −1 truffle/src/main/java/org/jruby/truffle/language/objects/DefineModuleNode.java
  69. +2 −1 truffle/src/main/java/org/jruby/truffle/language/objects/ObjectGraph.java
  70. +1 −34 truffle/src/main/java/org/jruby/truffle/language/parser/jruby/BodyTranslator.java
  71. +0 −1 truffle/src/main/java/org/jruby/truffle/language/yield/YieldExpressionNode.java
  72. +8 −3 truffle/src/main/java/org/jruby/truffle/stdlib/readline/ReadlineHistoryNodes.java
  73. +12 −3 truffle/src/main/java/org/jruby/truffle/stdlib/readline/ReadlineNodes.java
  74. +11 −10 truffle/src/main/ruby/core/array.rb
  75. +1 −1 truffle/src/main/ruby/core/float.rb
  76. +2 −2 truffle/src/main/ruby/core/integer.rb
  77. +18 −6 truffle/src/main/ruby/core/io.rb
  78. +3 −3 truffle/src/main/ruby/core/range.rb
  79. +1 −1 truffle/src/main/ruby/core/string.rb
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
9.1.2.0-SNAPSHOT
9.1.3.0-SNAPSHOT
2 changes: 1 addition & 1 deletion core/pom.xml
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@ DO NOT MODIFIY - GENERATED CODE
<parent>
<groupId>org.jruby</groupId>
<artifactId>jruby-parent</artifactId>
<version>9.1.2.0-SNAPSHOT</version>
<version>9.1.3.0-SNAPSHOT</version>
</parent>
<artifactId>jruby-core</artifactId>
<name>JRuby Core</name>
3 changes: 2 additions & 1 deletion core/src/main/java/org/jruby/RubyIO.java
Original file line number Diff line number Diff line change
@@ -2853,9 +2853,10 @@ IRubyObject getPartial(ThreadContext context, IRubyObject[] args, boolean nonblo
// n = arg.len;
n = OpenFile.readInternal(context, fptr, fptr.fd(), strByteList.unsafeBytes(), strByteList.begin(), len);
if (n < 0) {
Errno e = fptr.errno();
if (!nonblock && fptr.waitReadable(context))
continue again;
if (nonblock && (fptr.errno() == Errno.EWOULDBLOCK || fptr.errno() == Errno.EAGAIN)) {
if (nonblock && (e == Errno.EWOULDBLOCK || e == Errno.EAGAIN)) {
if (noException) return runtime.newSymbol("wait_readable");
throw runtime.newErrnoEAGAINReadableError("read would block");
}
17 changes: 9 additions & 8 deletions core/src/main/java/org/jruby/RubyString.java
Original file line number Diff line number Diff line change
@@ -3388,6 +3388,10 @@ public IRubyObject stringToInum(int base, boolean badcheck) {

public IRubyObject stringToInum19(int base, boolean badcheck) {
ByteList s = this.value;
if (!s.getEncoding().isAsciiCompatible()) {
throw getRuntime().newEncodingCompatibilityError("ASCII incompatible encoding: " + s.getEncoding());
}

return ConvertBytes.byteListToInum19(getRuntime(), s, base, badcheck);
}

@@ -3400,9 +3404,6 @@ public IRubyObject oct(ThreadContext context) {

@JRubyMethod(name = "oct")
public IRubyObject oct19(ThreadContext context) {
if (!value.getEncoding().isAsciiCompatible()) {
throw context.runtime.newEncodingCompatibilityError("ASCII incompatible encoding: " + value.getEncoding());
}
return stringToInum19(-8, false);
}

@@ -3415,9 +3416,6 @@ public IRubyObject hex(ThreadContext context) {

@JRubyMethod(name = "hex")
public IRubyObject hex19(ThreadContext context) {
if (!value.getEncoding().isAsciiCompatible()) {
throw context.runtime.newEncodingCompatibilityError("ASCII incompatible encoding: " + value.getEncoding());
}
return stringToInum19(16, false);
}

@@ -4119,7 +4117,8 @@ public IRubyObject partition(ThreadContext context, IRubyObject arg, Block block
}

private IRubyObject partitionMismatch(Ruby runtime) {
return RubyArray.newArray(runtime, new IRubyObject[]{this, newEmptyString(runtime), newEmptyString(runtime)});
final Encoding enc = getEncoding();
return RubyArray.newArray(runtime, new IRubyObject[]{this, newEmptyString(runtime, enc), newEmptyString(runtime, enc)});
}

@JRubyMethod(name = "rpartition", reads = BACKREF, writes = BACKREF)
@@ -4149,7 +4148,8 @@ public IRubyObject rpartition(ThreadContext context, IRubyObject arg) {
}

private IRubyObject rpartitionMismatch(Ruby runtime) {
return RubyArray.newArray(runtime, new IRubyObject[]{newEmptyString(runtime), newEmptyString(runtime), this});
final Encoding enc = getEncoding();
return RubyArray.newArray(runtime, new IRubyObject[]{newEmptyString(runtime, enc), newEmptyString(runtime, enc), this});
}

/** rb_str_chop / rb_str_chop_bang
@@ -4417,6 +4417,7 @@ public IRubyObject rstrip_bang19(ThreadContext context) {
return runtime.getNil();
}

checkDummyEncoding();
Encoding enc = EncodingUtils.STR_ENC_GET(this);
IRubyObject result = singleByteOptimizable(enc) ?
singleByteRStrip19(runtime) : multiByteRStrip19(runtime, context);
2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/ir/IRManager.java
Original file line number Diff line number Diff line change
@@ -30,7 +30,7 @@
public class IRManager {
public static final String SAFE_COMPILER_PASSES = "";
public static final String DEFAULT_BUILD_PASSES = "";
public static final String DEFAULT_JIT_PASSES = "LocalOptimizationPass,OptimizeDelegationPass,DeadCodeElimination,AddLocalVarLoadStoreInstructions,OptimizeDynScopesPass,AddCallProtocolInstructions,EnsureTempsAssigned";
public static final String DEFAULT_JIT_PASSES = "LocalOptimizationPass,DeadCodeElimination,OptimizeDynScopesPass,OptimizeDelegationPass,AddCallProtocolInstructions,EnsureTempsAssigned";
public static final String DEFAULT_INLINING_COMPILER_PASSES = "LocalOptimizationPass";

private final CompilerPass deadCodeEliminationPass = new DeadCodeElimination();
3 changes: 1 addition & 2 deletions core/src/main/java/org/jruby/ir/IRScope.java
Original file line number Diff line number Diff line change
@@ -666,8 +666,7 @@ private void calculateClosureScopeFlags() {
EnumSet.of(
CAN_RECEIVE_BREAKS,
HAS_NONLOCAL_RETURNS,CAN_RECEIVE_NONLOCAL_RETURNS,
BINDING_HAS_ESCAPED,
USES_ZSUPER);
BINDING_HAS_ESCAPED);

private void computeNeedsDynamicScopeFlag() {
for (IRFlags f : NEEDS_DYNAMIC_SCOPE_FLAGS) {
32 changes: 12 additions & 20 deletions core/src/main/java/org/jruby/ir/instructions/CallBase.java
Original file line number Diff line number Diff line change
@@ -34,7 +34,7 @@ public abstract class CallBase extends NOperandInstr implements ClosureAccepting
private transient boolean targetRequiresCallersBinding; // Does this call make use of the caller's binding?
private transient boolean targetRequiresCallersFrame; // Does this call make use of the caller's frame?
private transient boolean dontInline;
private transient boolean containsArgSplat;
private transient boolean[] splatMap;
private transient boolean procNew;
private boolean potentiallyRefined;

@@ -48,7 +48,7 @@ protected CallBase(Operation op, CallType callType, String name, Operand receive
this.name = name;
this.callType = callType;
this.callSite = getCallSiteFor(callType, name, potentiallyRefined);
containsArgSplat = containsArgSplat(args);
splatMap = IRRuntimeHelpers.buildSplatMap(args);
flagsComputed = false;
canBeEval = true;
targetRequiresCallersBinding = true;
@@ -128,8 +128,8 @@ public CallType getCallType() {
return callType;
}

public boolean containsArgSplat() {
return containsArgSplat;
public boolean[] splatMap() {
return splatMap;
}

public void setProcNew(boolean procNew) {
@@ -231,8 +231,8 @@ public boolean computeScopeFlags(IRScope scope) {
public void simplifyOperands(Map<Operand, Operand> valueMap, boolean force) {
super.simplifyOperands(valueMap, force);

// Recompute containsArgSplat flag
containsArgSplat = containsArgSplat(operands); // also checking receiver but receiver can never be a splat
// Recompute splatMap
splatMap = IRRuntimeHelpers.buildSplatMap(getCallArgs()); // also checking receiver but receiver can never be a splat
flagsComputed = false; // Forces recomputation of flags
}

@@ -424,7 +424,7 @@ public Object interpret(ThreadContext context, StaticScope currScope, DynamicSco
}

protected IRubyObject[] prepareArguments(ThreadContext context, IRubyObject self, StaticScope currScope, DynamicScope dynamicScope, Object[] temp) {
return containsArgSplat ?
return splatMap != null ?
prepareArgumentsComplex(context, self, currScope, dynamicScope, temp) :
prepareArgumentsSimple(context, self, currScope, dynamicScope, temp);
}
@@ -445,20 +445,12 @@ protected IRubyObject[] prepareArgumentsComplex(ThreadContext context, IRubyObje
// But when zsuper is converted to SuperInstr with known args, splats can appear anywhere
// in the list. So, this looping handles both these scenarios, although if we wanted to
// optimize for CallInstr which has splats only in the first position, we could do that.
List<IRubyObject> argList = new ArrayList<>(argsCount * 2);
for (int i = 0; i < argsCount; i++) { // receiver is operands[0]
IRubyObject rArg = (IRubyObject) operands[i+1].retrieve(context, self, currScope, currDynScope, temp);
if (operands[i+1] instanceof Splat) {
RubyArray array = (RubyArray) rArg;
for (int j = 0; j < array.size(); j++) {
argList.add(array.eltOk(j));
}
} else {
argList.add(rArg);
}
}

return argList.toArray(new IRubyObject[argList.size()]);
// CON: Using same logic as super splatting, but this will at least only allocate at
// most two "carrier" arrays.
return IRRuntimeHelpers.splatArguments(
prepareArgumentsSimple(context, self, currScope, currDynScope, temp),
splatMap);
}

public Block prepareBlock(ThreadContext context, IRubyObject self, StaticScope currScope, DynamicScope currDynScope, Object[] temp) {
Original file line number Diff line number Diff line change
@@ -26,7 +26,6 @@ public ZSuperInstr(Variable result, Operand receiver, Operand[] args, Operand cl
public boolean computeScopeFlags(IRScope scope) {
super.computeScopeFlags(scope);
scope.getFlags().add(IRFlags.USES_ZSUPER);
scope.getFlags().add(IRFlags.CAN_CAPTURE_CALLERS_BINDING);
return true;
}

@@ -67,8 +66,7 @@ public static ZSuperInstr decode(IRReaderDecoder d) {
public Object interpret(ThreadContext context, StaticScope currScope, DynamicScope currDynScope, IRubyObject self, Object[] temp) {
IRubyObject[] args = prepareArguments(context, self, currScope, currDynScope, temp);
Block block = prepareBlock(context, self, currScope, currDynScope, temp);
if (block == null || !block.isGiven()) block = context.getFrameBlock();
return IRRuntimeHelpers.unresolvedSuper(context, self, args, block);
return IRRuntimeHelpers.zSuper(context, self, args, block);
}

@Override
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@
import org.jruby.ir.instructions.CopyInstr;
import org.jruby.ir.instructions.Instr;
import org.jruby.ir.instructions.ReifyClosureInstr;
import org.jruby.ir.operands.LocalVariable;
import org.jruby.ir.operands.Operand;
import org.jruby.ir.operands.Variable;
import org.jruby.ir.representations.BasicBlock;
@@ -41,6 +42,11 @@ private static void optimizeDelegatedVars(IRScope s) {
for (Instr i: bb.getInstrs()) {
if (i instanceof ReifyClosureInstr) {
ReifyClosureInstr ri = (ReifyClosureInstr) i;

// can't store un-reified block in DynamicScope (only accepts IRubyObject)
// FIXME: (con) it would be nice to not have this limitation
if (ri.getResult() instanceof LocalVariable) continue;

unusedExplicitBlocks.put(ri.getResult(), ri.getSource());
} else {
Iterator<Operand> it = unusedExplicitBlocks.keySet().iterator();
33 changes: 23 additions & 10 deletions core/src/main/java/org/jruby/ir/runtime/IRRuntimeHelpers.java
Original file line number Diff line number Diff line change
@@ -1001,7 +1001,12 @@ public static IRubyObject unresolvedSuper(ThreadContext context, IRubyObject sel

public static IRubyObject zSuperSplatArgs(ThreadContext context, IRubyObject self, IRubyObject[] args, Block block, boolean[] splatMap) {
if (block == null || !block.isGiven()) block = context.getFrameBlock();
return unresolvedSuperSplatArgs(context, self, args, block, splatMap);
return unresolvedSuper(context, self, splatArguments(args, splatMap), block);
}

public static IRubyObject zSuper(ThreadContext context, IRubyObject self, IRubyObject[] args, Block block) {
if (block == null || !block.isGiven()) block = context.getFrameBlock();
return unresolvedSuper(context, self, args, block);
}

public static IRubyObject[] splatArguments(IRubyObject[] args, boolean[] splatMap) {
@@ -1049,26 +1054,34 @@ public static boolean[] decodeSplatmap(String splatmapString) {
}
}
} else {
splatMap = new boolean[0];
splatMap = null;
}
return splatMap;
}

public static boolean[] buildSplatMap(Operand[] args, boolean containsArgSplat) {
boolean[] splatMap = new boolean[args.length];
public static boolean[] buildSplatMap(Operand[] args) {
boolean[] splatMap = null;

if (containsArgSplat) {
for (int i = 0; i < args.length; i++) {
Operand operand = args[i];
if (operand instanceof Splat) {
splatMap[i] = true;
}
for (int i = 0; i < args.length; i++) {
Operand operand = args[i];
if (operand instanceof Splat) {
if (splatMap == null) splatMap = new boolean[args.length];
splatMap[i] = true;
}
}

return splatMap;
}

public static boolean anyTrue(boolean[] booleans) {
for (boolean b : booleans) if (b) return true;
return false;
}

public static boolean needsSplatting(boolean[] splatmap) {
return splatmap != null && splatmap.length > 0 && anyTrue(splatmap);
}

public static final Type[] typesFromSignature(Signature signature) {
Type[] types = new Type[signature.argCount()];
for (int i = 0; i < signature.argCount(); i++) {
49 changes: 30 additions & 19 deletions core/src/main/java/org/jruby/ir/targets/IRBytecodeAdapter6.java
Original file line number Diff line number Diff line change
@@ -61,6 +61,12 @@
* CON FIXME: These are all dirt-stupid impls that will not be as efficient.
*/
public class IRBytecodeAdapter6 extends IRBytecodeAdapter{

public static final String SUPER_SPLAT_UNRESOLVED = sig(JVM.OBJECT, params(ThreadContext.class, IRubyObject.class, JVM.OBJECT_ARRAY, Block.class, boolean[].class));
public static final String SUPER_NOSPLAT_UNRESOLVED = sig(JVM.OBJECT, params(ThreadContext.class, IRubyObject.class, JVM.OBJECT_ARRAY, Block.class));
public static final String SUPER_SPLAT_RESOLVED = sig(JVM.OBJECT, params(ThreadContext.class, IRubyObject.class, String.class, RubyModule.class, JVM.OBJECT_ARRAY, Block.class, boolean[].class));
public static final String SUPER_NOSPLAT_RESOLVED = sig(JVM.OBJECT, params(ThreadContext.class, IRubyObject.class, String.class, RubyModule.class, JVM.OBJECT_ARRAY, Block.class));

public IRBytecodeAdapter6(SkinnyMethodAdapter adapter, Signature signature, ClassData classData) {
super(adapter, signature, classData);
}
@@ -629,42 +635,52 @@ public void invokeSelf(String name, int arity, boolean hasClosure, CallType call
public void invokeInstanceSuper(String name, int arity, boolean hasClosure, boolean[] splatmap) {
if (arity > MAX_ARGUMENTS) throw new NotCompilableException("call to instance super has more than " + MAX_ARGUMENTS + " arguments");

performSuper(name, arity, hasClosure, splatmap, "instanceSuperSplatArgs", false);
performSuper(name, arity, hasClosure, splatmap, "instanceSuper", "instanceSuperSplatArgs", false);
}

public void invokeClassSuper(String name, int arity, boolean hasClosure, boolean[] splatmap) {
if (arity > MAX_ARGUMENTS) throw new NotCompilableException("call to class super has more than " + MAX_ARGUMENTS + " arguments");

performSuper(name, arity, hasClosure, splatmap, "classSuperSplatArgs", false);
performSuper(name, arity, hasClosure, splatmap, "classSuper", "classSuperSplatArgs", false);
}

public void invokeUnresolvedSuper(String name, int arity, boolean hasClosure, boolean[] splatmap) {
if (arity > MAX_ARGUMENTS) throw new NotCompilableException("call to unresolved super has more than " + MAX_ARGUMENTS + " arguments");

performSuper(name, arity, hasClosure, splatmap, "unresolvedSuperSplatArgs", true);
performSuper(name, arity, hasClosure, splatmap, "unresolvedSuper", "unresolvedSuperSplatArgs", true);
}

public void invokeZSuper(String name, int arity, boolean hasClosure, boolean[] splatmap) {
if (arity > MAX_ARGUMENTS) throw new NotCompilableException("call to zsuper has more than " + MAX_ARGUMENTS + " arguments");

performSuper(name, arity, hasClosure, splatmap, "zSuperSplatArgs", true);
performSuper(name, arity, hasClosure, splatmap, "zSuper", "zSuperSplatArgs", true);
}

private void performSuper(String name, int arity, boolean hasClosure, boolean[] splatmap, String helperName, boolean unresolved) {
private void performSuper(String name, int arity, boolean hasClosure, boolean[] splatmap, String superHelper, String splatHelper, boolean unresolved) {
SkinnyMethodAdapter adapter2;
String incomingSig;
String outgoingSig;

boolean needsSplatting = IRRuntimeHelpers.needsSplatting(splatmap);

if (hasClosure) {
incomingSig = sig(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT, RubyClass.class, JVM.OBJECT, arity, Block.class));
outgoingSig = unresolved ?
sig(JVM.OBJECT, params(ThreadContext.class, IRubyObject.class, JVM.OBJECT_ARRAY, Block.class, boolean[].class)) :
sig(JVM.OBJECT, params(ThreadContext.class, IRubyObject.class, String.class, RubyModule.class, JVM.OBJECT_ARRAY, Block.class, boolean[].class));
} else {
incomingSig = sig(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT, RubyClass.class, JVM.OBJECT, arity));
outgoingSig = unresolved ?
sig(JVM.OBJECT, params(ThreadContext.class, IRubyObject.class, JVM.OBJECT_ARRAY, Block.class, boolean[].class)) :
sig(JVM.OBJECT, params(ThreadContext.class, IRubyObject.class, String.class, RubyModule.class, JVM.OBJECT_ARRAY, Block.class, boolean[].class));
}

if (unresolved) {
if (needsSplatting) {
outgoingSig = SUPER_SPLAT_UNRESOLVED;
} else {
outgoingSig = SUPER_NOSPLAT_UNRESOLVED;
}
} else {
if (needsSplatting) {
outgoingSig = SUPER_SPLAT_RESOLVED;
} else {
outgoingSig = SUPER_NOSPLAT_RESOLVED;
}
}

String methodName = "invokeSuper" + getClassData().callSiteCount.getAndIncrement() + ':' + JavaNameMangler.mangleMethodName(name);
@@ -690,27 +706,22 @@ private void performSuper(String name, int arity, boolean hasClosure, boolean[]
adapter2.getstatic(p(Block.class), "NULL_BLOCK", ci(Block.class));
}

if (splatmap != null || splatmap.length > 0 || anyTrue(splatmap)) {
if (needsSplatting) {
String splatmapString = IRRuntimeHelpers.encodeSplatmap(splatmap);
adapter2.ldc(splatmapString);
adapter2.invokestatic(p(IRRuntimeHelpers.class), "decodeSplatmap", sig(boolean[].class, String.class));
adapter2.invokestatic(p(IRRuntimeHelpers.class), splatHelper, outgoingSig);
} else {
adapter2.getstatic(p(IRRuntimeHelpers.class), "EMPTY_BOOLEAN_ARRAY", ci(boolean[].class));
adapter2.invokestatic(p(IRRuntimeHelpers.class), superHelper, outgoingSig);
}

adapter2.invokestatic(p(IRRuntimeHelpers.class), helperName, outgoingSig);
adapter2.areturn();
adapter2.end();

// now call it
adapter.invokestatic(getClassData().clsName, methodName, incomingSig);
}

private static boolean anyTrue(boolean[] booleans) {
for (boolean b : booleans) if (b) return true;
return false;
}

public void searchConst(String name, boolean noPrivateConsts) {
adapter.invokedynamic("searchConst", sig(JVM.OBJECT, params(ThreadContext.class, StaticScope.class)), ConstantLookupSite.BOOTSTRAP, name, noPrivateConsts ? 1 : 0);
}
Loading