/**
  * A helper for {@link ResolvedJavaMethod#getParameterAnnotations()} that handles the absence of
  * parameter annotations on bridge methods where the bridged method has parameter annotations.
  */
 public static Annotation[][] getParameterAnnotations(ResolvedJavaMethod method) {
   Annotation[][] a = method.getParameterAnnotations();
   if (a.length == 0 && method.isBridge()) {
     a = getBridgedMethod(method).getParameterAnnotations();
   }
   return a;
 }
  /** Invokes a given method via {@link Method#invoke(Object, Object...)}. */
  default Object invoke(ResolvedJavaMethod method, Object receiver, Object... args) {
    try {
      JavaType[] parameterTypes = method.toParameterTypes();
      Class<?>[] parameterClasses = new Class<?>[parameterTypes.length];
      for (int i = 0; i < parameterClasses.length; ++i) {
        JavaType type = parameterTypes[i];
        if (type.getJavaKind() != JavaKind.Object) {
          parameterClasses[i] = type.getJavaKind().toJavaClass();
        } else {
          parameterClasses[i] = resolveClassForSnippet(parameterTypes[i]);
        }
      }

      Class<?> c = resolveClassForSnippet(method.getDeclaringClass());
      if (method.isConstructor()) {
        Constructor<?> javaConstructor = c.getDeclaredConstructor(parameterClasses);
        javaConstructor.setAccessible(true);
        return javaConstructor.newInstance(args);
      } else {
        Method javaMethod = c.getDeclaredMethod(method.getName(), parameterClasses);
        javaMethod.setAccessible(true);
        return javaMethod.invoke(receiver, args);
      }
    } catch (IllegalAccessException
        | InstantiationException
        | InvocationTargetException
        | ClassNotFoundException
        | NoSuchMethodException ex) {
      throw new IllegalArgumentException(ex);
    }
  }
 /**
  * Gets the input bytecode {@linkplain ResolvedJavaMethod#getCodeSize() size} from which this
  * graph is constructed. This ignores how many bytecodes in each constituent method are actually
  * parsed (which may be none for methods whose IR is retrieved from a cache or less than the full
  * amount for any given method due to profile guided branch pruning).
  */
 public int getBytecodeSize() {
   int res = method.getCodeSize();
   for (ResolvedJavaMethod e : inlinedMethods) {
     res += e.getCodeSize();
   }
   return res;
 }
 /**
  * A helper for {@link ResolvedJavaMethod#getParameterAnnotation(Class, int)} that handles the
  * absence of parameter annotations on bridge methods where the bridged method has parameter
  * annotations.
  */
 public static <T extends Annotation> T getParameterAnnotation(
     Class<T> annotationClass, int parameterIndex, ResolvedJavaMethod method) {
   T a = method.getParameterAnnotation(annotationClass, parameterIndex);
   if (a == null && method.isBridge()) {
     a = getBridgedMethod(method).getParameterAnnotation(annotationClass, parameterIndex);
   }
   return a;
 }
 /**
  * Gets the profiling info for a given method that is or will be part of this graph, taking into
  * account {@link #useProfilingInfo()}.
  */
 public ProfilingInfo getProfilingInfo(ResolvedJavaMethod m) {
   if (useProfilingInfo && m != null) {
     return m.getProfilingInfo();
   } else {
     return DefaultProfilingInfo.get(TriState.UNKNOWN);
   }
 }
Beispiel #6
0
 protected MacroNode(
     NodeClass<? extends MacroNode> c,
     InvokeKind invokeKind,
     ResolvedJavaMethod targetMethod,
     int bci,
     StampPair returnStamp,
     ValueNode... arguments) {
   super(c, returnStamp.getTrustedStamp());
   assert targetMethod.getSignature().getParameterCount(!targetMethod.isStatic())
       == arguments.length;
   this.arguments = new NodeInputList<>(this, arguments);
   this.bci = bci;
   this.targetMethod = targetMethod;
   this.returnStamp = returnStamp;
   this.invokeKind = invokeKind;
   assert !isPlaceholderBci(bci);
 }
  @SuppressWarnings("try")
  private void testImplicit(Integer i) {
    Assume.assumeTrue(config().useCompressedOops);

    Container c = new Container();
    c.i = i;

    try (OverrideScope s = OptionValue.override(GraalOptions.OptImplicitNullChecks, true)) {
      ResolvedJavaMethod method = getResolvedJavaMethod("testSnippet");
      Result expect = executeExpected(method, null, c);

      // make sure we don't get a profile that removes the implicit null check
      method.reprofile();

      Result actual = executeActual(method, null, c);
      assertEquals(expect, actual);
    }
  }
 static ResolvedJavaMethod findMethod(
     ResolvedJavaType type, String name, String descriptor, boolean isStatic) {
   if (isStatic && name.equals("<clinit>")) {
     ResolvedJavaMethod method = type.getClassInitializer();
     if (method != null) {
       return method;
     }
   }
   ResolvedJavaMethod[] methodsToSearch =
       name.equals("<init>") ? type.getDeclaredConstructors() : type.getDeclaredMethods();
   for (ResolvedJavaMethod method : methodsToSearch) {
     if (method.isStatic() == isStatic
         && method.getName().equals(name)
         && method.getSignature().toMethodDescriptor().equals(descriptor)) {
       return method;
     }
   }
   return null;
 }
Beispiel #9
0
  @Override
  public void lower(LoweringTool tool) {
    StructuredGraph replacementGraph = getLoweredSnippetGraph(tool);

    InvokeNode invoke = replaceWithInvoke();
    assert invoke.verify();

    if (replacementGraph != null) {
      // Pull out the receiver null check so that a replaced
      // receiver can be lowered if necessary
      if (!targetMethod.isStatic()) {
        ValueNode nonNullReceiver = InliningUtil.nonNullReceiver(invoke);
        if (nonNullReceiver instanceof Lowerable) {
          ((Lowerable) nonNullReceiver).lower(tool);
        }
      }
      InliningUtil.inline(invoke, replacementGraph, false, null);
      Debug.dump(Debug.INFO_LOG_LEVEL, graph(), "After inlining replacement %s", replacementGraph);
    } else {
      if (isPlaceholderBci(invoke.bci())) {
        throw new GraalError("%s: cannot lower to invoke with placeholder BCI: %s", graph(), this);
      }

      if (invoke.stateAfter() == null) {
        ResolvedJavaMethod method = graph().method();
        if (method.getAnnotation(MethodSubstitution.class) != null
            || method.getAnnotation(Snippet.class) != null) {
          // One cause for this is that a MacroNode is created for a method that
          // no longer needs a MacroNode. For example, Class.getComponentType()
          // only needs a MacroNode prior to JDK9 as it was given a non-native
          // implementation in JDK9.
          throw new GraalError(
              "%s macro created for call to %s in %s must be lowerable to a snippet or intrinsic graph. "
                  + "Maybe a macro node is not needed for this method in the current JDK?",
              getClass().getSimpleName(), targetMethod.format("%h.%n(%p)"), graph());
        }
        throw new GraalError("%s: cannot lower to invoke without state: %s", graph(), this);
      }
      invoke.lower(tool);
    }
  }
Beispiel #10
0
  @Test
  public void test() throws Throwable {

    Method fooMethod = Foo.class.getDeclaredMethod("getName");

    ResolvedJavaMethod foo1 = metaAccess.lookupJavaMethod(fooMethod);
    ResolvedJavaMethod foo2 = metaAccess.lookupJavaMethod(fooMethod);

    String foo1Code = Arrays.toString(foo1.getCode());
    String foo2Code = Arrays.toString(foo2.getCode());

    Assert.assertEquals("foo", Foo.getName());

    redefineFoo();
    System.gc();

    // Make sure the transformation happened
    Assert.assertEquals("bar", Foo.getName());

    Assert.assertEquals(foo1Code, Arrays.toString(foo1.getCode()));
    Assert.assertEquals(foo2Code, Arrays.toString(foo1.getCode()));
  }
 /**
  * Gets the method bridged to by a {@linkplain ResolvedJavaMethod#isBridge() bridge} method. The
  * value returned is the method called by {@code method} that has the same name as {@code bridge}.
  *
  * @param bridge a bridge method
  * @return the method called by {@code bridge} whose name is the same as {@code bridge.getName()}
  */
 public static ResolvedJavaMethod getBridgedMethod(ResolvedJavaMethod bridge) {
   assert bridge.isBridge();
   Bytecode code = new ResolvedJavaMethodBytecode(bridge);
   BytecodeStream stream = new BytecodeStream(code.getCode());
   int opcode = stream.currentBC();
   ResolvedJavaMethod bridged = null;
   while (opcode != Bytecodes.END) {
     switch (opcode) {
       case INVOKEVIRTUAL:
       case INVOKESPECIAL:
       case INVOKESTATIC:
       case INVOKEINTERFACE:
         {
           int cpi = stream.readCPI();
           ConstantPool cp = code.getConstantPool();
           cp.loadReferencedType(cpi, opcode);
           ResolvedJavaMethod method = (ResolvedJavaMethod) cp.lookupMethod(cpi, opcode);
           if (method.getName().equals(bridge.getName())) {
             if (!assertionsEnabled()) {
               return method;
             }
             assert bridged == null || bridged.equals(method)
                 : String.format(
                     "Found calls to different methods named %s in bridge method %s%n  callee 1: %s%n  callee 2: %s",
                     bridge.getName(),
                     bridge.format("%R %H.%n(%P)"),
                     bridged.format("%R %H.%n(%P)"),
                     method.format("%R %H.%n(%P)"));
             bridged = method;
           }
           break;
         }
     }
     stream.next();
     opcode = stream.currentBC();
   }
   if (bridged == null) {
     throw new InternalError("Couldn't find method bridged by " + bridge.format("%R %H.%n(%P)"));
   }
   return bridged;
 }
 @Override
 public Bytecode getBytecode(ResolvedJavaMethod method) {
   Classfile classfile = getClassfile(resolveToClass(method.getDeclaringClass().getName()));
   return classfile.getCode(method.getName(), method.getSignature().toMethodDescriptor());
 }