@Override public LocalVariable getLocalVariable(RubySymbol name, int scopeDepth) { LocalVariable lvar = findExistingLocalVariable(name, scopeDepth); if (lvar == null) lvar = getNewLocalVariable(name, scopeDepth); return lvar; }
public synchronized InterpreterContext lazilyAcquireInterpreterContext() { if (!hasBeenBuilt()) { IRBuilder.topIRBuilder(getManager(), this).defineMethodInner(defn, getLexicalParent(), getFlags().contains(IRFlags.CODE_COVERAGE)); defn = null; } return interpreterContext; }
public void emit(IRMethod method) { String name = emitScope(method, method.getName(), method.getCallArgs().length); // push a method handle for binding purposes jvm.method().pushHandle(jvm.clsData().clsName, name, method.getStaticScope().getRequiredArgs()); }
@Override public String toString() { return getOperation() + "(" + container + ", " + method.getName() + ", " + method.getFileName() + ")"; }
private IRMethod defineNewMethod(MethodDefNode defNode, IRScope s, boolean isInstanceMethod) { IRMethod method = new IRMethod(manager, s, defNode.getName(), isInstanceMethod, defNode.getPosition().getLine(), defNode.getScope()); method.addInstr(new ReceiveSelfInstr(getSelf(s))); // Set %current_scope = <current-scope> // Set %current_module = isInstanceMethod ? %self.metaclass : %self IRScope nearestScope = s.getNearestModuleReferencingScope(); method.addInstr(new CopyInstr(method.getCurrentScopeVariable(), new CurrentScope(nearestScope == null ? s : nearestScope))); method.addInstr(new CopyInstr(method.getCurrentModuleVariable(), new ScopeModule(nearestScope == null ? s : nearestScope))); // Build IR for arguments (including the block arg) receiveMethodArgs(defNode.getArgsNode(), method); // Thread poll on entry to method method.addInstr(new ThreadPollInstr()); // Build IR for body Node bodyNode = defNode.getBodyNode(); if (bodyNode != null) { // Create a new nested builder to ensure this gets its own IR builder state Operand rv = newIRBuilder(manager).build(bodyNode, method); if (rv != null) method.addInstr(new ReturnInstr(rv)); } else { method.addInstr(new ReturnInstr(manager.getNil())); } // If the method can receive non-local returns if (method.canReceiveNonlocalReturns()) { handleNonlocalReturnInMethod(method); } return method; }
@Override public void DefineInstanceMethodInstr(DefineInstanceMethodInstr defineinstancemethodinstr) { IRMethod method = defineinstancemethodinstr.getMethod(); StaticScope scope = method.getStaticScope(); if (scope.getRequiredArgs() > 3 || scope.getRestArg() >= 0 || scope.getOptionalArgs() != 0) { throw new RuntimeException("can't compile variable method: " + this); a.ldc(method.getName()); a.ldc(method.getName()); a.ldc(method.getFileName()); a.ldc(method.getLineNumber());
@Override public String toString() { return getOperation() + "(" + returnValue + ", <" + (methodToReturnFrom == null ? "-NULL-" : methodToReturnFrom.getName()) + ">" + ")"; }
public IRMethod convertToMethod(RubySymbol name) { // We want variable scoping to be the same as a method and not see outside itself. if (source == null || getFlags().contains(IRFlags.ACCESS_PARENTS_LOCAL_VARIABLES) || // Built methods cannot search down past method scope getFlags().contains(IRFlags.RECEIVES_CLOSURE_ARG) || // we pass in captured block at define_method as block so explicits ones not supported !isNestedClosuresSafeForMethodConversion()) { source = null; return null; } DefNode def = source; source = null; // FIXME: This should be bytelist from param vs being made (see above). return new IRMethod(getManager(), getLexicalParent(), def, name, true, getLine(), getStaticScope(), getFlags().contains(IRFlags.CODE_COVERAGE)); }
public IRMethod(IRManager manager, IRScope lexicalParent, DefNode defn, RubySymbol name, boolean isInstanceMethod, int lineNumber, StaticScope staticScope, boolean needsCodeCoverage) { super(manager, lexicalParent, name, lineNumber, staticScope); this.defn = defn; this.isInstanceMethod = isInstanceMethod; if (needsCodeCoverage) getFlags().add(IRFlags.CODE_COVERAGE); if (!getManager().isDryRun() && staticScope != null) { staticScope.setIRScope(this); } }
public IRMethod loadInternalMethod(ThreadContext context, IRubyObject self, String method) { try { RubyModule type = self.getMetaClass(); String fileName = "classpath:/jruby/ruby_implementations/" + type + "/" + method + ".rb"; FileResource file = JRubyFile.createResourceAsFile(context.runtime, fileName); Node parseResult = parse(context, file, fileName); IScopingNode scopeNode = (IScopingNode) parseResult.childNodes().get(0); scopeNode.getScope().setModule(type); DefNode defNode = (DefNode) scopeNode.getBodyNode(); IRScriptBody script = new IRScriptBody(this, runtime.newSymbol(parseResult.getFile()), ((RootNode) parseResult).getStaticScope()); IRModuleBody containingScope; if (scopeNode instanceof ModuleNode) { containingScope = new IRModuleBody(this, script, scopeNode.getCPath().getName(), 0, scopeNode.getScope()); } else { containingScope = new IRClassBody(this, script, scopeNode.getCPath().getName(), 0, scopeNode.getScope()); } IRMethod newMethod = new IRMethod(this, containingScope, defNode, context.runtime.newSymbol(method), true, 0, defNode.getScope(), false); newMethod.prepareForCompilation(); return newMethod; } catch (IOException e) { e.printStackTrace(); // FIXME: More elegantly handle broken internal implementations return null; } }
public static void initiateNonLocalReturn(ThreadContext context, IRScope scope, IRMethod methodToReturnFrom, IRubyObject returnValue) { if (scope instanceof IRClosure) { if (methodToReturnFrom == null) { // SSS FIXME: As Tom correctly pointed out, this is not correct. The example that breaks this code is: // // jruby -X-CIR -e "Thread.new { Proc.new { return }.call }.join" // // This should report a LocalJumpError, not a ThreadError. // // The right fix would involve checking the closure to see who it is associated with. // If it is a thread-body, it would be a ThreadError. If not, it would be a local-jump-error // This requires having access to the block -- same requirement as in handleBreakJump. if (context.getThread() == context.runtime.getThreadService().getMainThread()) { throw IRException.RETURN_LocalJumpError.getException(context.runtime); } else { throw context.runtime.newThreadError("return can't jump across threads"); } } // Cannot return from the call that we have long since exited. if (!context.scopeExistsOnCallStack(methodToReturnFrom.getStaticScope())) { if (isDebug()) LOG.info("in scope: " + scope + ", raising unexpected return local jump error"); throw IRException.RETURN_LocalJumpError.getException(context.runtime); } } // methodtoReturnFrom will not be null for explicit returns from class/module/sclass bodies throw IRReturnJump.create(methodToReturnFrom, returnValue); }
public void receiveRequiredArg(Node node, IRScope s, int argIndex, boolean post, int numPreReqd, int numPostRead) { switch (node.getNodeType()) { case ARGUMENTNODE: { ArgumentNode a = (ArgumentNode)node; String argName = a.getName(); if (s instanceof IRMethod) ((IRMethod)s).addArgDesc("req", argName); addArgReceiveInstr(s, s.getNewLocalVariable(argName, 0), argIndex, post, numPreReqd, numPostRead); break; } case MULTIPLEASGN19NODE: { MultipleAsgn19Node childNode = (MultipleAsgn19Node) node; Variable v = s.getNewTemporaryVariable(); addArgReceiveInstr(s, v, argIndex, post, numPreReqd, numPostRead); if (s instanceof IRMethod) ((IRMethod)s).addArgDesc("rest", ""); s.addInstr(new ToAryInstr(v, v, manager.getFalse())); buildMultipleAsgn19Assignment(childNode, s, v, null); break; } default: throw new NotCompilableException("Can't build assignment node: " + node); } }
public IRMethod(IRManager manager, IRScope lexicalParent, String name, boolean isInstanceMethod, int lineNumber, StaticScope staticScope) { super(manager, lexicalParent, name, lexicalParent.getFileName(), lineNumber, staticScope); this.isInstanceMethod = isInstanceMethod; this.callArgs = new ArrayList<Operand>(); this.argDesc = new ArrayList<String[]>(); if (!getManager().isDryRun()) { if (staticScope != null) ((IRStaticScope)staticScope).setIRScope(this); } }
public List<String[]> getParameterList() { return (method instanceof IRMethod) ? ((IRMethod)method).getArgDesc() : new ArrayList<String[]>(); }
private IRMethod defineNewMethod(MethodDefNode defNode, IRScope s, boolean isInstanceMethod) { IRMethod method = new IRMethod(manager, s, defNode.getName(), isInstanceMethod, defNode.getPosition().getLine(), defNode.getScope()); method.addInstr(new ReceiveSelfInstr(getSelf(s))); // Set %current_scope = <current-scope> // Set %current_module = isInstanceMethod ? %self.metaclass : %self IRScope nearestScope = s.getNearestModuleReferencingScope(); method.addInstr(new CopyInstr(method.getCurrentScopeVariable(), new CurrentScope(nearestScope == null ? s : nearestScope))); method.addInstr(new CopyInstr(method.getCurrentModuleVariable(), new ScopeModule(nearestScope == null ? s : nearestScope))); // Build IR for arguments (including the block arg) receiveMethodArgs(defNode.getArgsNode(), method); // Thread poll on entry to method method.addInstr(new ThreadPollInstr()); // Build IR for body Node bodyNode = defNode.getBodyNode(); if (bodyNode != null) { // Create a new nested builder to ensure this gets its own IR builder state Operand rv = newIRBuilder(manager).build(bodyNode, method); if (rv != null) method.addInstr(new ReturnInstr(rv)); } else { method.addInstr(new ReturnInstr(manager.getNil())); } // If the method can receive non-local returns if (method.canReceiveNonlocalReturns()) { handleNonlocalReturnInMethod(method); } return method; }
@Override public void DefineInstanceMethodInstr(DefineInstanceMethodInstr defineinstancemethodinstr) { IRMethod method = defineinstancemethodinstr.getMethod(); StaticScope scope = method.getStaticScope(); if (scope.getRequiredArgs() > 3 || scope.getRestArg() >= 0 || scope.getOptionalArgs() != 0) { throw new RuntimeException("can't compile variable method: " + this); a.ldc(method.getName()); a.ldc(method.getName()); a.ldc(method.getFileName()); a.ldc(method.getLineNumber());
@Override public String toString() { return getOperation() + "(" + container + ", " + method.getName() + ", " + method.getFileName() + ")"; }
@Override public String toString() { return getOperation() + "(" + returnValue + ", <" + (methodToReturnFrom == null ? "-NULL-" : methodToReturnFrom.getName()) + ">" + ")"; }
private IRMethod defineNewMethod(MethodDefNode defNode, boolean isInstanceMethod) { return new IRMethod(manager, scope, defNode, defNode.getName(), isInstanceMethod, defNode.getLine(), defNode.getScope(), needsCodeCoverage()); }
public IRMethod(IRManager manager, IRScope lexicalParent, DefNode defn, RubySymbol name, boolean isInstanceMethod, int lineNumber, StaticScope staticScope, boolean needsCodeCoverage) { super(manager, lexicalParent, name, lineNumber, staticScope); this.defn = defn; this.isInstanceMethod = isInstanceMethod; if (needsCodeCoverage) getFlags().add(IRFlags.CODE_COVERAGE); if (!getManager().isDryRun() && staticScope != null) { staticScope.setIRScope(this); } }