@Override public IRubyObject interpret( Ruby runtime, ThreadContext context, IRubyObject self, Block aBlock) { // Serialization killed our dynamic scope. We can just create an empty one // since serialization cannot serialize an eval (which is the only thing // which is capable of having a non-empty dynamic scope). if (scope == null) { scope = DynamicScope.newDynamicScope(staticScope); } StaticScope theStaticScope = scope.getStaticScope(); // Each root node has a top-level scope that we need to push context.preScopedBody(scope); if (theStaticScope.getModule() == null) { theStaticScope.setModule(runtime.getObject()); } try { return bodyNode.interpret(runtime, context, self, aBlock); } finally { context.postScopedBody(); } }
private Object cache( ThreadContext context, DynamicScope currDynScope, IRubyObject self, Object[] temp, Ruby runtime, Object constant) { StaticScope staticScope = (StaticScope) definingScope.retrieve(context, self, currDynScope, temp); RubyModule object = runtime.getObject(); // SSS FIXME: IRManager objects dont have a static-scope yet, so this hack of looking up the // module right away // This IR needs fixing! constant = (staticScope == null) ? object.getConstant(constName) : staticScope.getConstantInner(runtime, constName, object); if (constant == null) { constant = UndefinedValue.UNDEFINED; } else { // recache generation = runtime.getConstantInvalidator().getData(); cachedConstant = constant; } return constant; }
public BodyCompiler startFileMethod( CompilerCallback args, StaticScope scope, ASTInspector inspector) { MethodBodyCompiler methodCompiler = new MethodBodyCompiler(this, "__file__", "__file__", inspector, scope, 0); // allocate the 0 StaticScope slot in the cache int reservedIndex = cacheCompiler.reserveStaticScope(); assert reservedIndex == 0 : "__file__ scope index was not zero"; methodCompiler.beginMethod(args, scope); // boxed arg list __file__ SkinnyMethodAdapter method = new SkinnyMethodAdapter( getClassVisitor(), ACC_PUBLIC, "__file__", getMethodSignature(4), null, null); method.start(); // invoke static __file__ method.aload(THIS); method.aload(THREADCONTEXT_INDEX); method.aload(SELF_INDEX); method.aload(ARGS_INDEX); method.aload(ARGS_INDEX + 1); // block method.invokestatic(getClassname(), "__file__", getStaticMethodSignature(getClassname(), 4)); method.areturn(); method.end(); if (methodCompiler.isSpecificArity()) { // exact arg list __file__ method = new SkinnyMethodAdapter( getClassVisitor(), ACC_PUBLIC, "__file__", getMethodSignature(scope.getRequiredArgs()), null, null); method.start(); // invoke static __file__ method.aload(THIS); method.aload(THREADCONTEXT_INDEX); method.aload(SELF_INDEX); for (int i = 0; i < scope.getRequiredArgs(); i++) { method.aload(ARGS_INDEX + i); } method.aload(ARGS_INDEX + scope.getRequiredArgs()); // block method.invokestatic( getClassname(), "__file__", getStaticMethodSignature(getClassname(), scope.getRequiredArgs())); method.areturn(); method.end(); } return methodCompiler; }
public void preCompiledClassDummyScope(RubyModule type, StaticScope staticScope) { pushRubyClass(type); pushFrameCopy(); getCurrentFrame().setSelf(type); getCurrentFrame().setVisibility(Visibility.PUBLIC); staticScope.setModule(type); pushScope(staticScope.getDummyScope()); }
public void preMethodNoFrameAndDummyScope(RubyModule clazz, StaticScope staticScope) { RubyModule implementationClass = staticScope.getModule(); // FIXME: This is currently only here because of some problems with IOOutputStream writing to a // "bare" runtime without a proper scope if (implementationClass == null) { implementationClass = clazz; } pushScope(staticScope.getDummyScope()); pushRubyClass(implementationClass); }
@JRubyMethod(name = "initialize", frame = true, visibility = Visibility.PRIVATE) public IRubyObject initialize(ThreadContext context, Block procBlock) { if (!procBlock.isGiven()) { throw getRuntime().newArgumentError("tried to create Proc object without a block"); } if (isLambda() && procBlock == null) { // TODO: warn "tried to create Proc object without a block" } block = procBlock.cloneBlock(); if (isThread()) { // modify the block with a new backref/lastline-grabbing scope StaticScope oldScope = block.getBody().getStaticScope(); StaticScope newScope = new BlockStaticScope(oldScope.getEnclosingScope(), oldScope.getVariables()); newScope.setBackrefLastlineScope(true); newScope.setPreviousCRefScope(oldScope.getPreviousCRefScope()); newScope.setModule(oldScope.getModule()); block.getBody().setStaticScope(newScope); } block.type = type; block.setProcObject(this); file = context.getFile(); line = context.getLine(); return this; }
private static Block getIterNodeBlock(Node blockNode, ThreadContext context, IRubyObject self) { IterNode iterNode = (IterNode) blockNode; StaticScope scope = iterNode.getScope(); scope.determineModule(); // Create block for this iter node // FIXME: We shouldn't use the current scope if it's not actually from the same hierarchy of // static scopes return InterpretedBlock.newInterpretedClosure(context, iterNode.getBlockBody(), self); }
// XXX: Again, screwy evaling under previous frame's scope public void preExecuteUnder(RubyModule executeUnderClass, Block block) { Frame frame = getCurrentFrame(); pushRubyClass(executeUnderClass); DynamicScope scope = getCurrentScope(); StaticScope sScope = new BlockStaticScope(scope.getStaticScope()); sScope.setModule(executeUnderClass); pushScope(DynamicScope.newDynamicScope(sScope, scope)); pushCallFrame(frame.getKlazz(), frame.getName(), frame.getSelf(), block); getCurrentFrame().setVisibility(getPreviousFrame().getVisibility()); }
public static IRubyObject lexicalSearchConst( ThreadContext context, StaticScope scope, MutableCallSite site, String constName, boolean noPrivateConsts) throws Throwable { Ruby runtime = context.runtime; IRubyObject constant = scope.getConstantInner(constName); if (constant == null) { constant = UndefinedValue.UNDEFINED; } SwitchPoint switchPoint = (SwitchPoint) runtime.getConstantInvalidator(constName).getData(); // bind constant until invalidated MethodHandle target = Binder.from(site.type()).drop(0, 2).constant(constant); MethodHandle fallback = Binder.from(site.type()) .append(site, constName) .append(noPrivateConsts) .invokeStatic(LOOKUP, Bootstrap.class, "lexicalSearchConst"); site.setTarget(switchPoint.guardWithTest(target, fallback)); return constant; }
public static IRubyObject searchConst( ThreadContext context, StaticScope staticScope, MutableCallSite site, String constName, boolean noPrivateConsts) throws Throwable { // Lexical lookup Ruby runtime = context.getRuntime(); RubyModule object = runtime.getObject(); IRubyObject constant = (staticScope == null) ? object.getConstant(constName) : staticScope.getConstantInner(constName); // Inheritance lookup RubyModule module = null; if (constant == null) { // SSS FIXME: Is this null check case correct? module = staticScope == null ? object : staticScope.getModule(); constant = noPrivateConsts ? module.getConstantFromNoConstMissing(constName, false) : module.getConstantNoConstMissing(constName); } // Call const_missing or cache if (constant == null) { return module.callMethod(context, "const_missing", context.runtime.fastNewSymbol(constName)); } SwitchPoint switchPoint = (SwitchPoint) runtime.getConstantInvalidator(constName).getData(); // bind constant until invalidated MethodHandle target = Binder.from(site.type()).drop(0, 2).constant(constant); MethodHandle fallback = Binder.from(site.type()) .append(site, constName) .append(noPrivateConsts) .invokeStatic(LOOKUP, Bootstrap.class, "searchConst"); site.setTarget(switchPoint.guardWithTest(target, fallback)); return constant; }
public IRubyObject shadowing_lvar(IRubyObject identifier) { String name = lexer.getIdent(); if (name == "_") return identifier; StaticScope current = getCurrentScope(); if (current.isBlockScope()) { if (current.exists(name) >= 0) yyerror("duplicated argument name"); if (lexer.isVerbose() && current.isDefined(name) >= 0) { lexer.warning("shadowing outer local variable - " + name); } } else if (current.exists(name) >= 0) { yyerror("duplicated argument name"); } return identifier; }
public static RubyModule getClassVariableBase(Ruby runtime, StaticScope scope) { RubyModule rubyClass = scope.getModule(); while (rubyClass.isSingleton() || rubyClass == runtime.getDummy()) { // We ran out of scopes to check if (scope == null) return null; scope = scope.getPreviousCRefScope(); rubyClass = scope.getModule(); if (scope.getPreviousCRefScope() == null) { runtime .getWarnings() .warn( ID.CVAR_FROM_TOPLEVEL_SINGLETON_METHOD, "class variable access from toplevel singleton method"); } } return rubyClass; }
public IRubyObject arg_var(IRubyObject identifier) { String name = lexer.getIdent(); StaticScope current = getCurrentScope(); // Multiple _ arguments are allowed. To not screw with tons of arity // issues in our runtime we will allocate unnamed bogus vars so things // still work. MRI does not use name as intern'd value so they don't // have this issue. if (name == "_") { int count = 0; while (current.exists(name) >= 0) { name = "_$" + count++; } } current.addVariableThisScope(name); return identifier; }
private void setup(Block procBlock) { if (!procBlock.isGiven()) { throw getRuntime().newArgumentError("tried to create Proc object without a block"); } if (isLambda()) { // TODO: warn "tried to create Proc object without a block" } if (isThread()) { // binding for incoming proc must not share frame Binding oldBinding = procBlock.getBinding(); Binding newBinding = new Binding( oldBinding.getSelf(), oldBinding.getFrame().duplicate(), oldBinding.getVisibility(), oldBinding.getDynamicScope(), oldBinding.getMethod(), oldBinding.getFile(), oldBinding.getLine()); block = new Block(procBlock.getBody(), newBinding); // modify the block with a new backref/lastline-grabbing scope StaticScope oldScope = block.getBody().getStaticScope(); StaticScope newScope = oldScope.duplicate(); block.getBody().setStaticScope(newScope); } else { // just use as is block = procBlock; } // force file/line info into the new block's binding block.getBinding().setFile(block.getBody().getFile()); block.getBinding().setLine(block.getBody().getLine()); block.type = type; block.setProcObject(this); // pre-request dummy scope to avoid clone overhead in lightweight blocks block.getBinding().getDummyScope(block.getBody().getStaticScope()); }
private static IRScope getEvalContainerScope(Ruby runtime, StaticScope evalScope) { // SSS FIXME: Weirdness here. We cannot get the containing IR scope from evalScope because of // static-scope wrapping // that is going on // 1. In all cases, DynamicScope.getEvalScope wraps the executing static scope in a new local // scope. // 2. For instance-eval (module-eval, class-eval) scenarios, there is an extra scope that is // added to // the stack in ThreadContext.java:preExecuteUnder // I dont know what rule to apply when. However, in both these cases, since there is no // IR-scope associated, // I have used the hack below where I first unwrap once and see if I get a non-null IR scope. // If that doesn't // work, I unwarp once more and I am guaranteed to get the IR scope I want. IRScope containingIRScope = ((IRStaticScope) evalScope.getEnclosingScope()).getIRScope(); if (containingIRScope == null) containingIRScope = ((IRStaticScope) evalScope.getEnclosingScope().getEnclosingScope()).getIRScope(); return containingIRScope; }
public void preMethodFrameAndScope( RubyModule clazz, String name, IRubyObject self, Block block, StaticScope staticScope) { RubyModule implementationClass = staticScope.getModule(); // FIXME: This is currently only here because of some problems with IOOutputStream writing to a // "bare" runtime without a proper scope if (implementationClass == null) { implementationClass = clazz; } pushCallFrame(clazz, name, self, block); pushScope(DynamicScope.newDynamicScope(staticScope)); pushRubyClass(implementationClass); }
private Object cache( ThreadContext context, StaticScope currScope, DynamicScope currDynScope, IRubyObject self, Object[] temp) { StaticScope staticScope = (StaticScope) definingScope.retrieve(context, self, currScope, currDynScope, temp); IRubyObject constant = staticScope.getConstantInner(constName); if (constant == null) { constant = UndefinedValue.UNDEFINED; } else { // recache Invalidator invalidator = context.runtime.getConstantInvalidator(constName); cache = new ConstantCache(constant, invalidator.getData(), invalidator); } return constant; }