Beispiel #1
0
  /**
   * For Type.LAMBDA, ensures that the args have the correct arity.
   *
   * <p>For others, transforms the given arguments appropriately for the given arity (i.e. trimming
   * to one arg for fixed arity of one, etc.)
   */
  public static IRubyObject[] prepareArgs(
      ThreadContext context, Block.Type type, BlockBody blockBody, IRubyObject[] args) {
    Signature signature = blockBody.getSignature();

    if (args == null) return IRubyObject.NULL_ARRAY;

    if (type == Block.Type.LAMBDA) {
      signature.checkArity(context.runtime, args);
      return args;
    }

    boolean isFixed = signature.isFixed();
    int required = signature.required();
    int actual = args.length;
    boolean restKwargs =
        blockBody instanceof IRBlockBody && ((IRBlockBody) blockBody).getSignature().hasKwargs();

    // FIXME: This is a hot mess.  restkwargs factors into destructing a single element array as
    // well.  I just weaved it into this logic.
    // for procs and blocks, single array passed to multi-arg must be spread
    if ((signature != Signature.ONE_ARGUMENT
                && required != 0
                && (isFixed || signature != Signature.OPTIONAL)
            || restKwargs)
        && actual == 1
        && args[0].respondsTo("to_ary")) {
      IRubyObject newAry = Helpers.aryToAry(args[0]);

      // This is very common to yield in *IRBlockBody.  When we tackle call protocol for blocks this
      // will combine.
      if (newAry.isNil()) {
        args = new IRubyObject[] {args[0]};
      } else if (newAry instanceof RubyArray) {
        args = ((RubyArray) newAry).toJavaArrayMaybeUnsafe();
      } else {
        throw context.runtime.newTypeError(
            args[0].getType().getName() + "#to_ary should return Array");
      }
      actual = args.length;
    }

    // fixed arity > 0 with mismatch needs a new args array
    if (isFixed && required > 0 && required != actual) {
      IRubyObject[] newArgs = ArraySupport.newCopy(args, required);

      if (required > actual) { // Not enough required args pad.
        Helpers.fillNil(newArgs, actual, required, context.runtime);
      }

      args = newArgs;
    }

    return args;
  }
  public void writeInvokers(File destination) throws IOException {
    for (InvokerDescriptor descriptor : invokerDescriptors) {
      byte[] invokerBytes =
          Helpers.defOffline(
              descriptor.getRubyName(),
              descriptor.getJavaName(),
              descriptor.getClassname(),
              descriptor.getInvokerName(),
              descriptor.getArity(),
              descriptor.getScope(),
              descriptor.getCallConfig(),
              descriptor.getFile(),
              descriptor.getLine());

      if (VERIFY_CLASSFILES)
        CheckClassAdapter.verify(new ClassReader(invokerBytes), false, new PrintWriter(System.err));

      writeClassFile(destination, invokerBytes, descriptor.getInvokerName());
    }

    for (BlockCallbackDescriptor descriptor : blockCallbackDescriptors) {
      byte[] callbackBytes =
          Helpers.createBlockCallbackOffline(
              descriptor.getClassname(),
              descriptor.getMethod(),
              descriptor.getFile(),
              descriptor.getLine());

      if (VERIFY_CLASSFILES)
        CheckClassAdapter.verify(
            new ClassReader(callbackBytes), false, new PrintWriter(System.err));

      writeClassFile(destination, callbackBytes, descriptor.getCallbackName());
    }

    for (BlockCallbackDescriptor descriptor : blockCallback19Descriptors) {
      byte[] callbackBytes =
          Helpers.createBlockCallback19Offline(
              descriptor.getClassname(),
              descriptor.getMethod(),
              descriptor.getFile(),
              descriptor.getLine());

      if (VERIFY_CLASSFILES)
        CheckClassAdapter.verify(
            new ClassReader(callbackBytes), false, new PrintWriter(System.err));

      writeClassFile(destination, callbackBytes, descriptor.getCallbackName());
    }
  }
Beispiel #3
0
  @JRubyMethod
  public IRubyObject parameters(ThreadContext context) {
    BlockBody body = this.getBlock().getBody();

    return Helpers.argumentDescriptorsToParameters(
        context.runtime, body.getArgumentDescriptors(), isLambda());
  }
Beispiel #4
0
  @JRubyMethod(
      name = "raise",
      optional = 3,
      frame = true,
      module = true,
      visibility = Visibility.PRIVATE,
      omit = true)
  public static IRubyObject rbRaise(
      ThreadContext context, IRubyObject recv, IRubyObject[] args, Block block) {
    Ruby runtime = context.runtime;

    // Check for a Java exception
    ConcreteJavaProxy exception = null;
    if (args.length == 0 && runtime.getGlobalVariables().get("$!") instanceof ConcreteJavaProxy) {
      exception = (ConcreteJavaProxy) runtime.getGlobalVariables().get("$!");
    } else if (args.length == 1 && args[0] instanceof ConcreteJavaProxy) {
      exception = (ConcreteJavaProxy) args[0];
    }

    if (exception != null) {
      // looks like someone's trying to raise a Java exception. Let them.
      Object maybeThrowable = exception.getObject();

      if (maybeThrowable instanceof Throwable) {
        // yes, we're cheating here.
        Helpers.throwException((Throwable) maybeThrowable);
        return recv; // not reached
      } else {
        throw runtime.newTypeError("can't raise a non-Throwable Java object");
      }
    } else {
      return RubyKernel.raise(context, recv, args, block);
    }
  }
Beispiel #5
0
 private IRubyObject doCallProcForObj(IRubyObject result) {
   if (proc != null) {
     // return the result of the proc, but not for symbols
     return Helpers.invoke(getRuntime().getCurrentContext(), proc, "call", result);
   }
   return result;
 }
  @Override
  public IRubyObject interpret(
      Ruby runtime, ThreadContext context, IRubyObject self, Block aBlock) {
    RubyModule target = Helpers.checkIsModule(leftNode.interpret(runtime, context, self, aBlock));
    IRubyObject value = getValue(context, target);

    return value != null ? value : target.getConstantFromConstMissing(name);
  }
Beispiel #7
0
  @JRubyMethod(module = true)
  public static IRubyObject timeout(
      final ThreadContext context,
      IRubyObject timeout,
      IRubyObject seconds,
      IRubyObject exceptionType,
      Block block) {
    // No seconds, just yield
    if (seconds.isNil() || Helpers.invoke(context, seconds, "zero?").isTrue()) {
      return block.yieldSpecific(context);
    }

    final Ruby runtime = context.runtime;

    // No timeout in critical section
    if (runtime.getThreadService().getCritical()) {
      return raiseBecauseCritical(context);
    }

    final RubyThread currentThread = context.getThread();
    final AtomicBoolean latch = new AtomicBoolean(false);

    IRubyObject id = new RubyObject(runtime, runtime.getObject());
    RubyClass anonException = (RubyClass) runtime.getClassFromPath("Timeout::AnonymousException");
    Runnable timeoutRunnable =
        exceptionType.isNil()
            ? prepareRunnable(currentThread, runtime, latch, id)
            : prepareRunnableWithException(currentThread, exceptionType, runtime, latch);
    Future timeoutFuture = null;

    try {
      try {
        timeoutFuture =
            timeoutExecutor.schedule(
                timeoutRunnable,
                (long) (seconds.convertToFloat().getDoubleValue() * 1000000),
                TimeUnit.MICROSECONDS);

        return block.yield(context, seconds);
      } finally {
        killTimeoutThread(context, timeoutFuture, latch);
      }
    } catch (RaiseException re) {
      // if it's the exception we're expecting
      if (re.getException().getMetaClass() == anonException) {
        // and we were not given a specific exception
        if (exceptionType.isNil()) {
          // and it's the exception intended for us
          if (re.getException().getInternalVariable("__identifier__") == id) {
            return raiseTimeoutError(context, re);
          }
        }
      }

      // otherwise, rethrow
      throw re;
    }
  }
Beispiel #8
0
  @Override
  public IRubyObject interpret(
      Ruby runtime, ThreadContext context, IRubyObject self, Block aBlock) {
    IRubyObject result = super.interpret(runtime, context, self, aBlock);
    DynamicScope scope = context.getCurrentScope();

    Helpers.updateScopeWithCaptures(context, scope, scopeOffsets, result);

    return result;
  }
Beispiel #9
0
 private static RangeLike rangeValues(ThreadContext context, IRubyObject range) {
   RangeLike like = new RangeLike();
   if (range instanceof RubyRange) {
     RubyRange vrange = (RubyRange) range;
     like.begin = vrange.first(context);
     like.end = vrange.last(context);
     like.excl = vrange.exclude_end_p().isTrue();
   } else {
     if (!range.respondsTo("begin")
         || !range.respondsTo("end")
         || !range.respondsTo("exclude_end?")) {
       return null;
     }
     like.begin = Helpers.invoke(context, range, "begin");
     like.end = Helpers.invoke(context, range, "end");
     like.excl = Helpers.invoke(context, range, "exlucde_end?").isTrue();
   }
   like.range = Helpers.invoke(context, like.end, "-", like.begin);
   return like;
 }
Beispiel #10
0
 public IRubyObject callMethodMissing(
     CacheEntry entry,
     CallType callType,
     ThreadContext context,
     IRubyObject self,
     String name,
     IRubyObject[] args,
     Block block) {
   return Helpers.selectMethodMissing(context, self, entry.method.getVisibility(), name, callType)
       .call(context, self, self.getMetaClass(), name, args, block);
 }
Beispiel #11
0
  /**
   * How many of the keywords listed happen to be required keyword args. Note: total kwargs - req
   * kwarg = opt kwargs.
   */
  public int getRequiredKeywordCount() {
    if (getKeywordCount() < 1) return 0;

    int count = 0;
    for (int i = 0; i < getKeywordCount(); i++) {
      for (Node asgnNode : args[keywordsIndex + i].childNodes()) {
        if (Helpers.isRequiredKeywordArgumentValueNode(asgnNode)) count++;
      }
    }
    return count;
  }
Beispiel #12
0
    protected IRubyObject case_aware_op_aset(
        ThreadContext context, IRubyObject key, final IRubyObject value, boolean caseSensitive) {
      if (!key.respondsTo("to_str")) {
        throw getRuntime().newTypeError("can't convert " + key.getMetaClass() + " into String");
      }
      if (!value.respondsTo("to_str") && !value.isNil()) {
        throw getRuntime().newTypeError("can't convert " + value.getMetaClass() + " into String");
      }

      if (!caseSensitive) {
        key = getCorrectKey(key, context);
      }

      if (value.isNil()) {
        return super.delete(context, key, org.jruby.runtime.Block.NULL_BLOCK);
      }

      IRubyObject keyAsStr = normalizeEnvString(Helpers.invoke(context, key, "to_str"));
      IRubyObject valueAsStr =
          value.isNil()
              ? context.nil
              : normalizeEnvString(Helpers.invoke(context, value, "to_str"));

      if (updateRealENV) {
        POSIX posix = context.runtime.getPosix();
        String keyAsJava = keyAsStr.asJavaString();
        // libc (un)setenv is not reentrant, so we need to synchronize across the entire JVM
        // (JRUBY-5933)
        if (valueAsStr == context.nil) {
          synchronized (Object.class) {
            posix.unsetenv(keyAsJava);
          }
        } else {
          synchronized (Object.class) {
            posix.setenv(keyAsJava, valueAsStr.asJavaString(), 1);
          }
        }
      }

      return super.op_aset(context, keyAsStr, valueAsStr);
    }
Beispiel #13
0
  private static Block getBlockPassBlock(
      Node blockNode, Ruby runtime, ThreadContext context, IRubyObject self, Block currentBlock) {
    Node bodyNode = ((BlockPassNode) blockNode).getBodyNode();
    IRubyObject proc;
    if (bodyNode == null) {
      proc = runtime.getNil();
    } else {
      proc = bodyNode.interpret(runtime, context, self, currentBlock);
    }

    return Helpers.getBlockFromBlockPassBody(proc, currentBlock);
  }
Beispiel #14
0
  @Override
  public IRubyObject interpret(
      Ruby runtime, ThreadContext context, IRubyObject self, Block aBlock) {
    IRubyObject receiver = getReceiverNode().interpret(runtime, context, self, aBlock);

    return callAdapter.callIter(
        context,
        self,
        receiver,
        arg1.interpret(runtime, context, self, aBlock),
        arg2.interpret(runtime, context, self, aBlock),
        Helpers.getBlock(context, self, iterNode));
  }
Beispiel #15
0
  public static InetAddress getRubyInetAddress(ByteList address) throws UnknownHostException {
    // switched to String because the ByteLists were not comparing properly in 1.9 mode (encoding?
    // FIXME: Need to properly decode this string (see Helpers.decodeByteList)
    String addressString = Helpers.byteListToString(address);

    if (addressString.equals(BROADCAST)) {
      return InetAddress.getByAddress(INADDR_BROADCAST);

    } else if (addressString.equals(ANY)) {
      return InetAddress.getByAddress(INADDR_ANY);

    } else {
      return InetAddress.getByName(addressString);
    }
  }
  @Override
  public RubyString definition(
      Ruby runtime, ThreadContext context, IRubyObject self, Block aBlock) {
    IRubyObject lastError = context.getErrorInfo();
    try {
      if (Helpers.isModuleAndHasConstant(
          leftNode.interpret(runtime, context, self, aBlock), name)) {
        return runtime.getDefinedMessage(DefinedMessage.CONSTANT);
      }
    } catch (JumpException e) {
      // replace lastError
      context.setErrorInfo(lastError);
    }

    return null;
  }
Beispiel #17
0
 // c: rb_random_real
 public static double randomReal(ThreadContext context, IRubyObject obj) {
   RandomType random = null;
   if (obj.equals(context.runtime.getRandomClass())) {
     random = getDefaultRand(context);
   }
   if (obj instanceof RubyRandom) {
     random = ((RubyRandom) obj).random;
   }
   if (random != null) {
     return random.genrandReal();
   }
   double d = RubyNumeric.num2dbl(Helpers.invoke(context, obj, "rand"));
   if (d < 0.0 || d >= 1.0) {
     throw context.runtime.newRangeError("random number too big: " + d);
   }
   return d;
 }
Beispiel #18
0
 public IRubyObject dispatch(
     String method_name,
     IRubyObject arg1,
     IRubyObject arg2,
     IRubyObject arg3,
     IRubyObject arg4,
     IRubyObject arg5) {
   return Helpers.invoke(
       context,
       ripper,
       method_name,
       escape(arg1),
       escape(arg2),
       escape(arg3),
       escape(arg4),
       escape(arg5));
 }
Beispiel #19
0
  @JRubyMethod(name = "ruby", meta = true)
  public static IRubyObject ruby(ThreadContext context, IRubyObject recv) {
    Ruby runtime = context.runtime;
    RubyHash configHash = (RubyHash) runtime.getModule("RbConfig").getConstant("CONFIG");

    IRubyObject bindir = configHash.op_aref(context, runtime.newString("bindir"));
    IRubyObject ruby_install_name =
        configHash.op_aref(context, runtime.newString("ruby_install_name"));
    IRubyObject exeext = configHash.op_aref(context, runtime.newString("EXEEXT"));

    return Helpers.invoke(
        context,
        runtime.getClass("File"),
        "join",
        bindir,
        ruby_install_name.callMethod(context, "+", exeext));
  }
  /**
   * For handling all non-Ruby exceptions bubbling out of threads
   *
   * @param exception
   */
  @SuppressWarnings("deprecation")
  public void exceptionRaised(Throwable exception) {
    if (exception instanceof RaiseException) {
      exceptionRaised((RaiseException) exception);
      return;
    }

    assert isCurrent();

    Ruby runtime = getRuntime();
    if (abortOnException(runtime) && exception instanceof Error) {
      // re-propagate on main thread
      runtime.getThreadService().getMainThread().getNativeThread().stop(exception);
    } else {
      // just rethrow on this thread, let system handlers report it
      Helpers.throwException(exception);
    }
  }
Beispiel #21
0
  @JRubyMethod(module = true)
  public static IRubyObject timeout(
      final ThreadContext context, IRubyObject timeout, IRubyObject seconds, Block block) {
    // No seconds, just yield
    if (seconds.isNil() || Helpers.invoke(context, seconds, "zero?").isTrue()) {
      return block.yieldSpecific(context);
    }

    final Ruby runtime = context.runtime;

    // No timeout in critical section
    if (runtime.getThreadService().getCritical()) {
      return raiseBecauseCritical(context);
    }

    final RubyThread currentThread = context.getThread();
    final AtomicBoolean latch = new AtomicBoolean(false);

    IRubyObject id = new RubyObject(runtime, runtime.getObject());
    Runnable timeoutRunnable = prepareRunnable(currentThread, runtime, latch, id);
    Future timeoutFuture = null;

    try {
      try {
        timeoutFuture =
            timeoutExecutor.schedule(
                timeoutRunnable,
                (long) (seconds.convertToFloat().getDoubleValue() * 1000000),
                TimeUnit.MICROSECONDS);

        return block.yield(context, seconds);
      } finally {
        killTimeoutThread(context, timeoutFuture, latch);
      }
    } catch (RaiseException re) {
      if (re.getException().getInternalVariable("__identifier__") == id) {
        return raiseTimeoutError(context, re);
      } else {
        throw re;
      }
    }
  }
Beispiel #22
0
  private static JavaClass getTargetType(ThreadContext context, Ruby runtime, IRubyObject type) {
    JavaClass targetType;

    if (type instanceof RubyString || type instanceof RubySymbol) {
      targetType = runtime.getJavaSupport().getNameClassMap().get(type.asJavaString());
      if (targetType == null) targetType = JavaClass.forNameVerbose(runtime, type.asJavaString());
    } else if (type instanceof RubyModule && type.respondsTo("java_class")) {
      targetType = (JavaClass) Helpers.invoke(context, type, "java_class");
    } else if (type instanceof JavaProxy) {
      if (((JavaProxy) type).getObject() instanceof Class) {
        targetType = JavaClass.get(runtime, (Class) ((JavaProxy) type).getObject());
      } else {
        throw runtime.newTypeError("not a valid target type: " + type);
      }
    } else {
      throw runtime.newTypeError("unable to convert to type: " + type);
    }

    return targetType;
  }
  // ENEBO: Some of this logic should be put back into the Nodes themselves, but the more
  // esoteric features of 1.9 make this difficult to know how to do this yet.
  public BlockBody newCompiledBlockBody19(ThreadContext context, IterNode iterNode) {
    final ArgsNode argsNode = (ArgsNode) iterNode.getVarNode();

    boolean hasMultipleArgsHead = false;
    if (iterNode.getVarNode() instanceof MultipleAsgnNode) {
      hasMultipleArgsHead = ((MultipleAsgnNode) iterNode.getVarNode()).getHeadNode() != null;
    }

    NodeType argsNodeId = BlockBody.getArgumentTypeWackyHack(iterNode);

    return new CompiledBlock19(
        ((ArgsNode) iterNode.getVarNode()).getArity(),
        iterNode.getScope(),
        compileBlock19(
            context,
            new StandardASMCompiler("blahfooblah" + System.currentTimeMillis(), "blahfooblah"),
            iterNode),
        hasMultipleArgsHead,
        BlockBody.asArgumentType(argsNodeId),
        Helpers.encodeParameterList(argsNode).split(";"));
  }
Beispiel #24
0
    private IRubyObject invokeRuby(
        final DynamicMethod method,
        final JavaProxyMethod proxyMethod,
        final RubyClass metaClass,
        final String name,
        final Object[] nargs) {
      final IRubyObject[] newArgs = new IRubyObject[nargs.length];
      for (int i = nargs.length; --i >= 0; ) {
        newArgs[i] = JavaUtil.convertJavaToUsableRubyObject(runtime, nargs[i]);
      }

      final int arity = method.getArity().getValue();

      if (arity < 0 || arity == newArgs.length) {
        final ThreadContext context = runtime.getCurrentContext();
        return method.call(context, self, metaClass, name, newArgs);
      }
      if (proxyMethod.hasSuperImplementation()) {
        final ThreadContext context = runtime.getCurrentContext();
        final RubyClass superClass = metaClass.getSuperClass();
        return Helpers.invokeAs(context, superClass, self, name, newArgs, Block.NULL_BLOCK);
      }
      throw runtime.newArgumentError(newArgs.length, arity);
    }
  public void endScript(boolean generateLoad, boolean generateMain) {
    // add Script#run impl, used for running this script with a specified threadcontext and self
    // root method of a script is always in __file__ method
    String methodName = "__file__";

    String loadSig = sig(IRubyObject.class, ThreadContext.class, IRubyObject.class, boolean.class);

    if (generateLoad || generateMain) {
      // the load method is used for loading as a top-level script, and prepares appropriate scoping
      // around the code
      SkinnyMethodAdapter method =
          new SkinnyMethodAdapter(getClassVisitor(), ACC_PUBLIC, "load", loadSig, null, null);
      method.start();

      // invoke __file__ with threadcontext, self, args (null), and block (null)
      Label tryBegin = new Label();
      Label tryFinally = new Label();

      method.label(tryBegin);
      method.aload(THREADCONTEXT_INDEX);
      String scopeNames = Helpers.encodeScope(topLevelScope);
      method.ldc(scopeNames);
      method.iload(SELF_INDEX + 1);
      method.invokestatic(
          p(Helpers.class),
          "preLoad",
          sig(StaticScope.class, ThreadContext.class, String.class, boolean.class));

      // store root scope
      method.aload(THIS);
      method.swap();
      method.invokevirtual(
          p(AbstractScript.class), "setRootScope", sig(void.class, StaticScope.class));

      method.aload(THIS);
      method.aload(THREADCONTEXT_INDEX);
      method.aload(SELF_INDEX);
      method.getstatic(p(IRubyObject.class), "NULL_ARRAY", ci(IRubyObject[].class));
      method.getstatic(p(Block.class), "NULL_BLOCK", ci(Block.class));

      method.invokestatic(getClassname(), methodName, getStaticMethodSignature(getClassname(), 4));
      method.aload(THREADCONTEXT_INDEX);
      method.invokestatic(p(Helpers.class), "postLoad", sig(void.class, ThreadContext.class));
      method.areturn();

      method.label(tryFinally);
      method.aload(THREADCONTEXT_INDEX);
      method.invokestatic(p(Helpers.class), "postLoad", sig(void.class, ThreadContext.class));
      method.athrow();

      method.trycatch(tryBegin, tryFinally, tryFinally, null);

      method.end();
    }

    if (generateMain) {
      // add main impl, used for detached or command-line execution of this script with a new
      // runtime
      // root method of a script is always in stub0, method0
      SkinnyMethodAdapter method =
          new SkinnyMethodAdapter(
              getClassVisitor(),
              ACC_PUBLIC | ACC_STATIC,
              "main",
              sig(Void.TYPE, params(String[].class)),
              null,
              null);
      method.start();

      // init script filename to simple class name in case we don't assign it (null ClassLoader)
      method.ldc(getClassname().replaceAll("\\\\.", "/"));
      method.astore(1);

      // new instance to invoke run against
      method.newobj(getClassname());
      method.dup();
      method.invokespecial(getClassname(), "<init>", sig(Void.TYPE));

      // guard against null classloader
      method.ldc(Type.getType("L" + getClassname() + ";"));
      method.invokevirtual(p(Class.class), "getClassLoader", sig(ClassLoader.class));
      Label skip = new Label();
      method.ifnull(skip);

      // set filename for the loaded script class (JRUBY-4825)
      method.dup();
      method.ldc(Type.getType("L" + getClassname() + ";"));
      method.invokevirtual(p(Class.class), "getClassLoader", sig(ClassLoader.class));
      method.ldc(getClassname() + ".class");
      method.invokevirtual(p(ClassLoader.class), "getResource", sig(URL.class, String.class));
      method.invokevirtual(p(Object.class), "toString", sig(String.class));
      method.astore(1);
      method.aload(1);
      method.invokevirtual(p(AbstractScript.class), "setFilename", sig(void.class, String.class));

      // ifnull ClassLoader
      method.label(skip);

      // instance config for the script run
      method.newobj(p(RubyInstanceConfig.class));
      method.dup();
      method.invokespecial(p(RubyInstanceConfig.class), "<init>", "()V");

      // set argv from main's args
      method.dup();
      method.aload(0);
      method.invokevirtual(p(RubyInstanceConfig.class), "setArgv", sig(void.class, String[].class));

      // set script filename ($0)
      method.dup();
      method.aload(1);
      method.invokevirtual(
          p(RubyInstanceConfig.class), "setScriptFileName", sig(void.class, String.class));

      // invoke run with threadcontext and topself
      method.invokestatic(p(Ruby.class), "newInstance", sig(Ruby.class, RubyInstanceConfig.class));
      method.dup();

      method.invokevirtual(RUBY, "getCurrentContext", sig(ThreadContext.class));
      method.swap();
      method.invokevirtual(RUBY, "getTopSelf", sig(IRubyObject.class));
      method.ldc(false);

      method.invokevirtual(getClassname(), "load", loadSig);
      method.voidreturn();
      method.end();
    }

    getCacheCompiler().finish();

    endInit();
    endClassInit();
  }
Beispiel #26
0
 /** num_to_int */
 @JRubyMethod(name = "to_int")
 public IRubyObject to_int(ThreadContext context) {
   return Helpers.invoke(context, this, "to_i");
 }
Beispiel #27
0
 public IRubyObject dispatch(String method_name) {
   return Helpers.invoke(context, ripper, method_name);
 }
Beispiel #28
0
 public IRubyObject dispatch(String method_name, IRubyObject arg1) {
   return Helpers.invoke(context, ripper, method_name, escape(arg1));
 }
 public static String buildStaticScopeNames(StaticScope scope) {
   return Helpers.encodeScope(scope);
 }
Beispiel #30
0
  private static IRubyObject interpret(
      ThreadContext context,
      IRubyObject self,
      IRScope scope,
      Visibility visibility,
      RubyModule implClass,
      IRubyObject[] args,
      Block block,
      Block.Type blockType) {
    Instr[] instrs = scope.getInstrsForInterpretation();

    // The base IR may not have been processed yet
    if (instrs == null) instrs = scope.prepareForInterpretation(blockType == Block.Type.LAMBDA);

    int numTempVars = scope.getTemporaryVariableSize();
    Object[] temp = numTempVars > 0 ? new Object[numTempVars] : null;
    int n = instrs.length;
    int ipc = 0;
    Instr instr = null;
    Object exception = null;
    int kwArgHashCount =
        (scope.receivesKeywordArgs() && args[args.length - 1] instanceof RubyHash) ? 1 : 0;
    DynamicScope currDynScope = context.getCurrentScope();

    // Counter tpCount = null;

    // Init profiling this scope
    boolean debug = IRRuntimeHelpers.isDebug();
    boolean profile = IRRuntimeHelpers.inProfileMode();
    Integer scopeVersion = profile ? initProfiling(scope) : 0;

    // Enter the looooop!
    while (ipc < n) {
      instr = instrs[ipc];
      ipc++;
      Operation operation = instr.getOperation();
      if (debug) {
        LOG.info("I: {}", instr);
        interpInstrsCount++;
      } else if (profile) {
        if (operation.modifiesCode()) codeModificationsCount++;
        interpInstrsCount++;
        /*
        Counter cnt = opStats.get(operation);
        if (cnt == null) {
            cnt = new Counter();
            opStats.put(operation, cnt);
        }
        cnt.count++;
        */
      }

      try {
        switch (operation.opClass) {
          case ARG_OP:
            {
              receiveArg(
                  context,
                  instr,
                  operation,
                  args,
                  kwArgHashCount,
                  currDynScope,
                  temp,
                  exception,
                  block);
              break;
            }
          case BRANCH_OP:
            {
              if (operation == Operation.JUMP) {
                ipc = ((JumpInstr) instr).getJumpTarget().getTargetPC();
              } else {
                ipc = instr.interpretAndGetNewIPC(context, currDynScope, self, temp, ipc);
              }
              break;
            }
          case CALL_OP:
            {
              if (profile) updateCallSite(instr, scope, scopeVersion);
              processCall(
                  context, instr, operation, scope, currDynScope, temp, self, block, blockType);
              break;
            }
          case BOOK_KEEPING_OP:
            {
              switch (operation) {
                case PUSH_FRAME:
                  {
                    context.preMethodFrameAndClass(
                        implClass, scope.getName(), self, block, scope.getStaticScope());
                    context.setCurrentVisibility(visibility);
                    break;
                  }
                case PUSH_BINDING:
                  {
                    // SSS NOTE: Method scopes only!
                    //
                    // Blocks are a headache -- so, these instrs. are only added to IRMethods.
                    // Blocks have more complicated logic for pushing a dynamic scope (see
                    // InterpretedIRBlockBody)
                    // Changed by DPR
                    currDynScope =
                        DynamicScope.newDynamicScope(
                            scope.getStaticScope(), context.getCurrentScope().getDepth());
                    context.pushScope(currDynScope);
                    break;
                  }
                case CHECK_ARITY:
                  ((CheckArityInstr) instr).checkArity(context.runtime, args.length);
                  break;
                case POP_FRAME:
                  context.popFrame();
                  context.popRubyClass();
                  break;
                case POP_BINDING:
                  context.popScope();
                  break;
                case THREAD_POLL:
                  if (profile) {
                    // SSS: Not being used currently
                    // tpCount.count++;
                    globalThreadPollCount++;

                    // 20K is arbitrary
                    // Every 20K profile counts, spit out profile stats
                    if (globalThreadPollCount % 20000 == 0) {
                      analyzeProfile();
                      // outputProfileStats();
                    }
                  }
                  context.callThreadPoll();
                  break;
                case LINE_NUM:
                  context.setLine(((LineNumberInstr) instr).lineNumber);
                  break;
                case RECORD_END_BLOCK:
                  ((RecordEndBlockInstr) instr).interpret();
                  break;
              }
              break;
            }
          case OTHER_OP:
            {
              Object result = null;
              switch (operation) {
                  // --------- Return flavored instructions --------
                case BREAK:
                  {
                    BreakInstr bi = (BreakInstr) instr;
                    IRubyObject rv =
                        (IRubyObject)
                            bi.getReturnValue().retrieve(context, self, currDynScope, temp);
                    // This also handles breaks in lambdas -- by converting them to a return
                    return IRRuntimeHelpers.initiateBreak(
                        context, scope, bi.getScopeToReturnTo().getScopeId(), rv, blockType);
                  }
                case RETURN:
                  {
                    return (IRubyObject)
                        retrieveOp(
                            ((ReturnBase) instr).getReturnValue(),
                            context,
                            self,
                            currDynScope,
                            temp);
                  }
                case NONLOCAL_RETURN:
                  {
                    NonlocalReturnInstr ri = (NonlocalReturnInstr) instr;
                    IRubyObject rv =
                        (IRubyObject)
                            retrieveOp(ri.getReturnValue(), context, self, currDynScope, temp);
                    ipc = n;
                    // If not in a lambda, check if this was a non-local return
                    if (!IRRuntimeHelpers.inLambda(blockType)) {
                      IRRuntimeHelpers.initiateNonLocalReturn(
                          context, scope, ri.methodToReturnFrom, rv);
                    }
                    return rv;
                  }

                  // ---------- Common instruction ---------
                case COPY:
                  {
                    CopyInstr c = (CopyInstr) instr;
                    result = retrieveOp(c.getSource(), context, self, currDynScope, temp);
                    setResult(temp, currDynScope, c.getResult(), result);
                    break;
                  }

                case GET_FIELD:
                  {
                    GetFieldInstr gfi = (GetFieldInstr) instr;
                    IRubyObject object =
                        (IRubyObject) gfi.getSource().retrieve(context, self, currDynScope, temp);
                    VariableAccessor a = gfi.getAccessor(object);
                    result = a == null ? null : (IRubyObject) a.get(object);
                    if (result == null) {
                      result = context.nil;
                    }
                    setResult(temp, currDynScope, gfi.getResult(), result);
                    break;
                  }

                case SEARCH_CONST:
                  {
                    SearchConstInstr sci = (SearchConstInstr) instr;
                    result = sci.getCachedConst();
                    if (!sci.isCached(context, result))
                      result = sci.cache(context, currDynScope, self, temp);
                    setResult(temp, currDynScope, sci.getResult(), result);
                    break;
                  }

                  // ---------- All the rest ---------
                default:
                  result = instr.interpret(context, currDynScope, self, temp, block);
                  setResult(temp, currDynScope, instr, result);
                  break;
              }

              break;
            }
        }
      } catch (Throwable t) {
        // Unrescuable:
        //    IRReturnJump, ThreadKill, RubyContinuation, MainExitException, etc.
        //    These cannot be rescued -- only run ensure blocks
        //
        // Others:
        //    IRBreakJump, Ruby exceptions, errors, and other java exceptions.
        //    These can be rescued -- run rescue blocks

        if (debug)
          LOG.info(
              "in scope: "
                  + scope
                  + ", caught Java throwable: "
                  + t
                  + "; excepting instr: "
                  + instr);
        ipc = (t instanceof Unrescuable) ? scope.getEnsurerPC(instr) : scope.getRescuerPC(instr);
        if (debug) LOG.info("ipc for rescuer/ensurer: " + ipc);

        if (ipc == -1) {
          Helpers.throwException((Throwable) t);
        } else {
          exception = t;
        }
      }
    }

    // Control should never get here!
    // SSS FIXME: But looks like BEGIN/END blocks get here -- needs fixing
    return null;
  }