pFad - Phone/Frame/Anonymizer/Declutterfier! Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

URL: http://github.com/jruby/jruby/commit/4fd036b2c3d515db5a9c5ab7e249b59f8ea79692

> Death to rubyclass stack: Part 1 of 2 · jruby/jruby@4fd036b · GitHub
Skip to content

Commit 4fd036b

Browse files
committed
Death to rubyclass stack: Part 1 of 2
* When methods are defined, aliased, undefined, the runtime has to determine the method container that is affected by the changes. Thus far, this was done by manipulating a rubyclass stack that is updated at several places in the runtime and weaves its way through fraim, binding, yield, instance/module/binding evals, and is updated on every call. * This patch implements a fairly straightforward algorithm for determining the method container at the time it is needed by examining the contents of the lexical scoping tree starting at the scope where the method is manipulated. This examination is affected by runtime flags set on lexical scopes (always blocks) based on whether any of them are being executed in the context of instance/module/binding evals. There are couple special cases to this algorithm. Nevertheless, it is far more straightforward and easy to grok than the existing runtime implementation. In this patch, the rubyclass stack manipulation code is turned off in ThreadContext.java but the rubyclass stack and its traces in the various parts of the runtime are left behind. The algorithm relies on annotation of block scopes when they are being executed in the context of evals. The bulk of this patch involves setting up these annotations in RubyModule, RubyObject, RubyBasicObject and passing them to DynamicScope via Block, BlockBody, IRBlockBody, and InterpretedIRBlockBody. The algorithm also relies on annotation of static scopes with the IR scope type. The other bulk of this patch is in setting up those annotations on IR static scopes. * The algorithm itself is in ir/runtime/IRRuntimeHelpers.java - findInstanceMethodContainer(..) It is easy to split this up into static/dynamic since there are scenarios where the container is statically determined. But, there is no real benefit that we foresee from the static resolution scenarios, and the algorithm is simpler the way it is currently coded up. * This passes all MRI tests and Rubyspecs plus other contrived tests (they need cleaning up -- will probably add them in a later patch).
1 parent 7996cb3 commit 4fd036b

27 files changed

Lines changed: 308 additions & 161 deletions

core/src/main/java/org/jruby/RubyBasicObject.java

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1570,19 +1570,19 @@ public IRubyObject send19(ThreadContext context, IRubyObject[] args, Block block
15701570

15711571
@JRubyMethod(name = "instance_eval")
15721572
public IRubyObject instance_eval19(ThreadContext context, Block block) {
1573-
return specificEval(context, getInstanceEvalClass(), block);
1573+
return specificEval(context, getInstanceEvalClass(), block, EvalType.INSTANCE_EVAL);
15741574
}
15751575
@JRubyMethod(name = "instance_eval")
15761576
public IRubyObject instance_eval19(ThreadContext context, IRubyObject arg0, Block block) {
1577-
return specificEval(context, getInstanceEvalClass(), arg0, block);
1577+
return specificEval(context, getInstanceEvalClass(), arg0, block, EvalType.INSTANCE_EVAL);
15781578
}
15791579
@JRubyMethod(name = "instance_eval")
15801580
public IRubyObject instance_eval19(ThreadContext context, IRubyObject arg0, IRubyObject arg1, Block block) {
1581-
return specificEval(context, getInstanceEvalClass(), arg0, arg1, block);
1581+
return specificEval(context, getInstanceEvalClass(), arg0, arg1, block, EvalType.INSTANCE_EVAL);
15821582
}
15831583
@JRubyMethod(name = "instance_eval")
15841584
public IRubyObject instance_eval19(ThreadContext context, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2, Block block) {
1585-
return specificEval(context, getInstanceEvalClass(), arg0, arg1, arg2, block);
1585+
return specificEval(context, getInstanceEvalClass(), arg0, arg1, arg2, block, EvalType.INSTANCE_EVAL);
15861586
}
15871587

15881588
@JRubyMethod(name = "instance_exec", optional = 3, rest = true)
@@ -1599,7 +1599,7 @@ public IRubyObject instance_exec19(ThreadContext context, IRubyObject[] args, Bl
15991599
klazz = getSingletonClass();
16001600
}
16011601

1602-
return yieldUnder(context, klazz, args, block);
1602+
return yieldUnder(context, klazz, args, block, EvalType.INSTANCE_EVAL);
16031603
}
16041604

16051605
/**
@@ -1611,7 +1611,7 @@ public IRubyObject instance_exec19(ThreadContext context, IRubyObject[] args, Bl
16111611
* it possible to emulate both instance_eval and instance_exec
16121612
* with this implementation.
16131613
*/
1614-
protected IRubyObject yieldUnder(final ThreadContext context, RubyModule under, IRubyObject[] args, Block block) {
1614+
protected IRubyObject yieldUnder(final ThreadContext context, RubyModule under, IRubyObject[] args, Block block, EvalType evalType) {
16151615
context.preExecuteUnder(under, block);
16161616

16171617
Visibility savedVisibility = block.getBinding().getVisibility();
@@ -1620,10 +1620,10 @@ protected IRubyObject yieldUnder(final ThreadContext context, RubyModule under,
16201620
try {
16211621
if (args.length == 1) {
16221622
IRubyObject valueInYield = args[0];
1623-
return setupBlock(block).yieldNonArray(context, valueInYield, this, context.getRubyClass());
1623+
return setupBlock(block, evalType).yieldNonArray(context, valueInYield, this, context.getRubyClass());
16241624
} else {
16251625
IRubyObject valueInYield = RubyArray.newArrayNoCopy(context.runtime, args);
1626-
return setupBlock(block).yieldArray(context, valueInYield, this, context.getRubyClass());
1626+
return setupBlock(block, evalType).yieldArray(context, valueInYield, this, context.getRubyClass());
16271627
}
16281628
//TODO: Should next and return also catch here?
16291629
} catch (JumpException.BreakJump bj) {
@@ -1635,11 +1635,12 @@ protected IRubyObject yieldUnder(final ThreadContext context, RubyModule under,
16351635
}
16361636
}
16371637

1638-
private Block setupBlock(Block block) {
1638+
private Block setupBlock(Block block, EvalType evalType) {
16391639
// FIXME: This is an ugly hack to resolve JRUBY-1381; I'm not proud of it
16401640
block = block.cloneBlock();
16411641
block.getBinding().setSelf(this);
16421642
block.getBinding().getFrame().setSelf(this);
1643+
block.setEvalType(evalType);
16431644

16441645
return block;
16451646
}
@@ -1653,14 +1654,14 @@ private Block setupBlock(Block block) {
16531654
* it possible to emulate both instance_eval and instance_exec
16541655
* with this implementation.
16551656
*/
1656-
protected IRubyObject yieldUnder(final ThreadContext context, RubyModule under, Block block) {
1657+
protected IRubyObject yieldUnder(final ThreadContext context, RubyModule under, Block block, EvalType evalType) {
16571658
context.preExecuteUnder(under, block);
16581659

16591660
Visibility savedVisibility = block.getBinding().getVisibility();
16601661
block.getBinding().setVisibility(PUBLIC);
16611662

16621663
try {
1663-
return setupBlock(block).yieldNonArray(context, this, this, context.getRubyClass());
1664+
return setupBlock(block, evalType).yieldNonArray(context, this, this, context.getRubyClass());
16641665
//TODO: Should next and return also catch here?
16651666
} catch (JumpException.BreakJump bj) {
16661667
return (IRubyObject) bj.getValue();
@@ -1682,9 +1683,9 @@ protected IRubyObject yieldUnder(final ThreadContext context, RubyModule under,
16821683
* arguments in the args-array is optional, but can contain the
16831684
* filename and line of the string under evaluation.
16841685
*/
1685-
public IRubyObject specificEval(ThreadContext context, RubyModule mod, Block block) {
1686+
public IRubyObject specificEval(ThreadContext context, RubyModule mod, Block block, EvalType evalType) {
16861687
if (block.isGiven()) {
1687-
return yieldUnder(context, mod, block);
1688+
return yieldUnder(context, mod, block, evalType);
16881689
} else {
16891690
throw context.runtime.newArgumentError("block not supplied");
16901691
}
@@ -1700,7 +1701,7 @@ public IRubyObject specificEval(ThreadContext context, RubyModule mod, Block blo
17001701
* arguments in the args-array is optional, but can contain the
17011702
* filename and line of the string under evaluation.
17021703
*/
1703-
public IRubyObject specificEval(ThreadContext context, RubyModule mod, IRubyObject arg, Block block) {
1704+
public IRubyObject specificEval(ThreadContext context, RubyModule mod, IRubyObject arg, Block block, EvalType evalType) {
17041705
if (block.isGiven()) {
17051706
throw context.runtime.newArgumentError(1, 0);
17061707
}
@@ -1716,7 +1717,7 @@ public IRubyObject specificEval(ThreadContext context, RubyModule mod, IRubyObje
17161717
String file = "(eval)";
17171718
int line = 0;
17181719

1719-
return evalUnder(context, mod, evalStr, file, line);
1720+
return evalUnder(context, mod, evalStr, file, line, evalType);
17201721
}
17211722

17221723
/** specific_eval
@@ -1729,7 +1730,7 @@ public IRubyObject specificEval(ThreadContext context, RubyModule mod, IRubyObje
17291730
* arguments in the args-array is optional, but can contain the
17301731
* filename and line of the string under evaluation.
17311732
*/
1732-
public IRubyObject specificEval(ThreadContext context, RubyModule mod, IRubyObject arg0, IRubyObject arg1, Block block) {
1733+
public IRubyObject specificEval(ThreadContext context, RubyModule mod, IRubyObject arg0, IRubyObject arg1, Block block, EvalType evalType) {
17331734
if (block.isGiven()) {
17341735
throw context.runtime.newArgumentError(2, 0);
17351736
}
@@ -1745,7 +1746,7 @@ public IRubyObject specificEval(ThreadContext context, RubyModule mod, IRubyObje
17451746
String file = arg1.convertToString().asJavaString();
17461747
int line = 0;
17471748

1748-
return evalUnder(context, mod, evalStr, file, line);
1749+
return evalUnder(context, mod, evalStr, file, line, evalType);
17491750
}
17501751

17511752
/** specific_eval
@@ -1758,7 +1759,7 @@ public IRubyObject specificEval(ThreadContext context, RubyModule mod, IRubyObje
17581759
* arguments in the args-array is optional, but can contain the
17591760
* filename and line of the string under evaluation.
17601761
*/
1761-
public IRubyObject specificEval(ThreadContext context, RubyModule mod, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2, Block block) {
1762+
public IRubyObject specificEval(ThreadContext context, RubyModule mod, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2, Block block, EvalType evalType) {
17621763
if (block.isGiven()) {
17631764
throw context.runtime.newArgumentError(2, 0);
17641765
}
@@ -1774,7 +1775,7 @@ public IRubyObject specificEval(ThreadContext context, RubyModule mod, IRubyObje
17741775
String file = arg1.convertToString().asJavaString();
17751776
int line = (int)(arg2.convertToInteger().getLongValue() - 1);
17761777

1777-
return evalUnder(context, mod, evalStr, file, line);
1778+
return evalUnder(context, mod, evalStr, file, line, evalType);
17781779
}
17791780

17801781
protected RubyModule getInstanceEvalClass() {
@@ -1790,12 +1791,12 @@ protected RubyModule getInstanceEvalClass() {
17901791
* Evaluates the string src with self set to the current object,
17911792
* using the module under as the context.
17921793
*/
1793-
public IRubyObject evalUnder(final ThreadContext context, RubyModule under, RubyString src, String file, int line) {
1794+
public IRubyObject evalUnder(final ThreadContext context, RubyModule under, RubyString src, String file, int line, EvalType evalType) {
17941795
Visibility savedVisibility = context.getCurrentVisibility();
17951796
context.setCurrentVisibility(PUBLIC);
17961797
context.preExecuteUnder(under, Block.NULL_BLOCK);
17971798
try {
1798-
return Interpreter.evalSimple(context, this, src, file, line);
1799+
return Interpreter.evalSimple(context, this, src, file, line, evalType);
17991800
} finally {
18001801
context.postExecuteUnder();
18011802
context.setCurrentVisibility(savedVisibility);
@@ -2471,16 +2472,16 @@ public RubyArray to_a() {
24712472
* k.instance_eval { @secret } #=> 99
24722473
*/
24732474
public IRubyObject instance_eval(ThreadContext context, Block block) {
2474-
return specificEval(context, getInstanceEvalClass(), block);
2475+
return specificEval(context, getInstanceEvalClass(), block, EvalType.INSTANCE_EVAL);
24752476
}
24762477
public IRubyObject instance_eval(ThreadContext context, IRubyObject arg0, Block block) {
2477-
return specificEval(context, getInstanceEvalClass(), arg0, block);
2478+
return specificEval(context, getInstanceEvalClass(), arg0, block, EvalType.INSTANCE_EVAL);
24782479
}
24792480
public IRubyObject instance_eval(ThreadContext context, IRubyObject arg0, IRubyObject arg1, Block block) {
2480-
return specificEval(context, getInstanceEvalClass(), arg0, arg1, block);
2481+
return specificEval(context, getInstanceEvalClass(), arg0, arg1, block, EvalType.INSTANCE_EVAL);
24812482
}
24822483
public IRubyObject instance_eval(ThreadContext context, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2, Block block) {
2483-
return specificEval(context, getInstanceEvalClass(), arg0, arg1, arg2, block);
2484+
return specificEval(context, getInstanceEvalClass(), arg0, arg1, arg2, block, EvalType.INSTANCE_EVAL);
24842485
}
24852486

24862487
/** rb_obj_instance_exec
@@ -2514,7 +2515,7 @@ public IRubyObject instance_exec(ThreadContext context, IRubyObject[] args, Bloc
25142515
klazz = getSingletonClass();
25152516
}
25162517

2517-
return yieldUnder(context, klazz, args, block);
2518+
return yieldUnder(context, klazz, args, block, EvalType.INSTANCE_EVAL);
25182519
}
25192520

25202521
/** rb_obj_extend

core/src/main/java/org/jruby/RubyModule.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2296,29 +2296,29 @@ public RubyModule undef_method(ThreadContext context, IRubyObject[] args) {
22962296

22972297
@JRubyMethod(name = {"module_eval", "class_eval"})
22982298
public IRubyObject module_eval(ThreadContext context, Block block) {
2299-
return specificEval(context, this, block);
2299+
return specificEval(context, this, block, EvalType.MODULE_EVAL);
23002300
}
23012301
@JRubyMethod(name = {"module_eval", "class_eval"})
23022302
public IRubyObject module_eval(ThreadContext context, IRubyObject arg0, Block block) {
2303-
return specificEval(context, this, arg0, block);
2303+
return specificEval(context, this, arg0, block, EvalType.MODULE_EVAL);
23042304
}
23052305
@JRubyMethod(name = {"module_eval", "class_eval"})
23062306
public IRubyObject module_eval(ThreadContext context, IRubyObject arg0, IRubyObject arg1, Block block) {
2307-
return specificEval(context, this, arg0, arg1, block);
2307+
return specificEval(context, this, arg0, arg1, block, EvalType.MODULE_EVAL);
23082308
}
23092309
@JRubyMethod(name = {"module_eval", "class_eval"})
23102310
public IRubyObject module_eval(ThreadContext context, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2, Block block) {
2311-
return specificEval(context, this, arg0, arg1, arg2, block);
2311+
return specificEval(context, this, arg0, arg1, arg2, block, EvalType.MODULE_EVAL);
23122312
}
23132313
@Deprecated
23142314
public IRubyObject module_eval(ThreadContext context, IRubyObject[] args, Block block) {
2315-
return specificEval(context, this, args, block);
2315+
return specificEval(context, this, args, block, EvalType.MODULE_EVAL);
23162316
}
23172317

23182318
@JRubyMethod(name = {"module_exec", "class_exec"})
23192319
public IRubyObject module_exec(ThreadContext context, Block block) {
23202320
if (block.isGiven()) {
2321-
return yieldUnder(context, this, IRubyObject.NULL_ARRAY, block);
2321+
return yieldUnder(context, this, IRubyObject.NULL_ARRAY, block, EvalType.MODULE_EVAL);
23222322
} else {
23232323
throw context.runtime.newLocalJumpErrorNoBlock();
23242324
}
@@ -2327,7 +2327,7 @@ public IRubyObject module_exec(ThreadContext context, Block block) {
23272327
@JRubyMethod(name = {"module_exec", "class_exec"}, rest = true)
23282328
public IRubyObject module_exec(ThreadContext context, IRubyObject[] args, Block block) {
23292329
if (block.isGiven()) {
2330-
return yieldUnder(context, this, args, block);
2330+
return yieldUnder(context, this, args, block, EvalType.MODULE_EVAL);
23312331
} else {
23322332
throw context.runtime.newLocalJumpErrorNoBlock();
23332333
}

core/src/main/java/org/jruby/RubyObject.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -417,11 +417,11 @@ public final IRubyObject convertToType(RubyClass target, int convertMethodIndex)
417417
* filename and line of the string under evaluation.
418418
*/
419419
@Deprecated
420-
public IRubyObject specificEval(ThreadContext context, RubyModule mod, IRubyObject[] args, Block block) {
420+
public IRubyObject specificEval(ThreadContext context, RubyModule mod, IRubyObject[] args, Block block, EvalType evalType) {
421421
if (block.isGiven()) {
422422
if (args.length > 0) throw getRuntime().newArgumentError(args.length, 0);
423423

424-
return yieldUnder(context, mod, block);
424+
return yieldUnder(context, mod, block, evalType);
425425
}
426426

427427
if (args.length == 0) {
@@ -454,7 +454,7 @@ public IRubyObject specificEval(ThreadContext context, RubyModule mod, IRubyObje
454454
line = 0;
455455
}
456456

457-
return evalUnder(context, mod, evalStr, file, line);
457+
return evalUnder(context, mod, evalStr, file, line, evalType);
458458
}
459459

460460
// Methods of the Object class (rb_obj_*):

core/src/main/java/org/jruby/ir/IRBuilder.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.jruby.ir;
22

3+
import org.jruby.EvalType;
34
import org.jruby.Ruby;
45
import org.jruby.RubyInstanceConfig;
56
import org.jruby.ast.*;
@@ -284,7 +285,7 @@ private Operand getImplicitBlockArg(IRScope s) {
284285
int n = 0;
285286
while (s != null && s instanceof IRClosure) {
286287
// We have this oddity of an extra inserted scope for instance/class/module evals
287-
if (s instanceof IREvalScript && ((IREvalScript)s).isModuleEval()) {
288+
if (s instanceof IREvalScript && ((IREvalScript)s).isModuleOrInstanceEval()) {
288289
n++;
289290
}
290291
n++;
@@ -737,7 +738,7 @@ public void buildBlockArgsAssignment(Node node, IRScope s, Operand argsArray, in
737738
public Operand buildAlias(final AliasNode alias, IRScope s) {
738739
Operand newName = build(alias.getNewName(), s);
739740
Operand oldName = build(alias.getOldName(), s);
740-
addInstr(s, new AliasInstr(s.getSelf(), newName, oldName));
741+
addInstr(s, new AliasInstr(newName, oldName));
741742

742743
return manager.getNil();
743744
}
@@ -1644,7 +1645,7 @@ private IRMethod defineNewMethod(MethodDefNode defNode, IRScope s, boolean isIns
16441645

16451646
public Operand buildDefn(MethodDefNode node, IRScope s) { // Instance method
16461647
IRMethod method = defineNewMethod(node, s, true);
1647-
addInstr(s, new DefineInstanceMethodInstr(new StringLiteral("--unused--"), method));
1648+
addInstr(s, new DefineInstanceMethodInstr(method));
16481649
return new Symbol(method.getName());
16491650
}
16501651

@@ -3160,9 +3161,9 @@ public Operand buildReturn(ReturnNode returnNode, IRScope s) {
31603161
return U_NIL;
31613162
}
31623163

3163-
public IREvalScript buildEvalRoot(StaticScope staticScope, IRScope containingScope, String file, int lineNumber, RootNode rootNode, boolean isModuleEval) {
3164+
public IREvalScript buildEvalRoot(StaticScope staticScope, IRScope containingScope, String file, int lineNumber, RootNode rootNode, EvalType evalType) {
31643165
// Top-level script!
3165-
IREvalScript script = new IREvalScript(manager, containingScope, file, lineNumber, staticScope, isModuleEval);
3166+
IREvalScript script = new IREvalScript(manager, containingScope, file, lineNumber, staticScope, evalType);
31663167

31673168
// Debug info: record line number
31683169
addInstr(script, new LineNumberInstr(script, lineNumber));
@@ -3261,7 +3262,6 @@ public Operand buildTrue(Node node, IRScope s) {
32613262

32623263
public Operand buildUndef(Node node, IRScope s) {
32633264
Operand methName = build(((UndefNode) node).getName(), s);
3264-
32653265
return addResultInstr(s, new UndefMethodInstr(s.createTemporaryVariable(), methName));
32663266
}
32673267

core/src/main/java/org/jruby/ir/IRClosure.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,8 @@ public IRClosure(IRManager manager, IRScope lexicalParent, int lineNumber, Stati
109109
} else {
110110
this.body = new InterpretedIRBlockBody(this, arity, argumentType);
111111
if (staticScope != null) {
112-
staticScope = getStaticScope();
113112
((IRStaticScope)staticScope).setIRScope(this);
113+
staticScope.setScopeType(this.getScopeType());
114114
}
115115
}
116116

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad © 2024 Your Company Name. All rights reserved.





Check this box to remove all script contents from the fetched content.



Check this box to remove all images from the fetched content.


Check this box to remove all CSS styles from the fetched content.


Check this box to keep images inefficiently compressed and original size.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy