Пример #1
0
 @ExplodeLoop
 public void profileArguments(Object[] args) {
   Assumption typesAssumption = profiledArgumentTypesAssumption;
   if (typesAssumption == null) {
     CompilerDirectives.transferToInterpreterAndInvalidate();
     initializeProfiledArgumentTypes(args);
   } else {
     Class<?>[] types = profiledArgumentTypes;
     if (types != null) {
       if (types.length != args.length) {
         CompilerDirectives.transferToInterpreterAndInvalidate();
         typesAssumption.invalidate();
         profiledArgumentTypes = null;
       } else if (typesAssumption.isValid()) {
         for (int i = 0; i < types.length; i++) {
           Class<?> type = types[i];
           Object value = args[i];
           if (type != null && (value == null || value.getClass() != type)) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
             updateProfiledArgumentTypes(args, types);
             break;
           }
         }
       }
     }
   }
 }
Пример #2
0
 @Override
 public Object call(Object... args) {
   compilationProfile.reportIndirectCall();
   if (profiledArgumentTypesAssumption != null && profiledArgumentTypesAssumption.isValid()) {
     // Argument profiling is not possible for targets of indirect calls.
     CompilerDirectives.transferToInterpreterAndInvalidate();
     profiledArgumentTypesAssumption.invalidate();
     profiledArgumentTypes = null;
   }
   return doInvoke(args);
 }
  @Override
  public Object executeDispatch(
      VirtualFrame frame,
      Object receiverObject,
      Object methodName,
      DynamicObject blockObject,
      Object[] argumentsObjects) {
    try {
      unmodifiedAssumption.check();
    } catch (InvalidAssumptionException e) {
      return resetAndDispatch(
          frame, receiverObject, methodName, blockObject, argumentsObjects, "class modified");
    }

    if (!guard(methodName, receiverObject)) {
      return next.executeDispatch(frame, receiverObject, methodName, blockObject, argumentsObjects);
    }

    switch (getDispatchAction()) {
      case CALL_METHOD:
        return call(callNode, frame, method, expectedReceiver, blockObject, argumentsObjects);

      case RESPOND_TO_METHOD:
        return true;

      default:
        throw new UnsupportedOperationException();
    }
  }
Пример #4
0
 void invalidate() {
   if (version != null) {
     version.invalidate();
   } else {
     assert chain == null;
   }
 }
  @Override
  public Object executeDispatch(
      VirtualFrame frame,
      Object receiverObject,
      Object methodName,
      Object blockObject,
      Object argumentsObjects) {
    if (!guardName(methodName) || !(receiverObject instanceof RubySymbol)) {
      return next.executeDispatch(frame, receiverObject, methodName, blockObject, argumentsObjects);
    }

    // Check the class has not been modified

    try {
      unmodifiedAssumption.check();
    } catch (InvalidAssumptionException e) {
      return resetAndDispatch(
          frame,
          receiverObject,
          methodName,
          (RubyProc) blockObject,
          argumentsObjects,
          "class modified");
    }

    switch (getDispatchAction()) {
      case CALL_METHOD:
        {
          if (isIndirect()) {
            return indirectCallNode.call(
                frame,
                method.getCallTarget(),
                RubyArguments.pack(
                    method,
                    method.getDeclarationFrame(),
                    receiverObject,
                    (RubyProc) blockObject,
                    (Object[]) argumentsObjects));
          } else {
            return callNode.call(
                frame,
                RubyArguments.pack(
                    method,
                    method.getDeclarationFrame(),
                    receiverObject,
                    (RubyProc) blockObject,
                    (Object[]) argumentsObjects));
          }
        }

      case RESPOND_TO_METHOD:
        return true;

      case READ_CONSTANT:
        return value;

      default:
        throw new UnsupportedOperationException();
    }
  }
  @Override
  public Object executeDispatch(
      VirtualFrame frame,
      Object receiverObject,
      Object methodName,
      DynamicObject blockObject,
      Object[] argumentsObjects) {
    if (!guard(methodName, receiverObject)) {
      return next.executeDispatch(frame, receiverObject, methodName, blockObject, argumentsObjects);
    }

    // Check the class has not been modified

    try {
      unmodifiedAssumption.check();
    } catch (InvalidAssumptionException e) {
      return resetAndDispatch(
          frame, receiverObject, methodName, blockObject, argumentsObjects, "class modified");
    }

    switch (getDispatchAction()) {
      case CALL_METHOD:
        return MISSING;

      case RESPOND_TO_METHOD:
        return false;

      default:
        throw new UnsupportedOperationException();
    }
  }
Пример #7
0
 private void poll(Node currentNode, boolean fromBlockingCall) {
   try {
     assumption.check();
   } catch (InvalidAssumptionException e) {
     assumptionInvalidated(currentNode, fromBlockingCall);
   }
 }
Пример #8
0
 private boolean lazyUpdate(VirtualFrame frame) {
   if (version == null || !version.isValid()) {
     CompilerDirectives.transferToInterpreterAndInvalidate();
     // i am allowed to pass in the virtual frame as its instances are always materialized
     return lazyUpdatedImpl(frame);
   }
   return true;
 }
Пример #9
0
 public void profileReturnType(Object result) {
   Assumption returnTypeAssumption = profiledReturnTypeAssumption;
   if (returnTypeAssumption == null) {
     if (TruffleReturnTypeSpeculation.getValue()) {
       CompilerDirectives.transferToInterpreterAndInvalidate();
       profiledReturnType = (result == null ? null : result.getClass());
       profiledReturnTypeAssumption =
           Truffle.getRuntime().createAssumption("Profiled Return Type");
     }
   } else if (profiledReturnType != null) {
     if (result == null || profiledReturnType != result.getClass()) {
       CompilerDirectives.transferToInterpreterAndInvalidate();
       profiledReturnType = null;
       returnTypeAssumption.invalidate();
     }
   }
 }
Пример #10
0
 @Override
 public double executeFloat(RubyBasicObject receiver) throws UnexpectedResultException {
   if (hasFloat && receiver.getRubyClass() == expectedClass && unmodifiedAssumption.isValid()) {
     return integerFixnumValue;
   } else {
     return next.executeFloat(receiver);
   }
 }
Пример #11
0
 @Override
 public boolean executeBoolean(RubyBasicObject receiver) throws UnexpectedResultException {
   if (hasBoolean && receiver.getRubyClass() == expectedClass && unmodifiedAssumption.isValid()) {
     return booleanValue;
   } else {
     return next.executeBoolean(receiver);
   }
 }
Пример #12
0
 private void updateProfiledArgumentTypes(Object[] args, Class<?>[] types) {
   CompilerAsserts.neverPartOfCompilation();
   profiledArgumentTypesAssumption.invalidate();
   for (int j = 0; j < types.length; j++) {
     types[j] = joinTypes(types[j], classOf(args[j]));
   }
   profiledArgumentTypesAssumption =
       Truffle.getRuntime().createAssumption("Profiled Argument Types");
 }
Пример #13
0
 @Override
 public void leave(Node astNode, VirtualFrame frame, Object result) {
   try {
     inactiveAssumption.check();
   } catch (InvalidAssumptionException e) {
     final ActiveLeaveDebugProbe activeNode = createActive();
     replace(activeNode);
     activeNode.leave(astNode, frame, result);
   }
 }
Пример #14
0
 @Override
 public long executeLongFixnum(RubyBasicObject receiver) throws UnexpectedResultException {
   if (hasLongFixnum
       && receiver.getRubyClass() == expectedClass
       && unmodifiedAssumption.isValid()) {
     return longFixnumValue;
   } else {
     return next.executeLongFixnum(receiver);
   }
 }
Пример #15
0
  @Override
  public Object execute(RubyBasicObject receiver) {
    // TODO(CS): not sure trying next on invalid assumption is right...

    if (receiver.getRubyClass() == expectedClass && unmodifiedAssumption.isValid()) {
      return value;
    } else {
      return next.execute(receiver);
    }
  }
Пример #16
0
  public final Object callRoot(Object[] originalArguments) {
    Object[] args = originalArguments;
    if (CompilerDirectives.inCompiledCode()) {
      Assumption argumentTypesAssumption = this.profiledArgumentTypesAssumption;
      if (argumentTypesAssumption != null && argumentTypesAssumption.isValid()) {
        args =
            unsafeCast(
                castArrayFixedLength(args, profiledArgumentTypes.length),
                Object[].class,
                true,
                true);
        args = castArguments(args);
      }
    }

    VirtualFrame frame = createFrame(getRootNode().getFrameDescriptor(), args);
    Object result = callProxy(frame);

    profileReturnType(result);

    return result;
  }
Пример #17
0
  private void pauseAllThreadsAndExecute(
      Node currentNode, boolean isRubyThread, SafepointAction action, boolean deferred) {
    this.action = action;
    this.deferred = deferred;

    /* this is a potential cause for race conditions,
     * but we need to invalidate first so the interrupted threads
     * see the invalidation in poll() in their catch(InterruptedException) clause
     * and wait on the barrier instead of retrying their blocking action. */
    assumption.invalidate();
    interruptOtherThreads();

    step(currentNode, true);
  }
Пример #18
0
  @Override
  public void enter(Node node, VirtualFrame frame) {
    try {
      traceAssumption.check();
    } catch (InvalidAssumptionException e) {

      traceAssumption = context.getTraceManager().getTraceAssumption();
      traceFunc = context.getTraceManager().getTraceFunc();

      if (traceFunc != null) {
        callNode = insert(Truffle.getRuntime().createDirectCallNode(traceFunc.getCallTarget()));
      } else {
        callNode = null;
      }
    }

    if (traceFunc != null) {
      if (!context.getTraceManager().isInTraceFunc()) {
        context.getTraceManager().setInTraceFunc(true);

        final Object[] args =
            new Object[] {
              event,
              file,
              line,
              NilPlaceholder.INSTANCE,
              new RubyBinding(
                  context.getCoreLibrary().getBindingClass(),
                  RubyArguments.getSelf(frame.getArguments()),
                  frame.materialize()),
              NilPlaceholder.INSTANCE
            };

        try {
          callNode.call(
              frame,
              RubyArguments.pack(
                  traceFunc,
                  traceFunc.getDeclarationFrame(),
                  traceFunc.getSelfCapturedInScope(),
                  traceFunc.getBlockCapturedInScope(),
                  args));
        } finally {
          context.getTraceManager().setInTraceFunc(false);
        }
      }
    }
  }
  @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();
    }
  }
Пример #20
0
 @Specialization(
     guards = {"location != null", "object.getShape() == cachedShape"},
     assumptions = {"newArray(cachedShape.getValidAssumption(), validLocation)"},
     limit = "getCacheLimit()")
 public void writeExistingField(
     DynamicObject object,
     Object value,
     @Cached("object.getShape()") Shape cachedShape,
     @Cached("getLocation(object, value)") Location location,
     @Cached("createAssumption()") Assumption validLocation) {
   try {
     location.set(object, value, cachedShape);
   } catch (IncompatibleLocationException | FinalLocationException e) {
     // remove this entry
     validLocation.invalidate();
     execute(object, value);
   }
 }
Пример #21
0
 @Specialization(
     guards = {"!hasField", "object.getShape() == oldShape"},
     assumptions = {
       "newArray(oldShape.getValidAssumption(), newShape.getValidAssumption(), validLocation)"
     },
     limit = "getCacheLimit()")
 public void writeNewField(
     DynamicObject object,
     Object value,
     @Cached("hasField(object, value)") boolean hasField,
     @Cached("object.getShape()") Shape oldShape,
     @Cached("transitionWithNewField(oldShape, value)") Shape newShape,
     @Cached("getNewLocation(newShape)") Location location,
     @Cached("createAssumption()") Assumption validLocation) {
   try {
     location.set(object, value, oldShape, newShape);
   } catch (IncompatibleLocationException e) {
     // remove this entry
     validLocation.invalidate();
     execute(object, value);
   }
 }
Пример #22
0
 public final Object callDirect(Object... args) {
   compilationProfile.reportDirectCall();
   profileArguments(args);
   try {
     Object result = doInvoke(args);
     Class<?> klass = profiledReturnType;
     if (klass != null
         && CompilerDirectives.inCompiledCode()
         && profiledReturnTypeAssumption.isValid()) {
       result = unsafeCast(result, klass, true, true);
     }
     return result;
   } catch (Throwable t) {
     t = exceptionProfile.profile(t);
     if (t instanceof RuntimeException) {
       throw (RuntimeException) t;
     } else if (t instanceof Error) {
       throw (Error) t;
     } else {
       CompilerDirectives.transferToInterpreter();
       throw new RuntimeException(t);
     }
   }
 }