All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jruby.ir.interpreter.Interpreter Maven / Gradle / Ivy

package org.jruby.ir.interpreter;

import java.io.ByteArrayOutputStream;
import java.util.List;
import org.jruby.EvalType;
import org.jruby.Ruby;
import org.jruby.RubyModule;
import org.jruby.RubyString;
import org.jruby.ast.RootNode;
import org.jruby.ir.IRBuilder;
import org.jruby.ir.IRClosure;
import org.jruby.ir.IREvalScript;
import org.jruby.ir.IRScope;
import org.jruby.ir.IRScriptBody;
import org.jruby.ir.IRTranslator;
import org.jruby.ir.operands.IRException;
import org.jruby.ir.operands.WrappedIRClosure;
import org.jruby.ir.persistence.IRDumper;
import org.jruby.ir.runtime.IRBreakJump;
import org.jruby.ir.runtime.IRRuntimeHelpers;
import org.jruby.parser.StaticScope;
import org.jruby.runtime.Binding;
import org.jruby.runtime.Block;
import org.jruby.runtime.DynamicScope;
import org.jruby.runtime.Frame;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.Visibility;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.scope.ManyVarsDynamicScope;
import org.jruby.util.cli.Options;
import org.jruby.util.log.Logger;
import org.jruby.util.log.LoggerFactory;

public class Interpreter extends IRTranslator {
    public static final Logger LOG = LoggerFactory.getLogger(Interpreter.class);
    public static final String ROOT = "
"; static int interpInstrsCount = 0; public static void dumpStats() { if ((IRRuntimeHelpers.isDebug() || IRRuntimeHelpers.inProfileMode()) && interpInstrsCount > 10000) { LOG.info("-- Interpreted instructions: {}", interpInstrsCount); /* for (Operation o: opStats.keySet()) { System.out.println(o + " = " + opStats.get(o).count); } */ } } public static void runBeginBlocks(List beBlocks, ThreadContext context, IRubyObject self, StaticScope currScope, Object[] temp) { if (beBlocks == null) return; for (IRClosure b: beBlocks) { // SSS FIXME: Should I piggyback on WrappedIRClosure.retrieve or just copy that code here? Block blk = (Block)(new WrappedIRClosure(b.getSelf(), b)).retrieve(context, self, currScope, context.getCurrentScope(), temp); blk.yield(context, null); } } @Override protected IRubyObject execute(Ruby runtime, IRScriptBody irScope, IRubyObject self) { BeginEndInterpreterContext ic = (BeginEndInterpreterContext) irScope.getInterpreterContext(); if (IRRuntimeHelpers.shouldPrintIR(runtime)) { ByteArrayOutputStream baos = IRDumper.printIR(irScope, false); LOG.info("Printing simple IR for " + irScope.getId() + ":\n" + new String(baos.toByteArray())); } ThreadContext context = runtime.getCurrentContext(); String name = ROOT; if (IRRuntimeHelpers.isDebug()) LOG.info("Executing {}", ic); // We get the live object ball rolling here. // This give a valid value for the top of this lexical tree. // All new scopes can then retrieve and set based on lexical parent. StaticScope scope = ic.getStaticScope(); RubyModule currModule = scope.getModule(); if (currModule == null) { // SSS FIXME: Looks like this has to do with Kernel#load // and the wrap parameter. Figure it out and document it here. currModule = context.getRuntime().getObject(); } scope.setModule(currModule); IRRuntimeHelpers.prepareScriptScope(context, scope); context.setCurrentVisibility(Visibility.PRIVATE); try { runBeginBlocks(ic.getBeginBlocks(), context, self, scope, null); return INTERPRET_ROOT(context, self, ic, currModule, name); } catch (IRBreakJump bj) { throw IRException.BREAK_LocalJumpError.getException(context.runtime); } finally { dumpStats(); context.popScope(); } } public static IRubyObject INTERPRET_ROOT(ThreadContext context, IRubyObject self, InterpreterContext ic, RubyModule clazz, String name) { try { ThreadContext.pushBacktrace(context, name, ic.getFileName(), context.getLine()); return ic.getEngine().interpret(context, null, self, ic, clazz, name, IRubyObject.NULL_ARRAY, Block.NULL_BLOCK); } finally { ThreadContext.popBacktrace(context); } } public static IRubyObject INTERPRET_EVAL(ThreadContext context, IRubyObject self, InterpreterContext ic, RubyModule clazz, IRubyObject[] args, String name, Block blockArg) { try { ThreadContext.pushBacktrace(context, name, ic.getFileName(), context.getLine()); return ic.getEngine().interpret(context, null, self, ic, clazz, name, args, blockArg); } finally { ThreadContext.popBacktrace(context); } } public static IRubyObject INTERPRET_BLOCK(ThreadContext context, Block block, IRubyObject self, InterpreterContext ic, IRubyObject[] args, String name, Block blockArg) { try { ThreadContext.pushBacktrace(context, name, ic.getFileName(), context.getLine()); return ic.getEngine().interpret(context, block, self, ic, null, name, args, blockArg); } finally { ThreadContext.popBacktrace(context); } } /** * Evaluate the given string. * @param context the current thread's context * @param self the self to evaluate under * @param src The string containing the text to be evaluated * @param file The filename to use when reporting errors during the evaluation * @param lineNumber that the eval supposedly starts from * @return An IRubyObject result from the evaluation */ public static IRubyObject evalSimple(ThreadContext context, RubyModule under, IRubyObject self, RubyString src, String file, int lineNumber, EvalType evalType) { Ruby runtime = context.runtime; // no binding, just eval in "current" frame (caller's frame) DynamicScope parentScope = context.getCurrentScope(); DynamicScope evalScope = new ManyVarsDynamicScope(runtime.getStaticScopeFactory().newEvalScope(parentScope.getStaticScope()), parentScope); evalScope.getStaticScope().setModule(under); context.pushEvalSimpleFrame(self); try { return evalCommon(context, evalScope, self, src, file, lineNumber, "(eval)", Block.NULL_BLOCK, evalType); } finally { context.popFrame(); } } private static IRubyObject evalCommon(ThreadContext context, DynamicScope evalScope, IRubyObject self, IRubyObject src, String file, int lineNumber, String name, Block blockArg, EvalType evalType) { StaticScope ss = evalScope.getStaticScope(); BeginEndInterpreterContext ic = prepareIC(context, evalScope, src, file, lineNumber, evalType); evalScope.setEvalType(evalType); context.pushScope(evalScope); try { evalScope.growIfNeeded(); runBeginBlocks(ic.getBeginBlocks(), context, self, ss, null); return Interpreter.INTERPRET_EVAL(context, self, ic, ic.getStaticScope().getModule(), IRubyObject.NULL_ARRAY, name, blockArg); } finally { evalScope.clearEvalType(); context.popScope(); } } /** * Evaluate the given string under the specified binding object. If the binding is not a Proc or Binding object * (RubyProc or RubyBinding) throw an appropriate type error. * @param context the thread context for the current thread * @param self the self against which eval was called; used as self in the eval in 1.9 mode * @param src The string containing the text to be evaluated * @param binding The binding object under which to perform the evaluation * @return An IRubyObject result from the evaluation */ public static IRubyObject evalWithBinding(ThreadContext context, IRubyObject self, IRubyObject src, Binding binding) { Ruby runtime = context.runtime; DynamicScope evalScope = binding.getEvalScope(runtime); evalScope.getStaticScope().determineModule(); // FIXME: It would be nice to just set this or remove it from staticScope altogether Frame lastFrame = context.preEvalWithBinding(binding); try { return evalCommon(context, evalScope, self, src, binding.getFile(), binding.getLine(), binding.getMethod(), binding.getFrame().getBlock(), EvalType.BINDING_EVAL); } finally { context.postEvalWithBinding(binding, lastFrame); } } private static BeginEndInterpreterContext prepareIC(ThreadContext context, DynamicScope evalScope, IRubyObject src, String file, int lineNumber, EvalType evalType) { Ruby runtime = context.runtime; IRScope containingIRScope = evalScope.getStaticScope().getEnclosingScope().getIRScope(); RootNode rootNode = (RootNode) runtime.parseEval(src.convertToString().getByteList(), file, evalScope, lineNumber); StaticScope staticScope = evalScope.getStaticScope(); // Top-level script! IREvalScript script = new IREvalScript(runtime.getIRManager(), containingIRScope, file, lineNumber, staticScope, evalType); // enable refinements if incoming scope already has an overlay active if (staticScope.getOverlayModuleForRead() != null) { script.setIsMaybeUsingRefinements(); } // We link IRScope to StaticScope because we may add additional variables (like %block). During execution // we end up growing dynamicscope potentially based on any changes made. staticScope.setIRScope(script); BeginEndInterpreterContext ic = (BeginEndInterpreterContext) IRBuilder.topIRBuilder(runtime.getIRManager(), script).buildEvalRoot(rootNode); if (IRRuntimeHelpers.isDebug()) LOG.info(script.debugOutput()); return ic; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy