예제 #1
0
  @ExplodeLoop
  @Override
  public final Object execute(VirtualFrame frame) {
    final Object self = RubyArguments.getSelf(frame.getArguments());

    // Execute the arguments

    final Object[] argumentsObjects = new Object[arguments.length];

    CompilerAsserts.compilationConstant(arguments.length);
    for (int i = 0; i < arguments.length; i++) {
      argumentsObjects[i] = arguments[i].execute(frame);
    }

    // Execute the block

    RubyProc blockObject;

    if (block != null) {
      final Object blockTempObject = block.execute(frame);

      if (blockTempObject instanceof RubyNilClass) {
        blockObject = null;
      } else {
        blockObject = (RubyProc) blockTempObject;
      }
    } else {
      blockObject = null;
    }

    // Check we have a method and the module is unmodified

    if (!guard(frame, self)) {
      CompilerDirectives.transferToInterpreterAndInvalidate();
      lookup(frame);
    }

    // Call the method

    if (isSplatted) {
      // TODO(CS): need something better to splat the arguments array
      notDesignedForCompilation();
      final RubyArray argumentsArray = (RubyArray) argumentsObjects[0];
      return callNode.call(
          frame,
          RubyArguments.pack(
              superMethod,
              superMethod.getDeclarationFrame(),
              self,
              blockObject,
              argumentsArray.slowToArray()));
    } else {
      return callNode.call(
          frame,
          RubyArguments.pack(
              superMethod, superMethod.getDeclarationFrame(), self, blockObject, argumentsObjects));
    }
  }
  @Specialization(guards = "guardName")
  public Object dispatch(
      VirtualFrame frame,
      RubyNilClass methodReceiverObject,
      LexicalScope lexicalScope,
      RubySymbol receiverObject,
      Object methodName,
      Object blockObject,
      Object argumentsObjects,
      Dispatch.DispatchAction dispatchAction) {
    CompilerAsserts.compilationConstant(dispatchAction);

    // Check the class has not been modified

    try {
      unmodifiedAssumption.check();
    } catch (InvalidAssumptionException e) {
      return resetAndDispatch(
          frame,
          methodReceiverObject,
          lexicalScope,
          receiverObject,
          methodName,
          CompilerDirectives.unsafeCast(blockObject, RubyProc.class, true, false),
          argumentsObjects,
          dispatchAction,
          "class modified");
    }

    if (dispatchAction == Dispatch.DispatchAction.CALL_METHOD) {
      return callNode.call(
          frame,
          RubyArguments.pack(
              method,
              method.getDeclarationFrame(),
              receiverObject,
              CompilerDirectives.unsafeCast(blockObject, RubyProc.class, true, false),
              CompilerDirectives.unsafeCast(argumentsObjects, Object[].class, true)));
    } else if (dispatchAction == Dispatch.DispatchAction.RESPOND_TO_METHOD) {
      return true;
    } else if (dispatchAction == Dispatch.DispatchAction.READ_CONSTANT) {
      return value;
    } else {
      throw new UnsupportedOperationException();
    }
  }