Skip to content

Instantly share code, notes, and snippets.

@headius

headius/.diff Secret

Last active March 31, 2021 19:57
Show Gist options
  • Save headius/5aa42adc1cfd723a1c96b34a95645e4d to your computer and use it in GitHub Desktop.
Save headius/5aa42adc1cfd723a1c96b34a95645e4d to your computer and use it in GitHub Desktop.
diff --git a/core/src/main/java/org/jruby/ir/IRBuilder.java b/core/src/main/java/org/jruby/ir/IRBuilder.java
index 9de004437e..ca085b7dfd 100644
--- a/core/src/main/java/org/jruby/ir/IRBuilder.java
+++ b/core/src/main/java/org/jruby/ir/IRBuilder.java
@@ -314,6 +314,7 @@ public class IRBuilder {
protected int coverageMode;
private boolean executesOnce = true;
private int temporaryVariableIndex = -1;
+ private boolean needsFrameBlock = false;
// This variable is an out-of-band passing mechanism to pass the method name to the block the
// method is attached to. call/fcall will set this and iter building will pass it into the iter
@@ -575,6 +576,10 @@ public class IRBuilder {
// can be U_NIL if the node is an if node with returns in both branches.
if (closureRetVal != U_NIL) addInstr(new ReturnInstr(closureRetVal));
+ if (needsFrameBlock) {
+ addInstrAtBeginning(new LoadFrameClosureInstr(getYieldClosureVariable()));
+ }
+
handleBreakAndReturnsInLambdas();
computeScopeFlagsFrom(instructions);
@@ -2398,7 +2403,7 @@ public class IRBuilder {
// used for yields; metaclass body (sclass) inherits yield var from surrounding, and accesses it as implicit
if (scope instanceof IRMethod || scope instanceof IRMetaClassBody) {
addInstr(new LoadImplicitClosureInstr(getYieldClosureVariable()));
- } else {
+ } else if (!(scope instanceof IRClosure)) {
addInstr(new LoadFrameClosureInstr(getYieldClosureVariable()));
}
}
@@ -4146,6 +4151,12 @@ public class IRBuilder {
Variable ret = result == null ? createTemporaryVariable() : result;
Operand value = argNode instanceof ArrayNode && unwrap ? buildArray((ArrayNode)argNode, true) : build(argNode);
+
+ if (scope instanceof IRClosure) {
+ // prepend appropriate instrs at end of build
+ needsFrameBlock = true;
+ }
+
addInstr(new YieldInstr(ret, getYieldClosureVariable(), value, unwrap));
return ret;
BEFORE
```
[] ~/projects/jruby $ jruby -Xfixnum.cache=false -e "def foo; i = 1; while i < 10_000_000; i+=1; yield; end; end; loop { t = Time.now; foo {nil}; puts Time.now - t }"
0.7005009999999999
0.529096
0.504481
0.49585
0.5215110000000001
0.494913
0.493634
0.49637
0.493248
...
[] ~/projects/jruby $ jruby -Xcompile.invokedynamic -Xfixnum.cache=false -e "def foo; i = 1; while i < 10_000_000; i+=1; yield; end; end; loop { t = Time.now; foo {nil}; puts Time.now - t }"
0.274233
0.497083
0.326676
0.288207
0.29467499999999996
0.27169200000000004
0.279859
0.309235
0.302266
0.292161
0.268515
0.273928
0.285491
...
```
AFTER
```
[] ~/projects/jruby $ jruby -Xfixnum.cache=false -e "def foo; i = 1; while i < 10_000_000; i+=1; yield; end; end; loop { t = Time.now; foo {nil}; puts Time.now - t }"
0.667794
0.487722
0.135046
0.121193
0.12173199999999999
0.11939999999999999
0.118389
0.117979
0.11821
0.120463
0.121267
0.126666
0.121721
0.11757500000000001
0.11768899999999999
0.118839
0.11935899999999999
0.12311799999999999
0.12400699999999999
...
[] ~/projects/jruby $ jruby -Xcompile.invokedynamic -Xfixnum.cache=false -e "def foo; i = 1; while i < 10_000_000; i+=1; yield; end; end; loop { t = Time.now; foo {nil}; puts Time.now - t }"
0.28047300000000003
0.068653
0.012865
0.020288
0.015314
0.015127
0.017859
0.017547
0.056439
0.022213
0.01658
0.027721
0.032636
...
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment